@coral-viz/viz 0.2.3
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/LICENSE +4 -0
- package/README.md +11 -0
- package/dist/compatibility/CompatibilityEdge.d.ts +106 -0
- package/dist/compatibility/CompatibilityEdge.d.ts.map +1 -0
- package/dist/compatibility/CompatibilityEdge.js +233 -0
- package/dist/compatibility/CompatibilityEdge.js.map +1 -0
- package/dist/compatibility/IncompatibilityTooltip.d.ts +44 -0
- package/dist/compatibility/IncompatibilityTooltip.d.ts.map +1 -0
- package/dist/compatibility/IncompatibilityTooltip.js +145 -0
- package/dist/compatibility/IncompatibilityTooltip.js.map +1 -0
- package/dist/compatibility/index.d.ts +10 -0
- package/dist/compatibility/index.d.ts.map +1 -0
- package/dist/compatibility/index.js +10 -0
- package/dist/compatibility/index.js.map +1 -0
- package/dist/compatibility/useEdgeCompatibility.d.ts +82 -0
- package/dist/compatibility/useEdgeCompatibility.d.ts.map +1 -0
- package/dist/compatibility/useEdgeCompatibility.js +170 -0
- package/dist/compatibility/useEdgeCompatibility.js.map +1 -0
- package/dist/compatibility/validateConnection.d.ts +56 -0
- package/dist/compatibility/validateConnection.d.ts.map +1 -0
- package/dist/compatibility/validateConnection.js +382 -0
- package/dist/compatibility/validateConnection.js.map +1 -0
- package/dist/components/EditContext.d.ts +45 -0
- package/dist/components/EditContext.d.ts.map +1 -0
- package/dist/components/EditContext.js +41 -0
- package/dist/components/EditContext.js.map +1 -0
- package/dist/components/ShapeRenderer.d.ts +35 -0
- package/dist/components/ShapeRenderer.d.ts.map +1 -0
- package/dist/components/ShapeRenderer.js +77 -0
- package/dist/components/ShapeRenderer.js.map +1 -0
- package/dist/components/SymbolNode.d.ts +53 -0
- package/dist/components/SymbolNode.d.ts.map +1 -0
- package/dist/components/SymbolNode.js +333 -0
- package/dist/components/SymbolNode.js.map +1 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +10 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/nodes.d.ts +43 -0
- package/dist/components/nodes.d.ts.map +1 -0
- package/dist/components/nodes.js +111 -0
- package/dist/components/nodes.js.map +1 -0
- package/dist/editor/CoralEditor.d.ts +29 -0
- package/dist/editor/CoralEditor.d.ts.map +1 -0
- package/dist/editor/CoralEditor.js +112 -0
- package/dist/editor/CoralEditor.js.map +1 -0
- package/dist/editor/FileControls.d.ts +34 -0
- package/dist/editor/FileControls.d.ts.map +1 -0
- package/dist/editor/FileControls.js +139 -0
- package/dist/editor/FileControls.js.map +1 -0
- package/dist/editor/LayoutControls.d.ts +41 -0
- package/dist/editor/LayoutControls.d.ts.map +1 -0
- package/dist/editor/LayoutControls.js +124 -0
- package/dist/editor/LayoutControls.js.map +1 -0
- package/dist/editor/converter.d.ts +37 -0
- package/dist/editor/converter.d.ts.map +1 -0
- package/dist/editor/converter.js +256 -0
- package/dist/editor/converter.js.map +1 -0
- package/dist/editor/index.d.ts +8 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +8 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/file/deserialize.d.ts +15 -0
- package/dist/file/deserialize.d.ts.map +1 -0
- package/dist/file/deserialize.js +145 -0
- package/dist/file/deserialize.js.map +1 -0
- package/dist/file/index.d.ts +15 -0
- package/dist/file/index.d.ts.map +1 -0
- package/dist/file/index.js +20 -0
- package/dist/file/index.js.map +1 -0
- package/dist/file/migrate.d.ts +29 -0
- package/dist/file/migrate.d.ts.map +1 -0
- package/dist/file/migrate.js +103 -0
- package/dist/file/migrate.js.map +1 -0
- package/dist/file/schema.d.ts +385 -0
- package/dist/file/schema.d.ts.map +1 -0
- package/dist/file/schema.js +180 -0
- package/dist/file/schema.js.map +1 -0
- package/dist/file/serialize.d.ts +30 -0
- package/dist/file/serialize.d.ts.map +1 -0
- package/dist/file/serialize.js +218 -0
- package/dist/file/serialize.js.map +1 -0
- package/dist/file/validate.d.ts +21 -0
- package/dist/file/validate.d.ts.map +1 -0
- package/dist/file/validate.js +165 -0
- package/dist/file/validate.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/elk.d.ts +77 -0
- package/dist/layout/elk.d.ts.map +1 -0
- package/dist/layout/elk.js +379 -0
- package/dist/layout/elk.js.map +1 -0
- package/dist/layout/index.d.ts +12 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +12 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/nodeSizing.d.ts +65 -0
- package/dist/layout/nodeSizing.d.ts.map +1 -0
- package/dist/layout/nodeSizing.js +319 -0
- package/dist/layout/nodeSizing.js.map +1 -0
- package/dist/layout/positionStability.d.ts +73 -0
- package/dist/layout/positionStability.d.ts.map +1 -0
- package/dist/layout/positionStability.js +199 -0
- package/dist/layout/positionStability.js.map +1 -0
- package/dist/layout/useAxisConstrain.d.ts +20 -0
- package/dist/layout/useAxisConstrain.d.ts.map +1 -0
- package/dist/layout/useAxisConstrain.js +106 -0
- package/dist/layout/useAxisConstrain.js.map +1 -0
- package/dist/layout/useDiagramState.d.ts +92 -0
- package/dist/layout/useDiagramState.d.ts.map +1 -0
- package/dist/layout/useDiagramState.js +256 -0
- package/dist/layout/useDiagramState.js.map +1 -0
- package/dist/layout/useLayoutHistory.d.ts +53 -0
- package/dist/layout/useLayoutHistory.d.ts.map +1 -0
- package/dist/layout/useLayoutHistory.js +124 -0
- package/dist/layout/useLayoutHistory.js.map +1 -0
- package/dist/properties/NodePropertiesPanel.d.ts +47 -0
- package/dist/properties/NodePropertiesPanel.d.ts.map +1 -0
- package/dist/properties/NodePropertiesPanel.js +199 -0
- package/dist/properties/NodePropertiesPanel.js.map +1 -0
- package/dist/properties/index.d.ts +10 -0
- package/dist/properties/index.d.ts.map +1 -0
- package/dist/properties/index.js +10 -0
- package/dist/properties/index.js.map +1 -0
- package/dist/properties/propertyUtils.d.ts +60 -0
- package/dist/properties/propertyUtils.d.ts.map +1 -0
- package/dist/properties/propertyUtils.js +89 -0
- package/dist/properties/propertyUtils.js.map +1 -0
- package/dist/settings/FontSettingsForm.d.ts +28 -0
- package/dist/settings/FontSettingsForm.d.ts.map +1 -0
- package/dist/settings/FontSettingsForm.js +129 -0
- package/dist/settings/FontSettingsForm.js.map +1 -0
- package/dist/settings/LayoutSettingsForm.d.ts +37 -0
- package/dist/settings/LayoutSettingsForm.d.ts.map +1 -0
- package/dist/settings/LayoutSettingsForm.js +165 -0
- package/dist/settings/LayoutSettingsForm.js.map +1 -0
- package/dist/settings/SettingsPanel.d.ts +55 -0
- package/dist/settings/SettingsPanel.d.ts.map +1 -0
- package/dist/settings/SettingsPanel.js +84 -0
- package/dist/settings/SettingsPanel.js.map +1 -0
- package/dist/settings/index.d.ts +13 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +13 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/useSettings.d.ts +51 -0
- package/dist/settings/useSettings.d.ts.map +1 -0
- package/dist/settings/useSettings.js +154 -0
- package/dist/settings/useSettings.js.map +1 -0
- package/dist/text-editor/SplitEditor.d.ts +72 -0
- package/dist/text-editor/SplitEditor.d.ts.map +1 -0
- package/dist/text-editor/SplitEditor.js +172 -0
- package/dist/text-editor/SplitEditor.js.map +1 -0
- package/dist/text-editor/TextEditor.d.ts +53 -0
- package/dist/text-editor/TextEditor.d.ts.map +1 -0
- package/dist/text-editor/TextEditor.js +181 -0
- package/dist/text-editor/TextEditor.js.map +1 -0
- package/dist/text-editor/hooks/useBidirectionalSync.d.ts +106 -0
- package/dist/text-editor/hooks/useBidirectionalSync.d.ts.map +1 -0
- package/dist/text-editor/hooks/useBidirectionalSync.js +151 -0
- package/dist/text-editor/hooks/useBidirectionalSync.js.map +1 -0
- package/dist/text-editor/index.d.ts +9 -0
- package/dist/text-editor/index.d.ts.map +1 -0
- package/dist/text-editor/index.js +11 -0
- package/dist/text-editor/index.js.map +1 -0
- package/dist/types.d.ts +242 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/waypoints/index.d.ts +8 -0
- package/dist/waypoints/index.d.ts.map +1 -0
- package/dist/waypoints/index.js +7 -0
- package/dist/waypoints/index.js.map +1 -0
- package/dist/waypoints/operations.d.ts +29 -0
- package/dist/waypoints/operations.d.ts.map +1 -0
- package/dist/waypoints/operations.js +85 -0
- package/dist/waypoints/operations.js.map +1 -0
- package/dist/waypoints/router.d.ts +23 -0
- package/dist/waypoints/router.d.ts.map +1 -0
- package/dist/waypoints/router.js +109 -0
- package/dist/waypoints/router.js.map +1 -0
- package/dist/waypoints/types.d.ts +15 -0
- package/dist/waypoints/types.d.ts.map +1 -0
- package/dist/waypoints/types.js +5 -0
- package/dist/waypoints/types.js.map +1 -0
- package/dist/waypoints/useWaypointManager.d.ts +38 -0
- package/dist/waypoints/useWaypointManager.d.ts.map +1 -0
- package/dist/waypoints/useWaypointManager.js +106 -0
- package/dist/waypoints/useWaypointManager.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ELK Layout Integration
|
|
3
|
+
*
|
|
4
|
+
* Uses elkjs to compute automatic layouts for Graph-IR diagrams.
|
|
5
|
+
*/
|
|
6
|
+
import ELK from 'elkjs/lib/elk.bundled.js';
|
|
7
|
+
import { applyAdaptiveSizing } from './nodeSizing.js';
|
|
8
|
+
import { symbolRegistry } from '@coral-viz/render';
|
|
9
|
+
const elk = new ELK();
|
|
10
|
+
/**
|
|
11
|
+
* Default node dimensions when not specified
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_NODE_WIDTH = 150;
|
|
14
|
+
const DEFAULT_NODE_HEIGHT = 50;
|
|
15
|
+
const DEFAULT_GROUP_PADDING = 20;
|
|
16
|
+
/**
|
|
17
|
+
* Map Graph-IR layout direction to ELK direction
|
|
18
|
+
*/
|
|
19
|
+
const directionMap = {
|
|
20
|
+
DOWN: 'DOWN',
|
|
21
|
+
UP: 'UP',
|
|
22
|
+
LEFT: 'LEFT',
|
|
23
|
+
RIGHT: 'RIGHT',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Map Graph-IR algorithm to ELK algorithm
|
|
27
|
+
*/
|
|
28
|
+
const algorithmMap = {
|
|
29
|
+
layered: 'layered',
|
|
30
|
+
force: 'force',
|
|
31
|
+
radial: 'radial',
|
|
32
|
+
tree: 'mrtree',
|
|
33
|
+
fixed: 'fixed',
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Convert Graph-IR layout options to ELK options
|
|
37
|
+
*/
|
|
38
|
+
function toElkOptions(options) {
|
|
39
|
+
const elkOptions = {
|
|
40
|
+
'elk.algorithm': algorithmMap[options?.algorithm || 'layered'] || 'layered',
|
|
41
|
+
'elk.direction': directionMap[options?.direction || 'DOWN'] || 'DOWN',
|
|
42
|
+
};
|
|
43
|
+
if (options?.spacing) {
|
|
44
|
+
if (options.spacing.nodeNode !== undefined) {
|
|
45
|
+
elkOptions['elk.spacing.nodeNode'] = String(options.spacing.nodeNode);
|
|
46
|
+
}
|
|
47
|
+
if (options.spacing.layerSpacing !== undefined) {
|
|
48
|
+
elkOptions['elk.layered.spacing.nodeNodeBetweenLayers'] = String(options.spacing.layerSpacing);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return elkOptions;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Convert a GraphNode to ELK node format
|
|
55
|
+
*/
|
|
56
|
+
function toElkNode(node) {
|
|
57
|
+
const elkNode = {
|
|
58
|
+
id: node.id,
|
|
59
|
+
width: node.dimensions?.width || DEFAULT_NODE_WIDTH,
|
|
60
|
+
height: node.dimensions?.height || DEFAULT_NODE_HEIGHT,
|
|
61
|
+
};
|
|
62
|
+
// Handle children for group nodes
|
|
63
|
+
if (node.children && node.children.length > 0) {
|
|
64
|
+
elkNode.children = node.children.map(toElkNode);
|
|
65
|
+
elkNode.layoutOptions = {
|
|
66
|
+
'elk.padding': `[top=${DEFAULT_GROUP_PADDING},left=${DEFAULT_GROUP_PADDING},bottom=${DEFAULT_GROUP_PADDING},right=${DEFAULT_GROUP_PADDING}]`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return elkNode;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Convert a GraphEdge to ELK edge format
|
|
73
|
+
*/
|
|
74
|
+
function toElkEdge(edge) {
|
|
75
|
+
return {
|
|
76
|
+
id: edge.id,
|
|
77
|
+
sources: [edge.source],
|
|
78
|
+
targets: [edge.target],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Apply ELK positions back to GraphNodes
|
|
83
|
+
*/
|
|
84
|
+
function applyPositions(nodes, elkNodes) {
|
|
85
|
+
const positionMap = new Map();
|
|
86
|
+
// Build position map from ELK results (handles nested nodes)
|
|
87
|
+
function collectPositions(elkNodes, offsetX = 0, offsetY = 0) {
|
|
88
|
+
for (const elkNode of elkNodes) {
|
|
89
|
+
const x = (elkNode.x || 0) + offsetX;
|
|
90
|
+
const y = (elkNode.y || 0) + offsetY;
|
|
91
|
+
positionMap.set(elkNode.id, {
|
|
92
|
+
x,
|
|
93
|
+
y,
|
|
94
|
+
width: elkNode.width,
|
|
95
|
+
height: elkNode.height,
|
|
96
|
+
});
|
|
97
|
+
if (elkNode.children) {
|
|
98
|
+
collectPositions(elkNode.children, x, y);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
collectPositions(elkNodes);
|
|
103
|
+
// Apply positions to GraphNodes
|
|
104
|
+
function applyToNodes(nodes) {
|
|
105
|
+
return nodes.map((node) => {
|
|
106
|
+
const pos = positionMap.get(node.id);
|
|
107
|
+
const result = {
|
|
108
|
+
...node,
|
|
109
|
+
position: pos ? { x: pos.x, y: pos.y } : node.position,
|
|
110
|
+
};
|
|
111
|
+
if (pos?.width && pos?.height) {
|
|
112
|
+
result.dimensions = { width: pos.width, height: pos.height };
|
|
113
|
+
}
|
|
114
|
+
if (node.children) {
|
|
115
|
+
result.children = applyToNodes(node.children);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return applyToNodes(nodes);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Layout a Graph-IR structure using ELK
|
|
124
|
+
*
|
|
125
|
+
* @param graph - The Graph-IR to layout
|
|
126
|
+
* @returns Graph-IR with positions computed for all nodes
|
|
127
|
+
*/
|
|
128
|
+
export async function layoutGraph(graph) {
|
|
129
|
+
const elkGraph = {
|
|
130
|
+
id: graph.id || 'root',
|
|
131
|
+
layoutOptions: toElkOptions(graph.layoutOptions),
|
|
132
|
+
children: graph.nodes.map(toElkNode),
|
|
133
|
+
edges: graph.edges.map(toElkEdge),
|
|
134
|
+
};
|
|
135
|
+
const layoutedGraph = await elk.layout(elkGraph);
|
|
136
|
+
return {
|
|
137
|
+
...graph,
|
|
138
|
+
nodes: applyPositions(graph.nodes, layoutedGraph.children || []),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get shape ID from node data
|
|
143
|
+
*/
|
|
144
|
+
function getShapeIdFromNode(node) {
|
|
145
|
+
// Check symbolId first
|
|
146
|
+
const symbolId = node.data.symbolId;
|
|
147
|
+
if (symbolId) {
|
|
148
|
+
const symbol = symbolRegistry.get(symbolId);
|
|
149
|
+
if (symbol) {
|
|
150
|
+
return symbol.shape;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Fallback mapping from node types to shapes
|
|
154
|
+
const typeToShape = {
|
|
155
|
+
service: 'rectangle',
|
|
156
|
+
database: 'cylinder',
|
|
157
|
+
external_api: 'cloud',
|
|
158
|
+
actor: 'actor',
|
|
159
|
+
module: 'rectangle',
|
|
160
|
+
group: 'rectangle',
|
|
161
|
+
process: 'rectangle',
|
|
162
|
+
decision: 'diamond',
|
|
163
|
+
terminal: 'stadium',
|
|
164
|
+
io: 'parallelogram',
|
|
165
|
+
document: 'document',
|
|
166
|
+
};
|
|
167
|
+
return typeToShape[node.data.nodeType] || 'rectangle';
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Layout React Flow nodes using ELK
|
|
171
|
+
*
|
|
172
|
+
* This is a convenience function for use directly with React Flow state.
|
|
173
|
+
*
|
|
174
|
+
* @param nodes - React Flow nodes
|
|
175
|
+
* @param edges - React Flow edges
|
|
176
|
+
* @param options - Layout options (including sizing mode)
|
|
177
|
+
* @returns Nodes with positions updated
|
|
178
|
+
*/
|
|
179
|
+
export async function layoutFlowNodes(nodes, edges, options) {
|
|
180
|
+
// Apply adaptive sizing if enabled (CORAL-REQ-011)
|
|
181
|
+
let sizedNodes = nodes;
|
|
182
|
+
if (options?.sizingMode) {
|
|
183
|
+
sizedNodes = applyAdaptiveSizing(nodes, {
|
|
184
|
+
sizingMode: options.sizingMode,
|
|
185
|
+
getShapeId: getShapeIdFromNode,
|
|
186
|
+
fontSize: options.fontSize,
|
|
187
|
+
fontFamily: options.fontFamily,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// Build ELK graph from React Flow nodes
|
|
191
|
+
const nodeMap = new Map(sizedNodes.map((n) => [n.id, n]));
|
|
192
|
+
const rootNodes = [];
|
|
193
|
+
const childMap = new Map();
|
|
194
|
+
// First pass: create ELK nodes and group children
|
|
195
|
+
for (const node of sizedNodes) {
|
|
196
|
+
const elkNode = {
|
|
197
|
+
id: node.id,
|
|
198
|
+
width: node.measured?.width || node.width || DEFAULT_NODE_WIDTH,
|
|
199
|
+
height: node.measured?.height || node.height || DEFAULT_NODE_HEIGHT,
|
|
200
|
+
};
|
|
201
|
+
if (node.parentId) {
|
|
202
|
+
const siblings = childMap.get(node.parentId) || [];
|
|
203
|
+
siblings.push(elkNode);
|
|
204
|
+
childMap.set(node.parentId, siblings);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
rootNodes.push(elkNode);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Second pass: attach children to parents
|
|
211
|
+
for (const elkNode of rootNodes) {
|
|
212
|
+
const children = childMap.get(elkNode.id);
|
|
213
|
+
if (children) {
|
|
214
|
+
elkNode.children = children;
|
|
215
|
+
elkNode.layoutOptions = {
|
|
216
|
+
'elk.padding': `[top=${DEFAULT_GROUP_PADDING},left=${DEFAULT_GROUP_PADDING},bottom=${DEFAULT_GROUP_PADDING},right=${DEFAULT_GROUP_PADDING}]`,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Convert edges
|
|
221
|
+
const elkEdges = edges.map((e) => ({
|
|
222
|
+
id: e.id,
|
|
223
|
+
sources: [e.source],
|
|
224
|
+
targets: [e.target],
|
|
225
|
+
}));
|
|
226
|
+
const elkGraph = {
|
|
227
|
+
id: 'root',
|
|
228
|
+
layoutOptions: toElkOptions(options),
|
|
229
|
+
children: rootNodes,
|
|
230
|
+
edges: elkEdges,
|
|
231
|
+
};
|
|
232
|
+
const layoutedGraph = await elk.layout(elkGraph);
|
|
233
|
+
// Build position map
|
|
234
|
+
const positionMap = new Map();
|
|
235
|
+
function collectPositions(elkNodes, offsetX = 0, offsetY = 0) {
|
|
236
|
+
for (const elkNode of elkNodes) {
|
|
237
|
+
const x = (elkNode.x || 0) + offsetX;
|
|
238
|
+
const y = (elkNode.y || 0) + offsetY;
|
|
239
|
+
positionMap.set(elkNode.id, { x, y });
|
|
240
|
+
if (elkNode.children) {
|
|
241
|
+
// For children, we need relative positions within the parent
|
|
242
|
+
collectPositions(elkNode.children, 0, 0);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
collectPositions(layoutedGraph.children || []);
|
|
247
|
+
// Apply positions to React Flow nodes (use sizedNodes to preserve computed dimensions)
|
|
248
|
+
return sizedNodes.map((node) => {
|
|
249
|
+
const pos = positionMap.get(node.id);
|
|
250
|
+
if (pos) {
|
|
251
|
+
return {
|
|
252
|
+
...node,
|
|
253
|
+
position: { x: pos.x, y: pos.y },
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return node;
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Extract edge routing sections from ELK layout result.
|
|
261
|
+
*
|
|
262
|
+
* ELK computes edge sections with start/end points and bend points.
|
|
263
|
+
* Previously Coral discarded this data — now we capture it.
|
|
264
|
+
*/
|
|
265
|
+
export function extractEdgeSections(elkEdges) {
|
|
266
|
+
const routing = new Map();
|
|
267
|
+
if (!elkEdges)
|
|
268
|
+
return routing;
|
|
269
|
+
for (const edge of elkEdges) {
|
|
270
|
+
const section = edge.sections?.[0];
|
|
271
|
+
if (!section)
|
|
272
|
+
continue;
|
|
273
|
+
const bendPoints = (section.bendPoints ?? []).map((bp) => ({
|
|
274
|
+
x: bp.x,
|
|
275
|
+
y: bp.y,
|
|
276
|
+
}));
|
|
277
|
+
routing.set(edge.id, {
|
|
278
|
+
id: edge.id,
|
|
279
|
+
startPoint: { x: section.startPoint.x, y: section.startPoint.y },
|
|
280
|
+
endPoint: { x: section.endPoint.x, y: section.endPoint.y },
|
|
281
|
+
bendPoints,
|
|
282
|
+
sourceId: edge.sources[0],
|
|
283
|
+
targetId: edge.targets[0],
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
return routing;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Layout React Flow nodes and extract edge routing from ELK.
|
|
290
|
+
*
|
|
291
|
+
* Same as layoutFlowNodes but also returns the edge routing data
|
|
292
|
+
* that ELK computes. Use this when you want to render edges through
|
|
293
|
+
* ELK's computed bend points instead of React Flow's smoothstep.
|
|
294
|
+
*/
|
|
295
|
+
export async function layoutFlowNodesWithEdges(nodes, edges, options) {
|
|
296
|
+
// Apply adaptive sizing if enabled (CORAL-REQ-011)
|
|
297
|
+
let sizedNodes = nodes;
|
|
298
|
+
if (options?.sizingMode) {
|
|
299
|
+
sizedNodes = applyAdaptiveSizing(nodes, {
|
|
300
|
+
sizingMode: options.sizingMode,
|
|
301
|
+
getShapeId: getShapeIdFromNode,
|
|
302
|
+
fontSize: options.fontSize,
|
|
303
|
+
fontFamily: options.fontFamily,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
// Build ELK graph from React Flow nodes
|
|
307
|
+
const rootNodes = [];
|
|
308
|
+
const childMap = new Map();
|
|
309
|
+
for (const node of sizedNodes) {
|
|
310
|
+
const elkNode = {
|
|
311
|
+
id: node.id,
|
|
312
|
+
width: node.measured?.width || node.width || DEFAULT_NODE_WIDTH,
|
|
313
|
+
height: node.measured?.height || node.height || DEFAULT_NODE_HEIGHT,
|
|
314
|
+
};
|
|
315
|
+
if (node.parentId) {
|
|
316
|
+
const siblings = childMap.get(node.parentId) || [];
|
|
317
|
+
siblings.push(elkNode);
|
|
318
|
+
childMap.set(node.parentId, siblings);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
rootNodes.push(elkNode);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
for (const elkNode of rootNodes) {
|
|
325
|
+
const children = childMap.get(elkNode.id);
|
|
326
|
+
if (children) {
|
|
327
|
+
elkNode.children = children;
|
|
328
|
+
elkNode.layoutOptions = {
|
|
329
|
+
'elk.padding': `[top=${DEFAULT_GROUP_PADDING},left=${DEFAULT_GROUP_PADDING},bottom=${DEFAULT_GROUP_PADDING},right=${DEFAULT_GROUP_PADDING}]`,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const elkEdges = edges.map((e) => ({
|
|
334
|
+
id: e.id,
|
|
335
|
+
sources: [e.source],
|
|
336
|
+
targets: [e.target],
|
|
337
|
+
}));
|
|
338
|
+
const elkGraph = {
|
|
339
|
+
id: 'root',
|
|
340
|
+
layoutOptions: toElkOptions(options),
|
|
341
|
+
children: rootNodes,
|
|
342
|
+
edges: elkEdges,
|
|
343
|
+
};
|
|
344
|
+
const layoutedGraph = await elk.layout(elkGraph);
|
|
345
|
+
// Build position map
|
|
346
|
+
const positionMap = new Map();
|
|
347
|
+
function collectPositions(elkNodes, offsetX = 0, offsetY = 0) {
|
|
348
|
+
for (const elkNode of elkNodes) {
|
|
349
|
+
const x = (elkNode.x || 0) + offsetX;
|
|
350
|
+
const y = (elkNode.y || 0) + offsetY;
|
|
351
|
+
positionMap.set(elkNode.id, { x, y });
|
|
352
|
+
if (elkNode.children) {
|
|
353
|
+
collectPositions(elkNode.children, 0, 0);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
collectPositions(layoutedGraph.children || []);
|
|
358
|
+
// Extract edge routing from ELK
|
|
359
|
+
const edgeRouting = extractEdgeSections(layoutedGraph.edges);
|
|
360
|
+
// Apply positions to React Flow nodes
|
|
361
|
+
const layoutedNodes = sizedNodes.map((node) => {
|
|
362
|
+
const pos = positionMap.get(node.id);
|
|
363
|
+
if (pos) {
|
|
364
|
+
return {
|
|
365
|
+
...node,
|
|
366
|
+
position: { x: pos.x, y: pos.y },
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
return node;
|
|
370
|
+
});
|
|
371
|
+
return { nodes: layoutedNodes, edgeRouting };
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Get ELK instance for advanced usage
|
|
375
|
+
*/
|
|
376
|
+
export function getElk() {
|
|
377
|
+
return elk;
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=elk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elk.js","sourceRoot":"","sources":["../../src/layout/elk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coral Layout Module
|
|
3
|
+
*
|
|
4
|
+
* Provides automatic layout computation using ELK (Eclipse Layout Kernel).
|
|
5
|
+
*/
|
|
6
|
+
export { layoutGraph, layoutFlowNodes, layoutFlowNodesWithEdges, extractEdgeSections, getElk, type LayoutFlowOptions, type LayoutFlowResult, type ElkEdgeRouting, } from './elk.js';
|
|
7
|
+
export { useLayoutHistory, type PositionSnapshot, type UndoRedoResult, type UseLayoutHistoryOptions, type UseLayoutHistoryResult, } from './useLayoutHistory.js';
|
|
8
|
+
export { diffGraphs, resolvePositions, incrementalLayout, } from './positionStability.js';
|
|
9
|
+
export { useDiagramState, type ParsedGraph, type DiagramNode, type DiagramEdge, type UseDiagramStateOptions, type UseDiagramStateResult, } from './useDiagramState.js';
|
|
10
|
+
export { measureText, computeNodeSize, computeUniformSizes, applyAdaptiveSizing, } from './nodeSizing.js';
|
|
11
|
+
export { useAxisConstrain, type UseAxisConstrainResult, } from './useAxisConstrain.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,MAAM,EACN,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coral Layout Module
|
|
3
|
+
*
|
|
4
|
+
* Provides automatic layout computation using ELK (Eclipse Layout Kernel).
|
|
5
|
+
*/
|
|
6
|
+
export { layoutGraph, layoutFlowNodes, layoutFlowNodesWithEdges, extractEdgeSections, getElk, } from './elk.js';
|
|
7
|
+
export { useLayoutHistory, } from './useLayoutHistory.js';
|
|
8
|
+
export { diffGraphs, resolvePositions, incrementalLayout, } from './positionStability.js';
|
|
9
|
+
export { useDiagramState, } from './useDiagramState.js';
|
|
10
|
+
export { measureText, computeNodeSize, computeUniformSizes, applyAdaptiveSizing, } from './nodeSizing.js';
|
|
11
|
+
export { useAxisConstrain, } from './useAxisConstrain.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,MAAM,GAIP,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,gBAAgB,GAKjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,eAAe,GAMhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Sizing Utilities (CORAL-REQ-011)
|
|
3
|
+
*
|
|
4
|
+
* Provides text measurement and adaptive node sizing based on:
|
|
5
|
+
* - Text content dimensions
|
|
6
|
+
* - Shape geometry constraints (textBoundsRatio)
|
|
7
|
+
* - Minimum size requirements
|
|
8
|
+
* - Padding specifications
|
|
9
|
+
*/
|
|
10
|
+
import type { TextMeasureOptions, TextDimensions, NodeSizingOptions, NodeDimensions, SizingMode } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Measure text dimensions using canvas
|
|
13
|
+
*
|
|
14
|
+
* Uses the Canvas API's measureText() for accurate text width measurement,
|
|
15
|
+
* with word wrapping support when maxWidth is specified.
|
|
16
|
+
*/
|
|
17
|
+
export declare function measureText(options: TextMeasureOptions): TextDimensions;
|
|
18
|
+
/**
|
|
19
|
+
* Compute optimal node size based on text content and shape geometry
|
|
20
|
+
*
|
|
21
|
+
* The sizing algorithm:
|
|
22
|
+
* 1. Measure text dimensions
|
|
23
|
+
* 2. Apply shape's textBoundsRatio to account for geometry (e.g., diamond needs more space)
|
|
24
|
+
* 3. Add padding for visual breathing room
|
|
25
|
+
* 4. Enforce minimum size constraints
|
|
26
|
+
* 5. Optionally apply uniform sizing across nodes of the same shape
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeNodeSize(options: NodeSizingOptions): NodeDimensions;
|
|
29
|
+
/**
|
|
30
|
+
* Compute uniform sizes for all shapes in a diagram
|
|
31
|
+
*
|
|
32
|
+
* For uniform sizing mode, we need to find the maximum required size
|
|
33
|
+
* for each shape type, then apply that to all nodes of that type.
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeUniformSizes(nodes: Array<{
|
|
36
|
+
text: string;
|
|
37
|
+
shapeId: string;
|
|
38
|
+
}>, options?: {
|
|
39
|
+
fontSize?: number;
|
|
40
|
+
fontFamily?: string;
|
|
41
|
+
fontWeight?: string | number;
|
|
42
|
+
}): Map<string, {
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Apply adaptive sizing to a set of nodes
|
|
48
|
+
*
|
|
49
|
+
* This is the main entry point for layout integration.
|
|
50
|
+
* Returns nodes with updated width/height properties.
|
|
51
|
+
*/
|
|
52
|
+
export declare function applyAdaptiveSizing<T extends {
|
|
53
|
+
data: {
|
|
54
|
+
label?: string;
|
|
55
|
+
};
|
|
56
|
+
width?: number;
|
|
57
|
+
height?: number;
|
|
58
|
+
}>(nodes: T[], options: {
|
|
59
|
+
sizingMode: SizingMode;
|
|
60
|
+
getShapeId: (node: T) => string;
|
|
61
|
+
fontSize?: number;
|
|
62
|
+
fontFamily?: string;
|
|
63
|
+
fontWeight?: string | number;
|
|
64
|
+
}): T[];
|
|
65
|
+
//# sourceMappingURL=nodeSizing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeSizing.d.ts","sourceRoot":"","sources":["../../src/layout/nodeSizing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,UAAU,EAEX,MAAM,aAAa,CAAC;AA6CrB;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,cAAc,CA8CvE;AAmHD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CA8E1E;AAuBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC/C,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B,GACA,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA4BhD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EACzG,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE;IACP,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B,GACA,CAAC,EAAE,CA6BL"}
|