@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.
Files changed (77) hide show
  1. package/README.md +121 -44
  2. package/dist/{adjacency-list-VsUaH9SJ.mjs → adjacency-list-DQ32Mmhx.mjs} +3 -1
  3. package/dist/algorithms-D1cgly0g.d.mts +452 -0
  4. package/dist/algorithms-DBpH74hR.mjs +3309 -0
  5. package/dist/algorithms.d.mts +2 -2
  6. package/dist/algorithms.mjs +2 -2
  7. package/dist/config-Dt5u1gSf.mjs +793 -0
  8. package/dist/{converter-udLITX36.mjs → converter-DB6Rg6Vd.mjs} +2 -2
  9. package/dist/format-support.mjs +38 -11
  10. package/dist/formats/adjacency-list/index.d.mts +1 -1
  11. package/dist/formats/adjacency-list/index.mjs +1 -1
  12. package/dist/formats/converter/index.d.mts +1 -1
  13. package/dist/formats/converter/index.mjs +1 -1
  14. package/dist/formats/cytoscape/index.d.mts +4 -4
  15. package/dist/formats/cytoscape/index.mjs +10 -4
  16. package/dist/formats/d2/index.d.mts +1 -1
  17. package/dist/formats/d2/index.mjs +26 -12
  18. package/dist/formats/d3/index.d.mts +4 -4
  19. package/dist/formats/d3/index.mjs +10 -4
  20. package/dist/formats/dot/index.d.mts +1 -1
  21. package/dist/formats/dot/index.mjs +22 -6
  22. package/dist/formats/edge-list/index.d.mts +1 -1
  23. package/dist/formats/edge-list/index.mjs +1 -1
  24. package/dist/formats/elk/index.d.mts +1 -1
  25. package/dist/formats/elk/index.mjs +63 -24
  26. package/dist/formats/gexf/index.d.mts +1 -1
  27. package/dist/formats/gexf/index.mjs +43 -16
  28. package/dist/formats/gml/index.d.mts +4 -4
  29. package/dist/formats/gml/index.mjs +28 -15
  30. package/dist/formats/graphml/index.d.mts +1 -1
  31. package/dist/formats/graphml/index.mjs +96 -23
  32. package/dist/formats/jgf/index.d.mts +4 -4
  33. package/dist/formats/jgf/index.mjs +12 -5
  34. package/dist/formats/mermaid/index.d.mts +1 -1
  35. package/dist/formats/mermaid/index.mjs +49 -12
  36. package/dist/formats/tgf/index.d.mts +4 -4
  37. package/dist/formats/tgf/index.mjs +4 -4
  38. package/dist/formats/xyflow/index.d.mts +12 -6
  39. package/dist/formats/xyflow/index.mjs +42 -10
  40. package/dist/{index-D9Kj6Fe3.d.mts → index-BlbSWUvH.d.mts} +1 -1
  41. package/dist/{index-CHoriXZD.d.mts → index-CNvqxPLJ.d.mts} +157 -30
  42. package/dist/index.d.mts +6 -6
  43. package/dist/index.mjs +290 -307
  44. package/dist/layout/cytoscape.d.mts +66 -0
  45. package/dist/layout/cytoscape.mjs +114 -0
  46. package/dist/layout/d3-force.d.mts +52 -0
  47. package/dist/layout/d3-force.mjs +127 -0
  48. package/dist/layout/d3-hierarchy.d.mts +39 -0
  49. package/dist/layout/d3-hierarchy.mjs +135 -0
  50. package/dist/layout/dagre.d.mts +32 -0
  51. package/dist/layout/dagre.mjs +99 -0
  52. package/dist/layout/elk.d.mts +47 -0
  53. package/dist/layout/elk.mjs +73 -0
  54. package/dist/layout/forceatlas2.d.mts +48 -0
  55. package/dist/layout/forceatlas2.mjs +100 -0
  56. package/dist/layout/graphviz.d.mts +50 -0
  57. package/dist/layout/graphviz.mjs +179 -0
  58. package/dist/layout/index.d.mts +185 -0
  59. package/dist/layout/index.mjs +181 -0
  60. package/dist/layout/webcola.d.mts +40 -0
  61. package/dist/layout/webcola.mjs +104 -0
  62. package/dist/{queries-BlkA1HAN.d.mts → queries-B6quF529.d.mts} +43 -12
  63. package/dist/queries-BMM0XAv_.mjs +986 -0
  64. package/dist/queries.d.mts +1 -1
  65. package/dist/queries.mjs +1 -768
  66. package/dist/schemas.d.mts +19 -1
  67. package/dist/schemas.mjs +32 -84
  68. package/dist/{types-3-FS9NV2.d.mts → types-BAEQTwK_.d.mts} +99 -7
  69. package/dist/validate-BsfSOv0S.mjs +190 -0
  70. package/package.json +59 -7
  71. package/schemas/edge.schema.json +27 -0
  72. package/schemas/graph.schema.json +27 -0
  73. package/dist/algorithms-Ba7o7niK.mjs +0 -2394
  74. package/dist/algorithms-fTqmvhzP.d.mts +0 -178
  75. package/dist/indexing-DR8M1vBy.mjs +0 -137
  76. /package/dist/{edge-list-DP4otyPU.mjs → edge-list-CA9UTvn2.mjs} +0 -0
  77. /package/dist/{mode-D8OnHFBk.mjs → mode-gu_mhKKs.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- import { h as GraphFormatConverter, u as Graph } from "../../types-3-FS9NV2.mjs";
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/formats/jgf';
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/formats/jgf';
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/formats/jgf';
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-udLITX36.mjs";
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/formats/jgf';
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/formats/jgf';
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/formats/jgf';
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 { h as GraphFormatConverter, u as Graph } from "../../types-3-FS9NV2.mjs";
1
+ import { _ as GraphFormatConverter, f as Graph } from "../../types-BAEQTwK_.mjs";
2
2
 
3
3
  //#region src/formats/mermaid/sequence.d.ts
4
4
  interface SequenceNodeData {
@@ -1,4 +1,4 @@
1
- import { n as createFormatConverter } from "../../converter-udLITX36.mjs";
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 && top.includes("_region_")) parentStack.pop();
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 && !id.includes("_region_")) return 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 && top.includes("_region_")) parentStack.pop();
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: null,
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.id.includes("_region_")) continue;
1715
- if (node.data?.stateType && node.data.stateType !== "parallel") lines.push(`${indent}state ${node.id} <<${node.data.stateType}>>`);
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 = node.data?.description ? `state "${escapeMermaidLabel(node.data.description)}" as ${node.id} {` : `state ${node.id} {`;
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.id.includes("_region_"));
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
- } else if (node.data?.description) lines.push(`${indent}state "${escapeMermaidLabel(node.data.description)}" as ${node.id}`);
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 { h as GraphFormatConverter, u as Graph } from "../../types-3-FS9NV2.mjs";
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/formats/tgf';
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/formats/tgf';
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/formats/tgf';
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-udLITX36.mjs";
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/formats/tgf';
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/formats/tgf';
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/formats/tgf';
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 { F as VisualGraphFormatConverter, M as VisualGraph } from "../../types-3-FS9NV2.mjs";
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
- /** xyflow Edge — re-exported from `@xyflow/system`. */
8
- type XYFlowEdge<TEdgeData extends Record<string, unknown> = Record<string, unknown>> = EdgeBase<TEdgeData>;
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/formats/xyflow';
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/formats/xyflow';
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/formats/xyflow';
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 && "data" in metadata) return metadata.data;
23
- return value;
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/formats/xyflow';
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.data.label = e.label;
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/formats/xyflow';
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/formats/xyflow';
206
+ * import { xyflowConverter } from '@statelyai/graph/xyflow';
175
207
  *
176
208
  * const graph = createVisualGraph({
177
209
  * nodes: [
@@ -1,4 +1,4 @@
1
- import { h as GraphFormatConverter, u as Graph } from "./types-3-FS9NV2.mjs";
1
+ import { _ as GraphFormatConverter, f as Graph } from "./types-BAEQTwK_.mjs";
2
2
 
3
3
  //#region src/formats/converter/index.d.ts
4
4