'use client'; import * as React from 'react'; import type { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; import { ChevronRightIcon, FileCodeIcon, Heading1Icon, Heading2Icon, Heading3Icon, InfoIcon, ListIcon, ListOrderedIcon, MinusIcon, PilcrowIcon, PlusIcon, QuoteIcon, RadicalIcon, SquareIcon, SubscriptIcon, SuperscriptIcon, TableIcon, } from 'lucide-react'; import { KEYS } from 'platejs'; import { type PlateEditor, useEditorRef } from 'platejs/react'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { insertBlock, insertInlineElement, } from '@/components/editor/transforms'; import { ToolbarButton, ToolbarMenuGroup } from './toolbar'; type Group = { group: string; items: Item[]; }; type Item = { icon: React.ReactNode; value: string; onSelect: (editor: PlateEditor, value: string) => void; focusEditor?: boolean; label?: string; }; const groups: Group[] = [ { group: 'Basic blocks', items: [ { icon: , label: 'Paragraph', value: KEYS.p, }, { icon: , label: 'Heading 1', value: 'h1', }, { icon: , label: 'Heading 2', value: 'h2', }, { icon: , label: 'Heading 3', value: 'h3', }, { icon: , label: 'Table', value: KEYS.table, }, { icon: , label: 'Code block', value: KEYS.codeBlock, }, { icon: , label: 'Quote', value: KEYS.blockquote, }, { icon: , label: 'Divider', value: KEYS.hr, }, ].map((item) => ({ ...item, onSelect: (editor: PlateEditor, value: string) => { insertBlock(editor, value); }, })), }, { group: 'Lists', items: [ { icon: , label: 'Bulleted list', value: KEYS.ul, }, { icon: , label: 'Numbered list', value: KEYS.ol, }, { icon: , label: 'To-do list', value: KEYS.listTodo, }, { icon: , label: 'Toggle list', value: KEYS.toggle, }, ].map((item) => ({ ...item, onSelect: (editor: PlateEditor, value: string) => { insertBlock(editor, value); }, })), }, { group: 'Advanced', items: [ { icon: , label: 'Callout', value: KEYS.callout, }, { focusEditor: false, icon: , label: 'Equation', value: KEYS.equation, }, ].map((item) => ({ ...item, onSelect: (editor: PlateEditor, value: string) => { if (item.value === KEYS.equation) { insertInlineElement(editor, value); } else { insertBlock(editor, value); } }, })), }, { group: 'Marks', items: [ { icon: , label: 'Superscript', value: KEYS.sup, }, { icon: , label: 'Subscript', value: KEYS.sub, }, ].map((item) => ({ ...item, onSelect: (editor: PlateEditor, value: string) => { editor.tf.toggleMark(value, { remove: value === KEYS.sup ? KEYS.sub : KEYS.sup, }); }, })), }, ]; export function InsertToolbarButton(props: DropdownMenuProps) { const editor = useEditorRef(); const [open, setOpen] = React.useState(false); return ( {groups.map(({ group, items }) => ( {items.map(({ icon, label, value, onSelect, focusEditor }) => ( { onSelect(editor, value); if (focusEditor !== false) { editor.tf.focus(); } setOpen(false); }} className="group" >
{icon} {label || value}
))}
))}
); }