"use client" import { useEffect, useMemo, useState } from "react" import type { Editor } from "@tiptap/react" import type { DocsFormatMenuActions, DocsFormatMenuState, } from "@/components/drive/richtext/docs-format-menu" import { applyDocsParagraphStyleById, readActiveParagraphStyleId } from "@/lib/drive/docs-paragraph-style-apply" import { docsClearTableCellBorders, docsDefaultTableBorder, docsSetTableAlignment, docsSetTableCellBackground, docsSetTableCellBordersAll, docsSetTableRowHeight, docsTableCanMerge, docsTableCanSplit, } from "@/lib/drive/docs-table-actions" import { readDocsCustomSpacingDraft, readDocsParagraphSpacingState, setDocsCustomSpacing, } from "@/lib/drive/docs-line-spacing-actions" import { DOCS_DEFAULT_PARAGRAPH_SPACING } from "@/lib/drive/docs-line-spacing" import { readDocsListState, } from "@/lib/drive/docs-list-actions" export function useDocsFormatMenu({ editor, disabled, onPageSetup, }: { editor: Editor | null disabled?: boolean onPageSetup?: () => void }) { const [revision, setRevision] = useState(0) useEffect(() => { if (!editor || disabled) return const refresh = () => setRevision((value) => value + 1) editor.on("transaction", refresh) editor.on("selectionUpdate", refresh) return () => { editor.off("transaction", refresh) editor.off("selectionUpdate", refresh) } }, [disabled, editor]) const state = useMemo(() => { if (!editor) { return { isBold: false, isItalic: false, isUnderline: false, isStrike: false, alignLeft: true, alignCenter: false, alignRight: false, alignJustify: false, isBulletList: false, isOrderedList: false, styleId: "normal", tableSelected: false, tableCanMerge: false, tableCanSplit: false, graphicSelected: false, imageSelected: false, lineHeightPresetId: "1.15", hasSpaceBefore: false, hasSpaceAfter: false, keepWithNext: false, keepLinesTogether: false, preventWidowOrphan: false, pageBreakBefore: false, customSpacingDraft: { ...DOCS_DEFAULT_PARAGRAPH_SPACING }, isTaskList: false, bulletStyleId: null, orderedStyleId: null, checklistStyleId: null, orderedListStart: 1, } } let styleId = readActiveParagraphStyleId(editor) const spacing = readDocsParagraphSpacingState(editor) const listState = readDocsListState(editor) return { isBold: editor.isActive("bold"), isItalic: editor.isActive("italic"), isUnderline: editor.isActive("underline"), isStrike: editor.isActive("strike"), alignLeft: editor.isActive({ textAlign: "left" }), alignCenter: editor.isActive({ textAlign: "center" }), alignRight: editor.isActive({ textAlign: "right" }), alignJustify: editor.isActive({ textAlign: "justify" }), isBulletList: editor.isActive("bulletList"), isOrderedList: editor.isActive("orderedList"), styleId, tableSelected: editor.isActive("table"), tableCanMerge: docsTableCanMerge(editor), tableCanSplit: docsTableCanSplit(editor), graphicSelected: editor.isActive("docsGraphic") || editor.isActive("docsInlineGraphic"), imageSelected: editor.isActive("image"), lineHeightPresetId: spacing.lineHeightPresetId, hasSpaceBefore: spacing.hasSpaceBefore, hasSpaceAfter: spacing.hasSpaceAfter, keepWithNext: spacing.keepWithNext, keepLinesTogether: spacing.keepLinesTogether, preventWidowOrphan: spacing.preventWidowOrphan, pageBreakBefore: spacing.pageBreakBefore, customSpacingDraft: readDocsCustomSpacingDraft(editor), isTaskList: listState.isTaskList, bulletStyleId: listState.bulletStyleId, orderedStyleId: listState.orderedStyleId, checklistStyleId: listState.checklistStyleId, orderedListStart: listState.orderedStart, } }, [editor, revision]) const actions = useMemo( () => ({ onBold: () => editor?.chain().focus().toggleMark("bold").run(), onItalic: () => editor?.chain().focus().toggleMark("italic").run(), onUnderline: () => editor?.chain().focus().toggleUnderline().run(), onStrike: () => editor?.chain().focus().toggleMark("strike").run(), onAlignLeft: () => editor?.chain().focus().setTextAlign("left").run(), onAlignCenter: () => editor?.chain().focus().setTextAlign("center").run(), onAlignRight: () => editor?.chain().focus().setTextAlign("right").run(), onAlignJustify: () => editor?.chain().focus().setTextAlign("justify").run(), onIncreaseIndent: () => { if (!editor) return editor.chain().focus().increaseDocsIndent().run() }, onDecreaseIndent: () => { if (!editor) return editor.chain().focus().decreaseDocsIndent().run() }, onToggleBulletList: () => editor?.chain().focus().toggleBulletList().run(), onToggleOrderedList: () => editor?.chain().focus().toggleOrderedList().run(), onApplyStyle: (styleId) => { if (!editor) return applyDocsParagraphStyleById(editor, styleId) }, onClearFormatting: () => editor?.chain().focus().unsetAllMarks().clearNodes().run(), onPageSetup, onTableAddRowBefore: () => editor?.chain().focus().addRowBefore().run(), onTableAddRowAfter: () => editor?.chain().focus().addRowAfter().run(), onTableAddColumnBefore: () => editor?.chain().focus().addColumnBefore().run(), onTableAddColumnAfter: () => editor?.chain().focus().addColumnAfter().run(), onTableDeleteRow: () => editor?.chain().focus().deleteRow().run(), onTableDeleteColumn: () => editor?.chain().focus().deleteColumn().run(), onTableDelete: () => editor?.chain().focus().deleteTable().run(), onTableMergeCells: () => editor?.chain().focus().mergeCells().run(), onTableSplitCell: () => editor?.chain().focus().splitCell().run(), onTableToggleHeaderRow: () => editor?.chain().focus().toggleHeaderRow().run(), onTableToggleHeaderColumn: () => editor?.chain().focus().toggleHeaderColumn().run(), onTableSetCellBackground: (color) => docsSetTableCellBackground(editor, color), onTableAlignLeft: () => docsSetTableAlignment(editor, "left"), onTableAlignCenter: () => docsSetTableAlignment(editor, "center"), onTableAlignRight: () => docsSetTableAlignment(editor, "right"), onTableFixStructure: () => editor?.chain().focus().fixTables().run(), onTableSetCellBorders: (color) => docsSetTableCellBordersAll(editor, docsDefaultTableBorder(color)), onTableClearCellBorders: () => docsClearTableCellBorders(editor), onTableSetRowHeight: (height) => docsSetTableRowHeight(editor, height), onSetLineHeight: (lineHeight) => { if (!editor) return editor.chain().focus().setDocsLineHeight(lineHeight).run() }, onToggleSpaceBefore: () => { if (!editor) return editor.chain().focus().toggleDocsSpaceBefore().run() }, onToggleSpaceAfter: () => { if (!editor) return editor.chain().focus().toggleDocsSpaceAfter().run() }, onApplyCustomSpacing: (input) => { if (!editor) return setDocsCustomSpacing(editor, input) }, onToggleKeepWithNext: () => { if (!editor) return editor.chain().focus().toggleDocsKeepWithNext().run() }, onToggleKeepLinesTogether: () => { if (!editor) return editor.chain().focus().toggleDocsKeepLinesTogether().run() }, onTogglePreventWidowOrphan: () => { if (!editor) return editor.chain().focus().toggleDocsPreventWidowOrphan().run() }, onTogglePageBreakBefore: () => { if (!editor) return editor.chain().focus().toggleDocsPageBreakBefore().run() }, onApplyBulletStyle: (styleId) => { if (!editor) return editor.chain().focus().applyDocsBulletStyle(styleId).run() }, onApplyOrderedStyle: (styleId) => { if (!editor) return editor.chain().focus().applyDocsOrderedStyle(styleId).run() }, onApplyChecklistStyle: (styleId) => { if (!editor) return editor.chain().focus().applyDocsChecklistStyle(styleId).run() }, onRestartOrderedList: () => { if (!editor) return editor.chain().focus().restartDocsOrderedList().run() }, onContinueOrderedList: () => { if (!editor) return editor.chain().focus().continueDocsOrderedList().run() }, onSetOrderedListStart: (start) => { if (!editor) return editor.chain().focus().setDocsOrderedListStart(start).run() }, }), [editor, onPageSetup] ) return { actions, state, disabled, } }