import { useCallback } from 'react'; import ReactFlow, { ReactFlowProvider, addEdge, Controls, Connection, CoordinateExtent, Position, useNodesState, useEdgesState, } from 'react-flow-renderer'; import dagre from 'dagre'; import initialItems from './initial-elements'; import './layouting.css'; const dagreGraph = new dagre.graphlib.Graph(); dagreGraph.setDefaultEdgeLabel(() => ({})); const nodeExtent: CoordinateExtent = [ [0, 0], [1000, 1000], ]; const LayoutFlow = () => { const [nodes, setNodes, onNodesChange] = useNodesState(initialItems.nodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialItems.edges); const onConnect = useCallback((connection: Connection) => { setEdges((eds) => addEdge(connection, eds)); }, []); const onLayout = (direction: string) => { const isHorizontal = direction === 'LR'; dagreGraph.setGraph({ rankdir: direction }); nodes.forEach((node) => { dagreGraph.setNode(node.id, { width: 150, height: 50 }); }); edges.forEach((edge) => { dagreGraph.setEdge(edge.source, edge.target); }); dagre.layout(dagreGraph); const layoutedNodes = nodes.map((node) => { const nodeWithPosition = dagreGraph.node(node.id); node.targetPosition = isHorizontal ? Position.Left : Position.Top; node.sourcePosition = isHorizontal ? Position.Right : Position.Bottom; // we need to pass a slightly different position in order to notify react flow about the change // @TODO how can we change the position handling so that we dont need this hack? node.position = { x: nodeWithPosition.x + Math.random() / 1000, y: nodeWithPosition.y }; return node; }); setNodes(layoutedNodes); }; return (
onLayout('TB')} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} >
); }; export default LayoutFlow;