mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-26 08:34:28 +02:00
Fixed mentions example (#2877)
This commit is contained in:
committed by
Ian Storm Taylor
parent
67e397100e
commit
5471343ae8
@@ -41,12 +41,24 @@ import Suggestions from './Suggestions'
|
|||||||
const USER_MENTION_NODE_TYPE = 'userMention'
|
const USER_MENTION_NODE_TYPE = 'userMention'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The annotation mark type that the menu will position itself against. The
|
* The annotation type that the menu will position itself against. The
|
||||||
* "context" is just the current text after the @ symbol.
|
* "context" is just the current text after the @ symbol.
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CONTEXT_MARK_TYPE = 'mentionContext'
|
const CONTEXT_ANNOTATION_TYPE = 'mentionContext'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a unique key for the search highlight annotations.
|
||||||
|
*
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
|
||||||
|
let n = 0
|
||||||
|
|
||||||
|
function getMentionKey() {
|
||||||
|
return `highlight_${n++}`
|
||||||
|
}
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
inlines: {
|
inlines: {
|
||||||
@@ -119,7 +131,8 @@ class MentionsExample extends React.Component {
|
|||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
ref={this.editorRef}
|
ref={this.editorRef}
|
||||||
renderInline={this.renderInline}
|
renderInline={this.renderInline}
|
||||||
renderMark={this.renderMark}
|
renderBlock={this.renderBlock}
|
||||||
|
renderAnnotation={this.renderAnnotation}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
/>
|
/>
|
||||||
<Suggestions
|
<Suggestions
|
||||||
@@ -131,8 +144,8 @@ class MentionsExample extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMark(props, editor, next) {
|
renderAnnotation(props, editor, next) {
|
||||||
if (props.mark.type === CONTEXT_MARK_TYPE) {
|
if (props.annotation.type === CONTEXT_ANNOTATION_TYPE) {
|
||||||
return (
|
return (
|
||||||
// Adding the className here is important so that the `Suggestions`
|
// Adding the className here is important so that the `Suggestions`
|
||||||
// component can find an anchor.
|
// component can find an anchor.
|
||||||
@@ -145,6 +158,16 @@ class MentionsExample extends React.Component {
|
|||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderBlock(props, editor, next) {
|
||||||
|
const { attributes, node } = props
|
||||||
|
|
||||||
|
if (node.type === 'paragraph') {
|
||||||
|
return <p {...attributes}>{props.children}</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
renderInline(props, editor, next) {
|
renderInline(props, editor, next) {
|
||||||
const { attributes, node } = props
|
const { attributes, node } = props
|
||||||
|
|
||||||
@@ -216,11 +239,13 @@ class MentionsExample extends React.Component {
|
|||||||
const { selection } = change.value
|
const { selection } = change.value
|
||||||
|
|
||||||
let annotations = change.value.annotations.filter(
|
let annotations = change.value.annotations.filter(
|
||||||
value => value.mark.type !== CONTEXT_MARK_TYPE
|
annotation => annotation.type !== CONTEXT_ANNOTATION_TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
if (inputValue && hasValidAncestors(change.value)) {
|
if (inputValue && hasValidAncestors(change.value)) {
|
||||||
annotations = annotations.push({
|
const key = getMentionKey()
|
||||||
|
|
||||||
|
annotations = annotations.set(key, {
|
||||||
anchor: {
|
anchor: {
|
||||||
key: selection.start.key,
|
key: selection.start.key,
|
||||||
offset: selection.start.offset - inputValue.length,
|
offset: selection.start.offset - inputValue.length,
|
||||||
@@ -229,15 +254,14 @@ class MentionsExample extends React.Component {
|
|||||||
key: selection.start.key,
|
key: selection.start.key,
|
||||||
offset: selection.start.offset,
|
offset: selection.start.offset,
|
||||||
},
|
},
|
||||||
mark: {
|
type: CONTEXT_ANNOTATION_TYPE,
|
||||||
type: CONTEXT_MARK_TYPE,
|
key: getMentionKey(),
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ value: change.value }, () => {
|
this.setState({ value: change.value }, () => {
|
||||||
// We need to set annotations after the value flushes into the editor.
|
// We need to set annotations after the value flushes into the editor.
|
||||||
this.editorRef.current.setannotations(annotations)
|
this.editorRef.current.setAnnotations(annotations)
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -292,14 +316,9 @@ class MentionsExample extends React.Component {
|
|||||||
function hasValidAncestors(value) {
|
function hasValidAncestors(value) {
|
||||||
const { document, selection } = value
|
const { document, selection } = value
|
||||||
|
|
||||||
const invalidParent = document.getClosest(
|
// In this simple case, we only want mentions to live inside a paragraph.
|
||||||
selection.start.key,
|
// This check can be adjusted for more complex rich text implementations.
|
||||||
// In this simple case, we only want mentions to live inside a paragraph.
|
return document.getParent(selection.start.key).type === 'paragraph'
|
||||||
// This check can be adjusted for more complex rich text implementations.
|
|
||||||
node => node.type !== 'paragraph'
|
|
||||||
)
|
|
||||||
|
|
||||||
return !invalidParent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MentionsExample
|
export default MentionsExample
|
||||||
|
@@ -58,6 +58,18 @@ Commands.setAnnotation = (editor, annotation, newProperties) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Commands.setAnnotations = (editor, annotations = []) => {
|
||||||
|
const { value } = editor
|
||||||
|
const newProperties = Value.createProperties({ annotations })
|
||||||
|
const prevProperties = pick(value, Object.keys(newProperties))
|
||||||
|
|
||||||
|
editor.applyOperation({
|
||||||
|
type: 'set_value',
|
||||||
|
properties: prevProperties,
|
||||||
|
newProperties,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export.
|
* Export.
|
||||||
*
|
*
|
||||||
|
@@ -68,7 +68,7 @@ class Value extends Record(DEFAULTS) {
|
|||||||
if (isPlainObject(a)) {
|
if (isPlainObject(a)) {
|
||||||
const p = {}
|
const p = {}
|
||||||
if ('annotations' in a)
|
if ('annotations' in a)
|
||||||
p.annotations = Annotation.createList(a.annotations)
|
p.annotations = Annotation.createMap(a.annotations)
|
||||||
if ('data' in a) p.data = Data.create(a.data)
|
if ('data' in a) p.data = Data.create(a.data)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user