@almadar/shell-web 0.1.0 → 1.0.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 (118) hide show
  1. package/dist/{ArbitraryClassCompiler-Mzabq-UB.d.ts → ArbitraryClassCompiler-CO_iASBn.d.ts} +99 -4
  2. package/dist/AvlGlyph-EPJKFEO3.js +6 -0
  3. package/dist/AvlStateMachine-RKZIKNGC.js +9 -0
  4. package/dist/AvlTransitionDetail-63SD6GZF.js +11 -0
  5. package/dist/AvlTransitionExplainer-ZBTLOM3T.js +12 -0
  6. package/dist/BehaviorView-YS5G4GNB.js +11 -0
  7. package/dist/{Canvas3DHost-_Y-5uLM_.d.ts → Canvas3DHost-BkZQB5l2.d.ts} +1 -1
  8. package/dist/{EventBusProvider-CVwjkV_2.d.ts → EventBusProvider-BFFHfN4O.d.ts} +12 -0
  9. package/dist/FlowCanvas-AUMTWMNG.js +26 -0
  10. package/dist/{GameAudioProvider-Cm9BnvmP.d.ts → GameAudioProvider-ceM_n0ey.d.ts} +4 -7
  11. package/dist/KernelEngineContext-CcxGYtlr.d.ts +33 -0
  12. package/dist/LayersPanel-M2LHWUFF.js +6 -0
  13. package/dist/ModuleCard-QHDGK5XK.js +7 -0
  14. package/dist/OrbInspector-QCPEPUPH.js +26 -0
  15. package/dist/{Select-mDZIwNqN.d.ts → Select-B-iDdnvE.d.ts} +16 -30
  16. package/dist/ServerBridge-Bqsj-lOU.d.ts +124 -0
  17. package/dist/UISlotRenderer-C7WWOK43.js +26 -0
  18. package/dist/auth/browser/index.js +1 -0
  19. package/dist/auth/react/index.d.ts +8 -1
  20. package/dist/auth/react/index.js +40 -2
  21. package/dist/avl/index.d.ts +89 -79
  22. package/dist/avl/index.js +38 -38
  23. package/dist/{avl-3d-context-BIRKWpaL.d.ts → avl-3d-context-BycmO6tG.d.ts} +9 -12
  24. package/dist/{chunk-GKIFONTE.js → chunk-3S54FWRC.js} +2 -2
  25. package/dist/{chunk-DYEKAA4L.js → chunk-3VZ36ZKO.js} +240 -252
  26. package/dist/{chunk-PC7K4SK7.js → chunk-4T3P43NS.js} +18 -269
  27. package/dist/{chunk-MBQAMMSE.js → chunk-4YXBKHHM.js} +269 -658
  28. package/dist/{chunk-YDNJLLG6.js → chunk-57DC34LY.js} +19 -10
  29. package/dist/{chunk-SJGJJKBY.js → chunk-AB3X7QTE.js} +6 -3
  30. package/dist/{chunk-AILY3XPS.js → chunk-AE7VCQB6.js} +5 -6
  31. package/dist/{chunk-FAJDTHWC.js → chunk-AGXD77SL.js} +2 -2
  32. package/dist/chunk-AU7O65OX.js +66 -0
  33. package/dist/{chunk-L677XGY3.js → chunk-CPLN6NBQ.js} +5 -5
  34. package/dist/{chunk-DZ42OJQC.js → chunk-DZBQA2OW.js} +1 -1
  35. package/dist/{chunk-2PY54Z44.js → chunk-E6KA4J6N.js} +5 -5
  36. package/dist/{chunk-DJ433ET5.js → chunk-GFXCPUMX.js} +11 -4
  37. package/dist/{chunk-FP3WIKTC.js → chunk-HH5KSMH5.js} +9 -1
  38. package/dist/{chunk-U6QRZASX.js → chunk-ILQXJ2AR.js} +1 -1
  39. package/dist/{chunk-B4BU77LT.js → chunk-ILZ7ORX7.js} +1 -1
  40. package/dist/{chunk-SGM3FASH.js → chunk-K4MOPSEL.js} +14 -12
  41. package/dist/{chunk-GYTPOFVC.js → chunk-LHP2TK7O.js} +7402 -6970
  42. package/dist/{chunk-VFF5OO47.js → chunk-PCR37T3U.js} +15 -38
  43. package/dist/{chunk-R5O5AUPI.js → chunk-PRXQGGCO.js} +93 -86
  44. package/dist/{chunk-42FY4RYA.js → chunk-REXYVBUO.js} +2 -2
  45. package/dist/{chunk-DLZF4PVE.js → chunk-ROICKAU7.js} +3 -3
  46. package/dist/{chunk-KVQS4GXU.js → chunk-SP5CDJ6K.js} +18 -8
  47. package/dist/{chunk-P4LNHAFI.js → chunk-TUPZWTRE.js} +2 -2
  48. package/dist/chunk-TXAUOLWZ.js +490 -0
  49. package/dist/{chunk-EQAMU2ZC.js → chunk-UTDC2NEA.js} +1 -1
  50. package/dist/{chunk-73SRAB4P.js → chunk-UU57VNS2.js} +2 -2
  51. package/dist/{chunk-DFNZUYX4.js → chunk-UXLE3IPR.js} +70 -27
  52. package/dist/{chunk-L2DEKY4J.js → chunk-VO2TTLS5.js} +3 -6
  53. package/dist/{chunk-TESBIVUA.js → chunk-X3DMMX27.js} +2 -2
  54. package/dist/components/index.d.ts +331 -125
  55. package/dist/components/index.js +28 -28
  56. package/dist/context/index.d.ts +2 -3
  57. package/dist/context/index.js +4 -3
  58. package/dist/core.d.ts +93 -17
  59. package/dist/core.js +2 -1
  60. package/dist/design-classes/index.cjs +3 -1
  61. package/dist/design-classes/index.js +3 -1
  62. package/dist/hooks/index.d.ts +40 -5
  63. package/dist/hooks/index.js +5 -4
  64. package/dist/index.d.ts +36 -114
  65. package/dist/index.js +174 -34
  66. package/dist/kernel-client-TZKGHJRY.js +516 -0
  67. package/dist/kernel-wire-wNdAPfhJ.d.ts +88 -0
  68. package/dist/lib/index.d.ts +3 -3
  69. package/dist/lib/index.js +5 -4
  70. package/dist/{paintDispatch-ChW5mVuK.d.ts → paintDispatch-CuJLsr9Y.d.ts} +5 -15
  71. package/dist/{prism-AIWGN2X5.js → prism-X5YWKXO5.js} +5 -3
  72. package/dist/providers/index.d.ts +42 -27
  73. package/dist/providers/index.js +22 -23
  74. package/dist/renderer/index.d.ts +0 -2
  75. package/dist/renderer/index.js +1 -0
  76. package/dist/runtime/index.d.ts +52 -253
  77. package/dist/runtime/index.js +21 -24
  78. package/dist/ssr/index.cjs +2643 -535
  79. package/dist/ssr/index.d.cts +0 -23
  80. package/dist/ssr/index.d.ts +0 -23
  81. package/dist/ssr/index.js +2639 -535
  82. package/dist/storage/browser/index.js +1 -0
  83. package/dist/test-support.d.ts +15 -8
  84. package/dist/test-support.js +91 -24
  85. package/dist/three/index.d.ts +6 -6
  86. package/dist/three/index.js +49 -37
  87. package/dist/{verificationRegistry-CabxhfTv.d.ts → verificationRegistry-CVrcxG1s.d.ts} +3 -3
  88. package/package.json +13 -9
  89. package/src/core/lib/band-shapes.json +7 -0
  90. package/src/core/locales/ar.json +18 -5
  91. package/src/core/locales/en.json +18 -5
  92. package/src/core/locales/sl.json +18 -5
  93. package/tailwind-preset.cjs +30 -1
  94. package/dist/AvlGlyph-JKJOAH23.js +0 -6
  95. package/dist/AvlStateMachine-PI4YGREK.js +0 -8
  96. package/dist/AvlTransitionDetail-ZH7V24UG.js +0 -12
  97. package/dist/AvlTransitionExplainer-ZSRT7L6Y.js +0 -13
  98. package/dist/BehaviorValueFrame-6RUJXT4A.js +0 -29
  99. package/dist/BehaviorValueFrame-SSEMEBTG.css +0 -1756
  100. package/dist/BehaviorView-RFEE5J6E.js +0 -10
  101. package/dist/FlowCanvas-STDC4OWK.js +0 -27
  102. package/dist/KernelEngineContext-BOCQoFwk.d.ts +0 -43
  103. package/dist/LayersPanel-BBQ54IVG.js +0 -7
  104. package/dist/ModuleCard-3TT2X7IW.js +0 -7
  105. package/dist/OrbInspector-K6T6O7GI.js +0 -27
  106. package/dist/ServerBridge-Cm1On51b.d.ts +0 -233
  107. package/dist/TraitValueFrame-2PJGLLVI.js +0 -28
  108. package/dist/TraitValueFrame-4G3KOUBR.css +0 -1756
  109. package/dist/UISlotRenderer-JKFSX24W.js +0 -27
  110. package/dist/UserContext-DqWeZkUZ.d.ts +0 -100
  111. package/dist/chunk-2QOH2HWM.js +0 -95
  112. package/dist/chunk-6P3MWXYE.js +0 -440
  113. package/dist/chunk-FIW6WN23.js +0 -508
  114. package/dist/chunk-GAR5TQ5B.js +0 -199
  115. package/dist/chunk-ZO6MXAS3.js +0 -69
  116. package/dist/kernel-client-ZH4PSMCN.js +0 -367
  117. package/dist/kernel-wire-B4S8pnP3.d.ts +0 -65
  118. package/dist/useKeyboardRouter-Dsq553Ur.d.ts +0 -42
@@ -0,0 +1,490 @@
1
+ import { traitLevelFromMounted } from './chunk-PCR37T3U.js';
2
+ import { getStateRole } from './chunk-UXLE3IPR.js';
3
+ import { useState, useLayoutEffect } from 'react';
4
+
5
+ function useContainerWidth(ref) {
6
+ const [width, setWidth] = useState(null);
7
+ useLayoutEffect(() => {
8
+ const el = ref.current;
9
+ if (!el) return;
10
+ setWidth(el.clientWidth);
11
+ if (typeof ResizeObserver === "undefined") return;
12
+ const ro = new ResizeObserver(([entry]) => setWidth(entry.contentRect.width));
13
+ ro.observe(el);
14
+ return () => ro.disconnect();
15
+ }, [ref]);
16
+ return width;
17
+ }
18
+
19
+ // src/lib/avl-elk-layout.ts
20
+ function stateWidth(transitionCount) {
21
+ if (transitionCount >= 5) return 160;
22
+ if (transitionCount >= 3) return 130;
23
+ return 110;
24
+ }
25
+ var STATE_H = 40;
26
+ var elk;
27
+ function loadElk() {
28
+ elk ??= import('elkjs/lib/elk.bundled.js').then(({ default: Elk }) => new Elk());
29
+ return elk;
30
+ }
31
+ function flowOrder(data) {
32
+ const byName = new Map(data.states.map((s) => [s.name, s]));
33
+ const seen = /* @__PURE__ */ new Set();
34
+ const queue = data.states.filter((s) => s.isInitial).map((s) => s.name);
35
+ const out = [];
36
+ while (queue.length > 0) {
37
+ const name = queue.shift();
38
+ if (seen.has(name)) continue;
39
+ const state = byName.get(name);
40
+ if (!state) continue;
41
+ seen.add(name);
42
+ out.push(state);
43
+ for (const t of data.transitions) if (t.from === name && !seen.has(t.to)) queue.push(t.to);
44
+ }
45
+ for (const s of data.states) if (!seen.has(s.name)) out.push(s);
46
+ return out;
47
+ }
48
+ async function computeTraitLayout(data, metrics) {
49
+ const transitionCounts = {};
50
+ for (const s of data.states) transitionCounts[s.name] = 0;
51
+ for (const t of data.transitions) {
52
+ transitionCounts[t.from] = (transitionCounts[t.from] ?? 0) + 1;
53
+ transitionCounts[t.to] = (transitionCounts[t.to] ?? 0) + 1;
54
+ }
55
+ const maxTC = Math.max(...Object.values(transitionCounts), 0);
56
+ const LABEL_BASE_W = 100;
57
+ const LABEL_H = 44;
58
+ const states = metrics ? flowOrder(data) : data.states;
59
+ const elkGraph = {
60
+ id: "root",
61
+ layoutOptions: {
62
+ "elk.algorithm": "layered",
63
+ "elk.direction": metrics?.direction === "rtl" ? "LEFT" : "RIGHT",
64
+ "elk.spacing.nodeNode": String(metrics?.nodeSpacing ?? 80),
65
+ "elk.spacing.edgeNode": "30",
66
+ "elk.spacing.edgeEdge": "24",
67
+ "elk.spacing.edgeLabel": "10",
68
+ "elk.spacing.labelLabel": "8",
69
+ "elk.layered.spacing.nodeNodeBetweenLayers": String(metrics?.layerSpacing ?? 100),
70
+ ...metrics?.orthogonal ? { "elk.edgeRouting": "ORTHOGONAL" } : {},
71
+ ...metrics ? { "elk.layered.considerModelOrder.strategy": "NODES_AND_EDGES", "elk.layered.cycleBreaking.strategy": "MODEL_ORDER" } : {},
72
+ "elk.edgeLabels.placement": "CENTER",
73
+ "elk.layered.mergeEdges": "false",
74
+ "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX"
75
+ },
76
+ children: states.map((s) => {
77
+ const tc = transitionCounts[s.name] ?? 0;
78
+ const size = metrics ? metrics.nodeSize(s.name) : { width: stateWidth(tc), height: STATE_H };
79
+ return {
80
+ id: s.name,
81
+ width: size.width,
82
+ height: size.height,
83
+ labels: [{ text: s.name, width: size.width - 10, height: 14 }],
84
+ ...metrics && s.isInitial ? { layoutOptions: { "elk.layered.layering.layerConstraint": "FIRST" } } : {}
85
+ };
86
+ }),
87
+ edges: data.transitions.map((t, i) => {
88
+ const textW = Math.max(t.event.length * 8, 60);
89
+ const iconsW = Math.min(t.effects.length, 6) * 28 + 20;
90
+ const label = metrics ? metrics.labelSize(t) : { width: Math.max(textW, iconsW, LABEL_BASE_W), height: LABEL_H };
91
+ return {
92
+ id: `e${i}`,
93
+ sources: [t.from],
94
+ targets: [t.to],
95
+ labels: [{
96
+ text: t.event,
97
+ width: label.width,
98
+ height: label.height,
99
+ ...metrics ? { layoutOptions: { "elk.edgeLabels.inline": "true" } } : {}
100
+ }]
101
+ };
102
+ })
103
+ };
104
+ const layout = await (await loadElk()).layout(elkGraph);
105
+ const layoutChildren = layout.children ?? [];
106
+ const layoutEdges = layout.edges ?? [];
107
+ const nodeXMap = {};
108
+ for (const n of layoutChildren) {
109
+ nodeXMap[n.id] = n.x ?? 0;
110
+ }
111
+ const nodes = layoutChildren.map((n) => {
112
+ const name = n.id;
113
+ const stateInfo = data.states.find((s) => s.name === name);
114
+ const tc = transitionCounts[name] ?? 0;
115
+ return {
116
+ id: name,
117
+ x: n.x ?? 0,
118
+ y: n.y ?? 0,
119
+ width: n.width ?? 110,
120
+ height: n.height ?? STATE_H,
121
+ isInitial: stateInfo?.isInitial ?? void 0,
122
+ isTerminal: stateInfo?.isTerminal ?? void 0,
123
+ role: getStateRole(stateInfo?.isInitial ?? void 0, stateInfo?.isTerminal ?? void 0, tc, maxTC),
124
+ transitionCount: tc
125
+ };
126
+ });
127
+ const edges = layoutEdges.map((e, i) => {
128
+ const t = data.transitions[i];
129
+ const labels = e.labels ?? [];
130
+ const label = labels[0];
131
+ const sections = e.sections ?? [];
132
+ const points = [];
133
+ for (const section of sections) {
134
+ const bendPoints = section.bendPoints ?? [];
135
+ points.push({ x: section.startPoint.x, y: section.startPoint.y });
136
+ for (const bp of bendPoints) points.push({ x: bp.x, y: bp.y });
137
+ points.push({ x: section.endPoint.x, y: section.endPoint.y });
138
+ }
139
+ const isSelf = t.from === t.to;
140
+ const toX = nodeXMap[t.to] ?? 0;
141
+ const fromX = nodeXMap[t.from] ?? 0;
142
+ const isBackward = !isSelf && (metrics?.direction === "rtl" ? toX >= fromX : toX <= fromX);
143
+ const lw = label?.width ?? LABEL_BASE_W;
144
+ const lh = label?.height ?? LABEL_H;
145
+ return {
146
+ id: e.id,
147
+ from: t.from,
148
+ to: t.to,
149
+ event: t.event,
150
+ effects: t.effects,
151
+ guard: !!t.guard,
152
+ guardExpr: typeof t.guard === "string" ? t.guard : void 0,
153
+ index: t.index,
154
+ labelX: label?.x ?? 0,
155
+ labelY: label?.y ?? 0,
156
+ labelW: lw,
157
+ labelH: lh,
158
+ points,
159
+ isSelf,
160
+ isBackward
161
+ };
162
+ });
163
+ return {
164
+ nodes,
165
+ edges,
166
+ width: layout.width ?? 600,
167
+ height: layout.height ?? 400
168
+ };
169
+ }
170
+ function roundedEdgePath(points, radius) {
171
+ if (points.length < 3) return edgePath(points);
172
+ let d = `M ${points[0].x},${points[0].y}`;
173
+ for (let i = 1; i < points.length - 1; i++) {
174
+ const prev = points[i - 1];
175
+ const cur = points[i];
176
+ const next = points[i + 1];
177
+ const inLen = Math.hypot(cur.x - prev.x, cur.y - prev.y);
178
+ const outLen = Math.hypot(next.x - cur.x, next.y - cur.y);
179
+ const r = Math.min(radius, inLen / 2, outLen / 2);
180
+ if (r <= 0) {
181
+ d += ` L ${cur.x},${cur.y}`;
182
+ continue;
183
+ }
184
+ const ax = cur.x - (cur.x - prev.x) / inLen * r;
185
+ const ay = cur.y - (cur.y - prev.y) / inLen * r;
186
+ const bx = cur.x + (next.x - cur.x) / outLen * r;
187
+ const by = cur.y + (next.y - cur.y) / outLen * r;
188
+ d += ` L ${ax},${ay} Q ${cur.x},${cur.y} ${bx},${by}`;
189
+ }
190
+ const last = points[points.length - 1];
191
+ return `${d} L ${last.x},${last.y}`;
192
+ }
193
+ function edgePath(points) {
194
+ if (points.length === 0) return "";
195
+ let d = `M ${points[0].x},${points[0].y}`;
196
+ for (let i = 1; i < points.length; i++) d += ` L ${points[i].x},${points[i].y}`;
197
+ return d;
198
+ }
199
+ var BOX_PAD = 16;
200
+ var BOX_HEAD_MACHINE = 46;
201
+ var BOX_HEAD_CONTAINER = 38;
202
+ var COLLAPSED_H = 56;
203
+ var CHIP_H = 28;
204
+ var HEAD_GLYPH = 40;
205
+ var HEAD_TOGGLE = 28;
206
+ var LOOP_FOLD = 3;
207
+ var LOOP_LINE = 18;
208
+ function loopKey(trait, state) {
209
+ return `${trait}\0${state}`;
210
+ }
211
+ var LANE_HEAD = 30;
212
+ var LANE_MARGIN = 36;
213
+ var LANE_MIN_WIDTH = 480;
214
+ var PACK_ASPECT = 1.6;
215
+ var PACK_GAP = 14;
216
+ function sectionPoints(e) {
217
+ const points = [];
218
+ for (const section of e.sections ?? []) {
219
+ points.push({ x: section.startPoint.x, y: section.startPoint.y });
220
+ for (const bp of section.bendPoints ?? []) points.push({ x: bp.x, y: bp.y });
221
+ points.push({ x: section.endPoint.x, y: section.endPoint.y });
222
+ }
223
+ return points;
224
+ }
225
+ function boxWirePath(a, b) {
226
+ const ax = a.x + a.width / 2;
227
+ const ay = a.y + a.height / 2;
228
+ const bx = b.x + b.width / 2;
229
+ const by = b.y + b.height / 2;
230
+ if (b.x >= a.x + a.width) return [{ x: a.x + a.width, y: ay }, { x: b.x, y: by }];
231
+ if (a.x >= b.x + b.width) return [{ x: a.x, y: ay }, { x: b.x + b.width, y: by }];
232
+ if (by >= ay) return [{ x: ax, y: a.y + a.height }, { x: bx, y: b.y }];
233
+ return [{ x: ax, y: a.y }, { x: bx, y: b.y + b.height }];
234
+ }
235
+ function boxKind(trait, expandDepth, open, closed) {
236
+ if (trait.states.length <= 1) return "chip";
237
+ if (open.has(trait.trait)) return "machine";
238
+ if (closed.has(trait.trait)) return "collapsed";
239
+ return trait.depth < expandDepth ? "machine" : "collapsed";
240
+ }
241
+ function compactSize(trait, kind, charWidth) {
242
+ if (kind === "chip") return { width: Math.round(trait.trait.length * charWidth + 28 + HEAD_GLYPH), height: CHIP_H };
243
+ const sub = (trait.linkedEntity ?? "").length;
244
+ return { width: Math.max(132, Math.round(Math.max(trait.trait.length, sub) * charWidth + 64 + HEAD_GLYPH + HEAD_TOGGLE)), height: COLLAPSED_H };
245
+ }
246
+ function packOptions(padding, targetWidth) {
247
+ return {
248
+ "elk.algorithm": "rectpacking",
249
+ "elk.aspectRatio": String(PACK_ASPECT),
250
+ "elk.rectpacking.orderBySize": "false",
251
+ "elk.spacing.nodeNode": String(PACK_GAP),
252
+ "elk.padding": padding,
253
+ ...targetWidth === void 0 ? {} : { "elk.rectpacking.widthApproximation.targetWidth": String(targetWidth) }
254
+ };
255
+ }
256
+ async function computeOrbitalLayout(orbital, options) {
257
+ const { metrics, expandDepth, charWidth } = options;
258
+ const byName = new Map(orbital.traits.map((t) => [t.trait, t]));
259
+ const levels = new Map(orbital.traits.map((t) => [t.trait, traitLevelFromMounted(t)]));
260
+ const lane = orbital.traits.filter((t) => !t.renders && !t.linked);
261
+ const tree = orbital.traits.filter((t) => t.renders && !t.linked);
262
+ const linkedByOrbital = /* @__PURE__ */ new Map();
263
+ for (const t of orbital.traits.filter((x) => x.linked)) {
264
+ const key = t.orbital ?? "";
265
+ linkedByOrbital.set(key, [...linkedByOrbital.get(key) ?? [], t]);
266
+ }
267
+ const effectiveParent = /* @__PURE__ */ new Map();
268
+ for (const t of tree) {
269
+ let cur = t.parent === null ? void 0 : byName.get(t.parent);
270
+ while (cur !== void 0 && !cur.renders) cur = cur.parent === null ? void 0 : byName.get(cur.parent);
271
+ effectiveParent.set(t.trait, cur === void 0 ? null : cur.trait);
272
+ }
273
+ const childrenOf = /* @__PURE__ */ new Map();
274
+ const roots = [];
275
+ for (const t of tree) {
276
+ const p = effectiveParent.get(t.trait) ?? null;
277
+ if (p === null) roots.push(t);
278
+ else childrenOf.set(p, [...childrenOf.get(p) ?? [], t]);
279
+ }
280
+ const open = options.open ?? /* @__PURE__ */ new Set();
281
+ const closed = options.closed ?? /* @__PURE__ */ new Set();
282
+ const openLoops = options.openLoops ?? /* @__PURE__ */ new Set();
283
+ const loops = [];
284
+ const kinds = new Map(orbital.traits.map((t) => [t.trait, boxKind(t, expandDepth, open, closed)]));
285
+ const wirePairs = /* @__PURE__ */ new Map();
286
+ for (const w of orbital.wires) {
287
+ if (!byName.has(w.from) || !byName.has(w.to)) continue;
288
+ const key = `${w.from}\u2192${w.to}`;
289
+ const entry = wirePairs.get(key) ?? { from: w.from, to: w.to, pairs: [] };
290
+ entry.pairs.push({ event: w.event, triggers: w.triggers });
291
+ wirePairs.set(key, entry);
292
+ }
293
+ const wireLabel = (pairs) => [...new Set(pairs.map((p) => p.event))].join(", ");
294
+ const boxNode = (t) => {
295
+ const kind = kinds.get(t.trait) ?? "chip";
296
+ const kids = childrenOf.get(t.trait) ?? [];
297
+ const level = levels.get(t.trait);
298
+ const titleWidth = Math.round(Math.max(t.trait.length, (t.linkedEntity ?? "").length) * charWidth + 32 + HEAD_GLYPH + (kind === "chip" ? 0 : HEAD_TOGGLE));
299
+ if (kind !== "machine" && kids.length === 0) {
300
+ const size = compactSize(t, kind, charWidth);
301
+ return { id: `b:${t.trait}`, width: size.width, height: size.height };
302
+ }
303
+ const head = kind === "machine" ? BOX_HEAD_MACHINE : BOX_HEAD_CONTAINER;
304
+ const padding = `[top=${head},left=${BOX_PAD},bottom=${BOX_PAD},right=${BOX_PAD}]`;
305
+ const minimum = { "elk.nodeSize.constraints": "MINIMUM_SIZE", "elk.nodeSize.minimum": `(${titleWidth}, ${head + 20})` };
306
+ const kidNodes = kids.map(boxNode);
307
+ if (kind !== "machine" || level === void 0) {
308
+ return { id: `b:${t.trait}`, children: kidNodes, layoutOptions: { ...packOptions(padding), ...minimum } };
309
+ }
310
+ const selfCount = /* @__PURE__ */ new Map();
311
+ for (const tr of level.transitions) if (tr.from === tr.to) selfCount.set(tr.from, (selfCount.get(tr.from) ?? 0) + 1);
312
+ const folds = (tr) => tr.from === tr.to && (selfCount.get(tr.from) ?? 0) >= LOOP_FOLD;
313
+ for (const [state, count] of selfCount) {
314
+ if (count < LOOP_FOLD) continue;
315
+ loops.push({
316
+ trait: t.trait,
317
+ state,
318
+ events: level.transitions.filter((tr) => tr.from === state && tr.to === state).map((tr) => ({ event: tr.event, index: tr.index })),
319
+ open: openLoops.has(loopKey(t.trait, state))
320
+ });
321
+ }
322
+ const stateNodes = flowOrder(level).map((s) => {
323
+ const size = metrics.nodeSize(s.name);
324
+ const count = (selfCount.get(s.name) ?? 0) >= LOOP_FOLD ? selfCount.get(s.name) ?? 0 : 0;
325
+ const extra = count === 0 ? 0 : openLoops.has(loopKey(t.trait, s.name)) ? LOOP_LINE * (count + 1) + 8 : LOOP_LINE;
326
+ const longest = count === 0 ? 0 : Math.max(...level.transitions.filter((tr) => tr.from === s.name && tr.to === s.name).map((tr) => tr.event.length));
327
+ return {
328
+ id: `s:${t.trait}:${s.name}`,
329
+ width: Math.max(size.width, extra > LOOP_LINE ? Math.round(longest * charWidth + 40) : size.width),
330
+ height: size.height + extra,
331
+ layoutOptions: { "elk.partitioning.partition": "0", ...s.isInitial ? { "elk.layered.layering.layerConstraint": "FIRST" } : {} }
332
+ };
333
+ });
334
+ const group = kidNodes.length === 0 ? [] : [{
335
+ id: `k:${t.trait}`,
336
+ children: kidNodes,
337
+ layoutOptions: { ...packOptions("[top=0,left=0,bottom=0,right=0]"), "elk.partitioning.partition": "1" }
338
+ }];
339
+ return {
340
+ id: `b:${t.trait}`,
341
+ children: [...stateNodes, ...group],
342
+ edges: level.transitions.flatMap((tr, i) => {
343
+ if (folds(tr)) return [];
344
+ const size = metrics.labelSize(tr);
345
+ return [{
346
+ id: `x:${t.trait}:${i}`,
347
+ sources: [`s:${t.trait}:${tr.from}`],
348
+ targets: [`s:${t.trait}:${tr.to}`],
349
+ labels: [{ text: tr.event, width: size.width, height: size.height, layoutOptions: { "elk.edgeLabels.inline": "true" } }]
350
+ }];
351
+ }),
352
+ layoutOptions: {
353
+ "elk.algorithm": "layered",
354
+ "elk.direction": metrics.direction === "rtl" ? "LEFT" : "RIGHT",
355
+ "elk.padding": padding,
356
+ "elk.partitioning.activate": "true",
357
+ "elk.spacing.nodeNode": String(metrics.nodeSpacing),
358
+ "elk.spacing.edgeNode": "30",
359
+ "elk.spacing.edgeEdge": "24",
360
+ "elk.spacing.edgeLabel": "10",
361
+ "elk.layered.spacing.nodeNodeBetweenLayers": String(metrics.layerSpacing),
362
+ "elk.edgeRouting": "ORTHOGONAL",
363
+ "elk.layered.considerModelOrder.strategy": "NODES_AND_EDGES",
364
+ "elk.layered.cycleBreaking.strategy": "MODEL_ORDER",
365
+ "elk.edgeLabels.placement": "CENTER",
366
+ "elk.layered.mergeEdges": "false",
367
+ "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX",
368
+ ...minimum
369
+ }
370
+ };
371
+ };
372
+ const graph = {
373
+ id: "root",
374
+ layoutOptions: { ...packOptions("[top=0,left=0,bottom=0,right=0]"), "elk.hierarchyHandling": "SEPARATE_CHILDREN" },
375
+ children: roots.map(boxNode)
376
+ };
377
+ const elkEngine = await loadElk();
378
+ const result = roots.length === 0 ? { width: 0, height: 0 } : await elkEngine.layout(graph);
379
+ const boxes = [];
380
+ const groups = [];
381
+ const states = [];
382
+ const transitionEdges = [];
383
+ const walk = (node, ox, oy, parent) => {
384
+ for (const e of node.edges ?? []) {
385
+ const [, ...rest] = e.id.split(":");
386
+ const index = Number(rest[rest.length - 1]);
387
+ const trait = rest.slice(0, -1).join(":");
388
+ const tr = levels.get(trait)?.transitions[index];
389
+ if (tr === void 0) continue;
390
+ const label = (e.labels ?? [])[0];
391
+ transitionEdges.push({
392
+ id: e.id,
393
+ trait,
394
+ index: tr.index,
395
+ from: tr.from,
396
+ to: tr.to,
397
+ event: tr.event,
398
+ points: sectionPoints(e).map((p) => ({ x: p.x + ox, y: p.y + oy })),
399
+ labelX: (label?.x ?? 0) + ox,
400
+ labelY: (label?.y ?? 0) + oy,
401
+ labelW: label?.width ?? 0,
402
+ labelH: label?.height ?? 0,
403
+ isSelf: tr.from === tr.to
404
+ });
405
+ }
406
+ for (const c of node.children ?? []) {
407
+ const x = ox + (c.x ?? 0);
408
+ const y = oy + (c.y ?? 0);
409
+ if (c.id.startsWith("b:")) {
410
+ const name = c.id.slice(2);
411
+ boxes.push({ trait: name, kind: kinds.get(name) ?? "chip", lane: false, parent, container: (childrenOf.get(name) ?? []).length > 0, x, y, width: c.width ?? 0, height: c.height ?? 0 });
412
+ walk(c, x, y, name);
413
+ } else if (c.id.startsWith("g:")) {
414
+ groups.push({ orbital: c.id.slice(2), x, y, width: c.width ?? 0, height: c.height ?? 0 });
415
+ walk(c, x, y, null);
416
+ } else if (c.id.startsWith("k:")) {
417
+ walk(c, x, y, parent);
418
+ } else if (c.id.startsWith("s:")) {
419
+ const [, trait, ...rest] = c.id.split(":");
420
+ const name = rest.join(":");
421
+ const info = byName.get(trait)?.states.find((s) => s.name === name);
422
+ states.push({ trait, name, isInitial: info?.isInitial ?? false, isTerminal: info?.isTerminal ?? false, x, y, width: c.width ?? 0, height: c.height ?? 0 });
423
+ }
424
+ }
425
+ };
426
+ walk(result, 0, 0, null);
427
+ let width = result.width ?? 0;
428
+ let height = result.height ?? 0;
429
+ let laneTop = null;
430
+ if (lane.length > 0) {
431
+ laneTop = height + LANE_MARGIN;
432
+ const laneWidth = Math.max(width, LANE_MIN_WIDTH);
433
+ const chipSize = new Map(lane.map((t) => [t.trait, compactSize(t, kinds.get(t.trait) === "chip" ? "chip" : "collapsed", charWidth)]));
434
+ const packed = await elkEngine.layout({
435
+ id: "lane",
436
+ layoutOptions: packOptions("[top=0,left=0,bottom=0,right=0]", laneWidth),
437
+ children: lane.map((t) => ({ id: `b:${t.trait}`, width: chipSize.get(t.trait)?.width ?? 0, height: chipSize.get(t.trait)?.height ?? 0 }))
438
+ });
439
+ for (const c of packed.children ?? []) {
440
+ const name = c.id.slice(2);
441
+ boxes.push({ trait: name, kind: kinds.get(name) === "chip" ? "chip" : "collapsed", lane: true, parent: null, container: false, x: c.x ?? 0, y: laneTop + LANE_HEAD + (c.y ?? 0), width: c.width ?? 0, height: c.height ?? 0 });
442
+ }
443
+ width = Math.max(width, packed.width ?? 0);
444
+ height = laneTop + LANE_HEAD + (packed.height ?? 0);
445
+ }
446
+ let groupTop = null;
447
+ if (linkedByOrbital.size > 0) {
448
+ groupTop = height + LANE_MARGIN;
449
+ const padding = `[top=${BOX_HEAD_CONTAINER},left=${BOX_PAD},bottom=${BOX_PAD},right=${BOX_PAD}]`;
450
+ const packed = await elkEngine.layout({
451
+ id: "groups",
452
+ layoutOptions: { ...packOptions("[top=0,left=0,bottom=0,right=0]", Math.max(width, LANE_MIN_WIDTH)), "elk.hierarchyHandling": "SEPARATE_CHILDREN" },
453
+ children: [...linkedByOrbital].map(([name, traits]) => ({
454
+ id: `g:${name}`,
455
+ children: traits.map(boxNode),
456
+ layoutOptions: {
457
+ ...packOptions(padding),
458
+ "elk.nodeSize.constraints": "MINIMUM_SIZE",
459
+ "elk.nodeSize.minimum": `(${Math.round(name.length * charWidth + 32 + HEAD_GLYPH)}, ${BOX_HEAD_CONTAINER + 20})`
460
+ }
461
+ }))
462
+ });
463
+ walk(packed, 0, groupTop + LANE_HEAD, null);
464
+ width = Math.max(width, packed.width ?? 0);
465
+ height = groupTop + LANE_HEAD + (packed.height ?? 0);
466
+ }
467
+ const embeds = [];
468
+ for (const t of tree) {
469
+ const parent = effectiveParent.get(t.trait) ?? null;
470
+ const child = boxes.find((b) => b.trait === t.trait);
471
+ if (parent === null || child === void 0) continue;
472
+ for (const state of t.embeddedIn) {
473
+ const node = states.find((s) => s.trait === parent && s.name === state);
474
+ if (node !== void 0) embeds.push({ trait: t.trait, state, points: boxWirePath(node, child) });
475
+ }
476
+ }
477
+ const wires = [];
478
+ for (const [key, w] of wirePairs) {
479
+ const a = boxes.find((b2) => b2.trait === w.from);
480
+ const b = boxes.find((x) => x.trait === w.to);
481
+ if (a === void 0 || b === void 0) continue;
482
+ const points = boxWirePath(a, b);
483
+ const size = options.wireLabelSize(wireLabel(w.pairs));
484
+ const mid = { x: (points[0].x + points[1].x) / 2, y: (points[0].y + points[1].y) / 2 };
485
+ wires.push({ key, from: w.from, to: w.to, pairs: w.pairs, points, labelX: mid.x - size.width / 2, labelY: mid.y - size.height / 2, labelW: size.width, labelH: size.height });
486
+ }
487
+ return { boxes, loops, groups, groupTop, states, edges: transitionEdges, embeds, wires, laneTop, width, height };
488
+ }
489
+
490
+ export { LOOP_LINE, computeOrbitalLayout, computeTraitLayout, edgePath, loopKey, roundedEdgePath, useContainerWidth };
@@ -1,4 +1,4 @@
1
- import { ThemeProvider, useTheme } from './chunk-MBQAMMSE.js';
1
+ import { ThemeProvider, useTheme } from './chunk-4YXBKHHM.js';
2
2
 
3
3
  // src/providers/DesignThemeContext.tsx
4
4
  var DesignThemeProvider = ThemeProvider;
@@ -1,5 +1,5 @@
1
- import { claimDelivery } from './chunk-R5O5AUPI.js';
2
- import { useEventBus, getTraitPresence, beginPending, endPending } from './chunk-MBQAMMSE.js';
1
+ import { claimDelivery } from './chunk-PRXQGGCO.js';
2
+ import { useEventBus, getTraitPresence, beginPending, endPending } from './chunk-4YXBKHHM.js';
3
3
  import { createContext, useState, useCallback, useEffect, useMemo, useRef, useContext, useSyncExternalStore } from 'react';
4
4
  import { createLogger } from '@almadar/logger';
5
5
  import { mergeEntityFrame } from '@almadar/core';