@elucim/dsl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1533 @@
1
+ import { easeOutBounce as K, easeOutElastic as X, easeOutBack as Y, easeInBack as J, easeInOutExpo as Z, easeOutExpo as ee, easeInExpo as te, easeInOutSine as re, easeOutSine as ae, easeInSine as ie, easeInOutQuart as ne, easeOutQuart as se, easeInQuart as ce, easeInOutCubic as le, easeOutCubic as ue, easeInCubic as he, easeInOutQuad as fe, easeOutQuad as oe, easeInQuad as ye, linear as ge, spring as me, cubicBezier as be, Presentation as de, Player as xe, Scene as ve, Slide as we, Parallel as ke, Stagger as $e, Morph as Se, Transform as Ie, Write as Ce, Draw as Ae, FadeOut as Ee, FadeIn as Oe, BarChart as ze, LaTeX as Fe, Graph as Pe, Matrix as Me, VectorField as We, Vector as Ne, FunctionPlot as _e, Axes as Re, Text as De, Polygon as Te, Rect as Le, Arrow as je, Line as pe, Circle as qe, Sequence as Ue } from "@elucim/core";
2
+ import { jsxs as L, jsx as s } from "react/jsx-runtime";
3
+ import z from "react";
4
+ const M = {
5
+ sin: Math.sin,
6
+ cos: Math.cos,
7
+ tan: Math.tan,
8
+ asin: Math.asin,
9
+ acos: Math.acos,
10
+ atan: Math.atan,
11
+ atan2: (e, r) => Math.atan2(e, r),
12
+ sqrt: Math.sqrt,
13
+ abs: Math.abs,
14
+ log: Math.log10,
15
+ ln: Math.log,
16
+ exp: Math.exp,
17
+ floor: Math.floor,
18
+ ceil: Math.ceil,
19
+ round: Math.round,
20
+ min: (...e) => Math.min(...e),
21
+ max: (...e) => Math.max(...e),
22
+ sign: Math.sign,
23
+ pow: Math.pow
24
+ }, j = {
25
+ PI: Math.PI,
26
+ E: Math.E,
27
+ TAU: Math.PI * 2
28
+ };
29
+ function _(e) {
30
+ const r = [];
31
+ let t = 0;
32
+ for (; t < e.length; ) {
33
+ const a = e[t];
34
+ if (/\s/.test(a)) {
35
+ t++;
36
+ continue;
37
+ }
38
+ if (/[0-9]/.test(a) || a === "." && t + 1 < e.length && /[0-9]/.test(e[t + 1])) {
39
+ let n = "";
40
+ const l = t;
41
+ for (; t < e.length && /[0-9.]/.test(e[t]); )
42
+ n += e[t++];
43
+ r.push({ type: "NUMBER", value: n, pos: l });
44
+ continue;
45
+ }
46
+ if (/[a-zA-Z_]/.test(a)) {
47
+ let n = "";
48
+ const l = t;
49
+ for (; t < e.length && /[a-zA-Z0-9_]/.test(e[t]); )
50
+ n += e[t++];
51
+ r.push({ type: "IDENT", value: n, pos: l });
52
+ continue;
53
+ }
54
+ const i = t;
55
+ switch (t++, a) {
56
+ case "+":
57
+ r.push({ type: "PLUS", value: "+", pos: i });
58
+ break;
59
+ case "-":
60
+ r.push({ type: "MINUS", value: "-", pos: i });
61
+ break;
62
+ case "*":
63
+ r.push({ type: "STAR", value: "*", pos: i });
64
+ break;
65
+ case "/":
66
+ r.push({ type: "SLASH", value: "/", pos: i });
67
+ break;
68
+ case "^":
69
+ r.push({ type: "CARET", value: "^", pos: i });
70
+ break;
71
+ case "(":
72
+ r.push({ type: "LPAREN", value: "(", pos: i });
73
+ break;
74
+ case ")":
75
+ r.push({ type: "RPAREN", value: ")", pos: i });
76
+ break;
77
+ case "[":
78
+ r.push({ type: "LBRACKET", value: "[", pos: i });
79
+ break;
80
+ case "]":
81
+ r.push({ type: "RBRACKET", value: "]", pos: i });
82
+ break;
83
+ case ",":
84
+ r.push({ type: "COMMA", value: ",", pos: i });
85
+ break;
86
+ default:
87
+ throw new b(`Unexpected character '${a}'`, i);
88
+ }
89
+ }
90
+ return r.push({ type: "EOF", value: "", pos: t }), r;
91
+ }
92
+ class R {
93
+ constructor(r) {
94
+ this.pos = 0, this.tokens = r;
95
+ }
96
+ peek() {
97
+ return this.tokens[this.pos];
98
+ }
99
+ advance() {
100
+ const r = this.tokens[this.pos];
101
+ return this.pos++, r;
102
+ }
103
+ expect(r) {
104
+ const t = this.peek();
105
+ if (t.type !== r)
106
+ throw new b(
107
+ `Expected ${r} but got ${t.type} ('${t.value}')`,
108
+ t.pos
109
+ );
110
+ return this.advance();
111
+ }
112
+ // Entry point
113
+ parse() {
114
+ const r = this.parseExpression();
115
+ if (this.peek().type !== "EOF") {
116
+ const t = this.peek();
117
+ throw new b(
118
+ `Unexpected token '${t.value}' after expression`,
119
+ t.pos
120
+ );
121
+ }
122
+ return r;
123
+ }
124
+ // expression = term (('+' | '-') term)*
125
+ parseExpression() {
126
+ let r = this.parseTerm();
127
+ for (; this.peek().type === "PLUS" || this.peek().type === "MINUS"; ) {
128
+ const t = this.advance().value, a = this.parseTerm();
129
+ r = { kind: "binary", op: t, left: r, right: a };
130
+ }
131
+ return r;
132
+ }
133
+ // term = power (('*' | '/') power)*
134
+ parseTerm() {
135
+ let r = this.parsePower();
136
+ for (; this.peek().type === "STAR" || this.peek().type === "SLASH"; ) {
137
+ const t = this.advance().value, a = this.parsePower();
138
+ r = { kind: "binary", op: t, left: r, right: a };
139
+ }
140
+ return r;
141
+ }
142
+ // power = unary ('^' power)? (right-associative)
143
+ parsePower() {
144
+ const r = this.parseUnary();
145
+ if (this.peek().type === "CARET") {
146
+ this.advance();
147
+ const t = this.parsePower();
148
+ return { kind: "binary", op: "^", left: r, right: t };
149
+ }
150
+ return r;
151
+ }
152
+ // unary = ('+' | '-') unary | primary
153
+ parseUnary() {
154
+ return this.peek().type === "MINUS" ? (this.advance(), { kind: "unary", op: "-", operand: this.parseUnary() }) : this.peek().type === "PLUS" ? (this.advance(), this.parseUnary()) : this.parsePrimary();
155
+ }
156
+ // primary = NUMBER | IDENT ('(' args ')')? | '(' expression ')' | '[' elements ']'
157
+ parsePrimary() {
158
+ const r = this.peek();
159
+ if (r.type === "NUMBER")
160
+ return this.advance(), { kind: "number", value: parseFloat(r.value) };
161
+ if (r.type === "IDENT") {
162
+ this.advance();
163
+ const t = r.value;
164
+ if (this.peek().type === "LPAREN") {
165
+ this.advance();
166
+ const a = [];
167
+ if (this.peek().type !== "RPAREN")
168
+ for (a.push(this.parseExpression()); this.peek().type === "COMMA"; )
169
+ this.advance(), a.push(this.parseExpression());
170
+ if (this.expect("RPAREN"), !Object.prototype.hasOwnProperty.call(M, t))
171
+ throw new b(
172
+ `Unknown function '${t}'. Available: ${Object.keys(M).join(", ")}`,
173
+ r.pos
174
+ );
175
+ return { kind: "call", name: t, args: a };
176
+ }
177
+ return Object.prototype.hasOwnProperty.call(j, t) ? { kind: "number", value: j[t] } : { kind: "variable", name: t };
178
+ }
179
+ if (r.type === "LPAREN") {
180
+ this.advance();
181
+ const t = this.parseExpression();
182
+ return this.expect("RPAREN"), t;
183
+ }
184
+ if (r.type === "LBRACKET") {
185
+ this.advance();
186
+ const t = [];
187
+ if (this.peek().type !== "RBRACKET")
188
+ for (t.push(this.parseExpression()); this.peek().type === "COMMA"; )
189
+ this.advance(), t.push(this.parseExpression());
190
+ return this.expect("RBRACKET"), { kind: "array", elements: t };
191
+ }
192
+ throw new b(
193
+ `Unexpected token '${r.value}'`,
194
+ r.pos
195
+ );
196
+ }
197
+ }
198
+ function d(e, r) {
199
+ switch (e.kind) {
200
+ case "number":
201
+ return e.value;
202
+ case "variable":
203
+ if (Object.prototype.hasOwnProperty.call(r, e.name)) return r[e.name];
204
+ throw new b(`Unknown variable '${e.name}'`, 0);
205
+ case "unary":
206
+ const t = d(e.operand, r);
207
+ return e.op === "-" ? -t : t;
208
+ case "binary": {
209
+ const a = d(e.left, r), i = d(e.right, r);
210
+ switch (e.op) {
211
+ case "+":
212
+ return a + i;
213
+ case "-":
214
+ return a - i;
215
+ case "*":
216
+ return a * i;
217
+ case "/":
218
+ return i === 0 ? 1 / 0 : a / i;
219
+ case "^":
220
+ return Math.pow(a, i);
221
+ }
222
+ break;
223
+ }
224
+ case "call": {
225
+ const a = M[e.name], i = e.args.map((n) => d(n, r));
226
+ return a(...i);
227
+ }
228
+ case "array":
229
+ return e.elements.map((a) => d(a, r));
230
+ }
231
+ throw new b("Invalid AST node", 0);
232
+ }
233
+ class b extends Error {
234
+ constructor(r, t) {
235
+ super(r), this.name = "ExpressionError", this.position = t;
236
+ }
237
+ }
238
+ function Be(e) {
239
+ const r = _(e), t = new R(r).parse();
240
+ return (a) => d(t, a);
241
+ }
242
+ function Ve(e) {
243
+ const r = _(e), t = new R(r).parse();
244
+ if (t.kind !== "array" || t.elements.length !== 2)
245
+ throw new b(
246
+ 'Vector expression must be an array of 2 elements, e.g. "[-y, x]"',
247
+ 0
248
+ );
249
+ return (a) => d(t, a);
250
+ }
251
+ function U(e) {
252
+ try {
253
+ const r = _(e);
254
+ return new R(r).parse(), null;
255
+ } catch (r) {
256
+ return r instanceof b ? `${r.message} (at position ${r.position})` : String(r);
257
+ }
258
+ }
259
+ const W = {
260
+ linear: ge,
261
+ easeInQuad: ye,
262
+ easeOutQuad: oe,
263
+ easeInOutQuad: fe,
264
+ easeInCubic: he,
265
+ easeOutCubic: ue,
266
+ easeInOutCubic: le,
267
+ easeInQuart: ce,
268
+ easeOutQuart: se,
269
+ easeInOutQuart: ne,
270
+ easeInSine: ie,
271
+ easeOutSine: ae,
272
+ easeInOutSine: re,
273
+ easeInExpo: te,
274
+ easeOutExpo: ee,
275
+ easeInOutExpo: Z,
276
+ easeInBack: J,
277
+ easeOutBack: Y,
278
+ easeOutElastic: X,
279
+ easeOutBounce: K
280
+ };
281
+ function c(e) {
282
+ if (e !== void 0) {
283
+ if (typeof e == "string") {
284
+ const r = W[e];
285
+ if (!r) {
286
+ const t = Object.keys(W), a = t.find((n) => n.toLowerCase() === e.toLowerCase()), i = a ? ` Did you mean '${a}'?` : "";
287
+ throw new Error(`Unknown easing '${e}'.${i} Available: ${t.join(", ")}`);
288
+ }
289
+ return r;
290
+ }
291
+ if (e.type === "spring")
292
+ return me({
293
+ stiffness: e.stiffness,
294
+ damping: e.damping,
295
+ mass: e.mass
296
+ });
297
+ if (e.type === "cubicBezier")
298
+ return be(e.x1, e.y1, e.x2, e.y2);
299
+ throw new Error(`Unknown easing type: ${e.type}`);
300
+ }
301
+ }
302
+ const F = Object.keys(W);
303
+ function He(e) {
304
+ const r = [];
305
+ if (!e || typeof e != "object")
306
+ return r.push({ path: "", message: "Document must be an object", severity: "error" }), { valid: !1, errors: r };
307
+ const t = e;
308
+ return t.version !== "1.0" && r.push({ path: "version", message: `Expected version "1.0", got "${t.version}"`, severity: "error" }), !t.root || typeof t.root != "object" ? (r.push({ path: "root", message: 'Missing or invalid "root" node', severity: "error" }), { valid: r.filter((a) => a.severity === "error").length === 0, errors: r }) : (Ge(t.root, "root", r), {
309
+ valid: r.filter((a) => a.severity === "error").length === 0,
310
+ errors: r
311
+ });
312
+ }
313
+ const p = ["scene", "player", "presentation"], P = [
314
+ "sequence",
315
+ "group",
316
+ "circle",
317
+ "line",
318
+ "arrow",
319
+ "rect",
320
+ "polygon",
321
+ "text",
322
+ "axes",
323
+ "functionPlot",
324
+ "vectorField",
325
+ "vector",
326
+ "matrix",
327
+ "graph",
328
+ "latex",
329
+ "barChart",
330
+ "fadeIn",
331
+ "fadeOut",
332
+ "draw",
333
+ "write",
334
+ "transform",
335
+ "morph",
336
+ "stagger",
337
+ "parallel",
338
+ "player",
339
+ "scene"
340
+ ], q = ["none", "fade", "slide-left", "slide-up", "zoom"];
341
+ function Ge(e, r, t) {
342
+ const a = e.type;
343
+ if (!p.includes(a)) {
344
+ t.push({ path: `${r}.type`, message: `Root type must be one of: ${p.join(", ")}. Got "${a}"`, severity: "error" });
345
+ return;
346
+ }
347
+ a === "scene" || a === "player" ? B(e, r, a, t) : a === "presentation" && Qe(e, r, t);
348
+ }
349
+ function B(e, r, t, a) {
350
+ gt(e, "durationInFrames", r, a), o(e, "width", r, a), o(e, "height", r, a), o(e, "fps", r, a), x(e, "background", r, a), t === "player" && ($(e, "controls", r, a), $(e, "loop", r, a), $(e, "autoPlay", r, a)), w(e, r, a);
351
+ }
352
+ function Qe(e, r, t) {
353
+ if (o(e, "width", r, t), o(e, "height", r, t), x(e, "background", r, t), o(e, "transitionDuration", r, t), $(e, "showHud", r, t), $(e, "showNotes", r, t), e.transition !== void 0 && (q.includes(e.transition) || t.push({
354
+ path: `${r}.transition`,
355
+ message: `Invalid transition "${e.transition}". Must be one of: ${q.join(", ")}`,
356
+ severity: "error"
357
+ })), !Array.isArray(e.slides)) {
358
+ t.push({ path: `${r}.slides`, message: 'Presentation must have a "slides" array', severity: "error" });
359
+ return;
360
+ }
361
+ e.slides.length === 0 && t.push({ path: `${r}.slides`, message: "Presentation must have at least one slide", severity: "warning" }), e.slides.forEach((a, i) => {
362
+ Ke(a, `${r}.slides[${i}]`, t);
363
+ });
364
+ }
365
+ function Ke(e, r, t) {
366
+ if (!e || typeof e != "object") {
367
+ t.push({ path: r, message: "Slide must be an object", severity: "error" });
368
+ return;
369
+ }
370
+ x(e, "title", r, t), x(e, "notes", r, t), x(e, "background", r, t), e.children !== void 0 && (Array.isArray(e.children) ? e.children.forEach((a, i) => {
371
+ V(a, `${r}.children[${i}]`, t);
372
+ }) : t.push({ path: `${r}.children`, message: "Slide children must be an array", severity: "error" }));
373
+ }
374
+ function w(e, r, t) {
375
+ if (!Array.isArray(e.children)) {
376
+ t.push({ path: `${r}.children`, message: 'Expected "children" array', severity: "error" });
377
+ return;
378
+ }
379
+ e.children.forEach((a, i) => {
380
+ V(a, `${r}.children[${i}]`, t);
381
+ });
382
+ }
383
+ function V(e, r, t) {
384
+ if (!e || typeof e != "object") {
385
+ t.push({ path: r, message: "Element must be an object", severity: "error" });
386
+ return;
387
+ }
388
+ const a = e.type;
389
+ if (!a || !P.includes(a)) {
390
+ const i = a ? H(a, P) : "";
391
+ t.push({
392
+ path: `${r}.type`,
393
+ message: `Unknown element type "${a}".${i} Valid types: ${P.join(", ")}`,
394
+ severity: "error"
395
+ });
396
+ return;
397
+ }
398
+ switch (a) {
399
+ case "circle":
400
+ Xe(e, r, t);
401
+ break;
402
+ case "line":
403
+ Ye(e, r, t);
404
+ break;
405
+ case "arrow":
406
+ Je(e, r, t);
407
+ break;
408
+ case "rect":
409
+ Ze(e, r, t);
410
+ break;
411
+ case "polygon":
412
+ et(e, r, t);
413
+ break;
414
+ case "text":
415
+ tt(e, r, t);
416
+ break;
417
+ case "axes":
418
+ rt(e, r, t);
419
+ break;
420
+ case "functionPlot":
421
+ at(e, r, t);
422
+ break;
423
+ case "vector":
424
+ it(e, r, t);
425
+ break;
426
+ case "vectorField":
427
+ nt(e, r, t);
428
+ break;
429
+ case "matrix":
430
+ st(e, r, t);
431
+ break;
432
+ case "graph":
433
+ ct(e, r, t);
434
+ break;
435
+ case "latex":
436
+ lt(e, r, t);
437
+ break;
438
+ case "sequence":
439
+ ut(e, r, t);
440
+ break;
441
+ case "group":
442
+ case "parallel":
443
+ w(e, r, t);
444
+ break;
445
+ case "fadeIn":
446
+ case "fadeOut":
447
+ case "draw":
448
+ case "write":
449
+ ht(e, r, t);
450
+ break;
451
+ case "transform":
452
+ ft(e, r, t);
453
+ break;
454
+ case "morph":
455
+ ot(e, r, t);
456
+ break;
457
+ case "stagger":
458
+ yt(e, r, t);
459
+ break;
460
+ case "scene":
461
+ case "player":
462
+ B(e, r, a, t);
463
+ break;
464
+ }
465
+ }
466
+ function Xe(e, r, t) {
467
+ u(e, "cx", r, t), u(e, "cy", r, t), N(e, "r", r, t), y(e, r, t);
468
+ }
469
+ function Ye(e, r, t) {
470
+ u(e, "x1", r, t), u(e, "y1", r, t), u(e, "x2", r, t), u(e, "y2", r, t), y(e, r, t);
471
+ }
472
+ function Je(e, r, t) {
473
+ u(e, "x1", r, t), u(e, "y1", r, t), u(e, "x2", r, t), u(e, "y2", r, t), y(e, r, t);
474
+ }
475
+ function Ze(e, r, t) {
476
+ u(e, "x", r, t), u(e, "y", r, t), N(e, "width", r, t), N(e, "height", r, t), y(e, r, t);
477
+ }
478
+ function et(e, r, t) {
479
+ Array.isArray(e.points) ? e.points.length < 3 ? t.push({ path: `${r}.points`, message: "Polygon requires at least 3 points", severity: "error" }) : e.points.forEach((a, i) => {
480
+ (!Array.isArray(a) || a.length !== 2 || typeof a[0] != "number" || typeof a[1] != "number") && t.push({ path: `${r}.points[${i}]`, message: "Each point must be [number, number]", severity: "error" });
481
+ }) : t.push({ path: `${r}.points`, message: 'Polygon requires a "points" array', severity: "error" }), y(e, r, t);
482
+ }
483
+ function tt(e, r, t) {
484
+ u(e, "x", r, t), u(e, "y", r, t), typeof e.content != "string" && t.push({ path: `${r}.content`, message: 'Text requires a "content" string', severity: "error" }), y(e, r, t);
485
+ }
486
+ function rt(e, r, t) {
487
+ v(e, "domain", r, t), v(e, "range", r, t), v(e, "origin", r, t), y(e, r, t);
488
+ }
489
+ function at(e, r, t) {
490
+ if (typeof e.fn != "string")
491
+ t.push({ path: `${r}.fn`, message: 'FunctionPlot requires a "fn" expression string', severity: "error" });
492
+ else {
493
+ const a = U(e.fn);
494
+ a && t.push({ path: `${r}.fn`, message: `Invalid expression: ${a}`, severity: "error" });
495
+ }
496
+ v(e, "domain", r, t), y(e, r, t);
497
+ }
498
+ function it(e, r, t) {
499
+ (!Array.isArray(e.to) || e.to.length !== 2) && t.push({ path: `${r}.to`, message: 'Vector requires a "to" array of [number, number]', severity: "error" }), v(e, "from", r, t), y(e, r, t);
500
+ }
501
+ function nt(e, r, t) {
502
+ if (typeof e.fn != "string")
503
+ t.push({ path: `${r}.fn`, message: 'VectorField requires a "fn" expression string', severity: "error" });
504
+ else {
505
+ const a = U(e.fn);
506
+ a && t.push({ path: `${r}.fn`, message: `Invalid vector expression: ${a}`, severity: "error" });
507
+ }
508
+ v(e, "domain", r, t), v(e, "range", r, t), y(e, r, t);
509
+ }
510
+ function st(e, r, t) {
511
+ Array.isArray(e.values) ? e.values.forEach((a, i) => {
512
+ Array.isArray(a) || t.push({ path: `${r}.values[${i}]`, message: "Each matrix row must be an array", severity: "error" });
513
+ }) : t.push({ path: `${r}.values`, message: 'Matrix requires a "values" 2D array', severity: "error" }), y(e, r, t);
514
+ }
515
+ function ct(e, r, t) {
516
+ if (!Array.isArray(e.nodes))
517
+ t.push({ path: `${r}.nodes`, message: 'Graph requires a "nodes" array', severity: "error" });
518
+ else {
519
+ const a = /* @__PURE__ */ new Set();
520
+ e.nodes.forEach((i, n) => {
521
+ typeof i.id != "string" ? t.push({ path: `${r}.nodes[${n}].id`, message: 'Graph node requires a string "id"', severity: "error" }) : (a.has(i.id) && t.push({ path: `${r}.nodes[${n}].id`, message: `Duplicate node id "${i.id}"`, severity: "error" }), a.add(i.id)), u(i, "x", `${r}.nodes[${n}]`, t), u(i, "y", `${r}.nodes[${n}]`, t);
522
+ }), Array.isArray(e.edges) && e.edges.forEach((i, n) => {
523
+ (typeof i.from != "string" || !a.has(i.from)) && t.push({ path: `${r}.edges[${n}].from`, message: `Edge "from" references unknown node "${i.from}"`, severity: "error" }), (typeof i.to != "string" || !a.has(i.to)) && t.push({ path: `${r}.edges[${n}].to`, message: `Edge "to" references unknown node "${i.to}"`, severity: "error" });
524
+ });
525
+ }
526
+ y(e, r, t);
527
+ }
528
+ function lt(e, r, t) {
529
+ typeof e.expression != "string" && t.push({ path: `${r}.expression`, message: 'LaTeX requires an "expression" string', severity: "error" }), u(e, "x", r, t), u(e, "y", r, t), y(e, r, t);
530
+ }
531
+ function ut(e, r, t) {
532
+ u(e, "from", r, t), mt(e, "durationInFrames", r, t), w(e, r, t);
533
+ }
534
+ function ht(e, r, t) {
535
+ o(e, "duration", r, t), S(e, r, t), w(e, r, t);
536
+ }
537
+ function ft(e, r, t) {
538
+ if (o(e, "duration", r, t), S(e, r, t), e.translate !== void 0) {
539
+ const a = e.translate;
540
+ (!a || typeof a != "object") && t.push({ path: `${r}.translate`, message: "translate must be { from: [x,y], to: [x,y] }", severity: "error" });
541
+ }
542
+ if (e.scale !== void 0) {
543
+ const a = e.scale;
544
+ (!a || typeof a != "object" || typeof a.from != "number" || typeof a.to != "number") && t.push({ path: `${r}.scale`, message: "scale must be { from: number, to: number }", severity: "error" });
545
+ }
546
+ if (e.rotate !== void 0) {
547
+ const a = e.rotate;
548
+ (!a || typeof a != "object" || typeof a.from != "number" || typeof a.to != "number") && t.push({ path: `${r}.rotate`, message: "rotate must be { from: number, to: number }", severity: "error" });
549
+ }
550
+ if (e.opacity !== void 0) {
551
+ const a = e.opacity;
552
+ (!a || typeof a != "object" || typeof a.from != "number" || typeof a.to != "number") && t.push({ path: `${r}.opacity`, message: "opacity must be { from: number, to: number }", severity: "error" });
553
+ }
554
+ w(e, r, t);
555
+ }
556
+ function ot(e, r, t) {
557
+ o(e, "duration", r, t), S(e, r, t), x(e, "fromColor", r, t), x(e, "toColor", r, t), w(e, r, t);
558
+ }
559
+ function yt(e, r, t) {
560
+ o(e, "staggerDelay", r, t), S(e, r, t), w(e, r, t);
561
+ }
562
+ function y(e, r, t) {
563
+ o(e, "fadeIn", r, t), o(e, "fadeOut", r, t), o(e, "draw", r, t), S(e, r, t);
564
+ }
565
+ function S(e, r, t) {
566
+ if (e.easing !== void 0) {
567
+ if (typeof e.easing == "string") {
568
+ if (!F.includes(e.easing)) {
569
+ const a = H(e.easing, F);
570
+ t.push({
571
+ path: `${r}.easing`,
572
+ message: `Unknown easing "${e.easing}".${a} Available: ${F.join(", ")}`,
573
+ severity: "error"
574
+ });
575
+ }
576
+ return;
577
+ }
578
+ if (typeof e.easing == "object" && e.easing !== null) {
579
+ const a = e.easing;
580
+ if (a.type === "spring") return;
581
+ if (a.type === "cubicBezier") {
582
+ for (const i of ["x1", "y1", "x2", "y2"])
583
+ typeof a[i] != "number" && t.push({ path: `${r}.easing.${i}`, message: `cubicBezier requires numeric "${i}"`, severity: "error" });
584
+ return;
585
+ }
586
+ t.push({ path: `${r}.easing.type`, message: 'Easing object type must be "spring" or "cubicBezier"', severity: "error" });
587
+ return;
588
+ }
589
+ t.push({ path: `${r}.easing`, message: 'Easing must be a string name or { type: "spring"|"cubicBezier", ... }', severity: "error" });
590
+ }
591
+ }
592
+ function u(e, r, t, a) {
593
+ typeof e[r] != "number" && a.push({ path: `${t}.${r}`, message: `Required numeric field "${r}" is missing or not a number`, severity: "error" });
594
+ }
595
+ function N(e, r, t, a) {
596
+ (typeof e[r] != "number" || e[r] <= 0) && a.push({ path: `${t}.${r}`, message: `"${r}" must be a positive number`, severity: "error" });
597
+ }
598
+ function gt(e, r, t, a) {
599
+ const i = e[r];
600
+ (typeof i != "number" || i <= 0 || !Number.isInteger(i)) && a.push({ path: `${t}.${r}`, message: `"${r}" must be a positive integer`, severity: "error" });
601
+ }
602
+ function o(e, r, t, a) {
603
+ e[r] !== void 0 && (typeof e[r] != "number" || e[r] <= 0) && a.push({ path: `${t}.${r}`, message: `"${r}" must be a positive number`, severity: "error" });
604
+ }
605
+ function mt(e, r, t, a) {
606
+ const i = e[r];
607
+ i !== void 0 && (typeof i != "number" || i <= 0 || !Number.isInteger(i)) && a.push({ path: `${t}.${r}`, message: `"${r}" must be a positive integer`, severity: "error" });
608
+ }
609
+ function x(e, r, t, a) {
610
+ e[r] !== void 0 && typeof e[r] != "string" && a.push({ path: `${t}.${r}`, message: `"${r}" must be a string`, severity: "error" });
611
+ }
612
+ function $(e, r, t, a) {
613
+ e[r] !== void 0 && typeof e[r] != "boolean" && a.push({ path: `${t}.${r}`, message: `"${r}" must be a boolean`, severity: "error" });
614
+ }
615
+ function v(e, r, t, a) {
616
+ const i = e[r];
617
+ i !== void 0 && (!Array.isArray(i) || i.length !== 2 || typeof i[0] != "number" || typeof i[1] != "number") && a.push({ path: `${t}.${r}`, message: `"${r}" must be [number, number]`, severity: "error" });
618
+ }
619
+ function H(e, r) {
620
+ const t = e.toLowerCase(), a = r.find((n) => n.toLowerCase() === t);
621
+ if (a) return ` Did you mean '${a}'?`;
622
+ const i = r.find((n) => n.toLowerCase().startsWith(t.slice(0, 4)));
623
+ return i ? ` Did you mean '${i}'?` : "";
624
+ }
625
+ function Ct({ dsl: e, className: r, style: t }) {
626
+ const a = He(e);
627
+ return a.valid ? /* @__PURE__ */ s("div", { className: r, style: t, "data-testid": "dsl-root", children: bt(e.root) }) : /* @__PURE__ */ L(
628
+ "div",
629
+ {
630
+ className: r,
631
+ style: { color: "#ff6b6b", fontFamily: "monospace", padding: 16, ...t },
632
+ "data-testid": "dsl-error",
633
+ children: [
634
+ /* @__PURE__ */ s("strong", { children: "Elucim DSL Validation Errors:" }),
635
+ /* @__PURE__ */ s("ul", { children: a.errors.filter((i) => i.severity === "error").map((i, n) => /* @__PURE__ */ L("li", { children: [
636
+ i.path,
637
+ ": ",
638
+ i.message
639
+ ] }, n)) })
640
+ ]
641
+ }
642
+ );
643
+ }
644
+ function bt(e) {
645
+ switch (e.type) {
646
+ case "scene":
647
+ return G(e);
648
+ case "player":
649
+ return Q(e);
650
+ case "presentation":
651
+ return dt(e);
652
+ }
653
+ }
654
+ function G(e) {
655
+ return /* @__PURE__ */ s(
656
+ ve,
657
+ {
658
+ width: e.width,
659
+ height: e.height,
660
+ fps: e.fps,
661
+ durationInFrames: e.durationInFrames,
662
+ background: e.background,
663
+ children: e.children.map((r, t) => f(r, t))
664
+ }
665
+ );
666
+ }
667
+ function Q(e) {
668
+ return /* @__PURE__ */ s(
669
+ xe,
670
+ {
671
+ width: e.width,
672
+ height: e.height,
673
+ fps: e.fps,
674
+ durationInFrames: e.durationInFrames,
675
+ background: e.background,
676
+ controls: e.controls,
677
+ loop: e.loop,
678
+ autoPlay: e.autoPlay,
679
+ children: e.children.map((r, t) => f(r, t))
680
+ }
681
+ );
682
+ }
683
+ function dt(e) {
684
+ return /* @__PURE__ */ s(
685
+ de,
686
+ {
687
+ width: e.width,
688
+ height: e.height,
689
+ background: e.background,
690
+ transition: e.transition,
691
+ transitionDuration: e.transitionDuration,
692
+ showHUD: e.showHud,
693
+ showNotes: e.showNotes,
694
+ children: e.slides.map((r, t) => xt(r, t))
695
+ }
696
+ );
697
+ }
698
+ function xt(e, r) {
699
+ var t;
700
+ return /* @__PURE__ */ s(we, { title: e.title, notes: e.notes, background: e.background, children: (t = e.children) == null ? void 0 : t.map((a, i) => f(a, i)) }, r);
701
+ }
702
+ function f(e, r) {
703
+ switch (e.type) {
704
+ case "sequence":
705
+ return /* @__PURE__ */ s(Ue, { from: e.from, durationInFrames: e.durationInFrames, name: e.name, children: e.children.map((t, a) => f(t, a)) }, r);
706
+ case "group":
707
+ return /* @__PURE__ */ s(z.Fragment, { children: e.children.map((t, a) => f(t, a)) }, r);
708
+ case "circle":
709
+ return /* @__PURE__ */ s(
710
+ qe,
711
+ {
712
+ cx: e.cx,
713
+ cy: e.cy,
714
+ r: e.r,
715
+ fill: e.fill,
716
+ stroke: e.stroke,
717
+ strokeWidth: e.strokeWidth,
718
+ opacity: e.opacity,
719
+ fadeIn: e.fadeIn,
720
+ fadeOut: e.fadeOut,
721
+ draw: e.draw,
722
+ easing: c(e.easing)
723
+ },
724
+ r
725
+ );
726
+ case "line":
727
+ return /* @__PURE__ */ s(
728
+ pe,
729
+ {
730
+ x1: e.x1,
731
+ y1: e.y1,
732
+ x2: e.x2,
733
+ y2: e.y2,
734
+ stroke: e.stroke,
735
+ strokeWidth: e.strokeWidth,
736
+ strokeDasharray: e.strokeDasharray,
737
+ opacity: e.opacity,
738
+ fadeIn: e.fadeIn,
739
+ fadeOut: e.fadeOut,
740
+ draw: e.draw,
741
+ easing: c(e.easing)
742
+ },
743
+ r
744
+ );
745
+ case "arrow":
746
+ return /* @__PURE__ */ s(
747
+ je,
748
+ {
749
+ x1: e.x1,
750
+ y1: e.y1,
751
+ x2: e.x2,
752
+ y2: e.y2,
753
+ stroke: e.stroke,
754
+ strokeWidth: e.strokeWidth,
755
+ headSize: e.headSize,
756
+ strokeDasharray: e.strokeDasharray,
757
+ opacity: e.opacity,
758
+ fadeIn: e.fadeIn,
759
+ fadeOut: e.fadeOut,
760
+ draw: e.draw,
761
+ easing: c(e.easing)
762
+ },
763
+ r
764
+ );
765
+ case "rect":
766
+ return /* @__PURE__ */ s(
767
+ Le,
768
+ {
769
+ x: e.x,
770
+ y: e.y,
771
+ width: e.width,
772
+ height: e.height,
773
+ fill: e.fill,
774
+ stroke: e.stroke,
775
+ strokeWidth: e.strokeWidth,
776
+ rx: e.rx,
777
+ ry: e.ry,
778
+ strokeDasharray: e.strokeDasharray,
779
+ opacity: e.opacity,
780
+ fadeIn: e.fadeIn,
781
+ fadeOut: e.fadeOut,
782
+ draw: e.draw,
783
+ easing: c(e.easing)
784
+ },
785
+ r
786
+ );
787
+ case "polygon":
788
+ return /* @__PURE__ */ s(
789
+ Te,
790
+ {
791
+ points: e.points,
792
+ fill: e.fill,
793
+ stroke: e.stroke,
794
+ strokeWidth: e.strokeWidth,
795
+ closed: e.closed,
796
+ opacity: e.opacity,
797
+ fadeIn: e.fadeIn,
798
+ fadeOut: e.fadeOut,
799
+ draw: e.draw,
800
+ easing: c(e.easing)
801
+ },
802
+ r
803
+ );
804
+ case "text":
805
+ return /* @__PURE__ */ s(
806
+ De,
807
+ {
808
+ x: e.x,
809
+ y: e.y,
810
+ fill: e.fill,
811
+ fontSize: e.fontSize,
812
+ fontFamily: e.fontFamily,
813
+ fontWeight: e.fontWeight,
814
+ textAnchor: e.textAnchor,
815
+ dominantBaseline: e.dominantBaseline,
816
+ opacity: e.opacity,
817
+ fadeIn: e.fadeIn,
818
+ fadeOut: e.fadeOut,
819
+ easing: c(e.easing),
820
+ children: e.content
821
+ },
822
+ r
823
+ );
824
+ case "axes":
825
+ return /* @__PURE__ */ s(
826
+ Re,
827
+ {
828
+ domain: e.domain,
829
+ range: e.range,
830
+ origin: e.origin,
831
+ scale: e.scale,
832
+ showGrid: e.showGrid,
833
+ showTicks: e.showTicks,
834
+ showLabels: e.showLabels,
835
+ tickStep: e.tickStep,
836
+ axisColor: e.axisColor,
837
+ gridColor: e.gridColor,
838
+ labelColor: e.labelColor,
839
+ labelFontSize: e.labelFontSize,
840
+ fadeIn: e.fadeIn,
841
+ fadeOut: e.fadeOut,
842
+ draw: e.draw,
843
+ easing: c(e.easing)
844
+ },
845
+ r
846
+ );
847
+ case "functionPlot": {
848
+ const t = Be(e.fn);
849
+ return /* @__PURE__ */ s(
850
+ _e,
851
+ {
852
+ fn: (a) => t({ x: a }),
853
+ domain: e.domain,
854
+ yClamp: e.yClamp,
855
+ origin: e.origin,
856
+ scale: e.scale,
857
+ color: e.color,
858
+ strokeWidth: e.strokeWidth,
859
+ samples: e.samples,
860
+ draw: e.draw,
861
+ easing: c(e.easing),
862
+ opacity: e.opacity
863
+ },
864
+ r
865
+ );
866
+ }
867
+ case "vector":
868
+ return /* @__PURE__ */ s(
869
+ Ne,
870
+ {
871
+ from: e.from,
872
+ to: e.to,
873
+ origin: e.origin,
874
+ scale: e.scale,
875
+ color: e.color,
876
+ strokeWidth: e.strokeWidth,
877
+ headSize: e.headSize,
878
+ label: e.label,
879
+ labelOffset: e.labelOffset,
880
+ labelColor: e.labelColor,
881
+ labelFontSize: e.labelFontSize,
882
+ fadeIn: e.fadeIn,
883
+ fadeOut: e.fadeOut,
884
+ draw: e.draw,
885
+ easing: c(e.easing)
886
+ },
887
+ r
888
+ );
889
+ case "vectorField": {
890
+ const t = Ve(e.fn);
891
+ return /* @__PURE__ */ s(
892
+ We,
893
+ {
894
+ fn: (a, i) => t({ x: a, y: i }),
895
+ domain: e.domain,
896
+ range: e.range,
897
+ step: e.step,
898
+ origin: e.origin,
899
+ scale: e.scale,
900
+ arrowScale: e.arrowScale,
901
+ color: e.color,
902
+ strokeWidth: e.strokeWidth,
903
+ headSize: e.headSize,
904
+ normalize: e.normalize,
905
+ maxLength: e.maxLength,
906
+ fadeIn: e.fadeIn,
907
+ fadeOut: e.fadeOut,
908
+ easing: c(e.easing)
909
+ },
910
+ r
911
+ );
912
+ }
913
+ case "matrix":
914
+ return /* @__PURE__ */ s(
915
+ Me,
916
+ {
917
+ values: e.values,
918
+ x: e.x,
919
+ y: e.y,
920
+ cellSize: e.cellSize,
921
+ color: e.color,
922
+ bracketColor: e.bracketColor,
923
+ fontSize: e.fontSize,
924
+ fadeIn: e.fadeIn,
925
+ fadeOut: e.fadeOut,
926
+ easing: c(e.easing)
927
+ },
928
+ r
929
+ );
930
+ case "graph":
931
+ return /* @__PURE__ */ s(
932
+ Pe,
933
+ {
934
+ nodes: e.nodes,
935
+ edges: e.edges,
936
+ nodeColor: e.nodeColor,
937
+ nodeRadius: e.nodeRadius,
938
+ edgeColor: e.edgeColor,
939
+ edgeWidth: e.edgeWidth,
940
+ labelColor: e.labelColor,
941
+ labelFontSize: e.labelFontSize,
942
+ fadeIn: e.fadeIn,
943
+ fadeOut: e.fadeOut,
944
+ easing: c(e.easing)
945
+ },
946
+ r
947
+ );
948
+ case "latex":
949
+ return /* @__PURE__ */ s(
950
+ Fe,
951
+ {
952
+ expression: e.expression,
953
+ x: e.x,
954
+ y: e.y,
955
+ color: e.color,
956
+ fontSize: e.fontSize,
957
+ align: e.align,
958
+ fadeIn: e.fadeIn,
959
+ fadeOut: e.fadeOut,
960
+ easing: c(e.easing)
961
+ },
962
+ r
963
+ );
964
+ case "barChart":
965
+ return /* @__PURE__ */ s(
966
+ ze,
967
+ {
968
+ bars: e.bars,
969
+ x: e.x,
970
+ y: e.y,
971
+ width: e.width,
972
+ height: e.height,
973
+ barColor: e.barColor,
974
+ labelColor: e.labelColor,
975
+ labelFontSize: e.labelFontSize,
976
+ showValues: e.showValues,
977
+ maxValue: e.maxValue,
978
+ gap: e.gap,
979
+ valueFormat: e.valueFormat,
980
+ fadeIn: e.fadeIn,
981
+ fadeOut: e.fadeOut,
982
+ easing: c(e.easing)
983
+ },
984
+ r
985
+ );
986
+ case "fadeIn":
987
+ return /* @__PURE__ */ s(Oe, { duration: e.duration, easing: c(e.easing), children: e.children.map((t, a) => f(t, a)) }, r);
988
+ case "fadeOut":
989
+ return /* @__PURE__ */ s(Ee, { duration: e.duration, totalFrames: e.totalFrames, easing: c(e.easing), children: e.children.map((t, a) => f(t, a)) }, r);
990
+ case "draw":
991
+ return /* @__PURE__ */ s(Ae, { duration: e.duration, pathLength: e.pathLength, easing: c(e.easing), children: f(e.children[0], 0) }, r);
992
+ case "write":
993
+ return /* @__PURE__ */ s(Ce, { duration: e.duration, easing: c(e.easing), children: e.children.map((t, a) => f(t, a)) }, r);
994
+ case "transform":
995
+ return /* @__PURE__ */ s(
996
+ Ie,
997
+ {
998
+ duration: e.duration,
999
+ easing: c(e.easing),
1000
+ translate: e.translate,
1001
+ scale: e.scale,
1002
+ rotate: e.rotate,
1003
+ opacity: e.opacity,
1004
+ children: e.children.map((t, a) => f(t, a))
1005
+ },
1006
+ r
1007
+ );
1008
+ case "morph":
1009
+ return /* @__PURE__ */ s(
1010
+ Se,
1011
+ {
1012
+ duration: e.duration,
1013
+ easing: c(e.easing),
1014
+ fromColor: e.fromColor,
1015
+ toColor: e.toColor,
1016
+ fromOpacity: e.fromOpacity,
1017
+ toOpacity: e.toOpacity,
1018
+ fromScale: e.fromScale,
1019
+ toScale: e.toScale,
1020
+ children: e.children.map((t, a) => f(t, a))
1021
+ },
1022
+ r
1023
+ );
1024
+ case "stagger":
1025
+ return /* @__PURE__ */ s($e, { staggerDelay: e.staggerDelay, easing: c(e.easing), children: e.children.map((t, a) => f(t, a)) }, r);
1026
+ case "parallel":
1027
+ return /* @__PURE__ */ s(ke, { children: e.children.map((t, a) => f(t, a)) }, r);
1028
+ case "scene":
1029
+ return /* @__PURE__ */ s(z.Fragment, { children: G(e) }, r);
1030
+ case "player":
1031
+ return /* @__PURE__ */ s(z.Fragment, { children: Q(e) }, r);
1032
+ default:
1033
+ return null;
1034
+ }
1035
+ }
1036
+ class vt {
1037
+ constructor(r, t = 30, a = 900, i = 640) {
1038
+ this.elements = [], this.cursor = 0, this.theme = r, this._fps = t, this._width = a, this._height = i;
1039
+ }
1040
+ get width() {
1041
+ return this._width;
1042
+ }
1043
+ get height() {
1044
+ return this._height;
1045
+ }
1046
+ get fps() {
1047
+ return this._fps;
1048
+ }
1049
+ get cx() {
1050
+ return this._width / 2;
1051
+ }
1052
+ get cy() {
1053
+ return this._height / 2;
1054
+ }
1055
+ /** Current animation frame cursor */
1056
+ get frame() {
1057
+ return this.cursor;
1058
+ }
1059
+ /** Advance the cursor by N frames */
1060
+ wait(r) {
1061
+ return this.cursor += r, this;
1062
+ }
1063
+ /** Set cursor to an absolute frame */
1064
+ at(r) {
1065
+ return this.cursor = r, this;
1066
+ }
1067
+ // ─── High-level helpers ──────────────────────────────────────────────
1068
+ /** Large centered title text */
1069
+ title(r, t) {
1070
+ return this.addAtCursor({
1071
+ type: "fadeIn",
1072
+ duration: 15,
1073
+ children: [{
1074
+ type: "text",
1075
+ x: this.cx,
1076
+ y: (t == null ? void 0 : t.y) ?? 55,
1077
+ content: r,
1078
+ fontSize: (t == null ? void 0 : t.fontSize) ?? 28,
1079
+ fill: (t == null ? void 0 : t.color) ?? this.theme.title,
1080
+ textAnchor: "middle",
1081
+ fontWeight: "bold"
1082
+ }]
1083
+ }, 15);
1084
+ }
1085
+ /** Smaller subtitle text */
1086
+ subtitle(r, t) {
1087
+ return this.addAtCursor({
1088
+ type: "fadeIn",
1089
+ duration: 12,
1090
+ children: [{
1091
+ type: "text",
1092
+ x: this.cx,
1093
+ y: (t == null ? void 0 : t.y) ?? 95,
1094
+ content: r,
1095
+ fontSize: (t == null ? void 0 : t.fontSize) ?? 16,
1096
+ fill: (t == null ? void 0 : t.color) ?? this.theme.subtitle,
1097
+ textAnchor: "middle"
1098
+ }]
1099
+ }, 10);
1100
+ }
1101
+ /** Add a LaTeX expression */
1102
+ latex(r, t) {
1103
+ const a = (t == null ? void 0 : t.fadeIn) ?? 15;
1104
+ return this.addAtCursor({
1105
+ type: "fadeIn",
1106
+ duration: a,
1107
+ children: [{
1108
+ type: "latex",
1109
+ expression: r,
1110
+ x: (t == null ? void 0 : t.x) ?? this.cx,
1111
+ y: (t == null ? void 0 : t.y) ?? 300,
1112
+ fontSize: (t == null ? void 0 : t.fontSize) ?? 28,
1113
+ color: (t == null ? void 0 : t.color) ?? this.theme.primary,
1114
+ align: "center"
1115
+ }]
1116
+ }, (t == null ? void 0 : t.advance) ?? 10);
1117
+ }
1118
+ /** Add text at a position */
1119
+ text(r, t) {
1120
+ const a = t.fadeIn ?? 15, i = t.advance ?? 5;
1121
+ return this.addAtCursor({
1122
+ type: "fadeIn",
1123
+ duration: a,
1124
+ children: [{
1125
+ type: "text",
1126
+ x: t.x,
1127
+ y: t.y,
1128
+ content: r,
1129
+ fontSize: t.fontSize ?? 14,
1130
+ fill: t.color ?? this.theme.text,
1131
+ textAnchor: t.anchor ?? "middle",
1132
+ fontWeight: t.fontWeight,
1133
+ fontFamily: t.fontFamily
1134
+ }]
1135
+ }, i);
1136
+ }
1137
+ /** Add an arrow */
1138
+ arrow(r, t, a, i, n) {
1139
+ const l = (n == null ? void 0 : n.fadeIn) ?? 12, k = {
1140
+ type: "arrow",
1141
+ x1: r,
1142
+ y1: t,
1143
+ x2: a,
1144
+ y2: i,
1145
+ stroke: (n == null ? void 0 : n.color) ?? this.theme.primary,
1146
+ strokeWidth: (n == null ? void 0 : n.strokeWidth) ?? 2,
1147
+ headSize: (n == null ? void 0 : n.headSize) ?? 8,
1148
+ strokeDasharray: n != null && n.dashed ? "6 3" : void 0,
1149
+ fadeIn: l
1150
+ };
1151
+ return this.addAtCursor(k, (n == null ? void 0 : n.advance) ?? 3);
1152
+ }
1153
+ /** Add a line */
1154
+ line(r, t, a, i, n) {
1155
+ const l = (n == null ? void 0 : n.fadeIn) ?? 12;
1156
+ return this.addAtCursor({
1157
+ type: "line",
1158
+ x1: r,
1159
+ y1: t,
1160
+ x2: a,
1161
+ y2: i,
1162
+ stroke: (n == null ? void 0 : n.color) ?? this.theme.muted,
1163
+ strokeWidth: (n == null ? void 0 : n.strokeWidth) ?? 1,
1164
+ strokeDasharray: n != null && n.dashed ? "6 3" : void 0,
1165
+ fadeIn: l
1166
+ }, (n == null ? void 0 : n.advance) ?? 3);
1167
+ }
1168
+ /** Add a rectangle */
1169
+ rect(r, t, a, i, n) {
1170
+ const l = (n == null ? void 0 : n.fadeIn) ?? 12;
1171
+ return this.addAtCursor({
1172
+ type: "rect",
1173
+ x: r,
1174
+ y: t,
1175
+ width: a,
1176
+ height: i,
1177
+ fill: (n == null ? void 0 : n.fill) ?? "none",
1178
+ stroke: (n == null ? void 0 : n.stroke) ?? this.theme.boxStroke,
1179
+ strokeWidth: (n == null ? void 0 : n.strokeWidth) ?? 1.5,
1180
+ rx: (n == null ? void 0 : n.rx) ?? 6,
1181
+ strokeDasharray: n != null && n.dashed ? "6 3" : void 0,
1182
+ fadeIn: l
1183
+ }, (n == null ? void 0 : n.advance) ?? 5);
1184
+ }
1185
+ /** Add a circle */
1186
+ circle(r, t, a, i) {
1187
+ const n = (i == null ? void 0 : i.fadeIn) ?? 12;
1188
+ return this.addAtCursor({
1189
+ type: "circle",
1190
+ cx: r,
1191
+ cy: t,
1192
+ r: a,
1193
+ fill: (i == null ? void 0 : i.fill) ?? "none",
1194
+ stroke: (i == null ? void 0 : i.stroke) ?? this.theme.primary,
1195
+ strokeWidth: (i == null ? void 0 : i.strokeWidth) ?? 2,
1196
+ fadeIn: n
1197
+ }, (i == null ? void 0 : i.advance) ?? 5);
1198
+ }
1199
+ /** Add a bar chart */
1200
+ barChart(r, t) {
1201
+ const a = t.fadeIn ?? 20;
1202
+ return this.addAtCursor({
1203
+ type: "barChart",
1204
+ bars: r,
1205
+ x: t.x,
1206
+ y: t.y,
1207
+ width: t.width,
1208
+ height: t.height,
1209
+ barColor: t.barColor ?? this.theme.primary,
1210
+ labelColor: t.labelColor ?? this.theme.text,
1211
+ labelFontSize: t.labelFontSize,
1212
+ maxValue: t.maxValue,
1213
+ valueFormat: t.valueFormat,
1214
+ gap: t.gap,
1215
+ showValues: t.showValues,
1216
+ fadeIn: a
1217
+ }, 10);
1218
+ }
1219
+ /** Add a matrix visualization */
1220
+ matrix(r, t) {
1221
+ const a = (t == null ? void 0 : t.fadeIn) ?? 20;
1222
+ return this.addAtCursor({
1223
+ type: "matrix",
1224
+ values: r,
1225
+ x: (t == null ? void 0 : t.x) ?? this.cx,
1226
+ y: (t == null ? void 0 : t.y) ?? 300,
1227
+ cellSize: (t == null ? void 0 : t.cellSize) ?? 50,
1228
+ color: (t == null ? void 0 : t.color) ?? this.theme.text,
1229
+ bracketColor: (t == null ? void 0 : t.bracketColor) ?? this.theme.primary,
1230
+ fontSize: t == null ? void 0 : t.fontSize,
1231
+ fadeIn: a
1232
+ }, 10);
1233
+ }
1234
+ /** Add a graph (nodes + edges) */
1235
+ graph(r, t, a) {
1236
+ const i = (a == null ? void 0 : a.fadeIn) ?? 20;
1237
+ return this.addAtCursor({
1238
+ type: "graph",
1239
+ nodes: r,
1240
+ edges: t,
1241
+ nodeColor: (a == null ? void 0 : a.nodeColor) ?? this.theme.secondary,
1242
+ edgeColor: (a == null ? void 0 : a.edgeColor) ?? this.theme.muted,
1243
+ labelColor: (a == null ? void 0 : a.labelColor) ?? "#fff",
1244
+ nodeRadius: a == null ? void 0 : a.nodeRadius,
1245
+ edgeWidth: a == null ? void 0 : a.edgeWidth,
1246
+ fadeIn: i
1247
+ }, 10);
1248
+ }
1249
+ // ─── Layout helpers ──────────────────────────────────────────────────
1250
+ /**
1251
+ * Render a horizontal row of labeled boxes.
1252
+ * Returns the box positions for follow-up arrows, etc.
1253
+ */
1254
+ boxRow(r, t) {
1255
+ const a = (t == null ? void 0 : t.boxWidth) ?? 80, i = (t == null ? void 0 : t.boxHeight) ?? 40, n = (t == null ? void 0 : t.gap) ?? 12, l = (t == null ? void 0 : t.y) ?? 250, k = r.length * a + (r.length - 1) * n, I = (this._width - k) / 2;
1256
+ t == null || t.fadeIn;
1257
+ const C = r.map((m, h) => {
1258
+ const g = I + h * (a + n);
1259
+ return { x: g, y: l, w: a, h: i, cx: g + a / 2, cy: l + i / 2 };
1260
+ }), A = r.map((m, h) => {
1261
+ var D, T;
1262
+ const g = C[h], E = ((D = t == null ? void 0 : t.colors) == null ? void 0 : D[h]) ?? this.theme.boxFill, O = ((T = t == null ? void 0 : t.strokeColors) == null ? void 0 : T[h]) ?? this.theme.boxStroke;
1263
+ return {
1264
+ type: "group",
1265
+ children: [
1266
+ {
1267
+ type: "rect",
1268
+ x: g.x,
1269
+ y: g.y,
1270
+ width: a,
1271
+ height: i,
1272
+ fill: E,
1273
+ stroke: O,
1274
+ strokeWidth: 1.5,
1275
+ rx: 6
1276
+ },
1277
+ {
1278
+ type: "text",
1279
+ x: g.cx,
1280
+ y: g.cy + 5,
1281
+ content: m,
1282
+ fontSize: (t == null ? void 0 : t.fontSize) ?? 13,
1283
+ fill: (t == null ? void 0 : t.textColor) ?? this.theme.text,
1284
+ textAnchor: "middle",
1285
+ fontFamily: t == null ? void 0 : t.fontFamily
1286
+ }
1287
+ ]
1288
+ };
1289
+ });
1290
+ return this.addAtCursor({
1291
+ type: "stagger",
1292
+ staggerDelay: 3,
1293
+ children: A
1294
+ }, 8 + r.length * 2), C;
1295
+ }
1296
+ /**
1297
+ * Render a vertical stack of labeled boxes.
1298
+ */
1299
+ boxColumn(r, t) {
1300
+ const a = (t == null ? void 0 : t.boxWidth) ?? 160, i = (t == null ? void 0 : t.boxHeight) ?? 36, n = (t == null ? void 0 : t.gap) ?? 8, l = (t == null ? void 0 : t.y) ?? 150, k = (t == null ? void 0 : t.x) ?? this.cx;
1301
+ t == null || t.fadeIn;
1302
+ const I = r.map((A, m) => {
1303
+ const h = l + m * (i + n);
1304
+ return { x: k - a / 2, y: h, w: a, h: i, cx: k, cy: h + i / 2 };
1305
+ }), C = r.map((A, m) => {
1306
+ var E, O;
1307
+ const h = I[m], g = ((E = t == null ? void 0 : t.colors) == null ? void 0 : E[m]) ?? this.theme.boxFill;
1308
+ return {
1309
+ type: "group",
1310
+ children: [
1311
+ {
1312
+ type: "rect",
1313
+ x: h.x,
1314
+ y: h.y,
1315
+ width: a,
1316
+ height: i,
1317
+ fill: g,
1318
+ stroke: (O = t == null ? void 0 : t.colors) != null && O[m] ? t.colors[m] : this.theme.boxStroke,
1319
+ strokeWidth: 1.5,
1320
+ rx: 6
1321
+ },
1322
+ {
1323
+ type: "text",
1324
+ x: h.cx,
1325
+ y: h.cy + 5,
1326
+ content: A,
1327
+ fontSize: (t == null ? void 0 : t.fontSize) ?? 13,
1328
+ fill: (t == null ? void 0 : t.textColor) ?? this.theme.text,
1329
+ textAnchor: "middle"
1330
+ }
1331
+ ]
1332
+ };
1333
+ });
1334
+ return this.addAtCursor({
1335
+ type: "stagger",
1336
+ staggerDelay: 3,
1337
+ children: C
1338
+ }, 8 + r.length * 2), I;
1339
+ }
1340
+ /**
1341
+ * Draw arrows connecting sequential positions (e.g., output of boxRow/boxColumn).
1342
+ */
1343
+ connectDown(r, t) {
1344
+ const a = [];
1345
+ for (let i = 0; i < r.length - 1; i++) {
1346
+ const n = r[i], l = r[i + 1];
1347
+ a.push({
1348
+ type: "arrow",
1349
+ x1: n.cx,
1350
+ y1: n.y + n.h + 2,
1351
+ x2: l.cx,
1352
+ y2: l.y - 2,
1353
+ stroke: (t == null ? void 0 : t.color) ?? this.theme.muted,
1354
+ strokeWidth: 1.5,
1355
+ headSize: (t == null ? void 0 : t.headSize) ?? 6
1356
+ });
1357
+ }
1358
+ return this.addAtCursor({
1359
+ type: "stagger",
1360
+ staggerDelay: 2,
1361
+ children: a
1362
+ }, 5 + r.length * 2);
1363
+ }
1364
+ /**
1365
+ * Draw arrows between two rows of boxes (fan-out pattern).
1366
+ */
1367
+ connectRows(r, t, a) {
1368
+ const i = [];
1369
+ if (r.length === t.length)
1370
+ for (let n = 0; n < r.length; n++)
1371
+ i.push({
1372
+ type: "arrow",
1373
+ x1: r[n].cx,
1374
+ y1: r[n].y + r[n].h + 2,
1375
+ x2: t[n].cx,
1376
+ y2: t[n].y - 2,
1377
+ stroke: (a == null ? void 0 : a.color) ?? this.theme.muted,
1378
+ strokeWidth: 1.5,
1379
+ headSize: (a == null ? void 0 : a.headSize) ?? 6
1380
+ });
1381
+ return this.addAtCursor({
1382
+ type: "fadeIn",
1383
+ duration: 15,
1384
+ children: i
1385
+ }, 15);
1386
+ }
1387
+ // ─── Raw element access ──────────────────────────────────────────────
1388
+ /** Add any raw ElementNode at the current cursor position */
1389
+ add(r, t = 0) {
1390
+ return this.addAtCursor(r, t);
1391
+ }
1392
+ /** Add a raw element at a specific frame (doesn't move cursor) */
1393
+ addAt(r, t) {
1394
+ return this.elements.push({
1395
+ type: "sequence",
1396
+ from: r,
1397
+ children: [t]
1398
+ }), this;
1399
+ }
1400
+ /** Add multiple raw elements simultaneously at current cursor */
1401
+ addAll(r, t = 0) {
1402
+ return this.addAtCursor({
1403
+ type: "group",
1404
+ children: r
1405
+ }, t);
1406
+ }
1407
+ // ─── Internal ────────────────────────────────────────────────────────
1408
+ addAtCursor(r, t) {
1409
+ return this.elements.push({
1410
+ type: "sequence",
1411
+ from: this.cursor,
1412
+ children: [r]
1413
+ }), this.cursor += t, this;
1414
+ }
1415
+ /** Build the slide's player node with all timed elements */
1416
+ _build() {
1417
+ const r = Math.max(this.cursor + 60, 90);
1418
+ return { elements: this.elements, durationInFrames: r };
1419
+ }
1420
+ }
1421
+ const wt = {
1422
+ background: "#0a0a1e",
1423
+ title: "#e0e7ff",
1424
+ subtitle: "#94a3b8",
1425
+ primary: "#4fc3f7",
1426
+ secondary: "#a78bfa",
1427
+ tertiary: "#f472b6",
1428
+ muted: "#64748b",
1429
+ text: "#c8d6e5",
1430
+ boxFill: "rgba(79,195,247,0.12)",
1431
+ boxStroke: "#4fc3f7",
1432
+ success: "#34d399",
1433
+ warning: "#fbbf24",
1434
+ error: "#f87171",
1435
+ palette: ["#4fc3f7", "#a78bfa", "#f472b6", "#34d399", "#fbbf24", "#fb923c", "#6366f1", "#22d3ee"]
1436
+ }, At = {
1437
+ background: "#f8fafc",
1438
+ title: "#1e293b",
1439
+ subtitle: "#64748b",
1440
+ primary: "#2563eb",
1441
+ secondary: "#7c3aed",
1442
+ tertiary: "#db2777",
1443
+ muted: "#94a3b8",
1444
+ text: "#334155",
1445
+ boxFill: "rgba(37,99,235,0.08)",
1446
+ boxStroke: "#2563eb",
1447
+ success: "#16a34a",
1448
+ warning: "#d97706",
1449
+ error: "#dc2626",
1450
+ palette: ["#2563eb", "#7c3aed", "#db2777", "#16a34a", "#d97706", "#ea580c", "#4f46e5", "#0891b2"]
1451
+ };
1452
+ class kt {
1453
+ constructor(r, t, a) {
1454
+ this._slides = [], this._title = r, this._theme = t ?? wt, this._opts = {
1455
+ width: 900,
1456
+ height: 640,
1457
+ fps: 30,
1458
+ transition: "fade",
1459
+ transitionDuration: 10,
1460
+ showHud: !0,
1461
+ showNotes: !0,
1462
+ ...a
1463
+ };
1464
+ }
1465
+ /** Add a slide */
1466
+ slide(r, t, a) {
1467
+ return this._slides.push({ title: r, build: t, notes: a == null ? void 0 : a.notes, background: a == null ? void 0 : a.background }), this;
1468
+ }
1469
+ /** Build the final ElucimDocument */
1470
+ build() {
1471
+ const r = this._slides.map((a) => {
1472
+ const i = new vt(
1473
+ this._theme,
1474
+ this._opts.fps,
1475
+ this._opts.width,
1476
+ this._opts.height
1477
+ );
1478
+ a.build(i);
1479
+ const { elements: n, durationInFrames: l } = i._build();
1480
+ return {
1481
+ type: "slide",
1482
+ title: a.title,
1483
+ notes: a.notes,
1484
+ background: a.background,
1485
+ children: [{
1486
+ type: "player",
1487
+ width: this._opts.width,
1488
+ height: this._opts.height,
1489
+ fps: this._opts.fps,
1490
+ durationInFrames: l,
1491
+ controls: !1,
1492
+ loop: !1,
1493
+ autoPlay: !0,
1494
+ children: n
1495
+ }]
1496
+ };
1497
+ });
1498
+ return {
1499
+ version: "1.0",
1500
+ root: {
1501
+ type: "presentation",
1502
+ width: this._opts.width,
1503
+ height: this._opts.height,
1504
+ background: this._theme.background,
1505
+ transition: this._opts.transition,
1506
+ transitionDuration: this._opts.transitionDuration,
1507
+ showHud: this._opts.showHud,
1508
+ showNotes: this._opts.showNotes,
1509
+ slides: r
1510
+ }
1511
+ };
1512
+ }
1513
+ /** Build and return as JSON string (for saving to file) */
1514
+ toJSON(r = !0) {
1515
+ return JSON.stringify(this.build(), null, r ? 2 : void 0);
1516
+ }
1517
+ }
1518
+ function Et(e, r, t) {
1519
+ return new kt(e, r, t);
1520
+ }
1521
+ export {
1522
+ Ct as DslRenderer,
1523
+ kt as PresentationBuilder,
1524
+ vt as SlideBuilder,
1525
+ Be as compileExpression,
1526
+ Ve as compileVectorExpression,
1527
+ wt as darkTheme,
1528
+ At as lightTheme,
1529
+ Et as presentation,
1530
+ c as resolveEasing,
1531
+ He as validate,
1532
+ U as validateExpression
1533
+ };