@weasel-js/diagram 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -17
- package/dist/{chunk-Y72FK3Y7.js → chunk-5VNPLOIX.js} +94 -6
- package/dist/chunk-5VNPLOIX.js.map +1 -0
- package/dist/{chunk-ESFIS7BB.js → chunk-62SMY45E.js} +918 -574
- package/dist/chunk-62SMY45E.js.map +1 -0
- package/dist/{chunk-FAQXYGMX.js → chunk-TBG6DFB2.js} +3 -3
- package/dist/{chunk-FAQXYGMX.js.map → chunk-TBG6DFB2.js.map} +1 -1
- package/dist/{chunk-L4H444QI.js → chunk-VB6HUKNG.js} +659 -185
- package/dist/chunk-VB6HUKNG.js.map +1 -0
- package/dist/{chunk-QU4QZUC6.js → chunk-ZWXM5F4I.js} +141 -39
- package/dist/chunk-ZWXM5F4I.js.map +1 -0
- package/dist/{dataTypes-DW-MljuN.d.ts → dataTypes-BIkhAOc4.d.ts} +13 -2
- package/dist/effect-audio.d.ts +2 -1
- package/dist/effect-audio.js +6 -5
- package/dist/effect-audio.js.map +1 -1
- package/dist/effect.d.ts +46 -16
- package/dist/effect.js +257 -102
- package/dist/effect.js.map +1 -1
- package/dist/icons.table.js +262 -0
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +262 -0
- package/dist/index.d.ts +491 -167
- package/dist/index.js +586 -36
- package/dist/index.js.map +1 -1
- package/dist/labelTrait-BBjRgxbz.d.ts +44 -0
- package/dist/layout.d.ts +4 -3
- package/dist/{layout.entry-CQoPNfzA.d.ts → layout.entry-Ca6pVvqo.d.ts} +23 -2
- package/dist/layout.js +2 -2
- package/dist/{stageTypes-DvnR8cKQ.d.ts → stageTypes-UiO25hcn.d.ts} +7 -0
- package/dist/{types-vbW21fHm.d.ts → types-B0n2CNTW.d.ts} +108 -81
- package/package.json +11 -9
- package/dist/chunk-ESFIS7BB.js.map +0 -1
- package/dist/chunk-L4H444QI.js.map +0 -1
- package/dist/chunk-QU4QZUC6.js.map +0 -1
- package/dist/chunk-Y72FK3Y7.js.map +0 -1
|
@@ -1,57 +1,100 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { boundsOfPath, transformPath, ellipsePath, polylineFromPoints, pathFromD, worldCoords, PATH_M as PATH_M$1, PATH_CMD_LENGTHS, measurePath, forEachSegment, PATH_L as PATH_L$1, nearestOnLine, PATH_Q as PATH_Q$1, nearestOnQuadratic, PATH_C as PATH_C$1, nearestOnCubic } from '@weasel-js/geom';
|
|
2
|
+
import { PathBuilder, rectPath, polygonFromPoints, AUTO_POSE_DESCRIPTOR, rotatePoint, PATH_M, PATH_L, PATH_C, flattenCubic, PATH_Q, PATH_Z, pointAlongPath } from '@weasel-js/core/math';
|
|
3
3
|
import { cssFamilyName } from '@weasel-js/font/metrics';
|
|
4
4
|
import { createSimulation } from '@weasel-js/simulation';
|
|
5
5
|
|
|
6
|
-
// src/
|
|
6
|
+
// src/outlines/fromD.ts
|
|
7
|
+
var unitMatrix = (b) => [b.width, 0, 0, b.height, b.x, b.y];
|
|
8
|
+
function outlineFromD(d, opts = {}) {
|
|
9
|
+
const path = pathFromD(d);
|
|
10
|
+
const detail = opts.detail === void 0 ? void 0 : pathFromD(opts.detail);
|
|
11
|
+
const unit = opts.content ?? { x: 0, y: 0, width: 1, height: 1 };
|
|
12
|
+
return {
|
|
13
|
+
path: (b) => transformPath(path, unitMatrix(b)),
|
|
14
|
+
...detail ? { detail: (b) => transformPath(detail, unitMatrix(b)) } : {},
|
|
15
|
+
content: (b) => ({
|
|
16
|
+
x: b.x + unit.x * b.width,
|
|
17
|
+
y: b.y + unit.y * b.height,
|
|
18
|
+
width: unit.width * b.width,
|
|
19
|
+
height: unit.height * b.height
|
|
20
|
+
}),
|
|
21
|
+
boxForContent: (c) => ({ width: c.width / unit.width, height: c.height / unit.height })
|
|
22
|
+
};
|
|
23
|
+
}
|
|
7
24
|
var LEAN = 0.2;
|
|
8
25
|
var POINT = 0.2;
|
|
9
26
|
var KAPPA = 0.5522847498307936;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
27
|
+
var rect = {
|
|
28
|
+
path: ({ x, y, width, height }) => rectPath(x, y, width, height)
|
|
29
|
+
};
|
|
30
|
+
var diamond = {
|
|
31
|
+
path: ({ x, y, width: w, height: h }) => polygonFromPoints([
|
|
32
|
+
{ x: x + w / 2, y },
|
|
33
|
+
{ x: x + w, y: y + h / 2 },
|
|
34
|
+
{ x: x + w / 2, y: y + h },
|
|
35
|
+
{ x, y: y + h / 2 }
|
|
36
|
+
]),
|
|
37
|
+
// Half the width and half the height, centered: the inscribed rect.
|
|
38
|
+
content: ({ x, y, width: w, height: h }) => ({ x: x + w / 4, y: y + h / 4, width: w / 2, height: h / 2 }),
|
|
39
|
+
boxForContent: (c) => ({ width: c.width * 2, height: c.height * 2 })
|
|
40
|
+
};
|
|
41
|
+
var leanOf = (w) => Math.min(w * LEAN, w / 2);
|
|
42
|
+
var parallelogram = {
|
|
43
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
44
|
+
const lean = leanOf(w);
|
|
45
|
+
return polygonFromPoints([
|
|
46
|
+
{ x: x + lean, y },
|
|
47
|
+
{ x: x + w, y },
|
|
48
|
+
{ x: x + w - lean, y: y + h },
|
|
49
|
+
{ x, y: y + h }
|
|
50
|
+
]);
|
|
51
|
+
},
|
|
52
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
53
|
+
const lean = leanOf(w);
|
|
54
|
+
return { x: x + lean, y, width: Math.max(w - lean * 2, 0), height: h };
|
|
55
|
+
},
|
|
56
|
+
boxForContent: (c) => ({ width: c.width / (1 - LEAN * 2), height: c.height })
|
|
57
|
+
};
|
|
58
|
+
var trapezoid = {
|
|
59
|
+
path: ({ x, y, width: w, height: h }) => polygonFromPoints([
|
|
60
|
+
{ x, y: y + h / 4 },
|
|
61
|
+
{ x: x + w, y },
|
|
62
|
+
{ x: x + w, y: y + h },
|
|
63
|
+
{ x, y: y + h * 3 / 4 }
|
|
64
|
+
]),
|
|
65
|
+
content: ({ x, y, width: w, height: h }) => ({ x, y: y + h / 4, width: w, height: h / 2 }),
|
|
66
|
+
boxForContent: (c) => ({ width: c.width, height: c.height * 2 })
|
|
67
|
+
};
|
|
68
|
+
var hexagon = {
|
|
69
|
+
path: ({ x, y, width: w, height: h }) => polygonFromPoints([
|
|
70
|
+
{ x, y: y + h / 2 },
|
|
71
|
+
{ x: x + w * POINT, y },
|
|
72
|
+
{ x: x + w * (1 - POINT), y },
|
|
73
|
+
{ x: x + w, y: y + h / 2 },
|
|
74
|
+
{ x: x + w * (1 - POINT), y: y + h },
|
|
75
|
+
{ x: x + w * POINT, y: y + h }
|
|
76
|
+
]),
|
|
77
|
+
content: ({ x, y, width: w, height: h }) => ({ x: x + w * POINT, y, width: w * (1 - POINT * 2), height: h }),
|
|
78
|
+
boxForContent: (c) => ({ width: c.width / (1 - POINT * 2), height: c.height })
|
|
79
|
+
};
|
|
80
|
+
var ellipse = {
|
|
81
|
+
path: ellipsePath,
|
|
82
|
+
// The inscribed rect of an ellipse is its box over root two, centered.
|
|
83
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
84
|
+
const cw = w / Math.SQRT2;
|
|
85
|
+
const ch = h / Math.SQRT2;
|
|
86
|
+
return { x: x + (w - cw) / 2, y: y + (h - ch) / 2, width: cw, height: ch };
|
|
87
|
+
},
|
|
88
|
+
boxForContent: (c) => ({ width: c.width * Math.SQRT2, height: c.height * Math.SQRT2 })
|
|
89
|
+
};
|
|
90
|
+
var stadium = {
|
|
91
|
+
path: ({ x, y, width: w, height: h }) => stadiumPath(x, y, w, h),
|
|
92
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
93
|
+
const r = Math.min(w, h) / 2;
|
|
94
|
+
return w >= h ? { x: x + r, y, width: Math.max(w - r * 2, 0), height: h } : { x, y: y + r, width: w, height: Math.max(h - r * 2, 0) };
|
|
95
|
+
},
|
|
96
|
+
boxForContent: (c) => ({ width: c.width + c.height, height: c.height })
|
|
97
|
+
};
|
|
55
98
|
function stadiumPath(x, y, w, h) {
|
|
56
99
|
const r = Math.min(w, h) / 2;
|
|
57
100
|
const k = r * KAPPA;
|
|
@@ -71,51 +114,462 @@ function stadiumPath(x, y, w, h) {
|
|
|
71
114
|
const midX = x + w / 2;
|
|
72
115
|
return b.moveTo(right, top).lineTo(right, bottom).curveTo(right, bottom + k, midX + k, y + h, midX, y + h).curveTo(midX - k, y + h, left, bottom + k, left, bottom).lineTo(left, top).curveTo(left, top - k, midX - k, y, midX, y).curveTo(midX + k, y, right, top - k, right, top).close().build();
|
|
73
116
|
}
|
|
117
|
+
var FLOWCHART_OUTLINES = { rect, diamond, stadium, ellipse, parallelogram, trapezoid, hexagon };
|
|
118
|
+
var capOf = (w, h) => Math.min(h * 0.15, w * 0.25);
|
|
119
|
+
var cylinder = {
|
|
120
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
121
|
+
const ry = capOf(w, h);
|
|
122
|
+
const rx = w / 2;
|
|
123
|
+
const cx = x + rx;
|
|
124
|
+
const top = y + ry;
|
|
125
|
+
const bottom = y + h - ry;
|
|
126
|
+
return new PathBuilder().moveTo(x, top).curveTo(x, top - ry * KAPPA, cx - rx * KAPPA, y, cx, y).curveTo(cx + rx * KAPPA, y, x + w, top - ry * KAPPA, x + w, top).lineTo(x + w, bottom).curveTo(x + w, bottom + ry * KAPPA, cx + rx * KAPPA, y + h, cx, y + h).curveTo(cx - rx * KAPPA, y + h, x, bottom + ry * KAPPA, x, bottom).close().build();
|
|
127
|
+
},
|
|
128
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
129
|
+
const ry = capOf(w, h);
|
|
130
|
+
const rx = w / 2;
|
|
131
|
+
const cx = x + rx;
|
|
132
|
+
const top = y + ry;
|
|
133
|
+
return new PathBuilder().moveTo(x, top).curveTo(x, top + ry * KAPPA, cx - rx * KAPPA, top + ry, cx, top + ry).curveTo(cx + rx * KAPPA, top + ry, x + w, top + ry * KAPPA, x + w, top).build();
|
|
134
|
+
},
|
|
135
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
136
|
+
const ry = capOf(w, h);
|
|
137
|
+
return { x, y: y + ry * 2, width: w, height: Math.max(h - ry * 3, 0) };
|
|
138
|
+
},
|
|
139
|
+
boxForContent: (c) => ({ width: c.width, height: c.height / 0.55 })
|
|
140
|
+
};
|
|
141
|
+
var WAVE = 0.1;
|
|
142
|
+
var WAVE_CONTROL = 6 / Math.sqrt(3);
|
|
143
|
+
var document = {
|
|
144
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
145
|
+
const a = h * WAVE;
|
|
146
|
+
const mid = y + h - a;
|
|
147
|
+
const k = a * WAVE_CONTROL;
|
|
148
|
+
return new PathBuilder().moveTo(x, y).lineTo(x + w, y).lineTo(x + w, mid).curveTo(x + w * 2 / 3, mid - k, x + w / 3, mid + k, x, mid).close().build();
|
|
149
|
+
},
|
|
150
|
+
content: ({ x, y, width: w, height: h }) => ({ x, y, width: w, height: h * (1 - WAVE * 2) }),
|
|
151
|
+
boxForContent: (c) => ({ width: c.width, height: c.height / (1 - WAVE * 2) })
|
|
152
|
+
};
|
|
153
|
+
var MAX_FOLD = 20;
|
|
154
|
+
var foldOf = (w, h) => Math.min(MAX_FOLD, Math.min(w, h) / 4);
|
|
155
|
+
var note = {
|
|
156
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
157
|
+
const f = foldOf(w, h);
|
|
158
|
+
return polygonFromPoints([
|
|
159
|
+
{ x, y },
|
|
160
|
+
{ x: x + w - f, y },
|
|
161
|
+
{ x: x + w, y: y + f },
|
|
162
|
+
{ x: x + w, y: y + h },
|
|
163
|
+
{ x, y: y + h }
|
|
164
|
+
]);
|
|
165
|
+
},
|
|
166
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
167
|
+
const f = foldOf(w, h);
|
|
168
|
+
return polylineFromPoints([{ x: x + w - f, y }, { x: x + w - f, y: y + f }, { x: x + w, y: y + f }]);
|
|
169
|
+
},
|
|
170
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
171
|
+
const f = foldOf(w, h);
|
|
172
|
+
return { x, y: y + f, width: w, height: h - f };
|
|
173
|
+
},
|
|
174
|
+
boxForContent: (c) => ({ width: c.width, height: c.height + MAX_FOLD })
|
|
175
|
+
};
|
|
176
|
+
var MAX_TAB = 16;
|
|
177
|
+
var tabOf = (w, h) => {
|
|
178
|
+
const t = Math.min(MAX_TAB, h * 0.2);
|
|
179
|
+
return { t, tw: Math.max(Math.min(w * 0.4, w - t * 2), 0) };
|
|
180
|
+
};
|
|
181
|
+
var folder = {
|
|
182
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
183
|
+
const { t, tw } = tabOf(w, h);
|
|
184
|
+
return polygonFromPoints([
|
|
185
|
+
{ x, y },
|
|
186
|
+
{ x: x + tw, y },
|
|
187
|
+
{ x: x + tw + t, y: y + t },
|
|
188
|
+
{ x: x + w, y: y + t },
|
|
189
|
+
{ x: x + w, y: y + h },
|
|
190
|
+
{ x, y: y + h }
|
|
191
|
+
]);
|
|
192
|
+
},
|
|
193
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
194
|
+
const { t, tw } = tabOf(w, h);
|
|
195
|
+
return polylineFromPoints([{ x, y: y + t }, { x: x + tw + t, y: y + t }]);
|
|
196
|
+
},
|
|
197
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
198
|
+
const { t } = tabOf(w, h);
|
|
199
|
+
return { x, y: y + t, width: w, height: h - t };
|
|
200
|
+
},
|
|
201
|
+
boxForContent: (c) => ({ width: c.width, height: c.height + MAX_TAB })
|
|
202
|
+
};
|
|
203
|
+
var DEPTH = 0.15;
|
|
204
|
+
function insetByShorter(c, k) {
|
|
205
|
+
const d = k * Math.min(c.width, c.height) / (1 - k);
|
|
206
|
+
return { width: c.width + d, height: c.height + d };
|
|
207
|
+
}
|
|
208
|
+
var cube = {
|
|
209
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
210
|
+
const d = Math.min(w, h) * DEPTH;
|
|
211
|
+
return polygonFromPoints([
|
|
212
|
+
{ x, y: y + d },
|
|
213
|
+
{ x: x + d, y },
|
|
214
|
+
{ x: x + w, y },
|
|
215
|
+
{ x: x + w, y: y + h - d },
|
|
216
|
+
{ x: x + w - d, y: y + h },
|
|
217
|
+
{ x, y: y + h }
|
|
218
|
+
]);
|
|
219
|
+
},
|
|
220
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
221
|
+
const d = Math.min(w, h) * DEPTH;
|
|
222
|
+
return new PathBuilder().moveTo(x, y + d).lineTo(x + w - d, y + d).lineTo(x + w, y).moveTo(x + w - d, y + d).lineTo(x + w - d, y + h).build();
|
|
223
|
+
},
|
|
224
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
225
|
+
const d = Math.min(w, h) * DEPTH;
|
|
226
|
+
return { x, y: y + d, width: w - d, height: h - d };
|
|
227
|
+
},
|
|
228
|
+
boxForContent: (c) => insetByShorter(c, DEPTH)
|
|
229
|
+
};
|
|
230
|
+
var STORAGE_OUTLINES = { cylinder, document, note, folder, cube };
|
|
231
|
+
|
|
232
|
+
// src/outlines/figures.ts
|
|
233
|
+
var MAX_RADIUS = 10;
|
|
234
|
+
var radiusOf = (w, h) => Math.min(MAX_RADIUS, w / 6, h / 6);
|
|
235
|
+
var BITE = 1 - Math.SQRT1_2;
|
|
236
|
+
var roundRect = {
|
|
237
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
238
|
+
const r = radiusOf(w, h);
|
|
239
|
+
const k = r * KAPPA;
|
|
240
|
+
return new PathBuilder().moveTo(x + r, y).lineTo(x + w - r, y).curveTo(x + w - r + k, y, x + w, y + r - k, x + w, y + r).lineTo(x + w, y + h - r).curveTo(x + w, y + h - r + k, x + w - r + k, y + h, x + w - r, y + h).lineTo(x + r, y + h).curveTo(x + r - k, y + h, x, y + h - r + k, x, y + h - r).lineTo(x, y + r).curveTo(x, y + r - k, x + r - k, y, x + r, y).close().build();
|
|
241
|
+
},
|
|
242
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
243
|
+
const i = radiusOf(w, h) * BITE;
|
|
244
|
+
return { x: x + i, y: y + i, width: w - i * 2, height: h - i * 2 };
|
|
245
|
+
},
|
|
246
|
+
boxForContent: (c) => ({ width: c.width + MAX_RADIUS * BITE * 2, height: c.height + MAX_RADIUS * BITE * 2 })
|
|
247
|
+
};
|
|
248
|
+
var triangle = {
|
|
249
|
+
path: ({ x, y, width: w, height: h }) => polygonFromPoints([
|
|
250
|
+
{ x: x + w / 2, y },
|
|
251
|
+
{ x: x + w, y: y + h },
|
|
252
|
+
{ x, y: y + h }
|
|
253
|
+
]),
|
|
254
|
+
// The largest rect in a triangle: half its width and half its height, on the base.
|
|
255
|
+
content: ({ x, y, width: w, height: h }) => ({ x: x + w / 4, y: y + h / 2, width: w / 2, height: h / 2 }),
|
|
256
|
+
boxForContent: (c) => ({ width: c.width * 2, height: c.height * 2 })
|
|
257
|
+
};
|
|
258
|
+
var CUT = 1 - Math.SQRT1_2;
|
|
259
|
+
var octagon = {
|
|
260
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
261
|
+
const c = Math.min(w, h) * CUT;
|
|
262
|
+
return polygonFromPoints([
|
|
263
|
+
{ x: x + c, y },
|
|
264
|
+
{ x: x + w - c, y },
|
|
265
|
+
{ x: x + w, y: y + c },
|
|
266
|
+
{ x: x + w, y: y + h - c },
|
|
267
|
+
{ x: x + w - c, y: y + h },
|
|
268
|
+
{ x: x + c, y: y + h },
|
|
269
|
+
{ x, y: y + h - c },
|
|
270
|
+
{ x, y: y + c }
|
|
271
|
+
]);
|
|
272
|
+
},
|
|
273
|
+
// Its corners sit on the cuts' midpoints.
|
|
274
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
275
|
+
const c = Math.min(w, h) * CUT;
|
|
276
|
+
return { x: x + c / 2, y: y + c / 2, width: w - c, height: h - c };
|
|
277
|
+
},
|
|
278
|
+
boxForContent: (c) => insetByShorter(c, CUT)
|
|
279
|
+
};
|
|
280
|
+
function arc(b, cx, cy, r, from, sweep) {
|
|
281
|
+
const n = Math.ceil(Math.abs(sweep) / (Math.PI / 2));
|
|
282
|
+
const step = sweep / n;
|
|
283
|
+
const k = 4 / 3 * Math.tan(step / 4) * r;
|
|
284
|
+
for (let i = 0; i < n; i++) {
|
|
285
|
+
const a0 = from + step * i;
|
|
286
|
+
const a1 = a0 + step;
|
|
287
|
+
const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0);
|
|
288
|
+
const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1);
|
|
289
|
+
b.curveTo(x0 - k * Math.sin(a0), y0 + k * Math.cos(a0), x1 + k * Math.sin(a1), y1 - k * Math.cos(a1), x1, y1);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
var CLOUD_JOINS = [178, 222, 268, 318, 2, 46, 92, 136];
|
|
293
|
+
var CLOUD_RX = 0.36;
|
|
294
|
+
var CLOUD_RY = 0.3;
|
|
295
|
+
var CLOUD = (() => {
|
|
296
|
+
const pts = CLOUD_JOINS.map((deg) => {
|
|
297
|
+
const t = deg * Math.PI / 180;
|
|
298
|
+
return { x: 0.5 + CLOUD_RX * Math.cos(t), y: 0.5 + CLOUD_RY * Math.sin(t) };
|
|
299
|
+
});
|
|
300
|
+
const b = new PathBuilder().moveTo(pts[0].x, pts[0].y);
|
|
301
|
+
pts.forEach((p, i) => {
|
|
302
|
+
const q = pts[(i + 1) % pts.length];
|
|
303
|
+
const mx = (p.x + q.x) / 2, my = (p.y + q.y) / 2;
|
|
304
|
+
const r = Math.hypot(q.x - p.x, q.y - p.y) / 2;
|
|
305
|
+
const from = Math.atan2(p.y - my, p.x - mx);
|
|
306
|
+
const out = (s) => Math.hypot(mx + r * Math.cos(from + s) - 0.5, my + r * Math.sin(from + s) - 0.5);
|
|
307
|
+
arc(b, mx, my, r, from, out(Math.PI / 2) > out(-Math.PI / 2) ? Math.PI : -Math.PI);
|
|
308
|
+
});
|
|
309
|
+
const raw = b.close().build();
|
|
310
|
+
const box = boundsOfPath(raw);
|
|
311
|
+
const fit = (p) => ({ x: (p.x - box.x) / box.width, y: (p.y - box.y) / box.height });
|
|
312
|
+
const lo = fit({ x: 0.5 - CLOUD_RX * 0.85 / Math.SQRT2, y: 0.5 - CLOUD_RY * 0.85 / Math.SQRT2 });
|
|
313
|
+
const hi = fit({ x: 0.5 + CLOUD_RX * 0.85 / Math.SQRT2, y: 0.5 + CLOUD_RY * 0.85 / Math.SQRT2 });
|
|
314
|
+
return {
|
|
315
|
+
path: transformPath(raw, [1 / box.width, 0, 0, 1 / box.height, -box.x / box.width, -box.y / box.height]),
|
|
316
|
+
content: { x: lo.x, y: lo.y, width: hi.x - lo.x, height: hi.y - lo.y }
|
|
317
|
+
};
|
|
318
|
+
})();
|
|
319
|
+
var cloud = {
|
|
320
|
+
path: ({ x, y, width: w, height: h }) => transformPath(CLOUD.path, [w, 0, 0, h, x, y]),
|
|
321
|
+
content: ({ x, y, width: w, height: h }) => ({
|
|
322
|
+
x: x + CLOUD.content.x * w,
|
|
323
|
+
y: y + CLOUD.content.y * h,
|
|
324
|
+
width: CLOUD.content.width * w,
|
|
325
|
+
height: CLOUD.content.height * h
|
|
326
|
+
}),
|
|
327
|
+
boxForContent: (c) => ({ width: c.width / CLOUD.content.width, height: c.height / CLOUD.content.height })
|
|
328
|
+
};
|
|
329
|
+
function figureOver(def, aspect, share) {
|
|
330
|
+
const figureBox = ({ x, y, width: w, height: h }) => {
|
|
331
|
+
const s = Math.min(h * share, w / aspect);
|
|
332
|
+
return { x: x + (w - s * aspect) / 2, y: y + h * share - s, width: s * aspect, height: s };
|
|
333
|
+
};
|
|
334
|
+
const detail = def.detail;
|
|
335
|
+
return {
|
|
336
|
+
path: (b) => def.path(figureBox(b)),
|
|
337
|
+
...detail ? { detail: (b) => detail(figureBox(b)) } : {},
|
|
338
|
+
content: ({ x, y, width: w, height: h }) => ({ x, y: y + h * share, width: w, height: h * (1 - share) }),
|
|
339
|
+
boxForContent: (c) => ({ width: c.width, height: c.height / (1 - share) })
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
var ACTOR_FIGURE = {
|
|
343
|
+
path: ({ x, y, height: s }) => {
|
|
344
|
+
const at2 = (u, v) => [x + u * s, y + v * s];
|
|
345
|
+
const r = 0.13 * s;
|
|
346
|
+
const b = new PathBuilder().moveTo(x + 0.3 * s + r, y + r);
|
|
347
|
+
arc(b, x + 0.3 * s, y + r, r, 0, Math.PI * 2);
|
|
348
|
+
b.close();
|
|
349
|
+
for (const [from, to] of [
|
|
350
|
+
[at2(0.3, 0.26), at2(0.3, 0.62)],
|
|
351
|
+
[at2(0.02, 0.38), at2(0.58, 0.38)],
|
|
352
|
+
[at2(0.3, 0.62), at2(0.04, 1)],
|
|
353
|
+
[at2(0.3, 0.62), at2(0.56, 1)]
|
|
354
|
+
]) b.moveTo(...from).lineTo(...to);
|
|
355
|
+
return b.build();
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
var actor = figureOver(ACTOR_FIGURE, 0.6, 0.75);
|
|
359
|
+
var RING = 3;
|
|
360
|
+
var ringOf = (w, h) => Math.min(RING, w / 4, h / 4);
|
|
361
|
+
var doubleEllipse = {
|
|
362
|
+
path: ellipsePath,
|
|
363
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
364
|
+
const g = ringOf(w, h);
|
|
365
|
+
return ellipsePath({ x: x + g, y: y + g, width: w - g * 2, height: h - g * 2 });
|
|
366
|
+
},
|
|
367
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
368
|
+
const g = ringOf(w, h);
|
|
369
|
+
const cw = (w - g * 2) / Math.SQRT2;
|
|
370
|
+
const ch = (h - g * 2) / Math.SQRT2;
|
|
371
|
+
return { x: x + (w - cw) / 2, y: y + (h - ch) / 2, width: cw, height: ch };
|
|
372
|
+
},
|
|
373
|
+
boxForContent: (c) => ({ width: c.width * Math.SQRT2 + RING * 2, height: c.height * Math.SQRT2 + RING * 2 })
|
|
374
|
+
};
|
|
375
|
+
var FIGURE_OUTLINES = { roundRect, triangle, octagon, cloud, actor, doubleEllipse };
|
|
376
|
+
|
|
377
|
+
// src/outlines/bpmn.ts
|
|
378
|
+
var STRIP = 32;
|
|
379
|
+
var EVENT = 40;
|
|
380
|
+
var GATEWAY = 50;
|
|
381
|
+
var EVENT_SIZE = { width: 90, height: EVENT + STRIP };
|
|
382
|
+
var GATEWAY_SIZE = { width: 100, height: GATEWAY + STRIP };
|
|
383
|
+
var event = figureOver(FLOWCHART_OUTLINES.ellipse, 1, EVENT / (EVENT + STRIP));
|
|
384
|
+
var intermediateEvent = figureOver(FIGURE_OUTLINES.doubleEllipse, 1, EVENT / (EVENT + STRIP));
|
|
385
|
+
var DIAMOND = "M0.5 0L1 0.5L0.5 1L0 0.5Z";
|
|
386
|
+
var gateway = (marker) => figureOver(outlineFromD(DIAMOND, { detail: marker }), 1, GATEWAY / (GATEWAY + STRIP));
|
|
387
|
+
var ring = (r) => `M${0.5 + r} 0.5A${r} ${r} 0 1 1 ${0.5 - r} 0.5A${r} ${r} 0 1 1 ${0.5 + r} 0.5`;
|
|
388
|
+
var PENTAGON = (() => {
|
|
389
|
+
const r = 0.13;
|
|
390
|
+
const pts = [0, 1, 2, 3, 4].map((k) => {
|
|
391
|
+
const t = -Math.PI / 2 + k * 2 * Math.PI / 5;
|
|
392
|
+
return `${(0.5 + r * Math.cos(t)).toFixed(4)} ${(0.5 + r * Math.sin(t)).toFixed(4)}`;
|
|
393
|
+
});
|
|
394
|
+
return `M${pts.join("L")}Z`;
|
|
395
|
+
})();
|
|
396
|
+
var exclusiveGateway = gateway("M0.37 0.37L0.63 0.63M0.63 0.37L0.37 0.63");
|
|
397
|
+
var parallelGateway = gateway("M0.5 0.3V0.7M0.3 0.5H0.7");
|
|
398
|
+
var inclusiveGateway = gateway(ring(0.2));
|
|
399
|
+
var eventGateway = gateway(ring(0.22) + PENTAGON);
|
|
400
|
+
var MARKER = 14;
|
|
401
|
+
var MARKER_GAP = 4;
|
|
402
|
+
var markerOf = (w, h) => Math.min(MARKER, w / 4, h / 3);
|
|
403
|
+
var roundRect2 = FIGURE_OUTLINES.roundRect;
|
|
404
|
+
var subprocess = {
|
|
405
|
+
path: roundRect2.path,
|
|
406
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
407
|
+
const m = markerOf(w, h);
|
|
408
|
+
const left = x + (w - m) / 2;
|
|
409
|
+
const top = y + h - MARKER_GAP - m;
|
|
410
|
+
const arm = m * 0.25;
|
|
411
|
+
return new PathBuilder().moveTo(left, top).lineTo(left + m, top).lineTo(left + m, top + m).lineTo(left, top + m).close().moveTo(left + m / 2, top + arm).lineTo(left + m / 2, top + m - arm).moveTo(left + arm, top + m / 2).lineTo(left + m - arm, top + m / 2).build();
|
|
412
|
+
},
|
|
413
|
+
content: (b) => {
|
|
414
|
+
const c = roundRect2.content(b);
|
|
415
|
+
const foot = b.y + b.height - MARKER_GAP - markerOf(b.width, b.height);
|
|
416
|
+
return { ...c, height: Math.max(Math.min(c.y + c.height, foot) - c.y, 0) };
|
|
417
|
+
},
|
|
418
|
+
boxForContent: (c) => {
|
|
419
|
+
const box = roundRect2.boxForContent(c);
|
|
420
|
+
return { width: box.width, height: box.height + MARKER + MARKER_GAP };
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
var BPMN_OUTLINES = {
|
|
424
|
+
event,
|
|
425
|
+
intermediateEvent,
|
|
426
|
+
exclusiveGateway,
|
|
427
|
+
parallelGateway,
|
|
428
|
+
inclusiveGateway,
|
|
429
|
+
eventGateway,
|
|
430
|
+
subprocess
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
// src/outlines/network.ts
|
|
434
|
+
var GLYPH = 56;
|
|
435
|
+
var STRIP2 = 32;
|
|
436
|
+
var DEVICE_SIZE = { width: 96, height: GLYPH + STRIP2 };
|
|
437
|
+
var SHARE = GLYPH / (GLYPH + STRIP2);
|
|
438
|
+
var device = (d, detail) => figureOver(outlineFromD(d, { detail }), 1, SHARE);
|
|
439
|
+
var user = figureOver(ACTOR_FIGURE, 0.6, SHARE);
|
|
440
|
+
var ring2 = (cx, cy, r) => `M${cx + r} ${cy}A${r} ${r} 0 1 1 ${cx - r} ${cy}A${r} ${r} 0 1 1 ${cx + r} ${cy}`;
|
|
441
|
+
var server = device(
|
|
442
|
+
"M0.33 0H0.67Q0.7 0 0.7 0.03V0.97Q0.7 1 0.67 1H0.33Q0.3 1 0.3 0.97V0.03Q0.3 0 0.33 0Z",
|
|
443
|
+
`M0.37 0.16H0.63M0.37 0.28H0.63M0.37 0.4H0.63${ring2(0.5, 0.8, 0.045)}`
|
|
444
|
+
);
|
|
445
|
+
var router = device(
|
|
446
|
+
"M0.08 0.46A0.42 0.14 0 0 1 0.92 0.46V0.86A0.42 0.14 0 0 1 0.08 0.86Z",
|
|
447
|
+
"M0.08 0.46A0.42 0.14 0 0 0 0.92 0.46M0.38 0.68L0.62 0.92M0.53 0.92H0.62V0.83M0.38 0.92L0.62 0.68M0.53 0.68H0.62V0.77"
|
|
448
|
+
);
|
|
449
|
+
var switchDevice = device(
|
|
450
|
+
"M0.09 0.56H0.91Q0.94 0.56 0.94 0.59V0.97Q0.94 1 0.91 1H0.09Q0.06 1 0.06 0.97V0.59Q0.06 0.56 0.09 0.56Z",
|
|
451
|
+
"M0.24 0.69H0.76M0.715 0.645L0.76 0.69L0.715 0.735M0.76 0.87H0.24M0.285 0.825L0.24 0.87L0.285 0.915"
|
|
452
|
+
);
|
|
453
|
+
var firewall = device(
|
|
454
|
+
"M0.1 0.3H0.9V1H0.1Z",
|
|
455
|
+
"M0.1 0.475H0.9M0.1 0.65H0.9M0.1 0.825H0.9M0.37 0.3V0.475M0.63 0.3V0.475M0.24 0.475V0.65M0.5 0.475V0.65M0.76 0.475V0.65M0.37 0.65V0.825M0.63 0.65V0.825M0.24 0.825V1M0.5 0.825V1M0.76 0.825V1"
|
|
456
|
+
);
|
|
457
|
+
var laptop = device(
|
|
458
|
+
"M0.2 0.84V0.43Q0.2 0.4 0.23 0.4H0.77Q0.8 0.4 0.8 0.43V0.84L0.94 0.96Q0.96 1 0.92 1H0.08Q0.04 1 0.06 0.96Z",
|
|
459
|
+
"M0.26 0.46H0.74V0.78H0.26ZM0.2 0.84H0.8M0.43 0.92H0.57"
|
|
460
|
+
);
|
|
461
|
+
var desktop = device(
|
|
462
|
+
"M0.13 0.3H0.87Q0.9 0.3 0.9 0.33V0.79Q0.9 0.82 0.87 0.82H0.56V0.93H0.7V1H0.3V0.93H0.44V0.82H0.13Q0.1 0.82 0.1 0.79V0.33Q0.1 0.3 0.13 0.3Z",
|
|
463
|
+
"M0.16 0.36H0.84V0.76H0.16Z"
|
|
464
|
+
);
|
|
465
|
+
var phone = device(
|
|
466
|
+
"M0.37 0.4H0.63Q0.68 0.4 0.68 0.45V0.95Q0.68 1 0.63 1H0.37Q0.32 1 0.32 0.95V0.45Q0.32 0.4 0.37 0.4Z",
|
|
467
|
+
"M0.38 0.47H0.62V0.86H0.38ZM0.46 0.93H0.54"
|
|
468
|
+
);
|
|
469
|
+
var printer = device(
|
|
470
|
+
"M0.28 0.55V0.36H0.72V0.55H0.86Q0.9 0.55 0.9 0.59V0.84Q0.9 0.88 0.86 0.88H0.74V1H0.26V0.88H0.14Q0.1 0.88 0.1 0.84V0.59Q0.1 0.55 0.14 0.55Z",
|
|
471
|
+
`M0.26 0.88H0.74M0.34 0.94H0.66M0.2 0.78H0.8${ring2(0.78, 0.66, 0.025)}`
|
|
472
|
+
);
|
|
473
|
+
var globe = device(
|
|
474
|
+
ring2(0.5, 0.6, 0.4),
|
|
475
|
+
"M0.1 0.6H0.9M0.1536 0.4H0.8464M0.1536 0.8H0.8464M0.5 0.2V1M0.5 0.2A0.17 0.4 0 0 0 0.5 1A0.17 0.4 0 0 0 0.5 0.2"
|
|
476
|
+
);
|
|
477
|
+
var NETWORK_OUTLINES = {
|
|
478
|
+
server,
|
|
479
|
+
router,
|
|
480
|
+
switch: switchDevice,
|
|
481
|
+
firewall,
|
|
482
|
+
laptop,
|
|
483
|
+
desktop,
|
|
484
|
+
phone,
|
|
485
|
+
printer,
|
|
486
|
+
user,
|
|
487
|
+
globe
|
|
488
|
+
};
|
|
489
|
+
var ICON = { width: 14, height: 12, tab: { width: 6, height: 3 }, margin: 6 };
|
|
490
|
+
var ICON_SIDE = ICON.margin * 2 + ICON.width + ICON.tab.width / 2;
|
|
491
|
+
var component = {
|
|
492
|
+
path: ({ x, y, width: w, height: h }) => rectPath(x, y, w, h),
|
|
493
|
+
// The UML component glyph in the top-right corner: a body with two tabs across its left edge,
|
|
494
|
+
// the edge broken where each tab crosses it.
|
|
495
|
+
detail: ({ x, y, width: w }) => {
|
|
496
|
+
const left = x + w - ICON.margin - ICON.width;
|
|
497
|
+
const top = y + ICON.margin;
|
|
498
|
+
const { width: tw, height: th } = ICON.tab;
|
|
499
|
+
const tabs = [top + 2, top + ICON.height - 2 - th];
|
|
500
|
+
const b = new PathBuilder().moveTo(left, tabs[0]).lineTo(left, top).lineTo(left + ICON.width, top).lineTo(left + ICON.width, top + ICON.height).lineTo(left, top + ICON.height).lineTo(left, tabs[1] + th).moveTo(left, tabs[0] + th).lineTo(left, tabs[1]);
|
|
501
|
+
for (const t of tabs) b.moveTo(left - tw / 2, t).lineTo(left + tw / 2, t).lineTo(left + tw / 2, t + th).lineTo(left - tw / 2, t + th).close();
|
|
502
|
+
return b.build();
|
|
503
|
+
},
|
|
504
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
505
|
+
const side = Math.min(ICON_SIDE, w / 4);
|
|
506
|
+
return { x: x + side, y, width: w - side * 2, height: h };
|
|
507
|
+
},
|
|
508
|
+
boxForContent: (c) => ({ width: c.width + ICON_SIDE * 2, height: c.height })
|
|
509
|
+
};
|
|
510
|
+
var GAP = 4;
|
|
511
|
+
var gapOf = (w, h) => Math.min(GAP, w / 4, h / 4);
|
|
512
|
+
var inset = ({ x, y, width: w, height: h }, g) => ({ x: x + g, y: y + g, width: w - g * 2, height: h - g * 2 });
|
|
513
|
+
var doubleRect = {
|
|
514
|
+
path: ({ x, y, width: w, height: h }) => rectPath(x, y, w, h),
|
|
515
|
+
detail: (b) => {
|
|
516
|
+
const i = inset(b, gapOf(b.width, b.height));
|
|
517
|
+
return rectPath(i.x, i.y, i.width, i.height);
|
|
518
|
+
},
|
|
519
|
+
content: (b) => inset(b, gapOf(b.width, b.height)),
|
|
520
|
+
boxForContent: (c) => ({ width: c.width + GAP * 2, height: c.height + GAP * 2 })
|
|
521
|
+
};
|
|
522
|
+
var MODELING_OUTLINES = { component, doubleRect };
|
|
523
|
+
|
|
524
|
+
// src/outlines/table.ts
|
|
525
|
+
var BUILTINS = {
|
|
526
|
+
...FLOWCHART_OUTLINES,
|
|
527
|
+
...FIGURE_OUTLINES,
|
|
528
|
+
...STORAGE_OUTLINES,
|
|
529
|
+
...NETWORK_OUTLINES,
|
|
530
|
+
...BPMN_OUTLINES,
|
|
531
|
+
...MODELING_OUTLINES
|
|
532
|
+
};
|
|
533
|
+
var table = new Map(
|
|
534
|
+
Object.entries(BUILTINS).map(([name, def]) => [name, [def]])
|
|
535
|
+
);
|
|
536
|
+
var warned = /* @__PURE__ */ new Set();
|
|
537
|
+
function registerOutline(name, def) {
|
|
538
|
+
const stack = table.get(name) ?? [];
|
|
539
|
+
stack.push(def);
|
|
540
|
+
table.set(name, stack);
|
|
541
|
+
return () => {
|
|
542
|
+
const i = stack.lastIndexOf(def);
|
|
543
|
+
if (i >= 0) stack.splice(i, 1);
|
|
544
|
+
if (stack.length === 0) table.delete(name);
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function resolveOutline(name) {
|
|
548
|
+
const def = table.get(name)?.at(-1);
|
|
549
|
+
if (def) return def;
|
|
550
|
+
if (!warned.has(name)) {
|
|
551
|
+
warned.add(name);
|
|
552
|
+
console.warn(`@weasel-js/diagram: no outline named '${name}' is registered; painting it as 'rect'`);
|
|
553
|
+
}
|
|
554
|
+
return FLOWCHART_OUTLINES.rect;
|
|
555
|
+
}
|
|
556
|
+
function outlinePath(outline, bounds) {
|
|
557
|
+
const { x, y, width: w, height: h } = bounds;
|
|
558
|
+
if (w <= 0 || h <= 0) return rectPath(x, y, Math.max(w, 0), Math.max(h, 0));
|
|
559
|
+
if (typeof outline !== "string") return transformPath(outline, [w, 0, 0, h, x, y]);
|
|
560
|
+
return resolveOutline(outline).path(bounds);
|
|
561
|
+
}
|
|
562
|
+
function outlineDetail(outline, bounds) {
|
|
563
|
+
if (typeof outline !== "string" || bounds.width <= 0 || bounds.height <= 0) return null;
|
|
564
|
+
return resolveOutline(outline).detail?.(bounds) ?? null;
|
|
565
|
+
}
|
|
74
566
|
function contentBox(outline, bounds) {
|
|
75
567
|
if (typeof outline !== "string") return bounds;
|
|
76
|
-
|
|
77
|
-
switch (outline) {
|
|
78
|
-
case "rect":
|
|
79
|
-
return bounds;
|
|
80
|
-
case "diamond":
|
|
81
|
-
return { x: x + w / 4, y: y + h / 4, width: w / 2, height: h / 2 };
|
|
82
|
-
case "parallelogram": {
|
|
83
|
-
const lean = Math.min(w * LEAN, w / 2);
|
|
84
|
-
return { x: x + lean, y, width: Math.max(w - lean * 2, 0), height: h };
|
|
85
|
-
}
|
|
86
|
-
case "trapezoid":
|
|
87
|
-
return { x, y: y + h / 4, width: w, height: h / 2 };
|
|
88
|
-
case "hexagon":
|
|
89
|
-
return { x: x + w * POINT, y, width: w * (1 - POINT * 2), height: h };
|
|
90
|
-
case "ellipse": {
|
|
91
|
-
const cw = w / Math.SQRT2;
|
|
92
|
-
const ch = h / Math.SQRT2;
|
|
93
|
-
return { x: x + (w - cw) / 2, y: y + (h - ch) / 2, width: cw, height: ch };
|
|
94
|
-
}
|
|
95
|
-
case "stadium": {
|
|
96
|
-
const r = Math.min(w, h) / 2;
|
|
97
|
-
return w >= h ? { x: x + r, y, width: Math.max(w - r * 2, 0), height: h } : { x, y: y + r, width: w, height: Math.max(h - r * 2, 0) };
|
|
98
|
-
}
|
|
99
|
-
}
|
|
568
|
+
return resolveOutline(outline).content?.(bounds) ?? bounds;
|
|
100
569
|
}
|
|
101
570
|
function boxForContent(outline, content) {
|
|
102
571
|
if (typeof outline !== "string") return content;
|
|
103
|
-
|
|
104
|
-
case "rect":
|
|
105
|
-
return content;
|
|
106
|
-
case "diamond":
|
|
107
|
-
return { width: content.width * 2, height: content.height * 2 };
|
|
108
|
-
case "parallelogram":
|
|
109
|
-
return { width: content.width / (1 - LEAN * 2), height: content.height };
|
|
110
|
-
case "trapezoid":
|
|
111
|
-
return { width: content.width, height: content.height * 2 };
|
|
112
|
-
case "hexagon":
|
|
113
|
-
return { width: content.width / (1 - POINT * 2), height: content.height };
|
|
114
|
-
case "stadium":
|
|
115
|
-
return { width: content.width + content.height, height: content.height };
|
|
116
|
-
case "ellipse":
|
|
117
|
-
return { width: content.width * Math.SQRT2, height: content.height * Math.SQRT2 };
|
|
118
|
-
}
|
|
572
|
+
return resolveOutline(outline).boxForContent?.(content) ?? content;
|
|
119
573
|
}
|
|
120
574
|
var TOLERANCE = 0.25;
|
|
121
575
|
function outlinePolyline(outline, bounds) {
|
|
@@ -128,7 +582,8 @@ function flattenPath(path) {
|
|
|
128
582
|
return [x, y, x + w, y, x + w, y + h, x, y + h, x, y];
|
|
129
583
|
}
|
|
130
584
|
const out = [];
|
|
131
|
-
const { commands
|
|
585
|
+
const { commands } = path;
|
|
586
|
+
const coords = worldCoords(path);
|
|
132
587
|
let ci = 0;
|
|
133
588
|
let cx = 0;
|
|
134
589
|
let cy = 0;
|
|
@@ -367,10 +822,11 @@ function withLabels(ports, labels) {
|
|
|
367
822
|
var DEFAULT_PADDING = 8;
|
|
368
823
|
var DEFAULT_GAP = 4;
|
|
369
824
|
var FALLBACK_LINE = 16;
|
|
825
|
+
var DIVIDER_HEIGHT = 4;
|
|
370
826
|
function canvasMeasure(ctx) {
|
|
371
827
|
return (text, style) => {
|
|
372
828
|
const size = style.fontSize ?? FALLBACK_LINE;
|
|
373
|
-
ctx.font = `${style.bold === true ? "bold " : ""}${size}px ${cssFamilyName(style.fontFamily ?? "sans-serif")}`;
|
|
829
|
+
ctx.font = `${style.italic === true ? "italic " : ""}${style.bold === true ? "bold " : ""}${size}px ${cssFamilyName(style.fontFamily ?? "sans-serif")}`;
|
|
374
830
|
return { width: ctx.measureText(text).width, height: Math.ceil(size * 1.2) };
|
|
375
831
|
};
|
|
376
832
|
}
|
|
@@ -398,8 +854,13 @@ function measureRow(row, measure) {
|
|
|
398
854
|
}
|
|
399
855
|
case "slot":
|
|
400
856
|
return { width: row.width ?? 0, height: row.height };
|
|
857
|
+
case "divider":
|
|
858
|
+
return { width: 0, height: DIVIDER_HEIGHT };
|
|
401
859
|
}
|
|
402
860
|
}
|
|
861
|
+
function rowHeights(spec, measure) {
|
|
862
|
+
return spec.rows.map((row) => measureRow(row, measure).height);
|
|
863
|
+
}
|
|
403
864
|
function measureBody(spec, measure) {
|
|
404
865
|
const padding = spec.padding ?? DEFAULT_PADDING;
|
|
405
866
|
const gap = spec.gap ?? DEFAULT_GAP;
|
|
@@ -427,19 +888,22 @@ function layoutBody(spec, bounds, measure) {
|
|
|
427
888
|
const gap = spec.gap ?? DEFAULT_GAP;
|
|
428
889
|
const inner = contentBox(spec.outline, bounds);
|
|
429
890
|
const width = Math.max(inner.width - padding * 2, 0);
|
|
430
|
-
const heights = spec
|
|
891
|
+
const heights = rowHeights(spec, measure);
|
|
431
892
|
const used = heights.reduce((sum, h) => sum + h, 0) + gap * Math.max(heights.length - 1, 0);
|
|
432
893
|
const slack = Math.max(inner.height - padding * 2 - used, 0);
|
|
433
894
|
const share = { top: 0, center: 0.5, bottom: 1 }[spec.verticalAlign ?? "center"];
|
|
434
895
|
let y = inner.y + padding + slack * share;
|
|
435
896
|
return spec.rows.map((row, index) => {
|
|
436
897
|
const h = heights[index];
|
|
437
|
-
const
|
|
438
|
-
const box = { row, index, x: inner.x + padding + (width - w) / 2, y, width: w, height: h };
|
|
898
|
+
const box = row.kind === "divider" ? { row, index, x: inner.x + (row.inset ?? 0), y, width: Math.max(inner.width - 2 * (row.inset ?? 0), 0), height: h } : rowBox(row, index, inner.x + padding, width, y, h);
|
|
439
899
|
y += h + gap;
|
|
440
900
|
return box;
|
|
441
901
|
});
|
|
442
902
|
}
|
|
903
|
+
function rowBox(row, index, x, width, y, height) {
|
|
904
|
+
const w = row.kind === "slot" && row.width !== void 0 ? Math.min(row.width, width) : width;
|
|
905
|
+
return { row, index, x: x + (width - w) / 2, y, width: w, height };
|
|
906
|
+
}
|
|
443
907
|
function layoutRowPorts(row, box, measure) {
|
|
444
908
|
const width = (label) => label === void 0 ? 0 : measureRow({ kind: "label", text: label }, measure).width;
|
|
445
909
|
const slots = Math.max(row.left?.length ?? 0, row.right?.length ?? 0, 1);
|
|
@@ -727,28 +1191,28 @@ function graphOrder(graph) {
|
|
|
727
1191
|
}
|
|
728
1192
|
|
|
729
1193
|
// src/cluster.ts
|
|
730
|
-
function insetOf(
|
|
731
|
-
if (typeof
|
|
1194
|
+
function insetOf(inset2) {
|
|
1195
|
+
if (typeof inset2 === "number") return { top: inset2, right: inset2, bottom: inset2, left: inset2 };
|
|
732
1196
|
return {
|
|
733
|
-
top:
|
|
734
|
-
right:
|
|
735
|
-
bottom:
|
|
736
|
-
left:
|
|
1197
|
+
top: inset2?.top ?? DEFAULT_GROUP_INSET,
|
|
1198
|
+
right: inset2?.right ?? DEFAULT_GROUP_INSET,
|
|
1199
|
+
bottom: inset2?.bottom ?? DEFAULT_GROUP_INSET,
|
|
1200
|
+
left: inset2?.left ?? DEFAULT_GROUP_INSET
|
|
737
1201
|
};
|
|
738
1202
|
}
|
|
739
1203
|
var DEFAULT_GROUP_INSET = 12;
|
|
740
|
-
function canonical(
|
|
1204
|
+
function canonical(inset2, axes) {
|
|
741
1205
|
if (axes.rank === "y") {
|
|
742
|
-
return axes.sign === 1 ? { crossLo:
|
|
1206
|
+
return axes.sign === 1 ? { crossLo: inset2.left, crossHi: inset2.right, rankLo: inset2.top, rankHi: inset2.bottom } : { crossLo: inset2.left, crossHi: inset2.right, rankLo: inset2.bottom, rankHi: inset2.top };
|
|
743
1207
|
}
|
|
744
|
-
return axes.sign === 1 ? { crossLo:
|
|
1208
|
+
return axes.sign === 1 ? { crossLo: inset2.top, crossHi: inset2.bottom, rankLo: inset2.left, rankHi: inset2.right } : { crossLo: inset2.top, crossHi: inset2.bottom, rankLo: inset2.right, rankHi: inset2.left };
|
|
745
1209
|
}
|
|
746
|
-
function crossInset(
|
|
747
|
-
const c = canonical(
|
|
1210
|
+
function crossInset(inset2, axes) {
|
|
1211
|
+
const c = canonical(inset2, axes);
|
|
748
1212
|
return { lo: c.crossLo, hi: c.crossHi };
|
|
749
1213
|
}
|
|
750
|
-
function rankInset(
|
|
751
|
-
const c = canonical(
|
|
1214
|
+
function rankInset(inset2, axes) {
|
|
1215
|
+
const c = canonical(inset2, axes);
|
|
752
1216
|
return { lo: c.rankLo, hi: c.rankHi };
|
|
753
1217
|
}
|
|
754
1218
|
function rankGaps(graph, rows, axes, rankGap) {
|
|
@@ -863,8 +1327,8 @@ function packClusters(graph, rows, preferred2, axes, nodeGap) {
|
|
|
863
1327
|
return block;
|
|
864
1328
|
};
|
|
865
1329
|
function outer(span) {
|
|
866
|
-
const
|
|
867
|
-
return blockOf(span).width +
|
|
1330
|
+
const inset2 = insets.get(span);
|
|
1331
|
+
return blockOf(span).width + inset2.crossLo + inset2.crossHi;
|
|
868
1332
|
}
|
|
869
1333
|
const roots = spans.filter((s) => s.parent === void 0);
|
|
870
1334
|
const start = new Map(roots.map((s) => [s, centerOf.get(s) - outer(s) / 2]));
|
|
@@ -878,8 +1342,8 @@ function packClusters(graph, rows, preferred2, axes, nodeGap) {
|
|
|
878
1342
|
for (const root of roots) place(root, start.get(root));
|
|
879
1343
|
return at2;
|
|
880
1344
|
}
|
|
881
|
-
function widen(block, group,
|
|
882
|
-
const floor = axes.cross === "x" ? (group.minWidth ?? 0) -
|
|
1345
|
+
function widen(block, group, inset2, axes) {
|
|
1346
|
+
const floor = axes.cross === "x" ? (group.minWidth ?? 0) - inset2.crossLo - inset2.crossHi : 0;
|
|
883
1347
|
const slack = Math.max(0, floor - block.width) / 2;
|
|
884
1348
|
block.width += 2 * slack;
|
|
885
1349
|
for (const [child, local] of block.childAt) block.childAt.set(child, local + slack);
|
|
@@ -950,7 +1414,13 @@ function subpathOf(path, index) {
|
|
|
950
1414
|
if (i === commands.length || cmd === PATH_M$1) {
|
|
951
1415
|
if (seen === index) {
|
|
952
1416
|
if (start === 0 && i === commands.length) return path;
|
|
953
|
-
return {
|
|
1417
|
+
return {
|
|
1418
|
+
kind: "polygon",
|
|
1419
|
+
fillRule: path.fillRule,
|
|
1420
|
+
commands: commands.slice(start, i),
|
|
1421
|
+
coords: coords.slice(startCoord, coord2),
|
|
1422
|
+
...path.origin ? { origin: path.origin } : {}
|
|
1423
|
+
};
|
|
954
1424
|
}
|
|
955
1425
|
seen++;
|
|
956
1426
|
start = i;
|
|
@@ -963,7 +1433,8 @@ function subpathOf(path, index) {
|
|
|
963
1433
|
var NAMED = { start: 0, mid: 0.5, end: 1 };
|
|
964
1434
|
function nearestStation(path, near) {
|
|
965
1435
|
if (path.kind !== "polygon") return null;
|
|
966
|
-
const { commands
|
|
1436
|
+
const { commands } = path;
|
|
1437
|
+
const coords = worldCoords(path);
|
|
967
1438
|
let best = null;
|
|
968
1439
|
let heading = { x: 1, y: 0 };
|
|
969
1440
|
forEachSegment(commands, coords, (cmd, ci, x0, y0) => {
|
|
@@ -1167,8 +1638,8 @@ function boxOf(g) {
|
|
|
1167
1638
|
x1 = Math.max(x1, b.x1);
|
|
1168
1639
|
y1 = Math.max(y1, b.y1);
|
|
1169
1640
|
}
|
|
1170
|
-
const { inset } = g.group;
|
|
1171
|
-
return { x0: x0 -
|
|
1641
|
+
const { inset: inset2 } = g.group;
|
|
1642
|
+
return { x0: x0 - inset2.left, y0: y0 - inset2.top, x1: x1 + inset2.right, y1: y1 + inset2.bottom };
|
|
1172
1643
|
}
|
|
1173
1644
|
function clearance(a, b, padding) {
|
|
1174
1645
|
const gapX = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0) + padding;
|
|
@@ -1522,9 +1993,9 @@ function longestPath(count, arcs) {
|
|
|
1522
1993
|
const rank = new Array(count).fill(0);
|
|
1523
1994
|
const pending = new Array(count).fill(0);
|
|
1524
1995
|
const out = Array.from({ length: count }, () => []);
|
|
1525
|
-
for (const
|
|
1526
|
-
pending[
|
|
1527
|
-
out[
|
|
1996
|
+
for (const arc2 of arcs) {
|
|
1997
|
+
pending[arc2.head]++;
|
|
1998
|
+
out[arc2.tail].push(arc2.head);
|
|
1528
1999
|
}
|
|
1529
2000
|
const ready = [];
|
|
1530
2001
|
for (let i = 0; i < count; i++) if (pending[i] === 0) ready.push(i);
|
|
@@ -1539,9 +2010,9 @@ function longestPath(count, arcs) {
|
|
|
1539
2010
|
}
|
|
1540
2011
|
function components(count, arcs) {
|
|
1541
2012
|
const near = Array.from({ length: count }, () => []);
|
|
1542
|
-
for (const
|
|
1543
|
-
near[
|
|
1544
|
-
near[
|
|
2013
|
+
for (const arc2 of arcs) {
|
|
2014
|
+
near[arc2.tail].push(arc2.head);
|
|
2015
|
+
near[arc2.head].push(arc2.tail);
|
|
1545
2016
|
}
|
|
1546
2017
|
const part = new Array(count).fill(-1);
|
|
1547
2018
|
const parts = [];
|
|
@@ -1562,14 +2033,14 @@ function components(count, arcs) {
|
|
|
1562
2033
|
}
|
|
1563
2034
|
const local = new Array(count);
|
|
1564
2035
|
for (const p of parts) p.nodes.forEach((g, i) => local[g] = i);
|
|
1565
|
-
for (const
|
|
1566
|
-
parts[part[
|
|
2036
|
+
for (const arc2 of arcs) {
|
|
2037
|
+
parts[part[arc2.tail]].arcs.push({ tail: local[arc2.tail], head: local[arc2.head] });
|
|
1567
2038
|
}
|
|
1568
2039
|
return parts;
|
|
1569
2040
|
}
|
|
1570
|
-
var slackOf = (
|
|
2041
|
+
var slackOf = (arc2, rank) => rank[arc2.head] - rank[arc2.tail] - 1;
|
|
1571
2042
|
function simplex(arcs, rank) {
|
|
1572
|
-
if (arcs.length === 0 || arcs.some((
|
|
2043
|
+
if (arcs.length === 0 || arcs.some((arc2) => slackOf(arc2, rank) < 0)) return;
|
|
1573
2044
|
const inTree = feasibleTree(arcs, rank);
|
|
1574
2045
|
const cap = 4 * arcs.length + 100;
|
|
1575
2046
|
for (let round = 0; round < cap; round++) {
|
|
@@ -1588,10 +2059,10 @@ function simplex(arcs, rank) {
|
|
|
1588
2059
|
const inside = insideOf(tree2, childOf(arcs[leave], leave, tree2));
|
|
1589
2060
|
let enter = -1;
|
|
1590
2061
|
for (let a = 0; a < arcs.length; a++) {
|
|
1591
|
-
const
|
|
2062
|
+
const arc2 = arcs[a];
|
|
1592
2063
|
if (inTree[a]) continue;
|
|
1593
|
-
const crosses = tailInside ? !inside(
|
|
1594
|
-
if (crosses && (enter === -1 || slackOf(
|
|
2064
|
+
const crosses = tailInside ? !inside(arc2.tail) && inside(arc2.head) : inside(arc2.tail) && !inside(arc2.head);
|
|
2065
|
+
if (crosses && (enter === -1 || slackOf(arc2, rank) < slackOf(arcs[enter], rank))) enter = a;
|
|
1595
2066
|
}
|
|
1596
2067
|
if (enter === -1) return;
|
|
1597
2068
|
inTree[leave] = false;
|
|
@@ -1607,10 +2078,10 @@ function feasibleTree(arcs, rank) {
|
|
|
1607
2078
|
const grow = () => {
|
|
1608
2079
|
for (let changed = true; changed; ) {
|
|
1609
2080
|
changed = false;
|
|
1610
|
-
arcs.forEach((
|
|
1611
|
-
if (has[
|
|
2081
|
+
arcs.forEach((arc2, a) => {
|
|
2082
|
+
if (has[arc2.tail] === has[arc2.head] || slackOf(arc2, rank) !== 0) return;
|
|
1612
2083
|
inTree[a] = true;
|
|
1613
|
-
has[
|
|
2084
|
+
has[arc2.tail] = has[arc2.head] = true;
|
|
1614
2085
|
size++;
|
|
1615
2086
|
changed = true;
|
|
1616
2087
|
});
|
|
@@ -1619,12 +2090,12 @@ function feasibleTree(arcs, rank) {
|
|
|
1619
2090
|
grow();
|
|
1620
2091
|
while (size < rank.length) {
|
|
1621
2092
|
let best = -1;
|
|
1622
|
-
arcs.forEach((
|
|
1623
|
-
if (has[
|
|
1624
|
-
if (best === -1 || slackOf(
|
|
2093
|
+
arcs.forEach((arc3, a) => {
|
|
2094
|
+
if (has[arc3.tail] === has[arc3.head]) return;
|
|
2095
|
+
if (best === -1 || slackOf(arc3, rank) < slackOf(arcs[best], rank)) best = a;
|
|
1625
2096
|
});
|
|
1626
|
-
const
|
|
1627
|
-
const delta = has[
|
|
2097
|
+
const arc2 = arcs[best];
|
|
2098
|
+
const delta = has[arc2.head] ? -slackOf(arc2, rank) : slackOf(arc2, rank);
|
|
1628
2099
|
for (let v = 0; v < rank.length; v++) if (has[v]) rank[v] += delta;
|
|
1629
2100
|
grow();
|
|
1630
2101
|
}
|
|
@@ -1632,10 +2103,10 @@ function feasibleTree(arcs, rank) {
|
|
|
1632
2103
|
}
|
|
1633
2104
|
function treeAdjacency(count, arcs, inTree) {
|
|
1634
2105
|
const adj = Array.from({ length: count }, () => []);
|
|
1635
|
-
arcs.forEach((
|
|
2106
|
+
arcs.forEach((arc2, a) => {
|
|
1636
2107
|
if (!inTree[a]) return;
|
|
1637
|
-
adj[
|
|
1638
|
-
adj[
|
|
2108
|
+
adj[arc2.tail].push(a);
|
|
2109
|
+
adj[arc2.head].push(a);
|
|
1639
2110
|
});
|
|
1640
2111
|
return adj;
|
|
1641
2112
|
}
|
|
@@ -1656,16 +2127,16 @@ function postorder(count, arcs, inTree) {
|
|
|
1656
2127
|
continue;
|
|
1657
2128
|
}
|
|
1658
2129
|
if (a === parentArc[top.v]) continue;
|
|
1659
|
-
const
|
|
1660
|
-
const w =
|
|
2130
|
+
const arc2 = arcs[a];
|
|
2131
|
+
const w = arc2.tail === top.v ? arc2.head : arc2.tail;
|
|
1661
2132
|
parentArc[w] = a;
|
|
1662
2133
|
low[w] = next;
|
|
1663
2134
|
stack.push({ v: w, i: 0 });
|
|
1664
2135
|
}
|
|
1665
2136
|
return { low, lim, parentArc };
|
|
1666
2137
|
}
|
|
1667
|
-
function childOf(
|
|
1668
|
-
return tree2.parentArc[
|
|
2138
|
+
function childOf(arc2, a, tree2) {
|
|
2139
|
+
return tree2.parentArc[arc2.tail] === a ? arc2.tail : arc2.head;
|
|
1669
2140
|
}
|
|
1670
2141
|
function insideOf(tree2, child) {
|
|
1671
2142
|
const lo = tree2.low[child];
|
|
@@ -1678,9 +2149,9 @@ function cutValue(arcs, a, tree2) {
|
|
|
1678
2149
|
const inside = insideOf(tree2, child);
|
|
1679
2150
|
const tailInside = child === treeArc.tail;
|
|
1680
2151
|
let value = 0;
|
|
1681
|
-
for (const
|
|
1682
|
-
const from = inside(
|
|
1683
|
-
if (from === inside(
|
|
2152
|
+
for (const arc2 of arcs) {
|
|
2153
|
+
const from = inside(arc2.tail);
|
|
2154
|
+
if (from === inside(arc2.head)) continue;
|
|
1684
2155
|
value += from === tailInside ? 1 : -1;
|
|
1685
2156
|
}
|
|
1686
2157
|
return { value, tailInside };
|
|
@@ -1693,11 +2164,11 @@ function tighten(rank, arcs, inTree) {
|
|
|
1693
2164
|
for (let k = 0; k < queue.length; k++) {
|
|
1694
2165
|
const v = queue[k];
|
|
1695
2166
|
for (const a of adj[v]) {
|
|
1696
|
-
const
|
|
1697
|
-
const w =
|
|
2167
|
+
const arc2 = arcs[a];
|
|
2168
|
+
const w = arc2.tail === v ? arc2.head : arc2.tail;
|
|
1698
2169
|
if (seen[w]) continue;
|
|
1699
2170
|
seen[w] = true;
|
|
1700
|
-
rank[w] =
|
|
2171
|
+
rank[w] = arc2.tail === v ? rank[v] + 1 : rank[v] - 1;
|
|
1701
2172
|
queue.push(w);
|
|
1702
2173
|
}
|
|
1703
2174
|
}
|
|
@@ -1709,18 +2180,18 @@ var isPlaceholder = (id) => id.startsWith(PLACEHOLDER);
|
|
|
1709
2180
|
|
|
1710
2181
|
// src/layered/expand.ts
|
|
1711
2182
|
function labelRowsOf(drawn, ranks, span) {
|
|
1712
|
-
const
|
|
2183
|
+
const gapOf2 = /* @__PURE__ */ new Map();
|
|
1713
2184
|
for (const d of drawn) {
|
|
1714
2185
|
if (d.label === void 0) continue;
|
|
1715
2186
|
const a = span(d.back ? d.to : d.from, ranks);
|
|
1716
2187
|
const b = span(d.back ? d.from : d.to, ranks);
|
|
1717
2188
|
if (a === null || b === null || a[1] >= b[0]) continue;
|
|
1718
|
-
|
|
2189
|
+
gapOf2.set(d.id, a[1] + Math.floor((b[0] - a[1] - 1) / 2));
|
|
1719
2190
|
}
|
|
1720
|
-
const gaps = [...new Set(
|
|
2191
|
+
const gaps = [...new Set(gapOf2.values())];
|
|
1721
2192
|
const rowOf = (r) => r + gaps.filter((g) => g < r).length;
|
|
1722
2193
|
const rows = new Map([...ranks].map(([id, r]) => [id, rowOf(r)]));
|
|
1723
|
-
return { rows, labelRow: new Map([...
|
|
2194
|
+
return { rows, labelRow: new Map([...gapOf2].map(([id, g]) => [id, rowOf(g) + 1])) };
|
|
1724
2195
|
}
|
|
1725
2196
|
function labelRoom(room, axes, back, nodeGap) {
|
|
1726
2197
|
const across = extent({ width: room.width, height: room.height }, axes.cross);
|
|
@@ -3177,6 +3648,28 @@ function forestOf(graph, crossAxis) {
|
|
|
3177
3648
|
}
|
|
3178
3649
|
return { roots, children, depth };
|
|
3179
3650
|
}
|
|
3651
|
+
function subtreeBlocks(children, axis, gap) {
|
|
3652
|
+
const measured = /* @__PURE__ */ new Map();
|
|
3653
|
+
const kidsSpan = (kids) => kids.reduce((sum, k) => sum + span(k), 0) + Math.max(0, kids.length - 1) * gap;
|
|
3654
|
+
const span = (node) => {
|
|
3655
|
+
const known = measured.get(node.id);
|
|
3656
|
+
if (known !== void 0) return known;
|
|
3657
|
+
const block = Math.max(extent(node.bounds, axis), kidsSpan(children.get(node.id) ?? []));
|
|
3658
|
+
measured.set(node.id, block);
|
|
3659
|
+
return block;
|
|
3660
|
+
};
|
|
3661
|
+
const lay = (node, from, into) => {
|
|
3662
|
+
const kids = children.get(node.id) ?? [];
|
|
3663
|
+
const block = span(node);
|
|
3664
|
+
let cursor = from + (block - kidsSpan(kids)) / 2;
|
|
3665
|
+
for (const child of kids) {
|
|
3666
|
+
lay(child, cursor, into);
|
|
3667
|
+
cursor += span(child) + gap;
|
|
3668
|
+
}
|
|
3669
|
+
into.set(node.id, from + (block - extent(node.bounds, axis)) / 2);
|
|
3670
|
+
};
|
|
3671
|
+
return { span, lay };
|
|
3672
|
+
}
|
|
3180
3673
|
var tree = (graph, opts = {}) => (graph.groups?.length ?? 0) > 0 ? untilSettled(treeOnce, graph, opts) : treeOnce(graph, opts);
|
|
3181
3674
|
var treeOnce = (graph, opts = {}) => {
|
|
3182
3675
|
const axes = axesFor(opts.direction);
|
|
@@ -3199,48 +3692,29 @@ var treeOnce = (graph, opts = {}) => {
|
|
|
3199
3692
|
along += bands.get(at2) + (gaps[i] ?? 0);
|
|
3200
3693
|
}
|
|
3201
3694
|
const slots = /* @__PURE__ */ new Map();
|
|
3202
|
-
const
|
|
3203
|
-
const
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
const block = Math.max(extent(node.bounds, axes.cross), width);
|
|
3211
|
-
measured.set(node.id, block);
|
|
3212
|
-
return block;
|
|
3213
|
-
};
|
|
3214
|
-
const place = (node, from) => {
|
|
3215
|
-
const kids = children.get(node.id) ?? [];
|
|
3216
|
-
const block = measure(node);
|
|
3217
|
-
const width = kids.reduce((sum, k) => sum + measure(k), 0) + Math.max(0, kids.length - 1) * nodeGap;
|
|
3218
|
-
let cursor2 = from + (block - width) / 2;
|
|
3219
|
-
for (const child of kids) {
|
|
3220
|
-
place(child, cursor2);
|
|
3221
|
-
cursor2 += measure(child) + nodeGap;
|
|
3222
|
-
}
|
|
3223
|
-
const own = extent(node.bounds, axes.cross);
|
|
3695
|
+
const blocks = subtreeBlocks(children, axes.cross, nodeGap);
|
|
3696
|
+
const crossAt = /* @__PURE__ */ new Map();
|
|
3697
|
+
let cursor = 0;
|
|
3698
|
+
for (const root of roots) {
|
|
3699
|
+
blocks.lay(root, cursor, crossAt);
|
|
3700
|
+
cursor += blocks.span(root) + nodeGap;
|
|
3701
|
+
}
|
|
3702
|
+
for (const node of graph.nodes) {
|
|
3224
3703
|
const at2 = depth.get(node.id) ?? 0;
|
|
3225
3704
|
slots.set(node.id, {
|
|
3226
|
-
cross:
|
|
3705
|
+
cross: crossAt.get(node.id),
|
|
3227
3706
|
rank: bandStart.get(at2) + (bands.get(at2) - extent(node.bounds, axes.rank)) / 2
|
|
3228
3707
|
});
|
|
3229
|
-
};
|
|
3230
|
-
let cursor = 0;
|
|
3231
|
-
for (const root of roots) {
|
|
3232
|
-
place(root, cursor);
|
|
3233
|
-
cursor += measure(root) + nodeGap;
|
|
3234
3708
|
}
|
|
3235
3709
|
if (grouped) {
|
|
3236
3710
|
const preferred2 = new Map([...slots].map(([id, slot]) => [id, slot.cross]));
|
|
3237
3711
|
const ordered = rowsAt.map((row) => [...row].sort((a, b) => preferred2.get(a.id) - preferred2.get(b.id)));
|
|
3238
|
-
const
|
|
3239
|
-
for (const [id, slot] of slots) slots.set(id, { ...slot, cross:
|
|
3712
|
+
const crossAt2 = packClusters(graph, ordered, preferred2, axes, nodeGap);
|
|
3713
|
+
for (const [id, slot] of slots) slots.set(id, { ...slot, cross: crossAt2.get(id) ?? slot.cross });
|
|
3240
3714
|
}
|
|
3241
3715
|
return settle(graph, slots, opts);
|
|
3242
3716
|
};
|
|
3243
3717
|
|
|
3244
|
-
export { COMPASS, DEFAULT_GROUP_INSET, DEFAULT_NODE_GAP, DEFAULT_PORTS, DEFAULT_RANK_GAP, DIAGRAM_TRAIT_KEY, PORT_LABEL_GAP, SIDE_TRACK_GAP, anchorOffset, authoredOver, axesFor, backEdges, bodyOutline, bodyTrait, boxForContent, buildBody, canvasMeasure, center, chain, contentBox, createDiagramNodes, dataKeyReader, diagramEdgeOf, diagramNodeOf, expandGroupEdges, extent, footprintNode, force, forceRelaxation, forestOf, graphOrder, grownBy, insetOf, isPinned, isPromise, labelCenter, labelSpotAt, layered, layeredPlan, layeredRoutes, layoutBody, layoutOwnsPort, layoutOwnsRoute, layoutRowPorts, layoutWritesRoute, marginOf, measureBody, outlinePath, outlinePolyline, packAcross, packClusters, pinnedSet, planOf, plannerPlan, portLabelBox, portLabelsOf, portOf, portSitesOf, portsOf, portsOnOutline, rankGaps, ranksByLength, ranksOf, rayHit, routeHolds, samePoints, seededOrder, settle, sizeToBody, subpathOf, translated, tree, untilSettled, widenForMinWidth };
|
|
3245
|
-
//# sourceMappingURL=chunk-
|
|
3246
|
-
//# sourceMappingURL=chunk-
|
|
3718
|
+
export { COMPASS, DEFAULT_GROUP_INSET, DEFAULT_NODE_GAP, DEFAULT_PORTS, DEFAULT_RANK_GAP, DEVICE_SIZE, DIAGRAM_TRAIT_KEY, DIVIDER_HEIGHT, EVENT_SIZE, GATEWAY_SIZE, PORT_LABEL_GAP, SIDE_TRACK_GAP, anchorOffset, authoredOver, axesFor, backEdges, bodyOutline, bodyTrait, boxForContent, buildBody, canvasMeasure, center, chain, contentBox, createDiagramNodes, dataKeyReader, diagramEdgeOf, diagramNodeOf, expandGroupEdges, extent, footprintNode, force, forceRelaxation, forestOf, graphOrder, grownBy, insetOf, isPinned, isPromise, labelCenter, labelSpotAt, layered, layeredPlan, layeredRoutes, layoutBody, layoutOwnsPort, layoutOwnsRoute, layoutRowPorts, layoutWritesRoute, marginOf, measureBody, outlineDetail, outlineFromD, outlinePath, outlinePolyline, packAcross, packClusters, pinnedSet, planOf, plannerPlan, portLabelBox, portLabelsOf, portOf, portSitesOf, portsOf, portsOnOutline, rankGaps, ranksByLength, ranksOf, rayHit, registerOutline, resolveOutline, routeHolds, rowHeights, samePoints, seededOrder, settle, sizeToBody, subpathOf, subtreeBlocks, translated, tree, untilSettled, widenForMinWidth };
|
|
3719
|
+
//# sourceMappingURL=chunk-VB6HUKNG.js.map
|
|
3720
|
+
//# sourceMappingURL=chunk-VB6HUKNG.js.map
|