@zukhruf/diagram 0.3.33 → 0.3.34
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 +98 -52
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/compiler/diagram-compile.d.ts +3 -4
- package/dist/lib/compiler/diagram-compile.d.ts.map +1 -1
- package/dist/lib/compiler/diagram-compile.js +85 -370
- package/dist/lib/compiler/diagram-compile.js.map +1 -1
- package/dist/lib/layouts/graph/attach.d.ts.map +1 -1
- package/dist/lib/layouts/graph/attach.js +64 -8
- package/dist/lib/layouts/graph/attach.js.map +1 -1
- package/dist/lib/layouts/graph/connections.d.ts +11 -4
- package/dist/lib/layouts/graph/connections.d.ts.map +1 -1
- package/dist/lib/layouts/graph/connections.js +43 -17
- package/dist/lib/layouts/graph/connections.js.map +1 -1
- package/dist/lib/layouts/graph/graph-layout-result.d.ts +4 -2
- package/dist/lib/layouts/graph/graph-layout-result.d.ts.map +1 -1
- package/dist/lib/layouts/graph/graph-layout-result.js.map +1 -1
- package/dist/lib/layouts/graph/gutters.js +40 -21
- package/dist/lib/layouts/graph/gutters.js.map +1 -1
- package/dist/lib/layouts/graph/labels.d.ts +16 -9
- package/dist/lib/layouts/graph/labels.d.ts.map +1 -1
- package/dist/lib/layouts/graph/labels.js +62 -18
- package/dist/lib/layouts/graph/labels.js.map +1 -1
- package/dist/lib/layouts/graph/layout.d.ts +1 -1
- package/dist/lib/layouts/graph/layout.d.ts.map +1 -1
- package/dist/lib/layouts/graph/layout.js +6 -3
- package/dist/lib/layouts/graph/layout.js.map +1 -1
- package/dist/lib/layouts/graph/measure.d.ts +8 -5
- package/dist/lib/layouts/graph/measure.d.ts.map +1 -1
- package/dist/lib/layouts/graph/measure.js +47 -9
- package/dist/lib/layouts/graph/measure.js.map +1 -1
- package/dist/lib/layouts/graph/min-heap.d.ts +1 -5
- package/dist/lib/layouts/graph/min-heap.d.ts.map +1 -1
- package/dist/lib/layouts/graph/min-heap.js +1 -5
- package/dist/lib/layouts/graph/min-heap.js.map +1 -1
- package/dist/lib/layouts/graph/node-content.d.ts +1 -1
- package/dist/lib/layouts/graph/node-content.d.ts.map +1 -1
- package/dist/lib/layouts/graph/node-content.js +26 -7
- package/dist/lib/layouts/graph/node-content.js.map +1 -1
- package/dist/lib/layouts/graph/path.d.ts +2 -10
- package/dist/lib/layouts/graph/path.d.ts.map +1 -1
- package/dist/lib/layouts/graph/path.js +11 -13
- package/dist/lib/layouts/graph/path.js.map +1 -1
- package/dist/lib/layouts/graph/round.d.ts +11 -0
- package/dist/lib/layouts/graph/round.d.ts.map +1 -0
- package/dist/lib/layouts/graph/round.js +181 -0
- package/dist/lib/layouts/graph/round.js.map +1 -0
- package/dist/lib/layouts/graph/route.d.ts +10 -6
- package/dist/lib/layouts/graph/route.d.ts.map +1 -1
- package/dist/lib/layouts/graph/route.js +68 -33
- package/dist/lib/layouts/graph/route.js.map +1 -1
- package/dist/lib/layouts/graph/sides.d.ts +10 -5
- package/dist/lib/layouts/graph/sides.d.ts.map +1 -1
- package/dist/lib/layouts/graph/sides.js +14 -7
- package/dist/lib/layouts/graph/sides.js.map +1 -1
- package/dist/lib/layouts/timeline/timeline-layout.d.ts +2 -1
- package/dist/lib/layouts/timeline/timeline-layout.d.ts.map +1 -1
- package/dist/lib/layouts/timeline/timeline-layout.js +9 -4
- package/dist/lib/layouts/timeline/timeline-layout.js.map +1 -1
- package/dist/lib/model/diagram-ir.d.ts +19 -156
- package/dist/lib/model/diagram-ir.d.ts.map +1 -1
- package/dist/lib/model/diagram-ir.js.map +1 -1
- package/dist/lib/model/validate-graph.d.ts +7 -0
- package/dist/lib/model/validate-graph.d.ts.map +1 -0
- package/dist/lib/model/validate-graph.js +54 -0
- package/dist/lib/model/validate-graph.js.map +1 -0
- package/dist/lib/react/Diagram.d.ts +3 -9
- package/dist/lib/react/Diagram.d.ts.map +1 -1
- package/dist/lib/react/Diagram.js +1 -13
- package/dist/lib/react/Diagram.js.map +1 -1
- package/dist/lib/react/diagram-types.d.ts +17 -46
- package/dist/lib/react/diagram-types.d.ts.map +1 -1
- package/dist/lib/react/diagram-types.js.map +1 -1
- package/dist/lib/renderers/canvas/graph-canvas.d.ts +2 -5
- package/dist/lib/renderers/canvas/graph-canvas.d.ts.map +1 -1
- package/dist/lib/renderers/canvas/graph-canvas.js +68 -43
- package/dist/lib/renderers/canvas/graph-canvas.js.map +1 -1
- package/dist/lib/renderers/html/graph-html.d.ts +2 -3
- package/dist/lib/renderers/html/graph-html.d.ts.map +1 -1
- package/dist/lib/renderers/html/graph-html.js +298 -289
- package/dist/lib/renderers/html/graph-html.js.map +1 -1
- package/dist/lib/renderers/shared/graph-parts.d.ts +3 -1
- package/dist/lib/renderers/shared/graph-parts.d.ts.map +1 -1
- package/dist/lib/renderers/shared/graph-parts.js +350 -418
- package/dist/lib/renderers/shared/graph-parts.js.map +1 -1
- package/dist/lib/renderers/shared/node-parts.d.ts +5 -6
- package/dist/lib/renderers/shared/node-parts.d.ts.map +1 -1
- package/dist/lib/renderers/shared/node-parts.js +112 -190
- package/dist/lib/renderers/shared/node-parts.js.map +1 -1
- package/dist/lib/renderers/shared/run-spans.js +2 -2
- package/dist/lib/renderers/shared/run-spans.js.map +1 -1
- package/dist/lib/renderers/shared/text-runs.d.ts +0 -6
- package/dist/lib/renderers/shared/text-runs.d.ts.map +1 -1
- package/dist/lib/renderers/shared/text-runs.js +0 -12
- package/dist/lib/renderers/shared/text-runs.js.map +1 -1
- package/dist/lib/renderers/svg/graph-svg.d.ts +1 -3
- package/dist/lib/renderers/svg/graph-svg.d.ts.map +1 -1
- package/dist/lib/renderers/svg/graph-svg.js +66 -80
- package/dist/lib/renderers/svg/graph-svg.js.map +1 -1
- package/dist/lib/renderers/svg/timeline-svg.d.ts.map +1 -1
- package/dist/lib/renderers/svg/timeline-svg.js +7 -5
- package/dist/lib/renderers/svg/timeline-svg.js.map +1 -1
- package/package.json +1 -1
- package/dist/lib/layouts/graph/graph-layout.d.ts +0 -154
- package/dist/lib/layouts/graph/graph-layout.d.ts.map +0 -1
- package/dist/lib/layouts/graph/graph-layout.js +0 -2340
- package/dist/lib/layouts/graph/graph-layout.js.map +0 -1
- package/dist/lib/layouts/graph/legacy-graph-layout.d.ts +0 -6
- package/dist/lib/layouts/graph/legacy-graph-layout.d.ts.map +0 -1
- package/dist/lib/layouts/graph/legacy-graph-layout.js +0 -542
- package/dist/lib/layouts/graph/legacy-graph-layout.js.map +0 -1
- package/dist/lib/layouts/text-metrics.d.ts +0 -7
- package/dist/lib/layouts/text-metrics.d.ts.map +0 -1
- package/dist/lib/layouts/text-metrics.js +0 -40
- package/dist/lib/layouts/text-metrics.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Children, Fragment, isValidElement } from 'react';
|
|
2
|
-
import { parseEndpointRef } from "../model/endpoint-ref.js";
|
|
3
2
|
export const DIAGRAM_PRIMITIVE = Symbol.for('@zukhruf/diagram/primitive');
|
|
4
|
-
const PRIMITIVE_KINDS = ['node', 'box', 'card', 'port', 'label', 'float', '
|
|
3
|
+
const PRIMITIVE_KINDS = ['node', 'box', 'card', 'port', 'label', 'float', 'appliance', 'connector', 'junction', 'edge', 'arrow', 'wire', 'group', 'note', 'line', 'lane', 'signal', 'frame', 'marker', 'content'];
|
|
5
4
|
export function primitive(kind) {
|
|
6
5
|
return Object.assign(() => null, {
|
|
7
6
|
[DIAGRAM_PRIMITIVE]: kind
|
|
@@ -24,24 +23,20 @@ function emptyCompileResult() {
|
|
|
24
23
|
nodes: [],
|
|
25
24
|
edges: [],
|
|
26
25
|
groups: [],
|
|
27
|
-
annotations: [],
|
|
28
26
|
lanes: [],
|
|
29
27
|
signals: [],
|
|
30
|
-
frames: []
|
|
31
|
-
guides: []
|
|
28
|
+
frames: []
|
|
32
29
|
};
|
|
33
30
|
}
|
|
34
31
|
function mergeCompileResults(target, source) {
|
|
35
32
|
target.nodes.push(...source.nodes);
|
|
36
33
|
target.edges.push(...source.edges);
|
|
37
34
|
target.groups.push(...source.groups);
|
|
38
|
-
target.annotations.push(...source.annotations);
|
|
39
35
|
target.lanes.push(...source.lanes);
|
|
40
36
|
target.signals.push(...source.signals);
|
|
41
37
|
target.frames.push(...source.frames);
|
|
42
|
-
target.guides.push(...source.guides);
|
|
43
38
|
}
|
|
44
|
-
export function compileGraph(children
|
|
39
|
+
export function compileGraph(children) {
|
|
45
40
|
const result = compileChildren(children, {});
|
|
46
41
|
if (result.lanes.length > 0 || result.signals.length > 0 || result.frames.length > 0) {
|
|
47
42
|
throw new Error('A graph diagram cannot contain Diagram.Lane, Diagram.Signal or Diagram.Frame; draw those with SvgTimelineDiagram.');
|
|
@@ -49,15 +44,12 @@ export function compileGraph(children, layout) {
|
|
|
49
44
|
return {
|
|
50
45
|
nodes: result.nodes,
|
|
51
46
|
edges: result.edges,
|
|
52
|
-
groups: result.groups
|
|
53
|
-
annotations: result.annotations,
|
|
54
|
-
guides: result.guides,
|
|
55
|
-
layout
|
|
47
|
+
groups: result.groups
|
|
56
48
|
};
|
|
57
49
|
}
|
|
58
50
|
export function compileTimeline(children) {
|
|
59
51
|
const result = compileChildren(children, {});
|
|
60
|
-
if (result.nodes.length > 0 || result.edges.length > 0 || result.groups.length > 0
|
|
52
|
+
if (result.nodes.length > 0 || result.edges.length > 0 || result.groups.length > 0) {
|
|
61
53
|
throw new Error('A timeline diagram only accepts Diagram.Lane, Diagram.Signal and Diagram.Frame; draw other primitives with SvgGraphDiagram or CanvasGraphDiagram.');
|
|
62
54
|
}
|
|
63
55
|
return {
|
|
@@ -99,10 +91,6 @@ function compileChildren(children, context) {
|
|
|
99
91
|
mergeCompileResults(result, group.children);
|
|
100
92
|
return;
|
|
101
93
|
}
|
|
102
|
-
if (kind === 'text') {
|
|
103
|
-
result.annotations.push(compileText(child));
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
94
|
if (kind === 'lane') {
|
|
107
95
|
result.lanes.push(compileLane(child));
|
|
108
96
|
return;
|
|
@@ -118,10 +106,6 @@ function compileChildren(children, context) {
|
|
|
118
106
|
result.frames.push(compileFrame(child));
|
|
119
107
|
return;
|
|
120
108
|
}
|
|
121
|
-
if (kind === 'guide') {
|
|
122
|
-
result.guides.push(requirePrimitiveProps(child));
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
109
|
throw new Error(`<Diagram.${kind}> cannot be a direct child of Diagram.`);
|
|
126
110
|
});
|
|
127
111
|
return result;
|
|
@@ -130,7 +114,7 @@ function isTextNode(child) {
|
|
|
130
114
|
return typeof child === 'string' || typeof child === 'number';
|
|
131
115
|
}
|
|
132
116
|
function isNodeKind(kind) {
|
|
133
|
-
return kind === 'node' || kind === 'box' || kind === 'card' || kind === 'port' || kind === 'label' || kind === 'float' || kind === '
|
|
117
|
+
return kind === 'node' || kind === 'box' || kind === 'card' || kind === 'port' || kind === 'label' || kind === 'float' || kind === 'note' || kind === 'appliance' || kind === 'connector' || kind === 'junction' || kind === 'marker';
|
|
134
118
|
}
|
|
135
119
|
function isEdgeKind(kind) {
|
|
136
120
|
return kind === 'edge' || kind === 'arrow' || kind === 'wire';
|
|
@@ -144,182 +128,97 @@ function requirePrimitiveProps(child) {
|
|
|
144
128
|
return child.props;
|
|
145
129
|
}
|
|
146
130
|
function compileNode(kind, child, context) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
131
|
+
const group = context.groupId === undefined ? {} : {
|
|
132
|
+
group: context.groupId
|
|
133
|
+
};
|
|
134
|
+
if (kind === 'note') {
|
|
135
|
+
const {
|
|
136
|
+
children,
|
|
137
|
+
...props
|
|
138
|
+
} = requirePrimitiveProps(child);
|
|
151
139
|
return {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
height: props.height ?? 1,
|
|
158
|
-
...(props.group ?? context.groupId ? {
|
|
159
|
-
group: props.group ?? context.groupId
|
|
160
|
-
} : {}),
|
|
161
|
-
frame: 'none',
|
|
162
|
-
hidden: props.hidden ?? !hasLabel,
|
|
163
|
-
...(props.fontSize ? {
|
|
164
|
-
fontSize: props.fontSize
|
|
165
|
-
} : {}),
|
|
166
|
-
...(props.fontWeight ? {
|
|
167
|
-
fontWeight: props.fontWeight
|
|
168
|
-
} : {}),
|
|
169
|
-
...(props.textColor ? {
|
|
170
|
-
textColor: props.textColor
|
|
171
|
-
} : {}),
|
|
172
|
-
...(props.accent !== undefined ? {
|
|
173
|
-
accent: props.accent
|
|
174
|
-
} : {}),
|
|
175
|
-
...(props.textAlign ? {
|
|
176
|
-
textAlign: props.textAlign
|
|
177
|
-
} : {}),
|
|
178
|
-
...(props.connectable !== undefined ? {
|
|
179
|
-
connectable: props.connectable
|
|
180
|
-
} : {})
|
|
140
|
+
...props,
|
|
141
|
+
kind: 'note',
|
|
142
|
+
label: nodeLabel(children, 'Diagram.Note'),
|
|
143
|
+
...group,
|
|
144
|
+
frame: 'none'
|
|
181
145
|
};
|
|
182
146
|
}
|
|
183
147
|
if (kind === 'junction') {
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
148
|
+
const {
|
|
149
|
+
children,
|
|
150
|
+
...props
|
|
151
|
+
} = requirePrimitiveProps(child);
|
|
187
152
|
return {
|
|
188
|
-
|
|
153
|
+
...props,
|
|
189
154
|
kind: 'junction',
|
|
190
|
-
label:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
width: props.width ?? 16,
|
|
194
|
-
height: props.height ?? 16,
|
|
195
|
-
...(group ? {
|
|
196
|
-
group
|
|
197
|
-
} : {}),
|
|
198
|
-
frame: 'none',
|
|
199
|
-
connectable: true,
|
|
200
|
-
hidden: props.hidden,
|
|
201
|
-
accent: props.accent,
|
|
202
|
-
tone: props.tone,
|
|
203
|
-
fontSize: props.fontSize,
|
|
204
|
-
fontWeight: props.fontWeight,
|
|
205
|
-
textColor: props.textColor,
|
|
206
|
-
caption: props.caption,
|
|
207
|
-
captionSide: props.captionSide,
|
|
208
|
-
captionOffset: props.captionOffset,
|
|
209
|
-
captionColor: props.captionColor,
|
|
210
|
-
captionFontSize: props.captionFontSize,
|
|
211
|
-
captionFontWeight: props.captionFontWeight
|
|
155
|
+
label: nodeLabel(children, 'Diagram.Junction'),
|
|
156
|
+
...group,
|
|
157
|
+
frame: 'none'
|
|
212
158
|
};
|
|
213
159
|
}
|
|
214
160
|
if (kind === 'connector') {
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
161
|
+
const {
|
|
162
|
+
children,
|
|
163
|
+
...props
|
|
164
|
+
} = requirePrimitiveProps(child);
|
|
218
165
|
return {
|
|
219
|
-
|
|
166
|
+
...props,
|
|
220
167
|
kind: 'connector',
|
|
221
|
-
label:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
colSpan: props.colSpan,
|
|
225
|
-
width: props.width ?? 148,
|
|
226
|
-
height: props.height ?? 40,
|
|
227
|
-
...(group ? {
|
|
228
|
-
group
|
|
229
|
-
} : {}),
|
|
230
|
-
frame: 'solid',
|
|
231
|
-
connectable: true,
|
|
232
|
-
rx: props.rx ?? 10,
|
|
233
|
-
accent: props.accent,
|
|
234
|
-
tone: props.tone,
|
|
235
|
-
texture: props.texture,
|
|
236
|
-
icon: props.icon,
|
|
237
|
-
iconSize: props.iconSize,
|
|
238
|
-
ports: props.ports,
|
|
239
|
-
fontSize: props.fontSize,
|
|
240
|
-
fontWeight: props.fontWeight,
|
|
241
|
-
textColor: props.textColor,
|
|
242
|
-
caption: props.caption,
|
|
243
|
-
captionSide: props.captionSide,
|
|
244
|
-
captionOffset: props.captionOffset,
|
|
245
|
-
captionColor: props.captionColor,
|
|
246
|
-
captionFontSize: props.captionFontSize,
|
|
247
|
-
captionFontWeight: props.captionFontWeight
|
|
168
|
+
label: nodeLabel(children, 'Diagram.Connector'),
|
|
169
|
+
...group,
|
|
170
|
+
frame: 'solid'
|
|
248
171
|
};
|
|
249
172
|
}
|
|
250
173
|
if (kind === 'appliance') {
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
174
|
+
const {
|
|
175
|
+
children,
|
|
176
|
+
...props
|
|
177
|
+
} = requirePrimitiveProps(child);
|
|
254
178
|
return {
|
|
255
|
-
|
|
179
|
+
...props,
|
|
256
180
|
kind: 'appliance',
|
|
257
|
-
label:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
width: props.width ?? 112,
|
|
261
|
-
height: props.height ?? 72,
|
|
262
|
-
...(group ? {
|
|
263
|
-
group
|
|
264
|
-
} : {}),
|
|
265
|
-
frame: 'none',
|
|
266
|
-
connectable: true,
|
|
267
|
-
accent: props.accent,
|
|
268
|
-
tone: props.tone,
|
|
269
|
-
texture: props.texture,
|
|
270
|
-
ports: props.ports,
|
|
271
|
-
fontSize: props.fontSize,
|
|
272
|
-
fontWeight: props.fontWeight,
|
|
273
|
-
textColor: props.textColor,
|
|
274
|
-
caption: props.caption,
|
|
275
|
-
captionSide: props.captionSide,
|
|
276
|
-
captionOffset: props.captionOffset,
|
|
277
|
-
captionColor: props.captionColor,
|
|
278
|
-
captionFontSize: props.captionFontSize,
|
|
279
|
-
captionFontWeight: props.captionFontWeight,
|
|
280
|
-
appliancePorts: props.appliancePorts,
|
|
281
|
-
antenna: props.antenna,
|
|
282
|
-
slant: props.slant
|
|
181
|
+
label: nodeLabel(children, 'Diagram.Appliance'),
|
|
182
|
+
...group,
|
|
183
|
+
frame: 'none'
|
|
283
184
|
};
|
|
284
185
|
}
|
|
285
|
-
const props = requirePrimitiveProps(child);
|
|
286
186
|
const {
|
|
287
|
-
children
|
|
288
|
-
...
|
|
289
|
-
} =
|
|
187
|
+
children,
|
|
188
|
+
...props
|
|
189
|
+
} = requirePrimitiveProps(child);
|
|
290
190
|
const {
|
|
291
191
|
labelChildren,
|
|
292
192
|
content
|
|
293
|
-
} = splitNodeContent(
|
|
294
|
-
const label = compileLabelChildren(labelChildren, `Diagram.${kind}`);
|
|
295
|
-
const group = nodeProps.group ?? context.groupId;
|
|
193
|
+
} = splitNodeContent(children, kind);
|
|
296
194
|
return {
|
|
297
|
-
...
|
|
298
|
-
label:
|
|
299
|
-
...(content
|
|
300
|
-
content
|
|
195
|
+
...props,
|
|
196
|
+
label: nodeLabel(labelChildren, `Diagram.${kind}`),
|
|
197
|
+
...(content ? {
|
|
198
|
+
content
|
|
301
199
|
} : {}),
|
|
302
200
|
...(kind === 'marker' ? {
|
|
303
|
-
kind: 'marker'
|
|
304
|
-
width: nodeProps.width ?? 72,
|
|
305
|
-
height: nodeProps.height ?? 76
|
|
201
|
+
kind: 'marker'
|
|
306
202
|
} : {}),
|
|
307
|
-
...
|
|
308
|
-
|
|
203
|
+
...group,
|
|
204
|
+
frame: nodeFrame(kind, props.frame),
|
|
205
|
+
...(kind === 'card' ? {
|
|
206
|
+
textAlign: 'start'
|
|
309
207
|
} : {}),
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
connectable: kind === 'float' ? false : nodeProps.connectable,
|
|
314
|
-
...(kind === 'marker' ? {
|
|
315
|
-
frame: nodeProps.frame ?? 'none'
|
|
208
|
+
hidden: kind === 'marker' ? false : props.hidden,
|
|
209
|
+
...(kind === 'float' ? {
|
|
210
|
+
connectable: false
|
|
316
211
|
} : {})
|
|
317
212
|
};
|
|
318
213
|
}
|
|
214
|
+
function nodeLabel(children, owner) {
|
|
215
|
+
const label = compileLabelChildren(children, owner);
|
|
216
|
+
return label.length > 0 ? label : '';
|
|
217
|
+
}
|
|
319
218
|
const CONTENT_HOSTS = new Set(['node', 'box', 'card']);
|
|
320
219
|
function splitNodeContent(children, kind) {
|
|
321
220
|
const labelChildren = [];
|
|
322
|
-
|
|
221
|
+
let content;
|
|
323
222
|
Children.forEach(children, child => {
|
|
324
223
|
if (!isValidElement(child) || primitiveKind(child) !== 'content') {
|
|
325
224
|
labelChildren.push(child);
|
|
@@ -328,10 +227,17 @@ function splitNodeContent(children, kind) {
|
|
|
328
227
|
if (!CONTENT_HOSTS.has(kind)) {
|
|
329
228
|
throw new Error(`Diagram.Content goes inside Diagram.Box, Diagram.Card or Diagram.Node, not Diagram.${kind}.`);
|
|
330
229
|
}
|
|
331
|
-
if (content
|
|
230
|
+
if (content) {
|
|
332
231
|
throw new Error(`Diagram.${kind} accepts one Diagram.Content.`);
|
|
333
232
|
}
|
|
334
|
-
|
|
233
|
+
const {
|
|
234
|
+
children: element,
|
|
235
|
+
size
|
|
236
|
+
} = requirePrimitiveProps(child);
|
|
237
|
+
content = {
|
|
238
|
+
element,
|
|
239
|
+
size
|
|
240
|
+
};
|
|
335
241
|
});
|
|
336
242
|
return {
|
|
337
243
|
labelChildren,
|
|
@@ -348,51 +254,12 @@ function nodeFrame(kind, explicit) {
|
|
|
348
254
|
return 'solid';
|
|
349
255
|
}
|
|
350
256
|
function compileEdge(kind, child) {
|
|
351
|
-
const props = requirePrimitiveProps(child);
|
|
352
257
|
const {
|
|
353
|
-
children
|
|
258
|
+
children,
|
|
354
259
|
badgeLabel,
|
|
355
260
|
...edgeProps
|
|
356
|
-
} =
|
|
357
|
-
const lines =
|
|
358
|
-
const waypoints = [...(props.waypoints ?? [])];
|
|
359
|
-
let entrySide = props.entrySide;
|
|
360
|
-
let exitSide = props.exitSide;
|
|
361
|
-
let entryGap = props.entryGap;
|
|
362
|
-
Children.forEach(props.children, edgeChild => {
|
|
363
|
-
if (edgeChild === null || edgeChild === undefined || typeof edgeChild === 'boolean') return;
|
|
364
|
-
if (isTextNode(edgeChild)) {
|
|
365
|
-
const text = String(edgeChild).trim();
|
|
366
|
-
if (text.length > 0) lines.push(text);
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
if (!isValidElement(edgeChild)) {
|
|
370
|
-
throw new Error('Diagram edges only accept text, Line, Entry, Exit, and Waypoint children.');
|
|
371
|
-
}
|
|
372
|
-
if (edgeChild.type === Fragment) {
|
|
373
|
-
throw new Error('Diagram edges do not accept fragments. Use direct Line/Entry/Exit/Waypoint children.');
|
|
374
|
-
}
|
|
375
|
-
const edgeChildKind = primitiveKind(edgeChild);
|
|
376
|
-
if (edgeChildKind === 'line') {
|
|
377
|
-
lines.push(lineText(edgeChild));
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
if (edgeChildKind === 'entry') {
|
|
381
|
-
const entry = requirePrimitiveProps(edgeChild);
|
|
382
|
-
entrySide = entry.side;
|
|
383
|
-
entryGap = entry.gap ?? entryGap;
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
if (edgeChildKind === 'exit') {
|
|
387
|
-
exitSide = requirePrimitiveProps(edgeChild).side;
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
if (edgeChildKind === 'waypoint') {
|
|
391
|
-
waypoints.push(requirePrimitiveProps(edgeChild));
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
throw new Error(`Diagram edge cannot contain <Diagram.${edgeChildKind ?? 'Unknown'}>.`);
|
|
395
|
-
});
|
|
261
|
+
} = requirePrimitiveProps(child);
|
|
262
|
+
const lines = compileStringLines(children, `Diagram.${kind}`);
|
|
396
263
|
return {
|
|
397
264
|
...edgeProps,
|
|
398
265
|
...(lines.length > 0 ? {
|
|
@@ -401,18 +268,6 @@ function compileEdge(kind, child) {
|
|
|
401
268
|
...(badgeLabel !== undefined ? {
|
|
402
269
|
badgeLabel: normalizeStringLines(badgeLabel)
|
|
403
270
|
} : {}),
|
|
404
|
-
...(waypoints.length > 0 ? {
|
|
405
|
-
waypoints
|
|
406
|
-
} : {}),
|
|
407
|
-
...(entrySide ? {
|
|
408
|
-
entrySide
|
|
409
|
-
} : {}),
|
|
410
|
-
...(exitSide ? {
|
|
411
|
-
exitSide
|
|
412
|
-
} : {}),
|
|
413
|
-
...(entryGap !== undefined ? {
|
|
414
|
-
entryGap
|
|
415
|
-
} : {}),
|
|
416
271
|
headless: kind === 'wire' ? true : edgeProps.headless
|
|
417
272
|
};
|
|
418
273
|
}
|
|
@@ -420,39 +275,20 @@ function normalizeStringLines(value) {
|
|
|
420
275
|
return (Array.isArray(value) ? value : [value]).map(line => line.trim()).filter(Boolean);
|
|
421
276
|
}
|
|
422
277
|
function compileGroup(child, context) {
|
|
423
|
-
const
|
|
424
|
-
|
|
278
|
+
const {
|
|
279
|
+
children: groupChildren,
|
|
280
|
+
label,
|
|
281
|
+
...props
|
|
282
|
+
} = requirePrimitiveProps(child);
|
|
283
|
+
const children = compileChildren(groupChildren, {
|
|
425
284
|
...context,
|
|
426
285
|
groupId: props.id
|
|
427
286
|
});
|
|
428
|
-
const bounds = props.rowStart !== undefined && props.rowEnd !== undefined && props.colStart !== undefined && props.colEnd !== undefined ? {
|
|
429
|
-
rowStart: props.rowStart,
|
|
430
|
-
rowEnd: props.rowEnd,
|
|
431
|
-
colStart: props.colStart,
|
|
432
|
-
colEnd: props.colEnd
|
|
433
|
-
} : inferGroupBounds(props.id, children.nodes, children.groups);
|
|
434
287
|
return {
|
|
435
288
|
group: {
|
|
436
|
-
|
|
437
|
-
label: normalizeGroupLabel(
|
|
438
|
-
|
|
439
|
-
labelSide: props.labelSide,
|
|
440
|
-
accent: props.accent,
|
|
441
|
-
tone: props.tone,
|
|
442
|
-
texture: props.texture,
|
|
443
|
-
rx: props.rx,
|
|
444
|
-
frame: props.frame,
|
|
445
|
-
fill: props.fill,
|
|
446
|
-
ports: props.ports,
|
|
447
|
-
parent: context.groupId,
|
|
448
|
-
tight: props.tight,
|
|
449
|
-
tightX: props.tightX,
|
|
450
|
-
tightY: props.tightY,
|
|
451
|
-
titleBand: props.titleBand,
|
|
452
|
-
titleGap: props.titleGap,
|
|
453
|
-
padding: props.padding,
|
|
454
|
-
dividers: props.dividers,
|
|
455
|
-
bounds
|
|
289
|
+
...props,
|
|
290
|
+
label: normalizeGroupLabel(label),
|
|
291
|
+
parent: context.groupId
|
|
456
292
|
},
|
|
457
293
|
children
|
|
458
294
|
};
|
|
@@ -463,54 +299,6 @@ function normalizeGroupLabel(label) {
|
|
|
463
299
|
}
|
|
464
300
|
return label?.trim() ?? '';
|
|
465
301
|
}
|
|
466
|
-
function inferGroupBounds(groupId, nodes, groups = []) {
|
|
467
|
-
const grouped = nodes.filter(node => node.group === groupId);
|
|
468
|
-
const childGroups = groups.filter(group => group.parent === groupId);
|
|
469
|
-
if (grouped.length === 0 && childGroups.length === 0) {
|
|
470
|
-
throw new Error(`Diagram.Group "${groupId}" needs bounds or direct node/group children so bounds can be inferred.`);
|
|
471
|
-
}
|
|
472
|
-
const bounds = emptyGroupBounds();
|
|
473
|
-
for (const node of grouped) {
|
|
474
|
-
if (node.row === undefined || node.col === undefined) return undefined;
|
|
475
|
-
includeGroupBounds(bounds, {
|
|
476
|
-
rowStart: node.row,
|
|
477
|
-
rowEnd: node.row,
|
|
478
|
-
colStart: node.col,
|
|
479
|
-
colEnd: node.col + (node.colSpan ?? 1) - 1
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
for (const group of childGroups) {
|
|
483
|
-
if (!group.bounds) return undefined;
|
|
484
|
-
includeGroupBounds(bounds, group.bounds);
|
|
485
|
-
}
|
|
486
|
-
return bounds;
|
|
487
|
-
}
|
|
488
|
-
function emptyGroupBounds() {
|
|
489
|
-
return {
|
|
490
|
-
rowStart: Number.POSITIVE_INFINITY,
|
|
491
|
-
rowEnd: Number.NEGATIVE_INFINITY,
|
|
492
|
-
colStart: Number.POSITIVE_INFINITY,
|
|
493
|
-
colEnd: Number.NEGATIVE_INFINITY
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
function includeGroupBounds(target, source) {
|
|
497
|
-
target.rowStart = Math.min(target.rowStart, source.rowStart);
|
|
498
|
-
target.rowEnd = Math.max(target.rowEnd, source.rowEnd);
|
|
499
|
-
target.colStart = Math.min(target.colStart, source.colStart);
|
|
500
|
-
target.colEnd = Math.max(target.colEnd, source.colEnd);
|
|
501
|
-
}
|
|
502
|
-
function compileText(child) {
|
|
503
|
-
const props = requirePrimitiveProps(child);
|
|
504
|
-
const {
|
|
505
|
-
children: _children,
|
|
506
|
-
...textProps
|
|
507
|
-
} = props;
|
|
508
|
-
const lines = compileStringLines(props.children, 'Diagram.Text');
|
|
509
|
-
return {
|
|
510
|
-
...textProps,
|
|
511
|
-
text: lines.length > 0 ? lines : ['']
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
302
|
function compileLane(child) {
|
|
515
303
|
const props = requirePrimitiveProps(child);
|
|
516
304
|
return {
|
|
@@ -619,79 +407,6 @@ function lineText(child) {
|
|
|
619
407
|
return String(part).trim();
|
|
620
408
|
}).filter(Boolean).join('');
|
|
621
409
|
}
|
|
622
|
-
export function validateGraph(ir) {
|
|
623
|
-
const nodeIds = new Set();
|
|
624
|
-
for (const node of ir.nodes) {
|
|
625
|
-
if (nodeIds.has(node.id)) throw new Error(`Duplicate Diagram node id "${node.id}".`);
|
|
626
|
-
nodeIds.add(node.id);
|
|
627
|
-
}
|
|
628
|
-
const groupIds = new Set();
|
|
629
|
-
for (const group of ir.groups) {
|
|
630
|
-
if (groupIds.has(group.id)) throw new Error(`Duplicate Diagram group id "${group.id}".`);
|
|
631
|
-
groupIds.add(group.id);
|
|
632
|
-
}
|
|
633
|
-
const guideIds = new Set();
|
|
634
|
-
for (const guide of ir.guides) {
|
|
635
|
-
if (!guide.id) continue;
|
|
636
|
-
if (guideIds.has(guide.id)) throw new Error(`Duplicate Diagram guide id "${guide.id}".`);
|
|
637
|
-
guideIds.add(guide.id);
|
|
638
|
-
}
|
|
639
|
-
const nodesById = new Map(ir.nodes.map(node => [node.id, node]));
|
|
640
|
-
const groupsById = new Map(ir.groups.map(group => [group.id, group]));
|
|
641
|
-
for (const node of ir.nodes) {
|
|
642
|
-
if (groupsById.has(node.id)) {
|
|
643
|
-
throw new Error(`Diagram node id "${node.id}" conflicts with a Diagram group id. Node and group endpoint ids must be unique.`);
|
|
644
|
-
}
|
|
645
|
-
if (node.bodyFontSize !== undefined && (!Number.isFinite(node.bodyFontSize) || node.bodyFontSize <= 0)) {
|
|
646
|
-
throw new Error(`Diagram node "${node.id}" bodyFontSize must be a positive finite number, got ${node.bodyFontSize}.`);
|
|
647
|
-
}
|
|
648
|
-
if (node.bodyLineGap !== undefined && (!Number.isFinite(node.bodyLineGap) || node.bodyLineGap < 0)) {
|
|
649
|
-
throw new Error(`Diagram node "${node.id}" bodyLineGap must be a non-negative finite number, got ${node.bodyLineGap}.`);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
for (const edge of ir.edges) {
|
|
653
|
-
if (edge.route !== undefined && edge.route !== 'orthogonal' && edge.route !== 'straight') {
|
|
654
|
-
throw new Error(`Diagram edge route must be "orthogonal" or "straight", got "${edge.route}".`);
|
|
655
|
-
}
|
|
656
|
-
if (edge.labelLineGap !== undefined && (!Number.isFinite(edge.labelLineGap) || edge.labelLineGap < 0)) {
|
|
657
|
-
throw new Error(`Diagram edge labelLineGap must be a non-negative finite number, got ${edge.labelLineGap}.`);
|
|
658
|
-
}
|
|
659
|
-
if (edge.exitOffset !== undefined && !Number.isFinite(edge.exitOffset)) {
|
|
660
|
-
throw new Error(`Diagram edge exitOffset must be a finite number, got ${edge.exitOffset}.`);
|
|
661
|
-
}
|
|
662
|
-
if (edge.entryOffset !== undefined && !Number.isFinite(edge.entryOffset)) {
|
|
663
|
-
throw new Error(`Diagram edge entryOffset must be a finite number, got ${edge.entryOffset}.`);
|
|
664
|
-
}
|
|
665
|
-
if (edge.stubDistance !== undefined && (!Number.isFinite(edge.stubDistance) || edge.stubDistance < 0)) {
|
|
666
|
-
throw new Error(`Diagram edge stubDistance must be a non-negative finite number, got ${edge.stubDistance}.`);
|
|
667
|
-
}
|
|
668
|
-
const {
|
|
669
|
-
nodeId: sourceNodeId,
|
|
670
|
-
portId: sourcePortId
|
|
671
|
-
} = parseEndpointRef(edge.from);
|
|
672
|
-
const {
|
|
673
|
-
nodeId: targetNodeId,
|
|
674
|
-
portId: targetPortId
|
|
675
|
-
} = parseEndpointRef(edge.to);
|
|
676
|
-
if (!nodeIds.has(sourceNodeId) && !groupsById.has(sourceNodeId)) {
|
|
677
|
-
throw new Error(`Diagram edge ${edge.from}->${edge.to} references missing source "${sourceNodeId}".`);
|
|
678
|
-
}
|
|
679
|
-
if (!nodeIds.has(targetNodeId) && !groupsById.has(targetNodeId)) {
|
|
680
|
-
throw new Error(`Diagram edge ${edge.from}->${edge.to} references missing target "${targetNodeId}".`);
|
|
681
|
-
}
|
|
682
|
-
if (sourcePortId && !(nodesById.get(sourceNodeId)?.ports?.some(port => port.id === sourcePortId) || groupsById.get(sourceNodeId)?.ports?.some(port => port.id === sourcePortId))) {
|
|
683
|
-
throw new Error(`Diagram edge ${edge.from}->${edge.to} references missing source port "${sourcePortId}" on "${sourceNodeId}".`);
|
|
684
|
-
}
|
|
685
|
-
if (targetPortId && !(nodesById.get(targetNodeId)?.ports?.some(port => port.id === targetPortId) || groupsById.get(targetNodeId)?.ports?.some(port => port.id === targetPortId))) {
|
|
686
|
-
throw new Error(`Diagram edge ${edge.from}->${edge.to} references missing target port "${targetPortId}" on "${targetNodeId}".`);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
for (const annotation of ir.annotations) {
|
|
690
|
-
if (annotation.lineGap !== undefined && (!Number.isFinite(annotation.lineGap) || annotation.lineGap < 0)) {
|
|
691
|
-
throw new Error(`Diagram.Text lineGap must be a non-negative finite number, got ${annotation.lineGap}.`);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
410
|
export function validateTimeline(ir) {
|
|
696
411
|
const laneIds = new Set();
|
|
697
412
|
for (const lane of ir.lanes) {
|