@mmapp/react 0.1.0-alpha.18 → 0.1.0-alpha.20

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 (55) hide show
  1. package/dist/actions-HOXZPBTT.mjs +116 -0
  2. package/dist/actions-MFI2V4DX.mjs +116 -0
  3. package/dist/atoms/index.d.mts +2 -2
  4. package/dist/atoms/index.d.ts +2 -2
  5. package/dist/atoms/index.js +1 -1
  6. package/dist/atoms/index.mjs +1 -1
  7. package/dist/builtin-atoms-C-sNyYJl.d.mts +647 -0
  8. package/dist/builtin-atoms-C-sNyYJl.d.ts +647 -0
  9. package/dist/builtin-atoms-DCKrjG7i.d.mts +96 -0
  10. package/dist/builtin-atoms-DCKrjG7i.d.ts +96 -0
  11. package/dist/builtin-atoms-DRD3EwG6.d.mts +648 -0
  12. package/dist/builtin-atoms-DRD3EwG6.d.ts +648 -0
  13. package/dist/builtin-atoms-jt04b7Rw.d.mts +643 -0
  14. package/dist/builtin-atoms-jt04b7Rw.d.ts +643 -0
  15. package/dist/chunk-247T4GDJ.mjs +677 -0
  16. package/dist/chunk-3H6CR7E7.mjs +1924 -0
  17. package/dist/chunk-3PL6FL6I.mjs +96 -0
  18. package/dist/chunk-3SJSW3C4.mjs +2039 -0
  19. package/dist/chunk-5OI2VI57.mjs +1964 -0
  20. package/dist/chunk-CL6FYZ43.mjs +105 -0
  21. package/dist/chunk-ENQOCZI5.mjs +1938 -0
  22. package/dist/chunk-FB3WCZAU.mjs +512 -0
  23. package/dist/chunk-FBKUGKQI.mjs +1938 -0
  24. package/dist/chunk-GLJ7VC7Z.mjs +684 -0
  25. package/dist/chunk-HHMWR6NA.mjs +504 -0
  26. package/dist/chunk-HULEMSN2.mjs +120 -0
  27. package/dist/chunk-J5MW6CRU.mjs +1938 -0
  28. package/dist/chunk-PNTTKNYU.mjs +677 -0
  29. package/dist/chunk-TY5OTJP4.mjs +684 -0
  30. package/dist/chunk-WV7DVCP6.mjs +513 -0
  31. package/dist/chunk-YFMPTGUF.mjs +677 -0
  32. package/dist/chunk-ZAHMWAER.mjs +1960 -0
  33. package/dist/{chunk-2VJQJM7S.mjs → chunk-ZDWACXZN.mjs} +1 -1
  34. package/dist/composition-BJ6QQTWT.mjs +12 -0
  35. package/dist/composition-XBGKKCI7.mjs +57 -0
  36. package/dist/content-QVPFUG4P.mjs +246 -0
  37. package/dist/control-flow-CBREHWJW.mjs +35 -0
  38. package/dist/control-flow-FWBOI6SM.mjs +35 -0
  39. package/dist/control-flow-ZWUGCDSP.mjs +35 -0
  40. package/dist/data-WCMIZYKD.mjs +97 -0
  41. package/dist/grouping-E6F377VZ.mjs +204 -0
  42. package/dist/grouping-FRPOEXO3.mjs +233 -0
  43. package/dist/index.d.mts +4 -433
  44. package/dist/index.d.ts +4 -433
  45. package/dist/index.js +3671 -582
  46. package/dist/index.mjs +335 -1040
  47. package/dist/input-PUOZDNSI.mjs +222 -0
  48. package/dist/layout-RATDMCLP.mjs +106 -0
  49. package/dist/navigation-VCT7ZBMA.mjs +15 -0
  50. package/dist/navigation-WFV7YWOU.mjs +14 -0
  51. package/dist/player/index.d.mts +37 -11
  52. package/dist/player/index.d.ts +37 -11
  53. package/dist/player/index.js +3321 -193
  54. package/dist/player/index.mjs +55 -5
  55. package/package.json +4 -4
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -15,73 +18,3052 @@ var __copyProps = (to, from, except, desc) => {
15
18
  if (!__hasOwnProp.call(to, key) && key !== except)
16
19
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
20
  }
18
- return to;
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/player/expression-engine.ts
34
+ function setWasmModule(module2) {
35
+ _wasmModule = module2;
36
+ _wasmAvailable = module2 != null;
37
+ }
38
+ function classifyExpression(expr) {
39
+ const cached = classificationCache.get(expr);
40
+ if (cached) return cached;
41
+ const cls = classifyUncached(expr);
42
+ classificationCache.set(expr, cls);
43
+ return cls;
44
+ }
45
+ function classifyUncached(expr) {
46
+ const t = expr.trim();
47
+ if (t === "[Expression]" || t.includes("[Expression]")) return "literal";
48
+ if (t.startsWith("$expr(") && t.endsWith(")")) return "condition";
49
+ if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'")) return "literal";
50
+ if (/^-?\d+(\.\d+)?$/.test(t)) return "literal";
51
+ if (t === "true" || t === "false" || t === "null" || t === "undefined") return "literal";
52
+ if (t === "[]" || t === "{}") return "literal";
53
+ if (/^\$fn\.\w+\(/.test(t)) return "function";
54
+ if (/^\$action\.\w+\(/.test(t)) return "action";
55
+ if (t.startsWith("$action.") && !t.includes("(")) return "action";
56
+ if (t.startsWith("$") && !/[!=<>&|+\-*/%?:]/.test(t) && !t.includes("(")) return "path";
57
+ if (/^[a-zA-Z_]\w*(\.\w+)+$/.test(t) && !/[!=<>&|+\-*/%?:]/.test(t)) return "path";
58
+ if (/^[a-zA-Z_]\w*$/.test(t)) return "path";
59
+ return "condition";
60
+ }
61
+ function resolvePath(path, scope) {
62
+ const parts = path.split(".");
63
+ let current = scope;
64
+ for (const part of parts) {
65
+ if (current == null) return void 0;
66
+ if (typeof current !== "object") return void 0;
67
+ const asNum = Number(part);
68
+ if (Array.isArray(current) && !isNaN(asNum)) {
69
+ current = current[asNum];
70
+ } else {
71
+ current = current[part];
72
+ }
73
+ }
74
+ return current;
75
+ }
76
+ function validateExpression(expr) {
77
+ for (const pat of FORBIDDEN_PATTERNS) {
78
+ if (pat.test(expr)) {
79
+ return { valid: false, error: `Forbidden pattern: ${pat.source}` };
80
+ }
81
+ }
82
+ const depth = (expr.match(/\(/g) || []).length;
83
+ if (depth > 15) return { valid: false, error: "Expression too deeply nested" };
84
+ return { valid: true };
85
+ }
86
+ function compileToFunction(expr, paramNames) {
87
+ const cached = compiledCache.get(expr);
88
+ if (cached) return cached;
89
+ const validation = validateExpression(expr);
90
+ if (!validation.valid) {
91
+ console.warn(`[expression-engine] Unsafe expression blocked: ${validation.error} in "${expr}"`);
92
+ return null;
93
+ }
94
+ try {
95
+ const fn = new Function(...paramNames, `"use strict"; try { return (${expr}); } catch(e) { return undefined; }`);
96
+ compiledCache.set(expr, fn);
97
+ return fn;
98
+ } catch {
99
+ try {
100
+ const fn = new Function(...paramNames, `"use strict"; try { ${expr} } catch(e) { return undefined; }`);
101
+ compiledCache.set(expr, fn);
102
+ return fn;
103
+ } catch {
104
+ return null;
105
+ }
106
+ }
107
+ }
108
+ function evaluateExpression(expr, context) {
109
+ const trimmed = expr.trim();
110
+ if (!trimmed) return void 0;
111
+ const cls = classifyExpression(trimmed);
112
+ if (cls === "literal") return parseLiteral(trimmed);
113
+ if (cls === "path") return resolveScopePath(trimmed, context);
114
+ let evalExpr = trimmed;
115
+ if (evalExpr.startsWith("$expr(") && evalExpr.endsWith(")")) {
116
+ evalExpr = evalExpr.slice(6, -1);
117
+ }
118
+ if (_wasmAvailable && _wasmModule) {
119
+ try {
120
+ const translated = translateForWasm(evalExpr);
121
+ const contextJson = JSON.stringify(buildWasmContext(context));
122
+ const resultJson = _wasmModule.evaluateExpressionSync(translated, contextJson);
123
+ return JSON.parse(resultJson);
124
+ } catch {
125
+ }
126
+ }
127
+ return evaluateWithJS(evalExpr, context);
128
+ }
129
+ function parseLiteral(expr) {
130
+ if (expr.startsWith('"') && expr.endsWith('"') || expr.startsWith("'") && expr.endsWith("'")) {
131
+ return expr.slice(1, -1);
132
+ }
133
+ if (/^-?\d+(\.\d+)?$/.test(expr)) return Number(expr);
134
+ if (expr === "true") return true;
135
+ if (expr === "false") return false;
136
+ if (expr === "null") return null;
137
+ if (expr === "undefined") return void 0;
138
+ if (expr === "[]") return [];
139
+ if (expr === "{}") return {};
140
+ if (expr === "[Expression]") return void 0;
141
+ return void 0;
142
+ }
143
+ function resolveScopePath(expr, context) {
144
+ const trimmed = expr.trim();
145
+ if (trimmed.startsWith("$")) {
146
+ const dotIdx = trimmed.indexOf(".");
147
+ if (dotIdx === -1) {
148
+ return context[trimmed];
149
+ }
150
+ const root = trimmed.slice(0, dotIdx);
151
+ const rest = trimmed.slice(dotIdx + 1);
152
+ const rootVal = context[root];
153
+ if (rootVal == null) return void 0;
154
+ return resolvePath(rest, rootVal);
155
+ }
156
+ return resolvePath(trimmed, context);
157
+ }
158
+ function translateForWasm(expr) {
159
+ return expr.replace(/\$fn\./g, "").replace(/\$instance\./g, "state_data.").replace(/\$data\./g, "state_data.").replace(/\$row\./g, "state_data.");
160
+ }
161
+ function buildWasmContext(context) {
162
+ const wasmCtx = {};
163
+ if (context.$instance && typeof context.$instance === "object") {
164
+ const inst = context.$instance;
165
+ wasmCtx.state_data = inst.fields ?? inst;
166
+ }
167
+ if (context.$local) wasmCtx.$local = context.$local;
168
+ if (context.$user) wasmCtx.$user = context.$user;
169
+ if (context.$entity) wasmCtx.$entity = context.$entity;
170
+ if (context.state_data) wasmCtx.state_data = context.state_data;
171
+ if (context.memory) wasmCtx.memory = context.memory;
172
+ if (context.context) wasmCtx.context = context.context;
173
+ return wasmCtx;
174
+ }
175
+ function evaluateWithJS(expr, context) {
176
+ const paramNames = [];
177
+ const paramValues = [];
178
+ for (const [key, value] of Object.entries(context)) {
179
+ if (key.startsWith("$")) {
180
+ paramNames.push(key);
181
+ paramValues.push(value);
182
+ }
183
+ }
184
+ if (context.$fn && typeof context.$fn === "object") {
185
+ for (const [name, fn2] of Object.entries(context.$fn)) {
186
+ if (!paramNames.includes(name)) {
187
+ paramNames.push(name);
188
+ paramValues.push(fn2);
189
+ }
190
+ }
191
+ }
192
+ if ("item" in context) {
193
+ paramNames.push("item");
194
+ paramValues.push(context.item);
195
+ }
196
+ if ("index" in context) {
197
+ paramNames.push("index");
198
+ paramValues.push(context.index);
199
+ }
200
+ if (context.$instances) {
201
+ paramNames.push("items");
202
+ paramValues.push(context.$instances);
203
+ }
204
+ if (context.$instance) {
205
+ paramNames.push("instance");
206
+ paramValues.push(context.$instance);
207
+ }
208
+ if ("loading" in context) {
209
+ paramNames.push("loading");
210
+ paramValues.push(context.loading);
211
+ }
212
+ if (context.$local && typeof context.$local === "object") {
213
+ for (const [k, v] of Object.entries(context.$local)) {
214
+ if (!paramNames.includes(k)) {
215
+ paramNames.push(k);
216
+ paramValues.push(v);
217
+ }
218
+ }
219
+ }
220
+ const fn = compileToFunction(expr, paramNames);
221
+ if (!fn) return void 0;
222
+ try {
223
+ return fn(...paramValues);
224
+ } catch {
225
+ return void 0;
226
+ }
227
+ }
228
+ var _wasmModule, _wasmAvailable, LRUCache, classificationCache, builtinFunctions, compiledCache, FORBIDDEN_PATTERNS;
229
+ var init_expression_engine = __esm({
230
+ "src/player/expression-engine.ts"() {
231
+ "use strict";
232
+ _wasmModule = null;
233
+ _wasmAvailable = false;
234
+ LRUCache = class {
235
+ constructor(maxSize) {
236
+ this.maxSize = maxSize;
237
+ }
238
+ map = /* @__PURE__ */ new Map();
239
+ get(key) {
240
+ const val = this.map.get(key);
241
+ if (val !== void 0) {
242
+ this.map.delete(key);
243
+ this.map.set(key, val);
244
+ }
245
+ return val;
246
+ }
247
+ set(key, value) {
248
+ if (this.map.has(key)) this.map.delete(key);
249
+ this.map.set(key, value);
250
+ if (this.map.size > this.maxSize) {
251
+ const first = this.map.keys().next().value;
252
+ if (first !== void 0) this.map.delete(first);
253
+ }
254
+ }
255
+ has(key) {
256
+ return this.map.has(key);
257
+ }
258
+ };
259
+ classificationCache = new LRUCache(500);
260
+ builtinFunctions = {
261
+ // Array
262
+ filter: (arr, fn) => {
263
+ if (!Array.isArray(arr)) return [];
264
+ if (typeof fn === "function") return arr.filter(fn);
265
+ return arr;
266
+ },
267
+ map: (arr, fn) => {
268
+ if (!Array.isArray(arr)) return [];
269
+ if (typeof fn === "function") return arr.map(fn);
270
+ return arr;
271
+ },
272
+ reduce: (arr, fn, init) => {
273
+ if (!Array.isArray(arr)) return init;
274
+ if (typeof fn === "function") return arr.reduce(fn, init);
275
+ return init;
276
+ },
277
+ find: (arr, fn) => {
278
+ if (!Array.isArray(arr)) return void 0;
279
+ if (typeof fn === "function") return arr.find(fn);
280
+ return void 0;
281
+ },
282
+ includes: (arr, item) => {
283
+ if (Array.isArray(arr)) return arr.includes(item);
284
+ if (typeof arr === "string") return arr.includes(String(item));
285
+ return false;
286
+ },
287
+ indexOf: (arr, item) => {
288
+ if (Array.isArray(arr)) return arr.indexOf(item);
289
+ if (typeof arr === "string") return arr.indexOf(String(item));
290
+ return -1;
291
+ },
292
+ slice: (arr, start, end) => {
293
+ if (Array.isArray(arr) || typeof arr === "string") {
294
+ return arr.slice(Number(start) || 0, end != null ? Number(end) : void 0);
295
+ }
296
+ return arr;
297
+ },
298
+ sort: (arr, fn) => {
299
+ if (!Array.isArray(arr)) return [];
300
+ const copy = [...arr];
301
+ if (typeof fn === "function") return copy.sort(fn);
302
+ return copy.sort();
303
+ },
304
+ reverse: (arr) => {
305
+ if (!Array.isArray(arr)) return [];
306
+ return [...arr].reverse();
307
+ },
308
+ unique: (arr) => {
309
+ if (!Array.isArray(arr)) return [];
310
+ return [...new Set(arr)];
311
+ },
312
+ flat: (arr, depth) => {
313
+ if (!Array.isArray(arr)) return [];
314
+ return arr.flat(Number(depth) || 1);
315
+ },
316
+ concat: (a, b) => {
317
+ if (Array.isArray(a)) return a.concat(Array.isArray(b) ? b : [b]);
318
+ if (typeof a === "string") return a + String(b ?? "");
319
+ return [a, b];
320
+ },
321
+ any: (arr, fn) => {
322
+ if (!Array.isArray(arr)) return false;
323
+ if (typeof fn === "function") return arr.some(fn);
324
+ return arr.length > 0;
325
+ },
326
+ all: (arr, fn) => {
327
+ if (!Array.isArray(arr)) return false;
328
+ if (typeof fn === "function") return arr.every(fn);
329
+ return false;
330
+ },
331
+ group_by: (arr, key) => {
332
+ if (!Array.isArray(arr) || typeof key !== "string") return {};
333
+ const groups = {};
334
+ for (const item of arr) {
335
+ const k = String(item?.[key] ?? "undefined");
336
+ (groups[k] ??= []).push(item);
337
+ }
338
+ return groups;
339
+ },
340
+ count: (arr) => Array.isArray(arr) ? arr.length : 0,
341
+ sum: (arr, key) => {
342
+ if (!Array.isArray(arr)) return 0;
343
+ if (typeof key === "string") {
344
+ return arr.reduce((s, item) => s + (Number(item?.[key]) || 0), 0);
345
+ }
346
+ return arr.reduce((s, v) => s + (Number(v) || 0), 0);
347
+ },
348
+ avg: (arr, key) => {
349
+ if (!Array.isArray(arr) || arr.length === 0) return 0;
350
+ const s = builtinFunctions.sum(arr, key);
351
+ return s / arr.length;
352
+ },
353
+ min: (...args) => {
354
+ if (args.length === 1 && Array.isArray(args[0])) return Math.min(...args[0].map(Number));
355
+ return Math.min(...args.map(Number));
356
+ },
357
+ max: (...args) => {
358
+ if (args.length === 1 && Array.isArray(args[0])) return Math.max(...args[0].map(Number));
359
+ return Math.max(...args.map(Number));
360
+ },
361
+ // String
362
+ len: (v) => {
363
+ if (Array.isArray(v)) return v.length;
364
+ if (typeof v === "string") return v.length;
365
+ return 0;
366
+ },
367
+ upper: (v) => typeof v === "string" ? v.toUpperCase() : String(v ?? "").toUpperCase(),
368
+ lower: (v) => typeof v === "string" ? v.toLowerCase() : String(v ?? "").toLowerCase(),
369
+ trim: (v) => typeof v === "string" ? v.trim() : String(v ?? "").trim(),
370
+ contains: (haystack, needle) => {
371
+ if (typeof haystack === "string") return haystack.includes(String(needle));
372
+ if (Array.isArray(haystack)) return haystack.includes(needle);
373
+ return false;
374
+ },
375
+ starts_with: (v, prefix) => typeof v === "string" ? v.startsWith(String(prefix)) : false,
376
+ ends_with: (v, suffix) => typeof v === "string" ? v.endsWith(String(suffix)) : false,
377
+ replace: (v, search, rep) => typeof v === "string" ? v.replaceAll(String(search), String(rep)) : v,
378
+ split: (v, sep) => typeof v === "string" ? v.split(String(sep)) : [],
379
+ join: (arr, sep) => Array.isArray(arr) ? arr.join(String(sep ?? ",")) : String(arr),
380
+ substr: (v, start, len) => {
381
+ if (typeof v !== "string") return "";
382
+ return v.substring(Number(start) || 0, len != null ? (Number(start) || 0) + Number(len) : void 0);
383
+ },
384
+ format: (template, ...args) => {
385
+ if (typeof template !== "string") return String(template);
386
+ return template.replace(/\{(\d+)\}/g, (_, i) => String(args[Number(i)] ?? ""));
387
+ },
388
+ // Math
389
+ abs: (v) => Math.abs(Number(v) || 0),
390
+ ceil: (v) => Math.ceil(Number(v) || 0),
391
+ floor: (v) => Math.floor(Number(v) || 0),
392
+ round: (v, decimals) => {
393
+ const n = Number(v) || 0;
394
+ const d = Number(decimals) || 0;
395
+ const f = Math.pow(10, d);
396
+ return Math.round(n * f) / f;
397
+ },
398
+ pow: (base, exp) => Math.pow(Number(base) || 0, Number(exp) || 0),
399
+ sqrt: (v) => Math.sqrt(Number(v) || 0),
400
+ random: () => Math.random(),
401
+ clamp: (v, lo, hi) => Math.min(Math.max(Number(v), Number(lo)), Number(hi)),
402
+ // Date
403
+ now: () => (/* @__PURE__ */ new Date()).toISOString(),
404
+ formatDate: (v, fmt) => {
405
+ try {
406
+ const d = new Date(v);
407
+ if (isNaN(d.getTime())) return String(v);
408
+ if (fmt === "relative") {
409
+ const diff = Date.now() - d.getTime();
410
+ if (diff < 6e4) return "just now";
411
+ if (diff < 36e5) return `${Math.floor(diff / 6e4)}m ago`;
412
+ if (diff < 864e5) return `${Math.floor(diff / 36e5)}h ago`;
413
+ return `${Math.floor(diff / 864e5)}d ago`;
414
+ }
415
+ return d.toLocaleDateString();
416
+ } catch {
417
+ return String(v);
418
+ }
419
+ },
420
+ // Utility
421
+ coalesce: (...args) => args.find((a) => a != null),
422
+ default: (v, fallback) => v ?? fallback,
423
+ json: (v) => JSON.stringify(v),
424
+ keys: (v) => v && typeof v === "object" && !Array.isArray(v) ? Object.keys(v) : [],
425
+ values: (v) => v && typeof v === "object" && !Array.isArray(v) ? Object.values(v) : [],
426
+ entries: (v) => v && typeof v === "object" && !Array.isArray(v) ? Object.entries(v) : [],
427
+ merge: (...args) => Object.assign({}, ...args.filter((a) => a && typeof a === "object")),
428
+ debug: (v, label) => {
429
+ console.log(label ? `[debug:${label}]` : "[debug]", v);
430
+ return v;
431
+ },
432
+ Boolean: (v) => Boolean(v),
433
+ Number: (v) => Number(v),
434
+ String: (v) => String(v ?? "")
435
+ };
436
+ compiledCache = new LRUCache(2e3);
437
+ FORBIDDEN_PATTERNS = [
438
+ /\beval\b/,
439
+ /\bFunction\b/,
440
+ /\bfetch\b/,
441
+ /\bdocument\b/,
442
+ /\bwindow\b/,
443
+ /\bprocess\b/,
444
+ /\bglobalThis\b/,
445
+ /\bimport\b/,
446
+ /\brequire\b/,
447
+ /\b__proto__\b/,
448
+ /\bconstructor\b/
449
+ ];
450
+ }
451
+ });
452
+
453
+ // src/player/scope-builder.ts
454
+ function useScope() {
455
+ return (0, import_react.useContext)(ScopeContext);
456
+ }
457
+ function buildScope(opts) {
458
+ const {
459
+ dataSources = {},
460
+ localState = {},
461
+ auth,
462
+ entity,
463
+ parentScope,
464
+ actionScope,
465
+ functions = {}
466
+ } = opts;
467
+ const scope = {
468
+ ...parentScope ?? emptyScopeData,
469
+ $local: { ...parentScope?.$local ?? {}, ...localState },
470
+ $fn: { ...builtinFunctions, ...parentScope?.$fn ?? {}, ...functions }
471
+ };
472
+ if (auth) {
473
+ scope.$user = { id: auth.userId, roles: auth.roles ?? [] };
474
+ }
475
+ if (entity) {
476
+ scope.$entity = entity;
477
+ }
478
+ if (actionScope) {
479
+ scope.$action = actionScope;
480
+ }
481
+ if (Object.keys(dataSources).length > 0) {
482
+ const allInstances = [];
483
+ let primaryInstance;
484
+ let primaryDefinition;
485
+ let primaryPagination;
486
+ for (const [name, result] of Object.entries(dataSources)) {
487
+ if (result.instance) {
488
+ primaryInstance = result.instance;
489
+ scope[name] = result.instance;
490
+ }
491
+ if (result.instances) {
492
+ allInstances.push(...result.instances);
493
+ scope[name] = result.instances;
494
+ }
495
+ if (result.definition) {
496
+ primaryDefinition = result.definition;
497
+ }
498
+ if (result.pagination) {
499
+ primaryPagination = result.pagination;
500
+ }
501
+ }
502
+ if (primaryInstance) scope.$instance = primaryInstance;
503
+ if (allInstances.length > 0) scope.$instances = allInstances;
504
+ if (primaryDefinition) scope.$definition = primaryDefinition;
505
+ if (primaryPagination) scope.$pagination = primaryPagination;
506
+ const anyLoading = Object.values(dataSources).some((r) => r.loading);
507
+ scope.loading = anyLoading;
508
+ }
509
+ return scope;
510
+ }
511
+ function mergeScope(parent, child) {
512
+ return {
513
+ ...parent,
514
+ ...child,
515
+ $local: { ...parent.$local, ...child.$local ?? {} },
516
+ $fn: { ...parent.$fn, ...child.$fn ?? {} },
517
+ $action: child.$action ?? parent.$action
518
+ };
519
+ }
520
+ function buildLoopScope(parent, item, index, as) {
521
+ return {
522
+ ...parent,
523
+ $item: item,
524
+ $index: index,
525
+ [as]: item,
526
+ // Convenience: flatten item fields for direct access
527
+ item,
528
+ index
529
+ };
530
+ }
531
+ var import_react, emptyScopeData, ScopeContext;
532
+ var init_scope_builder = __esm({
533
+ "src/player/scope-builder.ts"() {
534
+ "use strict";
535
+ import_react = require("react");
536
+ init_expression_engine();
537
+ emptyScopeData = {
538
+ $local: {},
539
+ $user: { roles: [] },
540
+ $fn: builtinFunctions,
541
+ $action: {}
542
+ };
543
+ ScopeContext = (0, import_react.createContext)(emptyScopeData);
544
+ }
545
+ });
546
+
547
+ // src/player/atoms/layout.tsx
548
+ var layout_exports = {};
549
+ __export(layout_exports, {
550
+ Column: () => Column,
551
+ Divider: () => Divider,
552
+ Grid: () => Grid,
553
+ Row: () => Row,
554
+ Spacer: () => Spacer,
555
+ Stack: () => Stack
556
+ });
557
+ var import_jsx_runtime, filterHtmlProps, Stack, Row, Grid, Column, Divider, Spacer;
558
+ var init_layout = __esm({
559
+ "src/player/atoms/layout.tsx"() {
560
+ "use strict";
561
+ import_jsx_runtime = require("react/jsx-runtime");
562
+ filterHtmlProps = (props) => {
563
+ const html = {};
564
+ for (const [k, v] of Object.entries(props)) {
565
+ if (["className", "style", "id", "role", "tabIndex", "title", "onClick", "data-node-id"].includes(k)) {
566
+ html[k] = v;
567
+ }
568
+ if (k.startsWith("data-") || k.startsWith("aria-")) html[k] = v;
569
+ }
570
+ return html;
571
+ };
572
+ Stack = ({ children, gap, padding, align, justify, className, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
573
+ "div",
574
+ {
575
+ ...filterHtmlProps(rest),
576
+ className,
577
+ style: {
578
+ display: "flex",
579
+ flexDirection: "column",
580
+ gap: gap != null ? Number(gap) * 4 : void 0,
581
+ padding: padding != null ? Number(padding) * 4 : void 0,
582
+ alignItems: align,
583
+ justifyContent: justify,
584
+ ...style
585
+ },
586
+ children
587
+ }
588
+ );
589
+ Row = ({ children, gap, padding, align, justify, wrap, className, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
590
+ "div",
591
+ {
592
+ ...filterHtmlProps(rest),
593
+ className,
594
+ style: {
595
+ display: "flex",
596
+ flexDirection: "row",
597
+ gap: gap != null ? Number(gap) * 4 : void 0,
598
+ padding: padding != null ? Number(padding) * 4 : void 0,
599
+ alignItems: align ?? "center",
600
+ justifyContent: justify,
601
+ flexWrap: wrap ? "wrap" : void 0,
602
+ ...style
603
+ },
604
+ children
605
+ }
606
+ );
607
+ Grid = ({ children, columns, gap, padding, minChildWidth, className, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
608
+ "div",
609
+ {
610
+ ...filterHtmlProps(rest),
611
+ className,
612
+ style: {
613
+ display: "grid",
614
+ gridTemplateColumns: minChildWidth ? `repeat(auto-fill, minmax(${Number(minChildWidth)}px, 1fr))` : columns ? `repeat(${Number(columns)}, 1fr)` : "repeat(auto-fill, minmax(200px, 1fr))",
615
+ gap: gap != null ? Number(gap) * 4 : 16,
616
+ padding: padding != null ? Number(padding) * 4 : void 0,
617
+ ...style
618
+ },
619
+ children
620
+ }
621
+ );
622
+ Column = ({ children, span, className, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
623
+ "div",
624
+ {
625
+ ...filterHtmlProps(rest),
626
+ className,
627
+ style: {
628
+ gridColumn: span ? `span ${Number(span)}` : void 0,
629
+ ...style
630
+ },
631
+ children
632
+ }
633
+ );
634
+ Divider = ({ orientation, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
635
+ "hr",
636
+ {
637
+ className,
638
+ style: {
639
+ border: "none",
640
+ borderTop: orientation === "vertical" ? "none" : "1px solid #e2e8f0",
641
+ borderLeft: orientation === "vertical" ? "1px solid #e2e8f0" : "none",
642
+ margin: orientation === "vertical" ? "0 8px" : "8px 0",
643
+ alignSelf: orientation === "vertical" ? "stretch" : void 0,
644
+ ...style
645
+ }
646
+ }
647
+ );
648
+ Spacer = ({ size, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
649
+ "div",
650
+ {
651
+ className,
652
+ style: {
653
+ flex: size ? `0 0 ${Number(size) * 4}px` : "1",
654
+ ...style
655
+ }
656
+ }
657
+ );
658
+ }
659
+ });
660
+
661
+ // src/player/atoms/content.tsx
662
+ var content_exports = {};
663
+ __export(content_exports, {
664
+ Alert: () => Alert,
665
+ Badge: () => Badge,
666
+ EmptyState: () => EmptyState,
667
+ Field: () => Field,
668
+ Heading: () => Heading,
669
+ Icon: () => Icon,
670
+ Image: () => Image,
671
+ Markdown: () => Markdown,
672
+ Progress: () => Progress,
673
+ Separator: () => Separator,
674
+ Text: () => Text
675
+ });
676
+ var import_jsx_runtime2, Text, Heading, Field, Image, Badge, ICON_MAP, Icon, Alert, EmptyState, Markdown, Progress, Separator;
677
+ var init_content = __esm({
678
+ "src/player/atoms/content.tsx"() {
679
+ "use strict";
680
+ import_jsx_runtime2 = require("react/jsx-runtime");
681
+ Text = ({ value, children, variant, size, weight, color, align, className, style }) => {
682
+ const text = value ?? children;
683
+ const sizeMap = { xs: 11, sm: 13, md: 14, lg: 16, xl: 20, "2xl": 24 };
684
+ const weightMap = { light: 300, normal: 400, medium: 500, semibold: 600, bold: 700 };
685
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
686
+ "span",
687
+ {
688
+ className,
689
+ style: {
690
+ fontSize: size ? sizeMap[size] ?? Number(size) : void 0,
691
+ fontWeight: weight ? weightMap[weight] ?? weight : void 0,
692
+ color: variant === "muted" ? "#718096" : variant === "error" ? "#e53e3e" : variant === "success" ? "#38a169" : color,
693
+ textAlign: align,
694
+ ...style
695
+ },
696
+ children: text == null ? "" : String(text)
697
+ }
698
+ );
699
+ };
700
+ Heading = ({ value, children, level, className, style }) => {
701
+ const text = value ?? children;
702
+ const sizes = { 1: 32, 2: 24, 3: 20, 4: 16, 5: 14, 6: 12 };
703
+ const lvl = Number(level) || 2;
704
+ const Tag = `h${Math.min(Math.max(lvl, 1), 6)}`;
705
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
706
+ Tag,
707
+ {
708
+ className,
709
+ style: {
710
+ fontSize: sizes[lvl] ?? 20,
711
+ fontWeight: 600,
712
+ margin: "0 0 8px 0",
713
+ lineHeight: 1.3,
714
+ ...style
715
+ },
716
+ children: text == null ? "" : String(text)
717
+ }
718
+ );
719
+ };
720
+ Field = ({ label, value, type: _type, children, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className, style: { marginBottom: 8, ...style }, children: [
721
+ label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: { display: "block", fontSize: 12, fontWeight: 500, color: "#718096", marginBottom: 2 }, children: String(label) }) : null,
722
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14 }, children: children ?? (value != null ? String(value) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#a0aec0" }, children: "\u2014" })) })
723
+ ] });
724
+ Image = ({ src, alt, width, height, fit, radius, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
725
+ "img",
726
+ {
727
+ src,
728
+ alt: alt ?? "",
729
+ className,
730
+ style: {
731
+ width: width ? Number(width) : void 0,
732
+ height: height ? Number(height) : void 0,
733
+ objectFit: fit ?? "cover",
734
+ borderRadius: radius ? Number(radius) : void 0,
735
+ maxWidth: "100%",
736
+ ...style
737
+ }
738
+ }
739
+ );
740
+ Badge = ({ value, children, variant, color, className, style }) => {
741
+ const text = value ?? children;
742
+ const colorMap = {
743
+ default: { bg: "#edf2f7", fg: "#4a5568" },
744
+ primary: { bg: "#ebf8ff", fg: "#2b6cb0" },
745
+ success: { bg: "#f0fff4", fg: "#276749" },
746
+ warning: { bg: "#fffaf0", fg: "#c05621" },
747
+ error: { bg: "#fff5f5", fg: "#c53030" },
748
+ info: { bg: "#ebf8ff", fg: "#2b6cb0" }
749
+ };
750
+ const c = colorMap[variant ?? "default"] ?? colorMap.default;
751
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
752
+ "span",
753
+ {
754
+ className,
755
+ style: {
756
+ display: "inline-block",
757
+ padding: "1px 8px",
758
+ borderRadius: 9999,
759
+ fontSize: 12,
760
+ fontWeight: 500,
761
+ background: color ? void 0 : c.bg,
762
+ color: color ?? c.fg,
763
+ ...style
764
+ },
765
+ children: text == null ? "" : String(text)
766
+ }
767
+ );
768
+ };
769
+ ICON_MAP = {
770
+ "check": "\u2713",
771
+ "x": "\u2715",
772
+ "plus": "+",
773
+ "minus": "\u2212",
774
+ "arrow-right": "\u2192",
775
+ "arrow-left": "\u2190",
776
+ "arrow-up": "\u2191",
777
+ "arrow-down": "\u2193",
778
+ "search": "\u{1F50D}",
779
+ "home": "\u{1F3E0}",
780
+ "user": "\u{1F464}",
781
+ "settings": "\u2699",
782
+ "star": "\u2B50",
783
+ "heart": "\u2764",
784
+ "mail": "\u2709",
785
+ "phone": "\u{1F4DE}",
786
+ "calendar": "\u{1F4C5}",
787
+ "clock": "\u{1F550}",
788
+ "edit": "\u270E",
789
+ "trash": "\u{1F5D1}",
790
+ "download": "\u2B07",
791
+ "upload": "\u2B06",
792
+ "share": "\u2197",
793
+ "lock": "\u{1F512}",
794
+ "unlock": "\u{1F513}",
795
+ "eye": "\u{1F441}",
796
+ "eye-off": "\u{1F648}",
797
+ "bell": "\u{1F514}",
798
+ "info": "\u2139",
799
+ "warning": "\u26A0",
800
+ "error": "\u274C",
801
+ "loading": "\u23F3",
802
+ "menu": "\u2630",
803
+ "close": "\u2715",
804
+ "chevron-right": "\u203A",
805
+ "chevron-left": "\u2039",
806
+ "chevron-up": "\u2038",
807
+ "chevron-down": "\u02EC",
808
+ "copy": "\u{1F4CB}",
809
+ "save": "\u{1F4BE}",
810
+ "refresh": "\u21BB",
811
+ "filter": "\u23CF",
812
+ "sort": "\u21C5"
813
+ };
814
+ Icon = ({ name, size, color, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
815
+ "span",
816
+ {
817
+ className,
818
+ role: "img",
819
+ "aria-label": name,
820
+ style: {
821
+ fontSize: size ? Number(size) : 16,
822
+ color,
823
+ display: "inline-flex",
824
+ alignItems: "center",
825
+ justifyContent: "center",
826
+ ...style
827
+ },
828
+ children: ICON_MAP[name?.toLowerCase()] ?? name ?? "?"
829
+ }
830
+ );
831
+ Alert = ({ children, variant, title, message, className, style }) => {
832
+ const colorMap = {
833
+ info: { bg: "#ebf8ff", border: "#90cdf4", fg: "#2b6cb0" },
834
+ success: { bg: "#f0fff4", border: "#9ae6b4", fg: "#276749" },
835
+ warning: { bg: "#fffaf0", border: "#fbd38d", fg: "#c05621" },
836
+ error: { bg: "#fff5f5", border: "#feb2b2", fg: "#c53030" }
837
+ };
838
+ const c = colorMap[variant ?? "info"] ?? colorMap.info;
839
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
840
+ "div",
841
+ {
842
+ className,
843
+ role: "alert",
844
+ style: {
845
+ padding: "12px 16px",
846
+ borderRadius: 6,
847
+ border: `1px solid ${c.border}`,
848
+ background: c.bg,
849
+ color: c.fg,
850
+ fontSize: 14,
851
+ ...style
852
+ },
853
+ children: [
854
+ title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontWeight: 600, marginBottom: 4 }, children: String(title) }) : null,
855
+ message ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: String(message) }) : null,
856
+ children
857
+ ]
858
+ }
859
+ );
860
+ };
861
+ EmptyState = ({ children, title, description, icon, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
862
+ "div",
863
+ {
864
+ className,
865
+ style: {
866
+ textAlign: "center",
867
+ padding: "32px 16px",
868
+ color: "#a0aec0",
869
+ ...style
870
+ },
871
+ children: [
872
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 40, marginBottom: 12 }, children: ICON_MAP[icon] ?? icon }) : null,
873
+ title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 16, fontWeight: 600, color: "#4a5568", marginBottom: 4 }, children: String(title) }) : null,
874
+ description ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, marginBottom: 8 }, children: String(description) }) : null,
875
+ children
876
+ ]
877
+ }
878
+ );
879
+ Markdown = ({ value, children, className, style }) => {
880
+ const text = String(value ?? children ?? "");
881
+ const html = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>").replace(/\*(.+?)\*/g, "<em>$1</em>").replace(/`(.+?)`/g, '<code style="background:#edf2f7;padding:1px 4px;border-radius:3px;font-size:13px">$1</code>').replace(/\n/g, "<br/>");
882
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
883
+ "div",
884
+ {
885
+ className,
886
+ style: { fontSize: 14, lineHeight: 1.6, ...style },
887
+ dangerouslySetInnerHTML: { __html: html }
888
+ }
889
+ );
890
+ };
891
+ Progress = ({ value, max, label, variant, className, style }) => {
892
+ const pct = Math.min(100, Math.max(0, Number(value) / (Number(max) || 100) * 100));
893
+ const colorMap = {
894
+ default: "#3182ce",
895
+ success: "#38a169",
896
+ warning: "#dd6b20",
897
+ error: "#e53e3e"
898
+ };
899
+ const color = colorMap[variant ?? "default"] ?? colorMap.default;
900
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className, style: { ...style }, children: [
901
+ label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 12, marginBottom: 4, color: "#718096" }, children: String(label) }) : null,
902
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: 8, background: "#edf2f7", borderRadius: 4, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: "100%", width: `${pct}%`, background: color, borderRadius: 4, transition: "width 0.3s" } }) })
903
+ ] });
904
+ };
905
+ Separator = ({ className, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
906
+ "hr",
907
+ {
908
+ className,
909
+ style: { border: "none", borderTop: "1px solid #e2e8f0", margin: "16px 0", ...style }
910
+ }
911
+ );
912
+ }
913
+ });
914
+
915
+ // src/player/atoms/actions.tsx
916
+ var actions_exports = {};
917
+ __export(actions_exports, {
918
+ Button: () => Button,
919
+ Link: () => Link
920
+ });
921
+ var import_react4, import_jsx_runtime3, VARIANT_STYLES, SIZE_STYLES, Button, Link;
922
+ var init_actions = __esm({
923
+ "src/player/atoms/actions.tsx"() {
924
+ "use strict";
925
+ import_react4 = require("react");
926
+ import_jsx_runtime3 = require("react/jsx-runtime");
927
+ VARIANT_STYLES = {
928
+ primary: { background: "#3182ce", color: "#fff", border: "1px solid #3182ce" },
929
+ secondary: { background: "#edf2f7", color: "#4a5568", border: "1px solid #e2e8f0" },
930
+ outline: { background: "transparent", color: "#3182ce", border: "1px solid #3182ce" },
931
+ ghost: { background: "transparent", color: "#4a5568", border: "1px solid transparent" },
932
+ danger: { background: "#e53e3e", color: "#fff", border: "1px solid #e53e3e" },
933
+ destructive: { background: "#e53e3e", color: "#fff", border: "1px solid #e53e3e" },
934
+ success: { background: "#38a169", color: "#fff", border: "1px solid #38a169" },
935
+ link: { background: "transparent", color: "#3182ce", border: "none", textDecoration: "underline" },
936
+ default: { background: "#fff", color: "#1a202c", border: "1px solid #e2e8f0" }
937
+ };
938
+ SIZE_STYLES = {
939
+ xs: { padding: "2px 8px", fontSize: 11 },
940
+ sm: { padding: "4px 12px", fontSize: 13 },
941
+ md: { padding: "6px 16px", fontSize: 14 },
942
+ lg: { padding: "8px 24px", fontSize: 16 },
943
+ xl: { padding: "12px 32px", fontSize: 18 }
944
+ };
945
+ Button = ({
946
+ children,
947
+ label,
948
+ value,
949
+ onClick,
950
+ variant,
951
+ size,
952
+ disabled,
953
+ loading: loadingProp,
954
+ icon,
955
+ iconRight,
956
+ fullWidth,
957
+ className,
958
+ style
959
+ }) => {
960
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
961
+ const text = children ?? label ?? value;
962
+ const isDisabled = Boolean(disabled) || isLoading || Boolean(loadingProp);
963
+ const vs = VARIANT_STYLES[variant ?? "default"] ?? VARIANT_STYLES.default;
964
+ const ss = SIZE_STYLES[size ?? "md"] ?? SIZE_STYLES.md;
965
+ const handleClick = (0, import_react4.useCallback)(async (e) => {
966
+ if (isDisabled) return;
967
+ if (typeof onClick === "function") {
968
+ const result = onClick(e);
969
+ if (result && typeof result === "object" && typeof result.then === "function") {
970
+ setIsLoading(true);
971
+ try {
972
+ await result;
973
+ } finally {
974
+ setIsLoading(false);
975
+ }
976
+ }
977
+ }
978
+ }, [onClick, isDisabled]);
979
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
980
+ "button",
981
+ {
982
+ className,
983
+ disabled: isDisabled,
984
+ onClick: handleClick,
985
+ style: {
986
+ ...vs,
987
+ ...ss,
988
+ borderRadius: 6,
989
+ cursor: isDisabled ? "not-allowed" : "pointer",
990
+ opacity: isDisabled ? 0.6 : 1,
991
+ fontWeight: 500,
992
+ display: "inline-flex",
993
+ alignItems: "center",
994
+ justifyContent: "center",
995
+ gap: 6,
996
+ width: fullWidth ? "100%" : void 0,
997
+ transition: "opacity 0.15s, background 0.15s",
998
+ ...style
999
+ },
1000
+ children: [
1001
+ isLoading || loadingProp ? "\u23F3" : icon ? String(icon) : null,
1002
+ text != null ? typeof text === "string" || typeof text === "number" ? String(text) : text : null,
1003
+ iconRight ? String(iconRight) : null
1004
+ ]
1005
+ }
1006
+ );
1007
+ };
1008
+ Link = ({ children, href, to, label, onClick, external, className, style }) => {
1009
+ const text = children ?? label;
1010
+ const target = href ?? to;
1011
+ const handleClick = (0, import_react4.useCallback)((e) => {
1012
+ if (typeof onClick === "function") {
1013
+ e.preventDefault();
1014
+ onClick(e);
1015
+ }
1016
+ }, [onClick]);
1017
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1018
+ "a",
1019
+ {
1020
+ href: target ?? "#",
1021
+ className,
1022
+ onClick: handleClick,
1023
+ target: external ? "_blank" : void 0,
1024
+ rel: external ? "noopener noreferrer" : void 0,
1025
+ style: {
1026
+ color: "#3182ce",
1027
+ textDecoration: "none",
1028
+ cursor: "pointer",
1029
+ fontSize: 14,
1030
+ ...style
1031
+ },
1032
+ children: text != null ? String(text) : target ?? "Link"
1033
+ }
1034
+ );
1035
+ };
1036
+ }
1037
+ });
1038
+
1039
+ // src/player/atoms/control-flow.tsx
1040
+ var control_flow_exports = {};
1041
+ __export(control_flow_exports, {
1042
+ Each: () => Each,
1043
+ Show: () => Show
1044
+ });
1045
+ var import_jsx_runtime4, Show, Each;
1046
+ var init_control_flow = __esm({
1047
+ "src/player/atoms/control-flow.tsx"() {
1048
+ "use strict";
1049
+ init_scope_builder();
1050
+ import_jsx_runtime4 = require("react/jsx-runtime");
1051
+ Show = ({ when, fallback, children }) => {
1052
+ if (when) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
1053
+ if (fallback) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: fallback });
1054
+ return null;
1055
+ };
1056
+ Each = ({ items, as: asName, keyField, children, renderItem, emptyState, className, style }) => {
1057
+ const parentScope = useScope();
1058
+ const itemArray = Array.isArray(items) ? items : [];
1059
+ const varName = asName ?? "item";
1060
+ const keyProp = keyField ?? "id";
1061
+ if (itemArray.length === 0) {
1062
+ if (emptyState) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: emptyState });
1063
+ return null;
1064
+ }
1065
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style, children: itemArray.map((item, index) => {
1066
+ const loopScope = buildLoopScope(parentScope, item, index, varName);
1067
+ const key = item && typeof item === "object" && keyProp in item ? String(item[keyProp]) : String(index);
1068
+ if (typeof renderItem === "function") {
1069
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScopeContext.Provider, { value: loopScope, children: renderItem(item, index) }, key);
1070
+ }
1071
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScopeContext.Provider, { value: loopScope, children }, key);
1072
+ }) });
1073
+ };
1074
+ }
1075
+ });
1076
+
1077
+ // src/player/atoms/input.tsx
1078
+ var input_exports = {};
1079
+ __export(input_exports, {
1080
+ Select: () => Select,
1081
+ Slider: () => Slider,
1082
+ TextInput: () => TextInput,
1083
+ Toggle: () => Toggle
1084
+ });
1085
+ var import_react5, import_jsx_runtime5, inputBase, TextInput, Select, Toggle, Slider;
1086
+ var init_input = __esm({
1087
+ "src/player/atoms/input.tsx"() {
1088
+ "use strict";
1089
+ import_react5 = require("react");
1090
+ import_jsx_runtime5 = require("react/jsx-runtime");
1091
+ inputBase = {
1092
+ padding: "6px 12px",
1093
+ border: "1px solid #e2e8f0",
1094
+ borderRadius: 6,
1095
+ fontSize: 14,
1096
+ outline: "none",
1097
+ width: "100%",
1098
+ boxSizing: "border-box",
1099
+ background: "#fff",
1100
+ color: "#1a202c",
1101
+ transition: "border-color 0.15s"
1102
+ };
1103
+ TextInput = ({
1104
+ value,
1105
+ onChange,
1106
+ onBlur,
1107
+ placeholder,
1108
+ label,
1109
+ type,
1110
+ name,
1111
+ disabled,
1112
+ required,
1113
+ error,
1114
+ helperText,
1115
+ multiline,
1116
+ rows,
1117
+ maxLength,
1118
+ className,
1119
+ style,
1120
+ bind: _bind
1121
+ }) => {
1122
+ const isControlled = typeof onChange === "function";
1123
+ const [localValue, setLocalValue] = (0, import_react5.useState)(value ?? "");
1124
+ (0, import_react5.useEffect)(() => {
1125
+ if (value != null && String(value) !== localValue) {
1126
+ setLocalValue(String(value));
1127
+ }
1128
+ }, [value]);
1129
+ const handleChange = (0, import_react5.useCallback)((e) => {
1130
+ setLocalValue(e.target.value);
1131
+ if (typeof onChange === "function") {
1132
+ onChange(e);
1133
+ }
1134
+ }, [onChange]);
1135
+ const displayValue = isControlled ? value ?? "" : localValue;
1136
+ const hasError = Boolean(error);
1137
+ const inputStyle = {
1138
+ ...inputBase,
1139
+ borderColor: hasError ? "#e53e3e" : "#e2e8f0",
1140
+ ...style
1141
+ };
1142
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, style: { width: "100%" }, children: [
1143
+ label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "block", fontSize: 13, fontWeight: 500, marginBottom: 4, color: "#4a5568" }, children: [
1144
+ String(label),
1145
+ required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "#e53e3e" }, children: " *" }) : null
1146
+ ] }) : null,
1147
+ multiline ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1148
+ "textarea",
1149
+ {
1150
+ value: displayValue,
1151
+ onChange: handleChange,
1152
+ onBlur,
1153
+ placeholder,
1154
+ name,
1155
+ disabled: Boolean(disabled),
1156
+ required: Boolean(required),
1157
+ rows: Number(rows) || 3,
1158
+ maxLength: maxLength ? Number(maxLength) : void 0,
1159
+ style: inputStyle
1160
+ }
1161
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1162
+ "input",
1163
+ {
1164
+ type: type ?? "text",
1165
+ value: displayValue,
1166
+ onChange: handleChange,
1167
+ onBlur,
1168
+ placeholder,
1169
+ name,
1170
+ disabled: Boolean(disabled),
1171
+ required: Boolean(required),
1172
+ maxLength: maxLength ? Number(maxLength) : void 0,
1173
+ style: inputStyle
1174
+ }
1175
+ ),
1176
+ error || helperText ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { fontSize: 12, marginTop: 2, color: hasError ? "#e53e3e" : "#a0aec0" }, children: String(error || helperText) }) : null
1177
+ ] });
1178
+ };
1179
+ Select = ({
1180
+ value,
1181
+ onChange,
1182
+ options,
1183
+ placeholder,
1184
+ label,
1185
+ disabled,
1186
+ required,
1187
+ error,
1188
+ name,
1189
+ className,
1190
+ style
1191
+ }) => {
1192
+ const [localValue, setLocalValue] = (0, import_react5.useState)(value ?? "");
1193
+ const isControlled = typeof onChange === "function";
1194
+ (0, import_react5.useEffect)(() => {
1195
+ if (value != null && String(value) !== localValue) setLocalValue(String(value));
1196
+ }, [value]);
1197
+ const handleChange = (0, import_react5.useCallback)((e) => {
1198
+ setLocalValue(e.target.value);
1199
+ if (typeof onChange === "function") onChange(e);
1200
+ }, [onChange]);
1201
+ const displayValue = isControlled ? value ?? "" : localValue;
1202
+ const opts = Array.isArray(options) ? options : [];
1203
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, children: [
1204
+ label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "block", fontSize: 13, fontWeight: 500, marginBottom: 4, color: "#4a5568" }, children: [
1205
+ String(label),
1206
+ required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "#e53e3e" }, children: " *" }) : null
1207
+ ] }) : null,
1208
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1209
+ "select",
1210
+ {
1211
+ value: displayValue,
1212
+ onChange: handleChange,
1213
+ disabled: Boolean(disabled),
1214
+ name,
1215
+ style: {
1216
+ ...inputBase,
1217
+ borderColor: error ? "#e53e3e" : "#e2e8f0",
1218
+ ...style
1219
+ },
1220
+ children: [
1221
+ placeholder ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "", children: String(placeholder) }) : null,
1222
+ opts.map((opt, i) => {
1223
+ const val = typeof opt === "object" ? opt.value : opt;
1224
+ const lbl = typeof opt === "object" ? opt.label ?? val : opt;
1225
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: String(val), children: String(lbl) }, String(val) ?? i);
1226
+ })
1227
+ ]
1228
+ }
1229
+ )
1230
+ ] });
1231
+ };
1232
+ Toggle = ({ value, checked, onChange, label, disabled, className, style }) => {
1233
+ const isOn = Boolean(value ?? checked);
1234
+ const handleClick = (0, import_react5.useCallback)(() => {
1235
+ if (disabled) return;
1236
+ if (typeof onChange === "function") onChange(!isOn);
1237
+ }, [onChange, isOn, disabled]);
1238
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1239
+ "div",
1240
+ {
1241
+ className,
1242
+ style: { display: "flex", alignItems: "center", gap: 8, ...style },
1243
+ children: [
1244
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1245
+ "button",
1246
+ {
1247
+ role: "switch",
1248
+ "aria-checked": isOn,
1249
+ disabled: Boolean(disabled),
1250
+ onClick: handleClick,
1251
+ style: {
1252
+ width: 40,
1253
+ height: 22,
1254
+ borderRadius: 11,
1255
+ border: "none",
1256
+ cursor: disabled ? "not-allowed" : "pointer",
1257
+ background: isOn ? "#3182ce" : "#cbd5e0",
1258
+ padding: 2,
1259
+ transition: "background 0.2s",
1260
+ display: "flex",
1261
+ alignItems: "center"
1262
+ },
1263
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1264
+ width: 18,
1265
+ height: 18,
1266
+ borderRadius: "50%",
1267
+ background: "#fff",
1268
+ transform: isOn ? "translateX(18px)" : "translateX(0)",
1269
+ transition: "transform 0.2s",
1270
+ boxShadow: "0 1px 3px rgba(0,0,0,0.2)"
1271
+ } })
1272
+ }
1273
+ ),
1274
+ label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { fontSize: 14 }, children: String(label) }) : null
1275
+ ]
1276
+ }
1277
+ );
1278
+ };
1279
+ Slider = ({ value, onChange, min, max, step, label, disabled, className, style }) => {
1280
+ const numVal = Number(value) || Number(min) || 0;
1281
+ const handleChange = (0, import_react5.useCallback)((e) => {
1282
+ if (typeof onChange === "function") onChange(Number(e.target.value));
1283
+ }, [onChange]);
1284
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, style: { ...style }, children: [
1285
+ label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 13, marginBottom: 4 }, children: [
1286
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "#4a5568", fontWeight: 500 }, children: String(label) }),
1287
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "#718096" }, children: numVal })
1288
+ ] }) : null,
1289
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1290
+ "input",
1291
+ {
1292
+ type: "range",
1293
+ value: numVal,
1294
+ onChange: handleChange,
1295
+ min: Number(min) ?? 0,
1296
+ max: Number(max) ?? 100,
1297
+ step: Number(step) ?? 1,
1298
+ disabled: Boolean(disabled),
1299
+ style: { width: "100%" }
1300
+ }
1301
+ )
1302
+ ] });
1303
+ };
1304
+ }
1305
+ });
1306
+
1307
+ // src/player/atoms/grouping.tsx
1308
+ var grouping_exports = {};
1309
+ __export(grouping_exports, {
1310
+ Accordion: () => Accordion,
1311
+ Card: () => Card,
1312
+ Modal: () => Modal,
1313
+ ScrollArea: () => ScrollArea,
1314
+ Section: () => Section,
1315
+ Tabs: () => Tabs
1316
+ });
1317
+ var import_react6, import_jsx_runtime6, Card, Section, Tabs, Accordion, Modal, ScrollArea;
1318
+ var init_grouping = __esm({
1319
+ "src/player/atoms/grouping.tsx"() {
1320
+ "use strict";
1321
+ import_react6 = __toESM(require("react"));
1322
+ import_jsx_runtime6 = require("react/jsx-runtime");
1323
+ Card = ({ children, title, subtitle, padding, variant, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1324
+ "div",
1325
+ {
1326
+ className,
1327
+ style: {
1328
+ background: variant === "outlined" ? "transparent" : "#fff",
1329
+ border: "1px solid #e2e8f0",
1330
+ borderRadius: 8,
1331
+ padding: padding != null ? Number(padding) * 4 : 16,
1332
+ boxShadow: variant === "elevated" ? "0 2px 8px rgba(0,0,0,0.08)" : void 0,
1333
+ ...style
1334
+ },
1335
+ children: [
1336
+ title ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: subtitle ? 2 : 12 }, children: String(title) }) : null,
1337
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 13, color: "#718096", marginBottom: 12 }, children: String(subtitle) }) : null,
1338
+ children
1339
+ ]
1340
+ }
1341
+ );
1342
+ Section = ({ children, title, description, collapsible, defaultOpen, className, style }) => {
1343
+ const [open, setOpen] = (0, import_react6.useState)(defaultOpen !== false);
1344
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, style: { marginBottom: 16, ...style }, children: [
1345
+ title ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1346
+ "div",
1347
+ {
1348
+ style: {
1349
+ display: "flex",
1350
+ alignItems: "center",
1351
+ justifyContent: "space-between",
1352
+ marginBottom: open ? 12 : 0,
1353
+ cursor: collapsible ? "pointer" : void 0
1354
+ },
1355
+ onClick: collapsible ? () => setOpen((v) => !v) : void 0,
1356
+ children: [
1357
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1358
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontWeight: 600, fontSize: 15 }, children: String(title) }),
1359
+ description ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 13, color: "#718096", marginTop: 2 }, children: String(description) }) : null
1360
+ ] }),
1361
+ collapsible ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "#a0aec0", fontSize: 18 }, children: open ? "\u25BE" : "\u25B8" }) : null
1362
+ ]
1363
+ }
1364
+ ) : null,
1365
+ open ? children : null
1366
+ ] });
1367
+ };
1368
+ Tabs = ({ children, tabs, defaultTab, className, style }) => {
1369
+ const tabList = Array.isArray(tabs) ? tabs.map((t) => typeof t === "string" ? { label: t, value: t } : t) : [];
1370
+ const [active, setActive] = (0, import_react6.useState)(defaultTab ?? tabList[0]?.value ?? "");
1371
+ if (tabList.length === 0) {
1372
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, style, children });
1373
+ }
1374
+ const childArray = import_react6.default.Children.toArray(children);
1375
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, style, children: [
1376
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", borderBottom: "2px solid #e2e8f0", marginBottom: 12, gap: 0 }, children: tabList.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1377
+ "button",
1378
+ {
1379
+ onClick: () => setActive(tab.value),
1380
+ style: {
1381
+ padding: "8px 16px",
1382
+ fontSize: 14,
1383
+ fontWeight: 500,
1384
+ cursor: "pointer",
1385
+ border: "none",
1386
+ background: "none",
1387
+ borderBottom: "2px solid transparent",
1388
+ marginBottom: -2,
1389
+ color: active === tab.value ? "#3182ce" : "#718096",
1390
+ borderBottomColor: active === tab.value ? "#3182ce" : "transparent"
1391
+ },
1392
+ children: tab.label
1393
+ },
1394
+ tab.value
1395
+ )) }),
1396
+ childArray.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: tabList[i]?.value === active ? "block" : "none" }, children: child }, i))
1397
+ ] });
1398
+ };
1399
+ Accordion = ({ children, items, allowMultiple, className, style }) => {
1400
+ const [openItems, setOpenItems] = (0, import_react6.useState)(/* @__PURE__ */ new Set([0]));
1401
+ const toggle = (0, import_react6.useCallback)((index) => {
1402
+ setOpenItems((prev) => {
1403
+ const next = new Set(allowMultiple ? prev : []);
1404
+ if (prev.has(index)) next.delete(index);
1405
+ else next.add(index);
1406
+ return next;
1407
+ });
1408
+ }, [allowMultiple]);
1409
+ const itemList = Array.isArray(items) ? items : [];
1410
+ if (itemList.length === 0) {
1411
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, style, children });
1412
+ }
1413
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, style: { border: "1px solid #e2e8f0", borderRadius: 8, overflow: "hidden", ...style }, children: itemList.map((item, i) => {
1414
+ const itm = item;
1415
+ const isOpen = openItems.has(i);
1416
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { borderBottom: i < itemList.length - 1 ? "1px solid #e2e8f0" : "none" }, children: [
1417
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1418
+ "button",
1419
+ {
1420
+ onClick: () => toggle(i),
1421
+ style: {
1422
+ width: "100%",
1423
+ padding: "12px 16px",
1424
+ background: "none",
1425
+ border: "none",
1426
+ textAlign: "left",
1427
+ cursor: "pointer",
1428
+ display: "flex",
1429
+ justifyContent: "space-between",
1430
+ alignItems: "center",
1431
+ fontSize: 14,
1432
+ fontWeight: 500
1433
+ },
1434
+ children: [
1435
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: String(itm.title ?? itm.label ?? `Item ${i + 1}`) }),
1436
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "#a0aec0" }, children: isOpen ? "\u25BE" : "\u25B8" })
1437
+ ]
1438
+ }
1439
+ ),
1440
+ isOpen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "0 16px 12px" }, children: itm.content ? String(itm.content) : null }) : null
1441
+ ] }, i);
1442
+ }) });
1443
+ };
1444
+ Modal = ({ children, open, isOpen, onClose, title, size, id, nodeId, className, style }) => {
1445
+ const modalId = id ?? nodeId;
1446
+ const [eventOpen, setEventOpen] = (0, import_react6.useState)(false);
1447
+ (0, import_react6.useEffect)(() => {
1448
+ if (!modalId) return;
1449
+ const handleOpen = (e) => {
1450
+ const detail = e.detail;
1451
+ if (detail === modalId || detail?.id === modalId) {
1452
+ setEventOpen(true);
1453
+ }
1454
+ };
1455
+ const handleClose = (e) => {
1456
+ const detail = e.detail;
1457
+ if (detail === modalId || detail?.id === modalId) {
1458
+ setEventOpen(false);
1459
+ }
1460
+ };
1461
+ window.addEventListener("openModal", handleOpen);
1462
+ window.addEventListener("closeModal", handleClose);
1463
+ return () => {
1464
+ window.removeEventListener("openModal", handleOpen);
1465
+ window.removeEventListener("closeModal", handleClose);
1466
+ };
1467
+ }, [modalId]);
1468
+ const visible = Boolean(open ?? isOpen ?? eventOpen);
1469
+ (0, import_react6.useEffect)(() => {
1470
+ if (visible) document.body.style.overflow = "hidden";
1471
+ return () => {
1472
+ document.body.style.overflow = "";
1473
+ };
1474
+ }, [visible]);
1475
+ if (!visible) return null;
1476
+ const widthMap = { sm: 400, md: 560, lg: 720, xl: 960, full: 9999 };
1477
+ const maxWidth = widthMap[size ?? "md"] ?? 560;
1478
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1479
+ "div",
1480
+ {
1481
+ style: {
1482
+ position: "fixed",
1483
+ inset: 0,
1484
+ zIndex: 9999,
1485
+ display: "flex",
1486
+ alignItems: "center",
1487
+ justifyContent: "center",
1488
+ background: "rgba(0,0,0,0.4)"
1489
+ },
1490
+ onClick: (e) => {
1491
+ if (e.target === e.currentTarget) {
1492
+ setEventOpen(false);
1493
+ if (typeof onClose === "function") onClose();
1494
+ }
1495
+ },
1496
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1497
+ "div",
1498
+ {
1499
+ className,
1500
+ style: {
1501
+ background: "#fff",
1502
+ borderRadius: 12,
1503
+ padding: 24,
1504
+ maxWidth,
1505
+ width: "90%",
1506
+ maxHeight: "85vh",
1507
+ overflow: "auto",
1508
+ boxShadow: "0 20px 60px rgba(0,0,0,0.2)",
1509
+ ...style
1510
+ },
1511
+ children: [
1512
+ title || onClose ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }, children: [
1513
+ title ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontWeight: 600, fontSize: 18 }, children: String(title) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", {}),
1514
+ typeof onClose === "function" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1515
+ "button",
1516
+ {
1517
+ onClick: () => {
1518
+ setEventOpen(false);
1519
+ onClose();
1520
+ },
1521
+ style: { background: "none", border: "none", fontSize: 20, cursor: "pointer", color: "#a0aec0", padding: 4 },
1522
+ children: "\u2715"
1523
+ }
1524
+ ) : null
1525
+ ] }) : null,
1526
+ children
1527
+ ]
1528
+ }
1529
+ )
1530
+ }
1531
+ );
1532
+ };
1533
+ ScrollArea = ({ children, maxHeight, className, style }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1534
+ "div",
1535
+ {
1536
+ className,
1537
+ style: {
1538
+ overflow: "auto",
1539
+ maxHeight: maxHeight ? Number(maxHeight) : void 0,
1540
+ ...style
1541
+ },
1542
+ children
1543
+ }
1544
+ );
1545
+ }
1546
+ });
1547
+
1548
+ // src/player/atoms/navigation.tsx
1549
+ var navigation_exports = {};
1550
+ __export(navigation_exports, {
1551
+ NavLink: () => NavLink,
1552
+ RoleGuard: () => RoleGuard,
1553
+ Route: () => Route,
1554
+ Router: () => Router,
1555
+ usePlayerRouter: () => usePlayerRouter
1556
+ });
1557
+ function usePlayerRouter() {
1558
+ return (0, import_react7.useContext)(RouterCtx);
1559
+ }
1560
+ function matchPath(pattern, currentPath, exact) {
1561
+ const params = {};
1562
+ const patternParts = pattern.split("/").filter(Boolean);
1563
+ const pathParts = currentPath.split("/").filter(Boolean);
1564
+ if (exact && patternParts.length !== pathParts.length) {
1565
+ return { match: false, params };
1566
+ }
1567
+ if (patternParts.length > pathParts.length) {
1568
+ return { match: false, params };
1569
+ }
1570
+ for (let i = 0; i < patternParts.length; i++) {
1571
+ const pp = patternParts[i];
1572
+ if (pp.startsWith(":")) {
1573
+ params[pp.slice(1)] = pathParts[i];
1574
+ } else if (pp === "*") {
1575
+ return { match: true, params };
1576
+ } else if (pp !== pathParts[i]) {
1577
+ return { match: false, params };
1578
+ }
1579
+ }
1580
+ return { match: true, params };
1581
+ }
1582
+ var import_react7, import_jsx_runtime7, RouterCtx, Router, Route, NavLink, RoleGuard;
1583
+ var init_navigation = __esm({
1584
+ "src/player/atoms/navigation.tsx"() {
1585
+ "use strict";
1586
+ import_react7 = require("react");
1587
+ init_scope_builder();
1588
+ import_jsx_runtime7 = require("react/jsx-runtime");
1589
+ RouterCtx = (0, import_react7.createContext)({
1590
+ path: "/",
1591
+ navigate: () => {
1592
+ },
1593
+ params: {}
1594
+ });
1595
+ Router = ({ children, basePath, className, style }) => {
1596
+ const [path, setPath] = (0, import_react7.useState)(basePath ?? "/");
1597
+ const navigate = (0, import_react7.useCallback)((to) => {
1598
+ setPath(to);
1599
+ }, []);
1600
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RouterCtx.Provider, { value: { path, navigate, params: {} }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className, style, children }) });
1601
+ };
1602
+ Route = ({ children, path: routePath, exact, className, style }) => {
1603
+ const { path } = (0, import_react7.useContext)(RouterCtx);
1604
+ const pattern = routePath ?? "/";
1605
+ const { match, params } = matchPath(pattern, path, exact !== false);
1606
+ if (!match) return null;
1607
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RouterCtx.Provider, { value: { path, navigate: (0, import_react7.useContext)(RouterCtx).navigate, params }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className, style, children }) });
1608
+ };
1609
+ NavLink = ({
1610
+ children,
1611
+ to,
1612
+ label,
1613
+ icon,
1614
+ activeClassName,
1615
+ className,
1616
+ style,
1617
+ onClick
1618
+ }) => {
1619
+ const { path, navigate } = (0, import_react7.useContext)(RouterCtx);
1620
+ const target = to ?? "/";
1621
+ const isActive = path === target || path.startsWith(target + "/");
1622
+ const text = children ?? label;
1623
+ const handleClick = (0, import_react7.useCallback)((e) => {
1624
+ e.preventDefault();
1625
+ navigate(target);
1626
+ if (typeof onClick === "function") onClick(e);
1627
+ }, [navigate, target, onClick]);
1628
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1629
+ "button",
1630
+ {
1631
+ className: `${className ?? ""} ${isActive && activeClassName ? activeClassName : ""}`.trim() || void 0,
1632
+ onClick: handleClick,
1633
+ style: {
1634
+ background: isActive ? "#ebf8ff" : "transparent",
1635
+ color: isActive ? "#2b6cb0" : "#4a5568",
1636
+ border: "none",
1637
+ borderRadius: 6,
1638
+ padding: "6px 12px",
1639
+ fontSize: 14,
1640
+ fontWeight: isActive ? 600 : 400,
1641
+ cursor: "pointer",
1642
+ display: "inline-flex",
1643
+ alignItems: "center",
1644
+ gap: 6,
1645
+ transition: "background 0.15s, color 0.15s",
1646
+ ...style
1647
+ },
1648
+ children: [
1649
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: String(icon) }) : null,
1650
+ text != null ? String(text) : null
1651
+ ]
1652
+ }
1653
+ );
1654
+ };
1655
+ RoleGuard = ({ children, role, roles, fallback }) => {
1656
+ const scope = useScope();
1657
+ const allowed = (0, import_react7.useMemo)(() => {
1658
+ const required = Array.isArray(roles) ? roles : role != null ? [String(role)] : [];
1659
+ if (required.length === 0) return true;
1660
+ const userRoles = scope.$user?.roles ?? [];
1661
+ if (userRoles.length === 0) return false;
1662
+ return required.some((r) => userRoles.includes(r));
1663
+ }, [role, roles, scope.$user]);
1664
+ if (!allowed) {
1665
+ return fallback ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: fallback }) : null;
1666
+ }
1667
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children });
1668
+ };
1669
+ }
1670
+ });
1671
+
1672
+ // src/player/atoms/composition.tsx
1673
+ var composition_exports = {};
1674
+ __export(composition_exports, {
1675
+ ModuleOutlet: () => ModuleOutlet,
1676
+ Slot: () => Slot,
1677
+ SlotRegistryProvider: () => SlotRegistryProvider,
1678
+ useSlotContributions: () => useSlotContributions
1679
+ });
1680
+ function useSlotContributions(name) {
1681
+ const registry = (0, import_react8.useContext)(SlotRegistryContext);
1682
+ return registry.get(name) ?? [];
1683
+ }
1684
+ var import_react8, import_jsx_runtime8, SlotRegistryContext, SlotRegistryProvider, Slot, ModuleOutlet;
1685
+ var init_composition = __esm({
1686
+ "src/player/atoms/composition.tsx"() {
1687
+ "use strict";
1688
+ import_react8 = __toESM(require("react"));
1689
+ import_jsx_runtime8 = require("react/jsx-runtime");
1690
+ SlotRegistryContext = (0, import_react8.createContext)(/* @__PURE__ */ new Map());
1691
+ SlotRegistryProvider = ({ contributions, children }) => {
1692
+ const registry = (0, import_react8.useMemo)(() => {
1693
+ const map = /* @__PURE__ */ new Map();
1694
+ for (const c of contributions) {
1695
+ const list = map.get(c.name) ?? [];
1696
+ list.push(c);
1697
+ map.set(c.name, list);
1698
+ }
1699
+ for (const [, list] of map) {
1700
+ list.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
1701
+ }
1702
+ return map;
1703
+ }, [contributions]);
1704
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SlotRegistryContext.Provider, { value: registry, children });
1705
+ };
1706
+ Slot = ({ children, name, fallback, className, style }) => {
1707
+ const slotName = name ?? "";
1708
+ const contributions = useSlotContributions(slotName);
1709
+ const content = contributions.length > 0 ? contributions.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react8.default.Fragment, { children: c.tree }, i)) : children ?? fallback;
1710
+ if (!content) return null;
1711
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1712
+ "div",
1713
+ {
1714
+ className,
1715
+ "data-slot": slotName,
1716
+ style,
1717
+ children: content
1718
+ }
1719
+ );
1720
+ };
1721
+ ModuleOutlet = ({ children, module: moduleName, basePath, className, style }) => {
1722
+ const moduleKey = moduleName ?? "";
1723
+ const contributions = useSlotContributions(`module:${moduleKey}`);
1724
+ if (contributions.length > 0) {
1725
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1726
+ "div",
1727
+ {
1728
+ className,
1729
+ "data-module": moduleKey,
1730
+ style,
1731
+ children: contributions.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react8.default.Fragment, { children: c.tree }, i))
1732
+ }
1733
+ );
1734
+ }
1735
+ if (children) {
1736
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1737
+ "div",
1738
+ {
1739
+ className,
1740
+ "data-module": moduleKey,
1741
+ style,
1742
+ children
1743
+ }
1744
+ );
1745
+ }
1746
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1747
+ "div",
1748
+ {
1749
+ className,
1750
+ "data-module": moduleKey,
1751
+ style: {
1752
+ padding: 16,
1753
+ border: "1px dashed #cbd5e0",
1754
+ borderRadius: 8,
1755
+ color: "#a0aec0",
1756
+ fontSize: 13,
1757
+ textAlign: "center",
1758
+ ...style
1759
+ },
1760
+ children: [
1761
+ "Module: ",
1762
+ String(moduleName ?? "unknown"),
1763
+ basePath ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
1764
+ " (",
1765
+ String(basePath),
1766
+ ")"
1767
+ ] }) : null
1768
+ ]
1769
+ }
1770
+ );
1771
+ };
1772
+ }
1773
+ });
1774
+
1775
+ // src/player/atoms/data.tsx
1776
+ var data_exports = {};
1777
+ __export(data_exports, {
1778
+ DataGrid: () => DataGrid,
1779
+ Table: () => Table
1780
+ });
1781
+ var import_react9, import_jsx_runtime9, Table, DataGrid;
1782
+ var init_data = __esm({
1783
+ "src/player/atoms/data.tsx"() {
1784
+ "use strict";
1785
+ import_react9 = require("react");
1786
+ import_jsx_runtime9 = require("react/jsx-runtime");
1787
+ Table = ({ data, columns, rows, onRowClick, striped, compact, className, style }) => {
1788
+ const items = Array.isArray(data ?? rows) ? data ?? rows : [];
1789
+ const cols = Array.isArray(columns) ? columns.map(
1790
+ (c) => typeof c === "string" ? { key: c, label: c, header: c } : c
1791
+ ) : items.length > 0 ? Object.keys(items[0]).filter((k) => k !== "id" && !k.startsWith("_")).map((k) => ({ key: k, label: k, header: k })) : [];
1792
+ const pad = compact ? "4px 8px" : "8px 12px";
1793
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className, style: { overflow: "auto", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 14 }, children: [
1794
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { children: cols.map((col, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1795
+ "th",
1796
+ {
1797
+ style: {
1798
+ textAlign: "left",
1799
+ padding: pad,
1800
+ fontWeight: 600,
1801
+ fontSize: 12,
1802
+ color: "#718096",
1803
+ borderBottom: "2px solid #e2e8f0",
1804
+ textTransform: "uppercase",
1805
+ letterSpacing: "0.05em"
1806
+ },
1807
+ children: String(col.label ?? col.header ?? col.key ?? "")
1808
+ },
1809
+ String(col.key ?? i)
1810
+ )) }) }),
1811
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tbody", { children: [
1812
+ items.map((row, ri) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1813
+ "tr",
1814
+ {
1815
+ onClick: typeof onRowClick === "function" ? () => onRowClick(row) : void 0,
1816
+ style: {
1817
+ cursor: typeof onRowClick === "function" ? "pointer" : void 0,
1818
+ background: striped && ri % 2 === 1 ? "#f7fafc" : void 0
1819
+ },
1820
+ children: cols.map((col, ci) => {
1821
+ const val = row[col.key];
1822
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1823
+ "td",
1824
+ {
1825
+ style: { padding: pad, borderBottom: "1px solid #edf2f7" },
1826
+ children: val != null ? String(val) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: "#cbd5e0" }, children: "\u2014" })
1827
+ },
1828
+ String(col.key ?? ci)
1829
+ );
1830
+ })
1831
+ },
1832
+ String(row.id ?? ri)
1833
+ )),
1834
+ items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1835
+ "td",
1836
+ {
1837
+ colSpan: cols.length,
1838
+ style: { padding: "24px 12px", textAlign: "center", color: "#a0aec0", fontStyle: "italic" },
1839
+ children: "No data"
1840
+ }
1841
+ ) }) : null
1842
+ ] })
1843
+ ] }) });
1844
+ };
1845
+ DataGrid = ({ data, columns, onRowClick, searchable, className, style, children }) => {
1846
+ const [search, setSearch] = (0, import_react9.useState)("");
1847
+ const items = Array.isArray(data) ? data : [];
1848
+ const filtered = (0, import_react9.useMemo)(() => {
1849
+ if (!search) return items;
1850
+ const q = search.toLowerCase();
1851
+ return items.filter(
1852
+ (item) => Object.values(item).some((v) => v != null && String(v).toLowerCase().includes(q))
1853
+ );
1854
+ }, [items, search]);
1855
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, style, children: [
1856
+ searchable ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1857
+ "input",
1858
+ {
1859
+ type: "text",
1860
+ placeholder: "Search...",
1861
+ value: search,
1862
+ onChange: (e) => setSearch(e.target.value),
1863
+ style: {
1864
+ padding: "6px 12px",
1865
+ border: "1px solid #e2e8f0",
1866
+ borderRadius: 6,
1867
+ fontSize: 14,
1868
+ width: "100%",
1869
+ boxSizing: "border-box"
1870
+ }
1871
+ }
1872
+ ) }) : null,
1873
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Table, { data: filtered, columns, onRowClick, striped: true }),
1874
+ children
1875
+ ] });
1876
+ };
1877
+ }
1878
+ });
1879
+
1880
+ // src/player/index.ts
1881
+ var player_exports = {};
1882
+ __export(player_exports, {
1883
+ AtomRegistryImpl: () => AtomRegistryImpl,
1884
+ ComponentTreeRenderer: () => ComponentTreeRenderer,
1885
+ DEFAULT_DESIGN_TOKENS: () => DEFAULT_DESIGN_TOKENS,
1886
+ DevPlayer: () => DevPlayer,
1887
+ ExperienceRenderer: () => ExperienceRenderer,
1888
+ PlayerProvider: () => PlayerProvider,
1889
+ ScopeContext: () => ScopeContext,
1890
+ SlotRegistryProvider: () => SlotRegistryProvider,
1891
+ buildActionScope: () => buildActionScope,
1892
+ buildEvalContext: () => buildEvalContext,
1893
+ buildLoopScope: () => buildLoopScope,
1894
+ buildScope: () => buildScope,
1895
+ builtinAtoms: () => builtinAtoms,
1896
+ builtinFunctions: () => builtinFunctions,
1897
+ classifyBinding: () => classifyBinding,
1898
+ createApiResolver: () => createApiResolver,
1899
+ createCoreAtomRegistry: () => createCoreAtomRegistry,
1900
+ evaluateExpression: () => evaluateExpression,
1901
+ mergeRegistries: () => mergeRegistries,
1902
+ mergeScope: () => mergeScope,
1903
+ resolveAllBindings: () => resolveAllBindings,
1904
+ resolveBinding: () => resolveBinding,
1905
+ setWasmModule: () => setWasmModule,
1906
+ usePlayerContext: () => usePlayerContext,
1907
+ usePlayerRouter: () => usePlayerRouter,
1908
+ useScope: () => useScope,
1909
+ useSlotContributions: () => useSlotContributions,
1910
+ useTheme: () => useTheme
1911
+ });
1912
+ module.exports = __toCommonJS(player_exports);
1913
+
1914
+ // src/player/ExperienceRenderer.tsx
1915
+ var import_react12 = __toESM(require("react"));
1916
+ init_scope_builder();
1917
+
1918
+ // src/player/binding-resolver.ts
1919
+ init_expression_engine();
1920
+ function classifyBinding(expr) {
1921
+ const t = expr.trim();
1922
+ const type = classifyExpression(t);
1923
+ switch (type) {
1924
+ case "literal":
1925
+ return { type, value: parseLiteralValue(t) };
1926
+ case "path": {
1927
+ const dotIdx = t.indexOf(".");
1928
+ if (dotIdx === -1) return { type, root: t, rest: "" };
1929
+ return { type, root: t.slice(0, dotIdx), rest: t.slice(dotIdx + 1) };
1930
+ }
1931
+ case "function": {
1932
+ const fnCall = parseFunctionCall(t);
1933
+ if (fnCall) return { type, name: fnCall.name, rawArgs: fnCall.args };
1934
+ return { type, expression: t };
1935
+ }
1936
+ case "action": {
1937
+ const fnCall = parseFunctionCall(t);
1938
+ if (fnCall) return { type, name: fnCall.name, rawArgs: fnCall.args };
1939
+ if (t.startsWith("$action.")) return { type, name: t.slice("$action.".length), rawArgs: [] };
1940
+ return { type, expression: t };
1941
+ }
1942
+ case "condition":
1943
+ if (t.startsWith("$expr(") && t.endsWith(")")) return { type, expression: t.slice(6, -1) };
1944
+ return { type, expression: t };
1945
+ }
1946
+ }
1947
+ function parseLiteralValue(t) {
1948
+ if (t === "[Expression]" || t.includes("[Expression]")) return void 0;
1949
+ if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'")) return t.slice(1, -1);
1950
+ if (/^-?\d+(\.\d+)?$/.test(t)) return Number(t);
1951
+ if (t === "true") return true;
1952
+ if (t === "false") return false;
1953
+ if (t === "null") return null;
1954
+ return void 0;
1955
+ }
1956
+ function parseFunctionCall(expr) {
1957
+ const match = expr.match(/^\$(fn|action)\.(\w+)\((.*)\)$/s);
1958
+ if (!match) return null;
1959
+ const [, namespace, name, argsStr] = match;
1960
+ const args = argsStr.trim() ? splitArgs(argsStr.trim()) : [];
1961
+ return { namespace, name, args };
1962
+ }
1963
+ function splitArgs(argsStr) {
1964
+ const args = [];
1965
+ let current = "";
1966
+ let depth = 0;
1967
+ let inString = null;
1968
+ for (let i = 0; i < argsStr.length; i++) {
1969
+ const ch = argsStr[i];
1970
+ if (inString) {
1971
+ current += ch;
1972
+ if (ch === inString && argsStr[i - 1] !== "\\") inString = null;
1973
+ } else if (ch === '"' || ch === "'") {
1974
+ current += ch;
1975
+ inString = ch;
1976
+ } else if (ch === "(" || ch === "[") {
1977
+ current += ch;
1978
+ depth++;
1979
+ } else if (ch === ")" || ch === "]") {
1980
+ current += ch;
1981
+ depth--;
1982
+ } else if (ch === "," && depth === 0) {
1983
+ args.push(current.trim());
1984
+ current = "";
1985
+ } else {
1986
+ current += ch;
1987
+ }
1988
+ }
1989
+ if (current.trim()) args.push(current.trim());
1990
+ return args;
1991
+ }
1992
+ function resolveBinding(expr, scope) {
1993
+ const binding = classifyBinding(expr);
1994
+ switch (binding.type) {
1995
+ case "literal":
1996
+ return binding.value;
1997
+ case "path":
1998
+ return resolveScopedPath(binding.root, binding.rest, scope);
1999
+ case "function":
2000
+ return resolveFunction(binding.name, binding.rawArgs, scope);
2001
+ case "action":
2002
+ return resolveAction(binding.name, binding.rawArgs, scope);
2003
+ case "condition":
2004
+ return resolveCondition(binding.expression ?? expr, scope);
2005
+ default:
2006
+ return void 0;
2007
+ }
2008
+ }
2009
+ function resolveAllBindings(bindings, scope) {
2010
+ const resolved = {};
2011
+ for (const [propName, expr] of Object.entries(bindings)) {
2012
+ try {
2013
+ resolved[propName] = resolveBinding(expr, scope);
2014
+ } catch {
2015
+ resolved[propName] = void 0;
2016
+ }
2017
+ }
2018
+ return resolved;
2019
+ }
2020
+ function resolveScopedPath(root, rest, scope) {
2021
+ let rootValue;
2022
+ switch (root) {
2023
+ case "$instance":
2024
+ rootValue = scope.$instance;
2025
+ break;
2026
+ case "$instances":
2027
+ rootValue = scope.$instances;
2028
+ break;
2029
+ case "$definition":
2030
+ rootValue = scope.$definition;
2031
+ break;
2032
+ case "$pagination":
2033
+ rootValue = scope.$pagination;
2034
+ break;
2035
+ case "$entity":
2036
+ rootValue = scope.$entity;
2037
+ break;
2038
+ case "$local":
2039
+ rootValue = scope.$local;
2040
+ break;
2041
+ case "$user":
2042
+ rootValue = scope.$user;
2043
+ break;
2044
+ case "$action":
2045
+ rootValue = scope.$action;
2046
+ break;
2047
+ case "$fn":
2048
+ rootValue = scope.$fn;
2049
+ break;
2050
+ case "$item":
2051
+ rootValue = scope.$item;
2052
+ break;
2053
+ case "$index":
2054
+ rootValue = scope.$index;
2055
+ break;
2056
+ default:
2057
+ rootValue = scope[root];
2058
+ if (rootValue === void 0) {
2059
+ rootValue = scope.$item;
2060
+ if (rootValue != null && rest) {
2061
+ return resolvePath(`${root}.${rest}`, { [root]: scope.$item });
2062
+ }
2063
+ }
2064
+ }
2065
+ if (!rest) return rootValue;
2066
+ if (rootValue == null) return void 0;
2067
+ return resolvePath(rest, rootValue);
2068
+ }
2069
+ function resolveFunction(name, rawArgs, scope) {
2070
+ const fn = scope.$fn?.[name] ?? builtinFunctions[name];
2071
+ if (typeof fn !== "function") {
2072
+ console.warn(`[binding-resolver] Unknown function: $fn.${name}`);
2073
+ return void 0;
2074
+ }
2075
+ const resolvedArgs = rawArgs.map((arg) => resolveBinding(arg.trim(), scope));
2076
+ try {
2077
+ return fn(...resolvedArgs);
2078
+ } catch (err) {
2079
+ console.warn(`[binding-resolver] Error calling $fn.${name}:`, err);
2080
+ return void 0;
2081
+ }
2082
+ }
2083
+ function resolveAction(name, rawArgs, scope) {
2084
+ const actions = scope.$action;
2085
+ if (!actions) return void 0;
2086
+ if (rawArgs.length === 0) {
2087
+ const actionFn2 = actions[name];
2088
+ if (typeof actionFn2 === "function") return actionFn2;
2089
+ return void 0;
2090
+ }
2091
+ const actionFn = actions[name];
2092
+ if (typeof actionFn !== "function") return void 0;
2093
+ return (...callArgs) => {
2094
+ const resolvedArgs = rawArgs.map((arg) => resolveBinding(arg.trim(), scope));
2095
+ return actionFn(...resolvedArgs, ...callArgs);
2096
+ };
2097
+ }
2098
+ function resolveCondition(expression, scope) {
2099
+ const context = buildEvalContext(scope);
2100
+ return evaluateExpression(expression, context);
2101
+ }
2102
+ function buildEvalContext(scope) {
2103
+ const ctx = {};
2104
+ ctx.$instance = scope.$instance;
2105
+ ctx.$instances = scope.$instances;
2106
+ ctx.$definition = scope.$definition;
2107
+ ctx.$pagination = scope.$pagination;
2108
+ ctx.$entity = scope.$entity;
2109
+ ctx.$local = scope.$local;
2110
+ ctx.$user = scope.$user;
2111
+ ctx.$action = scope.$action;
2112
+ ctx.$fn = scope.$fn;
2113
+ ctx.$item = scope.$item;
2114
+ ctx.$index = scope.$index;
2115
+ if (scope.$instances) ctx.items = scope.$instances;
2116
+ if (scope.$instance) {
2117
+ ctx.instance = scope.$instance;
2118
+ ctx.loading = false;
2119
+ }
2120
+ if (scope.$item) ctx.item = scope.$item;
2121
+ if (scope.$index != null) ctx.index = scope.$index;
2122
+ if (scope.state_data) ctx.state_data = scope.state_data;
2123
+ if (scope.memory) ctx.memory = scope.memory;
2124
+ if (scope.context) ctx.context = scope.context;
2125
+ return ctx;
2126
+ }
2127
+ function buildActionScope(opts) {
2128
+ const { resolver, instanceId, slug, setLocal, router, toast, refreshQuery, onEvent } = opts;
2129
+ return {
2130
+ transition: async (name, id, data) => {
2131
+ const targetId = id ?? instanceId;
2132
+ if (!targetId) {
2133
+ console.warn("[action] transition called without instanceId");
2134
+ return;
2135
+ }
2136
+ await resolver.transition(targetId, name, data);
2137
+ refreshQuery?.();
2138
+ },
2139
+ create: async (targetSlug, data) => {
2140
+ const id = await resolver.create(targetSlug || slug || "", data);
2141
+ refreshQuery?.();
2142
+ return id;
2143
+ },
2144
+ update: async (id, fields) => {
2145
+ await resolver.update(id, fields);
2146
+ refreshQuery?.();
2147
+ },
2148
+ remove: async (id) => {
2149
+ await resolver.remove(id);
2150
+ refreshQuery?.();
2151
+ },
2152
+ setLocal: (key, value) => {
2153
+ setLocal(key, value);
2154
+ },
2155
+ navigate: (path) => {
2156
+ router?.push(path);
2157
+ },
2158
+ toast: (message, variant) => {
2159
+ toast?.(message, variant);
2160
+ },
2161
+ refreshQuery: (dataSourceName) => {
2162
+ refreshQuery?.(dataSourceName);
2163
+ },
2164
+ scrollTo: (elementId) => {
2165
+ if (typeof document !== "undefined") {
2166
+ const el = document.getElementById(elementId);
2167
+ el?.scrollIntoView({ behavior: "smooth" });
2168
+ }
2169
+ },
2170
+ openModal: (modalId) => {
2171
+ if (typeof window !== "undefined") {
2172
+ window.dispatchEvent(new CustomEvent("player:open_modal", { detail: { id: modalId } }));
2173
+ }
2174
+ },
2175
+ closeModal: (modalId) => {
2176
+ if (typeof window !== "undefined") {
2177
+ window.dispatchEvent(new CustomEvent("player:close_modal", { detail: { id: modalId } }));
2178
+ }
2179
+ },
2180
+ emit: (event, payload) => {
2181
+ onEvent?.(event, payload);
2182
+ }
2183
+ };
2184
+ }
2185
+
2186
+ // src/player/ExperienceRenderer.tsx
2187
+ init_expression_engine();
2188
+
2189
+ // src/player/PlayerProvider.tsx
2190
+ var import_react11 = require("react");
2191
+
2192
+ // src/hooks/useQuery.ts
2193
+ var import_react2 = require("react");
2194
+ var _globalResolver = null;
2195
+ function setQueryResolver(resolver) {
2196
+ _globalResolver = resolver;
2197
+ }
2198
+
2199
+ // src/hooks/useMutation.ts
2200
+ var import_react3 = require("react");
2201
+ var _globalMutationResolver = null;
2202
+ function setMutationResolver(resolver) {
2203
+ _globalMutationResolver = resolver;
2204
+ }
2205
+
2206
+ // src/player/atom-registry.ts
2207
+ var import_react10 = __toESM(require("react"));
2208
+ function namedExport(loader, exportName) {
2209
+ return () => loader().then((mod) => ({ default: mod[exportName] }));
2210
+ }
2211
+ var AtomRegistryImpl = class _AtomRegistryImpl {
2212
+ loaders = /* @__PURE__ */ new Map();
2213
+ lazyCache = /* @__PURE__ */ new Map();
2214
+ eagerCache = /* @__PURE__ */ new Map();
2215
+ register(name, loader) {
2216
+ this.loaders.set(name, loader);
2217
+ this.lazyCache.delete(name);
2218
+ }
2219
+ registerEager(name, component) {
2220
+ this.eagerCache.set(name, component);
2221
+ }
2222
+ resolve(name) {
2223
+ const eager = this.eagerCache.get(name);
2224
+ if (eager) {
2225
+ const cached2 = this.lazyCache.get(name);
2226
+ if (cached2) return cached2;
2227
+ const lazy2 = import_react10.default.lazy(() => Promise.resolve({ default: eager }));
2228
+ this.lazyCache.set(name, lazy2);
2229
+ return lazy2;
2230
+ }
2231
+ const cached = this.lazyCache.get(name);
2232
+ if (cached) return cached;
2233
+ const loader = this.loaders.get(name);
2234
+ if (!loader) return null;
2235
+ const lazy = import_react10.default.lazy(loader);
2236
+ this.lazyCache.set(name, lazy);
2237
+ return lazy;
2238
+ }
2239
+ resolveSync(name) {
2240
+ return this.eagerCache.get(name) ?? null;
2241
+ }
2242
+ has(name) {
2243
+ return this.loaders.has(name) || this.eagerCache.has(name);
2244
+ }
2245
+ list() {
2246
+ const names = /* @__PURE__ */ new Set();
2247
+ for (const k of this.loaders.keys()) names.add(k);
2248
+ for (const k of this.eagerCache.keys()) names.add(k);
2249
+ return Array.from(names).sort();
2250
+ }
2251
+ merge(other) {
2252
+ const merged = new _AtomRegistryImpl();
2253
+ for (const [name, loader] of this.loaders) merged.loaders.set(name, loader);
2254
+ for (const [name, comp] of this.eagerCache) merged.eagerCache.set(name, comp);
2255
+ for (const name of other.list()) {
2256
+ const otherImpl = other;
2257
+ if (otherImpl.loaders?.has(name)) {
2258
+ merged.loaders.set(name, otherImpl.loaders.get(name));
2259
+ }
2260
+ if (otherImpl.eagerCache?.has(name)) {
2261
+ merged.eagerCache.set(name, otherImpl.eagerCache.get(name));
2262
+ }
2263
+ }
2264
+ return merged;
2265
+ }
2266
+ toRecord() {
2267
+ const record = {};
2268
+ for (const name of this.eagerCache.keys()) {
2269
+ record[name] = this.eagerCache.get(name);
2270
+ }
2271
+ return record;
2272
+ }
19
2273
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
2274
+ function createCoreAtomRegistry() {
2275
+ const registry = new AtomRegistryImpl();
2276
+ registry.register("Stack", namedExport(() => Promise.resolve().then(() => (init_layout(), layout_exports)), "Stack"));
2277
+ registry.register("Row", namedExport(() => Promise.resolve().then(() => (init_layout(), layout_exports)), "Row"));
2278
+ registry.register("Grid", namedExport(() => Promise.resolve().then(() => (init_layout(), layout_exports)), "Grid"));
2279
+ registry.register("Column", namedExport(() => Promise.resolve().then(() => (init_layout(), layout_exports)), "Column"));
2280
+ registry.register("Divider", namedExport(() => Promise.resolve().then(() => (init_layout(), layout_exports)), "Divider"));
2281
+ registry.register("Spacer", namedExport(() => Promise.resolve().then(() => (init_layout(), layout_exports)), "Spacer"));
2282
+ registry.register("Text", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Text"));
2283
+ registry.register("Heading", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Heading"));
2284
+ registry.register("Field", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Field"));
2285
+ registry.register("Image", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Image"));
2286
+ registry.register("Badge", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Badge"));
2287
+ registry.register("Icon", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Icon"));
2288
+ registry.register("Button", namedExport(() => Promise.resolve().then(() => (init_actions(), actions_exports)), "Button"));
2289
+ registry.register("Link", namedExport(() => Promise.resolve().then(() => (init_actions(), actions_exports)), "Link"));
2290
+ registry.register("Show", namedExport(() => Promise.resolve().then(() => (init_control_flow(), control_flow_exports)), "Show"));
2291
+ registry.register("Each", namedExport(() => Promise.resolve().then(() => (init_control_flow(), control_flow_exports)), "Each"));
2292
+ registry.register("TextInput", namedExport(() => Promise.resolve().then(() => (init_input(), input_exports)), "TextInput"));
2293
+ registry.register("Input", namedExport(() => Promise.resolve().then(() => (init_input(), input_exports)), "TextInput"));
2294
+ registry.register("Select", namedExport(() => Promise.resolve().then(() => (init_input(), input_exports)), "Select"));
2295
+ registry.register("Toggle", namedExport(() => Promise.resolve().then(() => (init_input(), input_exports)), "Toggle"));
2296
+ registry.register("Slider", namedExport(() => Promise.resolve().then(() => (init_input(), input_exports)), "Slider"));
2297
+ registry.register("Card", namedExport(() => Promise.resolve().then(() => (init_grouping(), grouping_exports)), "Card"));
2298
+ registry.register("Section", namedExport(() => Promise.resolve().then(() => (init_grouping(), grouping_exports)), "Section"));
2299
+ registry.register("Tabs", namedExport(() => Promise.resolve().then(() => (init_grouping(), grouping_exports)), "Tabs"));
2300
+ registry.register("Accordion", namedExport(() => Promise.resolve().then(() => (init_grouping(), grouping_exports)), "Accordion"));
2301
+ registry.register("Modal", namedExport(() => Promise.resolve().then(() => (init_grouping(), grouping_exports)), "Modal"));
2302
+ registry.register("Router", namedExport(() => Promise.resolve().then(() => (init_navigation(), navigation_exports)), "Router"));
2303
+ registry.register("Route", namedExport(() => Promise.resolve().then(() => (init_navigation(), navigation_exports)), "Route"));
2304
+ registry.register("NavLink", namedExport(() => Promise.resolve().then(() => (init_navigation(), navigation_exports)), "NavLink"));
2305
+ registry.register("RoleGuard", namedExport(() => Promise.resolve().then(() => (init_navigation(), navigation_exports)), "RoleGuard"));
2306
+ registry.register("Slot", namedExport(() => Promise.resolve().then(() => (init_composition(), composition_exports)), "Slot"));
2307
+ registry.register("ModuleOutlet", namedExport(() => Promise.resolve().then(() => (init_composition(), composition_exports)), "ModuleOutlet"));
2308
+ registry.register("Markdown", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Markdown"));
2309
+ registry.register("ScrollArea", namedExport(() => Promise.resolve().then(() => (init_grouping(), grouping_exports)), "ScrollArea"));
2310
+ registry.register("Table", namedExport(() => Promise.resolve().then(() => (init_data(), data_exports)), "Table"));
2311
+ registry.register("DataGrid", namedExport(() => Promise.resolve().then(() => (init_data(), data_exports)), "DataGrid"));
2312
+ registry.register("Alert", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Alert"));
2313
+ registry.register("EmptyState", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "EmptyState"));
2314
+ registry.register("Progress", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Progress"));
2315
+ registry.register("Separator", namedExport(() => Promise.resolve().then(() => (init_content(), content_exports)), "Separator"));
2316
+ return registry;
2317
+ }
2318
+ function mergeRegistries(...registries) {
2319
+ let merged = new AtomRegistryImpl();
2320
+ for (const r of registries) {
2321
+ merged = merged.merge(r);
2322
+ }
2323
+ return merged;
2324
+ }
29
2325
 
30
- // src/player/index.ts
31
- var player_exports = {};
32
- __export(player_exports, {
33
- ComponentTreeRenderer: () => ComponentTreeRenderer,
34
- DevPlayer: () => DevPlayer,
35
- builtinAtoms: () => builtinAtoms,
36
- containsExpression: () => containsExpression,
37
- evaluateExpression: () => evaluateExpression,
38
- evaluateProp: () => evaluateProp
39
- });
40
- module.exports = __toCommonJS(player_exports);
2326
+ // src/player/theme.ts
2327
+ var DEFAULT_DESIGN_TOKENS = {
2328
+ // Colors
2329
+ "token:primary": "#3182ce",
2330
+ "token:primary-hover": "#2b6cb0",
2331
+ "token:primary-light": "#ebf8ff",
2332
+ "token:secondary": "#718096",
2333
+ "token:secondary-hover": "#4a5568",
2334
+ "token:accent": "#805ad5",
2335
+ "token:success": "#38a169",
2336
+ "token:warning": "#dd6b20",
2337
+ "token:error": "#e53e3e",
2338
+ "token:info": "#3182ce",
2339
+ // Surfaces
2340
+ "token:surface": "#ffffff",
2341
+ "token:surface-hover": "#f7fafc",
2342
+ "token:surface-secondary": "#edf2f7",
2343
+ "token:background": "#f7fafc",
2344
+ "token:card": "#ffffff",
2345
+ "token:overlay": "rgba(0, 0, 0, 0.4)",
2346
+ // Borders
2347
+ "token:border": "#e2e8f0",
2348
+ "token:border-light": "#edf2f7",
2349
+ "token:border-focus": "#3182ce",
2350
+ // Text
2351
+ "token:text": "#1a202c",
2352
+ "token:text-secondary": "#718096",
2353
+ "token:text-muted": "#a0aec0",
2354
+ "token:text-inverse": "#ffffff",
2355
+ "token:text-link": "#3182ce",
2356
+ // Shadows
2357
+ "token:shadow-sm": "0 1px 2px rgba(0, 0, 0, 0.05)",
2358
+ "token:shadow": "0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06)",
2359
+ "token:shadow-md": "0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06)",
2360
+ "token:shadow-lg": "0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.05)",
2361
+ // Spacing
2362
+ "token:spacing-xs": "4px",
2363
+ "token:spacing-sm": "8px",
2364
+ "token:spacing-md": "16px",
2365
+ "token:spacing-lg": "24px",
2366
+ "token:spacing-xl": "32px",
2367
+ // Radius
2368
+ "token:radius-sm": "4px",
2369
+ "token:radius": "6px",
2370
+ "token:radius-md": "8px",
2371
+ "token:radius-lg": "12px",
2372
+ "token:radius-full": "9999px"
2373
+ };
41
2374
 
42
- // src/player/ComponentTreeRenderer.tsx
43
- var import_react = __toESM(require("react"));
2375
+ // src/player/PlayerProvider.tsx
2376
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2377
+ var PlayerContext = (0, import_react11.createContext)(null);
2378
+ function usePlayerContext() {
2379
+ return (0, import_react11.useContext)(PlayerContext);
2380
+ }
2381
+ var ThemeContext = (0, import_react11.createContext)(DEFAULT_DESIGN_TOKENS);
2382
+ function useTheme() {
2383
+ return (0, import_react11.useContext)(ThemeContext);
2384
+ }
2385
+ var PlayerProvider = ({
2386
+ resolver,
2387
+ atomRegistry: userAtomRegistry,
2388
+ auth,
2389
+ router,
2390
+ toast,
2391
+ onEvent,
2392
+ theme: userTheme,
2393
+ children
2394
+ }) => {
2395
+ const atomRegistry = (0, import_react11.useMemo)(
2396
+ () => userAtomRegistry ?? createCoreAtomRegistry(),
2397
+ [userAtomRegistry]
2398
+ );
2399
+ const mergedTheme = (0, import_react11.useMemo)(
2400
+ () => userTheme ? { ...DEFAULT_DESIGN_TOKENS, ...userTheme } : DEFAULT_DESIGN_TOKENS,
2401
+ [userTheme]
2402
+ );
2403
+ const resolverRef = (0, import_react11.useRef)(resolver);
2404
+ resolverRef.current = resolver;
2405
+ (0, import_react11.useEffect)(() => {
2406
+ if (!resolver) return;
2407
+ setQueryResolver({
2408
+ query: async (_slug, params) => {
2409
+ const r = resolverRef.current;
2410
+ if (!r) return { data: [] };
2411
+ const result = await r.query(_slug, {
2412
+ state: params.state,
2413
+ filter: params.filter,
2414
+ limit: params.limit,
2415
+ offset: params.offset,
2416
+ search: params.search,
2417
+ searchFields: params.searchFields,
2418
+ sort: params.sort
2419
+ });
2420
+ return { data: result.data, total: result.total };
2421
+ }
2422
+ });
2423
+ setMutationResolver({
2424
+ create: async (_slug, input) => {
2425
+ const r = resolverRef.current;
2426
+ if (!r) throw new Error("No resolver");
2427
+ return r.create(_slug, input);
2428
+ },
2429
+ update: async (_slug, instanceId, fields) => {
2430
+ const r = resolverRef.current;
2431
+ if (!r) throw new Error("No resolver");
2432
+ await r.update(instanceId, fields);
2433
+ },
2434
+ transition: async (_slug, instanceId, transitionName, input) => {
2435
+ const r = resolverRef.current;
2436
+ if (!r) throw new Error("No resolver");
2437
+ await r.transition(instanceId, transitionName, input);
2438
+ },
2439
+ remove: async (_slug, instanceId) => {
2440
+ const r = resolverRef.current;
2441
+ if (!r) throw new Error("No resolver");
2442
+ await r.remove(instanceId);
2443
+ }
2444
+ });
2445
+ return () => {
2446
+ setQueryResolver(null);
2447
+ setMutationResolver(null);
2448
+ };
2449
+ }, [resolver]);
2450
+ const value = (0, import_react11.useMemo)(() => ({
2451
+ resolver: resolver ?? null,
2452
+ atomRegistry,
2453
+ auth,
2454
+ router,
2455
+ toast,
2456
+ onEvent
2457
+ }), [resolver, atomRegistry, auth, router, toast, onEvent]);
2458
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PlayerContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ThemeContext.Provider, { value: mergedTheme, children }) });
2459
+ };
44
2460
 
45
- // src/player/evaluator.ts
46
- var EXPR_PATTERN = /\{\{(.+?)\}\}/g;
47
- function containsExpression(value) {
48
- return typeof value === "string" && EXPR_PATTERN.test(value);
2461
+ // src/player/ExperienceRenderer.tsx
2462
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2463
+ var SharedLocalContext = import_react12.default.createContext({
2464
+ state: {},
2465
+ setLocal: () => {
2466
+ }
2467
+ });
2468
+ function useSharedLocal() {
2469
+ return import_react12.default.useContext(SharedLocalContext);
49
2470
  }
50
- function resolvePath(path, scope) {
51
- const parts = path.trim().split(".");
52
- let current = scope;
53
- for (const part of parts) {
54
- if (current == null || typeof current !== "object") return void 0;
55
- current = current[part];
2471
+ var NodeErrorBoundary = class extends import_react12.default.Component {
2472
+ constructor(props) {
2473
+ super(props);
2474
+ this.state = { hasError: false };
56
2475
  }
57
- return current;
2476
+ static getDerivedStateFromError(error) {
2477
+ return { hasError: true, error };
2478
+ }
2479
+ componentDidCatch(error, info) {
2480
+ console.error(`[ExperienceRenderer] Error in node ${this.props.nodeId}:`, error, info);
2481
+ }
2482
+ render() {
2483
+ if (this.state.hasError) {
2484
+ return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { padding: 8, background: "#fff5f5", border: "1px solid #fed7d7", borderRadius: 6, fontSize: 12, color: "#c53030" }, children: [
2485
+ "Error: ",
2486
+ this.state.error?.message ?? "Render failed"
2487
+ ] });
2488
+ }
2489
+ return this.props.children;
2490
+ }
2491
+ };
2492
+ function useDataSources(dataSources, resolver, scope) {
2493
+ const [results, setResults] = (0, import_react12.useState)({});
2494
+ const mountedRef = (0, import_react12.useRef)(true);
2495
+ (0, import_react12.useEffect)(() => {
2496
+ mountedRef.current = true;
2497
+ return () => {
2498
+ mountedRef.current = false;
2499
+ };
2500
+ }, []);
2501
+ (0, import_react12.useEffect)(() => {
2502
+ if (!dataSources?.length || !resolver) return;
2503
+ const loading = {};
2504
+ for (const ds of dataSources) {
2505
+ loading[ds.name] = { loading: true, error: null };
2506
+ }
2507
+ setResults(loading);
2508
+ const fetchAll = async () => {
2509
+ const entries = await Promise.all(
2510
+ dataSources.map(async (ds) => {
2511
+ try {
2512
+ const result = await fetchDataSource(ds, resolver, scope);
2513
+ return [ds.name, result];
2514
+ } catch (err) {
2515
+ return [ds.name, { loading: false, error: err instanceof Error ? err : new Error(String(err)) }];
2516
+ }
2517
+ })
2518
+ );
2519
+ if (mountedRef.current) {
2520
+ setResults(Object.fromEntries(entries));
2521
+ }
2522
+ };
2523
+ fetchAll();
2524
+ }, [dataSources, resolver]);
2525
+ return results;
58
2526
  }
59
- function evaluateExpression(expr, scopes) {
60
- const trimmed = expr.trim();
61
- if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
62
- return trimmed.slice(1, -1);
2527
+ async function fetchDataSource(ds, resolver, scope) {
2528
+ switch (ds.type) {
2529
+ case "workflow": {
2530
+ const slug = ds.slug ?? "";
2531
+ if (!slug) return { loading: false, error: new Error("workflow dataSource missing slug") };
2532
+ const queryResult = await resolver.query(slug, {
2533
+ state: ds.filter?.current_state,
2534
+ filter: ds.filter,
2535
+ limit: ds.pageSize ?? 20,
2536
+ page: scope.$local?.[ds.pageKey ?? "page"] ?? 1,
2537
+ search: ds.search ? interpolateTemplate(ds.search, scope) : void 0,
2538
+ searchFields: ds.searchFields,
2539
+ sort: ds.sort,
2540
+ facets: ds.facets,
2541
+ entity: ds.entity,
2542
+ includeDefinition: ds.includeDefinition,
2543
+ parentInstanceId: ds.parentInstanceId ? interpolateTemplate(ds.parentInstanceId, scope) : void 0
2544
+ });
2545
+ const result = {
2546
+ instances: queryResult.data,
2547
+ loading: false,
2548
+ error: null
2549
+ };
2550
+ if (queryResult.data.length === 1 && ds.query !== "list") {
2551
+ result.instance = queryResult.data[0];
2552
+ }
2553
+ if (queryResult.definition) result.definition = queryResult.definition;
2554
+ if (queryResult.total != null) {
2555
+ result.pagination = {
2556
+ total: queryResult.total,
2557
+ page: queryResult.page,
2558
+ pageSize: queryResult.pageSize
2559
+ };
2560
+ }
2561
+ if (queryResult.facets) result.facets = queryResult.facets;
2562
+ if (queryResult.aggregates) result.aggregates = queryResult.aggregates;
2563
+ if (ds.autoStart && queryResult.data.length === 0) {
2564
+ try {
2565
+ const id = await resolver.create(slug, ds.initialData);
2566
+ const instance = await resolver.getInstance(id);
2567
+ result.instance = instance;
2568
+ result.instances = [instance];
2569
+ } catch {
2570
+ }
2571
+ }
2572
+ return result;
2573
+ }
2574
+ case "api": {
2575
+ if (!resolver.fetch) return { loading: false, error: new Error("API datasource: resolver.fetch not implemented") };
2576
+ const endpoint = interpolateTemplate(ds.endpoint, scope);
2577
+ const raw = await resolver.fetch(endpoint, {
2578
+ method: ds.method,
2579
+ body: ds.body,
2580
+ headers: ds.headers
2581
+ });
2582
+ const mapped = mapApiResponse(raw, ds.mapping);
2583
+ return { instances: mapped.items, loading: false, error: null, pagination: mapped.pagination };
2584
+ }
2585
+ case "static": {
2586
+ const data = ds.data;
2587
+ if (Array.isArray(data)) {
2588
+ return {
2589
+ instances: data.map((d, i) => ({
2590
+ id: String(d.id ?? i),
2591
+ state: "static",
2592
+ fields: d
2593
+ })),
2594
+ loading: false,
2595
+ error: null
2596
+ };
2597
+ }
2598
+ return {
2599
+ instance: { id: "static", state: "static", fields: data },
2600
+ loading: false,
2601
+ error: null
2602
+ };
2603
+ }
2604
+ case "ref": {
2605
+ const ctx = buildEvalContext(scope);
2606
+ const resolved = evaluateExpression(ds.expression, ctx);
2607
+ if (Array.isArray(resolved)) {
2608
+ return {
2609
+ instances: resolved.map((item, i) => ({
2610
+ id: String(item?.id ?? i),
2611
+ state: String(item?.state ?? "ref"),
2612
+ fields: item && typeof item === "object" ? item : { value: item }
2613
+ })),
2614
+ loading: false,
2615
+ error: null
2616
+ };
2617
+ }
2618
+ if (resolved != null && typeof resolved === "object") {
2619
+ const obj = resolved;
2620
+ return {
2621
+ instance: {
2622
+ id: String(obj.id ?? "ref"),
2623
+ state: String(obj.state ?? "ref"),
2624
+ fields: obj
2625
+ },
2626
+ loading: false,
2627
+ error: null
2628
+ };
2629
+ }
2630
+ return { loading: false, error: null };
2631
+ }
2632
+ default:
2633
+ return { loading: false, error: new Error(`Unknown dataSource type: ${ds.type}`) };
2634
+ }
2635
+ }
2636
+ function interpolateTemplate(template, scope) {
2637
+ return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, path) => {
2638
+ const val = resolveBinding(`$${path}`, scope) ?? resolveBinding(path, scope);
2639
+ return val != null ? String(val) : "";
2640
+ });
2641
+ }
2642
+ function mapApiResponse(raw, mapping) {
2643
+ if (!raw || typeof raw !== "object") return { items: [] };
2644
+ const obj = raw;
2645
+ let items;
2646
+ if (mapping?.items || mapping?.data) {
2647
+ items = obj[mapping.items ?? mapping.data ?? "data"] ?? [];
2648
+ } else if (Array.isArray(raw)) {
2649
+ items = raw;
2650
+ } else if (Array.isArray(obj.data)) {
2651
+ items = obj.data;
2652
+ } else if (Array.isArray(obj.items)) {
2653
+ items = obj.items;
2654
+ } else {
2655
+ items = [raw];
2656
+ }
2657
+ const result = items.map((item, i) => ({
2658
+ id: String(item?.id ?? i),
2659
+ state: String(item?.state ?? "unknown"),
2660
+ fields: item ?? {}
2661
+ }));
2662
+ let pagination;
2663
+ const total = mapping?.total ? obj[mapping.total] : obj.total;
2664
+ if (total != null) {
2665
+ pagination = { total: Number(total), page: Number(obj.page ?? 1), pageSize: Number(obj.pageSize ?? items.length) };
2666
+ }
2667
+ return { items: result, pagination };
2668
+ }
2669
+ function resolveTokens(value, tokens) {
2670
+ if (typeof value === "string" && value.startsWith("token:")) {
2671
+ return tokens[value] ?? value;
2672
+ }
2673
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2674
+ const resolved = {};
2675
+ for (const [k, v] of Object.entries(value)) {
2676
+ resolved[k] = resolveTokens(v, tokens);
2677
+ }
2678
+ return resolved;
2679
+ }
2680
+ return value;
2681
+ }
2682
+ var NodeRenderer = ({ node, fallback }) => {
2683
+ const parentScope = useScope();
2684
+ const playerCtx = usePlayerContext();
2685
+ const resolver = playerCtx?.resolver ?? null;
2686
+ const atomRegistry = playerCtx?.atomRegistry;
2687
+ const themeTokens = useTheme();
2688
+ const sharedLocal = useSharedLocal();
2689
+ const localDefaults = node.config?.localDefaults ?? {};
2690
+ (0, import_react12.useEffect)(() => {
2691
+ if (Object.keys(localDefaults).length > 0) {
2692
+ for (const [key, value] of Object.entries(localDefaults)) {
2693
+ if (sharedLocal.state[key] === void 0) {
2694
+ sharedLocal.setLocal(key, value);
2695
+ }
2696
+ }
2697
+ }
2698
+ }, []);
2699
+ const localState = sharedLocal.state;
2700
+ const handleSetLocal = sharedLocal.setLocal;
2701
+ const [, setFetchVersion] = (0, import_react12.useState)(0);
2702
+ const handleRefreshQuery = (0, import_react12.useCallback)(() => {
2703
+ setFetchVersion((v) => v + 1);
2704
+ }, []);
2705
+ const dsResults = useDataSources(node.dataSources, resolver, parentScope);
2706
+ const primaryInstance = Object.values(dsResults).find((r) => r.instance)?.instance;
2707
+ const primarySlug = node.dataSources?.find((ds) => ds.type === "workflow")?.slug;
2708
+ const actionScope = (0, import_react12.useMemo)(() => {
2709
+ if (!resolver) {
2710
+ return {
2711
+ transition: async () => {
2712
+ },
2713
+ create: async () => "",
2714
+ update: async () => {
2715
+ },
2716
+ remove: async () => {
2717
+ },
2718
+ setLocal: handleSetLocal,
2719
+ navigate: () => {
2720
+ },
2721
+ toast: () => {
2722
+ },
2723
+ refreshQuery: handleRefreshQuery,
2724
+ scrollTo: () => {
2725
+ },
2726
+ openModal: () => {
2727
+ },
2728
+ closeModal: () => {
2729
+ },
2730
+ emit: () => {
2731
+ }
2732
+ };
2733
+ }
2734
+ return buildActionScope({
2735
+ resolver,
2736
+ instanceId: primaryInstance?.id,
2737
+ slug: primarySlug,
2738
+ setLocal: handleSetLocal,
2739
+ router: playerCtx?.router,
2740
+ toast: playerCtx?.toast,
2741
+ refreshQuery: handleRefreshQuery,
2742
+ onEvent: playerCtx?.onEvent
2743
+ });
2744
+ }, [resolver, primaryInstance?.id, primarySlug, handleSetLocal, handleRefreshQuery, playerCtx]);
2745
+ const scope = (0, import_react12.useMemo)(() => buildScope({
2746
+ dataSources: dsResults,
2747
+ localState,
2748
+ auth: playerCtx?.auth,
2749
+ entity: node.dataSources?.find((ds) => ds.type === "workflow")?.entity,
2750
+ parentScope,
2751
+ actionScope
2752
+ }), [dsResults, localState, parentScope, actionScope, playerCtx?.auth]);
2753
+ const enrichedScope = (0, import_react12.useMemo)(() => {
2754
+ const handleCreate = () => {
2755
+ if (primarySlug && resolver) {
2756
+ resolver.create(primarySlug).then(() => handleRefreshQuery());
2757
+ }
2758
+ };
2759
+ const setSearch = (e) => {
2760
+ const val = typeof e === "object" && e !== null && "target" in e ? e.target.value : String(e ?? "");
2761
+ handleSetLocal("search", val);
2762
+ };
2763
+ const enrichedAction = {
2764
+ ...scope.$action,
2765
+ handleCreate,
2766
+ setSearch
2767
+ };
2768
+ const enrichedInstance = scope.$instance ? { ...scope.$instance, handleCreate, setSearch } : void 0;
2769
+ return {
2770
+ ...scope,
2771
+ $action: enrichedAction,
2772
+ $instance: enrichedInstance,
2773
+ // Also add at top-level for direct access
2774
+ handleCreate,
2775
+ setSearch
2776
+ };
2777
+ }, [scope, primarySlug, resolver, handleRefreshQuery, handleSetLocal]);
2778
+ if (node.visible_when) {
2779
+ const ctx = buildEvalContext(enrichedScope);
2780
+ const visible = evaluateExpression(node.visible_when, ctx);
2781
+ if (!visible) return null;
63
2782
  }
64
- if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
65
- return Number(trimmed);
2783
+ if (node.$if) {
2784
+ const ctx = buildEvalContext(enrichedScope);
2785
+ const visible = evaluateExpression(node.$if, ctx);
2786
+ if (!visible) return null;
2787
+ }
2788
+ const resolvedBindings = node.bindings ? resolveAllBindings(node.bindings, enrichedScope) : {};
2789
+ const config = node.config ?? node.props ?? {};
2790
+ const rawMerged = { ...config, ...resolvedBindings };
2791
+ const mergedProps = {};
2792
+ for (const [k, v] of Object.entries(rawMerged)) {
2793
+ mergedProps[k] = resolveTokens(v, themeTokens);
2794
+ }
2795
+ if (node.className) mergedProps.className = node.className;
2796
+ if (node.id) mergedProps["data-node-id"] = node.id;
2797
+ const loadingAny = Object.values(dsResults).some((r) => r.loading);
2798
+ if (Object.keys(dsResults).length > 0) {
2799
+ mergedProps.loading = loadingAny;
2800
+ const firstResult = Object.values(dsResults)[0];
2801
+ if (firstResult?.instances) mergedProps.data = firstResult.instances;
2802
+ if (firstResult?.instance) mergedProps.instance = firstResult.instance;
2803
+ if (firstResult?.pagination) mergedProps.pagination = firstResult.pagination;
2804
+ if (firstResult?.definition) mergedProps.definition = firstResult.definition;
2805
+ }
2806
+ const componentName = node.component ?? node.type ?? "";
2807
+ let AtomComponent = null;
2808
+ if (atomRegistry) {
2809
+ const lazy = atomRegistry.resolve(componentName);
2810
+ if (lazy) AtomComponent = lazy;
2811
+ }
2812
+ if (!AtomComponent) {
2813
+ if (!componentName && node.children?.length) {
2814
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeContext.Provider, { value: enrichedScope, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: node.className, style: node.style, children: node.children.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeErrorBoundary, { nodeId: child.id, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeRenderer, { node: child, fallback }) }, child.id ?? i)) }) });
2815
+ }
2816
+ if (componentName) {
2817
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { border: "1px dashed #e53e3e", borderRadius: 6, padding: "8px 12px", margin: 4, fontSize: 13, color: "#e53e3e", background: "#fff5f5" }, children: [
2818
+ "Unknown: ",
2819
+ componentName
2820
+ ] });
2821
+ }
2822
+ return null;
66
2823
  }
67
- if (trimmed === "true") return true;
68
- if (trimmed === "false") return false;
69
- if (trimmed === "null" || trimmed === "undefined") return void 0;
70
- const flatScope = { ...scopes };
71
- if (scopes.state_data && typeof scopes.state_data === "object") {
72
- Object.assign(flatScope, scopes.state_data);
2824
+ let children = null;
2825
+ if (node.children?.length) {
2826
+ children = node.children.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeErrorBoundary, { nodeId: child.id, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeRenderer, { node: child, fallback }) }, child.id ?? i));
2827
+ }
2828
+ if (!children && mergedProps.children != null) {
2829
+ children = mergedProps.children;
2830
+ delete mergedProps.children;
73
2831
  }
74
- if (scopes.context && typeof scopes.context === "object") {
75
- Object.assign(flatScope, scopes.context);
2832
+ delete mergedProps.localDefaults;
2833
+ delete mergedProps.dataSources;
2834
+ delete mergedProps.bindings;
2835
+ delete mergedProps.visible_when;
2836
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeContext.Provider, { value: enrichedScope, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeErrorBoundary, { nodeId: node.id, fallback, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react12.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { padding: 8, color: "#a0aec0", fontSize: 13 }, children: [
2837
+ "Loading ",
2838
+ componentName,
2839
+ "..."
2840
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(AtomComponent, { ...mergedProps, children }) }) }) });
2841
+ };
2842
+ var ExperienceRenderer = ({
2843
+ tree,
2844
+ initialScope,
2845
+ entity,
2846
+ fallback,
2847
+ className
2848
+ }) => {
2849
+ const playerCtx = usePlayerContext();
2850
+ const nodes = Array.isArray(tree) ? tree : [tree];
2851
+ const [sharedLocalState, setSharedLocalState] = (0, import_react12.useState)({});
2852
+ const handleSharedSetLocal = (0, import_react12.useCallback)((key, value) => {
2853
+ setSharedLocalState((prev) => ({ ...prev, [key]: value }));
2854
+ }, []);
2855
+ const sharedLocal = (0, import_react12.useMemo)(() => ({
2856
+ state: sharedLocalState,
2857
+ setLocal: handleSharedSetLocal
2858
+ }), [sharedLocalState, handleSharedSetLocal]);
2859
+ const rootScope = (0, import_react12.useMemo)(() => buildScope({
2860
+ auth: playerCtx?.auth ?? initialScope?.auth,
2861
+ entity,
2862
+ localState: initialScope?.$local ?? {},
2863
+ actionScope: initialScope?.$action ?? {
2864
+ transition: async () => {
2865
+ },
2866
+ create: async () => "",
2867
+ update: async () => {
2868
+ },
2869
+ remove: async () => {
2870
+ },
2871
+ setLocal: () => {
2872
+ },
2873
+ navigate: () => {
2874
+ },
2875
+ toast: () => {
2876
+ },
2877
+ refreshQuery: () => {
2878
+ },
2879
+ scrollTo: () => {
2880
+ },
2881
+ openModal: () => {
2882
+ },
2883
+ closeModal: () => {
2884
+ },
2885
+ emit: () => {
2886
+ }
2887
+ }
2888
+ }), [playerCtx?.auth, entity, initialScope]);
2889
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SharedLocalContext.Provider, { value: sharedLocal, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeContext.Provider, { value: rootScope, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className, children: nodes.map((node, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeErrorBoundary, { nodeId: node.id, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeRenderer, { node, fallback }) }, node.id ?? i)) }) }) });
2890
+ };
2891
+
2892
+ // src/player/resolver.ts
2893
+ function getToken(token) {
2894
+ if (!token) return null;
2895
+ if (typeof token === "function") return token();
2896
+ return token;
2897
+ }
2898
+ function normalizeInstance(raw) {
2899
+ return {
2900
+ id: String(raw.id ?? ""),
2901
+ state: String(raw.current_state ?? raw.state ?? "unknown"),
2902
+ fields: raw.state_data ?? raw.fields ?? {},
2903
+ slug: raw.definition_slug,
2904
+ created_at: raw.created_at,
2905
+ updated_at: raw.updated_at,
2906
+ ...raw
2907
+ };
2908
+ }
2909
+ function createApiResolver(config) {
2910
+ const { baseUrl, defaults } = config;
2911
+ const fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
2912
+ const defCache = /* @__PURE__ */ new Map();
2913
+ async function apiRequest(path, options = {}) {
2914
+ const tok = getToken(config.token);
2915
+ const headers = {
2916
+ "Content-Type": "application/json",
2917
+ ...options.headers ?? {}
2918
+ };
2919
+ if (tok) headers["Authorization"] = `Bearer ${tok}`;
2920
+ const response = await fetchFn(`${baseUrl}${path}`, {
2921
+ ...options,
2922
+ headers
2923
+ });
2924
+ if (!response.ok) {
2925
+ const body = await response.text().catch(() => "");
2926
+ let message = `API error ${response.status}: ${response.statusText}`;
2927
+ try {
2928
+ const parsed = JSON.parse(body);
2929
+ if (parsed.message) message = parsed.message;
2930
+ if (parsed.error) message = `${parsed.error}: ${parsed.message || ""}`;
2931
+ } catch {
2932
+ }
2933
+ throw new Error(message);
2934
+ }
2935
+ return response.json();
76
2936
  }
77
- return resolvePath(trimmed, flatScope);
2937
+ const resolver = {
2938
+ async query(slug, params) {
2939
+ const searchParams = new URLSearchParams();
2940
+ searchParams.set("definition", slug);
2941
+ if (params.state) {
2942
+ const states = Array.isArray(params.state) ? params.state : [params.state];
2943
+ states.forEach((s) => searchParams.append("state", s));
2944
+ }
2945
+ if (params.status) searchParams.set("status", params.status);
2946
+ if (params.limit ?? defaults?.limit) searchParams.set("limit", String(params.limit ?? defaults?.limit ?? 20));
2947
+ if (params.page) searchParams.set("page", String(params.page));
2948
+ if (params.offset) searchParams.set("offset", String(params.offset));
2949
+ if (params.search) searchParams.set("search", params.search);
2950
+ if (params.searchFields?.length) searchParams.set("search_fields", params.searchFields.join(","));
2951
+ if (params.sort) {
2952
+ if (typeof params.sort === "string") {
2953
+ searchParams.set("sort", params.sort);
2954
+ } else if (Array.isArray(params.sort)) {
2955
+ const sortStr = params.sort.map((s) => `${s.direction === "desc" ? "-" : ""}${s.field}`).join(",");
2956
+ searchParams.set("sort", sortStr);
2957
+ }
2958
+ }
2959
+ if (params.filter) {
2960
+ searchParams.set("state_filter", JSON.stringify(params.filter));
2961
+ }
2962
+ if (params.facets?.length) {
2963
+ searchParams.set("facets", params.facets.join(","));
2964
+ }
2965
+ if (params.entity) {
2966
+ searchParams.set("entity_type", params.entity.type);
2967
+ searchParams.set("entity_id", params.entity.id);
2968
+ }
2969
+ if (params.parentInstanceId) {
2970
+ searchParams.set("spawned_by_instance_id", params.parentInstanceId);
2971
+ }
2972
+ if (params.includeDefinition) {
2973
+ searchParams.set("include_definition", "true");
2974
+ }
2975
+ const raw = await apiRequest(
2976
+ `/workflow/instances?${searchParams.toString()}`
2977
+ );
2978
+ const items = raw.items ?? raw.data ?? [];
2979
+ const total = Number(raw.total ?? raw.count ?? items.length);
2980
+ const page = Number(raw.page ?? params.page ?? 1);
2981
+ const pageSize = Number(raw.page_size ?? raw.pageSize ?? params.limit ?? defaults?.limit ?? 20);
2982
+ const result = {
2983
+ data: items.map(normalizeInstance),
2984
+ total,
2985
+ page,
2986
+ pageSize
2987
+ };
2988
+ if (raw.definition) result.definition = raw.definition;
2989
+ if (raw.facets) result.facets = raw.facets;
2990
+ if (raw.aggregates) result.aggregates = raw.aggregates;
2991
+ if (raw.grouped) result.grouped = raw.grouped;
2992
+ return result;
2993
+ },
2994
+ async getInstance(id) {
2995
+ const raw = await apiRequest(`/workflow/instances/${id}`);
2996
+ return normalizeInstance(raw);
2997
+ },
2998
+ async getDefinition(slug) {
2999
+ const cached = defCache.get(slug);
3000
+ if (cached && cached.expires > Date.now()) return cached.data;
3001
+ const raw = await apiRequest(`/workflow/definitions/slug/${slug}`);
3002
+ defCache.set(slug, { data: raw, expires: Date.now() + 5 * 60 * 1e3 });
3003
+ return raw;
3004
+ },
3005
+ async create(slug, data) {
3006
+ const raw = await apiRequest("/workflow/instances", {
3007
+ method: "POST",
3008
+ body: JSON.stringify({
3009
+ definition_slug: slug,
3010
+ state_data: data ?? {}
3011
+ })
3012
+ });
3013
+ return String(raw.id);
3014
+ },
3015
+ async update(id, fields) {
3016
+ await apiRequest(`/workflow/instances/${id}/state-data`, {
3017
+ method: "PATCH",
3018
+ body: JSON.stringify(fields)
3019
+ });
3020
+ },
3021
+ async transition(id, name, data) {
3022
+ const raw = await apiRequest(
3023
+ `/workflow/instances/${id}/transitions/${name}`,
3024
+ {
3025
+ method: "POST",
3026
+ body: JSON.stringify({ data: data ?? {} })
3027
+ }
3028
+ );
3029
+ return raw;
3030
+ },
3031
+ async remove(id) {
3032
+ await apiRequest(`/workflow/instances/${id}`, { method: "DELETE" });
3033
+ },
3034
+ async availableTransitions(id) {
3035
+ const raw = await apiRequest(`/workflow/instances/${id}/transitions`);
3036
+ return Array.isArray(raw) ? raw : [];
3037
+ },
3038
+ async fetch(endpoint, fetchConfig) {
3039
+ return apiRequest(endpoint, {
3040
+ method: fetchConfig.method ?? "GET",
3041
+ body: fetchConfig.body ? JSON.stringify(fetchConfig.body) : void 0,
3042
+ headers: fetchConfig.headers
3043
+ });
3044
+ }
3045
+ };
3046
+ return resolver;
3047
+ }
3048
+
3049
+ // src/player/index.ts
3050
+ init_expression_engine();
3051
+ init_scope_builder();
3052
+ init_composition();
3053
+ init_navigation();
3054
+
3055
+ // src/player/ComponentTreeRenderer.tsx
3056
+ var import_react13 = __toESM(require("react"));
3057
+ init_expression_engine();
3058
+ var import_jsx_runtime12 = require("react/jsx-runtime");
3059
+ var EXPR_PATTERN = /\{\{(.+?)\}\}/g;
3060
+ function containsExpression(value) {
3061
+ return typeof value === "string" && EXPR_PATTERN.test(value);
78
3062
  }
79
3063
  function evaluateProp(value, scopes) {
80
3064
  if (typeof value !== "string") return value;
81
3065
  const fullMatch = value.match(/^\{\{(.+)\}\}$/s);
82
- if (fullMatch) {
83
- return evaluateExpression(fullMatch[1], scopes);
84
- }
3066
+ if (fullMatch) return evaluateExpression(fullMatch[1], scopes);
85
3067
  if (containsExpression(value)) {
86
3068
  return value.replace(EXPR_PATTERN, (_, expr) => {
87
3069
  const result = evaluateExpression(expr, scopes);
@@ -90,17 +3072,16 @@ function evaluateProp(value, scopes) {
90
3072
  }
91
3073
  return value;
92
3074
  }
93
-
94
- // src/player/ComponentTreeRenderer.tsx
95
- var import_jsx_runtime = require("react/jsx-runtime");
96
- var UnknownAtom = ({ type, children }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { border: "1px dashed #e53e3e", borderRadius: 6, padding: "8px 12px", margin: 4, fontSize: 13, color: "#e53e3e", background: "#fff5f5" }, children: [
97
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontWeight: 600 }, children: [
3075
+ var UnknownAtom = ({ type, children }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { border: "1px dashed #e53e3e", borderRadius: 6, padding: "8px 12px", margin: 4, fontSize: 13, color: "#e53e3e", background: "#fff5f5" }, children: [
3076
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { style: { fontWeight: 600 }, children: [
98
3077
  "Unknown: ",
99
3078
  type
100
3079
  ] }),
101
- children && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 4 }, children })
3080
+ children && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 4 }, children })
102
3081
  ] });
103
3082
  var RenderNode = ({ node, scopes, atoms, onEvent }) => {
3083
+ const nodeType = node.type || node.component || "";
3084
+ const nodeProps = node.props || node.config || {};
104
3085
  if (node.$if) {
105
3086
  const condition = evaluateProp(node.$if, scopes);
106
3087
  if (!condition) return null;
@@ -109,7 +3090,7 @@ var RenderNode = ({ node, scopes, atoms, onEvent }) => {
109
3090
  const { each, as, key: keyField } = node.$for;
110
3091
  const items = evaluateProp(each, scopes);
111
3092
  if (!Array.isArray(items)) return null;
112
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: items.map((item, index) => {
3093
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: items.map((item, index) => {
113
3094
  const loopScopes = {
114
3095
  ...scopes,
115
3096
  state_data: {
@@ -120,27 +3101,27 @@ var RenderNode = ({ node, scopes, atoms, onEvent }) => {
120
3101
  };
121
3102
  const nodeWithoutFor = { ...node, $for: void 0 };
122
3103
  const itemKey = keyField ? String(item[keyField] ?? index) : String(index);
123
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RenderNode, { node: nodeWithoutFor, scopes: loopScopes, atoms, onEvent }, itemKey);
3104
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RenderNode, { node: nodeWithoutFor, scopes: loopScopes, atoms, onEvent }, itemKey);
124
3105
  }) });
125
3106
  }
126
- const Component = atoms[node.type];
3107
+ const Component = atoms[nodeType];
127
3108
  if (!Component) {
128
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnknownAtom, { type: node.type });
3109
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(UnknownAtom, { type: nodeType });
129
3110
  }
130
3111
  const evaluatedProps = {};
131
- if (node.props) {
132
- for (const [key, value] of Object.entries(node.props)) {
133
- if (key.startsWith("on") && typeof value === "string") {
134
- evaluatedProps[key] = (...args) => {
135
- if (containsExpression(value)) {
136
- evaluateExpression(value.replace(/^\{\{|\}\}$/g, ""), scopes);
137
- } else {
138
- onEvent(value, args[0]);
139
- }
140
- };
141
- } else {
142
- evaluatedProps[key] = evaluateProp(value, scopes);
143
- }
3112
+ if (node.className) evaluatedProps.className = node.className;
3113
+ if (node.id) evaluatedProps["data-node-id"] = node.id;
3114
+ for (const [key, value] of Object.entries(nodeProps)) {
3115
+ if (key.startsWith("on") && typeof value === "string") {
3116
+ evaluatedProps[key] = (...args) => {
3117
+ if (containsExpression(value)) {
3118
+ evaluateExpression(value.replace(/^\{\{|\}\}$/g, ""), scopes);
3119
+ } else {
3120
+ onEvent(value, args[0]);
3121
+ }
3122
+ };
3123
+ } else {
3124
+ evaluatedProps[key] = evaluateProp(value, scopes);
144
3125
  }
145
3126
  }
146
3127
  let children = null;
@@ -148,12 +3129,12 @@ var RenderNode = ({ node, scopes, atoms, onEvent }) => {
148
3129
  if (typeof node.children === "string") {
149
3130
  children = evaluateProp(node.children, scopes);
150
3131
  } else if (Array.isArray(node.children)) {
151
- children = node.children.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RenderNode, { node: child, scopes, atoms, onEvent }, index));
3132
+ children = node.children.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RenderNode, { node: child, scopes, atoms, onEvent }, child.id || index));
152
3133
  }
153
3134
  }
154
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...evaluatedProps, children });
3135
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Component, { ...evaluatedProps, children });
155
3136
  };
156
- var CTRErrorBoundary = class extends import_react.default.Component {
3137
+ var CTRErrorBoundary = class extends import_react13.default.Component {
157
3138
  constructor(props) {
158
3139
  super(props);
159
3140
  this.state = { hasError: false };
@@ -166,9 +3147,9 @@ var CTRErrorBoundary = class extends import_react.default.Component {
166
3147
  }
167
3148
  render() {
168
3149
  if (this.state.hasError) {
169
- return this.props.fallback || /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16, background: "#fff5f5", border: "1px solid #fed7d7", borderRadius: 8 }, children: [
170
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { style: { color: "#c53030" }, children: "Rendering Error" }),
171
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { color: "#e53e3e", fontSize: 14, marginTop: 4 }, children: this.state.error?.message || "An error occurred while rendering" })
3150
+ return this.props.fallback || /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { padding: 16, background: "#fff5f5", border: "1px solid #fed7d7", borderRadius: 8 }, children: [
3151
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { style: { color: "#c53030" }, children: "Rendering Error" }),
3152
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { color: "#e53e3e", fontSize: 14, marginTop: 4 }, children: this.state.error?.message || "An error occurred while rendering" })
172
3153
  ] });
173
3154
  }
174
3155
  return this.props.children;
@@ -182,43 +3163,44 @@ var ComponentTreeRenderer = ({
182
3163
  },
183
3164
  fallback
184
3165
  }) => {
185
- const allAtoms = (0, import_react.useMemo)(() => ({ ...atoms }), [atoms]);
186
- const handleEvent = (0, import_react.useCallback)(
3166
+ const allAtoms = (0, import_react13.useMemo)(() => ({ ...atoms }), [atoms]);
3167
+ const handleEvent = (0, import_react13.useCallback)(
187
3168
  (eventName, payload) => onEvent(eventName, payload),
188
3169
  [onEvent]
189
3170
  );
190
3171
  const nodes = Array.isArray(tree) ? tree : [tree];
191
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CTRErrorBoundary, { fallback, children: nodes.map((node, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RenderNode, { node, scopes, atoms: allAtoms, onEvent: handleEvent }, index)) });
3172
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CTRErrorBoundary, { fallback, children: nodes.map((node, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RenderNode, { node, scopes, atoms: allAtoms, onEvent: handleEvent }, index)) });
192
3173
  };
193
3174
 
194
3175
  // src/player/DevPlayer.tsx
195
- var import_react2 = require("react");
3176
+ var import_react15 = require("react");
196
3177
 
197
3178
  // src/player/builtin-atoms.tsx
198
- var import_jsx_runtime2 = require("react/jsx-runtime");
199
- var Stack = ({ children, gap = 8, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", flexDirection: "column", gap, ...style }, ...rest, children });
200
- var Row = ({ children, gap = 8, align, justify, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", flexDirection: "row", gap, alignItems: align, justifyContent: justify, ...style }, ...rest, children });
201
- var Column = ({ children, span, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: span ? `0 0 ${Number(span) / 12 * 100}%` : 1, ...style }, ...rest, children });
202
- var Grid = ({ children, columns = 2, gap = 8, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap, ...style }, ...rest, children });
203
- var Divider = ({ style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: "8px 0", ...style } });
204
- var Spacer = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { height: size, flexShrink: 0 } });
205
- var Text = ({ children, size, weight, color, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: size, fontWeight: weight, color, ...style }, ...rest, children });
206
- var Heading = ({ children, level = 2, style, ...rest }) => {
3179
+ var import_react14 = __toESM(require("react"));
3180
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3181
+ var Stack2 = ({ children, gap = 8, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexDirection: "column", gap, ...style }, ...rest, children });
3182
+ var Row2 = ({ children, gap = 8, align, justify, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexDirection: "row", gap, alignItems: align, justifyContent: justify, ...style }, ...rest, children });
3183
+ var Column2 = ({ children, span, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { flex: span ? `0 0 ${Number(span) / 12 * 100}%` : 1, ...style }, ...rest, children });
3184
+ var Grid2 = ({ children, columns = 2, gap = 8, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap, ...style }, ...rest, children });
3185
+ var Divider2 = ({ style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: "8px 0", ...style } });
3186
+ var Spacer2 = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { height: size, flexShrink: 0 } });
3187
+ var Text2 = ({ children, size, weight, color, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: size, fontWeight: weight, color, ...style }, ...rest, children });
3188
+ var Heading2 = ({ children, level = 2, style, ...rest }) => {
207
3189
  const lvl = Math.min(Math.max(Number(level), 1), 6);
208
3190
  const s = { margin: "0 0 8px", ...style };
209
3191
  const c = children;
210
- if (lvl === 1) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: s, ...rest, children: c });
211
- if (lvl === 2) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: s, ...rest, children: c });
212
- if (lvl === 3) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: s, ...rest, children: c });
213
- if (lvl === 4) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { style: s, ...rest, children: c });
214
- if (lvl === 5) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h5", { style: s, ...rest, children: c });
215
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h6", { style: s, ...rest, children: c });
3192
+ if (lvl === 1) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { style: s, ...rest, children: c });
3193
+ if (lvl === 2) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { style: s, ...rest, children: c });
3194
+ if (lvl === 3) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { style: s, ...rest, children: c });
3195
+ if (lvl === 4) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h4", { style: s, ...rest, children: c });
3196
+ if (lvl === 5) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h5", { style: s, ...rest, children: c });
3197
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h6", { style: s, ...rest, children: c });
216
3198
  };
217
- var Field = ({ label, value, children, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: 8, ...style }, children: [
218
- label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
219
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14 }, children: children ?? value ?? "\u2014" })
3199
+ var Field2 = ({ label, value, children, style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: 8, ...style }, children: [
3200
+ label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
3201
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontSize: 14 }, children: children ?? value ?? "\u2014" })
220
3202
  ] });
221
- var Badge = ({ children, variant = "default", style }) => {
3203
+ var Badge2 = ({ children, variant = "default", style }) => {
222
3204
  const colors = {
223
3205
  default: { bg: "#edf2f7", fg: "#4a5568" },
224
3206
  success: { bg: "#c6f6d5", fg: "#276749" },
@@ -227,10 +3209,10 @@ var Badge = ({ children, variant = "default", style }) => {
227
3209
  info: { bg: "#bee3f8", fg: "#2a4365" }
228
3210
  };
229
3211
  const c = colors[variant] ?? colors.default;
230
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { display: "inline-block", padding: "2px 8px", borderRadius: 9999, fontSize: 12, fontWeight: 500, background: c.bg, color: c.fg, ...style }, children });
3212
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { display: "inline-block", padding: "2px 8px", borderRadius: 9999, fontSize: 12, fontWeight: 500, background: c.bg, color: c.fg, ...style }, children });
231
3213
  };
232
- var ImageAtom = ({ src, alt, width, height, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src, alt: alt ?? "", width, height, style: { maxWidth: "100%", ...style }, ...rest });
233
- var Button = ({ children, onClick, variant = "primary", disabled, style, ...rest }) => {
3214
+ var ImageAtom = ({ src, alt, width, height, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src, alt: alt ?? "", width, height, style: { maxWidth: "100%", ...style }, ...rest });
3215
+ var Button2 = ({ children, onClick, variant = "primary", disabled, style, ...rest }) => {
234
3216
  const styles = {
235
3217
  primary: { background: "#3182ce", color: "#fff", border: "none" },
236
3218
  secondary: { background: "#edf2f7", color: "#4a5568", border: "1px solid #e2e8f0" },
@@ -238,7 +3220,7 @@ var Button = ({ children, onClick, variant = "primary", disabled, style, ...rest
238
3220
  ghost: { background: "transparent", color: "#4a5568", border: "none" }
239
3221
  };
240
3222
  const base = styles[variant] ?? styles.primary;
241
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3223
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
242
3224
  "button",
243
3225
  {
244
3226
  onClick,
@@ -249,78 +3231,202 @@ var Button = ({ children, onClick, variant = "primary", disabled, style, ...rest
249
3231
  }
250
3232
  );
251
3233
  };
252
- var LinkAtom = ({ children, href, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href, style: { color: "#3182ce", textDecoration: "underline", ...style }, ...rest, children });
253
- var TextInput = ({ value, onChange, placeholder, label, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: 8 }, children: [
254
- label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
255
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
256
- "input",
257
- {
258
- type: "text",
259
- value: value ?? "",
260
- onChange,
261
- placeholder,
262
- style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
263
- ...rest
264
- }
265
- )
266
- ] });
267
- var SelectAtom = ({ value, onChange, options, label, placeholder, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: 8 }, children: [
268
- label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
269
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3234
+ var LinkAtom = ({ children, href, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("a", { href, style: { color: "#3182ce", textDecoration: "underline", ...style }, ...rest, children });
3235
+ var TextInput2 = ({ value, onChange, placeholder, label, bind: _bind, style }) => {
3236
+ const isControlled = typeof onChange === "function";
3237
+ const [localValue, setLocalValue] = import_react14.default.useState(value ?? "");
3238
+ const handleChange = (e) => {
3239
+ setLocalValue(e.target.value);
3240
+ if (typeof onChange === "function") onChange(e);
3241
+ };
3242
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: 8 }, children: [
3243
+ label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
3244
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3245
+ "input",
3246
+ {
3247
+ type: "text",
3248
+ value: isControlled ? value ?? "" : localValue,
3249
+ onChange: handleChange,
3250
+ placeholder,
3251
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style }
3252
+ }
3253
+ )
3254
+ ] });
3255
+ };
3256
+ var SelectAtom = ({ value, onChange, options, label, placeholder, style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: 8 }, children: [
3257
+ label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
3258
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
270
3259
  "select",
271
3260
  {
272
3261
  value: value ?? "",
273
3262
  onChange,
274
3263
  style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
275
3264
  children: [
276
- placeholder ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "", children: placeholder }) : null,
3265
+ placeholder ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: placeholder }) : null,
277
3266
  Array.isArray(options) && options.map((opt) => {
278
3267
  const v = typeof opt === "string" ? opt : opt.value;
279
3268
  const l = typeof opt === "string" ? opt : opt.label;
280
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: v, children: l }, v);
3269
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: v, children: l }, v);
281
3270
  })
282
3271
  ]
283
3272
  }
284
3273
  )
285
3274
  ] });
286
- var Card = ({ children, title, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { border: "1px solid #e2e8f0", borderRadius: 8, padding: 16, background: "#fff", ...style }, ...rest, children: [
287
- title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: 12 }, children: title }) : null,
3275
+ var Card2 = ({ children, title, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { border: "1px solid #e2e8f0", borderRadius: 8, padding: 16, background: "#fff", ...style }, ...rest, children: [
3276
+ title ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: 12 }, children: title }) : null,
288
3277
  children
289
3278
  ] });
290
- var Section = ({ children, title, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { style: { marginBottom: 24, ...style }, ...rest, children: [
291
- title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: { fontSize: 18, fontWeight: 600, marginBottom: 8 }, children: title }) : null,
3279
+ var Section2 = ({ children, title, style, ...rest }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("section", { style: { marginBottom: 24, ...style }, ...rest, children: [
3280
+ title ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { style: { fontSize: 18, fontWeight: 600, marginBottom: 8 }, children: title }) : null,
292
3281
  children
293
3282
  ] });
294
- var Show = ({ when, children, fallback }) => when ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback ?? null });
295
- var Each = ({ items, children, renderItem }) => {
3283
+ var Show2 = ({ when, children, fallback }) => when ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: fallback ?? null });
3284
+ var Each2 = ({ items, children, renderItem }) => {
296
3285
  if (!Array.isArray(items)) return null;
297
- if (typeof renderItem === "function") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: items.map((item, i) => renderItem(item, i)) });
298
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
3286
+ if (typeof renderItem === "function") return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: items.map((item, i) => renderItem(item, i)) });
3287
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children });
3288
+ };
3289
+ var RouterContext = import_react14.default.createContext({ path: "/", navigate: () => {
3290
+ } });
3291
+ var Router2 = ({ children, basePath, className, style, ...rest }) => {
3292
+ const [path, setPath] = import_react14.default.useState("/");
3293
+ const navigate = import_react14.default.useCallback((to) => setPath(to), []);
3294
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RouterContext.Provider, { value: { path, navigate }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className, style, ...rest, children }) });
3295
+ };
3296
+ var Route2 = ({ children, path, exact, fallback: _fallback, className, style }) => {
3297
+ const { path: currentPath } = import_react14.default.useContext(RouterContext);
3298
+ const routePath = path || "/";
3299
+ const isExact = exact !== false;
3300
+ const matches = isExact ? currentPath === routePath || routePath === "/" && currentPath === "/" : currentPath.startsWith(routePath);
3301
+ if (!matches) return null;
3302
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className, style, children });
3303
+ };
3304
+ var NavLink2 = ({ children, to, label, icon, className, style, ...rest }) => {
3305
+ const { path, navigate } = import_react14.default.useContext(RouterContext);
3306
+ const target = to || "/";
3307
+ const isActive = path === target;
3308
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3309
+ "button",
3310
+ {
3311
+ onClick: () => navigate(target),
3312
+ className,
3313
+ style: {
3314
+ background: isActive ? "#edf2f7" : "transparent",
3315
+ border: "none",
3316
+ borderRadius: 4,
3317
+ padding: "4px 12px",
3318
+ fontSize: 13,
3319
+ cursor: "pointer",
3320
+ fontWeight: isActive ? 600 : 400,
3321
+ color: isActive ? "#2d3748" : "#718096",
3322
+ ...style
3323
+ },
3324
+ ...rest,
3325
+ children: children || label || target
3326
+ }
3327
+ );
3328
+ };
3329
+ var RoleGuard2 = ({ children, role: _role, fallback: _fallback }) => {
3330
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children });
3331
+ };
3332
+ var Icon2 = ({ name, size = 16, color, style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { display: "inline-flex", alignItems: "center", justifyContent: "center", width: size, height: size, fontSize: size, color, ...style }, title: name, children: iconGlyphs[name] || "\u25A1" });
3333
+ var iconGlyphs = {
3334
+ home: "\u2302",
3335
+ settings: "\u2699",
3336
+ plus: "+",
3337
+ search: "\u{1F50D}",
3338
+ box: "\u25A1",
3339
+ inbox: "\u2709",
3340
+ chevronRight: "\u203A",
3341
+ chevronLeft: "\u2039",
3342
+ x: "\u2715",
3343
+ check: "\u2713",
3344
+ edit: "\u270E",
3345
+ trash: "\u{1F5D1}",
3346
+ star: "\u2605",
3347
+ heart: "\u2665",
3348
+ user: "\u{1F464}",
3349
+ menu: "\u2630",
3350
+ close: "\u2715",
3351
+ arrow_right: "\u2192",
3352
+ arrow_left: "\u2190"
3353
+ };
3354
+ var Tabs2 = ({ children, tabs, defaultTab, style }) => {
3355
+ const tabList = tabs || [];
3356
+ const [active, setActive] = import_react14.default.useState(defaultTab || tabList[0]?.id || "");
3357
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style, children: [
3358
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", borderBottom: "1px solid #e2e8f0", marginBottom: 12 }, children: tabList.map((t) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3359
+ "button",
3360
+ {
3361
+ onClick: () => setActive(t.id),
3362
+ style: { padding: "6px 16px", border: "none", borderBottom: active === t.id ? "2px solid #3182ce" : "2px solid transparent", background: "none", cursor: "pointer", fontWeight: active === t.id ? 600 : 400, color: active === t.id ? "#3182ce" : "#718096" },
3363
+ children: t.label
3364
+ },
3365
+ t.id
3366
+ )) }),
3367
+ children
3368
+ ] });
3369
+ };
3370
+ var Accordion2 = ({ children, style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style, children });
3371
+ var Modal2 = ({ children, open, title, onClose: _onClose, style }) => {
3372
+ if (!open) return null;
3373
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1e3 }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { background: "#fff", borderRadius: 12, padding: 24, maxWidth: 480, width: "100%", ...style }, children: [
3374
+ title ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontWeight: 600, fontSize: 18, marginBottom: 16 }, children: String(title) }) : null,
3375
+ children
3376
+ ] }) });
299
3377
  };
3378
+ var Markdown2 = ({ content, children, style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { lineHeight: 1.6, ...style }, children: content || children });
3379
+ var ScrollArea2 = ({ children, maxHeight = 400, style }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { overflow: "auto", maxHeight, ...style }, children });
3380
+ var Slot2 = ({ children, fallback }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: children || fallback || null });
3381
+ var ModuleOutlet2 = ({ children, module: moduleName, fallback }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { "data-module": moduleName, children: children || fallback || /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: { color: "#a0aec0", fontSize: 13 }, children: [
3382
+ "Module: ",
3383
+ moduleName
3384
+ ] }) });
300
3385
  var builtinAtoms = {
301
- Stack,
302
- Row,
303
- Column,
304
- Grid,
305
- Divider,
306
- Spacer,
307
- Text,
308
- Heading,
309
- Field,
310
- Badge,
3386
+ // Layout
3387
+ Stack: Stack2,
3388
+ Row: Row2,
3389
+ Column: Column2,
3390
+ Grid: Grid2,
3391
+ Divider: Divider2,
3392
+ Spacer: Spacer2,
3393
+ // Typography
3394
+ Text: Text2,
3395
+ Heading: Heading2,
3396
+ Field: Field2,
3397
+ Badge: Badge2,
311
3398
  Image: ImageAtom,
312
- Button,
3399
+ Icon: Icon2,
3400
+ // Interactive
3401
+ Button: Button2,
313
3402
  Link: LinkAtom,
314
- TextInput,
3403
+ // Form
3404
+ TextInput: TextInput2,
315
3405
  Select: SelectAtom,
316
- Card,
317
- Section,
318
- Show,
319
- Each
3406
+ // Containers
3407
+ Card: Card2,
3408
+ Section: Section2,
3409
+ Tabs: Tabs2,
3410
+ Accordion: Accordion2,
3411
+ Modal: Modal2,
3412
+ // Content
3413
+ Markdown: Markdown2,
3414
+ ScrollArea: ScrollArea2,
3415
+ // Control Flow
3416
+ Show: Show2,
3417
+ Each: Each2,
3418
+ // Routing
3419
+ Router: Router2,
3420
+ Route: Route2,
3421
+ NavLink: NavLink2,
3422
+ RoleGuard: RoleGuard2,
3423
+ // Composition
3424
+ Slot: Slot2,
3425
+ ModuleOutlet: ModuleOutlet2
320
3426
  };
321
3427
 
322
3428
  // src/player/DevPlayer.tsx
323
- var import_jsx_runtime3 = require("react/jsx-runtime");
3429
+ var import_jsx_runtime14 = require("react/jsx-runtime");
324
3430
  var S = {
325
3431
  shell: {
326
3432
  display: "flex",
@@ -415,9 +3521,9 @@ var S = {
415
3521
  })
416
3522
  };
417
3523
  function useDevSocket(wsUrl, onReload) {
418
- const [connected, setConnected] = (0, import_react2.useState)(false);
419
- const wsRef = (0, import_react2.useRef)(null);
420
- (0, import_react2.useEffect)(() => {
3524
+ const [connected, setConnected] = (0, import_react15.useState)(false);
3525
+ const wsRef = (0, import_react15.useRef)(null);
3526
+ (0, import_react15.useEffect)(() => {
421
3527
  if (typeof window === "undefined") return;
422
3528
  const url = wsUrl ?? `ws://${window.location.host}/__mm_dev`;
423
3529
  let ws;
@@ -463,15 +3569,15 @@ var DevPlayer = ({
463
3569
  onReload,
464
3570
  onEvent: externalOnEvent
465
3571
  }) => {
466
- const [showSidebar, setShowSidebar] = (0, import_react2.useState)(true);
467
- const [events, setEvents] = (0, import_react2.useState)([]);
468
- const nextId = (0, import_react2.useRef)(0);
3572
+ const [showSidebar, setShowSidebar] = (0, import_react15.useState)(true);
3573
+ const [events, setEvents] = (0, import_react15.useState)([]);
3574
+ const nextId = (0, import_react15.useRef)(0);
469
3575
  const connected = useDevSocket(wsUrl, onReload);
470
- const mergedAtoms = (0, import_react2.useMemo)(
3576
+ const mergedAtoms = (0, import_react15.useMemo)(
471
3577
  () => ({ ...builtinAtoms, ...userAtoms }),
472
3578
  [userAtoms]
473
3579
  );
474
- const handleEvent = (0, import_react2.useCallback)(
3580
+ const handleEvent = (0, import_react15.useCallback)(
475
3581
  (name, payload) => {
476
3582
  setEvents((prev) => {
477
3583
  const entry = {
@@ -488,7 +3594,7 @@ var DevPlayer = ({
488
3594
  [externalOnEvent]
489
3595
  );
490
3596
  if (bare) {
491
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3597
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
492
3598
  ComponentTreeRenderer,
493
3599
  {
494
3600
  tree,
@@ -498,21 +3604,21 @@ var DevPlayer = ({
498
3604
  }
499
3605
  );
500
3606
  }
501
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.shell, children: [
502
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.toolbar, children: [
503
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.dot(connected), title: connected ? "HMR connected" : "HMR disconnected" }),
504
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: S.toolbarTitle, children: title }),
505
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: S.toolbarBadge, children: [
3607
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.shell, children: [
3608
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.toolbar, children: [
3609
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: S.dot(connected), title: connected ? "HMR connected" : "HMR disconnected" }),
3610
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: S.toolbarTitle, children: title }),
3611
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: S.toolbarBadge, children: [
506
3612
  Array.isArray(tree) ? tree.length : 1,
507
3613
  " node",
508
3614
  Array.isArray(tree) && tree.length !== 1 ? "s" : ""
509
3615
  ] }),
510
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: S.toolbarBadge, children: [
3616
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: S.toolbarBadge, children: [
511
3617
  Object.keys(mergedAtoms).length,
512
3618
  " atoms"
513
3619
  ] }),
514
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 } }),
515
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3620
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { flex: 1 } }),
3621
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
516
3622
  "button",
517
3623
  {
518
3624
  style: { ...S.toolbarBtn, ...showSidebar ? S.toolbarBtnActive : {} },
@@ -521,8 +3627,8 @@ var DevPlayer = ({
521
3627
  }
522
3628
  )
523
3629
  ] }),
524
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.body, children: [
525
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.preview, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3630
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.body, children: [
3631
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: S.preview, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
526
3632
  ComponentTreeRenderer,
527
3633
  {
528
3634
  tree,
@@ -531,18 +3637,18 @@ var DevPlayer = ({
531
3637
  onEvent: handleEvent
532
3638
  }
533
3639
  ) }),
534
- showSidebar && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebar, children: [
535
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebarSection, children: [
536
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.sidebarHeading, children: "Scopes" }),
537
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { style: S.pre, children: JSON.stringify(scopes, null, 2) })
3640
+ showSidebar && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebar, children: [
3641
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebarSection, children: [
3642
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: S.sidebarHeading, children: "Scopes" }),
3643
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { style: S.pre, children: JSON.stringify(scopes, null, 2) })
538
3644
  ] }),
539
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebarSection, children: [
540
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebarHeading, children: [
3645
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebarSection, children: [
3646
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebarHeading, children: [
541
3647
  "Atoms (",
542
3648
  Object.keys(mergedAtoms).length,
543
3649
  ")"
544
3650
  ] }),
545
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: Object.keys(mergedAtoms).sort().map((name) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3651
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: Object.keys(mergedAtoms).sort().map((name) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
546
3652
  "span",
547
3653
  {
548
3654
  style: {
@@ -560,14 +3666,14 @@ var DevPlayer = ({
560
3666
  name
561
3667
  )) })
562
3668
  ] }),
563
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebarSection, children: [
564
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }, children: [
565
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebarHeading, children: [
3669
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebarSection, children: [
3670
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }, children: [
3671
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebarHeading, children: [
566
3672
  "Events (",
567
3673
  events.length,
568
3674
  ")"
569
3675
  ] }),
570
- events.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3676
+ events.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
571
3677
  "button",
572
3678
  {
573
3679
  style: { background: "none", border: "none", color: "#a0aec0", fontSize: 11, cursor: "pointer" },
@@ -576,16 +3682,16 @@ var DevPlayer = ({
576
3682
  }
577
3683
  )
578
3684
  ] }),
579
- events.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { color: "#a0aec0", fontSize: 12, fontStyle: "italic" }, children: "No events yet" }),
580
- events.slice(0, 50).map((e) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.eventRow, children: [
581
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: S.eventTime, children: e.time }),
582
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: S.eventName, children: e.name }),
583
- e.payload !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "#718096", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: JSON.stringify(e.payload) })
3685
+ events.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { color: "#a0aec0", fontSize: 12, fontStyle: "italic" }, children: "No events yet" }),
3686
+ events.slice(0, 50).map((e) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.eventRow, children: [
3687
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: S.eventTime, children: e.time }),
3688
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: S.eventName, children: e.name }),
3689
+ e.payload !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { color: "#718096", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: JSON.stringify(e.payload) })
584
3690
  ] }, e.id))
585
3691
  ] }),
586
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.sidebarSection, children: [
587
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.sidebarHeading, children: "Tree (JSON)" }),
588
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { style: { ...S.pre, maxHeight: 400 }, children: JSON.stringify(tree, null, 2) })
3692
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: S.sidebarSection, children: [
3693
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: S.sidebarHeading, children: "Tree (JSON)" }),
3694
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { style: { ...S.pre, maxHeight: 400 }, children: JSON.stringify(tree, null, 2) })
589
3695
  ] })
590
3696
  ] })
591
3697
  ] })
@@ -593,10 +3699,32 @@ var DevPlayer = ({
593
3699
  };
594
3700
  // Annotate the CommonJS export names for ESM import in node:
595
3701
  0 && (module.exports = {
3702
+ AtomRegistryImpl,
596
3703
  ComponentTreeRenderer,
3704
+ DEFAULT_DESIGN_TOKENS,
597
3705
  DevPlayer,
3706
+ ExperienceRenderer,
3707
+ PlayerProvider,
3708
+ ScopeContext,
3709
+ SlotRegistryProvider,
3710
+ buildActionScope,
3711
+ buildEvalContext,
3712
+ buildLoopScope,
3713
+ buildScope,
598
3714
  builtinAtoms,
599
- containsExpression,
3715
+ builtinFunctions,
3716
+ classifyBinding,
3717
+ createApiResolver,
3718
+ createCoreAtomRegistry,
600
3719
  evaluateExpression,
601
- evaluateProp
3720
+ mergeRegistries,
3721
+ mergeScope,
3722
+ resolveAllBindings,
3723
+ resolveBinding,
3724
+ setWasmModule,
3725
+ usePlayerContext,
3726
+ usePlayerRouter,
3727
+ useScope,
3728
+ useSlotContributions,
3729
+ useTheme
602
3730
  });