2023-03-12 15:01:38 -07:00
|
|
|
/**
|
|
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
|
|
import { useLexicalTextEntity } from '@lexical/react/useLexicalTextEntity';
|
2023-03-30 09:17:12 -07:00
|
|
|
import { useCallback, useEffect } from 'react';
|
2023-03-12 15:01:38 -07:00
|
|
|
|
|
|
|
import { $createMentionNode, MentionNode } from '../nodes/mention-node';
|
|
|
|
|
2023-03-30 09:17:12 -07:00
|
|
|
import type { TextNode } from 'lexical';
|
2023-03-12 15:01:38 -07:00
|
|
|
|
2023-04-18 15:22:22 -07:00
|
|
|
const MENTION_REGEX = new RegExp('(^|$|(?:^|\\s))([@])([a-z\\d_-]+(?:@[^@\\s]+)?)', 'i');
|
2023-03-12 15:01:38 -07:00
|
|
|
|
2023-04-18 15:22:22 -07:00
|
|
|
const getMentionMatch = (text: string) => {
|
2023-04-01 04:40:15 -07:00
|
|
|
const matchArr = MENTION_REGEX.exec(text);
|
2023-03-27 11:54:28 -07:00
|
|
|
|
2023-03-30 09:17:12 -07:00
|
|
|
if (!matchArr) return null;
|
|
|
|
return matchArr;
|
|
|
|
};
|
2023-03-12 15:01:38 -07:00
|
|
|
|
2023-04-18 15:22:22 -07:00
|
|
|
const MentionPlugin = (): JSX.Element | null => {
|
2023-03-30 09:17:12 -07:00
|
|
|
const [editor] = useLexicalComposerContext();
|
2023-03-12 15:01:38 -07:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!editor.hasNodes([MentionNode])) {
|
|
|
|
throw new Error('MentionPlugin: MentionNode not registered on editor');
|
|
|
|
}
|
|
|
|
}, [editor]);
|
|
|
|
|
|
|
|
const createMentionNode = useCallback((textNode: TextNode): MentionNode => {
|
|
|
|
return $createMentionNode(textNode.getTextContent());
|
|
|
|
}, []);
|
|
|
|
|
2023-03-27 14:49:37 -07:00
|
|
|
const getEntityMatch = useCallback((text: string) => {
|
|
|
|
const matchArr = getMentionMatch(text);
|
|
|
|
|
|
|
|
if (!matchArr) return null;
|
2023-03-27 11:54:28 -07:00
|
|
|
|
2023-03-12 15:01:38 -07:00
|
|
|
const mentionLength = matchArr[3].length + 1;
|
|
|
|
const startOffset = matchArr.index + matchArr[1].length;
|
|
|
|
const endOffset = startOffset + mentionLength;
|
|
|
|
return {
|
|
|
|
end: endOffset,
|
|
|
|
start: startOffset,
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
useLexicalTextEntity<MentionNode>(
|
2023-03-27 14:49:37 -07:00
|
|
|
getEntityMatch,
|
2023-03-12 15:01:38 -07:00
|
|
|
MentionNode,
|
|
|
|
createMentionNode,
|
|
|
|
);
|
|
|
|
|
2023-03-30 09:17:12 -07:00
|
|
|
return null;
|
2023-03-17 14:05:59 -07:00
|
|
|
};
|
2023-04-18 15:22:22 -07:00
|
|
|
|
|
|
|
export default MentionPlugin;
|