import * as React from "react" import type { Editor } from "@tiptap/react" import type { FormatAction } from "../types" import type { VariantProps } from "class-variance-authority" import type { toggleVariants } from "@/components/ui/toggle" import { cn } from "@/lib/utils" import { CaretDownIcon } from "@radix-ui/react-icons" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { ToolbarButton } from "./toolbar-button" import { ShortcutKey } from "./shortcut-key" import { getShortcutKey } from "../utils" interface ToolbarSectionProps extends VariantProps { editor: Editor actions: FormatAction[] activeActions?: string[] mainActionCount?: number dropdownIcon?: React.ReactNode dropdownTooltip?: string dropdownClassName?: string } export const ToolbarSection: React.FC = ({ editor, actions, activeActions = actions.map((action) => action.value), mainActionCount = 0, dropdownIcon, dropdownTooltip = "More options", dropdownClassName = "w-12", size, variant, }) => { const { mainActions, dropdownActions } = React.useMemo(() => { const sortedActions = actions .filter((action) => activeActions.includes(action.value)) .sort( (a, b) => activeActions.indexOf(a.value) - activeActions.indexOf(b.value), ) return { mainActions: sortedActions.slice(0, mainActionCount), dropdownActions: sortedActions.slice(mainActionCount), } }, [actions, activeActions, mainActionCount]) const renderToolbarButton = React.useCallback( (action: FormatAction) => ( action.action(editor)} disabled={!action.canExecute(editor)} isActive={action.isActive(editor)} tooltip={`${action.label} ${action.shortcuts.map((s) => getShortcutKey(s).symbol).join(" ")}`} aria-label={action.label} size={size} variant={variant} > {action.icon} ), [editor, size, variant], ) const renderDropdownMenuItem = React.useCallback( (action: FormatAction) => ( action.action(editor)} disabled={!action.canExecute(editor)} className={cn("flex flex-row items-center justify-between gap-4", { "bg-accent": action.isActive(editor), })} aria-label={action.label} > {action.label} ), [editor], ) const isDropdownActive = React.useMemo( () => dropdownActions.some((action) => action.isActive(editor)), [dropdownActions, editor], ) return ( <> {mainActions.map(renderToolbarButton)} {dropdownActions.length > 0 && ( {dropdownIcon || } {dropdownActions.map(renderDropdownMenuItem)} )} ) } export default ToolbarSection