239 lines
8.8 KiB
TypeScript
239 lines
8.8 KiB
TypeScript
"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<DocsFormatMenuState>(() => {
|
|
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<DocsFormatMenuActions>(
|
|
() => ({
|
|
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,
|
|
}
|
|
}
|