import type { ComponentType } from 'react'; import { AnyExtension, PlainExtension } from '@remirror/core'; import { NodeViewMethod } from '@remirror/core-types'; import type { NodeViewComponentProps, ReactComponentEnvironment, ReactComponentOptions } from './node-view-types'; import { PortalContainer } from './portals'; /** * The extension transforms the `ReactComponent` property on extensions into the * following: * * - a valid `NodeView` wrapped dom element * - a valid `SSR` component. * * Currently this only support nodes. Support will be added for marks later. * * @remarks * * When creating a NodeView using the component property the `toDOM` method * returned by the `createNodeSpec` methods needs to be in the following format. * * - `string` - e.g. `div`. This will be used as the wrapper tag name. . * - `[string, 0]` - The wrapper tag name and a `0` indicating that this will be * accepting content. * - `[string, object, 0?]` -The wrapper tag name, an object of the attributes * that should be applied to the wrapper tag and a 0 when you want the react * component to have content inserted into it. * * Unfortunately `React Components` currently require a wrapping tag element * when being used in the DOM. See the following for the reasons. * * ### Caveats * * It's not possible to create a node view without nested dom element in `react` * due to this issue https://github.com/facebook/react/issues/12227. It's * unlikely that this limitation will be changed any time soon * https://github.com/ProseMirror/prosemirror/issues/803 * * NodeViews have a `dom` node which is used as the main wrapper element. For * paragraphs this would be the `p` tag and for text this is a `TEXT` node. * NodeView's also have a `contentDOM` property which is where any content from * ProseMirror is injected. * * The difficulty in integration is that the dom node and the content dom node * of the `NodeView` are consumed synchronously by ProseMirror. However, react * requires a ref to capture the dom node which corresponds to the mounted * component. This is done asynchronously. As a result it's not possible to * provide the `dom` node or `contentDOM` to ProseMirror while using react. * * The only way around this is to create both the top level `dom` element and * the `contentDOM` element manually in the NodeView and provide a `forwardRef` * prop to the component. This prop must be attached to the part of the tree * where content should be rendered to. Once the React ref is available the * `forwardRef` prop appends the `contentDOM` to the element where `forwardRef` * was attached. */ export declare class ReactComponentExtension extends PlainExtension { /** * The portal container which keeps track of all the React Portals containing * custom prosemirror NodeViews. */ private readonly portalContainer; get name(): "reactComponent"; /** * Add the portal container to the manager store. This can be used by the * `` component to manage portals for node content. */ onCreate(): void; /** * Create the node views from the custom components provided. */ createNodeViews(): Record; } declare global { namespace Remirror { interface ManagerStore { /** * The portal container which keeps track of all the React Portals * containing custom ProseMirror node views. */ portalContainer: PortalContainer; } interface ExcludeOptions { /** * Whether to exclude the react components. * * @defaultValue undefined */ reactComponents?: boolean; } interface BaseExtension { /** * Set the supported environments for this component. By default it is set * to use `both`. */ reactComponentEnvironment?: ReactComponentEnvironment; /** * The component that will be rendered as a node view and dom element. Can * also be used to render in SSR. * * Use this if the automatic componentization in ReactSerializer of the * `toDOM` method doesn't produce the expected results in SSR. * * TODO move this into a separate NodeExtension and MarkExtension based * merged interface so that the props can be specified as `{ mark: Mark }` * or `{ node: ProsemirrorNode }`. */ ReactComponent?: ComponentType; } interface ManagerSettings { /** * Override editor nodes with custom components.. * * ```ts * { * paragraph: ({ forwardRef }) =>

, * } * ``` */ nodeViewComponents?: Record>; } } } declare global { namespace Remirror { interface AllExtensions { reactComponent: ReactComponentExtension; } } }