UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

104 lines (100 loc) 3.1 kB
/** * 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 { LexicalBuilder, getExtensionDependencyFromEditor } from '@lexical/extension'; import { ReactExtension } from '@lexical/react/ReactExtension'; import { ReactProviderExtension } from '@lexical/react/ReactProviderExtension'; import { configExtension } from 'lexical'; import { useMemo, useEffect } from 'react'; import { jsx } from 'react/jsx-runtime'; /** * 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. * */ /** * The equivalent of LexicalComposer for an extension. Make sure that your extension * argument is stable (e.g. using module scope or useMemo) so * that you are not re-creating the editor on every render! * * @example * Module scoped extension * ```tsx * const extension = defineExtension({ * name: "[root]", * dependencies: [RichTextExtension, HistoryExtension, EmojiExtension] * }); * function MyEditor({ children }) { * return (<LexicalExtensionComposer extension={extension}>{children}</LexicalExtensionComposer>); * } * ``` * * @example * useMemo extension * ```tsx * function MyEditor({ emojiBaseUrl, children }) { * const extension = useMemo(() => { * return defineExtension({ * name: "[root]", * dependencies: [ * RichTextExtension, * HistoryExtension, * configExtension(EmojiExtension, { emojiBaseUrl }), * ], * }); * }, [emojiBaseUrl]); * return (<LexicalExtensionComposer extension={extension}>{children}</LexicalExtensionComposer>); * } * ``` * * @example * Incorrect usage with unstable extension * ```tsx * function MyBrokenEditor({ emojiBaseUrl }) { * // This argument is not stable, the editor is re-created every render and * // all state is lost! * const extension = defineExtension({ * name: "[root]", * dependencies: [RichTextExtension, HistoryExtension, EmojiExtension] * }); * return (<LexicalExtensionComposer extension={extension}>{children}</LexicalExtensionComposer>); * } * ``` */ function LexicalExtensionComposer({ extension, children, contentEditable }) { const editor = useMemo(() => { const builder = LexicalBuilder.fromExtensions([ReactProviderExtension, configExtension(ReactExtension, contentEditable === undefined ? {} : { contentEditable }), extension]); return builder.buildEditor(); }, [contentEditable, extension]); useEffect(() => { // Strict mode workaround let didMount = false; queueMicrotask(() => { didMount = true; }); return () => { if (didMount) { editor.dispose(); } }; }, [editor]); const { Component } = getExtensionDependencyFromEditor(editor, ReactExtension).output; return /*#__PURE__*/jsx(Component, { children: children }); } export { LexicalExtensionComposer };