Skip to content

Instantly share code, notes, and snippets.

@andreypopp
Last active May 1, 2022 06:02
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreypopp/88ec11a788110a27f6a5ee0068c07f0e to your computer and use it in GitHub Desktop.
Save andreypopp/88ec11a788110a27f6a5ee0068c07f0e to your computer and use it in GitHub Desktop.
type RenderProps = {
attrs: Record<string, any>;
children: React.ReactNode;
};
function RenderWrapper({
Render,
contentDOM,
node,
decorations,
}: {
Render: React.ComponentType<RenderProps>;
contentDOM: HTMLElement;
node: Node;
decorations: Decoration[];
}) {
let holeRef = React.useRef<null | HTMLDivElement>(null);
React.useLayoutEffect(() => {
if (holeRef.current != null) {
holeRef.current.appendChild(contentDOM);
}
// Looks like we don't need this as ProseMirror cleans this up on itself.
// return () => {
// if (holeRef.current != null) {
// holeRef.current.removeChild(contentDOM);
// }
// };
}, [contentDOM]);
let hole = React.useMemo(() => <div ref={holeRef} />, []);
let element = React.useMemo(() => {
return <Render attrs={node.attrs} children={hole} />;
}, [hole, node.attrs]);
return element;
}
function createNodeView(
Render: React.ComponentType<RenderProps>,
tagName: string = "div",
contentTagName: string = "div"
) {
return (
node: Node,
view: EditorView,
getPos: boolean | (() => number),
decorations: Decoration[]
) => {
let dom = document.createElement(tagName);
let contentDOM = document.createElement(contentTagName);
// Same as ReactDOM.render(<RenderWrapper ... />, dom)
let root = (ReactDOM as any).createRoot(dom);
root.render(
<RenderWrapper
Render={Render}
node={node}
decorations={decorations}
contentDOM={contentDOM}
/>
);
let nodeView: NodeView = {
dom,
contentDOM,
update(node: Node, decorations: Decoration[]) {
// Same as ReactDOM.render(<RenderWrapper ... />, dom)
root.render(
<RenderWrapper
Render={Render}
node={node}
decorations={decorations}
contentDOM={contentDOM}
/>
);
return true;
},
destroy() {
// Same as ReactDOM.unmountComponentAtNode(dom)
root.unmount();
root = null;
},
};
return nodeView;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment