@weasel-js/diagram 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +696 -4
  2. package/dist/chunk-2SYY4W3B.js +2055 -0
  3. package/dist/chunk-2SYY4W3B.js.map +1 -0
  4. package/dist/chunk-5GIP2LA6.js +312 -0
  5. package/dist/chunk-5GIP2LA6.js.map +1 -0
  6. package/dist/chunk-DYDX6EJC.js +3653 -0
  7. package/dist/chunk-DYDX6EJC.js.map +1 -0
  8. package/dist/chunk-GA4BX7SH.js +1431 -0
  9. package/dist/chunk-GA4BX7SH.js.map +1 -0
  10. package/dist/{chunk-NUMMW5BI.js → chunk-R2XB6D32.js} +416 -36
  11. package/dist/chunk-R2XB6D32.js.map +1 -0
  12. package/dist/chunk-WDIE35AK.js +3 -0
  13. package/dist/chunk-WDIE35AK.js.map +1 -0
  14. package/dist/{fromData-GKqRgPFs.d.ts → dataTypes-DHdkzCL8.d.ts} +238 -59
  15. package/dist/effect-audio.d.ts +139 -0
  16. package/dist/effect-audio.js +533 -0
  17. package/dist/effect-audio.js.map +1 -0
  18. package/dist/effect.d.ts +486 -121
  19. package/dist/effect.js +1632 -347
  20. package/dist/effect.js.map +1 -1
  21. package/dist/icons.table.d.ts +6 -0
  22. package/dist/icons.table.js +32 -0
  23. package/dist/icons.table.js.map +1 -0
  24. package/dist/icons.table.json +24 -0
  25. package/dist/index.d.ts +2159 -92
  26. package/dist/index.js +1056 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/layout.d.ts +3 -3
  29. package/dist/layout.entry-B-jJMc50.d.ts +617 -0
  30. package/dist/layout.js +3 -1
  31. package/dist/stageTypes-DvnR8cKQ.d.ts +189 -0
  32. package/dist/{body-2lC7IiIA.d.ts → types-M_ccNAlk.d.ts} +221 -182
  33. package/package.json +28 -7
  34. package/dist/chunk-C4NAI6NV.js +0 -2041
  35. package/dist/chunk-C4NAI6NV.js.map +0 -1
  36. package/dist/chunk-NUMMW5BI.js.map +0 -1
  37. package/dist/layout.entry-BoWFcR4G.d.ts +0 -285
@@ -1,2041 +0,0 @@
1
- import { grownBy, isPromise, DIAGRAM_TRAIT_KEY, insetOf, portsOf, portSitesOf, outlinePath, plannerPlan, planOf, layered, diagramNodeOf, forceRelaxation, center, expandGroupEdges, chain, force, tree, DEFAULT_GROUP_INSET, sizeToBody, measureBody, bodyTrait, authoredOver, isPinned, buildBody } from './chunk-NUMMW5BI.js';
2
- import { dragPanContribution, WeaselProvider, useScene, useSelection, useLatest, SceneCanvas, fitViewToBounds, AUTO_POSE_DESCRIPTOR, translatePoseViaDescriptor, polylineFromPoints, registerNodeShape, reconcileSpecs, nodeGates, effectivePose, usePoseRun, composeAffordanceLayer, pointAlongPath, RECT_POSE_DESCRIPTOR, commandFill, commandStroke, transformPath, pathFromD, paintsLayer, viewToTransform, ellipsePath, derivedDepOf } from '@weasel-js/core';
3
- import { forEachSegment, PATH_L, nearestOnLine, PATH_Q, nearestOnQuadratic, PATH_C, nearestOnCubic, portCurvePoints } from '@weasel-js/geom';
4
- import { AUTO_POSE_DESCRIPTOR as AUTO_POSE_DESCRIPTOR$1 } from '@weasel-js/core/math';
5
- import '@weasel-js/animator';
6
- import { forwardRef, useEffect, useMemo, useState, useImperativeHandle, useRef, useCallback } from 'react';
7
- import { jsx } from 'react/jsx-runtime';
8
-
9
- function traitOf(node) {
10
- const data = node.data;
11
- if (data === null || typeof data !== "object") return null;
12
- const trait = data[DIAGRAM_TRAIT_KEY];
13
- return trait !== null && typeof trait === "object" ? trait : null;
14
- }
15
- function diagramGroupOf(node) {
16
- const group = traitOf(node)?.group;
17
- return group !== null && typeof group === "object" ? group : null;
18
- }
19
- function diagramAnchorOf(node) {
20
- const anchor = traitOf(node)?.anchor;
21
- return anchor !== null && typeof anchor === "object" && "at" in anchor ? anchor : null;
22
- }
23
- function groupDerivePose(opts = {}) {
24
- const geometry = opts.geometry ?? AUTO_POSE_DESCRIPTOR;
25
- return (node, deps) => {
26
- const group = diagramGroupOf(node);
27
- if (group === null) return null;
28
- let x0 = Infinity;
29
- let y0 = Infinity;
30
- let x1 = -Infinity;
31
- let y1 = -Infinity;
32
- for (const dep of deps) {
33
- if (dep === void 0) continue;
34
- const b = grownBy(geometry.getBounds(dep.pose), traitOf(dep.node)?.margin);
35
- x0 = Math.min(x0, b.x);
36
- y0 = Math.min(y0, b.y);
37
- x1 = Math.max(x1, b.x + b.width);
38
- y1 = Math.max(y1, b.y + b.height);
39
- }
40
- if (!Number.isFinite(x0)) return null;
41
- return geometry.fromBounds(boxAround({ x: x0, y: y0, width: x1 - x0, height: y1 - y0 }, group), node.pose);
42
- };
43
- }
44
- function boxAround(union, group) {
45
- const inset = insetOf(group.inset);
46
- const width = union.width + inset.left + inset.right;
47
- const grow = Math.max(0, (group.minWidth ?? 0) - width);
48
- return {
49
- x: union.x - inset.left - grow / 2,
50
- y: union.y - inset.top,
51
- width: width + grow,
52
- height: union.height + inset.top + inset.bottom
53
- };
54
- }
55
- function anchorDerivePose(opts = {}) {
56
- const geometry = opts.geometry ?? AUTO_POSE_DESCRIPTOR;
57
- return (node, deps) => {
58
- const anchor = diagramAnchorOf(node);
59
- const dep = deps[0];
60
- if (anchor === null || dep === void 0) return null;
61
- const target = geometry.getBounds(dep.pose);
62
- const own = geometry.getBounds(node.pose);
63
- const self = anchor.self ?? anchor.at;
64
- const x = target.x + anchor.at.u * target.width + (anchor.offset?.x ?? 0) - self.u * own.width;
65
- const y = target.y + anchor.at.v * target.height + (anchor.offset?.y ?? 0) - self.v * own.height;
66
- return translatePoseViaDescriptor(node.pose, x - own.x, y - own.y, geometry);
67
- };
68
- }
69
- var DIAGRAM_GROUP = "diagram:group";
70
- var DIAGRAM_ANCHOR = "diagram:anchor";
71
- var GROUP_DERIVE_POSE = groupDerivePose();
72
- var ANCHOR_DERIVE_POSE = anchorDerivePose();
73
-
74
- // src/labelTrait.ts
75
- function diagramLabelOf(node) {
76
- const data = node.data;
77
- if (data === null || typeof data !== "object") return null;
78
- const trait = data.diagram;
79
- if (trait === null || typeof trait !== "object") return null;
80
- const label = trait.label;
81
- if (label === null || typeof label !== "object") return null;
82
- return "at" in label ? label : null;
83
- }
84
- var NAMED = { start: 0, mid: 0.5, end: 1 };
85
- function nearestStation(path, near2) {
86
- if (path.kind !== "polygon") return null;
87
- const { commands, coords } = path;
88
- let best = null;
89
- let heading = { x: 1, y: 0 };
90
- forEachSegment(commands, coords, (cmd, ci, x0, y0) => {
91
- let hit;
92
- let d;
93
- if (cmd === PATH_L) {
94
- hit = nearestOnLine(near2.x, near2.y, x0, y0, coords[ci], coords[ci + 1]);
95
- d = { x: coords[ci] - x0, y: coords[ci + 1] - y0 };
96
- } else if (cmd === PATH_Q) {
97
- hit = nearestOnQuadratic(near2.x, near2.y, x0, y0, coords[ci], coords[ci + 1], coords[ci + 2], coords[ci + 3]);
98
- const t = hit.t;
99
- d = {
100
- x: 2 * (1 - t) * (coords[ci] - x0) + 2 * t * (coords[ci + 2] - coords[ci]),
101
- y: 2 * (1 - t) * (coords[ci + 1] - y0) + 2 * t * (coords[ci + 3] - coords[ci + 1])
102
- };
103
- } else if (cmd === PATH_C) {
104
- hit = nearestOnCubic(
105
- near2.x,
106
- near2.y,
107
- x0,
108
- y0,
109
- coords[ci],
110
- coords[ci + 1],
111
- coords[ci + 2],
112
- coords[ci + 3],
113
- coords[ci + 4],
114
- coords[ci + 5]
115
- );
116
- const t = hit.t;
117
- const u = 1 - t;
118
- d = {
119
- x: 3 * u * u * (coords[ci] - x0) + 6 * u * t * (coords[ci + 2] - coords[ci]) + 3 * t * t * (coords[ci + 4] - coords[ci + 2]),
120
- y: 3 * u * u * (coords[ci + 1] - y0) + 6 * u * t * (coords[ci + 3] - coords[ci + 1]) + 3 * t * t * (coords[ci + 5] - coords[ci + 3])
121
- };
122
- } else return;
123
- const len = Math.hypot(d.x, d.y);
124
- if (len === 0 || best !== null && hit.dist >= best.dist) return;
125
- best = hit;
126
- heading = { x: d.x / len, y: d.y / len };
127
- });
128
- const found = best;
129
- return found === null ? null : { point: { x: found.x, y: found.y }, tangent: heading };
130
- }
131
- function labelCenter(path, label, size) {
132
- const station = typeof label.at === "object" ? nearestStation(path, label.at.near) ?? pointAlongPath(path, 0.5) : pointAlongPath(path, typeof label.at === "number" ? label.at : NAMED[label.at] ?? 0.5);
133
- if (station === null) return null;
134
- const nx = station.tangent.y;
135
- const ny = -station.tangent.x;
136
- const offset = label.offset ?? 0;
137
- const reach = offset + Math.sign(offset) * (Math.abs(nx) * size.width + Math.abs(ny) * size.height) / 2;
138
- return { x: station.point.x + nx * reach, y: station.point.y + ny * reach };
139
- }
140
- function labelDerivePose(opts = {}) {
141
- const geometry = opts.geometry ?? AUTO_POSE_DESCRIPTOR;
142
- return (node, deps) => {
143
- const label = diagramLabelOf(node);
144
- if (label === null) return null;
145
- const path = deps[0]?.path ?? null;
146
- if (path === null) return null;
147
- const bounds = geometry.getBounds(node.pose);
148
- const center2 = labelCenter(path, label, bounds);
149
- if (center2 === null) return null;
150
- return translatePoseViaDescriptor(
151
- node.pose,
152
- center2.x - (bounds.x + bounds.width / 2),
153
- center2.y - (bounds.y + bounds.height / 2),
154
- geometry
155
- );
156
- };
157
- }
158
- var DIAGRAM_LABEL = "diagram:label";
159
- var LABEL_DERIVE_POSE = labelDerivePose();
160
-
161
- // src/selfLoop.ts
162
- var dot = (a, b) => a.x * b.x + a.y * b.y;
163
- function selfLoop(ports, standoff) {
164
- const facing2 = ports.filter((p) => p.normal !== null);
165
- const most = (dir, among) => among.reduce(
166
- (best, p) => best === void 0 || dot(p.normal, dir) > dot(best.normal, dir) ? p : best,
167
- void 0
168
- );
169
- const from = most({ x: 1, y: 0 }, facing2);
170
- if (from === void 0) return null;
171
- const to = most({ x: 0, y: -1 }, facing2.filter((p) => Math.abs(dot(p.normal, from.normal)) < 0.5));
172
- if (to === void 0) return null;
173
- const out = { x: from.point.x + from.normal.x * standoff, y: from.point.y + from.normal.y * standoff };
174
- const reach = dot({ x: to.point.x - out.x, y: to.point.y - out.y }, to.normal) + standoff;
175
- return { from, to, via: { x: out.x + to.normal.x * reach, y: out.y + to.normal.y * reach } };
176
- }
177
-
178
- // src/edgeTrait.ts
179
- function layoutOwnsPort(end) {
180
- return end.port === void 0 || end.port === end.laidOut;
181
- }
182
- function layoutOwnsRoute(edge) {
183
- const points = edge.waypoints ?? [];
184
- if (points.length === 0) return true;
185
- return edge.laidOut !== void 0 && samePoints(points, edge.laidOut);
186
- }
187
- function samePoints(a, b) {
188
- return a.length === b.length && a.every((p, i) => p.x === b[i].x && p.y === b[i].y);
189
- }
190
- function diagramEdgeOf(node) {
191
- const data = node.data;
192
- if (data === null || typeof data !== "object") return null;
193
- const edge = data.diagram;
194
- if (edge === null || typeof edge !== "object") return null;
195
- return "from" in edge && "to" in edge ? edge : null;
196
- }
197
- var straight = (req) => [req.from.point, ...req.waypoints, req.to.point];
198
- var orthogonal = (req) => {
199
- const stops = [req.from.point, ...req.waypoints, req.to.point];
200
- const out = [stops[0]];
201
- for (let i = 1; i < stops.length; i++) {
202
- const a = out[out.length - 1];
203
- const b = stops[i];
204
- if (a.x === b.x || a.y === b.y) {
205
- out.push(b);
206
- continue;
207
- }
208
- const leaveHorizontal = i === 1 ? isHorizontal(req.from.normal) : out.length > 1 && out[out.length - 2].y === a.y;
209
- const arriving = i === stops.length - 1 ? req.to.normal : null;
210
- const arriveHorizontal = arriving == null ? !leaveHorizontal : isHorizontal(arriving);
211
- if (leaveHorizontal !== arriveHorizontal) {
212
- out.push(leaveHorizontal ? { x: b.x, y: a.y } : { x: a.x, y: b.y });
213
- out.push(b);
214
- continue;
215
- }
216
- const prev = out.length > 1 ? out[out.length - 2] : null;
217
- if (leaveHorizontal) {
218
- const mid = (a.x + b.x) / 2;
219
- if (prev !== null && (mid - a.x) * (a.x - prev.x) < 0) out.push({ x: a.x, y: b.y }, b);
220
- else out.push({ x: mid, y: a.y }, { x: mid, y: b.y }, b);
221
- } else {
222
- const mid = (a.y + b.y) / 2;
223
- if (prev !== null && (mid - a.y) * (a.y - prev.y) < 0) out.push({ x: b.x, y: a.y }, b);
224
- else out.push({ x: a.x, y: mid }, { x: b.x, y: mid }, b);
225
- }
226
- }
227
- return out;
228
- };
229
- function isHorizontal(normal) {
230
- return Math.abs(normal?.x ?? 1) >= Math.abs(normal?.y ?? 0);
231
- }
232
- var bezier = (req) => {
233
- const stops = [req.from.point, ...req.waypoints, req.to.point];
234
- const out = [stops[0]];
235
- for (let i = 1; i < stops.length; i++) {
236
- const a = stops[i - 1];
237
- const b = stops[i];
238
- const outN = i === 1 ? req.from.normal : through(stops, i - 1);
239
- const inN = i === stops.length - 1 ? req.to.normal : negated(through(stops, i));
240
- const leg = portCurvePoints(
241
- a.x,
242
- a.y,
243
- b.x,
244
- b.y,
245
- outN == null ? null : [outN.x, outN.y],
246
- inN == null ? null : [inN.x, inN.y],
247
- BEZIER_SAMPLES
248
- );
249
- for (const [x, y] of leg) out.push({ x, y });
250
- }
251
- return out;
252
- };
253
- var BEZIER_SAMPLES = 16;
254
- function through(stops, i) {
255
- const last = stops.length - 1;
256
- const run = (a, b) => a >= 1 && b <= last - 1 && (stops[a].x === stops[b].x || stops[a].y === stops[b].y);
257
- const [from, to] = run(i, i + 1) ? [i, i + 1] : run(i - 1, i) ? [i - 1, i] : [i - 1, i + 1];
258
- const dx = stops[to].x - stops[from].x;
259
- const dy = stops[to].y - stops[from].y;
260
- const len = Math.hypot(dx, dy);
261
- return len === 0 ? null : { x: dx / len, y: dy / len };
262
- }
263
- var negated = (v) => v === null ? null : { x: -v.x, y: -v.y };
264
- var ROUTERS = Object.freeze({
265
- straight,
266
- orthogonal,
267
- bezier
268
- });
269
- function resolveEnd(end, dep, toward, opts, allPorts) {
270
- if (end.port !== void 0) {
271
- const sites = portSitesOf(dep.node, dep.pose, end.port, opts);
272
- const ahead = sites.filter((p) => p.normal !== null && p.normal.x * (toward.x - p.point.x) + p.normal.y * (toward.y - p.point.y) > 0);
273
- if (sites.length > 0) return ahead.length > 0 ? facing(ahead, toward) : sites[0];
274
- }
275
- return facing(allPorts(dep), toward);
276
- }
277
- function facing(ports, toward) {
278
- let best;
279
- let bestScore = -Infinity;
280
- for (const port of ports) {
281
- const dx = toward.x - port.point.x;
282
- const dy = toward.y - port.point.y;
283
- const len = Math.hypot(dx, dy) || 1;
284
- const aim = port.normal === null ? 0 : (port.normal.x * dx + port.normal.y * dy) / len;
285
- const score = aim - len / 1e6;
286
- if (score > bestScore) {
287
- bestScore = score;
288
- best = port;
289
- }
290
- }
291
- return best;
292
- }
293
- function edgeDerivePath(opts = {}) {
294
- const geometry = opts.geometry ?? AUTO_POSE_DESCRIPTOR;
295
- const portOpts = { geometry, ...opts.read ? { read: opts.read } : {} };
296
- const allPorts = (d) => portsOf(d.node, d.pose, portOpts);
297
- const centerOf = (d) => {
298
- const b = geometry.getBounds(d.pose);
299
- return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
300
- };
301
- const standoffOf = (d) => {
302
- const b = geometry.getBounds(d.pose);
303
- return Math.min(b.width, b.height) / 2;
304
- };
305
- return (node, deps) => {
306
- const edge = diagramEdgeOf(node);
307
- if (edge === null) return null;
308
- const [fromDep, toDep] = deps;
309
- if (fromDep === void 0 || toDep === void 0) return null;
310
- const loop = fromDep.node.id === toDep.node.id && edge.from.port === void 0 && edge.to.port === void 0 ? selfLoop(allPorts(fromDep), opts.selfLoopStandoff ?? standoffOf(fromDep)) : null;
311
- const authored = edge.waypoints ?? [];
312
- const from = loop?.from ?? resolveEnd(edge.from, fromDep, authored[0] ?? centerOf(toDep), portOpts, allPorts);
313
- const to = loop?.to ?? resolveEnd(edge.to, toDep, authored[authored.length - 1] ?? centerOf(fromDep), portOpts, allPorts);
314
- if (from === void 0 || to === void 0) return null;
315
- const waypoints = loop !== null && authored.length === 0 ? [loop.via] : authored;
316
- const routers = opts.routers ?? ROUTERS;
317
- const router = edge.router !== void 0 && routers[edge.router] || straight;
318
- const points = router({ from, to, waypoints });
319
- return points.length < 2 ? null : polylineFromPoints(points);
320
- };
321
- }
322
- var DIAGRAM_EDGE = "diagram:edge";
323
- var EDGE_DERIVE_PATH = edgeDerivePath();
324
- function withDiagramRegistry(registry = {}) {
325
- return {
326
- ...registry,
327
- derivePath: {
328
- [DIAGRAM_EDGE]: EDGE_DERIVE_PATH,
329
- ...registry.derivePath
330
- },
331
- derivePose: {
332
- [DIAGRAM_LABEL]: LABEL_DERIVE_POSE,
333
- [DIAGRAM_GROUP]: GROUP_DERIVE_POSE,
334
- [DIAGRAM_ANCHOR]: ANCHOR_DERIVE_POSE,
335
- ...registry.derivePose
336
- }
337
- };
338
- }
339
- var PORT_LAYER_ID = "diagram-ports";
340
- var PORT_AFFORDANCE_KIND = `layer:${PORT_LAYER_ID}`;
341
- function offersPorts(p, view) {
342
- return p.hidden !== true && p.locked !== true && paintsLayer(view, p.layer);
343
- }
344
- var DEFAULT_HIT_PX = 8;
345
- var DEFAULT_SIZE_PX = 7;
346
- function portScratchOf(hit) {
347
- const payload = hit?.payload;
348
- return payload !== void 0 && typeof payload.portId === "string" ? payload : null;
349
- }
350
- function withPaint(paint) {
351
- return paint === void 0 ? {} : { paint };
352
- }
353
- function createPortAffordance(participants, opts = {}) {
354
- const {
355
- id = PORT_LAYER_ID,
356
- hitRadiusPx = DEFAULT_HIT_PX,
357
- sizePx = DEFAULT_SIZE_PX,
358
- strength = "exclusive"
359
- } = opts;
360
- const portOpts = {
361
- ...opts.geometry ? { geometry: opts.geometry } : {},
362
- ...opts.read ? { read: opts.read } : {}
363
- };
364
- const paintOf = (port) => {
365
- if (sizePx <= 0) return void 0;
366
- const fill = typeof opts.fill === "function" ? opts.fill(port) : opts.fill;
367
- const look = { ...fill ? { fill } : {}, ...opts.stroke ? { stroke: opts.stroke } : {} };
368
- if (opts.shape !== "circle") return { kind: "square", sizePx, ...look };
369
- return {
370
- kind: "custom",
371
- // An affordance layer paints in screen pixels, so the mark stays one size at any zoom.
372
- draw: ({ world, view }) => {
373
- const t = viewToTransform(view);
374
- const x = t.panX + world.x * t.zoom.x - sizePx / 2;
375
- const y = t.panY + world.y * t.zoom.y - sizePx / 2;
376
- return [{ kind: "path", path: ellipsePath({ x, y, width: sizePx, height: sizePx }), ...look }];
377
- }
378
- };
379
- };
380
- return {
381
- id,
382
- regions(state) {
383
- const out = [];
384
- for (const participant of participants()) {
385
- if (!offersPorts(participant, state)) continue;
386
- const { node, pose } = participant;
387
- if (opts.shows !== void 0 && !opts.shows(node, state)) continue;
388
- for (const port of portsOf(node, pose, portOpts)) {
389
- if (opts.showsPort !== void 0 && !opts.showsPort(port)) continue;
390
- out.push({
391
- id: `${node.id}:${port.id}`,
392
- targetId: null,
393
- shape: { kind: "point", x: port.point.x, y: port.point.y, hitRadiusPx },
394
- ...withPaint(paintOf(port)),
395
- ...opts.cursor !== void 0 ? { cursor: opts.cursor } : {},
396
- strength,
397
- claimedKinds: ["pointer"],
398
- bind: () => ({
399
- initialScratch: {
400
- targetId: node.id,
401
- nodeId: node.id,
402
- portId: port.id,
403
- port
404
- }
405
- })
406
- });
407
- }
408
- }
409
- return out;
410
- }
411
- };
412
- }
413
- var CONNECT_ACTION_ID = "diagram.connect";
414
- var defaultCanConnect = (from, to) => {
415
- if (from.nodeId === to.nodeId && from.id === to.id) return false;
416
- if (from.type === void 0 || to.type === void 0) return true;
417
- return from.type === to.type;
418
- };
419
- var DEFAULT_SNAP = 16;
420
- var DEFAULT_EDGE_STROKE = {
421
- paint: { color: "#7ba7c7" },
422
- width: 2,
423
- markerEnd: "arrow"
424
- };
425
- var DEFAULT_ROUTER = "straight";
426
- function connectBinding(actionId = CONNECT_ACTION_ID) {
427
- return {
428
- spec: { kind: "drag", target: `affordance:${PORT_AFFORDANCE_KIND}` },
429
- actionId
430
- };
431
- }
432
- var GRAB_PORT_ACTION_ID = "diagram.grabPort";
433
- function grabPortAction(id = GRAB_PORT_ACTION_ID) {
434
- return {
435
- id,
436
- label: "Grab port",
437
- group: "diagram",
438
- invoker: { timing: "immediate", run: () => {
439
- } },
440
- enabled: () => true
441
- };
442
- }
443
- function grabPortBindings(actionId = GRAB_PORT_ACTION_ID) {
444
- return [
445
- { spec: { kind: "pointerDown", target: `affordance:${PORT_AFFORDANCE_KIND}` }, actionId },
446
- { spec: { kind: "click", target: `affordance:${PORT_AFFORDANCE_KIND}` }, actionId }
447
- ];
448
- }
449
- function commitEdgeToScene(edge, ctx) {
450
- const scene = ctx.deps.scene;
451
- if (scene === void 0) return;
452
- const trait = {
453
- from: { port: edge.from.id },
454
- to: { port: edge.to.id },
455
- router: edge.router
456
- };
457
- const source = scene.get(edge.from.nodeId);
458
- scene.add({
459
- kind: "leaf",
460
- layer: source?.layer ?? scene.layers[0].id,
461
- pose: { x: 0, y: 0, width: 0, height: 0 },
462
- data: { diagram: trait, stroke: DEFAULT_EDGE_STROKE },
463
- dependsOn: [edge.from.nodeId, edge.to.nodeId],
464
- // Without this the edge re-resolves on every dependency move and paints
465
- // nothing. `EDGE_DERIVE_PATH` rather than a fresh `edgeDerivePath()` so the
466
- // scene can find its registry key and the edge survives `toJSON`.
467
- derivePath: EDGE_DERIVE_PATH
468
- });
469
- }
470
- function createConnectAction(opts) {
471
- const {
472
- id = CONNECT_ACTION_ID,
473
- canConnect = defaultCanConnect,
474
- snapRadius = DEFAULT_SNAP,
475
- router: routerKey = DEFAULT_ROUTER,
476
- commit = commitEdgeToScene
477
- } = opts;
478
- const routers = opts.routers ?? ROUTERS;
479
- const portOpts = {
480
- ...opts.geometry ? { geometry: opts.geometry } : {},
481
- ...opts.read ? { read: opts.read } : {}
482
- };
483
- const route = routers[routerKey] ?? routers["straight"] ?? ROUTERS["straight"];
484
- function targetPort(from, at, view) {
485
- let best = null;
486
- let bestD2 = snapRadius * snapRadius;
487
- for (const participant of opts.participants()) {
488
- if (!offersPorts(participant, view)) continue;
489
- for (const port of portsOf(participant.node, participant.pose, portOpts)) {
490
- if (opts.showsPort !== void 0 && !opts.showsPort(port)) continue;
491
- if (!canConnect(from, port)) continue;
492
- const d2 = (port.point.x - at.x) ** 2 + (port.point.y - at.y) ** 2;
493
- if (d2 <= bestD2) {
494
- bestD2 = d2;
495
- best = port;
496
- }
497
- }
498
- }
499
- return best;
500
- }
501
- function endAt(scratch, at) {
502
- const port = targetPort(scratch.from, at, scratch.deps.view);
503
- return {
504
- port,
505
- end: port ?? { id: "", nodeId: "", point: at, normal: null }
506
- };
507
- }
508
- return {
509
- id,
510
- label: "Connect",
511
- group: "diagram",
512
- requires: ["scene"],
513
- invoker: {
514
- timing: "ongoing",
515
- start(ctx) {
516
- const pressed = portScratchOf(ctx.drag?.affordance);
517
- if (pressed === null) return {};
518
- const scratch = {
519
- from: pressed.port,
520
- current: { x: ctx.world.x, y: ctx.world.y },
521
- open: true,
522
- deps: ctx.deps
523
- };
524
- return {
525
- kind: "diagram-connect",
526
- onMove(moveCtx) {
527
- scratch.current = { x: moveCtx.world.x, y: moveCtx.world.y };
528
- },
529
- overlay() {
530
- if (!scratch.open) return null;
531
- const { end } = endAt(scratch, scratch.current);
532
- const points = route({ from: scratch.from, to: end, waypoints: [] });
533
- if (points.length < 2) return null;
534
- return { kind: "polyline", points, role: "connector" };
535
- },
536
- onEnd(endCtx, reason) {
537
- scratch.open = false;
538
- if (reason === "cancel") return;
539
- const { port } = endAt(scratch, { x: endCtx.world.x, y: endCtx.world.y });
540
- if (port === null) return;
541
- commit(
542
- { from: scratch.from, to: port, router: routerKey },
543
- { ...endCtx, deps: scratch.deps }
544
- );
545
- }
546
- };
547
- }
548
- },
549
- enabled: () => true
550
- };
551
- }
552
- function sceneParticipants(scene) {
553
- return function* () {
554
- const gates = nodeGates(scene);
555
- for (const node of scene.renderOrderNodes()) {
556
- const hidden = gates.hidden(node.id);
557
- const locked = gates.locked(node.id);
558
- yield {
559
- node,
560
- pose: effectivePose(scene, node),
561
- ...node.layer !== void 0 ? { layer: node.layer } : {},
562
- ...hidden ? { hidden } : {},
563
- ...locked ? { locked } : {}
564
- };
565
- }
566
- };
567
- }
568
- function portLayer(participants, opts = {}) {
569
- return composeAffordanceLayer(
570
- opts.id ?? PORT_LAYER_ID,
571
- "Diagram ports",
572
- [createPortAffordance(participants, opts)]
573
- );
574
- }
575
-
576
- // src/contribution.ts
577
- function createDiagramContribution(opts) {
578
- const actionId = opts.id ?? CONNECT_ACTION_ID;
579
- return {
580
- id: "weasel-diagram",
581
- eligibility: { claimed: true },
582
- actions: [createConnectAction({ ...opts, id: actionId }), grabPortAction()],
583
- bindings: [connectBinding(actionId), ...grabPortBindings()]
584
- };
585
- }
586
- function diagramPorts(opts) {
587
- return {
588
- layer: portLayer(opts.participants, opts),
589
- contribution: createDiagramContribution(opts)
590
- };
591
- }
592
-
593
- // src/groupTree.ts
594
- function nestGroups(declared, isNode) {
595
- const groupIds = new Set(declared.map((g) => g.id));
596
- const parentOf = /* @__PURE__ */ new Map();
597
- const claimedNodes = /* @__PURE__ */ new Set();
598
- const direct = /* @__PURE__ */ new Map();
599
- const isAncestorOrSelf = (candidate, of) => {
600
- for (let at = of; at !== void 0; at = parentOf.get(at)) {
601
- if (at === candidate) return true;
602
- }
603
- return false;
604
- };
605
- for (const group of declared) {
606
- const own = [];
607
- for (const id of group.members) {
608
- if (isNode(id)) {
609
- if (claimedNodes.has(id)) continue;
610
- claimedNodes.add(id);
611
- own.push(id);
612
- } else if (groupIds.has(id) && !parentOf.has(id) && !isAncestorOrSelf(id, group.id)) {
613
- parentOf.set(id, group.id);
614
- own.push(id);
615
- }
616
- }
617
- direct.set(group.id, own);
618
- }
619
- const flat = /* @__PURE__ */ new Map();
620
- const flatten = (id) => {
621
- const known = flat.get(id);
622
- if (known !== void 0) return known;
623
- const out = [];
624
- for (const member of direct.get(id)) {
625
- if (groupIds.has(member)) out.push(...flatten(member));
626
- else out.push(member);
627
- }
628
- flat.set(id, out);
629
- return out;
630
- };
631
- const live = new Set(declared.filter((g) => flatten(g.id).length > 0).map((g) => g.id));
632
- return declared.filter((g) => live.has(g.id)).map((g) => {
633
- const parent = parentOf.get(g.id);
634
- return {
635
- id: g.id,
636
- direct: direct.get(g.id).filter((id) => !groupIds.has(id) || live.has(id)),
637
- members: flat.get(g.id),
638
- ...parent !== void 0 ? { parent } : {}
639
- };
640
- });
641
- }
642
-
643
- // src/graph.ts
644
- function buildGraph(source, opts = {}) {
645
- const geometry = opts.geometry ?? AUTO_POSE_DESCRIPTOR$1;
646
- const nodes = [];
647
- const byId = /* @__PURE__ */ new Map();
648
- const candidates = [];
649
- const groupNodes = [];
650
- const routed = /* @__PURE__ */ new Set();
651
- const rooms = /* @__PURE__ */ new Map();
652
- for (const { node, pose } of source()) {
653
- const edge = diagramEdgeOf(node);
654
- if (edge !== null) {
655
- const deps = node.dependsOn;
656
- if (Array.isArray(deps) && deps.length === 2) {
657
- candidates.push({
658
- id: node.id,
659
- from: deps[0],
660
- to: deps[1],
661
- ...edge.from.port !== void 0 ? { fromPort: edge.from.port } : {},
662
- ...edge.to.port !== void 0 ? { toPort: edge.to.port } : {},
663
- ...edge.waypoints !== void 0 && edge.waypoints.length > 0 ? { waypoints: edge.waypoints } : {},
664
- ...layoutOwnsRoute(edge) ? {} : { authored: true }
665
- });
666
- if (layoutOwnsRoute(edge)) routed.add(node.id);
667
- }
668
- continue;
669
- }
670
- const label = diagramLabelOf(node);
671
- if (label !== null) {
672
- const deps = node.dependsOn;
673
- if (Array.isArray(deps) && deps.length === 1 && labelFollowsLayout(label.at) && !rooms.has(deps[0])) {
674
- const { width, height } = geometry.getBounds(pose);
675
- rooms.set(deps[0], { width, height, ...label.offset ? { offset: label.offset } : {} });
676
- }
677
- continue;
678
- }
679
- const trait = diagramNodeOf(node, opts.read);
680
- if (trait === null) continue;
681
- if (trait.group !== void 0) {
682
- const deps = node.dependsOn;
683
- groupNodes.push({
684
- id: node.id,
685
- members: Array.isArray(deps) ? deps : [],
686
- inset: insetOf(trait.group.inset),
687
- ...trait.group.minWidth !== void 0 ? { minWidth: trait.group.minWidth } : {}
688
- });
689
- continue;
690
- }
691
- const entry = {
692
- id: node.id,
693
- bounds: geometry.getBounds(pose),
694
- pinned: trait.pinned === true,
695
- ...trait.ports !== void 0 ? { ports: trait.ports } : {},
696
- ...trait.outline !== void 0 ? { outline: trait.outline } : {},
697
- ...trait.margin !== void 0 ? { margin: trait.margin } : {}
698
- };
699
- nodes.push(entry);
700
- byId.set(entry.id, entry);
701
- }
702
- const declared = new Map(groupNodes.map((g) => [g.id, g]));
703
- const live = nestGroups(groupNodes, (id) => byId.has(id)).map((g) => {
704
- for (const id of g.direct) {
705
- const node = byId.get(id);
706
- if (node !== void 0) node.group = g.id;
707
- }
708
- return {
709
- id: g.id,
710
- members: g.members,
711
- inset: declared.get(g.id).inset,
712
- ...declared.get(g.id).minWidth !== void 0 ? { minWidth: declared.get(g.id).minWidth } : {},
713
- ...g.parent !== void 0 ? { parent: g.parent } : {}
714
- };
715
- });
716
- const known = (id) => byId.has(id) || live.some((g) => g.id === id);
717
- const roomed = candidates.map((e) => {
718
- const room = rooms.get(e.id);
719
- return room !== void 0 && routed.has(e.id) ? { ...e, label: room } : e;
720
- });
721
- const edges = expandGroupEdges(roomed.filter((e) => known(e.from) && known(e.to)), live);
722
- const out = /* @__PURE__ */ new Map();
723
- const into = /* @__PURE__ */ new Map();
724
- for (const edge of edges) {
725
- push(out, edge.from, edge);
726
- push(into, edge.to, edge);
727
- }
728
- const NONE2 = Object.freeze([]);
729
- return {
730
- nodes,
731
- edges,
732
- groups: live,
733
- node: (id) => byId.get(id),
734
- outgoing: (id) => out.get(id) ?? NONE2,
735
- incoming: (id) => into.get(id) ?? NONE2
736
- };
737
- }
738
- function labelFollowsLayout(at) {
739
- return at === "mid" || typeof at === "object";
740
- }
741
- function push(index, key, edge) {
742
- const list = index.get(key);
743
- if (list === void 0) index.set(key, [edge]);
744
- else list.push(edge);
745
- }
746
- function diagramMarkOf(node) {
747
- const data = node.data;
748
- if (data === null || typeof data !== "object") return null;
749
- const trait = data[DIAGRAM_TRAIT_KEY];
750
- if (trait === null || typeof trait !== "object" || !("mark" in trait)) return null;
751
- const mark = trait.mark;
752
- return mark !== null && typeof mark === "object" && typeof mark.d === "string" ? mark : null;
753
- }
754
- var PARSED = /* @__PURE__ */ new Map();
755
- var PARSED_MAX = 256;
756
- function unitPath(d, onWarn) {
757
- let path = PARSED.get(d);
758
- if (path === void 0) {
759
- let warned = false;
760
- path = pathFromD(d, (message) => {
761
- warned = true;
762
- onWarn?.(message);
763
- });
764
- if (path.kind === "polygon" && path.commands.length === 0) onWarn?.("it draws nothing");
765
- else if (!warned) {
766
- if (PARSED.size >= PARSED_MAX) PARSED.clear();
767
- PARSED.set(d, path);
768
- }
769
- }
770
- return path;
771
- }
772
- function checkMarkPath(nodeId, index, d) {
773
- unitPath(d, (message) => {
774
- throw new Error(`diagramScene: node "${nodeId}", mark ${index}: path data ${JSON.stringify(d)} does not parse: ${message}`);
775
- });
776
- }
777
- function markShape(opts = {}) {
778
- const geometry = opts.geometry ?? RECT_POSE_DESCRIPTOR;
779
- return {
780
- id: "diagram:mark",
781
- matches: (node) => diagramMarkOf(node) !== null,
782
- paint: (node, pose) => {
783
- const mark = diagramMarkOf(node);
784
- if (mark === null) return [];
785
- const box = geometry.getBounds(pose);
786
- const d = node.data;
787
- const fill = d.fill && commandFill(d.fill, box);
788
- const stroke = d.stroke && commandStroke(d.stroke, box);
789
- return [{
790
- kind: "path",
791
- path: transformPath(unitPath(mark.d), [box.width, 0, 0, box.height, box.x, box.y]),
792
- ...fill ? { fill } : {},
793
- ...stroke ? { stroke } : {}
794
- }];
795
- }
796
- };
797
- }
798
- function registerMarkShape(opts = {}) {
799
- return registerNodeShape(markShape(opts), { priority: "high" });
800
- }
801
- function markSpecs(nodeId, marks, box, ctx) {
802
- return marks.map((mark, i) => {
803
- const id = `${nodeId}/mark:${i}`;
804
- if ("d" in mark) {
805
- checkMarkPath(nodeId, i, mark.d);
806
- const paint = (color) => ({ color, ...mark.opacity !== void 0 ? { opacity: mark.opacity } : {} });
807
- const stroke = mark.stroke ?? (mark.fill === void 0 ? ctx.style.stroke : void 0);
808
- return {
809
- id,
810
- kind: "leaf",
811
- layer: "main",
812
- parent: nodeId,
813
- pickable: false,
814
- pose: { x: box.x, y: box.y, width: box.width, height: box.height },
815
- data: {
816
- diagram: { mark: { d: mark.d } },
817
- ...mark.fill !== void 0 ? { fill: { paint: paint(mark.fill) } } : {},
818
- ...stroke !== void 0 ? { stroke: { paint: paint(stroke), width: mark.strokeWidth ?? 1.5, ...mark.dash ? { dash: mark.dash } : {} } } : {}
819
- }
820
- };
821
- }
822
- const size = ctx.measure(mark.text, mark.style ?? {});
823
- const self = mark.self ?? mark.at;
824
- return {
825
- id,
826
- kind: "leaf",
827
- layer: "main",
828
- pickable: false,
829
- pose: {
830
- x: box.x + mark.at.u * box.width + (mark.offset?.x ?? 0) - self.u * size.width,
831
- y: box.y + mark.at.v * box.height + (mark.offset?.y ?? 0) - self.v * size.height,
832
- width: size.width,
833
- height: size.height
834
- },
835
- data: {
836
- diagram: { anchor: { at: mark.at, self, ...mark.offset ? { offset: mark.offset } : {} } },
837
- text: mark.text,
838
- style: ctx.textStyle(mark.style),
839
- fill: { paint: { color: mark.color ?? ctx.style.text } }
840
- },
841
- dependsOn: [nodeId],
842
- derivePose: ANCHOR_DERIVE_POSE
843
- };
844
- });
845
- }
846
-
847
- // src/dataGroups.ts
848
- function resolveGroups(groups, ids, nodeIds, opts) {
849
- for (const group of groups) {
850
- if (ids.has(group.id)) throw new Error(`diagramScene: group id "${group.id}" is already a node or group id`);
851
- ids.add(group.id);
852
- }
853
- const declared = new Map(groups.map((g) => [g.id, g]));
854
- const nested = nestGroups(groups, (id) => nodeIds.has(id));
855
- const depthOf = /* @__PURE__ */ new Map();
856
- const byId = new Map(nested.map((g) => [g.id, g]));
857
- const depth = (id) => {
858
- const parent = byId.get(id).parent;
859
- let d = depthOf.get(id);
860
- if (d === void 0) depthOf.set(id, d = parent === void 0 ? 0 : depth(parent) + 1);
861
- return d;
862
- };
863
- return nested.map((g, i) => ({ g, i })).sort((a, b) => depth(a.g.id) - depth(b.g.id) || a.i - b.i).map(({ g }) => {
864
- const group = declared.get(g.id);
865
- const pad = group.padding ?? opts.padding;
866
- const title = group.label ? opts.title(group.label) : null;
867
- const inset = { top: pad + (title ? title.height + pad / 2 : 0), right: pad, bottom: pad, left: pad };
868
- return {
869
- group,
870
- direct: g.direct,
871
- members: g.members,
872
- inset,
873
- pad,
874
- title,
875
- ...title ? { minWidth: title.width + 2 * pad } : {},
876
- ...g.parent !== void 0 ? { parent: g.parent } : {}
877
- };
878
- });
879
- }
880
- function labelsByGroup(groups, labels) {
881
- const byId = new Map(groups.map((g) => [g.group.id, g]));
882
- const holder = /* @__PURE__ */ new Map();
883
- for (const g of groups) for (const m of g.direct) holder.set(m, g.group.id);
884
- const ancestry = (id) => {
885
- const out2 = [];
886
- for (let at = byId.has(id) ? byId.get(id).parent : holder.get(id); at !== void 0; at = byId.get(at)?.parent) out2.push(at);
887
- return out2;
888
- };
889
- const out = /* @__PURE__ */ new Map();
890
- for (const label of labels) {
891
- const up = new Set(ancestry(label.to));
892
- const shared = ancestry(label.from).find((g) => up.has(g));
893
- if (shared !== void 0) out.set(shared, [...out.get(shared) ?? [], label]);
894
- }
895
- return out;
896
- }
897
- function groupBoxes(groups, placedAt, labels = /* @__PURE__ */ new Map()) {
898
- const byId = new Map(groups.map((g) => [g.group.id, g]));
899
- const boxes = /* @__PURE__ */ new Map();
900
- const boxOf = (id) => {
901
- const known = boxes.get(id);
902
- if (known !== void 0) return known;
903
- const g = byId.get(id);
904
- const rs = g.direct.map((m) => byId.has(m) ? boxOf(m) : placedAt.get(m));
905
- for (const label of labels.get(id) ?? []) if (label.at !== null) rs.push(label.at);
906
- const x = Math.min(...rs.map((r) => r.x));
907
- const y = Math.min(...rs.map((r) => r.y));
908
- const box = boxAround({
909
- x,
910
- y,
911
- width: Math.max(...rs.map((r) => r.x + r.width)) - x,
912
- height: Math.max(...rs.map((r) => r.y + r.height)) - y
913
- }, g);
914
- boxes.set(id, box);
915
- return box;
916
- };
917
- for (const g of groups) boxOf(g.group.id);
918
- return boxes;
919
- }
920
- function groupSpecs(groups, placedAt, styleOf, wireLabels2 = []) {
921
- const labels = labelsByGroup(groups, wireLabels2);
922
- const boxes = groupBoxes(groups, placedAt, labels);
923
- const specs = [];
924
- for (const g of groups) {
925
- const { style, text } = styleOf(g.group);
926
- const { x, y, width, height } = boxes.get(g.group.id);
927
- specs.push({
928
- id: g.group.id,
929
- kind: "leaf",
930
- layer: "main",
931
- pose: { x, y, width, height },
932
- data: {
933
- diagram: { outline: "rect", group: { inset: g.inset, ...g.minWidth !== void 0 ? { minWidth: g.minWidth } : {} } },
934
- fill: { paint: { color: style.fill } },
935
- stroke: {
936
- paint: { color: style.stroke },
937
- width: style.strokeWidth ?? 1,
938
- ...style.dash ? { dash: style.dash } : {}
939
- }
940
- },
941
- dependsOn: [...g.direct, ...(labels.get(g.group.id) ?? []).map((l) => l.id)],
942
- derivePose: GROUP_DERIVE_POSE
943
- });
944
- if (g.title === null || !g.group.label) continue;
945
- const anchor = { at: { u: 0, v: 0 }, offset: { x: g.pad, y: g.pad } };
946
- specs.push({
947
- id: `${g.group.id}/label`,
948
- kind: "leaf",
949
- layer: "main",
950
- pickable: false,
951
- pose: { x: x + g.pad, y: y + g.pad, width: g.title.width, height: g.title.height },
952
- data: { diagram: { anchor }, text: g.group.label, style: text, fill: { paint: { color: style.text } } },
953
- dependsOn: [g.group.id],
954
- derivePose: ANCHOR_DERIVE_POSE
955
- });
956
- }
957
- return specs;
958
- }
959
- var labelStyleOf = (font) => ({ ...font, fontSize: font.fontSize - 2 });
960
- function placementOf(e, route, ctx) {
961
- const placement = e.labelPlacement ?? ctx.opts.labelPlacement ?? ctx.labelPlacement;
962
- return route?.labelAt === void 0 ? placement : { ...placement, at: { near: route.labelAt } };
963
- }
964
- function labelSizeOf(text, ctx) {
965
- const style = labelStyleOf(ctx.font);
966
- return { width: ctx.measure(text, style).width, height: style.fontSize };
967
- }
968
- function wireLabels(edges, ctx) {
969
- const out = [];
970
- for (const e of edges) {
971
- if (!e.label) continue;
972
- const id = ctx.idOf(e);
973
- const route = ctx.routes?.get(id);
974
- const size = labelSizeOf(e.label, ctx);
975
- const placement = placementOf(e, route, ctx);
976
- const center2 = route?.waypoints !== void 0 && typeof placement.at === "object" ? labelCenter(polylineFromPoints([...route.waypoints]), placement, size) : null;
977
- out.push({
978
- id: `${id}/label`,
979
- from: e.from,
980
- to: e.to,
981
- at: center2 === null ? null : { x: center2.x - size.width / 2, y: center2.y - size.height / 2, ...size }
982
- });
983
- }
984
- return out;
985
- }
986
- var endOf = (own, port) => !port ? {} : own === void 0 ? { port, laidOut: port } : { port };
987
- function edgeSpecs(edges, ctx) {
988
- const specs = [];
989
- for (const e of edges) {
990
- const id = ctx.idOf(e);
991
- const route = ctx.routes?.get(id);
992
- const { fromPort, toPort, waypoints } = route ?? {
993
- fromPort: e.fromPort ?? e.routedPorts?.from,
994
- toPort: e.toPort ?? e.routedPorts?.to,
995
- waypoints: e.waypoints ?? e.routed
996
- };
997
- const laidOut = e.waypoints === void 0 && waypoints !== void 0;
998
- const style = ctx.opts.edgeStyle?.(e) ?? ctx.fallback;
999
- const markerStart = style.markerStart ?? null;
1000
- const markerEnd = style.markerEnd === void 0 ? "arrow" : style.markerEnd;
1001
- specs.push({
1002
- id,
1003
- kind: "leaf",
1004
- layer: "main",
1005
- pickable: false,
1006
- pose: { x: 0, y: 0, width: 0, height: 0 },
1007
- data: {
1008
- diagram: {
1009
- from: endOf(e.fromPort, fromPort),
1010
- to: endOf(e.toPort, toPort),
1011
- router: e.router ?? ctx.opts.router ?? "bezier",
1012
- ...waypoints ? { waypoints } : {},
1013
- ...laidOut ? { laidOut: waypoints } : {}
1014
- },
1015
- stroke: {
1016
- paint: { color: style.stroke },
1017
- width: style.width ?? 1.5,
1018
- ...style.dash ? { dash: style.dash } : {},
1019
- ...markerStart !== null ? { markerStart } : {},
1020
- ...markerEnd !== null ? { markerEnd } : {}
1021
- }
1022
- },
1023
- dependsOn: [e.from, e.to],
1024
- derivePath: EDGE_DERIVE_PATH
1025
- });
1026
- if (!e.label) continue;
1027
- const labelStyle = labelStyleOf(ctx.font);
1028
- specs.push({
1029
- id: `${id}/label`,
1030
- kind: "leaf",
1031
- layer: "main",
1032
- pickable: false,
1033
- pose: { x: 0, y: 0, ...labelSizeOf(e.label, ctx) },
1034
- data: {
1035
- diagram: { label: placementOf(e, route, ctx) },
1036
- text: e.label,
1037
- style: labelStyle,
1038
- fill: { paint: { color: style.label ?? style.stroke } }
1039
- },
1040
- dependsOn: [id],
1041
- derivePose: LABEL_DERIVE_POSE
1042
- });
1043
- }
1044
- return specs;
1045
- }
1046
-
1047
- // src/fromData.ts
1048
- var SLOT_FRAME = "M0 0H1V1H0Z";
1049
- var FONT = { fontFamily: "sans-serif", fontSize: 12 };
1050
- var NODE = { fill: "#16222c", stroke: "#7ba7c7", text: "#dbe7f2" };
1051
- var EDGE = { stroke: "#7ba7c7" };
1052
- var GROUP = { fill: "rgba(123, 167, 199, 0.08)", stroke: "#7ba7c7", text: "#9fbdd6", strokeWidth: 1, dash: [4, 3] };
1053
- var LABEL_PLACEMENT = { at: "mid", offset: 9 };
1054
- var LINE = 1.4;
1055
- var GLYPH = 0.6;
1056
- var MIN_WIDTH = 64;
1057
- var LAYOUTS = { layered, tree, force, chain };
1058
- var idPart = (s) => s.replace(/[\\.>:/]/g, "\\$&");
1059
- var edgeIdOf = (e) => {
1060
- const part = (mark, p) => p === void 0 ? "" : `${mark}${idPart(p)}`;
1061
- return `edge:${idPart(e.from)}${part(".", e.fromPort)}->${idPart(e.to)}${part(".", e.toPort)}${part(":", e.label)}`;
1062
- };
1063
- function graphOf(nodes, edges, groups = []) {
1064
- const byId = new Map(nodes.map((n) => [n.id, n]));
1065
- const out = /* @__PURE__ */ new Map();
1066
- const inc = /* @__PURE__ */ new Map();
1067
- for (const e of edges) {
1068
- out.set(e.from, [...out.get(e.from) ?? [], e]);
1069
- inc.set(e.to, [...inc.get(e.to) ?? [], e]);
1070
- }
1071
- return {
1072
- nodes,
1073
- edges,
1074
- groups,
1075
- node: (id) => byId.get(id),
1076
- outgoing: (id) => out.get(id) ?? [],
1077
- incoming: (id) => inc.get(id) ?? []
1078
- };
1079
- }
1080
- function labelRoomOf(e, opts, font, measure) {
1081
- if (!e.label || e.waypoints !== void 0) return null;
1082
- if (e.labelPlacement !== void 0 && !labelFollowsLayout(e.labelPlacement.at)) return null;
1083
- const style = labelStyleOf(font);
1084
- const offset = (e.labelPlacement ?? opts.labelPlacement ?? LABEL_PLACEMENT).offset;
1085
- return { width: measure(e.label, style).width, height: style.fontSize, ...offset !== void 0 ? { offset } : {} };
1086
- }
1087
- function graphEdgeOf(e, room) {
1088
- return {
1089
- id: edgeIdOf(e),
1090
- from: e.from,
1091
- to: e.to,
1092
- ...e.fromPort ? { fromPort: e.fromPort } : {},
1093
- ...e.toPort ? { toPort: e.toPort } : {},
1094
- ...room !== null ? { label: room } : {}
1095
- };
1096
- }
1097
- function placed(data, seeds, moved) {
1098
- return new Map(data.nodes.map((n, i) => {
1099
- const seed = seeds[i].bounds;
1100
- const at = moved.get(n.id) ?? seed;
1101
- return [n.id, { x: at.x, y: at.y, width: seed.width, height: seed.height }];
1102
- }));
1103
- }
1104
- function nodeSpecs(n, body, box, look) {
1105
- const { style } = look;
1106
- const textData = (text, s) => ({ text, style: look.text(s), fill: { paint: { color: style.text } } });
1107
- const built = buildBody(body, box, {
1108
- id: n.id,
1109
- layer: "main",
1110
- measure: look.measure,
1111
- body: (trait) => ({
1112
- diagram: n.pinned === true ? { ...trait, pinned: true } : trait,
1113
- fill: { paint: { color: style.fill } },
1114
- stroke: { paint: { color: style.stroke }, width: style.strokeWidth ?? 2, ...style.dash ? { dash: style.dash } : {} }
1115
- }),
1116
- row: (text, at) => at.row.kind === "slot" ? at.row.id === void 0 ? null : { diagram: { mark: { d: SLOT_FRAME } }, stroke: { paint: { color: style.stroke }, width: 1 } } : text === "" ? null : textData(text, at.row.kind === "label" || at.row.kind === "field" ? at.row.style : void 0),
1117
- portLabel: (text) => textData(text, void 0)
1118
- });
1119
- return built.specs.map((s, k) => ({ ...s, ...s.id !== void 0 ? {} : { id: `${n.id}/${k}` } }));
1120
- }
1121
- function diagramScene(data, opts = {}) {
1122
- const font = opts.font ?? FONT;
1123
- const styleOf = (s) => ({
1124
- fontFamily: s?.fontFamily ?? font.fontFamily,
1125
- fontSize: s?.fontSize ?? font.fontSize,
1126
- ...s?.bold === true ? { fontWeight: 700 } : {}
1127
- });
1128
- const measure = opts.measure ? (text, s) => opts.measure(text, { ...s, fontFamily: s.fontFamily ?? font.fontFamily, fontSize: s.fontSize ?? font.fontSize }) : (text, s) => {
1129
- const size = s.fontSize ?? font.fontSize;
1130
- return { width: text.length * GLYPH * size, height: Math.ceil(LINE * size) };
1131
- };
1132
- const ids = /* @__PURE__ */ new Set();
1133
- for (const n of data.nodes) {
1134
- if (ids.has(n.id)) throw new Error(`diagramScene: node id "${n.id}" appears more than once`);
1135
- ids.add(n.id);
1136
- }
1137
- const nodeIds = new Set(ids);
1138
- const titleStyle = { ...font, fontSize: font.fontSize - 1 };
1139
- const groups = resolveGroups(data.groups ?? [], ids, nodeIds, {
1140
- padding: opts.groupPadding ?? DEFAULT_GROUP_INSET,
1141
- title: (text) => measure(text, titleStyle)
1142
- });
1143
- const seen = /* @__PURE__ */ new Set();
1144
- const edges = data.edges.filter((e) => {
1145
- const id = edgeIdOf(e);
1146
- if (seen.has(id) || !ids.has(e.from) || !ids.has(e.to)) return false;
1147
- seen.add(id);
1148
- return true;
1149
- });
1150
- const bodies = data.nodes.map((n) => ({
1151
- outline: n.outline ?? opts.outline ?? "rect",
1152
- rows: n.rows ?? (n.lines ?? []).map((text) => ({ kind: "label", text })),
1153
- padding: n.padding ?? opts.padding ?? 8,
1154
- gap: n.gap ?? opts.gap ?? 4,
1155
- verticalAlign: n.verticalAlign ?? opts.verticalAlign ?? "center",
1156
- ...n.ports ? { ports: n.ports } : {},
1157
- ...n.portLabels ? { portLabels: n.portLabels } : {}
1158
- }));
1159
- const seeds = data.nodes.map((n, i) => {
1160
- const pose = sizeToBody(
1161
- { ...n.at ?? { x: i, y: i }, width: n.width ?? opts.minWidth ?? MIN_WIDTH, height: n.height ?? 0 },
1162
- measureBody(bodies[i], measure)
1163
- );
1164
- const { ports, outline, margin } = bodyTrait(bodies[i], pose, measure);
1165
- return {
1166
- id: n.id,
1167
- bounds: pose,
1168
- pinned: n.pinned === true,
1169
- ...ports !== void 0 ? { ports } : {},
1170
- ...outline !== void 0 ? { outline } : {},
1171
- ...margin !== void 0 ? { margin } : {}
1172
- };
1173
- });
1174
- const graphGroups = groups.map((g) => ({
1175
- id: g.group.id,
1176
- members: g.members,
1177
- inset: g.inset,
1178
- ...g.minWidth !== void 0 ? { minWidth: g.minWidth } : {},
1179
- ...g.parent !== void 0 ? { parent: g.parent } : {}
1180
- }));
1181
- const seedOf = new Map(seeds.map((n) => [n.id, n]));
1182
- for (const g of groups) {
1183
- for (const m of g.direct) {
1184
- const seed = seedOf.get(m);
1185
- if (seed !== void 0) seed.group = g.group.id;
1186
- }
1187
- }
1188
- const graph = graphOf(
1189
- seeds,
1190
- expandGroupEdges(edges.map((e) => graphEdgeOf(e, labelRoomOf(e, opts, font, measure))), graphGroups),
1191
- graphGroups
1192
- );
1193
- const layout = typeof opts.layout === "function" ? opts.layout : opts.layout === "none" ? null : LAYOUTS[opts.layout ?? "layered"];
1194
- const layoutOptions = { order: "barycenter", ...opts.layoutOptions };
1195
- const plan = layout === null ? null : planOf(layout, graph, layoutOptions);
1196
- const moved = plan?.moves ?? /* @__PURE__ */ new Map();
1197
- const specs = [];
1198
- const placedAt = placed(data, seeds, moved);
1199
- const routes = plan === null || layout?.plan === void 0 ? null : authoredOver(edges.map((e) => ({ ...e, id: edgeIdOf(e) })), plan);
1200
- const edgeCtx = { idOf: edgeIdOf, font, measure, fallback: EDGE, labelPlacement: LABEL_PLACEMENT, routes, opts };
1201
- const groupLook = (g) => ({ style: opts.groupStyle?.(g) ?? GROUP, text: styleOf(titleStyle) });
1202
- const footprints = new Map(seeds.map((s) => [s.id, grownBy(placedAt.get(s.id), s.margin)]));
1203
- specs.push(...groupSpecs(groups, footprints, groupLook, wireLabels(edges, edgeCtx)));
1204
- for (const [i, n] of data.nodes.entries()) {
1205
- const seed = seeds[i].bounds;
1206
- const at = placedAt.get(n.id);
1207
- const style = opts.nodeStyle?.(n) ?? NODE;
1208
- specs.push(...nodeSpecs(n, bodies[i], { x: at.x, y: at.y, width: seed.width, height: seed.height }, { style, text: styleOf, measure }));
1209
- if (n.marks) specs.push(...markSpecs(n.id, n.marks, at, { style, textStyle: styleOf, measure }));
1210
- }
1211
- specs.push(...edgeSpecs(edges, edgeCtx));
1212
- return specs;
1213
- }
1214
-
1215
- // src/routeWrites.ts
1216
- var ROUTE_TOLERANCE = 1e-3;
1217
- function routesOf(graph, plan) {
1218
- return {
1219
- edges: new Set(graph.edges.map((e) => e.origin?.id ?? e.id)),
1220
- waypoints: plan.waypoints ?? /* @__PURE__ */ new Map(),
1221
- ...plan.labels !== void 0 ? { labels: plan.labels } : {},
1222
- ...plan.ports !== void 0 ? { ports: plan.ports } : {}
1223
- };
1224
- }
1225
- function routeWrites(scene, routes) {
1226
- const out = /* @__PURE__ */ new Map();
1227
- const owned = /* @__PURE__ */ new Set();
1228
- for (const id of routes.edges) {
1229
- const node = scene.get(id);
1230
- const edge = node === void 0 ? null : diagramEdgeOf(node);
1231
- if (node === void 0 || edge === null || scene.isLocked(id)) {
1232
- if (edge !== null && layoutOwnsRoute(edge)) owned.add(id);
1233
- continue;
1234
- }
1235
- let next = edge;
1236
- if (layoutOwnsRoute(edge)) {
1237
- owned.add(id);
1238
- next = rerouted(edge, routes.waypoints.get(id));
1239
- }
1240
- const ports = routes.ports?.get(id);
1241
- const from = renamed(edge.from, ports?.from);
1242
- const to = renamed(edge.to, ports?.to);
1243
- if (from !== edge.from || to !== edge.to) next = { ...next, from, to };
1244
- if (next !== edge) out.set(id, withTrait(node.data, next));
1245
- }
1246
- const stationed = /* @__PURE__ */ new Set();
1247
- for (const node of scene.renderOrderNodes()) {
1248
- const label = diagramLabelOf(node);
1249
- const deps = node.dependsOn;
1250
- if (label === null || !Array.isArray(deps) || deps.length !== 1 || !owned.has(deps[0])) continue;
1251
- if (!labelFollowsLayout(label.at) || stationed.has(deps[0])) continue;
1252
- stationed.add(deps[0]);
1253
- const near2 = routes.labels?.get(deps[0]);
1254
- const at = near2 === void 0 ? "mid" : { near: near2 };
1255
- if (sameAt(label.at, at) || scene.isLocked(node.id)) continue;
1256
- out.set(node.id, withTrait(node.data, { ...label, at }, "label"));
1257
- }
1258
- return out;
1259
- }
1260
- function rerouted(edge, route) {
1261
- if (route === void 0 || route.length === 0) {
1262
- if ((edge.waypoints ?? []).length === 0 && edge.laidOut === void 0) return edge;
1263
- const { waypoints: _w, laidOut: _l, ...rest } = edge;
1264
- return rest;
1265
- }
1266
- if (edge.waypoints !== void 0 && near(edge.waypoints, route)) return edge;
1267
- return { ...edge, waypoints: route, laidOut: route };
1268
- }
1269
- function renamed(end, port) {
1270
- if (!layoutOwnsPort(end) || end.port === port && (port === void 0 || end.laidOut === port)) return end;
1271
- const { port: _p, laidOut: _l, ...rest } = end;
1272
- return port === void 0 ? rest : { ...rest, port, laidOut: port };
1273
- }
1274
- function near(a, b) {
1275
- return a.length === b.length && a.every((p, i) => Math.abs(p.x - b[i].x) <= ROUTE_TOLERANCE && Math.abs(p.y - b[i].y) <= ROUTE_TOLERANCE);
1276
- }
1277
- function sameAt(a, b) {
1278
- if (typeof a === "object" && typeof b === "object") return near([a.near], [b.near]);
1279
- return a === b;
1280
- }
1281
- function withTrait(data, value, key) {
1282
- const own = data;
1283
- const diagram = key === void 0 ? value : { ...own.diagram, [key]: value };
1284
- return { ...own, diagram };
1285
- }
1286
- var LAYOUTS2 = Object.freeze({
1287
- layered,
1288
- tree,
1289
- force,
1290
- chain
1291
- });
1292
- function applyLayout(scene, result, opts = {}) {
1293
- const poses = layoutPoses(scene, result, opts.geometry);
1294
- const data = opts.routes === void 0 ? /* @__PURE__ */ new Map() : routeWrites(scene, opts.routes);
1295
- if (poses.size === 0 && data.size === 0) return 0;
1296
- const open = [...poses].filter(([id]) => !scene.isLocked(id));
1297
- if (open.length === 0 && data.size === 0) return 0;
1298
- scene.batch(opts.label ?? "Layout", () => {
1299
- for (const [id, pose] of open) scene.setPose(id, pose);
1300
- for (const [id, d] of data) scene.update(id, { data: d });
1301
- });
1302
- const wrote = new Set(open.map(([id]) => id));
1303
- let moved = 0;
1304
- for (const id of result.keys()) if (wrote.has(id)) moved++;
1305
- return moved;
1306
- }
1307
- function layoutPoses(scene, result, geometry = AUTO_POSE_DESCRIPTOR) {
1308
- const out = /* @__PURE__ */ new Map();
1309
- for (const [id, at] of result) {
1310
- const node = scene.get(id);
1311
- if (node === void 0) continue;
1312
- const bounds = geometry.getBounds(node.pose);
1313
- const dx = at.x - bounds.x;
1314
- const dy = at.y - bounds.y;
1315
- if (dx === 0 && dy === 0) continue;
1316
- out.set(id, translatePoseViaDescriptor(node.pose, dx, dy, geometry));
1317
- for (const descendant of subtreeOf(scene, id)) {
1318
- const child = scene.get(descendant);
1319
- if (child === void 0) continue;
1320
- out.set(descendant, translatePoseViaDescriptor(child.pose, dx, dy, geometry));
1321
- }
1322
- }
1323
- return out;
1324
- }
1325
- function subtreeOf(scene, id) {
1326
- const out = [];
1327
- const stack = [...scene.childrenOf(id)];
1328
- while (stack.length > 0) {
1329
- const next = stack.pop();
1330
- out.push(next);
1331
- stack.push(...scene.childrenOf(next));
1332
- }
1333
- return out;
1334
- }
1335
- var LAYOUT_ACTION_ID = "diagram.layout";
1336
- function createLayoutAction(opts) {
1337
- const algorithm = typeof opts.algorithm === "function" ? opts.algorithm : LAYOUTS2[opts.algorithm ?? "layered"] ?? layered;
1338
- const build = {
1339
- ...opts.read ? { read: opts.read } : {},
1340
- ...opts.geometry ? { geometry: opts.geometry } : {}
1341
- };
1342
- return {
1343
- id: opts.id ?? LAYOUT_ACTION_ID,
1344
- label: opts.label ?? "Lay out diagram",
1345
- group: opts.group ?? "diagram",
1346
- requires: ["scene"],
1347
- invoker: {
1348
- timing: "immediate",
1349
- run: (deps) => {
1350
- const scene = deps["scene"];
1351
- if (scene === void 0) return;
1352
- const graph = buildGraph(opts.source, build);
1353
- const plan = planOf(algorithm, graph, opts.layout);
1354
- applyLayout(scene, plan.moves, {
1355
- ...opts.geometry ? { geometry: opts.geometry } : {},
1356
- ...opts.label ? { label: opts.label } : {},
1357
- routes: routesOf(graph, plan)
1358
- });
1359
- }
1360
- },
1361
- enabled: () => true
1362
- };
1363
- }
1364
- var EASE_FRAMES = 24;
1365
- var easeInOut = (t) => t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2;
1366
- function progress(frame, frames, easing) {
1367
- const t = Math.min((frame + 1) / frames, 1);
1368
- return { t, u: easing(t) };
1369
- }
1370
- var REST_DISTANCE = 0.1;
1371
- var REST_TICKS = 5;
1372
- function forceProducer(graph, opts = {}) {
1373
- const geometry = opts.geometry ?? AUTO_POSE_DESCRIPTOR;
1374
- const relaxation = forceRelaxation(graph, opts);
1375
- const dragAlpha = opts.dragAlpha ?? 0.3;
1376
- const restDistance = opts.restDistance ?? REST_DISTANCE;
1377
- const restTicks = opts.restTicks ?? REST_TICKS;
1378
- const was = relaxation.bodies.map((b) => ({ x: b.x, y: b.y }));
1379
- let still = 0;
1380
- return ({ pinned }) => {
1381
- for (const node of graph.nodes) {
1382
- const body = relaxation.byId.get(node.id);
1383
- if (body === void 0) continue;
1384
- const held = pinned.get(node.id);
1385
- if (held !== void 0) {
1386
- const bounds = geometry.getBounds(held);
1387
- body.fx = center(bounds, "x");
1388
- body.fy = center(bounds, "y");
1389
- } else if (!relaxation.pinned.has(node.id)) {
1390
- delete body.fx;
1391
- delete body.fy;
1392
- }
1393
- }
1394
- relaxation.sim.alphaTarget(pinned.size > 0 ? dragAlpha : 0);
1395
- relaxation.sim.tick();
1396
- let moved = 0;
1397
- relaxation.bodies.forEach((body, i) => {
1398
- const at = was[i];
1399
- moved = Math.max(moved, Math.hypot(body.x - at.x, body.y - at.y));
1400
- at.x = body.x;
1401
- at.y = body.y;
1402
- });
1403
- still = pinned.size === 0 && moved < restDistance ? still + 1 : 0;
1404
- const done = still >= restTicks || relaxation.sim.isSettled();
1405
- return { result: relaxation.placed(), done };
1406
- };
1407
- }
1408
- function easedProducer(graph, algorithm, opts = {}) {
1409
- const frames = opts.frames ?? EASE_FRAMES;
1410
- const easing = opts.easing ?? easeInOut;
1411
- const target = algorithm(graph, opts.layout);
1412
- const from = /* @__PURE__ */ new Map();
1413
- for (const node of graph.nodes) from.set(node.id, { x: node.bounds.x, y: node.bounds.y });
1414
- return ({ pinned, frame }) => {
1415
- const { t, u } = progress(frame, frames, easing);
1416
- const result = /* @__PURE__ */ new Map();
1417
- for (const [id, to] of target) {
1418
- if (pinned.has(id)) continue;
1419
- const start = from.get(id);
1420
- if (start === void 0) continue;
1421
- result.set(id, {
1422
- x: start.x + (to.x - start.x) * u,
1423
- y: start.y + (to.y - start.y) * u
1424
- });
1425
- }
1426
- return { result, done: t >= 1 };
1427
- };
1428
- }
1429
- function shapeOf(graph) {
1430
- const nodes = graph.nodes.map((n) => n.id).sort().join(",");
1431
- const edges = graph.edges.map((e) => `${e.from}>${e.to}`).sort().join(",");
1432
- return `${nodes}|${edges}`;
1433
- }
1434
- function sameGraph(a, b) {
1435
- if (shapeOf(a) !== shapeOf(b)) return false;
1436
- return a.nodes.every((n) => {
1437
- const m = b.node(n.id)?.bounds;
1438
- const k = n.bounds;
1439
- return m !== void 0 && m.x === k.x && m.y === k.y && m.width === k.width && m.height === k.height;
1440
- });
1441
- }
1442
- function usePendingPlan() {
1443
- const generation = useRef(0);
1444
- const waiting = useRef(false);
1445
- const pending = useMemo(() => ({
1446
- request(answer, ready, failed) {
1447
- const mine = ++generation.current;
1448
- waiting.current = true;
1449
- const current = () => generation.current === mine;
1450
- void answer.then(
1451
- (plan) => {
1452
- if (!current()) return;
1453
- waiting.current = false;
1454
- ready(plan);
1455
- },
1456
- (error) => {
1457
- if (!current()) return;
1458
- waiting.current = false;
1459
- failed(error);
1460
- }
1461
- );
1462
- },
1463
- drop() {
1464
- generation.current++;
1465
- waiting.current = false;
1466
- },
1467
- isWaiting: () => waiting.current
1468
- }), []);
1469
- useEffect(() => () => pending.drop(), [pending]);
1470
- return pending;
1471
- }
1472
- var lerp = (a, b, u) => ({ x: a.x + (b.x - a.x) * u, y: a.y + (b.y - a.y) * u });
1473
- function along(points, s) {
1474
- if (points.length === 1) return points[0];
1475
- const lengths = points.slice(1).map((p, i) => Math.hypot(p.x - points[i].x, p.y - points[i].y));
1476
- const total = lengths.reduce((a, b) => a + b, 0);
1477
- let left = s * total;
1478
- for (const [i, len] of lengths.entries()) {
1479
- if (left <= len || i === lengths.length - 1) return lerp(points[i], points[i + 1], len === 0 ? 0 : Math.min(left / len, 1));
1480
- left -= len;
1481
- }
1482
- return points[points.length - 1];
1483
- }
1484
- var straightRun = (count, start, end) => Array.from({ length: count }, (_, k) => lerp(start, end, (k + 1) / (count + 1)));
1485
- function respread(points, count, start, end) {
1486
- if (points.length === count) return [...points];
1487
- if (points.length === 0) return straightRun(count, start, end);
1488
- return Array.from({ length: count }, (_, k) => along(points, count === 1 ? 0.5 : k / (count - 1)));
1489
- }
1490
- function routeEasings(scene, graph, routes) {
1491
- const centerOf = (id) => {
1492
- const ids = graph.node(id) !== void 0 ? [id] : graph.groups?.find((g) => g.id === id)?.members ?? [];
1493
- const boxes = ids.flatMap((m) => graph.node(m)?.bounds ?? []);
1494
- if (boxes.length === 0) return null;
1495
- const x0 = Math.min(...boxes.map((b) => b.x));
1496
- const y0 = Math.min(...boxes.map((b) => b.y));
1497
- const x1 = Math.max(...boxes.map((b) => b.x + b.width));
1498
- const y1 = Math.max(...boxes.map((b) => b.y + b.height));
1499
- return { x: (x0 + x1) / 2, y: (y0 + y1) / 2 };
1500
- };
1501
- const writes = routeWrites(scene, routes);
1502
- const out = [];
1503
- for (const id of routes.edges) {
1504
- const node = scene.get(id);
1505
- const edge = node === void 0 ? null : diagramEdgeOf(node);
1506
- const written = writes.get(id);
1507
- if (node === void 0 || edge === null || written === void 0) continue;
1508
- const next = diagramEdgeOf({ data: written });
1509
- if (next === null) continue;
1510
- const ends = { from: next.from, to: next.to };
1511
- const was = edge.waypoints ?? [];
1512
- if (!layoutOwnsRoute(edge)) {
1513
- out.push({ id, from: was, to: was, ends });
1514
- continue;
1515
- }
1516
- const after = routes.waypoints.get(id) ?? [];
1517
- if (after.length === 0) {
1518
- out.push({ id, from: was, to: null, ends });
1519
- continue;
1520
- }
1521
- const deps = Array.isArray(node.dependsOn) ? node.dependsOn : [];
1522
- const [a, b] = deps.length === 2 ? [centerOf(deps[0]), centerOf(deps[1])] : [null, null];
1523
- if (a === null || b === null) continue;
1524
- const count = Math.max(was.length, after.length);
1525
- out.push({ id, from: respread(was, count, a, b), to: respread(after, count, a, b), ends });
1526
- }
1527
- return out;
1528
- }
1529
- function easedPaths(scene, easings, u, poseOf, geometry = AUTO_POSE_DESCRIPTOR) {
1530
- const depOf = frameDeps(scene, poseOf);
1531
- const centerOf = (dep) => {
1532
- const b = geometry.getBounds(dep.pose);
1533
- return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
1534
- };
1535
- const out = /* @__PURE__ */ new Map();
1536
- for (const { id, from, to, ends } of easings) {
1537
- const node = scene.get(id);
1538
- if (node?.derivePath === void 0 || !Array.isArray(node.dependsOn)) continue;
1539
- const deps = node.dependsOn.map(depOf);
1540
- let target = to;
1541
- if (target === null) {
1542
- const [a, b] = deps;
1543
- target = u >= 1 || a === void 0 || b === void 0 ? [] : straightRun(from.length, centerOf(a), centerOf(b));
1544
- }
1545
- const waypoints = target.length === 0 && u >= 1 ? [] : from.map((p, k) => lerp(p, target[k], u));
1546
- const data = node.data;
1547
- const diagram = { ...data.diagram, ...ends, waypoints };
1548
- const path = node.derivePath({ ...node, data: { ...data, diagram } }, deps);
1549
- if (path !== null) out.set(id, path);
1550
- }
1551
- return out;
1552
- }
1553
- function frameDeps(scene, poseOf) {
1554
- const memo = /* @__PURE__ */ new Map();
1555
- const depOf = (id) => {
1556
- if (memo.has(id)) return memo.get(id);
1557
- memo.set(id, derivedDepOf(scene, id));
1558
- const shown = memo.get(id);
1559
- if (shown === void 0) return void 0;
1560
- const pose = poseOf(id) ?? derivedFromFrame(scene, shown, depOf) ?? shown.pose;
1561
- const dep = { node: shown.node, pose, get path() {
1562
- return shown.path;
1563
- } };
1564
- memo.set(id, dep);
1565
- return dep;
1566
- };
1567
- return depOf;
1568
- }
1569
- function derivedFromFrame(scene, shown, depOf) {
1570
- const { node } = shown;
1571
- if (node.derivePose === void 0 || scene.overrides.read(node.id)?.pose !== void 0) return void 0;
1572
- const ids = node.dependsOn === "children" ? scene.childrenOf(node.id) : node.dependsOn ?? [];
1573
- if (ids.length === 0) return void 0;
1574
- return node.derivePose(node, ids.map(depOf)) ?? void 0;
1575
- }
1576
- function pathHold(scene) {
1577
- const held = /* @__PURE__ */ new Map();
1578
- const release = (id, entry) => {
1579
- held.delete(id);
1580
- if (scene.overrides.get(id) === entry) scene.overrides.clear(id);
1581
- };
1582
- return {
1583
- show(paths) {
1584
- for (const [id, entry] of held) if (!paths.has(id)) release(id, entry);
1585
- for (const [id, path] of paths) {
1586
- const entry = held.get(id);
1587
- if (entry !== void 0 && scene.overrides.get(id) === entry) {
1588
- entry.path = path;
1589
- continue;
1590
- }
1591
- const fresh = { path };
1592
- held.set(id, fresh);
1593
- scene.overrides.set(id, fresh);
1594
- }
1595
- },
1596
- drop() {
1597
- for (const [id, entry] of held) release(id, entry);
1598
- }
1599
- };
1600
- }
1601
- function useEasedRoutes() {
1602
- const easings = useRef([]);
1603
- const held = useRef(null);
1604
- const routes = useMemo(() => ({
1605
- set(next) {
1606
- held.current?.hold.drop();
1607
- easings.current = next;
1608
- },
1609
- show(scene, u, poseOf, geometry) {
1610
- if (u === null) held.current?.hold.drop();
1611
- if (u === null || easings.current.length === 0) return;
1612
- if (held.current?.scene !== scene) {
1613
- held.current?.hold.drop();
1614
- held.current = { scene, hold: pathHold(scene) };
1615
- }
1616
- held.current.hold.show(easedPaths(scene, easings.current, u, poseOf, geometry));
1617
- },
1618
- drop() {
1619
- held.current?.hold.drop();
1620
- }
1621
- }), []);
1622
- useEffect(() => () => routes.drop(), [routes]);
1623
- return routes;
1624
- }
1625
-
1626
- // src/live.ts
1627
- function graphOf2(o) {
1628
- return buildGraph(o.source, {
1629
- ...o.read ? { read: o.read } : {},
1630
- ...o.geometry ? { geometry: o.geometry } : {}
1631
- });
1632
- }
1633
- function planFor(graph, o) {
1634
- const algorithm = o.algorithm ?? "force";
1635
- if (algorithm === "force") return null;
1636
- if (typeof algorithm === "object") return plannerPlan(algorithm, graph, o.layout);
1637
- return planOf(typeof algorithm === "function" ? algorithm : LAYOUTS2[algorithm] ?? layered, graph, o.layout);
1638
- }
1639
- function producerFor(graph, plan, o) {
1640
- if (plan === null) return forceProducer(graph, { ...o.layout, ...o.force, ...o.geometry ? { geometry: o.geometry } : {} });
1641
- return easedProducer(graph, () => plan.moves, {
1642
- ...o.frames === void 0 ? {} : { frames: o.frames },
1643
- ...o.easing ? { easing: o.easing } : {}
1644
- });
1645
- }
1646
- function useLiveLayout(opts) {
1647
- const optsRef = useLatest(opts);
1648
- const producer = useRef(null);
1649
- const producerFrame = useRef(0);
1650
- const shape = useRef("");
1651
- const routes = useRef(void 0);
1652
- const held = useRef(false);
1653
- const eased = useEasedRoutes();
1654
- const pending = usePendingPlan();
1655
- const install = useCallback((graph, plan) => {
1656
- const o = optsRef.current;
1657
- producerFrame.current = 0;
1658
- held.current = false;
1659
- routes.current = routesOf(graph, plan ?? { });
1660
- eased.set(routeEasings(o.scene, graph, routes.current));
1661
- producer.current = producerFor(graph, plan, o);
1662
- }, [optsRef, eased]);
1663
- const step = useCallback((ctx) => {
1664
- const o = optsRef.current;
1665
- if (producer.current === null) return { poses: [], done: true };
1666
- if (ctx.pinned.size > 0) held.current = true;
1667
- const frame = producerFrame.current++;
1668
- const { result, done } = producer.current({ pinned: ctx.pinned, frame });
1669
- let placed2 = result;
1670
- if (ctx.pinned.size > 0) {
1671
- const held2 = new Map(result);
1672
- for (const id of ctx.pinned.keys()) held2.delete(id);
1673
- placed2 = held2;
1674
- }
1675
- const poses = layoutPoses(o.scene, placed2, o.geometry);
1676
- const { u } = progress(frame, o.frames ?? EASE_FRAMES, o.easing ?? easeInOut);
1677
- eased.show(o.scene, held.current ? null : u, (id) => poses.get(id) ?? ctx.pinned.get(id), o.geometry);
1678
- return { poses: [...poses], done };
1679
- }, [optsRef, eased]);
1680
- const run = usePoseRun({
1681
- scene: opts.scene,
1682
- step,
1683
- // Eased routes go once the routes are in the document, so no frame shows the old ones.
1684
- onCommit: (moved) => {
1685
- eased.drop();
1686
- optsRef.current.onSettle?.(moved);
1687
- },
1688
- // Routes match where the layout was going, so only a run that got there
1689
- // with nothing held along the way writes them.
1690
- commitWith: (finished) => {
1691
- if (!finished || held.current || routes.current === void 0) return;
1692
- const scene = optsRef.current.scene;
1693
- for (const [id, data] of routeWrites(scene, routes.current)) scene.update(id, { data });
1694
- },
1695
- ...opts.label ? { label: opts.label } : {},
1696
- ...opts.requestFrame ? { requestFrame: opts.requestFrame } : {},
1697
- ...opts.cancelFrame ? { cancelFrame: opts.cancelFrame } : {}
1698
- });
1699
- const build = useCallback(() => {
1700
- const graph = graphOf2(optsRef.current);
1701
- shape.current = shapeOf(graph);
1702
- const plan = planFor(graph, optsRef.current);
1703
- if (plan === null || !isPromise(plan)) {
1704
- install(graph, plan);
1705
- return true;
1706
- }
1707
- pending.request(plan, (answer) => {
1708
- if (!sameGraph(graph, graphOf2(optsRef.current))) return;
1709
- install(graph, answer);
1710
- run.start();
1711
- }, (error) => {
1712
- const onError = optsRef.current.onError;
1713
- if (onError) onError(error);
1714
- else console.error(error);
1715
- });
1716
- return false;
1717
- }, [optsRef, install, pending, run]);
1718
- const restart = useCallback(() => {
1719
- pending.drop();
1720
- run.cancel();
1721
- if (build()) run.start();
1722
- }, [pending, run, build]);
1723
- useEffect(() => {
1724
- if (opts.reheatOnGraphChange === false) return;
1725
- return opts.scene.subscribe(() => {
1726
- if (!run.isRunning() && !pending.isWaiting()) return;
1727
- if (shapeOf(graphOf2(optsRef.current)) === shape.current) return;
1728
- if (typeof optsRef.current.algorithm === "object") restart();
1729
- else build();
1730
- });
1731
- }, [opts.scene, opts.reheatOnGraphChange, run, build, restart, pending, optsRef]);
1732
- return useMemo(() => ({
1733
- start() {
1734
- if (run.isRunning() || pending.isWaiting()) return;
1735
- if (build()) run.start();
1736
- },
1737
- stop: () => {
1738
- pending.drop();
1739
- run.stop();
1740
- },
1741
- cancel: () => {
1742
- pending.drop();
1743
- run.cancel();
1744
- eased.drop();
1745
- },
1746
- restart,
1747
- isRunning: () => run.isRunning() || pending.isWaiting()
1748
- }), [run, build, restart, eased, pending]);
1749
- }
1750
- var EASED_LAYOUTS = Object.freeze({
1751
- layered,
1752
- tree,
1753
- chain
1754
- });
1755
- function diagramShape(opts = {}) {
1756
- const geometry = opts.geometry ?? RECT_POSE_DESCRIPTOR;
1757
- const outlineOf = (node) => diagramNodeOf(node, opts.read)?.outline;
1758
- return {
1759
- id: opts.id ?? "diagram:outline",
1760
- matches: (node) => outlineOf(node) !== void 0,
1761
- paint: (node, pose) => {
1762
- const outline = outlineOf(node);
1763
- if (outline === void 0) return [];
1764
- const d = node.data;
1765
- const box = geometry.getBounds(pose);
1766
- const declaredFill = d.fill === void 0 ? opts.defaultFill : d.fill;
1767
- const declaredStroke = d.stroke === void 0 ? opts.defaultStroke : d.stroke;
1768
- const fill = declaredFill && commandFill(declaredFill, box);
1769
- const stroke = declaredStroke && commandStroke(declaredStroke, box);
1770
- return [{
1771
- kind: "path",
1772
- path: outlinePath(outline, box),
1773
- ...fill ? { fill } : {},
1774
- ...stroke ? { stroke } : {}
1775
- }];
1776
- },
1777
- // The drawn boundary, so picking and clipping follow the diamond rather
1778
- // than its bounding box.
1779
- silhouette: (node, pose) => {
1780
- const outline = outlineOf(node);
1781
- return outline === void 0 ? null : outlinePath(outline, geometry.getBounds(pose));
1782
- }
1783
- };
1784
- }
1785
- function registerDiagramShape(opts = {}) {
1786
- return registerNodeShape(diagramShape(opts), { priority: "high" });
1787
- }
1788
- function useMirroredSelection(selection, selected, onSelect) {
1789
- const want = selected ?? null;
1790
- const pushed = useRef(void 0);
1791
- useEffect(() => {
1792
- if (pushed.current === want) return;
1793
- pushed.current = want;
1794
- if ((selection.get()[0] ?? null) !== want) selection.set(want === null ? [] : [want]);
1795
- }, [want]);
1796
- const onSelectRef = useLatest(onSelect);
1797
- return useCallback(() => {
1798
- onSelectRef.current?.(selection.get()[0] ?? null);
1799
- }, [selection, onSelectRef]);
1800
- }
1801
- var NONE = [];
1802
- var laidPort = (end) => end.laidOut !== void 0 && end.port === end.laidOut ? end.laidOut : void 0;
1803
- function portsOf2(from, to) {
1804
- const f = laidPort(from);
1805
- const t = laidPort(to);
1806
- return { ...f !== void 0 ? { from: f } : {}, ...t !== void 0 ? { to: t } : {} };
1807
- }
1808
- var samePorts = (a, b) => a.from === b.from && a.to === b.to;
1809
- var routeOf = (edge) => ({ waypoints: edge.waypoints ?? NONE, ports: portsOf2(edge.from, edge.to) });
1810
- function readScene(scene) {
1811
- const nodes = /* @__PURE__ */ new Map();
1812
- const routes = /* @__PURE__ */ new Map();
1813
- for (const n of scene.renderOrderNodes()) {
1814
- if (n.kind === "container") {
1815
- nodes.set(n.id, { x: n.pose.x, y: n.pose.y });
1816
- continue;
1817
- }
1818
- const edge = diagramEdgeOf(n);
1819
- if (edge !== null) routes.set(n.id, routeOf(edge));
1820
- }
1821
- return { nodes, routes };
1822
- }
1823
- function diagramLayoutOf(specs) {
1824
- const moves = [];
1825
- const routes = [];
1826
- for (const s of specs) {
1827
- const id = s.id;
1828
- if (id === void 0) continue;
1829
- if (s.kind === "container") {
1830
- if (diagramGroupOf(s) === null && !isPinned({ id, kind: s.kind, data: s.data })) moves.push({ id, x: s.pose.x, y: s.pose.y });
1831
- continue;
1832
- }
1833
- const edge = diagramEdgeOf(s);
1834
- if (edge === null) continue;
1835
- const route = routeOf(edge);
1836
- const laid = edge.laidOut !== void 0 && route.waypoints.length > 0 && layoutOwnsRoute(edge);
1837
- if (laid || route.ports.from !== void 0 || route.ports.to !== void 0) {
1838
- routes.push({ id, waypoints: laid ? route.waypoints : NONE, ports: route.ports });
1839
- }
1840
- }
1841
- return { moves, routes };
1842
- }
1843
- function changes(was, now) {
1844
- const moves = [];
1845
- for (const [id, at] of now.nodes) {
1846
- const before = was.nodes.get(id);
1847
- if (before !== void 0 && (before.x !== at.x || before.y !== at.y)) moves.push({ id, ...at });
1848
- }
1849
- const routes = [];
1850
- for (const [id, after] of now.routes) {
1851
- const before = was.routes.get(id);
1852
- if (before === void 0) continue;
1853
- const moved = before.waypoints !== after.waypoints && !samePoints(before.waypoints, after.waypoints);
1854
- if (moved || !samePorts(before.ports, after.ports)) routes.push({ id, ...after });
1855
- }
1856
- return { moves, routes };
1857
- }
1858
- function useSceneSync(scene, specs, onMove) {
1859
- const onMoveRef = useLatest(onMove);
1860
- const syncing = useRef(false);
1861
- const applied = useRef(specs);
1862
- useEffect(() => {
1863
- let known = readScene(scene);
1864
- return scene.subscribe(() => {
1865
- const now = readScene(scene);
1866
- const found = syncing.current ? null : changes(known, now);
1867
- known = now;
1868
- if (found !== null && (found.moves.length > 0 || found.routes.length > 0)) {
1869
- onMoveRef.current?.(found.moves, found.routes);
1870
- }
1871
- });
1872
- }, [scene, onMoveRef]);
1873
- useEffect(() => {
1874
- if (applied.current === specs) return;
1875
- syncing.current = true;
1876
- try {
1877
- reconcileSpecs(scene, applied.current, specs);
1878
- } finally {
1879
- syncing.current = false;
1880
- }
1881
- applied.current = specs;
1882
- }, [scene, specs]);
1883
- }
1884
- var AMBIENT = [dragPanContribution()];
1885
- var IDENTITY = { x: 0, y: 0, scale: { x: 1, y: 1 } };
1886
- var sameView = (a, b) => a.x === b.x && a.y === b.y && a.scale.x === b.scale.x && a.scale.y === b.scale.y;
1887
- var NO_MARQUEE = { areaSelect: null };
1888
- var DiagramView = forwardRef(function DiagramView2(props, ref) {
1889
- return /* @__PURE__ */ jsx(WeaselProvider, { children: /* @__PURE__ */ jsx(Inner, { ...props, apiRef: ref }) });
1890
- });
1891
- function Inner({
1892
- specs,
1893
- width,
1894
- height,
1895
- selected,
1896
- onSelect,
1897
- onMove,
1898
- onConnect,
1899
- enableKeybindings,
1900
- canConnect,
1901
- portOptions,
1902
- ports: portMode,
1903
- live: liveOpts,
1904
- minScale,
1905
- maxScale,
1906
- anchor,
1907
- fitPadding,
1908
- background,
1909
- view,
1910
- onViewChange,
1911
- className,
1912
- apiRef
1913
- }) {
1914
- useEffect(() => {
1915
- const disposers = [registerDiagramShape(), registerMarkShape()];
1916
- return () => disposers.forEach((dispose) => dispose());
1917
- }, []);
1918
- const registry = useMemo(() => withDiagramRegistry(), []);
1919
- const scene = useScene({
1920
- systemLayers: [{ id: "main" }],
1921
- initial: specs,
1922
- registry
1923
- });
1924
- const selection = useSelection({ scene, mode: "single" });
1925
- const onClick = useMirroredSelection(selection, selected, onSelect);
1926
- useSceneSync(scene, specs, onMove);
1927
- const source = useMemo(() => sceneParticipants(scene), [scene]);
1928
- const [run, setRun] = useState(null);
1929
- const controlled = view !== void 0;
1930
- const fills = width === void 0 || height === void 0;
1931
- const [measured, setMeasured] = useState(null);
1932
- const boxWidth = width ?? measured?.width ?? 0;
1933
- const boxHeight = height ?? measured?.height ?? 0;
1934
- const unsized = boxWidth === 0 || boxHeight === 0;
1935
- const fitOpts = { minScale, maxScale, anchor, padding: fitPadding };
1936
- const defaultView = useMemo(
1937
- () => controlled || unsized ? void 0 : fitDiagram(specs, { width: boxWidth, height: boxHeight }, fitOpts),
1938
- // A later `specs` keeps the view it has.
1939
- // eslint-disable-next-line react-hooks/exhaustive-deps
1940
- [controlled, unsized, boxWidth, boxHeight, minScale, maxScale, anchor, fitPadding]
1941
- );
1942
- const [settledFit, setSettledFit] = useState(null);
1943
- const fit = settledFit !== null && settledFit.over === defaultView ? settledFit.view : defaultView;
1944
- const settled = useLatest((moved) => {
1945
- liveOpts?.onSettle?.(moved);
1946
- if (controlled || moved === 0) return;
1947
- const boxes = Array.from(source(), ({ node, pose }) => ({ ...node, pose }));
1948
- setSettledFit({ view: fitDiagram(boxes, { width: boxWidth, height: boxHeight }, fitOpts), over: defaultView });
1949
- });
1950
- const live = useLiveLayout({
1951
- ...liveOpts,
1952
- scene,
1953
- source,
1954
- algorithm: run?.algorithm ?? "force",
1955
- onSettle: (moved) => settled.current(moved)
1956
- });
1957
- useEffect(() => {
1958
- if (run !== null) live.restart();
1959
- }, [run, live]);
1960
- useImperativeHandle(apiRef, () => ({
1961
- layout: (algorithm = "force") => setRun({ algorithm }),
1962
- live
1963
- }), [live]);
1964
- const onConnectRef = useLatest(onConnect);
1965
- const mode = portMode ?? (onConnect !== void 0 ? "connect" : "none");
1966
- const ports = useMemo(() => mode === "connect" ? diagramPorts({
1967
- ...portOptions,
1968
- participants: source,
1969
- ...canConnect ? { canConnect } : {},
1970
- commit: ({ from, to }) => onConnectRef.current?.({
1971
- from: from.nodeId,
1972
- fromPort: from.id,
1973
- to: to.nodeId,
1974
- toPort: to.id
1975
- })
1976
- }) : null, [mode, source, canConnect, portOptions, onConnectRef]);
1977
- const shown = useMemo(() => {
1978
- if (mode !== "show") return null;
1979
- const { hitTest: _hitTest, ...paintOnly } = portLayer(source, portOptions);
1980
- return paintOnly;
1981
- }, [mode, source, portOptions]);
1982
- const canvasRef = useRef(null);
1983
- const layer = ports?.layer ?? shown;
1984
- useEffect(() => layer ? canvasRef.current?.registerLayer(layer) : void 0, [layer]);
1985
- const ambient = useMemo(() => ports ? [...AMBIENT, ports.contribution] : AMBIENT, [ports]);
1986
- useRefit(canvasRef, fit);
1987
- return /* @__PURE__ */ jsx(
1988
- SceneCanvas,
1989
- {
1990
- ref: canvasRef,
1991
- scene,
1992
- selection,
1993
- features: onMove ? ["view", "pick", "move"] : ["view", "pick"],
1994
- enableKeybindings: enableKeybindings ?? (onMove !== void 0 || onConnect !== void 0),
1995
- ambient,
1996
- actions: NO_MARQUEE,
1997
- onClick,
1998
- width,
1999
- height,
2000
- ...fills ? { onResize: setMeasured } : {},
2001
- className,
2002
- ...defaultView ? { defaultView } : {},
2003
- ...view ? { view } : {},
2004
- ...onViewChange ? { onViewChange } : {},
2005
- ...background ? { backgroundFill: background } : {}
2006
- }
2007
- );
2008
- }
2009
- function useRefit(canvasRef, fit) {
2010
- const fitted = useRef(fit);
2011
- useEffect(() => {
2012
- const canvas = canvasRef.current;
2013
- const was = fitted.current;
2014
- if (canvas === null || fit === void 0 || was === fit) return;
2015
- if (!sameView(canvas.getView(), was ?? IDENTITY)) return;
2016
- fitted.current = fit;
2017
- canvas.setView(fit);
2018
- }, [canvasRef, fit]);
2019
- }
2020
- function fitDiagram(specs, size, fit = {}) {
2021
- const boxes = specs.filter((s) => s.kind === "container" || diagramGroupOf(s) !== null).map((s) => s.pose);
2022
- if (boxes.length === 0) return void 0;
2023
- const x = Math.min(...boxes.map((b) => b.x));
2024
- const y = Math.min(...boxes.map((b) => b.y));
2025
- const bounds = {
2026
- x,
2027
- y,
2028
- width: Math.max(...boxes.map((b) => b.x + b.width)) - x,
2029
- height: Math.max(...boxes.map((b) => b.y + b.height)) - y
2030
- };
2031
- return fitViewToBounds(bounds, size, { x: 0, y: 0, scale: { x: 1, y: 1 } }, {
2032
- maxScale: fit.maxScale ?? 1,
2033
- ...fit.minScale !== void 0 ? { minScale: fit.minScale } : {},
2034
- ...fit.anchor !== void 0 ? { anchor: fit.anchor } : {},
2035
- ...fit.padding !== void 0 ? { padding: fit.padding } : {}
2036
- });
2037
- }
2038
-
2039
- export { ANCHOR_DERIVE_POSE, CONNECT_ACTION_ID, DEFAULT_EDGE_STROKE, DIAGRAM_ANCHOR, DIAGRAM_EDGE, DIAGRAM_GROUP, DIAGRAM_LABEL, DiagramView, EASED_LAYOUTS, EDGE_DERIVE_PATH, GRAB_PORT_ACTION_ID, GROUP_DERIVE_POSE, LABEL_DERIVE_POSE, LABEL_PLACEMENT, LAYOUTS2 as LAYOUTS, LAYOUT_ACTION_ID, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, ROUTERS, anchorDerivePose, applyLayout, bezier, boxAround, buildGraph, commitEdgeToScene, connectBinding, createConnectAction, createDiagramContribution, createLayoutAction, createPortAffordance, defaultCanConnect, diagramAnchorOf, diagramEdgeOf, diagramGroupOf, diagramLabelOf, diagramLayoutOf, diagramMarkOf, diagramPorts, diagramScene, diagramShape, easedProducer, edgeDerivePath, edgeIdOf, forceProducer, grabPortAction, grabPortBindings, groupDerivePose, labelCenter, labelDerivePose, layoutOwnsPort, layoutOwnsRoute, layoutPoses, markShape, orthogonal, portLayer, portScratchOf, registerDiagramShape, registerMarkShape, resolveEnd, routeWrites, routesOf, sceneParticipants, selfLoop, straight, useLiveLayout, useMirroredSelection, withDiagramRegistry };
2040
- //# sourceMappingURL=chunk-C4NAI6NV.js.map
2041
- //# sourceMappingURL=chunk-C4NAI6NV.js.map