import { useState, useRef, useEffect } from 'react' export default function NodeEditor({ nodes, setNodes, connections, setConnections, selectedNode, setSelectedNode }) { const canvasRef = useRef(null) const [isConnecting, setIsConnecting] = useState(false) const [connectionStart, setConnectionStart] = useState(null) const [draggedNode, setDraggedNode] = useState(null) const [mousePos, setMousePos] = useState({ x: 0, y: 0 }) useEffect(() => { const handleDragOver = (e) => { e.preventDefault() setMousePos({ x: e.clientX, y: e.clientY }) } const handleDrop = (e) => { e.preventDefault() const nodeType = e.dataTransfer.getData('node-type') if (nodeType && canvasRef.current) { const rect = canvasRef.current.getBoundingClientRect() const newNode = { id: `node-${Date.now()}`, type: nodeType, x: e.clientX - rect.left - 75, y: e.clientY - rect.top - 30, properties: { name: nodeType, units: 128, activation: 'relu' } } setNodes(prev => [...prev, newNode]) } } const canvas = canvasRef.current if (canvas) { canvas.addEventListener('dragover', handleDragOver) canvas.addEventListener('drop', handleDrop) } return () => { if (canvas) { canvas.removeEventListener('dragover', handleDragOver) canvas.removeEventListener('drop', handleDrop) } } }, [setNodes]) const handleNodeMouseDown = (e, nodeId) => { if (e.target.dataset.handle === 'output') { setIsConnecting(true) setConnectionStart(nodeId) } else { setDraggedNode(nodeId) setSelectedNode(nodeId) } } const handleNodeMouseUp = (e, nodeId) => { if (isConnecting && connectionStart && connectionStart !== nodeId) { const newConnection = { id: `conn-${Date.now()}`, from: connectionStart, to: nodeId } setConnections(prev => [...prev, newConnection]) } setIsConnecting(false) setConnectionStart(null) } const handleMouseMove = (e) => { if (draggedNode && canvasRef.current) { const rect = canvasRef.current.getBoundingClientRect() setNodes(prev => prev.map(node => node.id === draggedNode ? { ...node, x: e.clientX - rect.left - 75, y: e.clientY - rect.top - 30 } : node )) } setMousePos({ x: e.clientX, y: e.clientY }) } const handleMouseUp = () => { setDraggedNode(null) setIsConnecting(false) setConnectionStart(null) } return (
{/* Grid Background */}
{/* Connections */} {connections.map(conn => { const fromNode = nodes.find(n => n.id === conn.from) const toNode = nodes.find(n => n.id === conn.to) if (!fromNode || !toNode) return null return ( ) })} {isConnecting && connectionStart && (() => { const fromNode = nodes.find(n => n.id === connectionStart) if (!fromNode) return null return ( ) })()} {/* Nodes */} {nodes.map(node => (
handleNodeMouseDown(e, node.id)} onMouseUp={(e) => handleNodeMouseUp(e, node.id)} >

{node.properties.name}

{node.type}
Units: {node.properties.units}
))} {/* Empty State */} {nodes.length === 0 && (

Start Building Your Architecture

Drag layers from the toolbar onto the canvas

)}
) }