import { useCallback, useState } from 'react'; import { Layout, Type, Square, Image, Link, List, PanelTop, PanelBottom, Menu, ChevronRight, Edit3, Hash, Grid3X3, Music, Video, Code, Table, CheckSquare, Star, Layers, Plus } from 'lucide-react'; interface ElementPreset { tagName: string; label: string; icon: any; defaultProps: any; } const ELEMENT_CATEGORIES: { name: string; icon: any; items: ElementPreset[] }[] = [ { name: 'Layout', icon: Layout, items: [ { tagName: 'div', label: 'Container', icon: Layout, defaultProps: { style: { padding: '16px', border: '1px dashed #94a3b8', minHeight: '50px', borderRadius: '4px' } } }, { tagName: 'span', label: 'Inline Box', icon: Layout, defaultProps: { style: { padding: '4px 8px', border: '1px dashed #94a3b8', borderRadius: '4px', display: 'inline-block' } } }, { tagName: 'section', label: 'Section', icon: Layout, defaultProps: { style: { padding: '24px 16px', margin: '8px 0', border: '1px dashed #cbd5e1', borderRadius: '8px' } } }, { tagName: 'article', label: 'Article', icon: Layout, defaultProps: { style: { padding: '24px', margin: '8px 0', border: '1px dashed #cbd5e1', borderRadius: '8px' } } }, { tagName: 'main', label: 'Main Content', icon: Layout, defaultProps: { style: { padding: '16px', minHeight: '200px' } } }, { tagName: 'header', label: 'Header', icon: PanelTop, defaultProps: { style: { padding: '16px', background: '#f1f5f9', borderRadius: '4px' } } }, { tagName: 'footer', label: 'Footer', icon: PanelBottom, defaultProps: { style: { padding: '16px', background: '#f1f5f9', borderRadius: '4px', marginTop: '16px' } } }, { tagName: 'nav', label: 'Nav Bar', icon: Menu, defaultProps: { style: { padding: '12px 16px', background: '#1e293b', color: '#fff', display: 'flex', gap: '20px', borderRadius: '4px' } } }, { tagName: 'aside', label: 'Sidebar', icon: Layout, defaultProps: { style: { padding: '16px', background: '#f8fafc', borderRadius: '4px', width: '250px' } } }, { tagName: 'details', label: 'Details', icon: ChevronRight, defaultProps: { style: { padding: '8px', border: '1px solid #e2e8f0', borderRadius: '4px' } } }, { tagName: 'dialog', label: 'Dialog/Modal', icon: Layers, defaultProps: { style: { padding: '24px', background: '#fff', border: '1px solid #cbd5e1', borderRadius: '8px', boxShadow: '0 20px 60px rgba(0,0,0,0.3)', maxWidth: '400px', margin: '40px auto' } } }, ] }, { name: 'Typography', icon: Type, items: [ { tagName: 'h1', label: 'Heading 1', icon: Type, defaultProps: { textContent: 'Heading 1', style: { fontSize: '32px', fontWeight: 'bold', margin: '0 0 8px 0' } } }, { tagName: 'h2', label: 'Heading 2', icon: Type, defaultProps: { textContent: 'Heading 2', style: { fontSize: '28px', fontWeight: 'bold', margin: '0 0 8px 0' } } }, { tagName: 'h3', label: 'Heading 3', icon: Type, defaultProps: { textContent: 'Heading 3', style: { fontSize: '24px', fontWeight: '600', margin: '0 0 6px 0' } } }, { tagName: 'h4', label: 'Heading 4', icon: Type, defaultProps: { textContent: 'Heading 4', style: { fontSize: '20px', fontWeight: '600', margin: '0 0 6px 0' } } }, { tagName: 'h5', label: 'Heading 5', icon: Type, defaultProps: { textContent: 'Heading 5', style: { fontSize: '18px', fontWeight: '600', margin: '0 0 4px 0' } } }, { tagName: 'h6', label: 'Heading 6', icon: Type, defaultProps: { textContent: 'Heading 6', style: { fontSize: '16px', fontWeight: '600', margin: '0 0 4px 0' } } }, { tagName: 'p', label: 'Paragraph', icon: Type, defaultProps: { textContent: 'This is a paragraph of text that can be edited. You can change its color, size, and more in the properties panel.', style: { fontSize: '16px', lineHeight: '1.6', margin: '0 0 12px 0' } } }, { tagName: 'blockquote', label: 'Quote', icon: Type, defaultProps: { textContent: 'A famous quote goes right here.', style: { padding: '12px 20px', borderLeft: '4px solid #6366f1', background: '#f8fafc', fontStyle: 'italic', margin: '12px 0' } } }, { tagName: 'pre', label: 'Preformatted', icon: Code, defaultProps: { textContent: 'code block\n with formatting', style: { padding: '12px', background: '#1e293b', color: '#e2e8f0', borderRadius: '4px', fontFamily: 'monospace', fontSize: '14px' } } }, { tagName: 'code', label: 'Inline Code', icon: Code, defaultProps: { textContent: 'code()', style: { padding: '2px 6px', background: '#f1f5f9', borderRadius: '3px', fontFamily: 'monospace', fontSize: '14px' } } }, { tagName: 'mark', label: 'Highlight', icon: Type, defaultProps: { textContent: 'highlighted text', style: { background: '#fef08a', padding: '2px 4px', borderRadius: '2px' } } }, { tagName: 'small', label: 'Small Text', icon: Type, defaultProps: { textContent: 'small print', style: { fontSize: '12px', color: '#64748b' } } }, { tagName: 'abbr', label: 'Abbreviation', icon: Type, defaultProps: { textContent: 'HTML', style: { textDecoration: 'underline dotted', cursor: 'help' } } }, ] }, { name: 'Forms & Inputs', icon: Edit3, items: [ { tagName: 'form', label: 'Form', icon: Layout, defaultProps: { style: { padding: '20px', border: '1px solid #e2e8f0', borderRadius: '8px', background: '#f8fafc', display: 'flex', flexDirection: 'column', gap: '12px' } } }, { tagName: 'input', label: 'Text Input', icon: Edit3, defaultProps: { type: 'text', placeholder: 'Enter text...', style: { padding: '8px 12px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px', width: '100%' } } }, { tagName: 'input', label: 'Number Input', icon: Hash, defaultProps: { type: 'number', placeholder: '0', style: { padding: '8px 12px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px', width: '100%' } } }, { tagName: 'input', label: 'Email Input', icon: Edit3, defaultProps: { type: 'email', placeholder: 'email@example.com', style: { padding: '8px 12px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px', width: '100%' } } }, { tagName: 'input', label: 'Password Input', icon: Edit3, defaultProps: { type: 'password', placeholder: '••••••••', style: { padding: '8px 12px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px', width: '100%' } } }, { tagName: 'input', label: 'Checkbox', icon: CheckSquare, defaultProps: { type: 'checkbox', style: { width: '18px', height: '18px', cursor: 'pointer' } } }, { tagName: 'input', label: 'Radio', icon: Star, defaultProps: { type: 'radio', style: { width: '18px', height: '18px', cursor: 'pointer' } } }, { tagName: 'input', label: 'Color Picker', icon: Layout, defaultProps: { type: 'color', value: '#6366f1', style: { width: '40px', height: '40px', cursor: 'pointer', border: 'none', padding: '0' } } }, { tagName: 'input', label: 'Range Slider', icon: Layout, defaultProps: { type: 'range', min: '0', max: '100', value: '50', style: { width: '100%', cursor: 'pointer' } } }, { tagName: 'input', label: 'Date Picker', icon: Layout, defaultProps: { type: 'date', style: { padding: '8px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px' } } }, { tagName: 'input', label: 'File Upload', icon: Image, defaultProps: { type: 'file', style: { fontSize: '14px' } } }, { tagName: 'textarea', label: 'Text Area', icon: Edit3, defaultProps: { placeholder: 'Enter long text...', style: { padding: '8px 12px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px', width: '100%', minHeight: '80px', resize: 'vertical' } } }, { tagName: 'select', label: 'Dropdown', icon: ChevronRight, defaultProps: { style: { padding: '8px 12px', border: '1px solid #cbd5e1', borderRadius: '4px', fontSize: '14px', width: '100%', background: '#fff' } } }, { tagName: 'option', label: 'Option', icon: ChevronRight, defaultProps: { textContent: 'Option 1', value: '1', style: { padding: '4px' } } }, { tagName: 'label', label: 'Label', icon: Type, defaultProps: { textContent: 'Label:', style: { fontSize: '14px', fontWeight: '500', marginBottom: '4px', display: 'block' } } }, { tagName: 'fieldset', label: 'Field Set', icon: Layout, defaultProps: { style: { padding: '16px', border: '1px solid #cbd5e1', borderRadius: '6px' } } }, { tagName: 'legend', label: 'Legend', icon: Type, defaultProps: { textContent: 'Section Title', style: { fontSize: '14px', fontWeight: '600', padding: '0 6px' } } }, { tagName: 'progress', label: 'Progress Bar', icon: Layout, defaultProps: { value: '50', max: '100', style: { width: '100%', height: '12px', borderRadius: '6px' } } }, { tagName: 'meter', label: 'Meter', icon: Layout, defaultProps: { value: '0.6', min: '0', max: '1', style: { width: '100%', height: '16px' } } }, ] }, { name: 'Buttons', icon: Square, items: [ { tagName: 'button', label: 'Button', icon: Square, defaultProps: { textContent: 'Click Me', type: 'button', style: { padding: '10px 20px', background: '#6366f1', color: '#fff', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', fontWeight: '500' } } }, { tagName: 'button', label: 'Success Button', icon: Square, defaultProps: { textContent: 'Save', type: 'button', style: { padding: '10px 20px', background: '#22c55e', color: '#fff', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', fontWeight: '500' } } }, { tagName: 'button', label: 'Danger Button', icon: Square, defaultProps: { textContent: 'Delete', type: 'button', style: { padding: '10px 20px', background: '#ef4444', color: '#fff', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', fontWeight: '500' } } }, { tagName: 'button', label: 'Outline Button', icon: Square, defaultProps: { textContent: 'Cancel', type: 'button', style: { padding: '10px 20px', background: 'transparent', color: '#64748b', border: '1px solid #cbd5e1', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', fontWeight: '500' } } }, { tagName: 'button', label: 'Icon Button', icon: Square, defaultProps: { textContent: '★', type: 'button', style: { padding: '8px 12px', background: '#f1f5f9', color: '#64748b', border: '1px solid #e2e8f0', borderRadius: '6px', cursor: 'pointer', fontSize: '16px', lineHeight: '1' } } }, ] }, { name: 'Media', icon: Image, items: [ { tagName: 'img', label: 'Image', icon: Image, defaultProps: { src: 'https://via.placeholder.com/300x200', alt: 'Placeholder image', style: { maxWidth: '100%', borderRadius: '4px', height: 'auto' } } }, { tagName: 'img', label: 'Avatar', icon: Image, defaultProps: { src: 'https://via.placeholder.com/48', alt: 'Avatar', style: { borderRadius: '50%', width: '48px', height: '48px' } } }, { tagName: 'figure', label: 'Figure', icon: Image, defaultProps: { style: { margin: '12px 0', textAlign: 'center' } } }, { tagName: 'figcaption', label: 'Caption', icon: Type, defaultProps: { textContent: 'Image caption here', style: { fontSize: '13px', color: '#64748b', marginTop: '4px', fontStyle: 'italic' } } }, { tagName: 'picture', label: 'Picture', icon: Image, defaultProps: { style: { display: 'block' } } }, { tagName: 'video', label: 'Video', icon: Video, defaultProps: { src: 'https://www.w3schools.com/html/mov_bbb.mp4', controls: true, style: { maxWidth: '100%', borderRadius: '4px' } } }, { tagName: 'audio', label: 'Audio', icon: Music, defaultProps: { src: 'https://www.w3schools.com/html/horse.mp3', controls: true, style: { width: '100%' } } }, { tagName: 'canvas', label: 'Canvas', icon: Layout, defaultProps: { width: '300', height: '150', style: { border: '1px solid #cbd5e1', borderRadius: '4px', width: '100%' } } }, { tagName: 'svg', label: 'SVG Icon', icon: Layout, defaultProps: { width: '24', height: '24', viewBox: '0 0 24 24', style: { display: 'inline-block' } } }, { tagName: 'iframe', label: 'IFrame', icon: Layout, defaultProps: { src: 'https://example.com', style: { width: '100%', height: '200px', border: '1px solid #e2e8f0', borderRadius: '4px' } } }, ] }, { name: 'Links & Navigation', icon: Link, items: [ { tagName: 'a', label: 'Link', icon: Link, defaultProps: { href: '#', textContent: 'Click here', style: { color: '#6366f1', textDecoration: 'underline', cursor: 'pointer' } } }, { tagName: 'a', label: 'Button Link', icon: Link, defaultProps: { href: '#', textContent: 'Get Started', style: { display: 'inline-block', padding: '10px 24px', background: '#6366f1', color: '#fff', borderRadius: '6px', textDecoration: 'none', fontWeight: '500' } } }, { tagName: 'nav', label: 'Nav Bar', icon: Menu, defaultProps: { style: { padding: '12px 16px', background: '#1e293b', color: '#fff', display: 'flex', gap: '20px', borderRadius: '4px' } } }, ] }, { name: 'Lists', icon: List, items: [ { tagName: 'ul', label: 'Unordered List', icon: List, defaultProps: { style: { paddingLeft: '24px', margin: '8px 0' } } }, { tagName: 'ol', label: 'Ordered List', icon: List, defaultProps: { style: { paddingLeft: '24px', margin: '8px 0' } } }, { tagName: 'li', label: 'List Item', icon: List, defaultProps: { textContent: 'List item', style: { margin: '4px 0' } } }, { tagName: 'dl', label: 'Definition List', icon: List, defaultProps: { style: { margin: '8px 0' } } }, { tagName: 'dt', label: 'Term', icon: List, defaultProps: { textContent: 'Term', style: { fontWeight: '600', marginTop: '8px' } } }, { tagName: 'dd', label: 'Definition', icon: List, defaultProps: { textContent: 'Definition description', style: { marginLeft: '20px', color: '#475569' } } }, ] }, { name: 'Tables', icon: Table, items: [ { tagName: 'table', label: 'Table', icon: Table, defaultProps: { style: { width: '100%', borderCollapse: 'collapse', border: '1px solid #e2e8f0' } } }, { tagName: 'thead', label: 'Table Head', icon: Table, defaultProps: { style: { background: '#f8fafc' } } }, { tagName: 'tbody', label: 'Table Body', icon: Table, defaultProps: {} }, { tagName: 'tfoot', label: 'Table Foot', icon: Table, defaultProps: { style: { background: '#f8fafc', fontWeight: '600' } } }, { tagName: 'tr', label: 'Table Row', icon: Table, defaultProps: { style: { borderBottom: '1px solid #e2e8f0' } } }, { tagName: 'th', label: 'Table Header', icon: Table, defaultProps: { textContent: 'Header', style: { padding: '8px 12px', textAlign: 'left', fontWeight: '600', borderBottom: '2px solid #e2e8f0' } } }, { tagName: 'td', label: 'Table Cell', icon: Table, defaultProps: { textContent: 'Cell data', style: { padding: '8px 12px', borderBottom: '1px solid #e2e8f0' } } }, { tagName: 'caption', label: 'Table Caption', icon: Type, defaultProps: { textContent: 'Table Title', style: { captionSide: 'bottom', padding: '8px', fontSize: '13px', color: '#64748b', fontStyle: 'italic' } } }, ] }, { name: 'Interactive', icon: Layers, items: [ { tagName: 'details', label: 'Collapsible', icon: ChevronRight, defaultProps: { textContent: 'Click to expand', style: { padding: '8px 12px', border: '1px solid #e2e8f0', borderRadius: '6px' } } }, { tagName: 'summary', label: 'Summary', icon: ChevronRight, defaultProps: { textContent: 'Click me', style: { fontWeight: '600', cursor: 'pointer', padding: '4px 0' } } }, { tagName: 'dialog', label: 'Modal', icon: Layers, defaultProps: { textContent: 'Modal content', style: { padding: '24px', background: '#fff', border: 'none', borderRadius: '12px', boxShadow: '0 20px 60px rgba(0,0,0,0.3)', maxWidth: '400px', margin: '40px auto' } } }, { tagName: 'menu', label: 'Menu', icon: Menu, defaultProps: { style: { padding: '4px', border: '1px solid #e2e8f0', borderRadius: '6px', background: '#fff', display: 'flex', flexDirection: 'column', gap: '2px' } } }, ] }, { name: 'Semantic', icon: Type, items: [ { tagName: 'strong', label: 'Strong', icon: Type, defaultProps: { textContent: 'important text', style: { fontWeight: 'bold' } } }, { tagName: 'em', label: 'Emphasis', icon: Type, defaultProps: { textContent: 'emphasized text', style: { fontStyle: 'italic' } } }, { tagName: 'b', label: 'Bold', icon: Type, defaultProps: { textContent: 'bold text', style: { fontWeight: 'bold' } } }, { tagName: 'i', label: 'Italic', icon: Type, defaultProps: { textContent: 'italic text', style: { fontStyle: 'italic' } } }, { tagName: 'u', label: 'Underline', icon: Type, defaultProps: { textContent: 'underlined text', style: { textDecoration: 'underline' } } }, { tagName: 's', label: 'Strikethrough', icon: Type, defaultProps: { textContent: 'strikethrough', style: { textDecoration: 'line-through' } } }, { tagName: 'sub', label: 'Subscript', icon: Type, defaultProps: { textContent: '2', style: { fontSize: '75%', verticalAlign: 'sub' } } }, { tagName: 'sup', label: 'Superscript', icon: Type, defaultProps: { textContent: 'th', style: { fontSize: '75%', verticalAlign: 'super' } } }, { tagName: 'cite', label: 'Citation', icon: Type, defaultProps: { textContent: 'Source Title', style: { fontStyle: 'italic' } } }, { tagName: 'time', label: 'Date/Time', icon: Type, defaultProps: { textContent: 'June 9, 2026', style: { fontWeight: '500' } } }, { tagName: 'address', label: 'Address', icon: Type, defaultProps: { textContent: '123 Main St, City', style: { fontStyle: 'normal', padding: '8px', background: '#f8fafc', borderRadius: '4px' } } }, ] }, ]; export default function Toolbox() { const [expandedCategories, setExpandedCategories] = useState>(() => new Set(ELEMENT_CATEGORIES.slice(0, 3).map(c => c.name))); const handleDragStart = useCallback((e: React.DragEvent, element: ElementPreset) => { e.dataTransfer.setData('application/visual-element', JSON.stringify(element)); e.dataTransfer.effectAllowed = 'copy'; }, []); const toggleCategory = useCallback((name: string) => { setExpandedCategories(prev => { const next = new Set(prev); if (next.has(name)) next.delete(name); else next.add(name); return next; }); }, []); return (
{ELEMENT_CATEGORIES.map((cat) => { const isExpanded = expandedCategories.has(cat.name); const CatIcon = cat.icon; return (
{isExpanded && (
{cat.items.map((el) => { const Icon = el.icon; return (
handleDragStart(e, el)} className="w-full flex items-center gap-1.5 px-2 py-1 rounded-md cursor-grab active:cursor-grabbing hover:bg-surface-700 text-surface-400 hover:text-white transition-colors text-xs" title={el.label} > {el.label}
); })}
)}
); })}
); }