"use client" import * as React from "react" import { isNodeSelection, type Editor } from "@tiptap/react" // --- Hooks --- import { useTiptapEditor } from "@/hooks/use-tiptap-editor" // --- Icons --- import { ChevronDownIcon } from "@/components/tiptap-icons/chevron-down-icon" import { HeadingIcon } from "@/components/tiptap-icons/heading-icon" // --- Lib --- import { isNodeInSchema } from "@/lib/tiptap-utils" // --- Tiptap UI --- import { HeadingButton, headingIcons, type Level, getFormattedHeadingName, } from "@/components/tiptap-ui/heading-button/heading-button" // --- UI Primitives --- import type { ButtonProps } from "@/components/tiptap-ui-primitive/button" import { Button } from "@/components/tiptap-ui-primitive/button" import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuGroup, } from "@/components/tiptap-ui-primitive/dropdown-menu" export interface HeadingDropdownMenuProps extends Omit { editor?: Editor | null levels?: Level[] hideWhenUnavailable?: boolean onOpenChange?: (isOpen: boolean) => void } export function HeadingDropdownMenu({ editor: providedEditor, levels = [1, 2, 3, 4, 5, 6], hideWhenUnavailable = false, onOpenChange, ...props }: HeadingDropdownMenuProps) { const [isOpen, setIsOpen] = React.useState(false) const editor = useTiptapEditor(providedEditor) const headingInSchema = isNodeInSchema("heading", editor) const handleOnOpenChange = React.useCallback( (open: boolean) => { setIsOpen(open) onOpenChange?.(open) }, [onOpenChange] ) const getActiveIcon = React.useCallback(() => { if (!editor) return const activeLevel = levels.find((level) => editor.isActive("heading", { level }) ) as Level | undefined if (!activeLevel) return const ActiveIcon = headingIcons[activeLevel] return }, [editor, levels]) const canToggleAnyHeading = React.useCallback((): boolean => { if (!editor) return false return levels.some((level) => editor.can().toggleNode("heading", "paragraph", { level }) ) }, [editor, levels]) const isDisabled = !canToggleAnyHeading() const isAnyHeadingActive = editor?.isActive("heading") ?? false const show = React.useMemo(() => { if (!headingInSchema || !editor) { return false } if (hideWhenUnavailable) { if (isNodeSelection(editor.state.selection) || !canToggleAnyHeading()) { return false } } return true }, [headingInSchema, editor, hideWhenUnavailable, canToggleAnyHeading]) if (!show || !editor || !editor.isEditable) { return null } return ( {levels.map((level) => ( ))} ) } export default HeadingDropdownMenu