/** * 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 type { EditorChildrenComponentProps, ReactConfig, ReactOutputs, } from './shared/types'; import type {LexicalComposerContextWithEditor} from '@lexical/react/LexicalComposerContext'; import invariant from '@lexical/internal/invariant'; import {ContentEditable} from '@lexical/react/LexicalContentEditable'; import {LexicalErrorBoundary} from '@lexical/react/LexicalErrorBoundary'; import {ReactProviderExtension} from '@lexical/react/ReactProviderExtension'; import { declarePeerDependency, defineExtension, shallowMergeConfig, } from 'lexical'; import {buildEditorComponent} from './shared/buildEditorComponent'; export type {EditorChildrenComponentProps, ReactConfig, ReactOutputs}; /** * @example * The default EditorChildrenComponent implementation * ```jsx * return ( * <> * {contentEditable} * {children} * * ); * ``` */ export function DefaultEditorChildrenComponent({ contentEditable, children, }: EditorChildrenComponentProps) { return ( <> {contentEditable} {children} ); } const initialConfig: ReactConfig = { EditorChildrenComponent: DefaultEditorChildrenComponent, ErrorBoundary: LexicalErrorBoundary, contentEditable: , decorators: [], }; /** * An extension to use or configure React for use with Lexical. In an editor, you * would typically use {@link LexicalExtensionComposer} (for React projects) or * {@link ReactPluginHostExtension} (to use React Extensions and plug-ins in a non-React * project). * * See {@link ReactConfig} for more detailed exextensionations of how to use * the config for this Extension. * * For an Extension developer, you can defineConfig() override the extension with * decorators to add JSX inside the editor context that is not * location-dependent (e.g. floating UI that does not need to be mounted in * some specific location, or effects that return null). */ export const ReactExtension = defineExtension({ build(editor, config, state) { const providerPeer = state.getPeer( ReactProviderExtension.name, ); if (!providerPeer) { invariant( false, 'No ReactProviderExtension detected. You must use ReactPluginHostExtension or LexicalExtensionComposer to host React extensions. The following extensions depend on ReactExtension: %s', [...state.getDirectDependentNames()].join(' '), ); } const context: LexicalComposerContextWithEditor = [ editor, {getTheme: () => editor._config.theme}, ]; const Component = buildEditorComponent(config, context); return {Component, context}; }, config: initialConfig, mergeConfig(a, b) { const config = shallowMergeConfig(a, b); if (b.decorators) { config.decorators = b.decorators.length > 0 ? [...a.decorators, ...b.decorators] : a.decorators; } return config; }, name: '@lexical/react/React', peerDependencies: [ // We are not trying to avoid the import, just the direct dependency, // so using the extension directly is fine. declarePeerDependency( ReactProviderExtension.name, ), ], });