lexical-remark
Version:
This package contains Markdown helpers and functionality for Lexical using remark-parse.
60 lines (51 loc) • 2.15 kB
text/typescript
import lexicalComposerContext from '@lexical/react/LexicalComposerContext.js';
import lexicalUtils from '@lexical/utils';
import lexical, { type LexicalCommand } from 'lexical';
import { useEffect } from 'react';
import { $createAttachmentNode, AttachmentNode } from './node.js';
type AttachmentPayload = Readonly<{ filename: string; url: string }>;
/**
* A command to insert an attachment. The argument is an {@link AttachmentPayload}.
*/
export const INSERT_ATTACHMENT_COMMAND: LexicalCommand<AttachmentPayload> =
lexical.createCommand('INSERT_ATTACHMENT_COMMAND');
/**
* A Lexical plugin to register the INSERT_ATTACHMENT_COMMAND
*/
export const AttachmentPlugin = (): JSX.Element | null => {
const [editor] = lexicalComposerContext.useLexicalComposerContext();
useEffect(() => {
if (!editor.hasNodes([AttachmentNode])) {
throw new Error('AttachmentsPlugin: AttachmentNode not registered on editor');
}
return lexicalUtils.mergeRegister(
editor.registerCommand<AttachmentPayload>(
INSERT_ATTACHMENT_COMMAND,
(payload) => {
editor.update(() => {
const attachmentNode = $createAttachmentNode(payload.url, payload.filename);
const textNode = lexical.$createTextNode(`📎 ${payload.filename}`);
attachmentNode.append(textNode);
const selection = lexical.$getRoot().selectEnd();
if (
lexical.$isRangeSelection(selection) &&
selection.anchor.key === selection.focus.key &&
selection.anchor.offset === selection.focus.offset
) {
const node = selection.anchor.getNode();
if (!lexical.$isParagraphNode(node) || !node.isEmpty()) {
editor.dispatchCommand(lexical.INSERT_PARAGRAPH_COMMAND, undefined);
}
} else {
editor.dispatchCommand(lexical.INSERT_PARAGRAPH_COMMAND, undefined);
}
lexical.$insertNodes([attachmentNode]);
});
return true;
},
lexical.COMMAND_PRIORITY_EDITOR,
),
);
}, [editor]);
return null;
};