@statelyai/graph 1.0.0 → 2.1.0
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/README.md +121 -44
- package/dist/{adjacency-list-VsUaH9SJ.mjs → adjacency-list-DQ32Mmhx.mjs} +3 -1
- package/dist/algorithms-D1cgly0g.d.mts +452 -0
- package/dist/algorithms-DBpH74hR.mjs +3309 -0
- package/dist/algorithms.d.mts +2 -2
- package/dist/algorithms.mjs +2 -2
- package/dist/config-Dt5u1gSf.mjs +793 -0
- package/dist/{converter-udLITX36.mjs → converter-DB6Rg6Vd.mjs} +2 -2
- package/dist/format-support.mjs +38 -11
- package/dist/formats/adjacency-list/index.d.mts +1 -1
- package/dist/formats/adjacency-list/index.mjs +1 -1
- package/dist/formats/converter/index.d.mts +1 -1
- package/dist/formats/converter/index.mjs +1 -1
- package/dist/formats/cytoscape/index.d.mts +4 -4
- package/dist/formats/cytoscape/index.mjs +10 -4
- package/dist/formats/d2/index.d.mts +1 -1
- package/dist/formats/d2/index.mjs +26 -12
- package/dist/formats/d3/index.d.mts +4 -4
- package/dist/formats/d3/index.mjs +10 -4
- package/dist/formats/dot/index.d.mts +1 -1
- package/dist/formats/dot/index.mjs +22 -6
- package/dist/formats/edge-list/index.d.mts +1 -1
- package/dist/formats/edge-list/index.mjs +1 -1
- package/dist/formats/elk/index.d.mts +1 -1
- package/dist/formats/elk/index.mjs +63 -24
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gexf/index.mjs +43 -16
- package/dist/formats/gml/index.d.mts +4 -4
- package/dist/formats/gml/index.mjs +28 -15
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +96 -23
- package/dist/formats/jgf/index.d.mts +4 -4
- package/dist/formats/jgf/index.mjs +12 -5
- package/dist/formats/mermaid/index.d.mts +1 -1
- package/dist/formats/mermaid/index.mjs +49 -12
- package/dist/formats/tgf/index.d.mts +4 -4
- package/dist/formats/tgf/index.mjs +4 -4
- package/dist/formats/xyflow/index.d.mts +12 -6
- package/dist/formats/xyflow/index.mjs +42 -10
- package/dist/{index-D9Kj6Fe3.d.mts → index-BlbSWUvH.d.mts} +1 -1
- package/dist/{index-CHoriXZD.d.mts → index-CNvqxPLJ.d.mts} +157 -30
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +290 -307
- package/dist/layout/cytoscape.d.mts +66 -0
- package/dist/layout/cytoscape.mjs +114 -0
- package/dist/layout/d3-force.d.mts +52 -0
- package/dist/layout/d3-force.mjs +127 -0
- package/dist/layout/d3-hierarchy.d.mts +39 -0
- package/dist/layout/d3-hierarchy.mjs +135 -0
- package/dist/layout/dagre.d.mts +32 -0
- package/dist/layout/dagre.mjs +99 -0
- package/dist/layout/elk.d.mts +47 -0
- package/dist/layout/elk.mjs +73 -0
- package/dist/layout/forceatlas2.d.mts +48 -0
- package/dist/layout/forceatlas2.mjs +100 -0
- package/dist/layout/graphviz.d.mts +50 -0
- package/dist/layout/graphviz.mjs +179 -0
- package/dist/layout/index.d.mts +185 -0
- package/dist/layout/index.mjs +181 -0
- package/dist/layout/webcola.d.mts +40 -0
- package/dist/layout/webcola.mjs +104 -0
- package/dist/{queries-BlkA1HAN.d.mts → queries-B6quF529.d.mts} +43 -12
- package/dist/queries-BMM0XAv_.mjs +986 -0
- package/dist/queries.d.mts +1 -1
- package/dist/queries.mjs +1 -768
- package/dist/schemas.d.mts +19 -1
- package/dist/schemas.mjs +32 -84
- package/dist/{types-3-FS9NV2.d.mts → types-BAEQTwK_.d.mts} +99 -7
- package/dist/validate-BsfSOv0S.mjs +190 -0
- package/package.json +59 -7
- package/schemas/edge.schema.json +27 -0
- package/schemas/graph.schema.json +27 -0
- package/dist/algorithms-Ba7o7niK.mjs +0 -2394
- package/dist/algorithms-fTqmvhzP.d.mts +0 -178
- package/dist/indexing-DR8M1vBy.mjs +0 -137
- /package/dist/{edge-list-DP4otyPU.mjs → edge-list-CA9UTvn2.mjs} +0 -0
- /package/dist/{mode-D8OnHFBk.mjs → mode-gu_mhKKs.mjs} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as GraphFormatConverter, f as Graph } from "../../types-BAEQTwK_.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/jgf/index.d.ts
|
|
4
4
|
interface JGFNode {
|
|
@@ -28,7 +28,7 @@ interface JGFGraph {
|
|
|
28
28
|
* @example
|
|
29
29
|
* ```ts
|
|
30
30
|
* import { createGraph } from '@statelyai/graph';
|
|
31
|
-
* import { toJGF } from '@statelyai/graph/
|
|
31
|
+
* import { toJGF } from '@statelyai/graph/jgf';
|
|
32
32
|
*
|
|
33
33
|
* const graph = createGraph({
|
|
34
34
|
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
@@ -45,7 +45,7 @@ declare function toJGF(graph: Graph): JGFGraph;
|
|
|
45
45
|
*
|
|
46
46
|
* @example
|
|
47
47
|
* ```ts
|
|
48
|
-
* import { fromJGF } from '@statelyai/graph/
|
|
48
|
+
* import { fromJGF } from '@statelyai/graph/jgf';
|
|
49
49
|
*
|
|
50
50
|
* const graph = fromJGF({
|
|
51
51
|
* graph: {
|
|
@@ -63,7 +63,7 @@ declare function fromJGF(jgf: JGFGraph): Graph;
|
|
|
63
63
|
* @example
|
|
64
64
|
* ```ts
|
|
65
65
|
* import { createGraph } from '@statelyai/graph';
|
|
66
|
-
* import { jgfConverter } from '@statelyai/graph/
|
|
66
|
+
* import { jgfConverter } from '@statelyai/graph/jgf';
|
|
67
67
|
*
|
|
68
68
|
* const graph = createGraph({
|
|
69
69
|
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createFormatConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter } from "../../converter-DB6Rg6Vd.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/jgf/index.ts
|
|
4
4
|
/**
|
|
@@ -7,7 +7,7 @@ import { n as createFormatConverter } from "../../converter-udLITX36.mjs";
|
|
|
7
7
|
* @example
|
|
8
8
|
* ```ts
|
|
9
9
|
* import { createGraph } from '@statelyai/graph';
|
|
10
|
-
* import { toJGF } from '@statelyai/graph/
|
|
10
|
+
* import { toJGF } from '@statelyai/graph/jgf';
|
|
11
11
|
*
|
|
12
12
|
* const graph = createGraph({
|
|
13
13
|
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
@@ -20,6 +20,7 @@ import { n as createFormatConverter } from "../../converter-udLITX36.mjs";
|
|
|
20
20
|
*/
|
|
21
21
|
function toJGF(graph) {
|
|
22
22
|
const metadata = {};
|
|
23
|
+
if (graph.mode === "bidirectional") metadata.mode = graph.mode;
|
|
23
24
|
if (graph.initialNodeId) metadata.initialNodeId = graph.initialNodeId;
|
|
24
25
|
if (graph.data !== void 0) metadata.data = graph.data;
|
|
25
26
|
if (graph.direction) metadata.direction = graph.direction;
|
|
@@ -49,8 +50,11 @@ function toJGF(graph) {
|
|
|
49
50
|
}),
|
|
50
51
|
edges: graph.edges.map((e) => {
|
|
51
52
|
const meta = {};
|
|
53
|
+
if (e.mode) meta.mode = e.mode;
|
|
52
54
|
if (e.data !== void 0) meta.data = e.data;
|
|
53
55
|
if (e.weight !== void 0) meta.weight = e.weight;
|
|
56
|
+
if (e.points !== void 0) meta.points = e.points;
|
|
57
|
+
if (e.routing !== void 0) meta.routing = e.routing;
|
|
54
58
|
if (e.x !== void 0) meta.x = e.x;
|
|
55
59
|
if (e.y !== void 0) meta.y = e.y;
|
|
56
60
|
if (e.width !== void 0) meta.width = e.width;
|
|
@@ -74,7 +78,7 @@ function toJGF(graph) {
|
|
|
74
78
|
*
|
|
75
79
|
* @example
|
|
76
80
|
* ```ts
|
|
77
|
-
* import { fromJGF } from '@statelyai/graph/
|
|
81
|
+
* import { fromJGF } from '@statelyai/graph/jgf';
|
|
78
82
|
*
|
|
79
83
|
* const graph = fromJGF({
|
|
80
84
|
* graph: {
|
|
@@ -93,7 +97,7 @@ function fromJGF(jgf) {
|
|
|
93
97
|
if (!Array.isArray(g.edges)) throw new Error("JGF: \"graph.edges\" must be an array");
|
|
94
98
|
return {
|
|
95
99
|
id: g.id ?? "",
|
|
96
|
-
mode: g.directed === false ? "undirected" : "directed",
|
|
100
|
+
mode: g.metadata?.mode ?? (g.directed === false ? "undirected" : "directed"),
|
|
97
101
|
initialNodeId: g.metadata?.initialNodeId ?? null,
|
|
98
102
|
data: g.metadata?.data,
|
|
99
103
|
...g.metadata?.direction && { direction: g.metadata.direction },
|
|
@@ -120,8 +124,11 @@ function fromJGF(jgf) {
|
|
|
120
124
|
sourceId: e.source,
|
|
121
125
|
targetId: e.target,
|
|
122
126
|
label: e.label ?? "",
|
|
127
|
+
...e.metadata?.mode && { mode: e.metadata.mode },
|
|
123
128
|
data: e.metadata?.data,
|
|
124
129
|
...e.metadata?.weight !== void 0 && { weight: e.metadata.weight },
|
|
130
|
+
...e.metadata?.points !== void 0 && { points: e.metadata.points },
|
|
131
|
+
...e.metadata?.routing !== void 0 && { routing: e.metadata.routing },
|
|
125
132
|
...e.metadata?.x !== void 0 && { x: e.metadata.x },
|
|
126
133
|
...e.metadata?.y !== void 0 && { y: e.metadata.y },
|
|
127
134
|
...e.metadata?.width !== void 0 && { width: e.metadata.width },
|
|
@@ -139,7 +146,7 @@ function fromJGF(jgf) {
|
|
|
139
146
|
* @example
|
|
140
147
|
* ```ts
|
|
141
148
|
* import { createGraph } from '@statelyai/graph';
|
|
142
|
-
* import { jgfConverter } from '@statelyai/graph/
|
|
149
|
+
* import { jgfConverter } from '@statelyai/graph/jgf';
|
|
143
150
|
*
|
|
144
151
|
* const graph = createGraph({
|
|
145
152
|
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createFormatConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter } from "../../converter-DB6Rg6Vd.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/mermaid/shared.ts
|
|
4
4
|
const MERMAID_TO_DIRECTION = {
|
|
@@ -16,11 +16,11 @@ const DIRECTION_TO_MERMAID = {
|
|
|
16
16
|
};
|
|
17
17
|
/** Escape a label for Mermaid output (quotes special chars). */
|
|
18
18
|
function escapeMermaidLabel(s) {
|
|
19
|
-
return s.replace(/\\/g, "\\\\").replace(/"/g, "#quot;").replace(/;/g, "#59;").replace(/#(?!quot;|59;|35;)/g, "#35;");
|
|
19
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, "#quot;").replace(/;/g, "#59;").replace(/\|/g, "#124;").replace(/#(?!quot;|59;|35;|124;)/g, "#35;");
|
|
20
20
|
}
|
|
21
21
|
/** Unescape a Mermaid label back to plain text. */
|
|
22
22
|
function unescapeMermaidLabel(s) {
|
|
23
|
-
return s.replace(/#quot;/g, "\"").replace(/#59;/g, ";").replace(/#35;/g, "#");
|
|
23
|
+
return s.replace(/#quot;/g, "\"").replace(/#59;/g, ";").replace(/#124;/g, "|").replace(/#35;/g, "#");
|
|
24
24
|
}
|
|
25
25
|
/** Generate a deterministic edge ID from source, target, and index. */
|
|
26
26
|
function generateEdgeId(sourceId, targetId, index) {
|
|
@@ -1389,6 +1389,19 @@ const mermaidFlowchartConverter = createFormatConverter(toMermaidFlowchart, from
|
|
|
1389
1389
|
//#endregion
|
|
1390
1390
|
//#region src/formats/mermaid/state.ts
|
|
1391
1391
|
/**
|
|
1392
|
+
* Whether a node is a parallel-region marker. Region nodes are generated with
|
|
1393
|
+
* the exact id `${parentId}_region_${integer}`, so a node only counts when its
|
|
1394
|
+
* id matches that structure for its *actual* parent and that parent is a
|
|
1395
|
+
* parallel state. User ids that merely contain `_region_` (e.g.
|
|
1396
|
+
* `foo_region_bar`) are ordinary states.
|
|
1397
|
+
*/
|
|
1398
|
+
function isParallelRegionNode(node, nodesById) {
|
|
1399
|
+
if (!node || !node.parentId) return false;
|
|
1400
|
+
if (nodesById.get(node.parentId)?.data?.stateType !== "parallel") return false;
|
|
1401
|
+
const prefix = `${node.parentId}_region_`;
|
|
1402
|
+
return node.id.startsWith(prefix) && /^\d+$/.test(node.id.slice(prefix.length));
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1392
1405
|
* Parses a Mermaid state diagram string into a Graph.
|
|
1393
1406
|
*
|
|
1394
1407
|
* @example
|
|
@@ -1410,6 +1423,7 @@ function fromMermaidState(input) {
|
|
|
1410
1423
|
let startCounter = 0;
|
|
1411
1424
|
let endCounter = 0;
|
|
1412
1425
|
let graphDirection;
|
|
1426
|
+
let initialNodeId = null;
|
|
1413
1427
|
const classDefs = {};
|
|
1414
1428
|
const classAssignments = {};
|
|
1415
1429
|
const parentStack = [null];
|
|
@@ -1474,6 +1488,7 @@ function fromMermaidState(input) {
|
|
|
1474
1488
|
const stateId = compositeStateAsMatch[2];
|
|
1475
1489
|
const node = ensureNode(stateId);
|
|
1476
1490
|
node.data.description = description;
|
|
1491
|
+
node.label = description;
|
|
1477
1492
|
parentStack.push(stateId);
|
|
1478
1493
|
continue;
|
|
1479
1494
|
}
|
|
@@ -1492,12 +1507,13 @@ function fromMermaidState(input) {
|
|
|
1492
1507
|
const stateId = stateAsMatch[2];
|
|
1493
1508
|
const node = ensureNode(stateId);
|
|
1494
1509
|
node.data.description = description;
|
|
1510
|
+
node.label = description;
|
|
1495
1511
|
continue;
|
|
1496
1512
|
}
|
|
1497
1513
|
if (line === "}" || line === "end") {
|
|
1498
1514
|
if (parentStack.length > 1) {
|
|
1499
1515
|
const top = parentStack[parentStack.length - 1];
|
|
1500
|
-
if (top &&
|
|
1516
|
+
if (top && isParallelRegionNode(nodeMap.get(top), nodeMap)) parentStack.pop();
|
|
1501
1517
|
parentStack.pop();
|
|
1502
1518
|
}
|
|
1503
1519
|
continue;
|
|
@@ -1506,7 +1522,7 @@ function fromMermaidState(input) {
|
|
|
1506
1522
|
const compositeParent = (() => {
|
|
1507
1523
|
for (let s = parentStack.length - 1; s >= 0; s--) {
|
|
1508
1524
|
const id = parentStack[s];
|
|
1509
|
-
if (id && !
|
|
1525
|
+
if (id && !isParallelRegionNode(nodeMap.get(id), nodeMap)) return id;
|
|
1510
1526
|
}
|
|
1511
1527
|
return null;
|
|
1512
1528
|
})();
|
|
@@ -1540,7 +1556,7 @@ function fromMermaidState(input) {
|
|
|
1540
1556
|
regionCounters.set(compositeParent, 2);
|
|
1541
1557
|
} else {
|
|
1542
1558
|
const top = parentStack[parentStack.length - 1];
|
|
1543
|
-
if (top &&
|
|
1559
|
+
if (top && isParallelRegionNode(nodeMap.get(top), nodeMap)) parentStack.pop();
|
|
1544
1560
|
const nextRegionId = `${compositeParent}_region_${regionIndex}`;
|
|
1545
1561
|
const nextRegion = {
|
|
1546
1562
|
type: "node",
|
|
@@ -1588,6 +1604,7 @@ function fromMermaidState(input) {
|
|
|
1588
1604
|
let targetId = transMatch[3];
|
|
1589
1605
|
const targetClass = transMatch[4];
|
|
1590
1606
|
const label = transMatch[5]?.trim() ?? "";
|
|
1607
|
+
const isTopLevelStart = sourceId === "[*]" && parentStack[parentStack.length - 1] === null;
|
|
1591
1608
|
if (sourceId === "[*]") sourceId = resolveStarNode("source");
|
|
1592
1609
|
else {
|
|
1593
1610
|
ensureNode(sourceId);
|
|
@@ -1603,6 +1620,7 @@ function fromMermaidState(input) {
|
|
|
1603
1620
|
if (!classAssignments[targetId]) classAssignments[targetId] = [];
|
|
1604
1621
|
classAssignments[targetId].push(targetClass);
|
|
1605
1622
|
}
|
|
1623
|
+
if (isTopLevelStart && initialNodeId === null) initialNodeId = targetId;
|
|
1606
1624
|
}
|
|
1607
1625
|
const edgeId = generateEdgeId(sourceId, targetId, edgeCounter++);
|
|
1608
1626
|
edges.push({
|
|
@@ -1676,7 +1694,7 @@ function fromMermaidState(input) {
|
|
|
1676
1694
|
return {
|
|
1677
1695
|
id: "",
|
|
1678
1696
|
mode: "directed",
|
|
1679
|
-
initialNodeId
|
|
1697
|
+
initialNodeId,
|
|
1680
1698
|
nodes: Array.from(nodeMap.values()),
|
|
1681
1699
|
edges,
|
|
1682
1700
|
data: {
|
|
@@ -1699,6 +1717,7 @@ function toMermaidState(graph) {
|
|
|
1699
1717
|
const mDir = DIRECTION_TO_MERMAID[graph.direction];
|
|
1700
1718
|
if (mDir) lines.push(` direction ${mDir}`);
|
|
1701
1719
|
}
|
|
1720
|
+
const nodesById = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
1702
1721
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
1703
1722
|
for (const node of graph.nodes) {
|
|
1704
1723
|
const pid = node.parentId ?? null;
|
|
@@ -1707,28 +1726,44 @@ function toMermaidState(graph) {
|
|
|
1707
1726
|
}
|
|
1708
1727
|
const isParent = /* @__PURE__ */ new Set();
|
|
1709
1728
|
for (const node of graph.nodes) if (childrenMap.has(node.id)) isParent.add(node.id);
|
|
1729
|
+
const referencedByEdge = /* @__PURE__ */ new Set();
|
|
1730
|
+
for (const edge of graph.edges) {
|
|
1731
|
+
referencedByEdge.add(edge.sourceId);
|
|
1732
|
+
referencedByEdge.add(edge.targetId);
|
|
1733
|
+
}
|
|
1734
|
+
if (graph.initialNodeId) referencedByEdge.add(graph.initialNodeId);
|
|
1710
1735
|
function writeNodes(parentId, indent) {
|
|
1711
1736
|
const children = childrenMap.get(parentId) ?? [];
|
|
1712
1737
|
for (const node of children) {
|
|
1713
1738
|
if (node.data?.isStart || node.data?.isEnd) continue;
|
|
1714
|
-
if (node
|
|
1715
|
-
|
|
1739
|
+
if (isParallelRegionNode(node, nodesById)) continue;
|
|
1740
|
+
const description = node.data?.description ?? (node.label && node.label !== node.id ? node.label : void 0);
|
|
1741
|
+
let declared = false;
|
|
1742
|
+
if (node.data?.stateType && node.data.stateType !== "parallel") {
|
|
1743
|
+
lines.push(`${indent}state ${node.id} <<${node.data.stateType}>>`);
|
|
1744
|
+
declared = true;
|
|
1745
|
+
}
|
|
1716
1746
|
if (isParent.has(node.id)) {
|
|
1717
|
-
const stateDecl =
|
|
1747
|
+
const stateDecl = description ? `state "${escapeMermaidLabel(description)}" as ${node.id} {` : `state ${node.id} {`;
|
|
1718
1748
|
lines.push(`${indent}${stateDecl}`);
|
|
1719
1749
|
if (node.data?.direction) {
|
|
1720
1750
|
const mDir = DIRECTION_TO_MERMAID[node.data.direction];
|
|
1721
1751
|
if (mDir) lines.push(`${indent} direction ${mDir}`);
|
|
1722
1752
|
}
|
|
1723
1753
|
if (node.data?.stateType === "parallel") {
|
|
1724
|
-
const regions = (childrenMap.get(node.id) ?? []).filter((r) => r
|
|
1754
|
+
const regions = (childrenMap.get(node.id) ?? []).filter((r) => isParallelRegionNode(r, nodesById));
|
|
1725
1755
|
for (let ri = 0; ri < regions.length; ri++) {
|
|
1726
1756
|
if (ri > 0) lines.push(`${indent} --`);
|
|
1727
1757
|
writeNodes(regions[ri].id, indent + " ");
|
|
1728
1758
|
}
|
|
1729
1759
|
} else writeNodes(node.id, indent + " ");
|
|
1730
1760
|
lines.push(`${indent}}`);
|
|
1731
|
-
|
|
1761
|
+
declared = true;
|
|
1762
|
+
} else if (description) {
|
|
1763
|
+
lines.push(`${indent}state "${escapeMermaidLabel(description)}" as ${node.id}`);
|
|
1764
|
+
declared = true;
|
|
1765
|
+
}
|
|
1766
|
+
if (!declared && !referencedByEdge.has(node.id)) lines.push(`${indent}${node.id}`);
|
|
1732
1767
|
if (node.data?.notes) for (const note of node.data.notes) if (note.format === "block" || note.text.includes("\n")) {
|
|
1733
1768
|
lines.push(`${indent}note ${note.position} of ${node.id}`);
|
|
1734
1769
|
for (const noteLine of note.text.split("\n")) lines.push(`${indent} ${escapeMermaidLabel(noteLine)}`);
|
|
@@ -1737,6 +1772,8 @@ function toMermaidState(graph) {
|
|
|
1737
1772
|
}
|
|
1738
1773
|
}
|
|
1739
1774
|
writeNodes(null, " ");
|
|
1775
|
+
const hasTopLevelStart = graph.nodes.some((n) => n.data?.isStart && (n.parentId ?? null) === null);
|
|
1776
|
+
if (graph.initialNodeId && !hasTopLevelStart) lines.push(` [*] --> ${graph.initialNodeId}`);
|
|
1740
1777
|
for (const edge of graph.edges) {
|
|
1741
1778
|
let sourceId = edge.sourceId;
|
|
1742
1779
|
let targetId = edge.targetId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as GraphFormatConverter, f as Graph } from "../../types-BAEQTwK_.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/tgf/index.d.ts
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@ import { h as GraphFormatConverter, u as Graph } from "../../types-3-FS9NV2.mjs"
|
|
|
8
8
|
* @example
|
|
9
9
|
* ```ts
|
|
10
10
|
* import { createGraph } from '@statelyai/graph';
|
|
11
|
-
* import { toTGF } from '@statelyai/graph/
|
|
11
|
+
* import { toTGF } from '@statelyai/graph/tgf';
|
|
12
12
|
*
|
|
13
13
|
* const graph = createGraph({
|
|
14
14
|
* nodes: [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }],
|
|
@@ -25,7 +25,7 @@ declare function toTGF(graph: Graph): string;
|
|
|
25
25
|
*
|
|
26
26
|
* @example
|
|
27
27
|
* ```ts
|
|
28
|
-
* import { fromTGF } from '@statelyai/graph/
|
|
28
|
+
* import { fromTGF } from '@statelyai/graph/tgf';
|
|
29
29
|
*
|
|
30
30
|
* const graph = fromTGF('a A\nb B\n#\na b go');
|
|
31
31
|
* // graph.nodes = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
|
|
@@ -38,7 +38,7 @@ declare function fromTGF(tgf: string): Graph;
|
|
|
38
38
|
* @example
|
|
39
39
|
* ```ts
|
|
40
40
|
* import { createGraph } from '@statelyai/graph';
|
|
41
|
-
* import { tgfConverter } from '@statelyai/graph/
|
|
41
|
+
* import { tgfConverter } from '@statelyai/graph/tgf';
|
|
42
42
|
*
|
|
43
43
|
* const graph = createGraph({
|
|
44
44
|
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createFormatConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter } from "../../converter-DB6Rg6Vd.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/tgf/index.ts
|
|
4
4
|
/**
|
|
@@ -7,7 +7,7 @@ import { n as createFormatConverter } from "../../converter-udLITX36.mjs";
|
|
|
7
7
|
* @example
|
|
8
8
|
* ```ts
|
|
9
9
|
* import { createGraph } from '@statelyai/graph';
|
|
10
|
-
* import { toTGF } from '@statelyai/graph/
|
|
10
|
+
* import { toTGF } from '@statelyai/graph/tgf';
|
|
11
11
|
*
|
|
12
12
|
* const graph = createGraph({
|
|
13
13
|
* nodes: [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }],
|
|
@@ -34,7 +34,7 @@ function toTGF(graph) {
|
|
|
34
34
|
*
|
|
35
35
|
* @example
|
|
36
36
|
* ```ts
|
|
37
|
-
* import { fromTGF } from '@statelyai/graph/
|
|
37
|
+
* import { fromTGF } from '@statelyai/graph/tgf';
|
|
38
38
|
*
|
|
39
39
|
* const graph = fromTGF('a A\nb B\n#\na b go');
|
|
40
40
|
* // graph.nodes = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
|
|
@@ -94,7 +94,7 @@ function fromTGF(tgf) {
|
|
|
94
94
|
* @example
|
|
95
95
|
* ```ts
|
|
96
96
|
* import { createGraph } from '@statelyai/graph';
|
|
97
|
-
* import { tgfConverter } from '@statelyai/graph/
|
|
97
|
+
* import { tgfConverter } from '@statelyai/graph/tgf';
|
|
98
98
|
*
|
|
99
99
|
* const graph = createGraph({
|
|
100
100
|
* nodes: [{ id: 'a' }, { id: 'b' }],
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as VisualGraph, z as VisualGraphFormatConverter } from "../../types-BAEQTwK_.mjs";
|
|
2
2
|
import { EdgeBase, NodeBase } from "@xyflow/system";
|
|
3
3
|
|
|
4
4
|
//#region src/formats/xyflow/index.d.ts
|
|
5
5
|
/** xyflow Node — re-exported from `@xyflow/system`. */
|
|
6
6
|
type XYFlowNode<TNodeData extends Record<string, unknown> = Record<string, unknown>> = NodeBase<TNodeData>;
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* xyflow Edge — `EdgeBase` from `@xyflow/system` plus the top-level `label`
|
|
9
|
+
* that React Flow / Svelte Flow actually render (it's a renderer prop, so
|
|
10
|
+
* `EdgeBase` itself doesn't declare it).
|
|
11
|
+
*/
|
|
12
|
+
type XYFlowEdge<TEdgeData extends Record<string, unknown> = Record<string, unknown>> = EdgeBase<TEdgeData> & {
|
|
13
|
+
label?: string;
|
|
14
|
+
};
|
|
9
15
|
interface XYFlow<TNodeData extends Record<string, unknown> = Record<string, unknown>, TEdgeData extends Record<string, unknown> = Record<string, unknown>> {
|
|
10
16
|
nodes: XYFlowNode<TNodeData>[];
|
|
11
17
|
edges: XYFlowEdge<TEdgeData>[];
|
|
@@ -17,7 +23,7 @@ interface XYFlow<TNodeData extends Record<string, unknown> = Record<string, unkn
|
|
|
17
23
|
* @example
|
|
18
24
|
* ```ts
|
|
19
25
|
* import { createVisualGraph } from '@statelyai/graph';
|
|
20
|
-
* import { toXYFlow } from '@statelyai/graph/
|
|
26
|
+
* import { toXYFlow } from '@statelyai/graph/xyflow';
|
|
21
27
|
*
|
|
22
28
|
* const graph = createVisualGraph({
|
|
23
29
|
* nodes: [
|
|
@@ -37,7 +43,7 @@ declare function toXYFlow(graph: VisualGraph): XYFlow;
|
|
|
37
43
|
*
|
|
38
44
|
* @example
|
|
39
45
|
* ```ts
|
|
40
|
-
* import { fromXYFlow } from '@statelyai/graph/
|
|
46
|
+
* import { fromXYFlow } from '@statelyai/graph/xyflow';
|
|
41
47
|
*
|
|
42
48
|
* const graph = fromXYFlow({
|
|
43
49
|
* nodes: [
|
|
@@ -55,7 +61,7 @@ declare function fromXYFlow(flow: XYFlow): VisualGraph;
|
|
|
55
61
|
* @example
|
|
56
62
|
* ```ts
|
|
57
63
|
* import { createVisualGraph } from '@statelyai/graph';
|
|
58
|
-
* import { xyflowConverter } from '@statelyai/graph/
|
|
64
|
+
* import { xyflowConverter } from '@statelyai/graph/xyflow';
|
|
59
65
|
*
|
|
60
66
|
* const graph = createVisualGraph({
|
|
61
67
|
* nodes: [
|
|
@@ -19,8 +19,33 @@ function readMetadata(value) {
|
|
|
19
19
|
}
|
|
20
20
|
function readUserData(value) {
|
|
21
21
|
const metadata = readMetadata(value);
|
|
22
|
-
if (metadata
|
|
23
|
-
return
|
|
22
|
+
if (!metadata) return value;
|
|
23
|
+
return "data" in metadata ? metadata.data : void 0;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* React Flow requires parent nodes to appear before their children in the
|
|
27
|
+
* nodes array. Reorders iteratively, keeping authored order otherwise: each
|
|
28
|
+
* pass emits nodes whose parent is already emitted (or absent). Nodes left
|
|
29
|
+
* over by a parentId cycle are appended in authored order rather than hanging.
|
|
30
|
+
*/
|
|
31
|
+
function orderParentsFirst(nodes) {
|
|
32
|
+
const nodeIds = new Set(nodes.map((n) => n.id));
|
|
33
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
34
|
+
const result = [];
|
|
35
|
+
let remaining = nodes;
|
|
36
|
+
while (remaining.length > 0) {
|
|
37
|
+
const deferred = [];
|
|
38
|
+
for (const node of remaining) if (!node.parentId || emitted.has(node.parentId) || !nodeIds.has(node.parentId)) {
|
|
39
|
+
result.push(node);
|
|
40
|
+
emitted.add(node.id);
|
|
41
|
+
} else deferred.push(node);
|
|
42
|
+
if (deferred.length === remaining.length) {
|
|
43
|
+
result.push(...deferred);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
remaining = deferred;
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
24
49
|
}
|
|
25
50
|
/**
|
|
26
51
|
* Converts a visual graph to xyflow (React Flow / Svelte Flow) format.
|
|
@@ -28,7 +53,7 @@ function readUserData(value) {
|
|
|
28
53
|
* @example
|
|
29
54
|
* ```ts
|
|
30
55
|
* import { createVisualGraph } from '@statelyai/graph';
|
|
31
|
-
* import { toXYFlow } from '@statelyai/graph/
|
|
56
|
+
* import { toXYFlow } from '@statelyai/graph/xyflow';
|
|
32
57
|
*
|
|
33
58
|
* const graph = createVisualGraph({
|
|
34
59
|
* nodes: [
|
|
@@ -52,7 +77,7 @@ function toXYFlow(graph) {
|
|
|
52
77
|
direction: graph.direction,
|
|
53
78
|
style: graph.style
|
|
54
79
|
} } },
|
|
55
|
-
nodes: graph.nodes.map((n) => {
|
|
80
|
+
nodes: orderParentsFirst(graph.nodes.map((n) => {
|
|
56
81
|
const node = {
|
|
57
82
|
id: n.id,
|
|
58
83
|
position: {
|
|
@@ -68,11 +93,12 @@ function toXYFlow(graph) {
|
|
|
68
93
|
} })
|
|
69
94
|
};
|
|
70
95
|
if (n.parentId) node.parentId = n.parentId;
|
|
96
|
+
if (n.label) node.data.label = n.label;
|
|
71
97
|
if (n.shape) node.type = n.shape;
|
|
72
98
|
if (n.width !== void 0) node.width = n.width;
|
|
73
99
|
if (n.height !== void 0) node.height = n.height;
|
|
74
100
|
return node;
|
|
75
|
-
}),
|
|
101
|
+
})),
|
|
76
102
|
edges: graph.edges.map((e) => {
|
|
77
103
|
const edge = {
|
|
78
104
|
id: e.id,
|
|
@@ -83,7 +109,10 @@ function toXYFlow(graph) {
|
|
|
83
109
|
if (e.targetPort) edge.targetHandle = e.targetPort;
|
|
84
110
|
edge.data = withMetadata(e.data, { edge: {
|
|
85
111
|
label: e.label,
|
|
112
|
+
mode: e.mode,
|
|
86
113
|
weight: e.weight,
|
|
114
|
+
points: e.points,
|
|
115
|
+
routing: e.routing,
|
|
87
116
|
color: e.color,
|
|
88
117
|
style: e.style,
|
|
89
118
|
x: e.x,
|
|
@@ -91,7 +120,7 @@ function toXYFlow(graph) {
|
|
|
91
120
|
width: e.width,
|
|
92
121
|
height: e.height
|
|
93
122
|
} });
|
|
94
|
-
if (e.label) edge.
|
|
123
|
+
if (e.label) edge.label = e.label;
|
|
95
124
|
return edge;
|
|
96
125
|
})
|
|
97
126
|
};
|
|
@@ -101,7 +130,7 @@ function toXYFlow(graph) {
|
|
|
101
130
|
*
|
|
102
131
|
* @example
|
|
103
132
|
* ```ts
|
|
104
|
-
* import { fromXYFlow } from '@statelyai/graph/
|
|
133
|
+
* import { fromXYFlow } from '@statelyai/graph/xyflow';
|
|
105
134
|
*
|
|
106
135
|
* const graph = fromXYFlow({
|
|
107
136
|
* nodes: [
|
|
@@ -131,7 +160,7 @@ function fromXYFlow(flow) {
|
|
|
131
160
|
id: n.id,
|
|
132
161
|
parentId: n.parentId ?? null,
|
|
133
162
|
initialNodeId: metadata && "initialNodeId" in metadata ? metadata.initialNodeId : null,
|
|
134
|
-
label: metadata && "label" in metadata ? metadata.label : "",
|
|
163
|
+
label: metadata && "label" in metadata ? metadata.label : n.data?.label?.toString() ?? "",
|
|
135
164
|
data: readUserData(n.data),
|
|
136
165
|
x: n.position.x,
|
|
137
166
|
y: n.position.y,
|
|
@@ -150,7 +179,7 @@ function fromXYFlow(flow) {
|
|
|
150
179
|
id: e.id ?? `e${i}`,
|
|
151
180
|
sourceId: e.source,
|
|
152
181
|
targetId: e.target,
|
|
153
|
-
label: metadata && "label" in metadata ? metadata.label : e.data?.label?.toString() ?? "",
|
|
182
|
+
label: metadata && "label" in metadata ? metadata.label : e.label ?? e.data?.label?.toString() ?? "",
|
|
154
183
|
...e.sourceHandle && { sourcePort: e.sourceHandle },
|
|
155
184
|
...e.targetHandle && { targetPort: e.targetHandle },
|
|
156
185
|
data: readUserData(e.data),
|
|
@@ -158,7 +187,10 @@ function fromXYFlow(flow) {
|
|
|
158
187
|
y: metadata?.y ?? 0,
|
|
159
188
|
width: metadata?.width ?? 0,
|
|
160
189
|
height: metadata?.height ?? 0,
|
|
190
|
+
...metadata?.mode !== void 0 && { mode: metadata.mode },
|
|
161
191
|
...metadata?.weight !== void 0 && { weight: metadata.weight },
|
|
192
|
+
...metadata?.points !== void 0 && { points: metadata.points },
|
|
193
|
+
...metadata?.routing !== void 0 && { routing: metadata.routing },
|
|
162
194
|
...metadata?.color !== void 0 && { color: metadata.color },
|
|
163
195
|
...metadata?.style !== void 0 && { style: metadata.style }
|
|
164
196
|
};
|
|
@@ -171,7 +203,7 @@ function fromXYFlow(flow) {
|
|
|
171
203
|
* @example
|
|
172
204
|
* ```ts
|
|
173
205
|
* import { createVisualGraph } from '@statelyai/graph';
|
|
174
|
-
* import { xyflowConverter } from '@statelyai/graph/
|
|
206
|
+
* import { xyflowConverter } from '@statelyai/graph/xyflow';
|
|
175
207
|
*
|
|
176
208
|
* const graph = createVisualGraph({
|
|
177
209
|
* nodes: [
|