1
0
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:
Nadeem Shaik
2019-06-12 23:37:35 +05:30
committed by Ian Storm Taylor
parent 67e397100e
commit 5471343ae8
3 changed files with 51 additions and 20 deletions

View File

@@ -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(
selection.start.key,
// In this simple case, we only want mentions to live inside a paragraph. // In this simple case, we only want mentions to live inside a paragraph.
// This check can be adjusted for more complex rich text implementations. // This check can be adjusted for more complex rich text implementations.
node => node.type !== 'paragraph' return document.getParent(selection.start.key).type === 'paragraph'
)
return !invalidParent
} }
export default MentionsExample export default MentionsExample

View File

@@ -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.
* *

View File

@@ -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
} }