MCPcopy Create free account
hub / github.com/ScaleML/AgentSPEX / getLayoutedElements

Function getLayoutedElements

yaml-flow-editor/src/utils/layout.ts:569–667  ·  view source on GitHub ↗
(
  nodes: FlowNode[],
  edges: FlowEdge[],
  direction: 'TB' | 'LR' = 'TB',
  options: LayoutOptions = {}
)

Source from the content-addressed store, hash-verified

567}
568
569export function getLayoutedElements(
570 nodes: FlowNode[],
571 edges: FlowEdge[],
572 direction: 'TB' | 'LR' = 'TB',
573 options: LayoutOptions = {}
574): { nodes: FlowNode[]; edges: FlowEdge[] } {
575 const { compact = false } = options;
576 if (nodes.length === 0) {
577 return { nodes, edges };
578 }
579
580 const nodeDimensions = new Map<string, { width: number; height: number }>();
581 nodes.forEach((node) => {
582 nodeDimensions.set(node.id, getNodeDimensions(node));
583 });
584
585 // ── Separate main workflow from orphan nodes ────────────────────
586 // The main workflow is the connected component that contains a 'start' node.
587 // All other components are treated as orphans and placed to the side.
588 const components = findConnectedComponents(nodes, edges);
589 const startNode = nodes.find((n) => n.type === 'start');
590 const mainIds = startNode
591 ? components.find((c) => c.has(startNode.id)) ?? new Set<string>()
592 : components.reduce((largest, c) => (c.size > largest.size ? c : largest), new Set<string>());
593
594 const mainNodes = nodes.filter((n) => mainIds.has(n.id));
595 const orphanNodes = nodes.filter((n) => !mainIds.has(n.id));
596 const mainEdges = edges.filter((e) => mainIds.has(e.source) && mainIds.has(e.target));
597
598 // ── Layout main workflow ────────────────────────────────────────
599 let layoutedMain: FlowNode[];
600
601 if (compact) {
602 layoutedMain = applyCompactGridLayout(
603 mainNodes, mainEdges, direction, nodeDimensions,
604 COMPACT_GRID_GAP, COMPACT_GRID_MARGIN,
605 );
606 } else {
607 const dagreGraph = new dagre.graphlib.Graph();
608 dagreGraph.setDefaultEdgeLabel(() => ({}));
609 dagreGraph.setGraph({
610 rankdir: direction,
611 nodesep: DEFAULT_NODESEP,
612 ranksep: DEFAULT_RANKSEP,
613 marginx: DEFAULT_MARGIN,
614 marginy: DEFAULT_MARGIN,
615 });
616
617 mainNodes.forEach((node) => {
618 const dim = nodeDimensions.get(node.id)!;
619 dagreGraph.setNode(node.id, { width: dim.width, height: dim.height });
620 });
621 mainEdges.forEach((edge) => {
622 dagreGraph.setEdge(edge.source, edge.target);
623 });
624 dagre.layout(dagreGraph);
625
626 const rawMain = mainNodes.map((node, index) => {

Callers 2

App.tsxFile · 0.90
applyFunction · 0.90

Calls 5

getNodeDimensionsFunction · 0.85
findConnectedComponentsFunction · 0.85
applyCompactGridLayoutFunction · 0.85
resolveOverlapsFunction · 0.85
getMethod · 0.80

Tested by

no test coverage detected