dress/resources/js/hooks/use-tiptap-editor.ts

70 lines
1.9 KiB
TypeScript

import type { Editor } from "@tiptap/react"
import { useCurrentEditor, useEditorState } from "@tiptap/react"
import { useEffect, useState } from "react"
function getActivePageEditor(editor: Editor): Editor | null {
const storage = editor.storage as unknown as Record<string, unknown>
const pages = storage.pages as { activeEditor?: Editor | null } | undefined
if (!pages || !("activeEditor" in pages)) return null
return pages.activeEditor ?? null
}
export function useTiptapEditor(providedEditor?: Editor | null): {
editor: Editor | null
editorState?: Editor["state"]
canCommand?: Editor["can"]
} {
const { editor: coreEditor } = useCurrentEditor()
const mainEditor = providedEditor ?? coreEditor
const [storageEditor, setStorageEditor] = useState<Editor | null>(null)
useEffect(() => {
if (!mainEditor) {
setStorageEditor(null)
return
}
const updateHandler = () =>
setStorageEditor(getActivePageEditor(mainEditor))
updateHandler()
mainEditor.on("update", updateHandler)
mainEditor.on("selectionUpdate", updateHandler)
return () => {
mainEditor.off("update", updateHandler)
mainEditor.off("selectionUpdate", updateHandler)
}
}, [mainEditor])
useEffect(() => {
if (!storageEditor) return
const handleDestroy = () => setStorageEditor(null)
storageEditor.on("destroy", handleDestroy)
return () => {
storageEditor.off("destroy", handleDestroy)
}
}, [storageEditor])
const editorState = useEditorState({
editor: storageEditor ?? mainEditor,
selector(context) {
if (!context.editor) {
return { editor: null, editorState: undefined, canCommand: undefined }
}
return {
editor: context.editor,
editorState: context.editor.state,
canCommand: context.editor.can,
}
},
})
return editorState ?? { editor: null }
}