Files
AutoMetabuilder/frontend/autometabuilder/hooks/useCanvasNodes.ts
copilot-swe-agent[bot] 6e9ff896e7 Phase 9: Implement atomic hooks-based workflow canvas components
- Created custom hooks: useWorkflowGraph, useWorkflowPlugins, usePluginSearch, useTabNavigation
- Decomposed canvas logic into: useCanvasNodes, useCanvasEdges, useCanvasDragDrop
- Built atomic node components: NodeHeader, NodeBody, NodePorts
- Created canvas UI components: CanvasInfoPanel, CanvasHintPanel
- Split builder into: LoadingState, ErrorState, WorkflowBuilderHeader, WorkflowBuilderTabs, WorkflowBuilderContent
- Added React Flow for n8n-style visual canvas with drag-and-drop
- All components now under 100 LOC following PROMPT.md guidelines

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
2026-01-10 12:25:36 +00:00

43 lines
1.1 KiB
TypeScript

import { useEffect } from "react";
import { Node, useNodesState } from "reactflow";
import { WorkflowGraph, WorkflowPluginMap } from "../lib/types";
export function useCanvasNodes(
graph: WorkflowGraph,
plugins: WorkflowPluginMap,
t: (key: string, fallback?: string) => string,
onNodesChange?: (nodes: Node[]) => void
) {
const [nodes, setNodes, onNodesChangeInternal] = useNodesState([]);
useEffect(() => {
const flowNodes: Node[] = graph.nodes.map((node, index) => {
const plugin = plugins[node.type] || {};
const x = (index % 5) * 250;
const y = Math.floor(index / 5) * 150;
return {
id: node.id,
type: "workflow",
position: { x, y },
data: {
label: plugin.label ? t(plugin.label, node.type) : node.type,
type: node.type,
inputs: node.inputs || {},
outputs: node.outputs || {},
plugin,
t,
},
};
});
setNodes(flowNodes);
}, [graph, plugins, t, setNodes]);
useEffect(() => {
if (onNodesChange) onNodesChange(nodes);
}, [nodes, onNodesChange]);
return { nodes, setNodes, onNodesChangeInternal };
}