@statelyai/graph 0.4.0 → 0.5.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/dist/{algorithms-CnTmuX9t.mjs → algorithms-DldwenLt.mjs} +1 -1
- package/dist/algorithms.d.mts +1 -1
- package/dist/algorithms.mjs +1 -1
- package/dist/{converter-C5DlzzHs.mjs → converter-B5CUD0r9.mjs} +2 -2
- 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 +2 -2
- package/dist/formats/converter/index.mjs +1 -1
- package/dist/formats/cytoscape/index.d.mts +1 -1
- package/dist/formats/cytoscape/index.mjs +1 -1
- package/dist/formats/d3/index.d.mts +1 -1
- package/dist/formats/d3/index.mjs +1 -1
- package/dist/formats/dot/index.d.mts +1 -1
- package/dist/formats/dot/index.mjs +1 -1
- 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 +61 -0
- package/dist/formats/elk/index.mjs +176 -0
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gexf/index.mjs +1 -1
- package/dist/formats/gml/index.d.mts +1 -1
- package/dist/formats/gml/index.mjs +1 -1
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +1 -1
- package/dist/formats/jgf/index.d.mts +1 -1
- package/dist/formats/jgf/index.mjs +1 -1
- package/dist/formats/mermaid/index.d.mts +46 -33
- package/dist/formats/mermaid/index.mjs +315 -31
- package/dist/formats/tgf/index.d.mts +1 -1
- package/dist/formats/tgf/index.mjs +1 -1
- package/dist/formats/xyflow/index.d.mts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/queries.d.mts +1 -1
- package/dist/queries.mjs +1 -1
- package/dist/schemas.d.mts +37 -4
- package/dist/schemas.mjs +26 -5
- package/dist/{types-Bq_fmLwW.d.mts → types-FBZCrmnG.d.mts} +6 -6
- package/package.json +7 -1
- package/schemas/edge.schema.json +32 -1
- package/schemas/graph.schema.json +114 -4
- package/schemas/node.schema.json +45 -2
- /package/dist/{adjacency-list-Bv4tfiM3.mjs → adjacency-list-fldj-QAL.mjs} +0 -0
- /package/dist/{edge-list-R1SUbHwe.mjs → edge-list-Br05wXMg.mjs} +0 -0
- /package/dist/{indexing-DitHphT7.mjs → indexing-DyfgLuzw.mjs} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as indexUpdateEdgeEndpoints, i as indexReparentNode, n as indexAddEdge, o as invalidateIndex, r as indexAddNode, t as getIndex } from "./indexing-
|
|
1
|
+
import { a as indexUpdateEdgeEndpoints, i as indexReparentNode, n as indexAddEdge, o as invalidateIndex, r as indexAddNode, t as getIndex } from "./indexing-DyfgLuzw.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/graph.ts
|
|
4
4
|
function resolveNode(config) {
|
package/dist/algorithms.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as TraversalOptions, _ as MSTOptions, b as PathOptions, c as Graph, h as GraphPath, p as GraphNode, t as AllPairsShortestPathsOptions, x as SinglePathOptions } from "./types-
|
|
1
|
+
import { C as TraversalOptions, _ as MSTOptions, b as PathOptions, c as Graph, h as GraphPath, p as GraphNode, t as AllPairsShortestPathsOptions, x as SinglePathOptions } from "./types-FBZCrmnG.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/algorithms.d.ts
|
|
4
4
|
|
package/dist/algorithms.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as isAcyclic, E as joinPaths, S as hasPath, T as isTree, _ as getShortestPaths, a as genPreorders, b as getStronglyConnectedComponents, c as getAllPairsShortestPaths, d as getMinimumSpanningTree, f as getPostorder, g as getShortestPath, h as getPreorders, i as genPostorders, l as getConnectedComponents, m as getPreorder, n as dfs, o as genShortestPaths, p as getPostorders, r as genCycles, s as genSimplePaths, t as bfs, u as getCycles, v as getSimplePath, w as isConnected, x as getTopologicalSort, y as getSimplePaths } from "./algorithms-
|
|
1
|
+
import { C as isAcyclic, E as joinPaths, S as hasPath, T as isTree, _ as getShortestPaths, a as genPreorders, b as getStronglyConnectedComponents, c as getAllPairsShortestPaths, d as getMinimumSpanningTree, f as getPostorder, g as getShortestPath, h as getPreorders, i as genPostorders, l as getConnectedComponents, m as getPreorder, n as dfs, o as genShortestPaths, p as getPostorders, r as genCycles, s as genSimplePaths, t as bfs, u as getCycles, v as getSimplePath, w as isConnected, x as getTopologicalSort, y as getSimplePaths } from "./algorithms-DldwenLt.mjs";
|
|
2
2
|
|
|
3
3
|
export { bfs, dfs, genCycles, genPostorders, genPreorders, genShortestPaths, genSimplePaths, getAllPairsShortestPaths, getConnectedComponents, getCycles, getMinimumSpanningTree, getPostorder, getPostorders, getPreorder, getPreorders, getShortestPath, getShortestPaths, getSimplePath, getSimplePaths, getStronglyConnectedComponents, getTopologicalSort, hasPath, isAcyclic, isConnected, isTree, joinPaths };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as toAdjacencyList, t as fromAdjacencyList } from "./adjacency-list-
|
|
2
|
-
import { n as toEdgeList, t as fromEdgeList } from "./edge-list-
|
|
1
|
+
import { n as toAdjacencyList, t as fromAdjacencyList } from "./adjacency-list-fldj-QAL.mjs";
|
|
2
|
+
import { n as toEdgeList, t as fromEdgeList } from "./edge-list-Br05wXMg.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/formats/converter/index.ts
|
|
5
5
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as Graph, f as GraphFormatConverter } from "../../types-
|
|
1
|
+
import { c as Graph, f as GraphFormatConverter } from "../../types-FBZCrmnG.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formats/converter/index.d.ts
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ import { c as Graph, f as GraphFormatConverter } from "../../types-Bq_fmLwW.mjs"
|
|
|
18
18
|
* const graph = yamlConverter.from(yaml);
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
declare function createFormatConverter<TSerial>(to: (graph: Graph) => TSerial, from: (input: TSerial) => Graph): GraphFormatConverter<TSerial>;
|
|
21
|
+
declare function createFormatConverter<TSerial, N = any, E = any, G = any>(to: (graph: Graph<N, E, G>) => TSerial, from: (input: TSerial) => Graph<N, E, G>): GraphFormatConverter<TSerial, N, E, G>;
|
|
22
22
|
/**
|
|
23
23
|
* Bidirectional converter for adjacency-list format (`Record<string, string[]>`).
|
|
24
24
|
*
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as createFormatConverter, r as edgeListConverter, t as adjacencyListConverter } from "../../converter-
|
|
1
|
+
import { n as createFormatConverter, r as edgeListConverter, t as adjacencyListConverter } from "../../converter-B5CUD0r9.mjs";
|
|
2
2
|
|
|
3
3
|
export { adjacencyListConverter, createFormatConverter, edgeListConverter };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { D as VisualGraphFormatConverter, T as VisualGraph } from "../../types-FBZCrmnG.mjs";
|
|
2
|
+
import { ElkEdge, ElkEdgeSection, ElkExtendedEdge, ElkGraphElement, ElkLabel, ElkNode, ElkNode as ElkNode$1, ElkPoint, ElkPort, ElkPrimitiveEdge, ElkShape, LayoutOptions } from "elkjs/lib/elk-api";
|
|
3
|
+
|
|
4
|
+
//#region src/formats/elk/index.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Converts a visual graph to ELK JSON format.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { createVisualGraph } from '@statelyai/graph';
|
|
12
|
+
* import { toELK } from '@statelyai/graph/elk';
|
|
13
|
+
*
|
|
14
|
+
* const graph = createVisualGraph({
|
|
15
|
+
* nodes: [
|
|
16
|
+
* { id: 'a', x: 0, y: 0, width: 100, height: 50 },
|
|
17
|
+
* { id: 'b', x: 200, y: 0, width: 100, height: 50 },
|
|
18
|
+
* ],
|
|
19
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* const elk = toELK(graph);
|
|
23
|
+
* // { id: '', children: [...], edges: [...] }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare function toELK(graph: VisualGraph): ElkNode$1;
|
|
27
|
+
/**
|
|
28
|
+
* Parses an ELK JSON node into a visual graph.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { fromELK } from '@statelyai/graph/elk';
|
|
33
|
+
*
|
|
34
|
+
* const graph = fromELK({
|
|
35
|
+
* id: 'root',
|
|
36
|
+
* children: [
|
|
37
|
+
* { id: 'a', x: 0, y: 0, width: 100, height: 50 },
|
|
38
|
+
* { id: 'b', x: 200, y: 0, width: 100, height: 50 },
|
|
39
|
+
* ],
|
|
40
|
+
* edges: [{ id: 'e1', sources: ['a'], targets: ['b'] }],
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* graph.nodes; // [{id: 'a', x: 0, y: 0, ...}, {id: 'b', x: 200, ...}]
|
|
44
|
+
* graph.edges; // [{sourceId: 'a', targetId: 'b', ...}]
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function fromELK(elkRoot: ElkNode$1): VisualGraph;
|
|
48
|
+
/**
|
|
49
|
+
* Bidirectional converter for ELK JSON format.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { elkConverter } from '@statelyai/graph/elk';
|
|
54
|
+
*
|
|
55
|
+
* const elk = elkConverter.to(graph);
|
|
56
|
+
* const roundTripped = elkConverter.from(elk);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare const elkConverter: VisualGraphFormatConverter<ElkNode$1>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { type ElkEdge, type ElkEdgeSection, type ElkExtendedEdge, type ElkGraphElement, type ElkLabel, type ElkNode, type ElkPoint, type ElkPort, type ElkPrimitiveEdge, type ElkShape, type LayoutOptions, elkConverter, fromELK, toELK };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { getChildren } from "../../queries.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/formats/elk/index.ts
|
|
4
|
+
const DIRECTION_TO_ELK = {
|
|
5
|
+
down: "DOWN",
|
|
6
|
+
up: "UP",
|
|
7
|
+
right: "RIGHT",
|
|
8
|
+
left: "LEFT"
|
|
9
|
+
};
|
|
10
|
+
const ELK_TO_DIRECTION = {
|
|
11
|
+
DOWN: "down",
|
|
12
|
+
UP: "up",
|
|
13
|
+
RIGHT: "right",
|
|
14
|
+
LEFT: "left"
|
|
15
|
+
};
|
|
16
|
+
function convertEdge(edge) {
|
|
17
|
+
const elkEdge = {
|
|
18
|
+
id: edge.id,
|
|
19
|
+
sources: [edge.sourceId],
|
|
20
|
+
targets: [edge.targetId]
|
|
21
|
+
};
|
|
22
|
+
if (edge.label) elkEdge.labels = [{ text: edge.label }];
|
|
23
|
+
return elkEdge;
|
|
24
|
+
}
|
|
25
|
+
function convertNode(graph, node) {
|
|
26
|
+
const elkNode = {
|
|
27
|
+
id: node.id,
|
|
28
|
+
x: node.x,
|
|
29
|
+
y: node.y,
|
|
30
|
+
width: node.width,
|
|
31
|
+
height: node.height
|
|
32
|
+
};
|
|
33
|
+
if (node.label) elkNode.labels = [{ text: node.label }];
|
|
34
|
+
const children = getChildren(graph, node.id);
|
|
35
|
+
if (children.length > 0) {
|
|
36
|
+
elkNode.children = children.map((child) => convertNode(graph, child));
|
|
37
|
+
const descendantIds = /* @__PURE__ */ new Set();
|
|
38
|
+
collectDescendants(graph, node.id, descendantIds);
|
|
39
|
+
const innerEdges = graph.edges.filter((e) => descendantIds.has(e.sourceId) && descendantIds.has(e.targetId));
|
|
40
|
+
if (innerEdges.length > 0) elkNode.edges = innerEdges.map(convertEdge);
|
|
41
|
+
}
|
|
42
|
+
return elkNode;
|
|
43
|
+
}
|
|
44
|
+
function collectDescendants(graph, nodeId, set) {
|
|
45
|
+
const children = getChildren(graph, nodeId);
|
|
46
|
+
for (const child of children) {
|
|
47
|
+
set.add(child.id);
|
|
48
|
+
collectDescendants(graph, child.id, set);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Converts a visual graph to ELK JSON format.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { createVisualGraph } from '@statelyai/graph';
|
|
57
|
+
* import { toELK } from '@statelyai/graph/elk';
|
|
58
|
+
*
|
|
59
|
+
* const graph = createVisualGraph({
|
|
60
|
+
* nodes: [
|
|
61
|
+
* { id: 'a', x: 0, y: 0, width: 100, height: 50 },
|
|
62
|
+
* { id: 'b', x: 200, y: 0, width: 100, height: 50 },
|
|
63
|
+
* ],
|
|
64
|
+
* edges: [{ id: 'e1', sourceId: 'a', targetId: 'b' }],
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* const elk = toELK(graph);
|
|
68
|
+
* // { id: '', children: [...], edges: [...] }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
function toELK(graph) {
|
|
72
|
+
const root = { id: graph.id };
|
|
73
|
+
const elkDir = DIRECTION_TO_ELK[graph.direction];
|
|
74
|
+
if (elkDir) root.layoutOptions = { "elk.direction": elkDir };
|
|
75
|
+
const roots = getChildren(graph, null);
|
|
76
|
+
if (roots.length > 0) root.children = roots.map((node) => convertNode(graph, node));
|
|
77
|
+
const allInnerEdgeIds = /* @__PURE__ */ new Set();
|
|
78
|
+
for (const node of graph.nodes) if (getChildren(graph, node.id).length > 0) {
|
|
79
|
+
const descendantIds = /* @__PURE__ */ new Set();
|
|
80
|
+
collectDescendants(graph, node.id, descendantIds);
|
|
81
|
+
for (const edge of graph.edges) if (descendantIds.has(edge.sourceId) && descendantIds.has(edge.targetId)) allInnerEdgeIds.add(edge.id);
|
|
82
|
+
}
|
|
83
|
+
const rootEdges = graph.edges.filter((e) => !allInnerEdgeIds.has(e.id));
|
|
84
|
+
if (rootEdges.length > 0) root.edges = rootEdges.map(convertEdge);
|
|
85
|
+
return root;
|
|
86
|
+
}
|
|
87
|
+
function flattenElkNodes(elkNode, parentId, nodes, edges, edgeIdx) {
|
|
88
|
+
if (elkNode.children) for (const child of elkNode.children) {
|
|
89
|
+
const label = child.labels?.[0]?.text ?? "";
|
|
90
|
+
const node = {
|
|
91
|
+
type: "node",
|
|
92
|
+
id: child.id,
|
|
93
|
+
parentId,
|
|
94
|
+
initialNodeId: null,
|
|
95
|
+
label,
|
|
96
|
+
data: void 0,
|
|
97
|
+
x: child.x ?? 0,
|
|
98
|
+
y: child.y ?? 0,
|
|
99
|
+
width: child.width ?? 0,
|
|
100
|
+
height: child.height ?? 0
|
|
101
|
+
};
|
|
102
|
+
nodes.push(node);
|
|
103
|
+
flattenElkNodes(child, child.id, nodes, edges, edgeIdx);
|
|
104
|
+
}
|
|
105
|
+
if (elkNode.edges) for (const elkEdge of elkNode.edges) for (const source of elkEdge.sources) for (const target of elkEdge.targets) {
|
|
106
|
+
const edge = {
|
|
107
|
+
type: "edge",
|
|
108
|
+
id: elkEdge.id ?? `e${edgeIdx.value++}`,
|
|
109
|
+
sourceId: source,
|
|
110
|
+
targetId: target,
|
|
111
|
+
label: elkEdge.labels?.[0]?.text ?? "",
|
|
112
|
+
data: void 0,
|
|
113
|
+
x: 0,
|
|
114
|
+
y: 0,
|
|
115
|
+
width: 0,
|
|
116
|
+
height: 0
|
|
117
|
+
};
|
|
118
|
+
edges.push(edge);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Parses an ELK JSON node into a visual graph.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* import { fromELK } from '@statelyai/graph/elk';
|
|
127
|
+
*
|
|
128
|
+
* const graph = fromELK({
|
|
129
|
+
* id: 'root',
|
|
130
|
+
* children: [
|
|
131
|
+
* { id: 'a', x: 0, y: 0, width: 100, height: 50 },
|
|
132
|
+
* { id: 'b', x: 200, y: 0, width: 100, height: 50 },
|
|
133
|
+
* ],
|
|
134
|
+
* edges: [{ id: 'e1', sources: ['a'], targets: ['b'] }],
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* graph.nodes; // [{id: 'a', x: 0, y: 0, ...}, {id: 'b', x: 200, ...}]
|
|
138
|
+
* graph.edges; // [{sourceId: 'a', targetId: 'b', ...}]
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
function fromELK(elkRoot) {
|
|
142
|
+
const nodes = [];
|
|
143
|
+
const edges = [];
|
|
144
|
+
flattenElkNodes(elkRoot, null, nodes, edges, { value: 0 });
|
|
145
|
+
const seenEdges = /* @__PURE__ */ new Map();
|
|
146
|
+
for (const edge of edges) if (!seenEdges.has(edge.id)) seenEdges.set(edge.id, edge);
|
|
147
|
+
const elkDir = elkRoot.layoutOptions?.["elk.direction"];
|
|
148
|
+
const direction = (elkDir ? ELK_TO_DIRECTION[elkDir] : void 0) ?? "down";
|
|
149
|
+
return {
|
|
150
|
+
id: elkRoot.id,
|
|
151
|
+
type: "directed",
|
|
152
|
+
initialNodeId: null,
|
|
153
|
+
nodes,
|
|
154
|
+
edges: [...seenEdges.values()],
|
|
155
|
+
data: void 0,
|
|
156
|
+
direction
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Bidirectional converter for ELK JSON format.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* import { elkConverter } from '@statelyai/graph/elk';
|
|
165
|
+
*
|
|
166
|
+
* const elk = elkConverter.to(graph);
|
|
167
|
+
* const roundTripped = elkConverter.from(elk);
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
const elkConverter = {
|
|
171
|
+
to: toELK,
|
|
172
|
+
from: fromELK
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
//#endregion
|
|
176
|
+
export { elkConverter, fromELK, toELK };
|