visual/react/lib/util_elk.tsx (94 lines of code) (raw):
'use client';
import { ElkNode, ElkExtendedEdge } from 'elkjs/lib/elk.bundled.js'
import { Node, Edge } from 'reactflow';
let rootID = 'root';
interface traverseOption {
elkNode: ElkNode,
parentNode?: ElkNode,
zIndex?: number,
}
export function traverseElk({ elkNode, parentNode, zIndex = 0 }: traverseOption, onNode: (opt: traverseOption) => void,) {
onNode({ elkNode, parentNode, zIndex })
elkNode.children && elkNode.children.forEach((child) => traverseElk({
elkNode: child,
parentNode: elkNode,
zIndex: zIndex + 1,
}, onNode));
}
export function fromElk(elkNode: ElkNode): { nodes: Node[], edges: Edge[] } {
let nodes: Node[] = [];
let edges: Edge[] = [];
traverseElk(
{ elkNode },
({ elkNode, parentNode, zIndex = 0 }: traverseOption) => {
if (elkNode.id !== rootID) {
nodes.push({
id: elkNode.id,
data: { label: elkNode.labels && elkNode.labels[0].text },
position: { x: elkNode.x || 0, y: elkNode.y || 0 },
parentId: parentNode && parentNode.id !== rootID ? parentNode.id : undefined,
zIndex: zIndex,
});
}
elkNode.edges && elkNode.edges.forEach((edge: ElkExtendedEdge) => {
edges.push({
id: edge.id,
source: edge.sources[0],
target: edge.targets[0],
zIndex: zIndex + 1,
});
});
},
)
return { nodes, edges }
}
export function toElk({ nodes, edges }: { nodes: Node[], edges: Edge[] }): ElkNode {
let rootElkNode: ElkNode = { id: rootID, children: [], edges: [] }
let allElkNodes: Map<string, ElkNode> = new Map();
let whoIsParent: Map<string, string> = new Map();
allElkNodes.set(rootID, rootElkNode)
nodes.forEach((node) => {
let elkNode = allElkNodes.get(node.id)
if (!elkNode) {
elkNode = {
id: node.id,
x: node.position.x,
y: node.position.y,
width: node.width === null ? undefined : node.width,
height: node.height === null ? undefined : node.height,
labels: [{text: node.data.label }],
children: [],
edges: [],
}
allElkNodes.set(node.id, elkNode)
}
let parentElkNode: ElkNode | undefined
let parentId = node.parentId || rootID
whoIsParent.set(node.id, parentId)
parentElkNode = allElkNodes.get(parentId)
if (!parentElkNode) {
parentElkNode = { id: parentId, children: [] }
allElkNodes.set(parentId, parentElkNode)
}
parentElkNode?.children?.push(elkNode)
})
edges.forEach((edge) => {
let sourceNode = allElkNodes.get(edge.source)
let targetNode = allElkNodes.get(edge.target)
if (sourceNode && targetNode) {
let elkEdge: ElkExtendedEdge = {
id: edge.id,
sources: [sourceNode.id],
targets: [targetNode.id],
}
let parent = whoIsParent.get(edge.source)
if (parent) {
let parentNode = allElkNodes.get(parent)
if (parentNode) {
parentNode.edges?.push(elkEdge)
}
}
}
})
return rootElkNode
}