@energy8platform/game-engine 0.33.2 → 0.33.4

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.
@@ -0,0 +1,377 @@
1
+ 'use strict';
2
+
3
+ // Pure helpers behind the scene inspector — kept renderer/DOM-free so the control
4
+ // inference and layout-field enumeration are unit-testable and reusable (the same
5
+ // mapping later feeds schema-driven autogen and the agent's docs).
6
+ /** Infer an editor control for a props value (schema-less fallback). */
7
+ function propControlKind(value) {
8
+ switch (typeof value) {
9
+ case 'number':
10
+ return 'number';
11
+ case 'boolean':
12
+ return 'boolean';
13
+ case 'string':
14
+ return /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(value) ? 'color' : 'text';
15
+ default:
16
+ return 'json';
17
+ }
18
+ }
19
+ const FRACTION_KEYS = /frac|anchor|scale|sag|left$|top$|width$|height$/i;
20
+ function numberStep(path, value) {
21
+ if (/rotation/i.test(path))
22
+ return 0.01;
23
+ if (FRACTION_KEYS.test(path) && Math.abs(value) <= 4)
24
+ return 0.01;
25
+ return 1;
26
+ }
27
+ /** Flatten a layout rule into editable field specs (mode itself is structural → readonly). */
28
+ function layoutFieldSpecs(rule) {
29
+ const out = [];
30
+ const visit = (value, path, label) => {
31
+ if (typeof value === 'number') {
32
+ out.push({ path, label, kind: 'number', value, step: numberStep(path, value) });
33
+ }
34
+ else if (typeof value === 'string') {
35
+ out.push(path === 'mode' ? { path, label, kind: 'readonly', value } : { path, label, kind: 'text', value });
36
+ }
37
+ else if (typeof value === 'boolean') {
38
+ out.push({ path, label, kind: 'text', value: String(value) });
39
+ }
40
+ else if (Array.isArray(value)) {
41
+ value.forEach((item, i) => visit(item, `${path}.${i}`, `${label}[${i}]`));
42
+ }
43
+ else if (value && typeof value === 'object') {
44
+ for (const [k, v] of Object.entries(value))
45
+ visit(v, `${path}.${k}`, `${label}.${k}`);
46
+ }
47
+ };
48
+ for (const [key, value] of Object.entries(rule))
49
+ visit(value, key, key);
50
+ return out;
51
+ }
52
+ /** Immutable set of a dot-path inside a (JSON-ish) rule object. */
53
+ function setRulePath(rule, path, value) {
54
+ const clone = JSON.parse(JSON.stringify(rule));
55
+ const parts = path.split('.');
56
+ let cursor = clone;
57
+ for (let i = 0; i < parts.length - 1; i++) {
58
+ const key = parts[i];
59
+ const next = Array.isArray(cursor) ? cursor[Number(key)] : cursor[key];
60
+ if (typeof next !== 'object' || next === null) {
61
+ const fresh = {};
62
+ if (Array.isArray(cursor))
63
+ cursor[Number(key)] = fresh;
64
+ else
65
+ cursor[key] = fresh;
66
+ cursor = fresh;
67
+ }
68
+ else {
69
+ cursor = next;
70
+ }
71
+ }
72
+ const last = parts[parts.length - 1];
73
+ if (Array.isArray(cursor))
74
+ cursor[Number(last)] = value;
75
+ else
76
+ cursor[last] = value;
77
+ return clone;
78
+ }
79
+
80
+ // Scene outliner + inspector — the human lens over the same SceneHandle surface the
81
+ // agent drives (tree/patch/setState). Framework-free DOM, dev-only: hosts (scene-lab,
82
+ // a game's preview page, later a harness panel) mount it into any container element.
83
+ // Every edit leaves through a ScenePatch, so a mouse edit and an agent edit are the
84
+ // same operation on the same doc.
85
+ const STYLE = `
86
+ .e8si { font: 12px/1.45 system-ui, sans-serif; color: #dfe6f5; display: flex; flex-direction: column; height: 100%; min-height: 0; }
87
+ .e8si h3 { margin: 0; padding: 8px 10px 6px; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; color: #7d8ab0; }
88
+ .e8si-tree { overflow: auto; max-height: 42%; border-bottom: 1px solid #1c2540; padding-bottom: 6px; }
89
+ .e8si-row { display: flex; gap: 6px; align-items: baseline; padding: 2px 10px; cursor: pointer; white-space: nowrap; }
90
+ .e8si-row:hover { background: #141c36; }
91
+ .e8si-row.sel { background: #1d2b55; }
92
+ .e8si-row .t { color: #7d8ab0; }
93
+ .e8si-row .dim { opacity: 0.45; }
94
+ .e8si-insp { overflow: auto; flex: 1; padding: 4px 0 12px; }
95
+ .e8si-head { padding: 6px 10px; }
96
+ .e8si-head .id { font-weight: 700; font-size: 13px; }
97
+ .e8si-head .meta { color: #7d8ab0; }
98
+ .e8si-sec { margin-top: 6px; }
99
+ .e8si-field { display: flex; align-items: center; gap: 6px; padding: 2px 10px; }
100
+ .e8si-field label { flex: 0 0 96px; color: #9fb0d8; overflow: hidden; text-overflow: ellipsis; }
101
+ .e8si-field input[type=number], .e8si-field input[type=text], .e8si-field select, .e8si-field textarea {
102
+ flex: 1; min-width: 0; background: #0d1428; color: #dfe6f5; border: 1px solid #2b3866; border-radius: 6px; padding: 3px 6px; font: inherit; }
103
+ .e8si-field input[type=color] { width: 34px; height: 24px; padding: 0; border: 1px solid #2b3866; border-radius: 6px; background: none; }
104
+ .e8si-field .ro { color: #8fa0c9; }
105
+ .e8si-json { display: block; width: calc(100% - 20px); margin: 2px 10px; min-height: 52px; font: 11px/1.4 ui-monospace, monospace; }
106
+ .e8si-apply { margin: 4px 10px; padding: 3px 10px; background: #18213d; color: #dfe6f5; border: 1px solid #2b3866; border-radius: 6px; cursor: pointer; }
107
+ .e8si-empty { padding: 10px; color: #7d8ab0; }
108
+ .e8si-badge { display: inline-block; padding: 0 6px; border: 1px solid #2b3866; border-radius: 8px; color: #9fb0d8; font-size: 10px; }
109
+ `;
110
+ function createSceneInspector(opts) {
111
+ const { handle, container } = opts;
112
+ const applyPatch = opts.applyPatch ?? handle.patch;
113
+ const getOrientation = opts.getOrientation ?? (() => 'landscape');
114
+ const root = document.createElement('div');
115
+ root.className = 'e8si';
116
+ const style = document.createElement('style');
117
+ style.textContent = STYLE;
118
+ root.appendChild(style);
119
+ const treeHost = document.createElement('div');
120
+ treeHost.className = 'e8si-tree';
121
+ const inspHost = document.createElement('div');
122
+ inspHost.className = 'e8si-insp';
123
+ root.append(treeHost, inspHost);
124
+ container.appendChild(root);
125
+ let selectedId = null;
126
+ // Edits from our own inputs schedule a refresh that must not rebuild the form under
127
+ // the user's cursor — only the outliner refreshes then.
128
+ let ownEdit = false;
129
+ const findNode = (id) => {
130
+ const walk = (n) => n.id === id ? n : n.children.map(walk).find(Boolean);
131
+ return walk(handle.tree());
132
+ };
133
+ const docNode = (id) => {
134
+ const walk = (n) => {
135
+ if (n.id === id)
136
+ return n;
137
+ for (const child of n.children ?? []) {
138
+ const hit = walk(child);
139
+ if (hit)
140
+ return hit;
141
+ }
142
+ return undefined;
143
+ };
144
+ return walk(handle.doc().root);
145
+ };
146
+ const patchAndRefresh = (patch) => {
147
+ ownEdit = true;
148
+ applyPatch(patch);
149
+ ownEdit = false;
150
+ renderTree();
151
+ };
152
+ // ── Outliner ────────────────────────────────────────────────────────────────
153
+ const renderTree = () => {
154
+ treeHost.textContent = '';
155
+ const title = document.createElement('h3');
156
+ title.textContent = 'Scene';
157
+ treeHost.appendChild(title);
158
+ const renderRow = (node, depth) => {
159
+ const row = document.createElement('div');
160
+ row.className = `e8si-row${node.id === selectedId ? ' sel' : ''}${node.visible ? '' : ' dim'}`;
161
+ row.style.paddingLeft = `${10 + depth * 12}px`;
162
+ const id = document.createElement('span');
163
+ id.textContent = node.id;
164
+ const type = document.createElement('span');
165
+ type.className = 't';
166
+ type.textContent = node.name ? `${node.type} · ${node.name}` : node.type;
167
+ row.append(id, type);
168
+ if (node.state) {
169
+ const badge = document.createElement('span');
170
+ badge.className = 'e8si-badge';
171
+ badge.textContent = node.state;
172
+ row.appendChild(badge);
173
+ }
174
+ row.addEventListener('click', () => {
175
+ select(node.id);
176
+ opts.onSelect?.(node.id);
177
+ });
178
+ treeHost.appendChild(row);
179
+ node.children.forEach((child) => renderRow(child, depth + 1));
180
+ };
181
+ renderRow(handle.tree(), 0);
182
+ };
183
+ // ── Inspector form ─────────────────────────────────────────────────────────
184
+ const field = (labelText) => {
185
+ const wrap = document.createElement('div');
186
+ wrap.className = 'e8si-field';
187
+ const label = document.createElement('label');
188
+ label.textContent = labelText;
189
+ label.title = labelText;
190
+ wrap.appendChild(label);
191
+ return wrap;
192
+ };
193
+ const renderInspector = () => {
194
+ inspHost.textContent = '';
195
+ if (!selectedId) {
196
+ const empty = document.createElement('div');
197
+ empty.className = 'e8si-empty';
198
+ empty.textContent = 'Select a node (canvas or tree) to edit its layout & props.';
199
+ inspHost.appendChild(empty);
200
+ return;
201
+ }
202
+ const id = selectedId;
203
+ const node = docNode(id);
204
+ const outline = findNode(id);
205
+ if (!node || !outline)
206
+ return;
207
+ const head = document.createElement('div');
208
+ head.className = 'e8si-head';
209
+ head.innerHTML = '';
210
+ const idEl = document.createElement('div');
211
+ idEl.className = 'id';
212
+ idEl.textContent = `#${node.id}`;
213
+ const meta = document.createElement('div');
214
+ meta.className = 'meta';
215
+ meta.textContent = `${node.type}${node.name ? ` · ${node.name}` : ''}${node.anchorName ? ` · @${node.anchorName}` : ''}${node.visibleWhen ? ` · when: ${node.visibleWhen}` : ''}`;
216
+ head.append(idEl, meta);
217
+ inspHost.appendChild(head);
218
+ // State selector (named prop variants).
219
+ const stateNames = Object.keys(node.states ?? {});
220
+ if (stateNames.length > 0) {
221
+ const wrap = field('state');
222
+ const select = document.createElement('select');
223
+ for (const name of ['—', ...stateNames]) {
224
+ const option = document.createElement('option');
225
+ option.value = name;
226
+ option.textContent = name;
227
+ select.appendChild(option);
228
+ }
229
+ select.value = outline.state ?? '—';
230
+ select.addEventListener('change', () => {
231
+ patchAndRefresh({ op: 'set-state', id, state: select.value === '—' ? null : select.value });
232
+ });
233
+ wrap.appendChild(select);
234
+ inspHost.appendChild(wrap);
235
+ }
236
+ // Layout — the EFFECTIVE rule for the current orientation, edited in place.
237
+ const orientation = getOrientation();
238
+ const override = node.responsive?.[orientation]?.layout;
239
+ const rule = override ?? node.layout;
240
+ const layoutTitle = document.createElement('h3');
241
+ layoutTitle.textContent = `Layout (${orientation}${override ? ' override' : ''})`;
242
+ layoutTitle.className = 'e8si-sec';
243
+ inspHost.appendChild(layoutTitle);
244
+ if (!rule) {
245
+ const none = document.createElement('div');
246
+ none.className = 'e8si-empty';
247
+ none.textContent = '(no rule — parent-relative identity)';
248
+ inspHost.appendChild(none);
249
+ }
250
+ else {
251
+ for (const spec of layoutFieldSpecs(rule)) {
252
+ const wrap = field(spec.label);
253
+ if (spec.kind === 'readonly') {
254
+ const span = document.createElement('span');
255
+ span.className = 'ro';
256
+ span.textContent = String(spec.value);
257
+ wrap.appendChild(span);
258
+ }
259
+ else {
260
+ const input = document.createElement('input');
261
+ input.type = spec.kind === 'number' ? 'number' : 'text';
262
+ if (spec.step !== undefined)
263
+ input.step = String(spec.step);
264
+ input.value = String(spec.value);
265
+ input.addEventListener('change', () => {
266
+ const raw = spec.kind === 'number' ? Number(input.value) : input.value;
267
+ if (spec.kind === 'number' && !Number.isFinite(raw))
268
+ return;
269
+ patchAndRefresh({
270
+ op: 'set-layout',
271
+ id,
272
+ layout: setRulePath(rule, spec.path, raw),
273
+ orientation: override ? orientation : undefined,
274
+ });
275
+ });
276
+ wrap.appendChild(input);
277
+ }
278
+ inspHost.appendChild(wrap);
279
+ }
280
+ }
281
+ // Props — base props, schema-less control inference.
282
+ const props = node.props ?? {};
283
+ const propKeys = Object.keys(props);
284
+ if (propKeys.length > 0) {
285
+ const propsTitle = document.createElement('h3');
286
+ propsTitle.textContent = 'Props';
287
+ propsTitle.className = 'e8si-sec';
288
+ inspHost.appendChild(propsTitle);
289
+ for (const key of propKeys) {
290
+ const value = props[key];
291
+ const kind = propControlKind(value);
292
+ if (kind === 'json') {
293
+ const wrap = field(key);
294
+ inspHost.appendChild(wrap);
295
+ const area = document.createElement('textarea');
296
+ area.className = 'e8si-json';
297
+ area.value = JSON.stringify(value, null, 1);
298
+ const apply = document.createElement('button');
299
+ apply.className = 'e8si-apply';
300
+ apply.textContent = `apply ${key}`;
301
+ apply.addEventListener('click', () => {
302
+ try {
303
+ patchAndRefresh({ op: 'set-props', id, props: { [key]: JSON.parse(area.value) } });
304
+ }
305
+ catch {
306
+ apply.textContent = `apply ${key} — invalid JSON`;
307
+ }
308
+ });
309
+ inspHost.append(area, apply);
310
+ continue;
311
+ }
312
+ const wrap = field(key);
313
+ if (kind === 'boolean') {
314
+ const input = document.createElement('input');
315
+ input.type = 'checkbox';
316
+ input.checked = value === true;
317
+ input.addEventListener('change', () => patchAndRefresh({ op: 'set-props', id, props: { [key]: input.checked } }));
318
+ wrap.appendChild(input);
319
+ }
320
+ else if (kind === 'color') {
321
+ const color = document.createElement('input');
322
+ color.type = 'color';
323
+ color.value = String(value).slice(0, 7);
324
+ const text = document.createElement('input');
325
+ text.type = 'text';
326
+ text.value = String(value);
327
+ const push = (v) => patchAndRefresh({ op: 'set-props', id, props: { [key]: v } });
328
+ color.addEventListener('input', () => {
329
+ text.value = color.value;
330
+ push(color.value);
331
+ });
332
+ text.addEventListener('change', () => push(text.value));
333
+ wrap.append(color, text);
334
+ }
335
+ else {
336
+ const input = document.createElement('input');
337
+ input.type = kind === 'number' ? 'number' : 'text';
338
+ input.value = String(value);
339
+ input.addEventListener('change', () => {
340
+ const raw = kind === 'number' ? Number(input.value) : input.value;
341
+ if (kind === 'number' && !Number.isFinite(raw))
342
+ return;
343
+ patchAndRefresh({ op: 'set-props', id, props: { [key]: raw } });
344
+ });
345
+ wrap.appendChild(input);
346
+ }
347
+ inspHost.appendChild(wrap);
348
+ }
349
+ }
350
+ };
351
+ const select = (id) => {
352
+ selectedId = id;
353
+ renderTree();
354
+ renderInspector();
355
+ };
356
+ renderTree();
357
+ renderInspector();
358
+ return {
359
+ select,
360
+ selected: () => selectedId,
361
+ refresh() {
362
+ renderTree();
363
+ // Keep the form stable while the user is typing into it after their own edit.
364
+ if (!ownEdit && !inspHost.contains(document.activeElement))
365
+ renderInspector();
366
+ },
367
+ destroy() {
368
+ root.remove();
369
+ },
370
+ };
371
+ }
372
+
373
+ exports.createSceneInspector = createSceneInspector;
374
+ exports.layoutFieldSpecs = layoutFieldSpecs;
375
+ exports.propControlKind = propControlKind;
376
+ exports.setRulePath = setRulePath;
377
+ //# sourceMappingURL=scene-devtools.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-devtools.cjs.js","sources":["../src/scene/devtools/helpers.ts","../src/scene/devtools/inspector.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
@@ -0,0 +1,239 @@
1
+ import { Container } from 'pixi.js';
2
+
3
+ type Orientation = 'landscape' | 'portrait';
4
+ interface SceneDoc {
5
+ version: 1;
6
+ /** Stable document id (usually the game id). */
7
+ id: string;
8
+ /** Design space the layout rules are authored in (viewport arrives in these units). */
9
+ design: {
10
+ width: number;
11
+ height: number;
12
+ };
13
+ root: SceneNode;
14
+ }
15
+ interface SceneNode {
16
+ /** Stable id — flow, code and patches address the node by it. Unique per doc. */
17
+ id: string;
18
+ /** Node kind resolved through the registry (built-in or plugin-contributed). */
19
+ type: string;
20
+ /** Human label for the outliner; never used for addressing. */
21
+ name?: string;
22
+ /** Kind-specific properties (validated by the contribution's schema). */
23
+ props?: Record<string, unknown>;
24
+ layout?: LayoutRule;
25
+ /** Per-orientation override merged over the base node before layout. */
26
+ responsive?: Partial<Record<Orientation, NodeOverride>>;
27
+ /**
28
+ * Named variants toggled at runtime (flow `setState`, editor, code) — e.g. a reel
29
+ * frame's `anticipation` / `bonus` looks. A state is an override, not a new node.
30
+ */
31
+ states?: Record<string, NodeOverride>;
32
+ /** Id of another node in this doc used as this node's mask. */
33
+ mask?: string;
34
+ /**
35
+ * Tiny condition over runtime vars, e.g. `"mode === 'free_spins'"`. Supported form:
36
+ * `<var> <op> <literal>` with `=== !== >= <= > <`. Anything richer belongs in flow/code.
37
+ */
38
+ visibleWhen?: string;
39
+ /** Entry in the shared anchor vocabulary flow/animation use to address the node. */
40
+ anchorName?: string;
41
+ /** Order = z-order. */
42
+ children?: SceneNode[];
43
+ }
44
+ /** Partial node applied on top of the base for an orientation or a named state. */
45
+ interface NodeOverride {
46
+ layout?: LayoutRule;
47
+ props?: Record<string, unknown>;
48
+ visible?: boolean;
49
+ }
50
+ interface LayoutCommon {
51
+ /** Content anchor [ax, ay] in 0..1 (applied via pivot on the node's natural size). */
52
+ anchor?: [number, number];
53
+ /** Final hand-tuned nudge in design px, applied after the rule resolves. */
54
+ pxNudge?: {
55
+ x?: number;
56
+ y?: number;
57
+ };
58
+ /** Static rotation in radians (choreographed rotation belongs to flow/animation). */
59
+ rotation?: number;
60
+ }
61
+ /** Fixed design-space coordinates. */
62
+ interface AbsoluteLayout extends LayoutCommon {
63
+ mode: 'absolute';
64
+ x: number;
65
+ y: number;
66
+ scale?: number;
67
+ rotation?: number;
68
+ }
69
+ /**
70
+ * Position as a fraction of the live viewport. Sizing, strongest first:
71
+ * `widthFrac`/`heightFrac` size the node to that fraction of the viewport (contain when
72
+ * both are given) — the "frame is 92% of the screen in portrait" idiom; otherwise
73
+ * `scaleWith` multiplies `scale` by the viewport/design ratio; otherwise plain `scale`.
74
+ */
75
+ interface ViewportFractionLayout extends LayoutCommon {
76
+ mode: 'viewport-fraction';
77
+ xFrac: number;
78
+ yFrac: number;
79
+ scale?: number;
80
+ /** Multiply `scale` by viewport/design ratio: width | height | min | max. */
81
+ scaleWith?: 'width' | 'height' | 'min' | 'max';
82
+ /** Size the node to this fraction of the viewport width (scale derived from natural size). */
83
+ widthFrac?: number;
84
+ /** Size the node to this fraction of the viewport height. */
85
+ heightFrac?: number;
86
+ /** With both fracs: contain (default) keeps aspect, stretch distorts to fill exactly. */
87
+ fit?: 'contain' | 'stretch';
88
+ }
89
+ /**
90
+ * Center-crop fill of the current space (backgrounds, diorama layers). `scale` multiplies
91
+ * the computed cover scale (the paper-duel `e` idiom); `pxNudge` offsets from center.
92
+ */
93
+ interface CoverLayout extends LayoutCommon {
94
+ mode: 'cover';
95
+ scale?: number;
96
+ }
97
+ /**
98
+ * Place inside another node's laid-out rect using fractions of that rect.
99
+ * `use: 'inner'` reads the target's declared `props.inner` fractions (reel frames
100
+ * declare where their hollow is) instead of spelling the fractions twice.
101
+ * When a box (`wFrac`/`hFrac` or `use`) is given the node is contain-fitted into it
102
+ * (`fit: 'stretch'` distorts instead).
103
+ */
104
+ interface FrameFractionLayout extends LayoutCommon {
105
+ mode: 'frame-fraction';
106
+ frame: string;
107
+ xFrac?: number;
108
+ yFrac?: number;
109
+ wFrac?: number;
110
+ hFrac?: number;
111
+ use?: 'inner';
112
+ fit?: 'contain' | 'stretch';
113
+ }
114
+ /**
115
+ * Center of a reel-grid cell (badges, per-cell VFX slots). `grid` defaults to the sole
116
+ * reelGrid. By default the node scales with the grid (sizes authored in grid-design px);
117
+ * `scaleWithGrid: false` keeps it in absolute design units.
118
+ */
119
+ interface GridCellLayout extends LayoutCommon {
120
+ mode: 'grid-cell';
121
+ grid?: string;
122
+ col: number;
123
+ row: number;
124
+ scale?: number;
125
+ scaleWithGrid?: boolean;
126
+ }
127
+ /** Pin to an edge/center of another node's laid-out rect. */
128
+ interface PinLayout extends LayoutCommon {
129
+ mode: 'pin';
130
+ to: string;
131
+ edge: PinEdge;
132
+ offset?: [number, number];
133
+ scale?: number;
134
+ }
135
+ type PinEdge = 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
136
+ type LayoutRule = AbsoluteLayout | ViewportFractionLayout | CoverLayout | FrameFractionLayout | GridCellLayout | PinLayout;
137
+ type ScenePatch = {
138
+ op: 'set-props';
139
+ id: string;
140
+ props: Record<string, unknown>;
141
+ }
142
+ /** Without `orientation` replaces the base rule; with it, that orientation's override. */
143
+ | {
144
+ op: 'set-layout';
145
+ id: string;
146
+ layout: LayoutRule;
147
+ orientation?: Orientation;
148
+ } | {
149
+ op: 'set-state';
150
+ id: string;
151
+ state: string | null;
152
+ } | {
153
+ op: 'set-var';
154
+ name: string;
155
+ value: unknown;
156
+ };
157
+ /** Outliner row — the tree the inspector and the agent both read. */
158
+ interface OutlineNode {
159
+ id: string;
160
+ type: string;
161
+ name?: string;
162
+ anchorName?: string;
163
+ visible: boolean;
164
+ state: string | null;
165
+ children: OutlineNode[];
166
+ }
167
+
168
+ interface Size {
169
+ width: number;
170
+ height: number;
171
+ }
172
+
173
+ /** Live counterpart of one scene node, produced by its contribution. */
174
+ interface NodeInstance {
175
+ view: Container;
176
+ /** Natural (unscaled) content size — drives anchor, cover and box fitting. */
177
+ measure(): Size;
178
+ /** Apply a props patch in place; absent → the engine rebuilds the node instead. */
179
+ applyProps?(props: Record<string, unknown>): void;
180
+ /** Scene-local center of a grid cell (reel-grid kinds only; enables `grid-cell` layout). */
181
+ gridCell?(col: number, row: number): {
182
+ x: number;
183
+ y: number;
184
+ };
185
+ destroy?(): void;
186
+ }
187
+
188
+ interface SceneHandle {
189
+ view: Container;
190
+ node(id: string): Container | undefined;
191
+ instance(id: string): NodeInstance | undefined;
192
+ anchor(name: string): Container | undefined;
193
+ tree(): OutlineNode;
194
+ layout(width: number, height: number): void;
195
+ setVar(name: string, value: unknown): void;
196
+ setState(id: string, state: string | null): void;
197
+ patch(patch: ScenePatch): void;
198
+ /** The live doc (mutated by patches) — serialize this to persist the scene. */
199
+ doc(): SceneDoc;
200
+ destroy(): void;
201
+ }
202
+
203
+ interface SceneInspectorOptions {
204
+ handle: SceneHandle;
205
+ container: HTMLElement;
206
+ /** Route for edits (host may add logging/saving); defaults to handle.patch. */
207
+ applyPatch?: (patch: ScenePatch) => void;
208
+ /** Current orientation — decides which effective layout rule is shown/edited. */
209
+ getOrientation?: () => Orientation;
210
+ /** Selection made in the panel (host mirrors it on the canvas). */
211
+ onSelect?: (id: string | null) => void;
212
+ }
213
+ interface SceneInspector {
214
+ select(id: string | null): void;
215
+ selected(): string | null;
216
+ refresh(): void;
217
+ destroy(): void;
218
+ }
219
+ declare function createSceneInspector(opts: SceneInspectorOptions): SceneInspector;
220
+
221
+ type PropControlKind = 'number' | 'text' | 'boolean' | 'color' | 'json';
222
+ /** Infer an editor control for a props value (schema-less fallback). */
223
+ declare function propControlKind(value: unknown): PropControlKind;
224
+ interface LayoutFieldSpec {
225
+ /** Dot-path inside the rule ('x', 'pxNudge.x', 'anchor.0', 'offset.1'). */
226
+ path: string;
227
+ label: string;
228
+ kind: 'number' | 'text' | 'readonly';
229
+ value: number | string;
230
+ /** Input step — fractions and anchors get fine steps, px fields get 1. */
231
+ step?: number;
232
+ }
233
+ /** Flatten a layout rule into editable field specs (mode itself is structural → readonly). */
234
+ declare function layoutFieldSpecs(rule: LayoutRule): LayoutFieldSpec[];
235
+ /** Immutable set of a dot-path inside a (JSON-ish) rule object. */
236
+ declare function setRulePath(rule: LayoutRule, path: string, value: unknown): LayoutRule;
237
+
238
+ export { createSceneInspector, layoutFieldSpecs, propControlKind, setRulePath };
239
+ export type { LayoutFieldSpec, PropControlKind, SceneInspector, SceneInspectorOptions };