| import { useState } from 'react' |
| import { |
| Database, Layers, Activity, Filter, Settings, ChevronDown, |
| Image, Type, Hash, Share2, Brain, Zap, BarChart3 |
| } from 'lucide-react' |
|
|
| const toolbarItems = [ |
| { |
| category: 'Input', |
| icon: Database, |
| color: 'text-blue-600', |
| bgColor: 'bg-blue-50', |
| items: [ |
| { name: 'Input Layer', icon: Image, desc: 'Input data layer' }, |
| { name: 'Embedding', icon: Type, desc: 'Embedding layer' }, |
| { name: 'Data Augmentation', icon: Zap, desc: 'Augment training data' } |
| ] |
| }, |
| { |
| category: 'Core', |
| icon: Layers, |
| color: 'text-purple-600', |
| bgColor: 'bg-purple-50', |
| items: [ |
| { name: 'Dense', icon: BarChart3, desc: 'Fully connected layer' }, |
| { name: 'Convolution', icon: Filter, desc: 'Conv2D layer' }, |
| { name: 'Recurrent', icon: Share2, desc: 'LSTM/GRU layer' }, |
| { name: 'Transformer', icon: Brain, desc: 'Attention layer' } |
| ] |
| }, |
| { |
| category: 'Activation', |
| icon: Activity, |
| color: 'text-green-600', |
| bgColor: 'bg-green-50', |
| items: [ |
| { name: 'ReLU', icon: Zap, desc: 'Rectified Linear Unit' }, |
| { name: 'Sigmoid', icon: Activity, desc: 'Sigmoid activation' }, |
| { name: 'Tanh', icon: BarChart3, desc: 'Hyperbolic tangent' }, |
| { name: 'Softmax', icon: Layers, desc: 'Softmax activation' } |
| ] |
| }, |
| { |
| category: 'Regularization', |
| icon: Filter, |
| color: 'text-orange-600', |
| bgColor: 'bg-orange-50', |
| items: [ |
| { name: 'Dropout', icon: Filter, desc: 'Dropout regularization' }, |
| { name: 'Batch Norm', icon: BarChart3, desc: 'Batch normalization' }, |
| { name: 'Layer Norm', icon: Layers, desc: 'Layer normalization' } |
| ] |
| }, |
| { |
| category: 'Output', |
| icon: Settings, |
| color: 'text-red-600', |
| bgColor: 'bg-red-50', |
| items: [ |
| { name: 'Output Layer', icon: Share2, desc: 'Final output layer' }, |
| { name: 'Loss Function', icon: Activity, desc: 'Loss/metric' }, |
| { name: 'Metric', icon: BarChart3, desc: 'Evaluation metric' } |
| ] |
| } |
| ] |
|
|
| export default function Toolbar({ sidebarOpen, setSidebarOpen }) { |
| const [expandedCategory, setExpandedCategory] = useState('Core') |
|
|
| const handleDragStart = (e, itemType) => { |
| e.dataTransfer.setData('node-type', itemType) |
| e.dataTransfer.effectAllowed = 'copy' |
| } |
|
|
| return ( |
| <> |
| {/* Mobile Sidebar */} |
| <div className={`fixed inset-0 z-40 lg:relative lg:inset-auto ${sidebarOpen ? 'block' : 'hidden'}`}> |
| <div className="absolute inset-0 bg-black bg-opacity-50 lg:hidden" onClick={() => setSidebarOpen(false)} /> |
| <div className="absolute left-0 top-0 h-full w-64 bg-white border-r border-gray-200 p-4 overflow-y-auto z-50 lg:relative lg:z-auto"> |
| <ToolbarContent |
| expandedCategory={expandedCategory} |
| setExpandedCategory={setExpandedCategory} |
| handleDragStart={handleDragStart} |
| /> |
| </div> |
| </div> |
| |
| {/* Desktop Toolbar */} |
| <div className="hidden lg:block w-64 bg-white border-r border-gray-200 p-4 overflow-y-auto" data-tutorial-target="toolbar"> |
| <ToolbarContent |
| expandedCategory={expandedCategory} |
| setExpandedCategory={setExpandedCategory} |
| handleDragStart={handleDragStart} |
| /> |
| </div> |
| </> |
| ) |
| } |
|
|
| function ToolbarContent({ expandedCategory, setExpandedCategory, handleDragStart }) { |
| return ( |
| <> |
| <div className="flex items-center justify-between mb-4"> |
| <h2 className="text-lg font-semibold text-gray-900">Layers & Nodes</h2> |
| <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" /> |
| </div> |
| <div className="space-y-2"> |
| {toolbarItems.map((category) => { |
| const Icon = category.icon |
| const isExpanded = expandedCategory === category.category |
| |
| return ( |
| <div key={category.category} className="border border-gray-200 rounded-lg overflow-hidden transition-all"> |
| <button |
| onClick={() => setExpandedCategory(isExpanded ? null : category.category)} |
| className={`w-full px-4 py-3 flex items-center justify-between transition-colors ${isExpanded ? category.bgColor : 'hover:bg-gray-50'}`} |
| > |
| <div className="flex items-center space-x-3"> |
| <Icon className={`w-5 h |