@cristianormazabal/triton-core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contracts/anchors.js +20 -0
- package/dist/contracts/anchors.js.map +1 -0
- package/dist/contracts/animations.d.ts +5 -0
- package/dist/contracts/animations.d.ts.map +1 -0
- package/dist/contracts/animations.js +15 -0
- package/dist/contracts/animations.js.map +1 -0
- package/dist/contracts/crosslink.d.ts +21 -41
- package/dist/contracts/crosslink.d.ts.map +1 -1
- package/dist/contracts/crosslink.js +17 -0
- package/dist/contracts/crosslink.js.map +1 -0
- package/dist/contracts/diagram.js +24 -0
- package/dist/contracts/diagram.js.map +1 -0
- package/dist/contracts/index.d.ts +6 -3
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +21 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/overlay.js +22 -0
- package/dist/contracts/overlay.js.map +1 -0
- package/dist/contracts/primitives.js +13 -0
- package/dist/contracts/primitives.js.map +1 -0
- package/dist/contracts/renderer.js +15 -0
- package/dist/contracts/renderer.js.map +1 -0
- package/dist/contracts/result.js +26 -0
- package/dist/contracts/result.js.map +1 -0
- package/dist/contracts/routing.d.ts +4 -0
- package/dist/contracts/routing.d.ts.map +1 -1
- package/dist/contracts/routing.js +14 -0
- package/dist/contracts/routing.js.map +1 -0
- package/dist/contracts/scene.d.ts +5 -1
- package/dist/contracts/scene.d.ts.map +1 -1
- package/dist/contracts/scene.js +18 -0
- package/dist/contracts/scene.js.map +1 -0
- package/dist/contracts/theme.js +18 -0
- package/dist/contracts/theme.js.map +1 -0
- package/dist/crosslink/connectors.d.ts +66 -0
- package/dist/crosslink/connectors.d.ts.map +1 -0
- package/dist/crosslink/connectors.js +130 -0
- package/dist/crosslink/connectors.js.map +1 -0
- package/dist/crosslink/engine2.d.ts +2 -2
- package/dist/crosslink/engine2.d.ts.map +1 -1
- package/dist/crosslink/engine2.js +783 -0
- package/dist/crosslink/engine2.js.map +1 -0
- package/dist/crosslink/engine3.d.ts +2 -2
- package/dist/crosslink/engine3.d.ts.map +1 -1
- package/dist/crosslink/engine3.js +968 -0
- package/dist/crosslink/engine3.js.map +1 -0
- package/dist/crosslink/index.d.ts +2 -0
- package/dist/crosslink/index.d.ts.map +1 -1
- package/dist/crosslink/index.js +4 -0
- package/dist/crosslink/index.js.map +1 -0
- package/dist/crosslink/render.d.ts +2 -2
- package/dist/crosslink/render.d.ts.map +1 -1
- package/dist/crosslink/render.js +997 -0
- package/dist/crosslink/render.js.map +1 -0
- package/dist/crosslink/resolve.js +331 -0
- package/dist/crosslink/resolve.js.map +1 -0
- package/dist/diagrams/{c4 → mermaid/c4}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/c4/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/c4/index.js +14 -0
- package/dist/diagrams/mermaid/c4/index.js.map +1 -0
- package/dist/diagrams/{c4 → mermaid/c4}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/c4/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/c4/ir.js +2 -0
- package/dist/diagrams/mermaid/c4/ir.js.map +1 -0
- package/dist/diagrams/{c4 → mermaid/c4}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/c4/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/c4/layout.js +110 -0
- package/dist/diagrams/mermaid/c4/layout.js.map +1 -0
- package/dist/diagrams/{class → mermaid/class}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/class/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/class/index.js +14 -0
- package/dist/diagrams/mermaid/class/index.js.map +1 -0
- package/dist/diagrams/{class → mermaid/class}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/class/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/class/ir.js +2 -0
- package/dist/diagrams/mermaid/class/ir.js.map +1 -0
- package/dist/diagrams/{class → mermaid/class}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/class/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/class/layout.js +877 -0
- package/dist/diagrams/mermaid/class/layout.js.map +1 -0
- package/dist/diagrams/{er → mermaid/er}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/er/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/er/index.js +14 -0
- package/dist/diagrams/mermaid/er/index.js.map +1 -0
- package/dist/diagrams/{er → mermaid/er}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/er/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/er/ir.js +2 -0
- package/dist/diagrams/mermaid/er/ir.js.map +1 -0
- package/dist/diagrams/{er → mermaid/er}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/er/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/er/layout.js +116 -0
- package/dist/diagrams/mermaid/er/layout.js.map +1 -0
- package/dist/diagrams/{flowchart → mermaid/flowchart}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/flowchart/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/flowchart/index.js +24 -0
- package/dist/diagrams/mermaid/flowchart/index.js.map +1 -0
- package/dist/diagrams/{flowchart → mermaid/flowchart}/ir.d.ts +7 -1
- package/dist/diagrams/mermaid/flowchart/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/flowchart/ir.js +2 -0
- package/dist/diagrams/mermaid/flowchart/ir.js.map +1 -0
- package/dist/diagrams/mermaid/flowchart/layout.d.ts +5 -0
- package/dist/diagrams/mermaid/flowchart/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/flowchart/layout.js +652 -0
- package/dist/diagrams/mermaid/flowchart/layout.js.map +1 -0
- package/dist/diagrams/{gantt → mermaid/gantt}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/gantt/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/gantt/index.js +89 -0
- package/dist/diagrams/mermaid/gantt/index.js.map +1 -0
- package/dist/diagrams/{gantt → mermaid/gantt}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/gantt/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/gantt/ir.js +2 -0
- package/dist/diagrams/mermaid/gantt/ir.js.map +1 -0
- package/dist/diagrams/{gantt → mermaid/gantt}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/gantt/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/gantt/layout.js +95 -0
- package/dist/diagrams/mermaid/gantt/layout.js.map +1 -0
- package/dist/diagrams/{gitgraph → mermaid/gitgraph}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/gitgraph/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/gitgraph/index.js +58 -0
- package/dist/diagrams/mermaid/gitgraph/index.js.map +1 -0
- package/dist/diagrams/{gitgraph → mermaid/gitgraph}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/gitgraph/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/gitgraph/ir.js +2 -0
- package/dist/diagrams/mermaid/gitgraph/ir.js.map +1 -0
- package/dist/diagrams/{gitgraph → mermaid/gitgraph}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/gitgraph/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/gitgraph/layout.js +89 -0
- package/dist/diagrams/mermaid/gitgraph/layout.js.map +1 -0
- package/dist/diagrams/{journey → mermaid/journey}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/journey/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/journey/index.js +14 -0
- package/dist/diagrams/mermaid/journey/index.js.map +1 -0
- package/dist/diagrams/{journey → mermaid/journey}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/journey/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/journey/ir.js +2 -0
- package/dist/diagrams/mermaid/journey/ir.js.map +1 -0
- package/dist/diagrams/{journey → mermaid/journey}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/journey/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/journey/layout.js +92 -0
- package/dist/diagrams/mermaid/journey/layout.js.map +1 -0
- package/dist/diagrams/{kanban → mermaid/kanban}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/kanban/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/kanban/index.js +14 -0
- package/dist/diagrams/mermaid/kanban/index.js.map +1 -0
- package/dist/diagrams/{kanban → mermaid/kanban}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/kanban/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/kanban/ir.js +2 -0
- package/dist/diagrams/mermaid/kanban/ir.js.map +1 -0
- package/dist/diagrams/{kanban → mermaid/kanban}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/kanban/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/kanban/layout.js +68 -0
- package/dist/diagrams/mermaid/kanban/layout.js.map +1 -0
- package/dist/diagrams/{mindmap → mermaid/mindmap}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/mindmap/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/mindmap/index.js +52 -0
- package/dist/diagrams/mermaid/mindmap/index.js.map +1 -0
- package/dist/diagrams/{mindmap → mermaid/mindmap}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/mindmap/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/mindmap/ir.js +2 -0
- package/dist/diagrams/mermaid/mindmap/ir.js.map +1 -0
- package/dist/diagrams/{mindmap → mermaid/mindmap}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/mindmap/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/mindmap/layout.js +100 -0
- package/dist/diagrams/mermaid/mindmap/layout.js.map +1 -0
- package/dist/diagrams/{pie → mermaid/pie}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/pie/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/pie/index.js +14 -0
- package/dist/diagrams/mermaid/pie/index.js.map +1 -0
- package/dist/diagrams/{pie → mermaid/pie}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/pie/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/pie/ir.js +2 -0
- package/dist/diagrams/mermaid/pie/ir.js.map +1 -0
- package/dist/diagrams/{pie → mermaid/pie}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/pie/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/pie/layout.js +84 -0
- package/dist/diagrams/mermaid/pie/layout.js.map +1 -0
- package/dist/diagrams/{quadrant → mermaid/quadrant}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/quadrant/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/quadrant/index.js +14 -0
- package/dist/diagrams/mermaid/quadrant/index.js.map +1 -0
- package/dist/diagrams/{quadrant → mermaid/quadrant}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/quadrant/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/quadrant/ir.js +2 -0
- package/dist/diagrams/mermaid/quadrant/ir.js.map +1 -0
- package/dist/diagrams/{quadrant → mermaid/quadrant}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/quadrant/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/quadrant/layout.js +83 -0
- package/dist/diagrams/mermaid/quadrant/layout.js.map +1 -0
- package/dist/diagrams/{radar → mermaid/radar}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/radar/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/radar/index.js +14 -0
- package/dist/diagrams/mermaid/radar/index.js.map +1 -0
- package/dist/diagrams/{radar → mermaid/radar}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/radar/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/radar/ir.js +2 -0
- package/dist/diagrams/mermaid/radar/ir.js.map +1 -0
- package/dist/diagrams/{radar → mermaid/radar}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/radar/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/radar/layout.js +91 -0
- package/dist/diagrams/mermaid/radar/layout.js.map +1 -0
- package/dist/diagrams/{requirement → mermaid/requirement}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/requirement/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/requirement/index.js +14 -0
- package/dist/diagrams/mermaid/requirement/index.js.map +1 -0
- package/dist/diagrams/{requirement → mermaid/requirement}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/requirement/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/requirement/ir.js +2 -0
- package/dist/diagrams/mermaid/requirement/ir.js.map +1 -0
- package/dist/diagrams/{requirement → mermaid/requirement}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/requirement/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/requirement/layout.js +79 -0
- package/dist/diagrams/mermaid/requirement/layout.js.map +1 -0
- package/dist/diagrams/{sankey → mermaid/sankey}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/sankey/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/sankey/index.js +14 -0
- package/dist/diagrams/mermaid/sankey/index.js.map +1 -0
- package/dist/diagrams/{sankey → mermaid/sankey}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/sankey/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/sankey/ir.js +2 -0
- package/dist/diagrams/mermaid/sankey/ir.js.map +1 -0
- package/dist/diagrams/{sankey → mermaid/sankey}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/sankey/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/sankey/layout.js +124 -0
- package/dist/diagrams/mermaid/sankey/layout.js.map +1 -0
- package/dist/diagrams/{sequence → mermaid/sequence}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/sequence/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/sequence/index.js +14 -0
- package/dist/diagrams/mermaid/sequence/index.js.map +1 -0
- package/dist/diagrams/{sequence → mermaid/sequence}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/sequence/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/sequence/ir.js +2 -0
- package/dist/diagrams/mermaid/sequence/ir.js.map +1 -0
- package/dist/diagrams/{sequence → mermaid/sequence}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/sequence/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/sequence/layout.js +168 -0
- package/dist/diagrams/mermaid/sequence/layout.js.map +1 -0
- package/dist/diagrams/{state → mermaid/state}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/state/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/state/index.js +14 -0
- package/dist/diagrams/mermaid/state/index.js.map +1 -0
- package/dist/diagrams/{state → mermaid/state}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/state/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/state/ir.js +2 -0
- package/dist/diagrams/mermaid/state/ir.js.map +1 -0
- package/dist/diagrams/{state → mermaid/state}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/state/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/state/layout.js +172 -0
- package/dist/diagrams/mermaid/state/layout.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/timeline/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/index.js +23 -0
- package/dist/diagrams/mermaid/timeline/index.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/timeline/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/ir.js +2 -0
- package/dist/diagrams/mermaid/timeline/ir.js.map +1 -0
- package/dist/diagrams/mermaid/timeline/layout.d.ts +5 -0
- package/dist/diagrams/mermaid/timeline/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/layout.js +228 -0
- package/dist/diagrams/mermaid/timeline/layout.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/numbered.d.ts +2 -2
- package/dist/diagrams/mermaid/timeline/numbered.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/numbered.js +112 -0
- package/dist/diagrams/mermaid/timeline/numbered.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/roadmap.d.ts +2 -2
- package/dist/diagrams/mermaid/timeline/roadmap.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/roadmap.js +125 -0
- package/dist/diagrams/mermaid/timeline/roadmap.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/serpentine.d.ts +2 -2
- package/dist/diagrams/mermaid/timeline/serpentine.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/serpentine.js +152 -0
- package/dist/diagrams/mermaid/timeline/serpentine.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/shared.d.ts +1 -1
- package/dist/diagrams/mermaid/timeline/shared.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/shared.js +47 -0
- package/dist/diagrams/mermaid/timeline/shared.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/timeline-columns.d.ts +2 -2
- package/dist/diagrams/mermaid/timeline/timeline-columns.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/timeline-columns.js +136 -0
- package/dist/diagrams/mermaid/timeline/timeline-columns.js.map +1 -0
- package/dist/diagrams/{timeline → mermaid/timeline}/vertical-spine.d.ts +2 -2
- package/dist/diagrams/mermaid/timeline/vertical-spine.d.ts.map +1 -0
- package/dist/diagrams/mermaid/timeline/vertical-spine.js +136 -0
- package/dist/diagrams/mermaid/timeline/vertical-spine.js.map +1 -0
- package/dist/diagrams/{xychart → mermaid/xychart}/index.d.ts +1 -1
- package/dist/diagrams/mermaid/xychart/index.d.ts.map +1 -0
- package/dist/diagrams/mermaid/xychart/index.js +14 -0
- package/dist/diagrams/mermaid/xychart/index.js.map +1 -0
- package/dist/diagrams/{xychart → mermaid/xychart}/ir.d.ts +1 -1
- package/dist/diagrams/mermaid/xychart/ir.d.ts.map +1 -0
- package/dist/diagrams/mermaid/xychart/ir.js +2 -0
- package/dist/diagrams/mermaid/xychart/ir.js.map +1 -0
- package/dist/diagrams/{xychart → mermaid/xychart}/layout.d.ts +2 -2
- package/dist/diagrams/mermaid/xychart/layout.d.ts.map +1 -0
- package/dist/diagrams/mermaid/xychart/layout.js +120 -0
- package/dist/diagrams/mermaid/xychart/layout.js.map +1 -0
- package/dist/diagrams/{architecture → triton/architecture}/index.d.ts +1 -1
- package/dist/diagrams/triton/architecture/index.d.ts.map +1 -0
- package/dist/diagrams/triton/architecture/index.js +14 -0
- package/dist/diagrams/triton/architecture/index.js.map +1 -0
- package/dist/diagrams/{architecture → triton/architecture}/ir.d.ts +1 -1
- package/dist/diagrams/triton/architecture/ir.d.ts.map +1 -0
- package/dist/diagrams/triton/architecture/ir.js +2 -0
- package/dist/diagrams/triton/architecture/ir.js.map +1 -0
- package/dist/diagrams/{architecture → triton/architecture}/layout.d.ts +2 -2
- package/dist/diagrams/triton/architecture/layout.d.ts.map +1 -0
- package/dist/diagrams/triton/architecture/layout.js +124 -0
- package/dist/diagrams/triton/architecture/layout.js.map +1 -0
- package/dist/diagrams/{block → triton/block}/index.d.ts +1 -1
- package/dist/diagrams/triton/block/index.d.ts.map +1 -0
- package/dist/diagrams/triton/block/index.js +14 -0
- package/dist/diagrams/triton/block/index.js.map +1 -0
- package/dist/diagrams/{block → triton/block}/ir.d.ts +1 -1
- package/dist/diagrams/triton/block/ir.d.ts.map +1 -0
- package/dist/diagrams/triton/block/ir.js +2 -0
- package/dist/diagrams/triton/block/ir.js.map +1 -0
- package/dist/diagrams/{block → triton/block}/layout.d.ts +2 -2
- package/dist/diagrams/triton/block/layout.d.ts.map +1 -0
- package/dist/diagrams/triton/block/layout.js +73 -0
- package/dist/diagrams/triton/block/layout.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/graph/graph.d.ts +1 -1
- package/dist/diagrams/triton/ds/graph/graph.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/graph/graph.js +140 -0
- package/dist/diagrams/triton/ds/graph/graph.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/hashmap/hashmap.d.ts +1 -1
- package/dist/diagrams/triton/ds/hashmap/hashmap.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/hashmap/hashmap.js +131 -0
- package/dist/diagrams/triton/ds/hashmap/hashmap.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/matrix/matrix.d.ts +1 -1
- package/dist/diagrams/triton/ds/matrix/matrix.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/matrix/matrix.js +113 -0
- package/dist/diagrams/triton/ds/matrix/matrix.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/queue/cqueue.d.ts +5 -3
- package/dist/diagrams/triton/ds/queue/cqueue.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/queue/cqueue.js +195 -0
- package/dist/diagrams/triton/ds/queue/cqueue.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/queue/deque.d.ts +3 -1
- package/dist/diagrams/triton/ds/queue/deque.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/queue/deque.js +118 -0
- package/dist/diagrams/triton/ds/queue/deque.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/queue/pqueue.d.ts +5 -3
- package/dist/diagrams/triton/ds/queue/pqueue.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/queue/pqueue.js +129 -0
- package/dist/diagrams/triton/ds/queue/pqueue.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/queue/queue.d.ts +3 -1
- package/dist/diagrams/triton/ds/queue/queue.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/queue/queue.js +128 -0
- package/dist/diagrams/triton/ds/queue/queue.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/queue/shared.d.ts +18 -2
- package/dist/diagrams/triton/ds/queue/shared.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/queue/shared.js +186 -0
- package/dist/diagrams/triton/ds/queue/shared.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/stack/stack.d.ts +3 -1
- package/dist/diagrams/triton/ds/stack/stack.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/stack/stack.js +119 -0
- package/dist/diagrams/triton/ds/stack/stack.js.map +1 -0
- package/dist/diagrams/triton/ds/struct/array.d.ts +52 -0
- package/dist/diagrams/triton/ds/struct/array.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/struct/array.js +491 -0
- package/dist/diagrams/triton/ds/struct/array.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/struct/linkedlist.d.ts +1 -1
- package/dist/diagrams/triton/ds/struct/linkedlist.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/struct/linkedlist.js +99 -0
- package/dist/diagrams/triton/ds/struct/linkedlist.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/struct/memory.d.ts +1 -1
- package/dist/diagrams/triton/ds/struct/memory.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/struct/memory.js +172 -0
- package/dist/diagrams/triton/ds/struct/memory.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/struct/page.d.ts +1 -1
- package/dist/diagrams/triton/ds/struct/page.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/struct/page.js +137 -0
- package/dist/diagrams/triton/ds/struct/page.js.map +1 -0
- package/dist/diagrams/triton/ds/struct/shared.d.ts +17 -0
- package/dist/diagrams/triton/ds/struct/shared.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/struct/shared.js +60 -0
- package/dist/diagrams/triton/ds/struct/shared.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/avl.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/avl.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/avl.js +87 -0
- package/dist/diagrams/triton/ds/tree/avl.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/btree.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/btree.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/btree.js +76 -0
- package/dist/diagrams/triton/ds/tree/btree.js.map +1 -0
- package/dist/diagrams/triton/ds/tree/build.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/build.js +51 -0
- package/dist/diagrams/triton/ds/tree/build.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/heap.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/heap.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/heap.js +48 -0
- package/dist/diagrams/triton/ds/tree/heap.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/index.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/index.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/index.js +20 -0
- package/dist/diagrams/triton/ds/tree/index.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/ir.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/ir.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/ir.js +10 -0
- package/dist/diagrams/triton/ds/tree/ir.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/layout.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/layout.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/layout.js +281 -0
- package/dist/diagrams/triton/ds/tree/layout.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/plan.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/plan.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/plan.js +48 -0
- package/dist/diagrams/triton/ds/tree/plan.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/radix.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/radix.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/radix.js +88 -0
- package/dist/diagrams/triton/ds/tree/radix.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/rbtree.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/rbtree.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/rbtree.js +78 -0
- package/dist/diagrams/triton/ds/tree/rbtree.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/tree/segtree.d.ts +1 -1
- package/dist/diagrams/triton/ds/tree/segtree.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/tree/segtree.js +51 -0
- package/dist/diagrams/triton/ds/tree/segtree.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/trie/trie.d.ts +1 -1
- package/dist/diagrams/triton/ds/trie/trie.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/trie/trie.js +58 -0
- package/dist/diagrams/triton/ds/trie/trie.js.map +1 -0
- package/dist/diagrams/{ds → triton/ds}/unionfind/unionfind.d.ts +1 -1
- package/dist/diagrams/triton/ds/unionfind/unionfind.d.ts.map +1 -0
- package/dist/diagrams/triton/ds/unionfind/unionfind.js +110 -0
- package/dist/diagrams/triton/ds/unionfind/unionfind.js.map +1 -0
- package/dist/diagrams/{packet → triton/packet}/index.d.ts +1 -1
- package/dist/diagrams/triton/packet/index.d.ts.map +1 -0
- package/dist/diagrams/triton/packet/index.js +14 -0
- package/dist/diagrams/triton/packet/index.js.map +1 -0
- package/dist/diagrams/{packet → triton/packet}/ir.d.ts +1 -1
- package/dist/diagrams/triton/packet/ir.d.ts.map +1 -0
- package/dist/diagrams/triton/packet/ir.js +2 -0
- package/dist/diagrams/triton/packet/ir.js.map +1 -0
- package/dist/diagrams/{packet → triton/packet}/layout.d.ts +2 -2
- package/dist/diagrams/triton/packet/layout.d.ts.map +1 -0
- package/dist/diagrams/triton/packet/layout.js +69 -0
- package/dist/diagrams/triton/packet/layout.js.map +1 -0
- package/dist/diagrams/{poster → triton/poster}/index.d.ts +1 -1
- package/dist/diagrams/triton/poster/index.d.ts.map +1 -0
- package/dist/diagrams/triton/poster/index.js +127 -0
- package/dist/diagrams/triton/poster/index.js.map +1 -0
- package/dist/diagrams/{poster → triton/poster}/ir.d.ts +1 -3
- package/dist/diagrams/{poster → triton/poster}/ir.d.ts.map +1 -1
- package/dist/diagrams/triton/poster/ir.js +2 -0
- package/dist/diagrams/triton/poster/ir.js.map +1 -0
- package/dist/diagrams/{poster → triton/poster}/layout.d.ts +2 -2
- package/dist/diagrams/triton/poster/layout.d.ts.map +1 -0
- package/dist/diagrams/triton/poster/layout.js +517 -0
- package/dist/diagrams/triton/poster/layout.js.map +1 -0
- package/dist/diagrams/{topology → triton/topology}/topology.d.ts +2 -2
- package/dist/diagrams/triton/topology/topology.d.ts.map +1 -0
- package/dist/diagrams/triton/topology/topology.js +198 -0
- package/dist/diagrams/triton/topology/topology.js.map +1 -0
- package/dist/frontend/detect.js +94 -0
- package/dist/frontend/detect.js.map +1 -0
- package/dist/frontend/index.d.ts +4 -4
- package/dist/frontend/index.d.ts.map +1 -1
- package/dist/frontend/index.js +196 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/preprocess.d.ts +28 -0
- package/dist/frontend/preprocess.d.ts.map +1 -0
- package/dist/frontend/preprocess.js +60 -0
- package/dist/frontend/preprocess.js.map +1 -0
- package/dist/frontend/registry.js +25 -0
- package/dist/frontend/registry.js.map +1 -0
- package/dist/graph/connect.js +44 -0
- package/dist/graph/connect.js.map +1 -0
- package/dist/graph/layered.d.ts +65 -5
- package/dist/graph/layered.d.ts.map +1 -1
- package/dist/graph/layered.js +936 -0
- package/dist/graph/layered.js.map +1 -0
- package/dist/graph/tree.js +107 -0
- package/dist/graph/tree.js.map +1 -0
- package/dist/index.js +4691 -2735
- package/dist/index.js.map +4 -4
- package/dist/overlay/apply.js +22 -0
- package/dist/overlay/apply.js.map +1 -0
- package/dist/overlay/compiler.js +48 -0
- package/dist/overlay/compiler.js.map +1 -0
- package/dist/overlay/layout.js +242 -0
- package/dist/overlay/layout.js.map +1 -0
- package/dist/palette/categorical.js +21 -0
- package/dist/palette/categorical.js.map +1 -0
- package/dist/render/registry.js +22 -0
- package/dist/render/registry.js.map +1 -0
- package/dist/render/svg.d.ts.map +1 -1
- package/dist/render/svg.js +287 -0
- package/dist/render/svg.js.map +1 -0
- package/dist/routing/d3-curves.d.ts +31 -0
- package/dist/routing/d3-curves.d.ts.map +1 -0
- package/dist/routing/d3-curves.js +58 -0
- package/dist/routing/d3-curves.js.map +1 -0
- package/dist/routing/registry.js +22 -0
- package/dist/routing/registry.js.map +1 -0
- package/dist/routing/router.d.ts +3 -0
- package/dist/routing/router.d.ts.map +1 -1
- package/dist/routing/router.js +849 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/scene/build.d.ts +3 -1
- package/dist/scene/build.d.ts.map +1 -1
- package/dist/scene/build.js +57 -0
- package/dist/scene/build.js.map +1 -0
- package/dist/scene/strip.js +46 -0
- package/dist/scene/strip.js.map +1 -0
- package/dist/style/cost.js +39 -0
- package/dist/style/cost.js.map +1 -0
- package/dist/text/metrics.js +62 -0
- package/dist/text/metrics.js.map +1 -0
- package/dist/text/wrap.js +84 -0
- package/dist/text/wrap.js.map +1 -0
- package/dist/theme/preset.d.ts +2 -0
- package/dist/theme/preset.d.ts.map +1 -1
- package/dist/theme/preset.js +295 -0
- package/dist/theme/preset.js.map +1 -0
- package/dist/theme/resolver.js +15 -0
- package/dist/theme/resolver.js.map +1 -0
- package/dist/time/dates.js +301 -0
- package/dist/time/dates.js.map +1 -0
- package/dist/util/round.js +17 -0
- package/dist/util/round.js.map +1 -0
- package/package.json +1 -1
- package/dist/diagrams/architecture/index.d.ts.map +0 -1
- package/dist/diagrams/architecture/ir.d.ts.map +0 -1
- package/dist/diagrams/architecture/layout.d.ts.map +0 -1
- package/dist/diagrams/block/index.d.ts.map +0 -1
- package/dist/diagrams/block/ir.d.ts.map +0 -1
- package/dist/diagrams/block/layout.d.ts.map +0 -1
- package/dist/diagrams/c4/index.d.ts.map +0 -1
- package/dist/diagrams/c4/ir.d.ts.map +0 -1
- package/dist/diagrams/c4/layout.d.ts.map +0 -1
- package/dist/diagrams/class/index.d.ts.map +0 -1
- package/dist/diagrams/class/ir.d.ts.map +0 -1
- package/dist/diagrams/class/layout.d.ts.map +0 -1
- package/dist/diagrams/ds/graph/graph.d.ts.map +0 -1
- package/dist/diagrams/ds/hashmap/hashmap.d.ts.map +0 -1
- package/dist/diagrams/ds/matrix/matrix.d.ts.map +0 -1
- package/dist/diagrams/ds/queue/cqueue.d.ts.map +0 -1
- package/dist/diagrams/ds/queue/deque.d.ts.map +0 -1
- package/dist/diagrams/ds/queue/pqueue.d.ts.map +0 -1
- package/dist/diagrams/ds/queue/queue.d.ts.map +0 -1
- package/dist/diagrams/ds/queue/shared.d.ts.map +0 -1
- package/dist/diagrams/ds/stack/stack.d.ts.map +0 -1
- package/dist/diagrams/ds/struct/array.d.ts +0 -28
- package/dist/diagrams/ds/struct/array.d.ts.map +0 -1
- package/dist/diagrams/ds/struct/linkedlist.d.ts.map +0 -1
- package/dist/diagrams/ds/struct/memory.d.ts.map +0 -1
- package/dist/diagrams/ds/struct/page.d.ts.map +0 -1
- package/dist/diagrams/ds/struct/shared.d.ts +0 -9
- package/dist/diagrams/ds/struct/shared.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/avl.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/btree.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/build.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/heap.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/index.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/ir.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/layout.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/plan.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/radix.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/rbtree.d.ts.map +0 -1
- package/dist/diagrams/ds/tree/segtree.d.ts.map +0 -1
- package/dist/diagrams/ds/trie/trie.d.ts.map +0 -1
- package/dist/diagrams/ds/unionfind/unionfind.d.ts.map +0 -1
- package/dist/diagrams/er/index.d.ts.map +0 -1
- package/dist/diagrams/er/ir.d.ts.map +0 -1
- package/dist/diagrams/er/layout.d.ts.map +0 -1
- package/dist/diagrams/flowchart/index.d.ts.map +0 -1
- package/dist/diagrams/flowchart/ir.d.ts.map +0 -1
- package/dist/diagrams/flowchart/layout.d.ts +0 -5
- package/dist/diagrams/flowchart/layout.d.ts.map +0 -1
- package/dist/diagrams/gantt/index.d.ts.map +0 -1
- package/dist/diagrams/gantt/ir.d.ts.map +0 -1
- package/dist/diagrams/gantt/layout.d.ts.map +0 -1
- package/dist/diagrams/gitgraph/index.d.ts.map +0 -1
- package/dist/diagrams/gitgraph/ir.d.ts.map +0 -1
- package/dist/diagrams/gitgraph/layout.d.ts.map +0 -1
- package/dist/diagrams/journey/index.d.ts.map +0 -1
- package/dist/diagrams/journey/ir.d.ts.map +0 -1
- package/dist/diagrams/journey/layout.d.ts.map +0 -1
- package/dist/diagrams/kanban/index.d.ts.map +0 -1
- package/dist/diagrams/kanban/ir.d.ts.map +0 -1
- package/dist/diagrams/kanban/layout.d.ts.map +0 -1
- package/dist/diagrams/mindmap/index.d.ts.map +0 -1
- package/dist/diagrams/mindmap/ir.d.ts.map +0 -1
- package/dist/diagrams/mindmap/layout.d.ts.map +0 -1
- package/dist/diagrams/packet/index.d.ts.map +0 -1
- package/dist/diagrams/packet/ir.d.ts.map +0 -1
- package/dist/diagrams/packet/layout.d.ts.map +0 -1
- package/dist/diagrams/pie/index.d.ts.map +0 -1
- package/dist/diagrams/pie/ir.d.ts.map +0 -1
- package/dist/diagrams/pie/layout.d.ts.map +0 -1
- package/dist/diagrams/poster/index.d.ts.map +0 -1
- package/dist/diagrams/poster/layout.d.ts.map +0 -1
- package/dist/diagrams/quadrant/index.d.ts.map +0 -1
- package/dist/diagrams/quadrant/ir.d.ts.map +0 -1
- package/dist/diagrams/quadrant/layout.d.ts.map +0 -1
- package/dist/diagrams/radar/index.d.ts.map +0 -1
- package/dist/diagrams/radar/ir.d.ts.map +0 -1
- package/dist/diagrams/radar/layout.d.ts.map +0 -1
- package/dist/diagrams/requirement/index.d.ts.map +0 -1
- package/dist/diagrams/requirement/ir.d.ts.map +0 -1
- package/dist/diagrams/requirement/layout.d.ts.map +0 -1
- package/dist/diagrams/sankey/index.d.ts.map +0 -1
- package/dist/diagrams/sankey/ir.d.ts.map +0 -1
- package/dist/diagrams/sankey/layout.d.ts.map +0 -1
- package/dist/diagrams/sequence/index.d.ts.map +0 -1
- package/dist/diagrams/sequence/ir.d.ts.map +0 -1
- package/dist/diagrams/sequence/layout.d.ts.map +0 -1
- package/dist/diagrams/state/index.d.ts.map +0 -1
- package/dist/diagrams/state/ir.d.ts.map +0 -1
- package/dist/diagrams/state/layout.d.ts.map +0 -1
- package/dist/diagrams/timeline/index.d.ts.map +0 -1
- package/dist/diagrams/timeline/ir.d.ts.map +0 -1
- package/dist/diagrams/timeline/layout.d.ts +0 -5
- package/dist/diagrams/timeline/layout.d.ts.map +0 -1
- package/dist/diagrams/timeline/numbered.d.ts.map +0 -1
- package/dist/diagrams/timeline/roadmap.d.ts.map +0 -1
- package/dist/diagrams/timeline/serpentine.d.ts.map +0 -1
- package/dist/diagrams/timeline/shared.d.ts.map +0 -1
- package/dist/diagrams/timeline/timeline-columns.d.ts.map +0 -1
- package/dist/diagrams/timeline/vertical-spine.d.ts.map +0 -1
- package/dist/diagrams/topology/topology.d.ts.map +0 -1
- package/dist/diagrams/xychart/index.d.ts.map +0 -1
- package/dist/diagrams/xychart/ir.d.ts.map +0 -1
- package/dist/diagrams/xychart/layout.d.ts.map +0 -1
- /package/dist/diagrams/{ds → triton/ds}/tree/build.d.ts +0 -0
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
import { getRouter } from '../../../routing/registry.js';
|
|
2
|
+
import { defaultRouter } from '../../../routing/router.js';
|
|
3
|
+
import { applyOverlays } from '../../../overlay/apply.js';
|
|
4
|
+
import { pen } from '../../../scene/build.js';
|
|
5
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
6
|
+
const NODE_W = 120;
|
|
7
|
+
const NODE_H = 40;
|
|
8
|
+
const ARROW_MARKER_ID = 'triton-arrow';
|
|
9
|
+
// ─── Public Entry ─────────────────────────────────────────────────────────────
|
|
10
|
+
export function layoutFlowchart(ir, theme, options) {
|
|
11
|
+
const { spacing, palette, typography, edges: edgeTheme } = theme;
|
|
12
|
+
const p = pen(theme);
|
|
13
|
+
const margin = spacing.diagramMargin;
|
|
14
|
+
const isLR = ir.direction === 'LR' || ir.direction === 'RL';
|
|
15
|
+
const isReverse = ir.direction === 'RL' || ir.direction === 'BT';
|
|
16
|
+
// ── Layer assignment ───────────────────────────────────────────────────────
|
|
17
|
+
const layers = assignLayers(ir.nodes, ir.edges);
|
|
18
|
+
const byLayer = groupByLayer(ir.nodes, layers);
|
|
19
|
+
// ── Phase 3: Crossing minimisation ────────────────────────────────────────
|
|
20
|
+
// Back-edges computed once; reused by both layout phases and the edge-drawing
|
|
21
|
+
// loop below (avoids a second DFS).
|
|
22
|
+
const backEdges = findBackEdges(ir.nodes, ir.edges);
|
|
23
|
+
const orderedByLayer = minimizeCrossings(byLayer, ir.edges, backEdges);
|
|
24
|
+
// ── Phase 4: Brandes–Köpf coordinate assignment ───────────────────────────
|
|
25
|
+
const colGap = spacing.nodeGap;
|
|
26
|
+
const rowGap = spacing.nodeGap;
|
|
27
|
+
let maxNodesInLayer = 0;
|
|
28
|
+
for (const [, nodes] of orderedByLayer)
|
|
29
|
+
maxNodesInLayer = Math.max(maxNodesInLayer, nodes.length);
|
|
30
|
+
const nodePos = assignCoordinatesBK(orderedByLayer, ir.edges, backEdges, isLR, isReverse, maxNodesInLayer, NODE_W, NODE_H, colGap, rowGap, margin);
|
|
31
|
+
// ── Build scene elements ───────────────────────────────────────────────────
|
|
32
|
+
const elements = [];
|
|
33
|
+
// Title
|
|
34
|
+
if (ir.metadata.title) {
|
|
35
|
+
elements.push(p.text(ir.metadata.title, margin, margin - 8, typography.titleFontSize, palette.text, { weight: 'bold' }));
|
|
36
|
+
}
|
|
37
|
+
// Subgraph backgrounds (drawn first — behind nodes)
|
|
38
|
+
for (const sg of ir.subgraphs) {
|
|
39
|
+
const sgRects = sg.nodeIds
|
|
40
|
+
.map(id => nodePos.get(id))
|
|
41
|
+
.filter((r) => r !== undefined);
|
|
42
|
+
if (sgRects.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
const pad = 12;
|
|
45
|
+
const minX = Math.min(...sgRects.map(r => r.x)) - pad;
|
|
46
|
+
const minY = Math.min(...sgRects.map(r => r.y)) - pad - 20;
|
|
47
|
+
const maxX = Math.max(...sgRects.map(r => r.x + r.width)) + pad;
|
|
48
|
+
const maxY = Math.max(...sgRects.map(r => r.y + r.height)) + pad;
|
|
49
|
+
elements.push(p.rect({ x: minX, y: minY, width: maxX - minX, height: maxY - minY }, palette.surface, palette.border, 1, { rx: 6, opacity: 0.6 }));
|
|
50
|
+
elements.push(p.text(sg.label, minX + 8, minY + 14, typography.smallFontSize, palette.textMuted));
|
|
51
|
+
}
|
|
52
|
+
// Edges (drawn before nodes so nodes appear on top).
|
|
53
|
+
//
|
|
54
|
+
// Back-edges (the cycle-closing edges identified by `findBackEdges`, the same
|
|
55
|
+
// set excluded from layer ranks) and self-loops are routed specially so they
|
|
56
|
+
// read as "feedback" instead of cutting straight back through the node column.
|
|
57
|
+
// Every OTHER (forward / acyclic) edge takes the unchanged orthogonal-router
|
|
58
|
+
// path below, so acyclic diagrams render byte-identically.
|
|
59
|
+
// (backEdges was computed in the layout phase above — reused here.)
|
|
60
|
+
let bowMaxX = -Infinity;
|
|
61
|
+
let bowMaxY = -Infinity;
|
|
62
|
+
for (let ei = 0; ei < ir.edges.length; ei++) {
|
|
63
|
+
const edge = ir.edges[ei];
|
|
64
|
+
const fromRect = nodePos.get(edge.from);
|
|
65
|
+
const toRect = nodePos.get(edge.to);
|
|
66
|
+
if (!fromRect || !toRect)
|
|
67
|
+
continue;
|
|
68
|
+
const dash = edge.style === 'dotted' ? '6 3' : edge.style === 'dashed' ? '8 4' : undefined;
|
|
69
|
+
// Self-loop (A → A): a small loop off one side, never a zero-length line.
|
|
70
|
+
if (edge.from === edge.to) {
|
|
71
|
+
const loop = selfLoopRoute(fromRect, isLR);
|
|
72
|
+
elements.push(p.path(loop.path, edge.kind === 'async' ? palette.textMuted : palette.primary, edgeTheme.strokeWidth, {
|
|
73
|
+
...(dash !== undefined ? { dash } : {}),
|
|
74
|
+
markerEnd: ARROW_MARKER_ID,
|
|
75
|
+
}));
|
|
76
|
+
bowMaxX = Math.max(bowMaxX, loop.maxX);
|
|
77
|
+
bowMaxY = Math.max(bowMaxY, loop.maxY);
|
|
78
|
+
if (edge.label) {
|
|
79
|
+
elements.push(p.text(edge.label, loop.labelPos.x, loop.labelPos.y - 4, edgeTheme.labelFontSize, palette.textMuted, { anchor: 'middle' }));
|
|
80
|
+
}
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Back-edge (feedback): bow out to one side around the intervening nodes.
|
|
84
|
+
if (backEdges.has(ei)) {
|
|
85
|
+
const bow = backEdgeRoute(fromRect, toRect, isLR);
|
|
86
|
+
elements.push(p.path(bow.path, edge.kind === 'async' ? palette.textMuted : palette.primary, edgeTheme.strokeWidth, {
|
|
87
|
+
...(dash !== undefined ? { dash } : {}),
|
|
88
|
+
markerEnd: ARROW_MARKER_ID,
|
|
89
|
+
}));
|
|
90
|
+
bowMaxX = Math.max(bowMaxX, bow.maxX);
|
|
91
|
+
bowMaxY = Math.max(bowMaxY, bow.maxY);
|
|
92
|
+
if (edge.label) {
|
|
93
|
+
elements.push(p.text(edge.label, bow.labelPos.x, bow.labelPos.y - 4, edgeTheme.labelFontSize, palette.textMuted, { anchor: 'middle' }));
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// Forward edge — default orthogonal route; an @route hint may override the
|
|
98
|
+
// routing style (straight | bezier | polyline) and/or the exit/entry walls.
|
|
99
|
+
const fromAnchor = edge.exitWall
|
|
100
|
+
? wallAnchor(fromRect, edge.exitWall)
|
|
101
|
+
: edgeAnchor(fromRect, ir.direction, 'exit', toRect);
|
|
102
|
+
const toAnchor = edge.entryWall
|
|
103
|
+
? wallAnchor(toRect, edge.entryWall)
|
|
104
|
+
: edgeAnchor(toRect, ir.direction, 'enter', fromRect);
|
|
105
|
+
const style = edge.routing ?? 'orthogonal';
|
|
106
|
+
const router = getRouter(style) ?? defaultRouter;
|
|
107
|
+
const route = router.route({
|
|
108
|
+
from: fromAnchor.point,
|
|
109
|
+
to: toAnchor.point,
|
|
110
|
+
style,
|
|
111
|
+
curveStyle: 'linear',
|
|
112
|
+
obstacles: [],
|
|
113
|
+
padding: 8,
|
|
114
|
+
fromDir: fromAnchor.portDir,
|
|
115
|
+
toDir: toAnchor.portDir,
|
|
116
|
+
});
|
|
117
|
+
elements.push(p.path(route.path, edge.kind === 'async' ? palette.textMuted : palette.primary, edgeTheme.strokeWidth, {
|
|
118
|
+
...(dash !== undefined ? { dash } : {}),
|
|
119
|
+
markerEnd: ARROW_MARKER_ID,
|
|
120
|
+
}));
|
|
121
|
+
if (edge.label) {
|
|
122
|
+
const lp = route.labelPosition;
|
|
123
|
+
elements.push(p.text(edge.label, lp.x, lp.y - 4, edgeTheme.labelFontSize, palette.textMuted, { anchor: 'middle' }));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Nodes
|
|
127
|
+
for (const node of ir.nodes) {
|
|
128
|
+
const r = nodePos.get(node.id);
|
|
129
|
+
if (!r)
|
|
130
|
+
continue;
|
|
131
|
+
const nodeElements = [];
|
|
132
|
+
const fill = nodeStatusFill(node, palette);
|
|
133
|
+
const stroke = palette.border;
|
|
134
|
+
nodeElements.push(...renderNodeShape(node, r, fill, stroke, edgeTheme.strokeWidth));
|
|
135
|
+
nodeElements.push(p.text(node.label, r.x + NODE_W / 2, r.y + NODE_H / 2 + typography.baseFontSize * 0.35, typography.baseFontSize, palette.text, { anchor: 'middle' }));
|
|
136
|
+
elements.push(p.group(nodeElements, { id: node.id }));
|
|
137
|
+
}
|
|
138
|
+
// ── Compute viewBox ────────────────────────────────────────────────────────
|
|
139
|
+
const allRects = [...nodePos.values()];
|
|
140
|
+
const nodeRight = Math.max(...allRects.map(r => r.x + r.width));
|
|
141
|
+
const nodeBottom = Math.max(...allRects.map(r => r.y + r.height));
|
|
142
|
+
// Grow only for back-edge / self-loop bows; with none, this is byte-identical.
|
|
143
|
+
const right = (Number.isFinite(bowMaxX) ? Math.max(nodeRight, bowMaxX) : nodeRight) + margin;
|
|
144
|
+
const bottom = (Number.isFinite(bowMaxY) ? Math.max(nodeBottom, bowMaxY) : nodeBottom) + margin;
|
|
145
|
+
const titleOffset = ir.metadata.title ? typography.titleFontSize + 12 : 0;
|
|
146
|
+
let scene = {
|
|
147
|
+
viewBox: { x: 0, y: 0, width: right, height: bottom + titleOffset },
|
|
148
|
+
background: palette.background,
|
|
149
|
+
elements,
|
|
150
|
+
defs: [arrowMarkerDef(palette.primary, edgeTheme.arrowSize)],
|
|
151
|
+
};
|
|
152
|
+
// ── Overlays ───────────────────────────────────────────────────────────────
|
|
153
|
+
scene = applyOverlays(scene, ir.overlays, theme);
|
|
154
|
+
// ── Build anchor registry ──────────────────────────────────────────────────
|
|
155
|
+
const anchors = {};
|
|
156
|
+
for (const [id, rect] of nodePos) {
|
|
157
|
+
anchors[id] = {
|
|
158
|
+
bounds: rect,
|
|
159
|
+
ports: {
|
|
160
|
+
N: { x: rect.x + rect.width / 2, y: rect.y },
|
|
161
|
+
S: { x: rect.x + rect.width / 2, y: rect.y + rect.height },
|
|
162
|
+
E: { x: rect.x + rect.width, y: rect.y + rect.height / 2 },
|
|
163
|
+
W: { x: rect.x, y: rect.y + rect.height / 2 },
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// ── Occupied ports: record which wall each edge exits/enters ──────────────
|
|
168
|
+
const occupiedPorts = [];
|
|
169
|
+
for (const edge of ir.edges) {
|
|
170
|
+
const fromRect = nodePos.get(edge.from);
|
|
171
|
+
const toRect = nodePos.get(edge.to);
|
|
172
|
+
if (!fromRect || !toRect)
|
|
173
|
+
continue;
|
|
174
|
+
const fromAnch = edgeAnchor(fromRect, ir.direction, 'exit', toRect);
|
|
175
|
+
const toAnch = edgeAnchor(toRect, ir.direction, 'enter', fromRect);
|
|
176
|
+
occupiedPorts.push({
|
|
177
|
+
nodeKey: edge.from,
|
|
178
|
+
wall: fromAnch.portDir,
|
|
179
|
+
t: wallT(fromRect, fromAnch.portDir, fromAnch.point),
|
|
180
|
+
source: 'intra',
|
|
181
|
+
});
|
|
182
|
+
occupiedPorts.push({
|
|
183
|
+
nodeKey: edge.to,
|
|
184
|
+
wall: toAnch.portDir,
|
|
185
|
+
t: wallT(toRect, toAnch.portDir, toAnch.point),
|
|
186
|
+
source: 'intra',
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return { scene, anchors, occupiedPorts };
|
|
190
|
+
}
|
|
191
|
+
// ─── Layer Assignment ─────────────────────────────────────────────────────────
|
|
192
|
+
/**
|
|
193
|
+
* Identify back-edges (the edges that close a cycle) via an iterative DFS.
|
|
194
|
+
*
|
|
195
|
+
* Removing a DFS's back-edge set always yields a DAG, so the longest-path
|
|
196
|
+
* layering below is guaranteed to terminate on ANY graph. The back-edges are
|
|
197
|
+
* still drawn in their original direction by the edge loop in
|
|
198
|
+
* {@link layoutFlowchart}; they are only excluded from rank assignment.
|
|
199
|
+
*
|
|
200
|
+
* Returns a set of indices into `edges`. Deterministic: nodes and edges are
|
|
201
|
+
* visited in their given order. Iterative (explicit stack) to stay safe on
|
|
202
|
+
* deep graphs.
|
|
203
|
+
*/
|
|
204
|
+
function findBackEdges(nodes, edges) {
|
|
205
|
+
const adj = new Map();
|
|
206
|
+
for (const n of nodes)
|
|
207
|
+
adj.set(n.id, []);
|
|
208
|
+
edges.forEach((e, idx) => { adj.get(e.from)?.push({ to: e.to, idx }); });
|
|
209
|
+
const WHITE = 0, GRAY = 1, BLACK = 2;
|
|
210
|
+
const color = new Map();
|
|
211
|
+
for (const n of nodes)
|
|
212
|
+
color.set(n.id, WHITE);
|
|
213
|
+
const backEdges = new Set();
|
|
214
|
+
for (const start of nodes) {
|
|
215
|
+
if (color.get(start.id) !== WHITE)
|
|
216
|
+
continue;
|
|
217
|
+
const stack = [{ id: start.id, i: 0 }];
|
|
218
|
+
color.set(start.id, GRAY);
|
|
219
|
+
while (stack.length > 0) {
|
|
220
|
+
const frame = stack[stack.length - 1];
|
|
221
|
+
const neighbors = adj.get(frame.id);
|
|
222
|
+
if (frame.i < neighbors.length) {
|
|
223
|
+
const { to, idx } = neighbors[frame.i];
|
|
224
|
+
frame.i++;
|
|
225
|
+
const c = color.get(to);
|
|
226
|
+
// GRAY target (incl. a self-loop, where target === current) closes a cycle.
|
|
227
|
+
if (c === GRAY) {
|
|
228
|
+
backEdges.add(idx);
|
|
229
|
+
}
|
|
230
|
+
else if (c === WHITE) {
|
|
231
|
+
color.set(to, GRAY);
|
|
232
|
+
stack.push({ id: to, i: 0 });
|
|
233
|
+
}
|
|
234
|
+
// BLACK target → forward/cross edge: keep it.
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
color.set(frame.id, BLACK);
|
|
238
|
+
stack.pop();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return backEdges;
|
|
243
|
+
}
|
|
244
|
+
function assignLayers(nodes, edges) {
|
|
245
|
+
// Cycle breaking: drop back-edges so layering runs on a DAG and terminates.
|
|
246
|
+
// (Back-edges are still rendered by the edge loop — only excluded from ranks.)
|
|
247
|
+
const backEdges = findBackEdges(nodes, edges);
|
|
248
|
+
const forwardEdges = edges.filter((_, i) => !backEdges.has(i));
|
|
249
|
+
const predecessors = new Map();
|
|
250
|
+
for (const n of nodes)
|
|
251
|
+
predecessors.set(n.id, new Set());
|
|
252
|
+
for (const e of forwardEdges)
|
|
253
|
+
predecessors.get(e.to)?.add(e.from);
|
|
254
|
+
const layers = new Map();
|
|
255
|
+
const queue = [];
|
|
256
|
+
// Roots: nodes with no predecessors (in the acyclic edge subset)
|
|
257
|
+
for (const n of nodes) {
|
|
258
|
+
if ((predecessors.get(n.id)?.size ?? 0) === 0) {
|
|
259
|
+
queue.push({ id: n.id, layer: 0 });
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
while (queue.length > 0) {
|
|
263
|
+
const item = queue.shift();
|
|
264
|
+
const current = layers.get(item.id) ?? -1;
|
|
265
|
+
if (item.layer <= current)
|
|
266
|
+
continue;
|
|
267
|
+
layers.set(item.id, item.layer);
|
|
268
|
+
for (const e of forwardEdges) {
|
|
269
|
+
if (e.from === item.id)
|
|
270
|
+
queue.push({ id: e.to, layer: item.layer + 1 });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Assign disconnected nodes to layer 0
|
|
274
|
+
for (const n of nodes) {
|
|
275
|
+
if (!layers.has(n.id))
|
|
276
|
+
layers.set(n.id, 0);
|
|
277
|
+
}
|
|
278
|
+
return layers;
|
|
279
|
+
}
|
|
280
|
+
function groupByLayer(nodes, layers) {
|
|
281
|
+
const groups = new Map();
|
|
282
|
+
for (const node of nodes) {
|
|
283
|
+
const l = layers.get(node.id) ?? 0;
|
|
284
|
+
if (!groups.has(l))
|
|
285
|
+
groups.set(l, []);
|
|
286
|
+
groups.get(l).push(node);
|
|
287
|
+
}
|
|
288
|
+
return new Map([...groups.entries()].sort(([a], [b]) => a - b));
|
|
289
|
+
}
|
|
290
|
+
// ─── Phase 3: Barycentric Crossing Minimisation ──────────────────────────────
|
|
291
|
+
/**
|
|
292
|
+
* Reorder nodes within each layer to reduce edge crossings using the
|
|
293
|
+
* barycentric heuristic with bi-directional sweeps (Sugiyama Phase 3).
|
|
294
|
+
*
|
|
295
|
+
* - Back-edges and self-loops are excluded from barycenter computation.
|
|
296
|
+
* - Nodes without neighbors in the reference layer keep their current relative
|
|
297
|
+
* order (their current position index is used as the barycenter).
|
|
298
|
+
* - Tie-breaking uses the original insertion index (deterministic / stable).
|
|
299
|
+
* - At most MAX_PASSES (4) bi-directional passes — provably terminates.
|
|
300
|
+
*/
|
|
301
|
+
function minimizeCrossings(byLayer, edges, backEdgeSet) {
|
|
302
|
+
// Build forward-edge predecessor and successor maps.
|
|
303
|
+
const pred = new Map();
|
|
304
|
+
const succ = new Map();
|
|
305
|
+
for (const [, nodes] of byLayer) {
|
|
306
|
+
for (const n of nodes) {
|
|
307
|
+
pred.set(n.id, []);
|
|
308
|
+
succ.set(n.id, []);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
edges.forEach((e, i) => {
|
|
312
|
+
if (backEdgeSet.has(i) || e.from === e.to)
|
|
313
|
+
return;
|
|
314
|
+
pred.get(e.to)?.push(e.from);
|
|
315
|
+
succ.get(e.from)?.push(e.to);
|
|
316
|
+
});
|
|
317
|
+
const layerKeys = [...byLayer.keys()].sort((a, b) => a - b);
|
|
318
|
+
// Original insertion index — stable tie-break preserved across all passes.
|
|
319
|
+
const origOrder = new Map();
|
|
320
|
+
for (const [, nodes] of byLayer)
|
|
321
|
+
nodes.forEach((n, i) => origOrder.set(n.id, i));
|
|
322
|
+
// Working layer arrays starting from insertion order.
|
|
323
|
+
const order = new Map();
|
|
324
|
+
for (const k of layerKeys)
|
|
325
|
+
order.set(k, [...byLayer.get(k)]);
|
|
326
|
+
// Position of each node in its current layer (rebuilt after every reorder).
|
|
327
|
+
const posInLayer = new Map();
|
|
328
|
+
function rebuildPos() {
|
|
329
|
+
for (const [, nodes] of order)
|
|
330
|
+
nodes.forEach((n, i) => posInLayer.set(n.id, i));
|
|
331
|
+
}
|
|
332
|
+
rebuildPos();
|
|
333
|
+
function reorderLayer(layerIdx, neighborMap) {
|
|
334
|
+
const curr = order.get(layerIdx);
|
|
335
|
+
const bary = curr.map((node, i) => {
|
|
336
|
+
const nbrs = neighborMap.get(node.id) ?? [];
|
|
337
|
+
if (nbrs.length === 0) {
|
|
338
|
+
// No anchoring neighbors: use current position so relative order is kept.
|
|
339
|
+
return { node, b: i, orig: origOrder.get(node.id) ?? i };
|
|
340
|
+
}
|
|
341
|
+
const sum = nbrs.reduce((s, nid) => s + (posInLayer.get(nid) ?? 0), 0);
|
|
342
|
+
return { node, b: sum / nbrs.length, orig: origOrder.get(node.id) ?? i };
|
|
343
|
+
});
|
|
344
|
+
// Stable sort: primary = barycenter, secondary = original insertion order.
|
|
345
|
+
bary.sort((a, b) => (a.b !== b.b ? a.b - b.b : a.orig - b.orig));
|
|
346
|
+
order.set(layerIdx, bary.map(e => e.node));
|
|
347
|
+
rebuildPos();
|
|
348
|
+
}
|
|
349
|
+
const MAX_PASSES = 4;
|
|
350
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
351
|
+
if (pass % 2 === 0) {
|
|
352
|
+
// Downward sweep: reorder each layer using predecessor positions.
|
|
353
|
+
for (let li = 1; li < layerKeys.length; li++)
|
|
354
|
+
reorderLayer(layerKeys[li], pred);
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
// Upward sweep: reorder each layer using successor positions.
|
|
358
|
+
for (let li = layerKeys.length - 2; li >= 0; li--)
|
|
359
|
+
reorderLayer(layerKeys[li], succ);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return order;
|
|
363
|
+
}
|
|
364
|
+
// ─── Phase 4: Simplified Brandes–Köpf Coordinate Assignment ──────────────────
|
|
365
|
+
/**
|
|
366
|
+
* Assign cross-axis coordinates (x for TB, y for LR) using a two-pass
|
|
367
|
+
* simplified Brandes–Köpf style approach (Sugiyama Phase 4).
|
|
368
|
+
*
|
|
369
|
+
* Each pass places every layer as a uniform block:
|
|
370
|
+
* - Each node's "preference" is the MEAN cross-axis position of its
|
|
371
|
+
* forward-edge neighbors in the adjacent layer (mean gives a centred
|
|
372
|
+
* result, matching what dagre does with weighted edges).
|
|
373
|
+
* - Nodes with no neighbors fall back to the same centering formula the
|
|
374
|
+
* old code used (keeps root/leaf layers stable when no anchor exists).
|
|
375
|
+
* - The block's start is max(margin, medianOfPrefs − ½·totalSpan) so the
|
|
376
|
+
* whole layer is centred on its collective preference, clamped to margin.
|
|
377
|
+
*
|
|
378
|
+
* Pass 1 (top-down) aligns each layer with its predecessors.
|
|
379
|
+
* Pass 2 (bottom-up) aligns each layer with its successors.
|
|
380
|
+
* Final positions = average of the two passes.
|
|
381
|
+
*
|
|
382
|
+
* Both passes independently produce non-overlapping layouts (uniform step
|
|
383
|
+
* ≥ crossSize + gap), and the average of two such arrangements with the same
|
|
384
|
+
* step is also non-overlapping — so no extra collision check is needed.
|
|
385
|
+
*
|
|
386
|
+
* Back-edges and self-loops are excluded from preference computation.
|
|
387
|
+
*/
|
|
388
|
+
function assignCoordinatesBK(byLayer, edges, backEdgeSet, isLR, isReverse, maxNodesInLayer, nodeW, nodeH, colGap, rowGap, margin) {
|
|
389
|
+
// Forward-edge predecessor and successor maps.
|
|
390
|
+
const predMap = new Map();
|
|
391
|
+
const succMap = new Map();
|
|
392
|
+
for (const [, nodes] of byLayer) {
|
|
393
|
+
for (const n of nodes) {
|
|
394
|
+
predMap.set(n.id, []);
|
|
395
|
+
succMap.set(n.id, []);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
edges.forEach((e, i) => {
|
|
399
|
+
if (backEdgeSet.has(i) || e.from === e.to)
|
|
400
|
+
return;
|
|
401
|
+
predMap.get(e.to)?.push(e.from);
|
|
402
|
+
succMap.get(e.from)?.push(e.to);
|
|
403
|
+
});
|
|
404
|
+
const layerKeys = [...byLayer.keys()].sort((a, b) => a - b);
|
|
405
|
+
const numLayers = layerKeys.length;
|
|
406
|
+
// Cross-axis = x for TB layout, y for LR layout.
|
|
407
|
+
const crossSize = isLR ? nodeH : nodeW;
|
|
408
|
+
const mainSize = isLR ? nodeW : nodeH;
|
|
409
|
+
const crossGap = isLR ? rowGap : colGap;
|
|
410
|
+
const mainGap = isLR ? colGap : rowGap;
|
|
411
|
+
const crossStep = crossSize + crossGap;
|
|
412
|
+
const mainStep = mainSize + mainGap;
|
|
413
|
+
/**
|
|
414
|
+
* Run one coordinate pass (top-down or bottom-up).
|
|
415
|
+
* Returns a map of node id → cross-axis left-edge position.
|
|
416
|
+
*/
|
|
417
|
+
function onePass(topDown) {
|
|
418
|
+
const crossPos = new Map();
|
|
419
|
+
const neighborMap = topDown ? predMap : succMap;
|
|
420
|
+
const indices = topDown
|
|
421
|
+
? Array.from({ length: numLayers }, (_, i) => i)
|
|
422
|
+
: Array.from({ length: numLayers }, (_, i) => numLayers - 1 - i);
|
|
423
|
+
for (const li of indices) {
|
|
424
|
+
const layerIdx = layerKeys[li];
|
|
425
|
+
const nodes = byLayer.get(layerIdx);
|
|
426
|
+
const count = nodes.length;
|
|
427
|
+
if (count === 0)
|
|
428
|
+
continue;
|
|
429
|
+
// Default (centering) start — same formula as the old algorithm so that
|
|
430
|
+
// layers with no anchoring neighbors fall back to a centred arrangement.
|
|
431
|
+
const centeredStart = margin + ((maxNodesInLayer - count) * crossStep) / 2;
|
|
432
|
+
// Compute preference for each node: mean of neighbor cross-axis positions.
|
|
433
|
+
const pref = nodes.map((node, i) => {
|
|
434
|
+
const nbrs = neighborMap.get(node.id) ?? [];
|
|
435
|
+
const nbrPos = nbrs
|
|
436
|
+
.map(nid => crossPos.get(nid))
|
|
437
|
+
.filter((p) => p !== undefined);
|
|
438
|
+
if (nbrPos.length === 0)
|
|
439
|
+
return centeredStart + i * crossStep;
|
|
440
|
+
return nbrPos.reduce((s, p) => s + p, 0) / nbrPos.length;
|
|
441
|
+
});
|
|
442
|
+
// Block centre = median of individual preferences.
|
|
443
|
+
const sortedPrefs = [...pref].sort((a, b) => a - b);
|
|
444
|
+
const medianPref = sortedPrefs[Math.floor((sortedPrefs.length - 1) / 2)];
|
|
445
|
+
// Centre block on medianPref; clamp so nothing goes left/above margin.
|
|
446
|
+
const blockStart = Math.max(margin, medianPref - ((count - 1) * crossStep) / 2);
|
|
447
|
+
for (let i = 0; i < count; i++) {
|
|
448
|
+
crossPos.set(nodes[i].id, blockStart + i * crossStep);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return crossPos;
|
|
452
|
+
}
|
|
453
|
+
const pass1 = onePass(true); // predecessor-aligned (top-down)
|
|
454
|
+
const pass2 = onePass(false); // successor-aligned (bottom-up)
|
|
455
|
+
// Average the two passes and emit Rect entries.
|
|
456
|
+
const nodePos = new Map();
|
|
457
|
+
for (let li = 0; li < numLayers; li++) {
|
|
458
|
+
const layerIdx = layerKeys[li];
|
|
459
|
+
const layerNum = isReverse ? numLayers - 1 - li : li;
|
|
460
|
+
const nodes = byLayer.get(layerIdx);
|
|
461
|
+
const mainPos = margin + layerNum * mainStep;
|
|
462
|
+
for (const node of nodes) {
|
|
463
|
+
const c1 = pass1.get(node.id) ?? margin;
|
|
464
|
+
const c2 = pass2.get(node.id) ?? margin;
|
|
465
|
+
const crossP = (c1 + c2) / 2;
|
|
466
|
+
nodePos.set(node.id, {
|
|
467
|
+
x: isLR ? mainPos : crossP,
|
|
468
|
+
y: isLR ? crossP : mainPos,
|
|
469
|
+
width: nodeW,
|
|
470
|
+
height: nodeH,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return nodePos;
|
|
475
|
+
}
|
|
476
|
+
// ─── Node Shape Rendering ─────────────────────────────────────────────────────
|
|
477
|
+
function renderNodeShape(node, r, fill, stroke, sw) {
|
|
478
|
+
const { x, y, width: w, height: h } = r;
|
|
479
|
+
switch (node.shape) {
|
|
480
|
+
case 'diamond': {
|
|
481
|
+
const cx = x + w / 2, cy = y + h / 2;
|
|
482
|
+
return [{ type: 'path', d: `M ${cx} ${y} L ${x + w} ${cy} L ${cx} ${y + h} L ${x} ${cy} Z`, fill, stroke, strokeWidth: sw }];
|
|
483
|
+
}
|
|
484
|
+
case 'circle':
|
|
485
|
+
return [{ type: 'circle', center: { x: x + w / 2, y: y + h / 2 }, radius: Math.min(w, h) / 2, fill, stroke, strokeWidth: sw }];
|
|
486
|
+
case 'rounded-rect':
|
|
487
|
+
case 'stadium':
|
|
488
|
+
return [{ type: 'rect', bounds: r, fill, stroke, strokeWidth: sw, rx: h / 2 }];
|
|
489
|
+
case 'subroutine':
|
|
490
|
+
return [
|
|
491
|
+
{ type: 'rect', bounds: r, fill, stroke, strokeWidth: sw },
|
|
492
|
+
{ type: 'rect', bounds: { x: x + 6, y, width: w - 12, height: h }, fill: 'none', stroke, strokeWidth: sw * 0.5 },
|
|
493
|
+
];
|
|
494
|
+
default:
|
|
495
|
+
return [{ type: 'rect', bounds: r, fill, stroke, strokeWidth: sw, rx: 2 }];
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Anchor on an explicitly requested wall (from a wall hint). Overrides the
|
|
500
|
+
* auto-derivation in `edgeAnchor` — the port sits at the midpoint of the named
|
|
501
|
+
* side with the matching port direction.
|
|
502
|
+
*/
|
|
503
|
+
function wallAnchor(r, wall) {
|
|
504
|
+
const cx = r.x + r.width / 2;
|
|
505
|
+
const cy = r.y + r.height / 2;
|
|
506
|
+
switch (wall) {
|
|
507
|
+
case 'N': return { point: { x: cx, y: r.y }, portDir: 'N' };
|
|
508
|
+
case 'S': return { point: { x: cx, y: r.y + r.height }, portDir: 'S' };
|
|
509
|
+
case 'E': return { point: { x: r.x + r.width, y: cy }, portDir: 'E' };
|
|
510
|
+
case 'W': return { point: { x: r.x, y: cy }, portDir: 'W' };
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function edgeAnchor(r, dir, role, peer) {
|
|
514
|
+
const cx = r.x + r.width / 2;
|
|
515
|
+
const cy = r.y + r.height / 2;
|
|
516
|
+
const pcx = peer.x + peer.width / 2;
|
|
517
|
+
const pcy = peer.y + peer.height / 2;
|
|
518
|
+
const dx = pcx - cx;
|
|
519
|
+
const dy = pcy - cy;
|
|
520
|
+
const isLR = dir === 'LR' || dir === 'RL';
|
|
521
|
+
if (isLR) {
|
|
522
|
+
// Primary axis is horizontal
|
|
523
|
+
const offAxis = Math.abs(dy);
|
|
524
|
+
const onAxis = Math.abs(dx);
|
|
525
|
+
// If the peer is more off-axis than on-axis, use top/bottom port
|
|
526
|
+
if (offAxis > onAxis && offAxis > r.height / 2) {
|
|
527
|
+
return dy > 0
|
|
528
|
+
? { point: { x: cx, y: r.y + r.height }, portDir: 'S' }
|
|
529
|
+
: { point: { x: cx, y: r.y }, portDir: 'N' };
|
|
530
|
+
}
|
|
531
|
+
// Otherwise use the flow-direction side
|
|
532
|
+
return role === 'exit'
|
|
533
|
+
? { point: { x: r.x + r.width, y: cy }, portDir: 'E' }
|
|
534
|
+
: { point: { x: r.x, y: cy }, portDir: 'W' };
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
// Primary axis is vertical
|
|
538
|
+
const offAxis = Math.abs(dx);
|
|
539
|
+
const onAxis = Math.abs(dy);
|
|
540
|
+
if (offAxis > onAxis && offAxis > r.width / 2) {
|
|
541
|
+
return dx > 0
|
|
542
|
+
? { point: { x: r.x + r.width, y: cy }, portDir: 'E' }
|
|
543
|
+
: { point: { x: r.x, y: cy }, portDir: 'W' };
|
|
544
|
+
}
|
|
545
|
+
return role === 'exit'
|
|
546
|
+
? { point: { x: cx, y: r.y + r.height }, portDir: 'S' }
|
|
547
|
+
: { point: { x: cx, y: r.y }, portDir: 'N' };
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Back-edge ("feedback") route. A back-edge runs against the layer flow (a lower
|
|
552
|
+
* layer back up to an ancestor); drawn like a forward edge it slices straight
|
|
553
|
+
* through the intervening node column. Instead we bow it out to one lateral side
|
|
554
|
+
* with a cubic Bézier: endpoints sit on the side wall (East for vertical flow,
|
|
555
|
+
* South for horizontal flow) and the control points push further out, so the arc
|
|
556
|
+
* stays clear of the centered node column. The arrowhead still lands on the
|
|
557
|
+
* target wall (the tangent at the end points back into the node).
|
|
558
|
+
*
|
|
559
|
+
* This is intentionally a simple offset arc, not an obstacle-avoiding router:
|
|
560
|
+
* the bar is "reads as feedback and doesn't cut through a node".
|
|
561
|
+
*/
|
|
562
|
+
function backEdgeRoute(from, to, isLR) {
|
|
563
|
+
if (isLR) {
|
|
564
|
+
// Horizontal flow → bow downward, off the South walls.
|
|
565
|
+
const start = { x: from.x + from.width / 2, y: from.y + from.height };
|
|
566
|
+
const end = { x: to.x + to.width / 2, y: to.y + to.height };
|
|
567
|
+
const span = Math.abs(end.x - start.x);
|
|
568
|
+
const bow = Math.max(NODE_H * 0.9, span * 0.35);
|
|
569
|
+
const c1 = { x: start.x, y: start.y + bow };
|
|
570
|
+
const c2 = { x: end.x, y: end.y + bow };
|
|
571
|
+
return {
|
|
572
|
+
path: `M ${start.x} ${start.y} C ${c1.x} ${c1.y}, ${c2.x} ${c2.y}, ${end.x} ${end.y}`,
|
|
573
|
+
labelPos: { x: (start.x + end.x) / 2, y: Math.max(start.y, end.y) + bow * 0.75 },
|
|
574
|
+
maxX: Math.max(start.x, end.x),
|
|
575
|
+
maxY: Math.max(c1.y, c2.y),
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
// Vertical flow → bow to the right, off the East walls.
|
|
579
|
+
const start = { x: from.x + from.width, y: from.y + from.height / 2 };
|
|
580
|
+
const end = { x: to.x + to.width, y: to.y + to.height / 2 };
|
|
581
|
+
const span = Math.abs(end.y - start.y);
|
|
582
|
+
const bow = Math.max(NODE_W * 0.75, span * 0.35);
|
|
583
|
+
const c1 = { x: start.x + bow, y: start.y };
|
|
584
|
+
const c2 = { x: end.x + bow, y: end.y };
|
|
585
|
+
return {
|
|
586
|
+
path: `M ${start.x} ${start.y} C ${c1.x} ${c1.y}, ${c2.x} ${c2.y}, ${end.x} ${end.y}`,
|
|
587
|
+
labelPos: { x: Math.max(start.x, end.x) + bow * 0.75, y: (start.y + end.y) / 2 },
|
|
588
|
+
maxX: Math.max(c1.x, c2.x),
|
|
589
|
+
maxY: Math.max(start.y, end.y),
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Self-loop (A → A) route. A small cubic loop hung off one side of the node
|
|
594
|
+
* (East for vertical flow, South for horizontal flow) so it never degenerates
|
|
595
|
+
* into a zero-length line drawn through the node. The arrowhead re-enters the
|
|
596
|
+
* same wall a little below/right of where it left.
|
|
597
|
+
*/
|
|
598
|
+
function selfLoopRoute(r, isLR) {
|
|
599
|
+
const loop = 28;
|
|
600
|
+
if (isLR) {
|
|
601
|
+
// Loop hangs below the node (South wall).
|
|
602
|
+
const x1 = r.x + r.width * 0.35;
|
|
603
|
+
const x2 = r.x + r.width * 0.65;
|
|
604
|
+
const sy = r.y + r.height;
|
|
605
|
+
return {
|
|
606
|
+
path: `M ${x1} ${sy} C ${x1 - loop} ${sy + loop}, ${x2 + loop} ${sy + loop}, ${x2} ${sy}`,
|
|
607
|
+
labelPos: { x: r.x + r.width / 2, y: sy + loop + 4 },
|
|
608
|
+
maxX: x2 + loop,
|
|
609
|
+
maxY: sy + loop,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
// Loop sits to the right of the node (East wall).
|
|
613
|
+
const y1 = r.y + r.height * 0.3;
|
|
614
|
+
const y2 = r.y + r.height * 0.7;
|
|
615
|
+
const ex = r.x + r.width;
|
|
616
|
+
return {
|
|
617
|
+
path: `M ${ex} ${y1} C ${ex + loop} ${y1 - loop}, ${ex + loop} ${y2 + loop}, ${ex} ${y2}`,
|
|
618
|
+
labelPos: { x: ex + loop, y: r.y + r.height / 2 },
|
|
619
|
+
maxX: ex + loop,
|
|
620
|
+
maxY: y2 + loop,
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
function nodeStatusFill(node, palette) {
|
|
624
|
+
switch (node.status) {
|
|
625
|
+
case 'active': return palette.primary + '22';
|
|
626
|
+
case 'success': return palette.success + '22';
|
|
627
|
+
case 'warning': return palette.warning + '22';
|
|
628
|
+
case 'error': return palette.error + '22';
|
|
629
|
+
case 'muted': return palette.surface;
|
|
630
|
+
default: return palette.surface;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function arrowMarkerDef(color, size) {
|
|
634
|
+
const s = size;
|
|
635
|
+
return `<marker id="${ARROW_MARKER_ID}" markerWidth="${s}" markerHeight="${s * 0.7}" refX="${s - 1}" refY="${s * 0.35}" orient="auto"><polygon points="0 0, ${s} ${s * 0.35}, 0 ${s * 0.7}" fill="${color}" /></marker>`;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Fractional position of a point along a node wall.
|
|
639
|
+
* N/S walls: fraction of width (0=left, 1=right).
|
|
640
|
+
* E/W walls: fraction of height (0=top, 1=bottom).
|
|
641
|
+
*/
|
|
642
|
+
function wallT(bounds, wall, pt) {
|
|
643
|
+
switch (wall) {
|
|
644
|
+
case 'N':
|
|
645
|
+
case 'S':
|
|
646
|
+
return bounds.width > 0 ? Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width)) : 0.5;
|
|
647
|
+
case 'E':
|
|
648
|
+
case 'W':
|
|
649
|
+
return bounds.height > 0 ? Math.max(0, Math.min(1, (pt.y - bounds.y) / bounds.height)) : 0.5;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
//# sourceMappingURL=layout.js.map
|