Selection state now stores IDs and derives objects from live arrays, so edits in PropertiesPanel inputs reflect immediately. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import { useCallback } from 'react'
|
|
import {
|
|
ReactFlow,
|
|
Background,
|
|
Controls,
|
|
MiniMap,
|
|
BackgroundVariant,
|
|
type OnConnect,
|
|
type OnNodesChange,
|
|
type OnEdgesChange,
|
|
type Node,
|
|
type Edge,
|
|
} from '@xyflow/react'
|
|
import { nodeTypes } from './nodes/nodeTypes'
|
|
import { edgeTypes } from './edges/edgeTypes'
|
|
|
|
interface NetworkCanvasProps {
|
|
nodes: Node[]
|
|
edges: Edge[]
|
|
onNodesChange: OnNodesChange
|
|
onEdgesChange: OnEdgesChange
|
|
onConnect: OnConnect
|
|
onNodeSelect: (nodeId: string | null) => void
|
|
onEdgeSelect: (edgeId: string | null) => void
|
|
onDrop: (event: React.DragEvent) => void
|
|
onDragOver: (event: React.DragEvent) => void
|
|
}
|
|
|
|
export function NetworkCanvas({
|
|
nodes,
|
|
edges,
|
|
onNodesChange,
|
|
onEdgesChange,
|
|
onConnect,
|
|
onNodeSelect,
|
|
onEdgeSelect,
|
|
onDrop,
|
|
onDragOver,
|
|
}: NetworkCanvasProps) {
|
|
const handleSelectionChange = useCallback(({ nodes: selectedNodes, edges: selectedEdges }: { nodes: Node[]; edges: Edge[] }) => {
|
|
if (selectedNodes.length === 1) {
|
|
onNodeSelect(selectedNodes[0].id)
|
|
onEdgeSelect(null)
|
|
} else if (selectedEdges.length === 1) {
|
|
onEdgeSelect(selectedEdges[0].id)
|
|
onNodeSelect(null)
|
|
} else {
|
|
onNodeSelect(null)
|
|
onEdgeSelect(null)
|
|
}
|
|
}, [onNodeSelect, onEdgeSelect])
|
|
|
|
const handlePaneClick = useCallback(() => {
|
|
onNodeSelect(null)
|
|
onEdgeSelect(null)
|
|
}, [onNodeSelect, onEdgeSelect])
|
|
|
|
return (
|
|
<ReactFlow
|
|
nodes={nodes}
|
|
edges={edges}
|
|
onNodesChange={onNodesChange}
|
|
onEdgesChange={onEdgesChange}
|
|
onConnect={onConnect}
|
|
onSelectionChange={handleSelectionChange}
|
|
onPaneClick={handlePaneClick}
|
|
onDrop={onDrop}
|
|
onDragOver={onDragOver}
|
|
nodeTypes={nodeTypes}
|
|
edgeTypes={edgeTypes}
|
|
defaultEdgeOptions={{ type: 'connection' }}
|
|
deleteKeyCode={['Backspace', 'Delete']}
|
|
multiSelectionKeyCode="Shift"
|
|
fitView
|
|
className="bg-page"
|
|
>
|
|
<Background variant={BackgroundVariant.Dots} color="var(--color-border-default)" gap={20} size={1} />
|
|
<Controls className="!border-default !bg-card [&>button]:!border-default [&>button]:!bg-card [&>button]:!fill-text-primary" />
|
|
<MiniMap
|
|
nodeColor="var(--color-bg-elevated)"
|
|
maskColor="rgba(0,0,0,0.5)"
|
|
className="!border-default !bg-card"
|
|
position="bottom-right"
|
|
/>
|
|
</ReactFlow>
|
|
)
|
|
}
|