import type { ComponentType } from 'react'; import { Decoration } from '@remirror/pm'; import { Dynamic } from '@remirror/core-types'; import { EditorView } from '@remirror/pm'; import { EditorViewProps } from '@remirror/core-types'; import type { FunctionComponent } from 'react'; import { GetFixed } from '@remirror/core-types'; import { NodeView } from '@remirror/pm'; import { NodeViewMethod } from '@remirror/core-types'; import { NodeWithAttributes } from '@remirror/core-types'; import { NodeWithAttributesProps } from '@remirror/core-types'; import { PlainExtension } from '@remirror/core'; import { ProsemirrorAttributes } from '@remirror/core-types'; import { ProsemirrorNode } from '@remirror/pm'; import type { RefCallback } from 'react'; import { Static } from '@remirror/core-types'; import { Unsubscribe } from 'nanoevents'; import type { ViewMutationRecord } from '@remirror/pm/view'; declare interface CreateNodeViewProps { /** * A container and event dispatcher which keeps track of all dom elements that * hold node views */ portalContainer: PortalContainer; /** * The react component that will be added to the DOM. */ ReactComponent: ComponentType; /** * The options passed through to the react extension component. */ options: GetFixed; } export { CreateNodeViewProps } export { CreateNodeViewProps as CreateNodeViewProps_alias_1 } /** * Retrieve the position of the current nodeView */ export declare type GetPosition = () => number | undefined; declare interface MountedPortal extends RenderProps { key: string; } export { MountedPortal } export { MountedPortal as MountedPortal_alias_1 } export { MountedPortal as MountedPortal_alias_2 } declare interface NodeViewComponentProps extends EditorViewProps, NodeWithAttributesProps { /** * Provides the position of the node view in the prosemirror document */ getPosition: GetPosition; /** * A ref callback which should be used by the component to pass the dom * reference of the react element back to the node view. This is used as * container where the content within which the content will be placed. * * This **must** be used in your component otherwise the editor has no * understanding of where to render the node content and defaults to placing * it within the provided element created by the `toDOM` method. */ forwardRef: RefCallback; /** * This is true when the component is selected. */ selected: boolean; /** * Update the attributes for the target node. * * This should be called in the `useEffect` hook to prevent excessive renders. */ updateAttributes: (attrs: ProsemirrorAttributes) => void; /** * The decorations which are currently applied to the ReactNodeView. */ decorations: readonly Decoration[]; } export { NodeViewComponentProps } export { NodeViewComponentProps as NodeViewComponentProps_alias_1 } /** * The node view portal container keeps track of all the portals which have been * added by react to render the node views in the editor. */ declare class PortalContainer { #private; /** * A map of all the active portals which have a one to one relation between * the container and the component. */ portals: PortalMap; /** * Event handler for subscribing to update events from the portalContainer. */ on: (callback: (portals: PortalMap) => void) => Unsubscribe; /** * Subscribe to one event before automatically unbinding. */ once: (callback: (portals: PortalMap) => void) => Unsubscribe; /** * Trigger an update in all subscribers. */ private update; /** * Responsible for registering a new portal by rendering the react element * into the provided container. */ render({ Component, container }: RenderMethodProps_2): void; /** * Force an update in all the portals by setting new keys for every portal. * * Delete all orphaned containers (deleted from the DOM). This is useful for * Decoration where there is no destroy method. */ forceUpdate(): void; /** * Deletes the portal within the container. */ remove(container: HTMLElement): void; } export { PortalContainer } export { PortalContainer as PortalContainer_alias_1 } export { PortalContainer as PortalContainer_alias_2 } declare type PortalList = ReadonlyArray<[HTMLElement, MountedPortal]>; export { PortalList } export { PortalList as PortalList_alias_1 } export { PortalList as PortalList_alias_2 } declare type PortalMap = Map; export { PortalMap } export { PortalMap as PortalMap_alias_1 } export { PortalMap as PortalMap_alias_2 } declare type ReactComponentEnvironment = 'ssr' | 'dom' | 'both'; export { ReactComponentEnvironment } export { ReactComponentEnvironment as ReactComponentEnvironment_alias_1 } /** * 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. */ 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; } export { ReactComponentExtension } export { ReactComponentExtension as ReactComponentExtension_alias_1 } declare interface ReactComponentOptions { /** * The default main block node. * * @defaultValue 'div' * * @staticOption */ defaultBlockNode?: Static; /** * The default main inline node (for inline content). * * @defaultValue 'span' * @staticOption */ defaultInlineNode?: Static; /** * The default content node to use. * * @defaultValue 'span' * @staticOption */ defaultContentNode?: Static; /** * Whether to render as a nodeView, as an ssr component or in both * environments. */ defaultEnvironment?: Static; /** * Override any valid schema node with your own custom components * * ```ts * { * paragraph: ({ forwardRef }) =>

, * } * ``` */ nodeViewComponents?: Dynamic>>; /** * Override the return value from the `stopEvent` method in `ReactNodeView` */ stopEvent?: Dynamic<(props: { event: Event; }) => boolean> | null; } export { ReactComponentOptions } export { ReactComponentOptions as ReactComponentOptions_alias_1 } /** * This is the node view rapper that makes */ export declare class ReactNodeView implements NodeView { #private; /** * A shorthand method for creating the `ReactNodeView`. */ static create(props: CreateNodeViewProps): (node: NodeWithAttributes, view: EditorView, getPosition: GetPosition) => NodeView; /** * Whether or not the node is currently selected. */ get selected(): boolean; /** * The DOM node that should hold the node's content. * * This is only meaningful if the NodeView is not a leaf type and it can * accept content. When these criteria are met, `ProseMirror` will take care of * rendering the node's children into it. * * In order to make use of this in a */ get contentDOM(): HTMLElement | undefined; /** * Provides readonly access to the dom element. The dom is automatically for * react components. */ get dom(): HTMLElement; /** * Create the node view for a react component and render it into the dom. */ private constructor(); /** * Render the react component into the dom. */ private renderComponent; /** * Create the dom element which will hold the react component. */ private createDom; /** * The element that will contain the content for this element. */ private createContentDom; /** * Render the provided component. * * This method is passed into the HTML element. */ private readonly Component; /** * Passed to the Component to enable updating the attributes from within the component. */ private readonly updateAttributes; /** * This is called whenever the node is called. */ update(node: ProsemirrorNode, decorations: readonly Decoration[]): boolean; /** * Copies the attributes from a ProseMirror Node to the parent DOM node. * * @param node The Prosemirror Node from which to source the attributes */ setDomAttributes(node: ProsemirrorNode, element: HTMLElement): void; /** * Marks the node as being selected. */ selectNode(): void; /** * Remove the selected node markings from this component. */ deselectNode(): void; /** * This is called whenever the node is being destroyed. */ destroy(): void; /** * The handler which decides when mutations should be ignored. */ ignoreMutation(mutation: ViewMutationRecord): boolean; stopEvent(event: Event): boolean; } export declare interface ReactNodeViewProps extends EditorViewProps, NodeWithAttributesProps, CreateNodeViewProps { /** * Method for retrieving the position of the current nodeView */ getPosition: GetPosition; } /** * The component that places all the portals into the DOM. * * Portals can currently be created by a [[`ReactNodeView`]] and coming soon * both the [[`ReactMarkView`]] and [[`ReactDecoration`]]. */ declare const RemirrorPortals: (props: RemirrorPortalsProps) => JSX.Element; export { RemirrorPortals } export { RemirrorPortals as RemirrorPortals_alias_1 } export { RemirrorPortals as RemirrorPortals_alias_2 } declare interface RemirrorPortalsProps { /** * An array of tuples holding all the element containers for node view * portals. */ portals: Array<[HTMLElement, MountedPortal]>; } export { RemirrorPortalsProps } export { RemirrorPortalsProps as RemirrorPortalsProps_alias_1 } export { RemirrorPortalsProps as RemirrorPortalsProps_alias_2 } declare type RenderMethodProps_2 = SingleRenderMethodProps; declare interface RenderProps { /** * Renders a JSX element. */ Component: FunctionComponent; } export { RenderProps } export { RenderProps as RenderProps_alias_1 } export { RenderProps as RenderProps_alias_2 } declare interface SharedRenderMethodProps extends RenderProps { /** * The DOM element to contain the react portal. */ container: HTMLElement; /** * Shared renders must provide a key. By setting this value, the portal will * be rendered as a shared parameter. */ key: string; } export { SharedRenderMethodProps } export { SharedRenderMethodProps as SharedRenderMethodProps_alias_1 } declare interface SingleRenderMethodProps extends RenderProps { key?: undefined; /** * The DOM element to contain the react portal. */ container: HTMLElement; } export { SingleRenderMethodProps as RenderMethodProps } export { SingleRenderMethodProps } export { SingleRenderMethodProps as SingleRenderMethodProps_alias_1 } /** * A hook which subscribes to updates from the portal container. * * This is should used in the `ReactEditor` component and the value should be * passed through to the `RemirrorPortals` component. */ declare function usePortals(portalContainer: PortalContainer): Array<[HTMLElement, MountedPortal]>; export { usePortals } export { usePortals as usePortals_alias_1 } export { usePortals as usePortals_alias_2 } export { } 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; } } }