Skip to content
File

Blob: src/client/components/editor/controllers/menu/renderer.ts

typescript45 lines
1import type { Editor } from "@tiptap/core";
2import { ReactRenderer } from "@tiptap/react";
3 
4type RendererProps = Record<string, unknown>;
5 
6export interface MountedEditorRenderer<Handle, Props> {
7 destroy(): void;
8 readonly ref: Handle | null;
9 updateProps(next: Partial<Props>): void;
10}
11 
12export function mountEditorRenderer<Handle, Props extends object>(
13 editor: Editor,
14 component: React.ComponentType<Props>,
15 props: Props,
16): MountedEditorRenderer<Handle, Props> {
17 let destroyed = false;
18 const renderer = new ReactRenderer<Handle, RendererProps>(component as React.ComponentType<RendererProps>, {
19 editor,
20 props: props as unknown as RendererProps,
21 });
22 document.body.appendChild(renderer.element);
23 
24 function destroy() {
25 if (destroyed) return;
26 destroyed = true;
27 editor.off("destroy", destroy);
28 renderer.destroy();
29 renderer.element.remove();
30 }
31 
32 editor.on("destroy", destroy);
33 
34 return {
35 destroy,
36 get ref() {
37 return destroyed ? null : renderer.ref;
38 },
39 updateProps(next) {
40 if (destroyed) return;
41 renderer.updateProps(next as RendererProps);
42 },
43 };
44}