import { ReactRenderer, useEditor } from "@tiptap/react"; import CommandList from "@/features/editor/components/slash-menu/command-list"; import { autoUpdate, computePosition, flip, offset, shift, } from "@floating-ui/dom"; const renderItems = () => { let component: ReactRenderer | null = null; let popup: HTMLElement | null = null; let cleanup: (() => void) | null = null; let getReferenceClientRect: (() => DOMRect) | null = null; const updatePosition = () => { if (!popup || !getReferenceClientRect) return; // @ts-ignore const rect = getReferenceClientRect(); computePosition({ getBoundingClientRect: () => rect }, popup, { placement: "bottom-start", middleware: [offset(0), flip(), shift()], }).then(({ x, y }) => { if (popup) { popup.style.left = `${x}px`; popup.style.top = `${y}px`; } }); }; return { onStart: (props: { editor: ReturnType; clientRect: DOMRect; }) => { component = new ReactRenderer(CommandList, { props, editor: props.editor, }); if (!props.clientRect) { return; } // @ts-ignore getReferenceClientRect = props.clientRect; popup = document.createElement("div"); popup.style.zIndex = "199"; popup.style.position = "absolute"; popup.style.top = "0"; popup.style.left = "0"; document.body.appendChild(popup); popup.appendChild(component.element); cleanup = autoUpdate( // @ts-ignore { getBoundingClientRect: () => { return getReferenceClientRect ? getReferenceClientRect() : new DOMRect(); }, }, popup, updatePosition ); }, onUpdate: (props: { editor: ReturnType; clientRect: DOMRect; }) => { component?.updateProps(props); if (!props.clientRect) { return; } // @ts-ignore getReferenceClientRect = props.clientRect; updatePosition(); }, onKeyDown: (props: { event: KeyboardEvent }) => { if (props.event.key === "Escape") { if (popup) { popup.style.display = "none"; } return true; } // @ts-ignore return component?.ref?.onKeyDown(props); }, onExit: () => { if (cleanup) { cleanup(); cleanup = null; } if (popup) { popup.remove(); popup = null; } if (component) { component.destroy(); component = null; } }, }; }; export default renderItems;