@sebastianwessel/isostate 0.5.0 → 0.6.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 (73) hide show
  1. package/dist/animation/animation-engine.d.ts +2 -0
  2. package/dist/animation/animation-engine.d.ts.map +1 -1
  3. package/dist/animation/controller.d.ts +4 -2
  4. package/dist/animation/controller.d.ts.map +1 -1
  5. package/dist/assets/software-architecture/IMAGEGEN-PROMPTS.md +66 -0
  6. package/dist/assets/software-architecture/LICENSE +21 -0
  7. package/dist/assets/software-architecture/NOTICE.md +17 -0
  8. package/dist/assets/software-architecture/README.md +105 -0
  9. package/dist/assets/software-architecture/agentic/AGENT-VISUAL-PROMPTS.md +42 -0
  10. package/dist/assets/software-architecture/agentic/HANDOFF-PROMPTS.md +19 -0
  11. package/dist/assets/software-architecture/agentic/PROCESS-VISUAL-PROMPTS.md +109 -0
  12. package/dist/assets/software-architecture/agentic/agents-sprites.png +0 -0
  13. package/dist/assets/software-architecture/agentic/ai-capabilities-sprites.png +0 -0
  14. package/dist/assets/software-architecture/agentic/ai-to-human-handoff.png +0 -0
  15. package/dist/assets/software-architecture/agentic/channels-sprites.png +0 -0
  16. package/dist/assets/software-architecture/agentic/human-to-ai-handoff.png +0 -0
  17. package/dist/assets/software-architecture/agentic/humans-sprites.png +0 -0
  18. package/dist/assets/software-architecture/agentic/infrastructure-sprites.png +0 -0
  19. package/dist/assets/software-architecture/agentic/lifecycle-sprites.png +0 -0
  20. package/dist/assets/software-architecture/agentic/orchestration-sprites.png +0 -0
  21. package/dist/assets/software-architecture/agentic/providers-sprites.png +0 -0
  22. package/dist/assets/software-architecture/agentic/servicenow-sprites.png +0 -0
  23. package/dist/assets/software-architecture/architecture/architecture-sprites.png +0 -0
  24. package/dist/assets/software-architecture/manifest.json +2095 -0
  25. package/dist/assets/software-architecture/workflow/workflow-process-sprites.png +0 -0
  26. package/dist/browser/isostate.runtime.js +4 -4
  27. package/dist/browser/isostate.runtime.js.map +9 -8
  28. package/dist/chunks/errors-2yA81Vfb.js +23 -0
  29. package/dist/chunks/{errors-DyqEkrm5.js.map → errors-2yA81Vfb.js.map} +1 -1
  30. package/dist/chunks/index-WmsNtuaZ.js +1685 -0
  31. package/dist/chunks/index-WmsNtuaZ.js.map +1 -0
  32. package/dist/chunks/rendering-engine-DLaM1XbU.js +1425 -0
  33. package/dist/chunks/rendering-engine-DLaM1XbU.js.map +1 -0
  34. package/dist/chunks/scene-parser-BNXXIAqj.js +3033 -0
  35. package/dist/chunks/scene-parser-BNXXIAqj.js.map +1 -0
  36. package/dist/chunks/sha256-BkgWUdh1.js +123 -0
  37. package/dist/chunks/sha256-BkgWUdh1.js.map +1 -0
  38. package/dist/dsl/browser.js +3 -3
  39. package/dist/dsl/index.js +3 -3
  40. package/dist/dsl/scene-parser.d.ts.map +1 -1
  41. package/dist/dsl/scene-validator.d.ts.map +1 -1
  42. package/dist/dsl/workflow-effects-validation.d.ts +8 -0
  43. package/dist/dsl/workflow-effects-validation.d.ts.map +1 -0
  44. package/dist/editor-support/adapter.d.ts.map +1 -1
  45. package/dist/editor-support/index.js +347 -394
  46. package/dist/editor-support/index.js.map +1 -1
  47. package/dist/index.d.ts +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +356 -424
  50. package/dist/index.js.map +1 -1
  51. package/dist/rendering/animation-css.d.ts.map +1 -1
  52. package/dist/rendering/rendering-engine.d.ts +2 -0
  53. package/dist/rendering/rendering-engine.d.ts.map +1 -1
  54. package/dist/rendering/scene-effects.d.ts +15 -0
  55. package/dist/rendering/scene-effects.d.ts.map +1 -0
  56. package/dist/runtime/index.js +4 -4
  57. package/dist/runtime/interactivity.d.ts.map +1 -1
  58. package/dist/types/asset-registry.d.ts.map +1 -1
  59. package/dist/types/errors.d.ts.map +1 -1
  60. package/dist/types/index.d.ts +1 -1
  61. package/dist/types/index.d.ts.map +1 -1
  62. package/dist/types/node.d.ts +40 -1
  63. package/dist/types/node.d.ts.map +1 -1
  64. package/package.json +9 -8
  65. package/dist/chunks/errors-DyqEkrm5.js +0 -29
  66. package/dist/chunks/index-CB6XEsbY.js +0 -1756
  67. package/dist/chunks/index-CB6XEsbY.js.map +0 -1
  68. package/dist/chunks/rendering-engine-nkqYx0qc.js +0 -1303
  69. package/dist/chunks/rendering-engine-nkqYx0qc.js.map +0 -1
  70. package/dist/chunks/scene-parser-F69XGE0l.js +0 -2743
  71. package/dist/chunks/scene-parser-F69XGE0l.js.map +0 -1
  72. package/dist/chunks/sha256-4JuurR-b.js +0 -69
  73. package/dist/chunks/sha256-4JuurR-b.js.map +0 -1
@@ -1,428 +1,381 @@
1
- import { g as getResolvedProjectionLayout, p as projectToRaw, a as getResolvedViewBox, b as getCurrentElementBounds, c as getElementState, h as hideElementAfterExit, u as unhideElementOnReadd, d as getConnectorState, e as updateElementTransforms } from '../chunks/rendering-engine-nkqYx0qc.js';
2
- import { R as RenderError } from '../chunks/errors-DyqEkrm5.js';
1
+ import { g as getResolvedProjectionLayout, p as projectToRaw, a as getResolvedViewBox, b as getElementState, c as getCurrentElementBounds, h as hideElementAfterExit, u as unhideElementOnReadd, d as getConnectorState, e as updateElementTransforms } from '../chunks/rendering-engine-DLaM1XbU.js';
2
+ import { R as RenderError } from '../chunks/errors-2yA81Vfb.js';
3
3
 
4
- /**
5
- * Project an isometric grid point into SVG screen coordinates.
6
- * Uses the same projection, bounds, and padding as the renderer.
7
- */
8
4
  function projectGridPoint(bundle, point) {
9
- const layout = getResolvedProjectionLayout(bundle);
10
- const rawX = layout.cellSize * (point[0] - point[1]) * 0.5;
11
- const rawY = layout.cellSize * (point[0] + point[1]) * 0.25;
12
- return {
13
- x: rawX - layout.selectedBounds.minX + layout.padding.x,
14
- y: rawY - layout.selectedBounds.minY + layout.padding.y,
15
- };
5
+ const layout = getResolvedProjectionLayout(bundle);
6
+ const rawX = layout.cellSize * (point[0] - point[1]) * 0.5;
7
+ const rawY = layout.cellSize * (point[0] + point[1]) * 0.25;
8
+ return {
9
+ x: rawX - layout.selectedBounds.minX + layout.padding.x,
10
+ y: rawY - layout.selectedBounds.minY + layout.padding.y
11
+ };
16
12
  }
17
- /**
18
- * Unproject an SVG screen point back into fractional isometric grid coordinates.
19
- * The editor owns snap-to-grid rounding.
20
- */
21
13
  function unprojectScreenPoint(bundle, point) {
22
- const layout = getResolvedProjectionLayout(bundle);
23
- const rawX = point.x + layout.selectedBounds.minX - layout.padding.x;
24
- const rawY = point.y + layout.selectedBounds.minY - layout.padding.y;
25
- const cellSize = layout.cellSize;
26
- const gridX = rawX / cellSize + (2 * rawY) / cellSize;
27
- const gridY = (2 * rawY) / cellSize - rawX / cellSize;
28
- return [gridX, gridY];
14
+ const layout = getResolvedProjectionLayout(bundle);
15
+ const rawX = point.x + layout.selectedBounds.minX - layout.padding.x;
16
+ const rawY = point.y + layout.selectedBounds.minY - layout.padding.y;
17
+ const cellSize = layout.cellSize;
18
+ const gridX = rawX / cellSize + 2 * rawY / cellSize;
19
+ const gridY = 2 * rawY / cellSize - rawX / cellSize;
20
+ return [gridX, gridY];
29
21
  }
30
- /**
31
- * Convert browser pointer coordinates into SVG user units using the root SVG
32
- * screen CTM inverse.
33
- * @throws {RenderError} `EDITOR_GEOMETRY_UNAVAILABLE` when the CTM is missing or not invertible.
34
- */
35
22
  function clientPointToSvgPoint(svg, point) {
36
- const ctm = svg.getScreenCTM();
37
- if (!ctm) {
38
- throw new RenderError("EDITOR_GEOMETRY_UNAVAILABLE", "SVG CTM is not available");
39
- }
40
- let inverse = null;
41
- try {
42
- inverse = ctm.inverse();
43
- }
44
- catch {
45
- // non-invertible matrix
46
- }
47
- if (!inverse) {
48
- throw new RenderError("EDITOR_GEOMETRY_UNAVAILABLE", "SVG CTM is not invertible");
49
- }
50
- const svgPoint = svg.createSVGPoint();
51
- svgPoint.x = point.clientX;
52
- svgPoint.y = point.clientY;
53
- const result = svgPoint.matrixTransform(inverse);
54
- return { x: result.x, y: result.y };
23
+ const ctm = svg.getScreenCTM();
24
+ if (!ctm) {
25
+ throw new RenderError("EDITOR_GEOMETRY_UNAVAILABLE", "SVG CTM is not available");
26
+ }
27
+ let inverse = null;
28
+ try {
29
+ inverse = ctm.inverse();
30
+ } catch {
31
+ }
32
+ if (!inverse) {
33
+ throw new RenderError("EDITOR_GEOMETRY_UNAVAILABLE", "SVG CTM is not invertible");
34
+ }
35
+ const svgPoint = svg.createSVGPoint();
36
+ svgPoint.x = point.clientX;
37
+ svgPoint.y = point.clientY;
38
+ const result = svgPoint.matrixTransform(inverse);
39
+ return { x: result.x, y: result.y };
55
40
  }
56
- /**
57
- * Return the four projected corners of a grid cell in clockwise order.
58
- */
59
41
  function getGridCellPolygon(bundle, cell) {
60
- const [x, y] = cell;
61
- return [
62
- projectGridPoint(bundle, [x, y]),
63
- projectGridPoint(bundle, [x + 1, y]),
64
- projectGridPoint(bundle, [x + 1, y + 1]),
65
- projectGridPoint(bundle, [x, y + 1]),
66
- ];
42
+ const [x, y] = cell;
43
+ return [
44
+ projectGridPoint(bundle, [x, y]),
45
+ projectGridPoint(bundle, [x + 1, y]),
46
+ projectGridPoint(bundle, [x + 1, y + 1]),
47
+ projectGridPoint(bundle, [x, y + 1])
48
+ ];
67
49
  }
68
50
 
69
- /**
70
- * Find the topmost runtime object at a screen point.
71
- * Hit testing follows the current rendered depth order so the visually
72
- * topmost object wins.
73
- */
74
51
  function getRuntimeObjectAtPoint(adapter, point, options = {}) {
75
- const kinds = options.kinds ?? ["element", "connection"];
76
- const currentScene = adapter.mounted.engine.getCurrentState();
77
- if (!currentScene)
78
- return undefined;
79
- const objects = adapter.getObjects(currentScene.id);
80
- const layerOrder = adapter.getLayerOrder();
81
- const layerRank = new Map(layerOrder.map((l, i) => [l.name, i]));
82
- const candidates = objects
83
- .filter((obj) => kinds.includes(obj.kind))
84
- .filter((obj) => options.includeHidden || obj.present)
85
- .sort((a, b) => {
86
- const rankA = layerRank.get(a.layer) ?? -1;
87
- const rankB = layerRank.get(b.layer) ?? -1;
88
- return rankA - rankB;
89
- });
90
- // Check topmost (highest layer rank) first
91
- for (let i = candidates.length - 1; i >= 0; i--) {
92
- const obj = candidates[i];
93
- if (pointInBounds(point, obj.bounds)) {
94
- return {
95
- id: obj.id,
96
- kind: obj.kind,
97
- layer: obj.layer,
98
- bounds: obj.bounds,
99
- };
100
- }
52
+ const kinds = options.kinds ?? ["element", "connection"];
53
+ const currentScene = adapter.mounted.engine.getCurrentState();
54
+ if (!currentScene) return void 0;
55
+ const objects = adapter.getObjects(currentScene.id);
56
+ const layerOrder = adapter.getLayerOrder();
57
+ const layerRank = new Map(layerOrder.map((l, i) => [l.name, i]));
58
+ const candidates = objects.filter((obj) => kinds.includes(obj.kind)).filter((obj) => options.includeHidden || obj.present).sort((a, b) => {
59
+ const rankA = layerRank.get(a.layer) ?? -1;
60
+ const rankB = layerRank.get(b.layer) ?? -1;
61
+ return rankA - rankB;
62
+ });
63
+ for (let i = candidates.length - 1; i >= 0; i--) {
64
+ const obj = candidates[i];
65
+ if (pointInBounds(point, obj.bounds)) {
66
+ return {
67
+ id: obj.id,
68
+ kind: obj.kind,
69
+ layer: obj.layer,
70
+ bounds: obj.bounds
71
+ };
101
72
  }
102
- return undefined;
73
+ }
74
+ return void 0;
103
75
  }
104
- /**
105
- * Compute the union bounds of a selection of runtime objects.
106
- * Missing ids are ignored. Returns `undefined` if no ids resolve.
107
- */
108
76
  function getRuntimeSelectionBounds(adapter, ids) {
109
- let minX = Number.POSITIVE_INFINITY;
110
- let minY = Number.POSITIVE_INFINITY;
111
- let maxX = Number.NEGATIVE_INFINITY;
112
- let maxY = Number.NEGATIVE_INFINITY;
113
- for (const id of ids) {
114
- const obj = adapter.getObject(id);
115
- if (!obj?.present)
116
- continue;
117
- const b = obj.bounds;
118
- minX = Math.min(minX, b.minX);
119
- minY = Math.min(minY, b.minY);
120
- maxX = Math.max(maxX, b.minX + b.width);
121
- maxY = Math.max(maxY, b.minY + b.height);
122
- }
123
- if (!Number.isFinite(minX))
124
- return undefined;
125
- return {
126
- minX,
127
- minY,
128
- width: maxX - minX,
129
- height: maxY - minY,
130
- };
77
+ let minX = Number.POSITIVE_INFINITY;
78
+ let minY = Number.POSITIVE_INFINITY;
79
+ let maxX = Number.NEGATIVE_INFINITY;
80
+ let maxY = Number.NEGATIVE_INFINITY;
81
+ for (const id of ids) {
82
+ const obj = adapter.getObject(id);
83
+ if (!obj?.present) continue;
84
+ const b = obj.bounds;
85
+ minX = Math.min(minX, b.minX);
86
+ minY = Math.min(minY, b.minY);
87
+ maxX = Math.max(maxX, b.minX + b.width);
88
+ maxY = Math.max(maxY, b.minY + b.height);
89
+ }
90
+ if (!Number.isFinite(minX)) return void 0;
91
+ return {
92
+ minX,
93
+ minY,
94
+ width: maxX - minX,
95
+ height: maxY - minY
96
+ };
131
97
  }
132
98
  function pointInBounds(point, bounds) {
133
- return (point.x >= bounds.minX &&
134
- point.x <= bounds.minX + bounds.width &&
135
- point.y >= bounds.minY &&
136
- point.y <= bounds.minY + bounds.height);
99
+ return point.x >= bounds.minX && point.x <= bounds.minX + bounds.width && point.y >= bounds.minY && point.y <= bounds.minY + bounds.height;
137
100
  }
138
- /** Compute screen-space bounds for a connector route. */
139
101
  function getConnectionBounds(route, bundle) {
140
- const layout = resolveLayoutForBounds(bundle);
141
- let minRawX = Number.POSITIVE_INFINITY;
142
- let minRawY = Number.POSITIVE_INFINITY;
143
- let maxRawX = Number.NEGATIVE_INFINITY;
144
- let maxRawY = Number.NEGATIVE_INFINITY;
145
- for (const [x, y] of route) {
146
- const { rawX, rawY } = projectToRaw(x, y, layout.cellSize);
147
- minRawX = Math.min(minRawX, rawX);
148
- minRawY = Math.min(minRawY, rawY);
149
- maxRawX = Math.max(maxRawX, rawX);
150
- maxRawY = Math.max(maxRawY, rawY);
151
- }
152
- const offsetX = -layout.selectedBounds.minX + layout.padding.x;
153
- const offsetY = -layout.selectedBounds.minY + layout.padding.y;
154
- return {
155
- minX: minRawX + offsetX,
156
- minY: minRawY + offsetY,
157
- width: maxRawX - minRawX,
158
- height: maxRawY - minRawY,
159
- };
102
+ const layout = resolveLayoutForBounds(bundle);
103
+ let minRawX = Number.POSITIVE_INFINITY;
104
+ let minRawY = Number.POSITIVE_INFINITY;
105
+ let maxRawX = Number.NEGATIVE_INFINITY;
106
+ let maxRawY = Number.NEGATIVE_INFINITY;
107
+ for (const [x, y] of route) {
108
+ const { rawX, rawY } = projectToRaw(x, y, layout.cellSize);
109
+ minRawX = Math.min(minRawX, rawX);
110
+ minRawY = Math.min(minRawY, rawY);
111
+ maxRawX = Math.max(maxRawX, rawX);
112
+ maxRawY = Math.max(maxRawY, rawY);
113
+ }
114
+ const offsetX = -layout.selectedBounds.minX + layout.padding.x;
115
+ const offsetY = -layout.selectedBounds.minY + layout.padding.y;
116
+ return {
117
+ minX: minRawX + offsetX,
118
+ minY: minRawY + offsetY,
119
+ width: maxRawX - minRawX,
120
+ height: maxRawY - minRawY
121
+ };
160
122
  }
161
- // Lightweight re-computation of the layout values needed for bounds projection.
162
123
  function resolveLayoutForBounds(bundle) {
163
- const cellSize = bundle.grid.cellSize;
164
- const padding = bundle.layout.padding;
165
- // Reproduce content bounds calculation
166
- let cMinX = Number.POSITIVE_INFINITY;
167
- let cMinY = Number.POSITIVE_INFINITY;
168
- let cMaxX = Number.NEGATIVE_INFINITY;
169
- let cMaxY = Number.NEGATIVE_INFINITY;
170
- for (const stop of bundle.scenes) {
171
- for (const el of stop.elements ?? []) {
172
- if (el.presence === "removed")
173
- continue;
174
- const { rawX, rawY } = projectToRaw(el.pos[0] + el.size, el.pos[1] + el.size, cellSize);
175
- const visualSize = cellSize * el.size;
176
- const anchor = bundle.assets?.[el.asset]?.anchor ?? [0.5, 1];
177
- cMinX = Math.min(cMinX, rawX - visualSize * anchor[0]);
178
- cMinY = Math.min(cMinY, rawY - visualSize * anchor[1]);
179
- cMaxX = Math.max(cMaxX, rawX + visualSize * (1 - anchor[0]));
180
- cMaxY = Math.max(cMaxY, rawY + visualSize * (1 - anchor[1]));
181
- }
182
- for (const conn of stop.connectors ?? []) {
183
- if (conn.presence === "removed")
184
- continue;
185
- for (const [x, y] of conn.route) {
186
- const { rawX, rawY } = projectToRaw(x, y, cellSize);
187
- cMinX = Math.min(cMinX, rawX);
188
- cMinY = Math.min(cMinY, rawY);
189
- cMaxX = Math.max(cMaxX, rawX);
190
- cMaxY = Math.max(cMaxY, rawY);
191
- }
192
- }
124
+ const cellSize = bundle.grid.cellSize;
125
+ const padding = bundle.layout.padding;
126
+ let cMinX = Number.POSITIVE_INFINITY;
127
+ let cMinY = Number.POSITIVE_INFINITY;
128
+ let cMaxX = Number.NEGATIVE_INFINITY;
129
+ let cMaxY = Number.NEGATIVE_INFINITY;
130
+ for (const stop of bundle.scenes) {
131
+ for (const el of stop.elements ?? []) {
132
+ if (el.presence === "removed") continue;
133
+ const { rawX, rawY } = projectToRaw(el.pos[0] + el.size, el.pos[1] + el.size, cellSize);
134
+ const visualSize = cellSize * el.size;
135
+ const anchor = bundle.assets?.[el.asset]?.anchor ?? [0.5, 1];
136
+ cMinX = Math.min(cMinX, rawX - visualSize * anchor[0]);
137
+ cMinY = Math.min(cMinY, rawY - visualSize * anchor[1]);
138
+ cMaxX = Math.max(cMaxX, rawX + visualSize * (1 - anchor[0]));
139
+ cMaxY = Math.max(cMaxY, rawY + visualSize * (1 - anchor[1]));
193
140
  }
194
- if (!Number.isFinite(cMinX)) {
195
- cMinX = 0;
196
- cMinY = 0;
197
- cMaxX = cellSize;
198
- cMaxY = cellSize;
199
- }
200
- // Floor bounds
201
- const [ox, oy] = bundle.floor.origin;
202
- const [fw, fh] = bundle.floor.size;
203
- const floorPoints = [
204
- [ox, oy],
205
- [ox + fw, oy],
206
- [ox, oy + fh],
207
- [ox + fw, oy + fh],
208
- ];
209
- let fMinX = Number.POSITIVE_INFINITY;
210
- let fMinY = Number.POSITIVE_INFINITY;
211
- let fMaxX = Number.NEGATIVE_INFINITY;
212
- let fMaxY = Number.NEGATIVE_INFINITY;
213
- for (const [x, y] of floorPoints) {
141
+ for (const conn of stop.connectors ?? []) {
142
+ if (conn.presence === "removed") continue;
143
+ for (const [x, y] of conn.route) {
214
144
  const { rawX, rawY } = projectToRaw(x, y, cellSize);
215
- fMinX = Math.min(fMinX, rawX);
216
- fMinY = Math.min(fMinY, rawY);
217
- fMaxX = Math.max(fMaxX, rawX);
218
- fMaxY = Math.max(fMaxY, rawY);
219
- }
220
- // Select bounds
221
- let sMinX;
222
- let sMinY;
223
- let sMaxX;
224
- let sMaxY;
225
- const mode = bundle.layout.bounds;
226
- if (mode === "content") {
227
- sMinX = cMinX;
228
- sMinY = cMinY;
229
- sMaxX = cMaxX;
230
- sMaxY = cMaxY;
231
- }
232
- else if (mode === "floor") {
233
- sMinX = fMinX;
234
- sMinY = fMinY;
235
- sMaxX = fMaxX;
236
- sMaxY = fMaxY;
145
+ cMinX = Math.min(cMinX, rawX);
146
+ cMinY = Math.min(cMinY, rawY);
147
+ cMaxX = Math.max(cMaxX, rawX);
148
+ cMaxY = Math.max(cMaxY, rawY);
149
+ }
237
150
  }
238
- else {
239
- sMinX = Math.min(cMinX, fMinX);
240
- sMinY = Math.min(cMinY, fMinY);
241
- sMaxX = Math.max(cMaxX, fMaxX);
242
- sMaxY = Math.max(cMaxY, fMaxY);
243
- }
244
- return {
245
- cellSize,
246
- padding,
247
- selectedBounds: { minX: sMinX, minY: sMinY, maxX: sMaxX, maxY: sMaxY },
248
- };
151
+ }
152
+ if (!Number.isFinite(cMinX)) {
153
+ cMinX = 0;
154
+ cMinY = 0;
155
+ cMaxX = cellSize;
156
+ cMaxY = cellSize;
157
+ }
158
+ const [ox, oy] = bundle.floor.origin;
159
+ const [fw, fh] = bundle.floor.size;
160
+ const floorPoints = [
161
+ [ox, oy],
162
+ [ox + fw, oy],
163
+ [ox, oy + fh],
164
+ [ox + fw, oy + fh]
165
+ ];
166
+ let fMinX = Number.POSITIVE_INFINITY;
167
+ let fMinY = Number.POSITIVE_INFINITY;
168
+ let fMaxX = Number.NEGATIVE_INFINITY;
169
+ let fMaxY = Number.NEGATIVE_INFINITY;
170
+ for (const [x, y] of floorPoints) {
171
+ const { rawX, rawY } = projectToRaw(x, y, cellSize);
172
+ fMinX = Math.min(fMinX, rawX);
173
+ fMinY = Math.min(fMinY, rawY);
174
+ fMaxX = Math.max(fMaxX, rawX);
175
+ fMaxY = Math.max(fMaxY, rawY);
176
+ }
177
+ let sMinX;
178
+ let sMinY;
179
+ let sMaxX;
180
+ let sMaxY;
181
+ const mode = bundle.layout.bounds;
182
+ if (mode === "content") {
183
+ sMinX = cMinX;
184
+ sMinY = cMinY;
185
+ sMaxX = cMaxX;
186
+ sMaxY = cMaxY;
187
+ } else if (mode === "floor") {
188
+ sMinX = fMinX;
189
+ sMinY = fMinY;
190
+ sMaxX = fMaxX;
191
+ sMaxY = fMaxY;
192
+ } else {
193
+ sMinX = Math.min(cMinX, fMinX);
194
+ sMinY = Math.min(cMinY, fMinY);
195
+ sMaxX = Math.max(cMaxX, fMaxX);
196
+ sMaxY = Math.max(cMaxY, fMaxY);
197
+ }
198
+ return {
199
+ cellSize,
200
+ padding,
201
+ selectedBounds: { minX: sMinX, minY: sMinY, maxX: sMaxX, maxY: sMaxY }
202
+ };
249
203
  }
250
204
 
251
- /**
252
- * Create an editor runtime adapter around an already mounted scene.
253
- * The adapter does not mutate the mounted scene or create editor UI.
254
- */
255
205
  function createEditorRuntimeAdapter(mounted) {
256
- const bundle = mounted.engine.bundle;
257
- if (!bundle) {
258
- throw new Error("EditorRuntimeAdapter requires an initialized mounted scene");
206
+ const bundle = mounted.engine.bundle;
207
+ if (!bundle) {
208
+ throw new Error("EditorRuntimeAdapter requires an initialized mounted scene");
209
+ }
210
+ const layerOrder = bundle.layers.map((layer) => ({ name: layer.name, order: layer.order })).sort((a, b) => a.order - b.order || a.name.localeCompare(b.name));
211
+ return {
212
+ mounted,
213
+ setActiveScene(sceneId) {
214
+ const scene = bundle.scenes.find((candidate) => candidate.id === sceneId);
215
+ if (!scene) return false;
216
+ this.setProgress(scene.progress);
217
+ return true;
218
+ },
219
+ setProgress(progress) {
220
+ if (mounted.controller) {
221
+ mounted.controller.setProgress(progress);
222
+ return;
223
+ }
224
+ mounted.engine.setProgress(progress);
225
+ applyEditorFrame(mounted);
226
+ },
227
+ getObjects(sceneId) {
228
+ const currentState = mounted.engine.getCurrentState();
229
+ if (!currentState || currentState.id !== sceneId) return [];
230
+ const result = [];
231
+ for (const update of mounted.engine.getFrameUpdates()) {
232
+ const bounds = getEditorElementBounds(mounted, update.id, update.asset);
233
+ result.push({
234
+ id: update.id,
235
+ kind: "element",
236
+ sceneId: currentState.id,
237
+ layer: update.layer,
238
+ present: update.lifecycle !== "removed",
239
+ bounds: bounds ?? { minX: 0, minY: 0, width: 0, height: 0 },
240
+ grid: { kind: "element", at: update.pos, size: update.size }
241
+ });
242
+ }
243
+ for (const update of mounted.engine.getConnectorFrameUpdates()) {
244
+ const bounds = getConnectionBounds(update.route, bundle);
245
+ result.push({
246
+ id: update.id,
247
+ kind: "connection",
248
+ sceneId: currentState.id,
249
+ layer: update.layer,
250
+ present: update.lifecycle !== "removed",
251
+ bounds,
252
+ grid: { kind: "connection", route: update.route }
253
+ });
254
+ }
255
+ return result;
256
+ },
257
+ getObject(id) {
258
+ const currentState = mounted.engine.getCurrentState();
259
+ if (!currentState) return void 0;
260
+ const elementUpdate = mounted.engine.getElementUpdate(id);
261
+ if (elementUpdate && elementUpdate.asset !== "") {
262
+ const bounds = getEditorElementBounds(mounted, id, elementUpdate.asset);
263
+ return {
264
+ id: elementUpdate.id,
265
+ kind: "element",
266
+ sceneId: currentState.id,
267
+ layer: elementUpdate.layer,
268
+ present: elementUpdate.lifecycle !== "removed",
269
+ bounds: bounds ?? { minX: 0, minY: 0, width: 0, height: 0 },
270
+ grid: { kind: "element", at: elementUpdate.pos, size: elementUpdate.size }
271
+ };
272
+ }
273
+ const connectorUpdate = mounted.engine.getConnectorUpdate(id);
274
+ if (connectorUpdate && connectorUpdate.route.length > 0) {
275
+ const bounds = getConnectionBounds(connectorUpdate.route, bundle);
276
+ return {
277
+ id: connectorUpdate.id,
278
+ kind: "connection",
279
+ sceneId: currentState.id,
280
+ layer: connectorUpdate.layer,
281
+ present: connectorUpdate.lifecycle !== "removed",
282
+ bounds,
283
+ grid: { kind: "connection", route: connectorUpdate.route }
284
+ };
285
+ }
286
+ return void 0;
287
+ },
288
+ getLayerOrder() {
289
+ return layerOrder.slice();
290
+ },
291
+ getResolvedViewBox() {
292
+ return getResolvedViewBox(bundle);
293
+ },
294
+ projectGridPoint(point) {
295
+ return projectGridPoint(bundle, point);
296
+ },
297
+ unprojectScreenPoint(point) {
298
+ return unprojectScreenPoint(bundle, point);
299
+ },
300
+ clientPointToSvgPoint(point) {
301
+ return clientPointToSvgPoint(mounted.svg, point);
302
+ },
303
+ getGridCellPolygon(cell) {
304
+ return getGridCellPolygon(bundle, cell);
305
+ },
306
+ getObjectAtPoint(point, options) {
307
+ return getRuntimeObjectAtPoint(this, point, options);
308
+ },
309
+ getSelectionBounds(ids) {
310
+ return getRuntimeSelectionBounds(this, ids);
311
+ },
312
+ destroy() {
313
+ }
314
+ };
315
+ }
316
+ function getEditorElementBounds(mounted, id, asset) {
317
+ if (asset === "text") {
318
+ const rect = getElementState(mounted.svg, id)?.node.getBoundingClientRect();
319
+ if (rect && rect.width > 0 && rect.height > 0) {
320
+ const topLeft = clientPointToSvgPoint(mounted.svg, { clientX: rect.left, clientY: rect.top });
321
+ const bottomRight = clientPointToSvgPoint(mounted.svg, { clientX: rect.right, clientY: rect.bottom });
322
+ return { minX: topLeft.x, minY: topLeft.y, width: bottomRight.x - topLeft.x, height: bottomRight.y - topLeft.y };
259
323
  }
260
- // Cache layer order since it is static for the bundle
261
- const layerOrder = bundle.layers
262
- .map((layer) => ({ name: layer.name, order: layer.order }))
263
- .sort((a, b) => a.order - b.order || a.name.localeCompare(b.name));
264
- return {
265
- mounted,
266
- setActiveScene(sceneId) {
267
- const scene = bundle.scenes.find((candidate) => candidate.id === sceneId);
268
- if (!scene)
269
- return false;
270
- this.setProgress(scene.progress);
271
- return true;
272
- },
273
- setProgress(progress) {
274
- mounted.engine.setProgress(progress);
275
- applyEditorFrame(mounted);
276
- },
277
- getObjects(sceneId) {
278
- const currentState = mounted.engine.getCurrentState();
279
- if (!currentState || currentState.id !== sceneId)
280
- return [];
281
- const result = [];
282
- // Elements from current engine frame
283
- for (const update of mounted.engine.getFrameUpdates()) {
284
- const bounds = getCurrentElementBounds(mounted.svg, update.id);
285
- result.push({
286
- id: update.id,
287
- kind: "element",
288
- sceneId: currentState.id,
289
- layer: update.layer,
290
- present: update.lifecycle !== "removed",
291
- bounds: bounds ?? { minX: 0, minY: 0, width: 0, height: 0 },
292
- grid: { kind: "element", at: update.pos, size: update.size },
293
- });
294
- }
295
- // Connections from current engine frame
296
- for (const update of mounted.engine.getConnectorFrameUpdates()) {
297
- const bounds = getConnectionBounds(update.route, bundle);
298
- result.push({
299
- id: update.id,
300
- kind: "connection",
301
- sceneId: currentState.id,
302
- layer: update.layer,
303
- present: update.lifecycle !== "removed",
304
- bounds,
305
- grid: { kind: "connection", route: update.route },
306
- });
307
- }
308
- return result;
309
- },
310
- getObject(id) {
311
- const currentState = mounted.engine.getCurrentState();
312
- if (!currentState)
313
- return undefined;
314
- const elementUpdate = mounted.engine.getElementUpdate(id);
315
- if (elementUpdate && elementUpdate.asset !== "") {
316
- const bounds = getCurrentElementBounds(mounted.svg, id);
317
- return {
318
- id: elementUpdate.id,
319
- kind: "element",
320
- sceneId: currentState.id,
321
- layer: elementUpdate.layer,
322
- present: elementUpdate.lifecycle !== "removed",
323
- bounds: bounds ?? { minX: 0, minY: 0, width: 0, height: 0 },
324
- grid: { kind: "element", at: elementUpdate.pos, size: elementUpdate.size },
325
- };
326
- }
327
- const connectorUpdate = mounted.engine.getConnectorUpdate(id);
328
- if (connectorUpdate && connectorUpdate.route.length > 0) {
329
- const bounds = getConnectionBounds(connectorUpdate.route, bundle);
330
- return {
331
- id: connectorUpdate.id,
332
- kind: "connection",
333
- sceneId: currentState.id,
334
- layer: connectorUpdate.layer,
335
- present: connectorUpdate.lifecycle !== "removed",
336
- bounds,
337
- grid: { kind: "connection", route: connectorUpdate.route },
338
- };
339
- }
340
- return undefined;
341
- },
342
- getLayerOrder() {
343
- return layerOrder.slice();
344
- },
345
- getResolvedViewBox() {
346
- return getResolvedViewBox(bundle);
347
- },
348
- projectGridPoint(point) {
349
- return projectGridPoint(bundle, point);
350
- },
351
- unprojectScreenPoint(point) {
352
- return unprojectScreenPoint(bundle, point);
353
- },
354
- clientPointToSvgPoint(point) {
355
- return clientPointToSvgPoint(mounted.svg, point);
356
- },
357
- getGridCellPolygon(cell) {
358
- return getGridCellPolygon(bundle, cell);
359
- },
360
- getObjectAtPoint(point, options) {
361
- return getRuntimeObjectAtPoint(this, point, options);
362
- },
363
- getSelectionBounds(ids) {
364
- return getRuntimeSelectionBounds(this, ids);
365
- },
366
- destroy() {
367
- // Adapter owns no listeners or caches that outlive this call.
368
- // The editor is responsible for mounted scene cleanup.
369
- },
370
- };
324
+ }
325
+ return getCurrentElementBounds(mounted.svg, id);
371
326
  }
372
327
  function applyEditorFrame(mounted) {
373
- const elements = mounted.engine.getFrameUpdates().map((update) => ({
374
- id: update.id,
375
- asset: update.asset,
376
- pos: update.pos,
377
- size: update.size,
378
- layer: update.layer,
379
- presence: update.lifecycle,
380
- enter: update.entry,
381
- exit: update.exit,
382
- ambient: update.ambient,
383
- text: update.text,
384
- primitive: update.primitive,
385
- }));
386
- const connectors = mounted.engine.getConnectorFrameUpdates().map((update) => ({
387
- id: update.id,
388
- route: update.route,
389
- layer: update.layer,
390
- presence: update.lifecycle,
391
- style: update.style,
392
- start: update.start,
393
- end: update.end,
394
- direction: update.direction,
395
- enter: update.entry,
396
- exit: update.exit,
397
- ambient: update.ambient,
398
- }));
399
- for (const element of elements) {
400
- const state = getElementState(mounted.svg, element.id);
401
- if (!state)
402
- continue;
403
- if (element.presence === "removed") {
404
- state.isHidden = true;
405
- hideElementAfterExit(state.node);
406
- }
407
- else {
408
- state.isHidden = false;
409
- unhideElementOnReadd(state.node);
410
- }
328
+ const elements = mounted.engine.getFrameUpdates().map((update) => ({
329
+ id: update.id,
330
+ asset: update.asset,
331
+ pos: update.pos,
332
+ size: update.size,
333
+ layer: update.layer,
334
+ presence: update.lifecycle,
335
+ enter: update.entry,
336
+ exit: update.exit,
337
+ ambient: update.ambient,
338
+ text: update.text,
339
+ primitive: update.primitive,
340
+ activity: update.activity
341
+ }));
342
+ const connectors = mounted.engine.getConnectorFrameUpdates().map((update) => ({
343
+ id: update.id,
344
+ route: update.route,
345
+ layer: update.layer,
346
+ presence: update.lifecycle,
347
+ style: update.style,
348
+ start: update.start,
349
+ end: update.end,
350
+ direction: update.direction,
351
+ enter: update.entry,
352
+ exit: update.exit,
353
+ ambient: update.ambient,
354
+ message: update.message
355
+ }));
356
+ for (const element of elements) {
357
+ const state = getElementState(mounted.svg, element.id);
358
+ if (!state) continue;
359
+ if (element.presence === "removed") {
360
+ state.isHidden = true;
361
+ hideElementAfterExit(state.node);
362
+ } else {
363
+ state.isHidden = false;
364
+ unhideElementOnReadd(state.node);
411
365
  }
412
- for (const connector of connectors) {
413
- const state = getConnectorState(mounted.svg, connector.id);
414
- if (!state)
415
- continue;
416
- if (connector.presence === "removed") {
417
- state.isHidden = true;
418
- hideElementAfterExit(state.node);
419
- }
420
- else {
421
- state.isHidden = false;
422
- unhideElementOnReadd(state.node);
423
- }
366
+ }
367
+ for (const connector of connectors) {
368
+ const state = getConnectorState(mounted.svg, connector.id);
369
+ if (!state) continue;
370
+ if (connector.presence === "removed") {
371
+ state.isHidden = true;
372
+ hideElementAfterExit(state.node);
373
+ } else {
374
+ state.isHidden = false;
375
+ unhideElementOnReadd(state.node);
424
376
  }
425
- updateElementTransforms(mounted.svg, elements, connectors);
377
+ }
378
+ updateElementTransforms(mounted.svg, elements, connectors);
426
379
  }
427
380
 
428
381
  export { clientPointToSvgPoint, createEditorRuntimeAdapter, getGridCellPolygon, getRuntimeObjectAtPoint, getRuntimeSelectionBounds, projectGridPoint, unprojectScreenPoint };