ReplicationDiagram.utils.ts45 lines · main
| 1 | import dagre from '@dagrejs/dagre' |
| 2 | import { Edge, Node, Position } from '@xyflow/react' |
| 3 | |
| 4 | import { NODE_WIDTH } from './Nodes' |
| 5 | |
| 6 | const NODE_SEP = 0 |
| 7 | const NODE_ROW_HEIGHT = 200 |
| 8 | |
| 9 | export const getDagreGraphLayout = (nodes: Node[], edges: Edge[]) => { |
| 10 | const dagreGraph = new dagre.graphlib.Graph() |
| 11 | dagreGraph.setDefaultEdgeLabel(() => ({})) |
| 12 | dagreGraph.setGraph({ |
| 13 | rankdir: 'LR', |
| 14 | ranksep: 200, |
| 15 | nodesep: NODE_SEP, |
| 16 | align: nodes.length <= 2 ? 'UL' : undefined, |
| 17 | }) |
| 18 | |
| 19 | nodes.forEach((node) => { |
| 20 | dagreGraph.setNode(node.id, { |
| 21 | width: NODE_WIDTH / 2, |
| 22 | height: NODE_ROW_HEIGHT / 2, |
| 23 | }) |
| 24 | }) |
| 25 | |
| 26 | edges.forEach((edge) => dagreGraph.setEdge(edge.source, edge.target)) |
| 27 | |
| 28 | dagre.layout(dagreGraph) |
| 29 | |
| 30 | nodes.forEach((node) => { |
| 31 | const nodeWithPosition = dagreGraph.node(node.id) |
| 32 | node.sourcePosition = Position.Right |
| 33 | node.targetPosition = Position.Left |
| 34 | // We are shifting the dagre node position (anchor=center center) to the top left |
| 35 | // so it matches the React Flow node anchor point (top left). |
| 36 | node.position = { |
| 37 | x: nodeWithPosition.x - nodeWithPosition.width / 2, |
| 38 | y: nodeWithPosition.y - nodeWithPosition.height / 2, |
| 39 | } |
| 40 | |
| 41 | return node |
| 42 | }) |
| 43 | |
| 44 | return { nodes, edges } |
| 45 | } |