"use client" import { useEditorState } from "@tiptap/react" import type { Editor } from "@tiptap/react" import { canStepFontSizePx, readFontSizeToolbarState, type FontSizeToolbarState, } from "@/lib/drive/docs-font-size" import { readFontFamilyToolbarState, type FontFamilyToolbarState, } from "@/lib/drive/docs-font-family" export const DOCS_TOOLBAR_DEFAULT_TEXT_COLOR = "#000000" function activeTextStyle(editor: Editor): string { if (editor.isActive("heading", { level: 1 })) return "heading1" if (editor.isActive("heading", { level: 2 })) return "heading2" if (editor.isActive("heading", { level: 3 })) return "heading3" if (editor.isActive("heading", { level: 4 })) return "heading4" return "paragraph" } export type DocsToolbarEditorState = { canUndo: boolean canRedo: boolean styleId: string fontFamilyState: FontFamilyToolbarState fontSizeState: FontSizeToolbarState canStepFontSizeDown: boolean canStepFontSizeUp: boolean textColor: string highlightColor: string | null isBold: boolean isItalic: boolean isUnderline: boolean isLink: boolean alignLeft: boolean alignCenter: boolean alignRight: boolean alignJustify: boolean isBulletList: boolean isOrderedList: boolean } function readHighlightColor(editor: Editor): string | null { const { storedMarks } = editor.state if (storedMarks) { const mark = storedMarks.find((m) => m.type.name === "highlight") const stored = mark?.attrs.color as string | undefined if (stored) return stored } if (!editor.isActive("highlight")) return null const color = editor.getAttributes("highlight").color as string | undefined return color ?? null } function selectDocsToolbarState({ editor }: { editor: Editor }): DocsToolbarEditorState { const highlightColor = readHighlightColor(editor) return { canUndo: editor.can().chain().focus().undo().run(), canRedo: editor.can().chain().focus().redo().run(), styleId: activeTextStyle(editor), fontFamilyState: readFontFamilyToolbarState(editor), fontSizeState: readFontSizeToolbarState(editor), canStepFontSizeDown: canStepFontSizePx(editor, -1), canStepFontSizeUp: canStepFontSizePx(editor, 1), textColor: (editor.getAttributes("textStyle").color as string | undefined) || DOCS_TOOLBAR_DEFAULT_TEXT_COLOR, highlightColor, isBold: editor.isActive("bold"), isItalic: editor.isActive("italic"), isUnderline: editor.isActive("underline"), isLink: editor.isActive("link"), 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"), } } function fontFamilyStateEqual(a: FontFamilyToolbarState, b: FontFamilyToolbarState): boolean { if (a.kind !== b.kind) return false if (a.kind === "single" && b.kind === "single") return a.name === b.name return true } function fontSizeStateEqual(a: FontSizeToolbarState, b: FontSizeToolbarState): boolean { if (a.kind !== b.kind) return false if (a.kind === "single" && b.kind === "single") return a.size === b.size return true } function toolbarStateEqual( a: DocsToolbarEditorState, b: DocsToolbarEditorState | null ): boolean { if (!b) return false if (!fontFamilyStateEqual(a.fontFamilyState, b.fontFamilyState)) return false if (!fontSizeStateEqual(a.fontSizeState, b.fontSizeState)) return false return ( a.canUndo === b.canUndo && a.canRedo === b.canRedo && a.styleId === b.styleId && a.canStepFontSizeDown === b.canStepFontSizeDown && a.canStepFontSizeUp === b.canStepFontSizeUp && a.textColor === b.textColor && a.highlightColor === b.highlightColor && a.isBold === b.isBold && a.isItalic === b.isItalic && a.isUnderline === b.isUnderline && a.isLink === b.isLink && a.alignLeft === b.alignLeft && a.alignCenter === b.alignCenter && a.alignRight === b.alignRight && a.alignJustify === b.alignJustify && a.isBulletList === b.isBulletList && a.isOrderedList === b.isOrderedList ) } function selectDocsToolbarStateOptional({ editor, }: { editor: Editor | null }): DocsToolbarEditorState | null { if (!editor) return null return selectDocsToolbarState({ editor }) } function toolbarStateEqualOptional( a: DocsToolbarEditorState | null, b: DocsToolbarEditorState | null ): boolean { if (a == null || b == null) return a === b return toolbarStateEqual(a, b) } export function useDocsToolbarState(editor: Editor | null): DocsToolbarEditorState | null { return useEditorState({ editor, selector: selectDocsToolbarStateOptional, equalityFn: toolbarStateEqualOptional, }) }