hey @strdr4605 can you share how you converted react-native-controlled-mentions value to lexical state?
@davevilela, we have a fork that also passes mention data to onChange
And we had a function that will transform text and mentions from
export type LocalEditorData = Array<Mendex>;
export type Mendex =
| {
type: 'text';
text: string;
}
| {
type: 'mention';
text: string;
};
// to handle @[hello](1) mentions
export const MarkdownMentionRegex = /@\[[^\]]+\]\([\d\w]+\)/g;
export const convertMarkdownToEditorData = (text: string, mentions: ApiMention[]): LocalEditorData => {
// get all markdown alike mentions
const matches = [...text.matchAll(MarkdownMentionRegex)];
if (!matches.length || !mentions.length) return [{ type: 'text', text }];
const finalArr: LocalEditorData = [{ type: 'text', text: '' }];
text.split(MarkdownMentionRegex).forEach((line, index) => {
finalArr.push({ type: 'text', text: line });
// sync back mentions that were splitted
// text line tag index is always before the mention tag index
if (matches[index]) {
const match = matches[index];
const foundMention = mentions.find(mention => match[0].includes(getMentionId(mention, type)));
if (foundMention) {
const totalLength = finalArr.reduce((total, current) => total + current.text.length, 0);
finalArr.push({
type: 'mention',
text: foundMention.name,
});
}
}
});
return finalArr;
};
and after having the LocalEditorData array we would convert to lexical state using a headless editor.
export const transformAllNodes = (editor: LexicalEditor) =>
mergeRegister(
editor.registerNodeTransform(ParagraphNode, transformParagraphDirection),
editor.registerNodeTransform(TextNode, findAndTransformHashtagNode),
editor.registerNodeTransform(TextNode, findAndTransformAutolinkNode),
editor.registerNodeTransform(TextNode, node => findAndTransformEmojiNode(node, $createCoreEmojiNode))
);
export const convertEditorDataToLexical = (editorData: LocalEditorData): LexicalNode[] =>
editorData.map(element => {
if (element.type === 'mention') {
const mention = element.data as Mention;
const { offset, ...remainingMention } = mention;
return $createCoreMentionNode(remainingMention);
}
if (element.type === 'text' && element.text === '\n') {
return $createLineBreakNode();
}
return $createTextNode(element.text);
});
const postEditor = createPostHeadlessEditor();
export const convertToLexical = (editorData: LocalEditorData): Promise<LexicalOutputType> =>
new Promise(resolve => {
postEditor.update(() => {
const defaultNodes = convertEditorDataToLexical(editorData);
const rootEditor = $getRoot().setDirection('ltr');
rootEditor.clear();
rootEditor.append($createParagraphNode().append(...defaultNodes));
});
const unsubscribeListeners = mergeRegister(
postEditor.registerNodeTransform(ParagraphNode, transformParagraphDirection),
postEditor.registerNodeTransform(TextNode, findAndTransformHashtagNode),
postEditor.registerNodeTransform(TextNode, findAndTransformAutolinkNode)
);
const removeUpdateListener = postEditor.registerUpdateListener(({ editorState }) => {
const serializedEditorState = editorState.toJSON();
const stringifiedEditorState = JSON.stringify(serializedEditorState);
const parsedEditorState = postEditor.parseEditorState(stringifiedEditorState);
const plainText = parsedEditorState.read(() => $getRoot().getTextContent());
resolve({ editorState: serializedEditorState, plainText });
removeUpdateListener();
unsubscribeListeners();
});
});