import React from 'react'; import { usePluginToolbarStore, type ToolbarItem } from '@/store/pluginToolbarStore'; function ToolbarButton({ item }: { item: ToolbarItem }) { return ( ); } function ToolbarSearch({ item }: { item: ToolbarItem }) { const [expanded, setExpanded] = React.useState(false); const [value, setValue] = React.useState(''); const inputRef = React.useRef(null); const handleToggle = () => { if (expanded) { // Collapse: clear and close setValue(''); item.onSearch?.(''); setExpanded(false); } else { setExpanded(true); setTimeout(() => inputRef.current?.focus(), 50); } }; const handleChange = (e: React.ChangeEvent) => { setValue(e.target.value); item.onSearch?.(e.target.value); }; if (!expanded) { return ( ); } return (
{ if (!value) { setExpanded(false); } }} className="w-28 sm:w-40 px-2 py-1 text-xs border border-secondary-200 rounded focus:outline-none focus:border-primary-400 focus:ring-1 focus:ring-primary-300 placeholder:text-secondary-400" />
); } function ToolbarDropdown({ item }: { item: ToolbarItem }) { const [open, setOpen] = React.useState(false); const ref = React.useRef(null); const menuRef = React.useRef(null); const [menuPos, setMenuPos] = React.useState({ top: 0, left: 0 }); React.useEffect(() => { if (!open) return; const handler = (e: MouseEvent) => { const target = e.target as Node; if (ref.current?.contains(target) || menuRef.current?.contains(target)) return; setOpen(false); }; document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, [open]); const handleToggle = () => { if (!open && ref.current) { const rect = ref.current.getBoundingClientRect(); setMenuPos({ top: rect.bottom + 4, left: rect.left }); } setOpen(!open); }; const activeOption = item.menuOptions?.find((o) => o.active); let lastSection: string | undefined = undefined; return ( <>
{open && (
{item.menuOptions?.map((opt) => { const showSection = opt.section && opt.section !== lastSection; if (showSection) lastSection = opt.section; return ( {showSection && (
{opt.section}
)} {opt.separator &&
} ); })}
)} ); } function ToolbarSelect({ item }: { item: ToolbarItem }) { return ( ); } export function PluginToolbar() { const { items, activePlugin } = usePluginToolbarStore(); const visibleItems = items.filter((i) => i.plugin === activePlugin); if (visibleItems.length === 0) return null; // Group items by group field const groups: Record = {}; for (const item of visibleItems) { const g = item.group || 'default'; if (!groups[g]) groups[g] = []; groups[g].push(item); } const groupNames = Object.keys(groups); const rightGroupNames = groupNames.filter((g) => g.startsWith('zz-right')); const leftGroupNames = groupNames.filter((g) => !g.startsWith('zz-right')); const renderGroup = (groupName: string, gi: number) => ( {gi > 0 &&
}
{groups[groupName].map((item) => { if (item.type === 'search') return ; if (item.type === 'select') return ; if (item.type === 'dropdown') return ; if (item.type === 'custom' && item.customComponent) return {item.customComponent}; return ; })}
); return (
{leftGroupNames.map((groupName, gi) => renderGroup(groupName, gi))} {rightGroupNames.length > 0 &&
} {rightGroupNames.map((groupName, gi) => renderGroup(groupName, gi))}
); }