@elucim/dsl 0.2.0 → 0.3.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/README.md CHANGED
@@ -126,6 +126,8 @@ Every document has this structure:
126
126
  | `rect` | `x`, `y`, `width`, `height` | Rectangle |
127
127
  | `polygon` | `points` (array of [x,y]) | Polygon/polyline |
128
128
  | `text` | `x`, `y`, `content` | Text element |
129
+ | `image` | `src`, `x`, `y`, `width`, `height` | Embed external images (PNG, SVG, etc.) |
130
+ | `barChart` | `bars` | Animated bar chart with labels and colors |
129
131
 
130
132
  #### Math Visualizations
131
133
  | Type | Required Props | Description |
@@ -154,7 +156,7 @@ Every document has this structure:
154
156
  | Type | Key Props | Description |
155
157
  |------|----------|-------------|
156
158
  | `sequence` | `from`, `durationInFrames` | Time-offset wrapper |
157
- | `group` | `children` | Logical grouping |
159
+ | `group` | `children` | Logical grouping with shared transforms (rotation, scale, translate) and zIndex sorting of children |
158
160
 
159
161
  ### Inline Animation Props
160
162
 
@@ -164,6 +166,15 @@ All primitives support these optional animation props directly:
164
166
  - `draw?: number` — Progressive stroke draw over N frames
165
167
  - `easing?: string | { type, ... }` — Easing function
166
168
 
169
+ ### Spatial Transform Props
170
+
171
+ All primitives and groups support these optional spatial transform props:
172
+ - `rotation?: number` — Rotate element in degrees
173
+ - `rotationOrigin?: [number, number]` — Center of rotation [cx, cy]
174
+ - `scale?: number` — Uniform scale factor
175
+ - `translate?: [number, number]` — Offset [dx, dy]
176
+ - `zIndex?: number` — Stacking order (higher renders on top)
177
+
167
178
  ### Easing
168
179
 
169
180
  **Named easings:** `linear`, `easeInQuad`, `easeOutQuad`, `easeInOutQuad`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`, `easeInQuart`, `easeOutQuart`, `easeInOutQuart`, `easeInSine`, `easeOutSine`, `easeInOutSine`, `easeInExpo`, `easeOutExpo`, `easeInOutExpo`, `easeInBack`, `easeOutBack`, `easeOutElastic`, `easeOutBounce`
package/dist/index.d.ts CHANGED
@@ -80,6 +80,33 @@ export declare interface BarChartNode {
80
80
  zIndex?: number;
81
81
  }
82
82
 
83
+ export declare interface BezierCurveNode {
84
+ type: 'bezierCurve';
85
+ id?: string;
86
+ x1: number;
87
+ y1: number;
88
+ cx1: number;
89
+ cy1: number;
90
+ cx2?: number;
91
+ cy2?: number;
92
+ x2: number;
93
+ y2: number;
94
+ stroke?: string;
95
+ strokeWidth?: number;
96
+ fill?: string;
97
+ strokeDasharray?: string;
98
+ opacity?: number;
99
+ fadeIn?: number;
100
+ fadeOut?: number;
101
+ draw?: number;
102
+ easing?: EasingSpec;
103
+ rotation?: number;
104
+ rotationOrigin?: [number, number];
105
+ scale?: number | [number, number];
106
+ translate?: [number, number];
107
+ zIndex?: number;
108
+ }
109
+
83
110
  export declare interface CircleNode {
84
111
  type: 'circle';
85
112
  id?: string;
@@ -154,7 +181,7 @@ declare type EasingName = 'linear' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQu
154
181
 
155
182
  export declare type EasingSpec = EasingName | SpringEasing | CubicBezierEasing;
156
183
 
157
- export declare type ElementNode = SequenceNode | GroupNode | CircleNode | LineNode | ArrowNode | RectNode | PolygonNode | TextNode | ImageNode | AxesNode | FunctionPlotNode | VectorNode | VectorFieldNode | MatrixNode | GraphNode | LaTeXNode | BarChartNode | FadeInNode | FadeOutNode | DrawNode | WriteNode | TransformNode | MorphNode | StaggerNode | ParallelNode | PlayerNode | SceneNode;
184
+ export declare type ElementNode = SequenceNode | GroupNode | BezierCurveNode | CircleNode | LineNode | ArrowNode | RectNode | PolygonNode | TextNode | ImageNode | AxesNode | FunctionPlotNode | VectorNode | VectorFieldNode | MatrixNode | GraphNode | LaTeXNode | BarChartNode | FadeInNode | FadeOutNode | DrawNode | WriteNode | TransformNode | MorphNode | StaggerNode | ParallelNode | PlayerNode | SceneNode;
158
185
 
159
186
  export declare interface ElucimDocument {
160
187
  /** JSON Schema URL for editor autocomplete */
@@ -252,7 +279,7 @@ export declare interface GroupNode {
252
279
  zIndex?: number;
253
280
  }
254
281
 
255
- declare interface ImageNode {
282
+ export declare interface ImageNode {
256
283
  type: 'image';
257
284
  id?: string;
258
285
  src: string;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { easeOutBounce as J, easeOutElastic as Z, easeOutBack as ee, easeInBack as te, easeInOutExpo as ae, easeOutExpo as ie, easeInExpo as re, easeInOutSine as ne, easeOutSine as se, easeInSine as ce, easeInOutQuart as le, easeOutQuart as ue, easeInQuart as he, easeInOutCubic as fe, easeOutCubic as ge, easeInCubic as oe, easeInOutQuad as ye, easeOutQuad as me, easeInQuad as be, linear as xe, spring as ve, cubicBezier as de, Presentation as we, Player as ke, Scene as Ie, Slide as $e, Parallel as Se, Stagger as Oe, Morph as Ae, Transform as Ce, Write as ze, Draw as Ee, FadeOut as Fe, FadeIn as Pe, BarChart as Re, LaTeX as pe, Graph as Ne, Matrix as Me, VectorField as We, Vector as _e, FunctionPlot as De, Axes as Te, Image as Le, Text as je, Polygon as qe, Rect as Be, Arrow as Ue, Line as Ve, Circle as He, Group as Ge, Sequence as Qe } from "@elucim/core";
1
+ import { easeOutBounce as J, easeOutElastic as Z, easeOutBack as ee, easeInBack as te, easeInOutExpo as ae, easeOutExpo as ie, easeInExpo as re, easeInOutSine as ne, easeOutSine as se, easeInSine as ce, easeInOutQuart as le, easeOutQuart as ue, easeInQuart as he, easeInOutCubic as fe, easeOutCubic as ge, easeInCubic as ye, easeInOutQuad as oe, easeOutQuad as me, easeInQuad as be, linear as xe, spring as ve, cubicBezier as we, Presentation as de, Player as ke, Scene as Ie, Slide as $e, Parallel as Se, Stagger as Oe, Morph as Ce, Transform as Ae, Write as ze, Draw as Ee, FadeOut as Fe, FadeIn as Pe, BarChart as Re, LaTeX as Ne, Graph as We, Matrix as Me, VectorField as _e, Vector as De, FunctionPlot as pe, Axes as Te, Image as Le, Text as je, Polygon as qe, Rect as Be, Arrow as Ue, Line as Ve, Circle as He, BezierCurve as Ge, Group as Qe, Sequence as Ke } from "@elucim/core";
2
2
  import { jsxs as L, jsx as s } from "react/jsx-runtime";
3
3
  import j from "react";
4
- const N = {
4
+ const W = {
5
5
  sin: Math.sin,
6
6
  cos: Math.cos,
7
7
  tan: Math.tan,
@@ -26,7 +26,7 @@ const N = {
26
26
  E: Math.E,
27
27
  TAU: Math.PI * 2
28
28
  };
29
- function W(e) {
29
+ function _(e) {
30
30
  const a = [];
31
31
  let t = 0;
32
32
  for (; t < e.length; ) {
@@ -89,7 +89,7 @@ function W(e) {
89
89
  }
90
90
  return a.push({ type: "EOF", value: "", pos: t }), a;
91
91
  }
92
- class _ {
92
+ class D {
93
93
  constructor(a) {
94
94
  this.pos = 0, this.tokens = a;
95
95
  }
@@ -167,9 +167,9 @@ class _ {
167
167
  if (this.peek().type !== "RPAREN")
168
168
  for (i.push(this.parseExpression()); this.peek().type === "COMMA"; )
169
169
  this.advance(), i.push(this.parseExpression());
170
- if (this.expect("RPAREN"), !Object.prototype.hasOwnProperty.call(N, t))
170
+ if (this.expect("RPAREN"), !Object.prototype.hasOwnProperty.call(W, t))
171
171
  throw new x(
172
- `Unknown function '${t}'. Available: ${Object.keys(N).join(", ")}`,
172
+ `Unknown function '${t}'. Available: ${Object.keys(W).join(", ")}`,
173
173
  a.pos
174
174
  );
175
175
  return { kind: "call", name: t, args: i };
@@ -195,7 +195,7 @@ class _ {
195
195
  );
196
196
  }
197
197
  }
198
- function w(e, a) {
198
+ function d(e, a) {
199
199
  switch (e.kind) {
200
200
  case "number":
201
201
  return e.value;
@@ -203,10 +203,10 @@ function w(e, a) {
203
203
  if (Object.prototype.hasOwnProperty.call(a, e.name)) return a[e.name];
204
204
  throw new x(`Unknown variable '${e.name}'`, 0);
205
205
  case "unary":
206
- const t = w(e.operand, a);
206
+ const t = d(e.operand, a);
207
207
  return e.op === "-" ? -t : t;
208
208
  case "binary": {
209
- const i = w(e.left, a), r = w(e.right, a);
209
+ const i = d(e.left, a), r = d(e.right, a);
210
210
  switch (e.op) {
211
211
  case "+":
212
212
  return i + r;
@@ -222,11 +222,11 @@ function w(e, a) {
222
222
  break;
223
223
  }
224
224
  case "call": {
225
- const i = N[e.name], r = e.args.map((n) => w(n, a));
225
+ const i = W[e.name], r = e.args.map((n) => d(n, a));
226
226
  return i(...r);
227
227
  }
228
228
  case "array":
229
- return e.elements.map((i) => w(i, a));
229
+ return e.elements.map((i) => d(i, a));
230
230
  }
231
231
  throw new x("Invalid AST node", 0);
232
232
  }
@@ -235,23 +235,23 @@ class x extends Error {
235
235
  super(a), this.name = "ExpressionError", this.position = t;
236
236
  }
237
237
  }
238
- function Ke(e) {
239
- const a = W(e), t = new _(a).parse();
240
- return (i) => w(t, i);
241
- }
242
238
  function Xe(e) {
243
- const a = W(e), t = new _(a).parse();
239
+ const a = _(e), t = new D(a).parse();
240
+ return (i) => d(t, i);
241
+ }
242
+ function Ye(e) {
243
+ const a = _(e), t = new D(a).parse();
244
244
  if (t.kind !== "array" || t.elements.length !== 2)
245
245
  throw new x(
246
246
  'Vector expression must be an array of 2 elements, e.g. "[-y, x]"',
247
247
  0
248
248
  );
249
- return (i) => w(t, i);
249
+ return (i) => d(t, i);
250
250
  }
251
251
  function H(e) {
252
252
  try {
253
- const a = W(e);
254
- return new _(a).parse(), null;
253
+ const a = _(e);
254
+ return new D(a).parse(), null;
255
255
  } catch (a) {
256
256
  return a instanceof x ? `${a.message} (at position ${a.position})` : String(a);
257
257
  }
@@ -260,8 +260,8 @@ const M = {
260
260
  linear: xe,
261
261
  easeInQuad: be,
262
262
  easeOutQuad: me,
263
- easeInOutQuad: ye,
264
- easeInCubic: oe,
263
+ easeInOutQuad: oe,
264
+ easeInCubic: ye,
265
265
  easeOutCubic: ge,
266
266
  easeInOutCubic: fe,
267
267
  easeInQuart: he,
@@ -278,7 +278,7 @@ const M = {
278
278
  easeOutElastic: Z,
279
279
  easeOutBounce: J
280
280
  };
281
- function c(e) {
281
+ function l(e) {
282
282
  if (e !== void 0) {
283
283
  if (typeof e == "string") {
284
284
  const a = M[e];
@@ -295,24 +295,25 @@ function c(e) {
295
295
  mass: e.mass
296
296
  });
297
297
  if (e.type === "cubicBezier")
298
- return de(e.x1, e.y1, e.x2, e.y2);
298
+ return we(e.x1, e.y1, e.x2, e.y2);
299
299
  throw new Error(`Unknown easing type: ${e.type}`);
300
300
  }
301
301
  }
302
302
  const R = Object.keys(M);
303
- function Ye(e) {
303
+ function Je(e) {
304
304
  const a = [];
305
305
  if (!e || typeof e != "object")
306
306
  return a.push({ path: "", message: "Document must be an object", severity: "error" }), { valid: !1, errors: a };
307
307
  const t = e;
308
- return t.version !== "1.0" && a.push({ path: "version", message: `Expected version "1.0", got "${t.version}"`, severity: "error" }), !t.root || typeof t.root != "object" ? (a.push({ path: "root", message: 'Missing or invalid "root" node', severity: "error" }), { valid: a.filter((i) => i.severity === "error").length === 0, errors: a }) : (Je(t.root, "root", a), {
308
+ return t.version !== "1.0" && a.push({ path: "version", message: `Expected version "1.0", got "${t.version}"`, severity: "error" }), !t.root || typeof t.root != "object" ? (a.push({ path: "root", message: 'Missing or invalid "root" node', severity: "error" }), { valid: a.filter((i) => i.severity === "error").length === 0, errors: a }) : (Ze(t.root, "root", a), {
309
309
  valid: a.filter((i) => i.severity === "error").length === 0,
310
310
  errors: a
311
311
  });
312
312
  }
313
- const B = ["scene", "player", "presentation"], p = [
313
+ const B = ["scene", "player", "presentation"], N = [
314
314
  "sequence",
315
315
  "group",
316
+ "bezierCurve",
316
317
  "circle",
317
318
  "line",
318
319
  "arrow",
@@ -339,19 +340,19 @@ const B = ["scene", "player", "presentation"], p = [
339
340
  "player",
340
341
  "scene"
341
342
  ], U = ["none", "fade", "slide-left", "slide-up", "zoom"];
342
- function Je(e, a, t) {
343
+ function Ze(e, a, t) {
343
344
  const i = e.type;
344
345
  if (!B.includes(i)) {
345
346
  t.push({ path: `${a}.type`, message: `Root type must be one of: ${B.join(", ")}. Got "${i}"`, severity: "error" });
346
347
  return;
347
348
  }
348
- i === "scene" || i === "player" ? G(e, a, i, t) : i === "presentation" && Ze(e, a, t);
349
+ i === "scene" || i === "player" ? G(e, a, i, t) : i === "presentation" && et(e, a, t);
349
350
  }
350
351
  function G(e, a, t, i) {
351
- St(e, "durationInFrames", a, i), h(e, "width", a, i), h(e, "height", a, i), h(e, "fps", a, i), v(e, "background", a, i), t === "player" && (S(e, "controls", a, i), S(e, "loop", a, i), S(e, "autoPlay", a, i)), d(e, a, i);
352
+ Ct(e, "durationInFrames", a, i), h(e, "width", a, i), h(e, "height", a, i), h(e, "fps", a, i), v(e, "background", a, i), t === "player" && (O(e, "controls", a, i), O(e, "loop", a, i), O(e, "autoPlay", a, i)), w(e, a, i);
352
353
  }
353
- function Ze(e, a, t) {
354
- if (h(e, "width", a, t), h(e, "height", a, t), v(e, "background", a, t), h(e, "transitionDuration", a, t), S(e, "showHud", a, t), S(e, "showNotes", a, t), e.transition !== void 0 && (U.includes(e.transition) || t.push({
354
+ function et(e, a, t) {
355
+ if (h(e, "width", a, t), h(e, "height", a, t), v(e, "background", a, t), h(e, "transitionDuration", a, t), O(e, "showHud", a, t), O(e, "showNotes", a, t), e.transition !== void 0 && (U.includes(e.transition) || t.push({
355
356
  path: `${a}.transition`,
356
357
  message: `Invalid transition "${e.transition}". Must be one of: ${U.join(", ")}`,
357
358
  severity: "error"
@@ -360,10 +361,10 @@ function Ze(e, a, t) {
360
361
  return;
361
362
  }
362
363
  e.slides.length === 0 && t.push({ path: `${a}.slides`, message: "Presentation must have at least one slide", severity: "warning" }), e.slides.forEach((i, r) => {
363
- et(i, `${a}.slides[${r}]`, t);
364
+ tt(i, `${a}.slides[${r}]`, t);
364
365
  });
365
366
  }
366
- function et(e, a, t) {
367
+ function tt(e, a, t) {
367
368
  if (!e || typeof e != "object") {
368
369
  t.push({ path: a, message: "Slide must be an object", severity: "error" });
369
370
  return;
@@ -372,7 +373,7 @@ function et(e, a, t) {
372
373
  Q(i, `${a}.children[${r}]`, t);
373
374
  }) : t.push({ path: `${a}.children`, message: "Slide children must be an array", severity: "error" }));
374
375
  }
375
- function d(e, a, t) {
376
+ function w(e, a, t) {
376
377
  if (!Array.isArray(e.children)) {
377
378
  t.push({ path: `${a}.children`, message: 'Expected "children" array', severity: "error" });
378
379
  return;
@@ -387,84 +388,87 @@ function Q(e, a, t) {
387
388
  return;
388
389
  }
389
390
  const i = e.type;
390
- if (!i || !p.includes(i)) {
391
- const r = i ? K(i, p) : "";
391
+ if (!i || !N.includes(i)) {
392
+ const r = i ? K(i, N) : "";
392
393
  t.push({
393
394
  path: `${a}.type`,
394
- message: `Unknown element type "${i}".${r} Valid types: ${p.join(", ")}`,
395
+ message: `Unknown element type "${i}".${r} Valid types: ${N.join(", ")}`,
395
396
  severity: "error"
396
397
  });
397
398
  return;
398
399
  }
399
400
  switch (i) {
401
+ case "bezierCurve":
402
+ at(e, a, t);
403
+ break;
400
404
  case "circle":
401
- tt(e, a, t);
405
+ it(e, a, t);
402
406
  break;
403
407
  case "line":
404
- at(e, a, t);
408
+ rt(e, a, t);
405
409
  break;
406
410
  case "arrow":
407
- it(e, a, t);
411
+ nt(e, a, t);
408
412
  break;
409
413
  case "rect":
410
- rt(e, a, t);
414
+ st(e, a, t);
411
415
  break;
412
416
  case "polygon":
413
- nt(e, a, t);
417
+ ct(e, a, t);
414
418
  break;
415
419
  case "text":
416
- st(e, a, t);
420
+ lt(e, a, t);
417
421
  break;
418
422
  case "image":
419
- kt(e, a, t);
423
+ $t(e, a, t);
420
424
  break;
421
425
  case "axes":
422
- ct(e, a, t);
426
+ ut(e, a, t);
423
427
  break;
424
428
  case "functionPlot":
425
- lt(e, a, t);
429
+ ht(e, a, t);
426
430
  break;
427
431
  case "vector":
428
- ut(e, a, t);
432
+ ft(e, a, t);
429
433
  break;
430
434
  case "vectorField":
431
- ht(e, a, t);
435
+ gt(e, a, t);
432
436
  break;
433
437
  case "matrix":
434
- ft(e, a, t);
438
+ yt(e, a, t);
435
439
  break;
436
440
  case "graph":
437
- gt(e, a, t);
441
+ ot(e, a, t);
438
442
  break;
439
443
  case "latex":
440
- ot(e, a, t);
444
+ mt(e, a, t);
441
445
  break;
442
446
  case "barChart":
443
- $t(e, a, t);
447
+ Ot(e, a, t);
444
448
  break;
445
449
  case "sequence":
446
- yt(e, a, t);
450
+ bt(e, a, t);
447
451
  break;
448
452
  case "group":
449
- It(e, a, t);
453
+ St(e, a, t);
450
454
  break;
451
455
  case "parallel":
452
- d(e, a, t);
456
+ w(e, a, t);
453
457
  break;
454
458
  case "fadeIn":
455
459
  case "fadeOut":
456
460
  case "draw":
457
461
  case "write":
458
- mt(e, a, t);
462
+ xt(e, a, t);
459
463
  break;
460
464
  case "transform":
461
- bt(e, a, t);
465
+ vt(e, a, t);
462
466
  break;
463
467
  case "morph":
464
- xt(e, a, t);
468
+ wt(e, a, t);
465
469
  break;
466
470
  case "stagger":
467
- vt(e, a, t);
471
+ dt(e, a, t);
468
472
  break;
469
473
  case "scene":
470
474
  case "player":
@@ -472,79 +476,82 @@ function Q(e, a, t) {
472
476
  break;
473
477
  }
474
478
  }
475
- function tt(e, a, t) {
476
- l(e, "cx", a, t), l(e, "cy", a, t), k(e, "r", a, t), o(e, a, t);
477
- }
478
479
  function at(e, a, t) {
479
- l(e, "x1", a, t), l(e, "y1", a, t), l(e, "x2", a, t), l(e, "y2", a, t), o(e, a, t);
480
+ c(e, "x1", a, t), c(e, "y1", a, t), c(e, "cx1", a, t), c(e, "cy1", a, t), c(e, "x2", a, t), c(e, "y2", a, t), e.cx2 !== void 0 && $(e, "cx2", a, t), e.cy2 !== void 0 && $(e, "cy2", a, t), y(e, a, t);
480
481
  }
481
482
  function it(e, a, t) {
482
- l(e, "x1", a, t), l(e, "y1", a, t), l(e, "x2", a, t), l(e, "y2", a, t), o(e, a, t);
483
+ c(e, "cx", a, t), c(e, "cy", a, t), k(e, "r", a, t), y(e, a, t);
483
484
  }
484
485
  function rt(e, a, t) {
485
- l(e, "x", a, t), l(e, "y", a, t), k(e, "width", a, t), k(e, "height", a, t), o(e, a, t);
486
+ c(e, "x1", a, t), c(e, "y1", a, t), c(e, "x2", a, t), c(e, "y2", a, t), y(e, a, t);
486
487
  }
487
488
  function nt(e, a, t) {
488
- Array.isArray(e.points) ? e.points.length < 3 ? t.push({ path: `${a}.points`, message: "Polygon requires at least 3 points", severity: "error" }) : e.points.forEach((i, r) => {
489
- (!Array.isArray(i) || i.length !== 2 || typeof i[0] != "number" || typeof i[1] != "number") && t.push({ path: `${a}.points[${r}]`, message: "Each point must be [number, number]", severity: "error" });
490
- }) : t.push({ path: `${a}.points`, message: 'Polygon requires a "points" array', severity: "error" }), o(e, a, t);
489
+ c(e, "x1", a, t), c(e, "y1", a, t), c(e, "x2", a, t), c(e, "y2", a, t), y(e, a, t);
491
490
  }
492
491
  function st(e, a, t) {
493
- l(e, "x", a, t), l(e, "y", a, t), typeof e.content != "string" && t.push({ path: `${a}.content`, message: 'Text requires a "content" string', severity: "error" }), o(e, a, t);
492
+ c(e, "x", a, t), c(e, "y", a, t), k(e, "width", a, t), k(e, "height", a, t), y(e, a, t);
494
493
  }
495
494
  function ct(e, a, t) {
496
- y(e, "domain", a, t), y(e, "range", a, t), y(e, "origin", a, t), P(e, a, t);
495
+ Array.isArray(e.points) ? e.points.length < 3 ? t.push({ path: `${a}.points`, message: "Polygon requires at least 3 points", severity: "error" }) : e.points.forEach((i, r) => {
496
+ (!Array.isArray(i) || i.length !== 2 || typeof i[0] != "number" || typeof i[1] != "number") && t.push({ path: `${a}.points[${r}]`, message: "Each point must be [number, number]", severity: "error" });
497
+ }) : t.push({ path: `${a}.points`, message: 'Polygon requires a "points" array', severity: "error" }), y(e, a, t);
497
498
  }
498
499
  function lt(e, a, t) {
500
+ c(e, "x", a, t), c(e, "y", a, t), typeof e.content != "string" && t.push({ path: `${a}.content`, message: 'Text requires a "content" string', severity: "error" }), y(e, a, t);
501
+ }
502
+ function ut(e, a, t) {
503
+ o(e, "domain", a, t), o(e, "range", a, t), o(e, "origin", a, t), P(e, a, t);
504
+ }
505
+ function ht(e, a, t) {
499
506
  if (typeof e.fn != "string")
500
507
  t.push({ path: `${a}.fn`, message: 'FunctionPlot requires a "fn" expression string', severity: "error" });
501
508
  else {
502
509
  const i = H(e.fn);
503
510
  i && t.push({ path: `${a}.fn`, message: `Invalid expression: ${i}`, severity: "error" });
504
511
  }
505
- y(e, "domain", a, t), P(e, a, t);
512
+ o(e, "domain", a, t), P(e, a, t);
506
513
  }
507
- function ut(e, a, t) {
508
- (!Array.isArray(e.to) || e.to.length !== 2) && t.push({ path: `${a}.to`, message: 'Vector requires a "to" array of [number, number]', severity: "error" }), y(e, "from", a, t), P(e, a, t);
514
+ function ft(e, a, t) {
515
+ (!Array.isArray(e.to) || e.to.length !== 2) && t.push({ path: `${a}.to`, message: 'Vector requires a "to" array of [number, number]', severity: "error" }), o(e, "from", a, t), P(e, a, t);
509
516
  }
510
- function ht(e, a, t) {
517
+ function gt(e, a, t) {
511
518
  if (typeof e.fn != "string")
512
519
  t.push({ path: `${a}.fn`, message: 'VectorField requires a "fn" expression string', severity: "error" });
513
520
  else {
514
521
  const i = H(e.fn);
515
522
  i && t.push({ path: `${a}.fn`, message: `Invalid vector expression: ${i}`, severity: "error" });
516
523
  }
517
- y(e, "domain", a, t), y(e, "range", a, t), P(e, a, t);
524
+ o(e, "domain", a, t), o(e, "range", a, t), P(e, a, t);
518
525
  }
519
- function ft(e, a, t) {
526
+ function yt(e, a, t) {
520
527
  Array.isArray(e.values) ? e.values.forEach((i, r) => {
521
528
  Array.isArray(i) || t.push({ path: `${a}.values[${r}]`, message: "Each matrix row must be an array", severity: "error" });
522
- }) : t.push({ path: `${a}.values`, message: 'Matrix requires a "values" 2D array', severity: "error" }), o(e, a, t);
529
+ }) : t.push({ path: `${a}.values`, message: 'Matrix requires a "values" 2D array', severity: "error" }), y(e, a, t);
523
530
  }
524
- function gt(e, a, t) {
531
+ function ot(e, a, t) {
525
532
  if (!Array.isArray(e.nodes))
526
533
  t.push({ path: `${a}.nodes`, message: 'Graph requires a "nodes" array', severity: "error" });
527
534
  else {
528
535
  const i = /* @__PURE__ */ new Set();
529
536
  e.nodes.forEach((r, n) => {
530
- typeof r.id != "string" ? t.push({ path: `${a}.nodes[${n}].id`, message: 'Graph node requires a string "id"', severity: "error" }) : (i.has(r.id) && t.push({ path: `${a}.nodes[${n}].id`, message: `Duplicate node id "${r.id}"`, severity: "error" }), i.add(r.id)), l(r, "x", `${a}.nodes[${n}]`, t), l(r, "y", `${a}.nodes[${n}]`, t);
537
+ typeof r.id != "string" ? t.push({ path: `${a}.nodes[${n}].id`, message: 'Graph node requires a string "id"', severity: "error" }) : (i.has(r.id) && t.push({ path: `${a}.nodes[${n}].id`, message: `Duplicate node id "${r.id}"`, severity: "error" }), i.add(r.id)), c(r, "x", `${a}.nodes[${n}]`, t), c(r, "y", `${a}.nodes[${n}]`, t);
531
538
  }), Array.isArray(e.edges) && e.edges.forEach((r, n) => {
532
539
  (typeof r.from != "string" || !i.has(r.from)) && t.push({ path: `${a}.edges[${n}].from`, message: `Edge "from" references unknown node "${r.from}"`, severity: "error" }), (typeof r.to != "string" || !i.has(r.to)) && t.push({ path: `${a}.edges[${n}].to`, message: `Edge "to" references unknown node "${r.to}"`, severity: "error" });
533
540
  });
534
541
  }
535
- o(e, a, t);
536
- }
537
- function ot(e, a, t) {
538
- typeof e.expression != "string" && t.push({ path: `${a}.expression`, message: 'LaTeX requires an "expression" string', severity: "error" }), l(e, "x", a, t), l(e, "y", a, t), o(e, a, t);
539
- }
540
- function yt(e, a, t) {
541
- l(e, "from", a, t), Ot(e, "durationInFrames", a, t), d(e, a, t);
542
+ y(e, a, t);
542
543
  }
543
544
  function mt(e, a, t) {
544
- h(e, "duration", a, t), $(e, a, t), d(e, a, t);
545
+ typeof e.expression != "string" && t.push({ path: `${a}.expression`, message: 'LaTeX requires an "expression" string', severity: "error" }), c(e, "x", a, t), c(e, "y", a, t), y(e, a, t);
545
546
  }
546
547
  function bt(e, a, t) {
547
- if (h(e, "duration", a, t), $(e, a, t), e.translate !== void 0) {
548
+ c(e, "from", a, t), At(e, "durationInFrames", a, t), w(e, a, t);
549
+ }
550
+ function xt(e, a, t) {
551
+ h(e, "duration", a, t), S(e, a, t), w(e, a, t);
552
+ }
553
+ function vt(e, a, t) {
554
+ if (h(e, "duration", a, t), S(e, a, t), e.translate !== void 0) {
548
555
  const i = e.translate;
549
556
  (!i || typeof i != "object") && t.push({ path: `${a}.translate`, message: "translate must be { from: [x,y], to: [x,y] }", severity: "error" });
550
557
  }
@@ -560,44 +567,44 @@ function bt(e, a, t) {
560
567
  const i = e.opacity;
561
568
  (!i || typeof i != "object" || typeof i.from != "number" || typeof i.to != "number") && t.push({ path: `${a}.opacity`, message: "opacity must be { from: number, to: number }", severity: "error" });
562
569
  }
563
- d(e, a, t);
570
+ w(e, a, t);
564
571
  }
565
- function xt(e, a, t) {
566
- h(e, "duration", a, t), $(e, a, t), v(e, "fromColor", a, t), v(e, "toColor", a, t), d(e, a, t);
572
+ function wt(e, a, t) {
573
+ h(e, "duration", a, t), S(e, a, t), v(e, "fromColor", a, t), v(e, "toColor", a, t), w(e, a, t);
567
574
  }
568
- function vt(e, a, t) {
569
- h(e, "staggerDelay", a, t), $(e, a, t), d(e, a, t);
575
+ function dt(e, a, t) {
576
+ h(e, "staggerDelay", a, t), S(e, a, t), w(e, a, t);
570
577
  }
571
- function o(e, a, t) {
572
- h(e, "fadeIn", a, t), h(e, "fadeOut", a, t), h(e, "draw", a, t), $(e, a, t), dt(e, a, t);
578
+ function y(e, a, t) {
579
+ h(e, "fadeIn", a, t), h(e, "fadeOut", a, t), h(e, "draw", a, t), S(e, a, t), kt(e, a, t);
573
580
  }
574
581
  function P(e, a, t) {
575
- h(e, "fadeIn", a, t), h(e, "fadeOut", a, t), h(e, "draw", a, t), $(e, a, t), wt(e, a, t);
582
+ h(e, "fadeIn", a, t), h(e, "fadeOut", a, t), h(e, "draw", a, t), S(e, a, t), It(e, a, t);
576
583
  }
577
584
  const V = ["none", "circle", "ellipse"];
578
- function dt(e, a, t) {
579
- if (F(e, "rotation", a, t), y(e, "rotationOrigin", a, t), y(e, "translate", a, t), F(e, "zIndex", a, t), e.scale !== void 0) {
585
+ function kt(e, a, t) {
586
+ if ($(e, "rotation", a, t), o(e, "rotationOrigin", a, t), o(e, "translate", a, t), $(e, "zIndex", a, t), e.scale !== void 0) {
580
587
  const i = e.scale;
581
588
  typeof i == "number" || Array.isArray(i) && i.length === 2 && typeof i[0] == "number" && typeof i[1] == "number" || t.push({ path: `${a}.scale`, message: '"scale" must be a number or [number, number]', severity: "error" });
582
589
  }
583
590
  }
584
- function wt(e, a, t) {
585
- F(e, "rotation", a, t), y(e, "rotationOrigin", a, t), y(e, "translate", a, t), F(e, "zIndex", a, t);
591
+ function It(e, a, t) {
592
+ $(e, "rotation", a, t), o(e, "rotationOrigin", a, t), o(e, "translate", a, t), $(e, "zIndex", a, t);
586
593
  }
587
- function kt(e, a, t) {
588
- typeof e.src != "string" && t.push({ path: `${a}.src`, message: 'Image requires a "src" string', severity: "error" }), l(e, "x", a, t), l(e, "y", a, t), k(e, "width", a, t), k(e, "height", a, t), v(e, "preserveAspectRatio", a, t), e.borderRadius !== void 0 && (typeof e.borderRadius != "number" || e.borderRadius < 0) && t.push({ path: `${a}.borderRadius`, message: '"borderRadius" must be a number >= 0', severity: "error" }), e.clipShape !== void 0 && (V.includes(e.clipShape) || t.push({
594
+ function $t(e, a, t) {
595
+ typeof e.src != "string" && t.push({ path: `${a}.src`, message: 'Image requires a "src" string', severity: "error" }), c(e, "x", a, t), c(e, "y", a, t), k(e, "width", a, t), k(e, "height", a, t), v(e, "preserveAspectRatio", a, t), e.borderRadius !== void 0 && (typeof e.borderRadius != "number" || e.borderRadius < 0) && t.push({ path: `${a}.borderRadius`, message: '"borderRadius" must be a number >= 0', severity: "error" }), e.clipShape !== void 0 && (V.includes(e.clipShape) || t.push({
589
596
  path: `${a}.clipShape`,
590
597
  message: `Invalid clipShape "${e.clipShape}". Must be one of: ${V.join(", ")}`,
591
598
  severity: "error"
592
- })), o(e, a, t);
599
+ })), y(e, a, t);
593
600
  }
594
- function It(e, a, t) {
595
- d(e, a, t), o(e, a, t);
601
+ function St(e, a, t) {
602
+ w(e, a, t), y(e, a, t);
596
603
  }
597
- function $t(e, a, t) {
598
- l(e, "x", a, t), l(e, "y", a, t), k(e, "width", a, t), k(e, "height", a, t), Array.isArray(e.bars) || t.push({ path: `${a}.bars`, message: 'BarChart requires a "bars" array', severity: "error" }), o(e, a, t);
604
+ function Ot(e, a, t) {
605
+ c(e, "x", a, t), c(e, "y", a, t), k(e, "width", a, t), k(e, "height", a, t), Array.isArray(e.bars) || t.push({ path: `${a}.bars`, message: 'BarChart requires a "bars" array', severity: "error" }), y(e, a, t);
599
606
  }
600
- function $(e, a, t) {
607
+ function S(e, a, t) {
601
608
  if (e.easing !== void 0) {
602
609
  if (typeof e.easing == "string") {
603
610
  if (!R.includes(e.easing)) {
@@ -624,33 +631,33 @@ function $(e, a, t) {
624
631
  t.push({ path: `${a}.easing`, message: 'Easing must be a string name or { type: "spring"|"cubicBezier", ... }', severity: "error" });
625
632
  }
626
633
  }
627
- function l(e, a, t, i) {
634
+ function c(e, a, t, i) {
628
635
  typeof e[a] != "number" && i.push({ path: `${t}.${a}`, message: `Required numeric field "${a}" is missing or not a number`, severity: "error" });
629
636
  }
630
637
  function k(e, a, t, i) {
631
638
  (typeof e[a] != "number" || e[a] <= 0) && i.push({ path: `${t}.${a}`, message: `"${a}" must be a positive number`, severity: "error" });
632
639
  }
633
- function St(e, a, t, i) {
640
+ function Ct(e, a, t, i) {
634
641
  const r = e[a];
635
642
  (typeof r != "number" || r <= 0 || !Number.isInteger(r)) && i.push({ path: `${t}.${a}`, message: `"${a}" must be a positive integer`, severity: "error" });
636
643
  }
637
644
  function h(e, a, t, i) {
638
645
  e[a] !== void 0 && (typeof e[a] != "number" || e[a] <= 0) && i.push({ path: `${t}.${a}`, message: `"${a}" must be a positive number`, severity: "error" });
639
646
  }
640
- function Ot(e, a, t, i) {
647
+ function At(e, a, t, i) {
641
648
  const r = e[a];
642
649
  r !== void 0 && (typeof r != "number" || r <= 0 || !Number.isInteger(r)) && i.push({ path: `${t}.${a}`, message: `"${a}" must be a positive integer`, severity: "error" });
643
650
  }
644
651
  function v(e, a, t, i) {
645
652
  e[a] !== void 0 && typeof e[a] != "string" && i.push({ path: `${t}.${a}`, message: `"${a}" must be a string`, severity: "error" });
646
653
  }
647
- function F(e, a, t, i) {
654
+ function $(e, a, t, i) {
648
655
  e[a] !== void 0 && typeof e[a] != "number" && i.push({ path: `${t}.${a}`, message: `"${a}" must be a number`, severity: "error" });
649
656
  }
650
- function S(e, a, t, i) {
657
+ function O(e, a, t, i) {
651
658
  e[a] !== void 0 && typeof e[a] != "boolean" && i.push({ path: `${t}.${a}`, message: `"${a}" must be a boolean`, severity: "error" });
652
659
  }
653
- function y(e, a, t, i) {
660
+ function o(e, a, t, i) {
654
661
  const r = e[a];
655
662
  r !== void 0 && (!Array.isArray(r) || r.length !== 2 || typeof r[0] != "number" || typeof r[1] != "number") && i.push({ path: `${t}.${a}`, message: `"${a}" must be [number, number]`, severity: "error" });
656
663
  }
@@ -660,9 +667,9 @@ function K(e, a) {
660
667
  const r = a.find((n) => n.toLowerCase().startsWith(t.slice(0, 4)));
661
668
  return r ? ` Did you mean '${r}'?` : "";
662
669
  }
663
- function Mt({ dsl: e, className: a, style: t }) {
664
- const i = Ye(e);
665
- return i.valid ? /* @__PURE__ */ s("div", { className: a, style: t, "data-testid": "dsl-root", children: At(e.root) }) : /* @__PURE__ */ L(
670
+ function Dt({ dsl: e, className: a, style: t }) {
671
+ const i = Je(e);
672
+ return i.valid ? /* @__PURE__ */ s("div", { className: a, style: t, "data-testid": "dsl-root", children: zt(e.root) }) : /* @__PURE__ */ L(
666
673
  "div",
667
674
  {
668
675
  className: a,
@@ -679,14 +686,14 @@ function Mt({ dsl: e, className: a, style: t }) {
679
686
  }
680
687
  );
681
688
  }
682
- function At(e) {
689
+ function zt(e) {
683
690
  switch (e.type) {
684
691
  case "scene":
685
692
  return X(e);
686
693
  case "player":
687
694
  return Y(e);
688
695
  case "presentation":
689
- return Ct(e);
696
+ return Et(e);
690
697
  }
691
698
  }
692
699
  function X(e) {
@@ -718,9 +725,9 @@ function Y(e) {
718
725
  }
719
726
  );
720
727
  }
721
- function Ct(e) {
728
+ function Et(e) {
722
729
  return /* @__PURE__ */ s(
723
- we,
730
+ de,
724
731
  {
725
732
  width: e.width,
726
733
  height: e.height,
@@ -729,25 +736,25 @@ function Ct(e) {
729
736
  transitionDuration: e.transitionDuration,
730
737
  showHUD: e.showHud,
731
738
  showNotes: e.showNotes,
732
- children: e.slides.map((a, t) => zt(a, t))
739
+ children: e.slides.map((a, t) => Ft(a, t))
733
740
  }
734
741
  );
735
742
  }
736
- function zt(e, a) {
743
+ function Ft(e, a) {
737
744
  var t;
738
745
  return /* @__PURE__ */ s($e, { title: e.title, notes: e.notes, background: e.background, children: (t = e.children) == null ? void 0 : t.map((i, r) => g(i, r)) }, a);
739
746
  }
740
747
  function g(e, a) {
741
748
  switch (e.type) {
742
749
  case "sequence":
743
- return /* @__PURE__ */ s(Qe, { from: e.from, durationInFrames: e.durationInFrames, name: e.name, children: e.children.map((t, i) => g(t, i)) }, a);
750
+ return /* @__PURE__ */ s(Ke, { from: e.from, durationInFrames: e.durationInFrames, name: e.name, children: e.children.map((t, i) => g(t, i)) }, a);
744
751
  case "group":
745
752
  return /* @__PURE__ */ s(
746
- Ge,
753
+ Qe,
747
754
  {
748
755
  fadeIn: e.fadeIn,
749
756
  fadeOut: e.fadeOut,
750
- easing: c(e.easing),
757
+ easing: l(e.easing),
751
758
  rotation: e.rotation,
752
759
  rotationOrigin: e.rotationOrigin,
753
760
  scale: e.scale,
@@ -757,6 +764,35 @@ function g(e, a) {
757
764
  },
758
765
  a
759
766
  );
767
+ case "bezierCurve":
768
+ return /* @__PURE__ */ s(
769
+ Ge,
770
+ {
771
+ x1: e.x1,
772
+ y1: e.y1,
773
+ cx1: e.cx1,
774
+ cy1: e.cy1,
775
+ cx2: e.cx2,
776
+ cy2: e.cy2,
777
+ x2: e.x2,
778
+ y2: e.y2,
779
+ stroke: e.stroke,
780
+ strokeWidth: e.strokeWidth,
781
+ fill: e.fill,
782
+ strokeDasharray: e.strokeDasharray,
783
+ opacity: e.opacity,
784
+ fadeIn: e.fadeIn,
785
+ fadeOut: e.fadeOut,
786
+ draw: e.draw,
787
+ easing: l(e.easing),
788
+ rotation: e.rotation,
789
+ rotationOrigin: e.rotationOrigin,
790
+ scale: e.scale,
791
+ translate: e.translate,
792
+ zIndex: e.zIndex
793
+ },
794
+ a
795
+ );
760
796
  case "circle":
761
797
  return /* @__PURE__ */ s(
762
798
  He,
@@ -771,7 +807,7 @@ function g(e, a) {
771
807
  fadeIn: e.fadeIn,
772
808
  fadeOut: e.fadeOut,
773
809
  draw: e.draw,
774
- easing: c(e.easing),
810
+ easing: l(e.easing),
775
811
  rotation: e.rotation,
776
812
  rotationOrigin: e.rotationOrigin,
777
813
  scale: e.scale,
@@ -795,7 +831,7 @@ function g(e, a) {
795
831
  fadeIn: e.fadeIn,
796
832
  fadeOut: e.fadeOut,
797
833
  draw: e.draw,
798
- easing: c(e.easing),
834
+ easing: l(e.easing),
799
835
  rotation: e.rotation,
800
836
  rotationOrigin: e.rotationOrigin,
801
837
  scale: e.scale,
@@ -820,7 +856,7 @@ function g(e, a) {
820
856
  fadeIn: e.fadeIn,
821
857
  fadeOut: e.fadeOut,
822
858
  draw: e.draw,
823
- easing: c(e.easing),
859
+ easing: l(e.easing),
824
860
  rotation: e.rotation,
825
861
  rotationOrigin: e.rotationOrigin,
826
862
  scale: e.scale,
@@ -847,7 +883,7 @@ function g(e, a) {
847
883
  fadeIn: e.fadeIn,
848
884
  fadeOut: e.fadeOut,
849
885
  draw: e.draw,
850
- easing: c(e.easing),
886
+ easing: l(e.easing),
851
887
  rotation: e.rotation,
852
888
  rotationOrigin: e.rotationOrigin,
853
889
  scale: e.scale,
@@ -869,7 +905,7 @@ function g(e, a) {
869
905
  fadeIn: e.fadeIn,
870
906
  fadeOut: e.fadeOut,
871
907
  draw: e.draw,
872
- easing: c(e.easing),
908
+ easing: l(e.easing),
873
909
  rotation: e.rotation,
874
910
  rotationOrigin: e.rotationOrigin,
875
911
  scale: e.scale,
@@ -893,7 +929,7 @@ function g(e, a) {
893
929
  opacity: e.opacity,
894
930
  fadeIn: e.fadeIn,
895
931
  fadeOut: e.fadeOut,
896
- easing: c(e.easing),
932
+ easing: l(e.easing),
897
933
  rotation: e.rotation,
898
934
  rotationOrigin: e.rotationOrigin,
899
935
  scale: e.scale,
@@ -918,7 +954,7 @@ function g(e, a) {
918
954
  opacity: e.opacity,
919
955
  fadeIn: e.fadeIn,
920
956
  fadeOut: e.fadeOut,
921
- easing: c(e.easing),
957
+ easing: l(e.easing),
922
958
  rotation: e.rotation,
923
959
  rotationOrigin: e.rotationOrigin,
924
960
  scale: e.scale,
@@ -946,7 +982,7 @@ function g(e, a) {
946
982
  fadeIn: e.fadeIn,
947
983
  fadeOut: e.fadeOut,
948
984
  draw: e.draw,
949
- easing: c(e.easing),
985
+ easing: l(e.easing),
950
986
  rotation: e.rotation,
951
987
  rotationOrigin: e.rotationOrigin,
952
988
  translate: e.translate,
@@ -955,9 +991,9 @@ function g(e, a) {
955
991
  a
956
992
  );
957
993
  case "functionPlot": {
958
- const t = Ke(e.fn);
994
+ const t = Xe(e.fn);
959
995
  return /* @__PURE__ */ s(
960
- De,
996
+ pe,
961
997
  {
962
998
  fn: (i) => t({ x: i }),
963
999
  domain: e.domain,
@@ -968,7 +1004,7 @@ function g(e, a) {
968
1004
  strokeWidth: e.strokeWidth,
969
1005
  samples: e.samples,
970
1006
  draw: e.draw,
971
- easing: c(e.easing),
1007
+ easing: l(e.easing),
972
1008
  opacity: e.opacity,
973
1009
  rotation: e.rotation,
974
1010
  rotationOrigin: e.rotationOrigin,
@@ -980,7 +1016,7 @@ function g(e, a) {
980
1016
  }
981
1017
  case "vector":
982
1018
  return /* @__PURE__ */ s(
983
- _e,
1019
+ De,
984
1020
  {
985
1021
  from: e.from,
986
1022
  to: e.to,
@@ -996,7 +1032,7 @@ function g(e, a) {
996
1032
  fadeIn: e.fadeIn,
997
1033
  fadeOut: e.fadeOut,
998
1034
  draw: e.draw,
999
- easing: c(e.easing),
1035
+ easing: l(e.easing),
1000
1036
  rotation: e.rotation,
1001
1037
  rotationOrigin: e.rotationOrigin,
1002
1038
  translate: e.translate,
@@ -1005,9 +1041,9 @@ function g(e, a) {
1005
1041
  a
1006
1042
  );
1007
1043
  case "vectorField": {
1008
- const t = Xe(e.fn);
1044
+ const t = Ye(e.fn);
1009
1045
  return /* @__PURE__ */ s(
1010
- We,
1046
+ _e,
1011
1047
  {
1012
1048
  fn: (i, r) => t({ x: i, y: r }),
1013
1049
  domain: e.domain,
@@ -1023,7 +1059,7 @@ function g(e, a) {
1023
1059
  maxLength: e.maxLength,
1024
1060
  fadeIn: e.fadeIn,
1025
1061
  fadeOut: e.fadeOut,
1026
- easing: c(e.easing),
1062
+ easing: l(e.easing),
1027
1063
  rotation: e.rotation,
1028
1064
  rotationOrigin: e.rotationOrigin,
1029
1065
  translate: e.translate,
@@ -1045,7 +1081,7 @@ function g(e, a) {
1045
1081
  fontSize: e.fontSize,
1046
1082
  fadeIn: e.fadeIn,
1047
1083
  fadeOut: e.fadeOut,
1048
- easing: c(e.easing),
1084
+ easing: l(e.easing),
1049
1085
  rotation: e.rotation,
1050
1086
  rotationOrigin: e.rotationOrigin,
1051
1087
  scale: e.scale,
@@ -1056,7 +1092,7 @@ function g(e, a) {
1056
1092
  );
1057
1093
  case "graph":
1058
1094
  return /* @__PURE__ */ s(
1059
- Ne,
1095
+ We,
1060
1096
  {
1061
1097
  nodes: e.nodes,
1062
1098
  edges: e.edges,
@@ -1068,7 +1104,7 @@ function g(e, a) {
1068
1104
  labelFontSize: e.labelFontSize,
1069
1105
  fadeIn: e.fadeIn,
1070
1106
  fadeOut: e.fadeOut,
1071
- easing: c(e.easing),
1107
+ easing: l(e.easing),
1072
1108
  rotation: e.rotation,
1073
1109
  rotationOrigin: e.rotationOrigin,
1074
1110
  scale: e.scale,
@@ -1079,7 +1115,7 @@ function g(e, a) {
1079
1115
  );
1080
1116
  case "latex":
1081
1117
  return /* @__PURE__ */ s(
1082
- pe,
1118
+ Ne,
1083
1119
  {
1084
1120
  expression: e.expression,
1085
1121
  x: e.x,
@@ -1089,7 +1125,7 @@ function g(e, a) {
1089
1125
  align: e.align,
1090
1126
  fadeIn: e.fadeIn,
1091
1127
  fadeOut: e.fadeOut,
1092
- easing: c(e.easing),
1128
+ easing: l(e.easing),
1093
1129
  rotation: e.rotation,
1094
1130
  rotationOrigin: e.rotationOrigin,
1095
1131
  scale: e.scale,
@@ -1116,7 +1152,7 @@ function g(e, a) {
1116
1152
  valueFormat: e.valueFormat,
1117
1153
  fadeIn: e.fadeIn,
1118
1154
  fadeOut: e.fadeOut,
1119
- easing: c(e.easing),
1155
+ easing: l(e.easing),
1120
1156
  rotation: e.rotation,
1121
1157
  rotationOrigin: e.rotationOrigin,
1122
1158
  scale: e.scale,
@@ -1126,19 +1162,19 @@ function g(e, a) {
1126
1162
  a
1127
1163
  );
1128
1164
  case "fadeIn":
1129
- return /* @__PURE__ */ s(Pe, { duration: e.duration, easing: c(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1165
+ return /* @__PURE__ */ s(Pe, { duration: e.duration, easing: l(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1130
1166
  case "fadeOut":
1131
- return /* @__PURE__ */ s(Fe, { duration: e.duration, totalFrames: e.totalFrames, easing: c(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1167
+ return /* @__PURE__ */ s(Fe, { duration: e.duration, totalFrames: e.totalFrames, easing: l(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1132
1168
  case "draw":
1133
- return /* @__PURE__ */ s(Ee, { duration: e.duration, pathLength: e.pathLength, easing: c(e.easing), children: g(e.children[0], 0) }, a);
1169
+ return /* @__PURE__ */ s(Ee, { duration: e.duration, pathLength: e.pathLength, easing: l(e.easing), children: g(e.children[0], 0) }, a);
1134
1170
  case "write":
1135
- return /* @__PURE__ */ s(ze, { duration: e.duration, easing: c(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1171
+ return /* @__PURE__ */ s(ze, { duration: e.duration, easing: l(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1136
1172
  case "transform":
1137
1173
  return /* @__PURE__ */ s(
1138
- Ce,
1174
+ Ae,
1139
1175
  {
1140
1176
  duration: e.duration,
1141
- easing: c(e.easing),
1177
+ easing: l(e.easing),
1142
1178
  translate: e.translate,
1143
1179
  scale: e.scale,
1144
1180
  rotate: e.rotate,
@@ -1149,10 +1185,10 @@ function g(e, a) {
1149
1185
  );
1150
1186
  case "morph":
1151
1187
  return /* @__PURE__ */ s(
1152
- Ae,
1188
+ Ce,
1153
1189
  {
1154
1190
  duration: e.duration,
1155
- easing: c(e.easing),
1191
+ easing: l(e.easing),
1156
1192
  fromColor: e.fromColor,
1157
1193
  toColor: e.toColor,
1158
1194
  fromOpacity: e.fromOpacity,
@@ -1164,7 +1200,7 @@ function g(e, a) {
1164
1200
  a
1165
1201
  );
1166
1202
  case "stagger":
1167
- return /* @__PURE__ */ s(Oe, { staggerDelay: e.staggerDelay, easing: c(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1203
+ return /* @__PURE__ */ s(Oe, { staggerDelay: e.staggerDelay, easing: l(e.easing), children: e.children.map((t, i) => g(t, i)) }, a);
1168
1204
  case "parallel":
1169
1205
  return /* @__PURE__ */ s(Se, { children: e.children.map((t, i) => g(t, i)) }, a);
1170
1206
  case "scene":
@@ -1175,7 +1211,7 @@ function g(e, a) {
1175
1211
  return null;
1176
1212
  }
1177
1213
  }
1178
- class Et {
1214
+ class Pt {
1179
1215
  constructor(a, t = 30, i = 900, r = 640) {
1180
1216
  this.elements = [], this.cursor = 0, this.theme = a, this._fps = t, this._width = i, this._height = r;
1181
1217
  }
@@ -1394,14 +1430,14 @@ class Et {
1394
1430
  * Returns the box positions for follow-up arrows, etc.
1395
1431
  */
1396
1432
  boxRow(a, t) {
1397
- const i = (t == null ? void 0 : t.boxWidth) ?? 80, r = (t == null ? void 0 : t.boxHeight) ?? 40, n = (t == null ? void 0 : t.gap) ?? 12, u = (t == null ? void 0 : t.y) ?? 250, I = a.length * i + (a.length - 1) * n, O = (this._width - I) / 2;
1433
+ const i = (t == null ? void 0 : t.boxWidth) ?? 80, r = (t == null ? void 0 : t.boxHeight) ?? 40, n = (t == null ? void 0 : t.gap) ?? 12, u = (t == null ? void 0 : t.y) ?? 250, I = a.length * i + (a.length - 1) * n, C = (this._width - I) / 2;
1398
1434
  t == null || t.fadeIn;
1399
1435
  const A = a.map((b, f) => {
1400
- const m = O + f * (i + n);
1436
+ const m = C + f * (i + n);
1401
1437
  return { x: m, y: u, w: i, h: r, cx: m + i / 2, cy: u + r / 2 };
1402
- }), C = a.map((b, f) => {
1403
- var D, T;
1404
- const m = A[f], z = ((D = t == null ? void 0 : t.colors) == null ? void 0 : D[f]) ?? this.theme.boxFill, E = ((T = t == null ? void 0 : t.strokeColors) == null ? void 0 : T[f]) ?? this.theme.boxStroke;
1438
+ }), z = a.map((b, f) => {
1439
+ var p, T;
1440
+ const m = A[f], E = ((p = t == null ? void 0 : t.colors) == null ? void 0 : p[f]) ?? this.theme.boxFill, F = ((T = t == null ? void 0 : t.strokeColors) == null ? void 0 : T[f]) ?? this.theme.boxStroke;
1405
1441
  return {
1406
1442
  type: "group",
1407
1443
  children: [
@@ -1411,8 +1447,8 @@ class Et {
1411
1447
  y: m.y,
1412
1448
  width: i,
1413
1449
  height: r,
1414
- fill: z,
1415
- stroke: E,
1450
+ fill: E,
1451
+ stroke: F,
1416
1452
  strokeWidth: 1.5,
1417
1453
  rx: 6
1418
1454
  },
@@ -1432,7 +1468,7 @@ class Et {
1432
1468
  return this.addAtCursor({
1433
1469
  type: "stagger",
1434
1470
  staggerDelay: 3,
1435
- children: C
1471
+ children: z
1436
1472
  }, 8 + a.length * 2), A;
1437
1473
  }
1438
1474
  /**
@@ -1441,12 +1477,12 @@ class Et {
1441
1477
  boxColumn(a, t) {
1442
1478
  const i = (t == null ? void 0 : t.boxWidth) ?? 160, r = (t == null ? void 0 : t.boxHeight) ?? 36, n = (t == null ? void 0 : t.gap) ?? 8, u = (t == null ? void 0 : t.y) ?? 150, I = (t == null ? void 0 : t.x) ?? this.cx;
1443
1479
  t == null || t.fadeIn;
1444
- const O = a.map((C, b) => {
1480
+ const C = a.map((z, b) => {
1445
1481
  const f = u + b * (r + n);
1446
1482
  return { x: I - i / 2, y: f, w: i, h: r, cx: I, cy: f + r / 2 };
1447
- }), A = a.map((C, b) => {
1448
- var z, E;
1449
- const f = O[b], m = ((z = t == null ? void 0 : t.colors) == null ? void 0 : z[b]) ?? this.theme.boxFill;
1483
+ }), A = a.map((z, b) => {
1484
+ var E, F;
1485
+ const f = C[b], m = ((E = t == null ? void 0 : t.colors) == null ? void 0 : E[b]) ?? this.theme.boxFill;
1450
1486
  return {
1451
1487
  type: "group",
1452
1488
  children: [
@@ -1457,7 +1493,7 @@ class Et {
1457
1493
  width: i,
1458
1494
  height: r,
1459
1495
  fill: m,
1460
- stroke: (E = t == null ? void 0 : t.colors) != null && E[b] ? t.colors[b] : this.theme.boxStroke,
1496
+ stroke: (F = t == null ? void 0 : t.colors) != null && F[b] ? t.colors[b] : this.theme.boxStroke,
1461
1497
  strokeWidth: 1.5,
1462
1498
  rx: 6
1463
1499
  },
@@ -1465,7 +1501,7 @@ class Et {
1465
1501
  type: "text",
1466
1502
  x: f.cx,
1467
1503
  y: f.cy + 5,
1468
- content: C,
1504
+ content: z,
1469
1505
  fontSize: (t == null ? void 0 : t.fontSize) ?? 13,
1470
1506
  fill: (t == null ? void 0 : t.textColor) ?? this.theme.text,
1471
1507
  textAnchor: "middle"
@@ -1477,7 +1513,7 @@ class Et {
1477
1513
  type: "stagger",
1478
1514
  staggerDelay: 3,
1479
1515
  children: A
1480
- }, 8 + a.length * 2), O;
1516
+ }, 8 + a.length * 2), C;
1481
1517
  }
1482
1518
  /**
1483
1519
  * Draw arrows connecting sequential positions (e.g., output of boxRow/boxColumn).
@@ -1560,7 +1596,7 @@ class Et {
1560
1596
  return { elements: this.elements, durationInFrames: a };
1561
1597
  }
1562
1598
  }
1563
- const Ft = {
1599
+ const Rt = {
1564
1600
  background: "#0a0a1e",
1565
1601
  title: "#e0e7ff",
1566
1602
  subtitle: "#94a3b8",
@@ -1575,7 +1611,7 @@ const Ft = {
1575
1611
  warning: "#fbbf24",
1576
1612
  error: "#f87171",
1577
1613
  palette: ["#4fc3f7", "#a78bfa", "#f472b6", "#34d399", "#fbbf24", "#fb923c", "#6366f1", "#22d3ee"]
1578
- }, Wt = {
1614
+ }, pt = {
1579
1615
  background: "#f8fafc",
1580
1616
  title: "#1e293b",
1581
1617
  subtitle: "#64748b",
@@ -1591,9 +1627,9 @@ const Ft = {
1591
1627
  error: "#dc2626",
1592
1628
  palette: ["#2563eb", "#7c3aed", "#db2777", "#16a34a", "#d97706", "#ea580c", "#4f46e5", "#0891b2"]
1593
1629
  };
1594
- class Pt {
1630
+ class Nt {
1595
1631
  constructor(a, t, i) {
1596
- this._slides = [], this._title = a, this._theme = t ?? Ft, this._opts = {
1632
+ this._slides = [], this._title = a, this._theme = t ?? Rt, this._opts = {
1597
1633
  width: 900,
1598
1634
  height: 640,
1599
1635
  fps: 30,
@@ -1611,7 +1647,7 @@ class Pt {
1611
1647
  /** Build the final ElucimDocument */
1612
1648
  build() {
1613
1649
  const a = this._slides.map((i) => {
1614
- const r = new Et(
1650
+ const r = new Pt(
1615
1651
  this._theme,
1616
1652
  this._opts.fps,
1617
1653
  this._opts.width,
@@ -1657,19 +1693,19 @@ class Pt {
1657
1693
  return JSON.stringify(this.build(), null, a ? 2 : void 0);
1658
1694
  }
1659
1695
  }
1660
- function _t(e, a, t) {
1661
- return new Pt(e, a, t);
1696
+ function Tt(e, a, t) {
1697
+ return new Nt(e, a, t);
1662
1698
  }
1663
1699
  export {
1664
- Mt as DslRenderer,
1665
- Pt as PresentationBuilder,
1666
- Et as SlideBuilder,
1667
- Ke as compileExpression,
1668
- Xe as compileVectorExpression,
1669
- Ft as darkTheme,
1670
- Wt as lightTheme,
1671
- _t as presentation,
1672
- c as resolveEasing,
1673
- Ye as validate,
1700
+ Dt as DslRenderer,
1701
+ Nt as PresentationBuilder,
1702
+ Pt as SlideBuilder,
1703
+ Xe as compileExpression,
1704
+ Ye as compileVectorExpression,
1705
+ Rt as darkTheme,
1706
+ pt as lightTheme,
1707
+ Tt as presentation,
1708
+ l as resolveEasing,
1709
+ Je as validate,
1674
1710
  H as validateExpression
1675
1711
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elucim/dsl",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "JSON/YAML DSL for declarative Elucim animations — define visualizations without writing React code",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -19,6 +19,9 @@
19
19
  "yaml",
20
20
  "visualization",
21
21
  "elucim",
22
+ "image",
23
+ "group",
24
+ "transforms",
22
25
  "declarative"
23
26
  ],
24
27
  "publishConfig": {
@@ -42,7 +45,7 @@
42
45
  "react-dom": "^18.0.0 || ^19.0.0"
43
46
  },
44
47
  "dependencies": {
45
- "@elucim/core": "0.2.0"
48
+ "@elucim/core": "0.3.0"
46
49
  },
47
50
  "devDependencies": {
48
51
  "@types/react": "^18.3.0",