@pixodesk/svg-animator-web 1.0.17 → 1.0.19

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.umd.js CHANGED
@@ -8,6 +8,7 @@ var PixodeskAnimator = (() => {
8
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
9
  var __hasOwnProp = Object.prototype.hasOwnProperty;
10
10
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
+ var __pow = Math.pow;
11
12
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
13
  var __spreadValues = (a, b) => {
13
14
  for (var prop in b || (b = {}))
@@ -83,7 +84,8 @@ var PixodeskAnimator = (() => {
83
84
  PxRetimeEffectSchema: () => PxRetimeEffectSchema,
84
85
  PxStrokeGradientEffectSchema: () => PxStrokeGradientEffectSchema,
85
86
  PxSvgNodeExtra: () => PxSvgNodeExtra,
86
- PxTextAlongPathEffectSchema: () => PxTextAlongPathEffectSchema,
87
+ PxTextEffectSchema: () => PxTextEffectSchema,
88
+ PxTextPathEffectSchema: () => PxTextPathEffectSchema,
87
89
  PxTransformPartsSchema: () => PxTransformPartsSchema,
88
90
  PxTransformValueSchema: () => PxTransformValueSchema,
89
91
  PxTransformationEffectSchema: () => PxTransformationEffectSchema,
@@ -103,6 +105,7 @@ var PixodeskAnimator = (() => {
103
105
  describeSchema: () => describeSchema,
104
106
  diffInEffect: () => diffInEffect,
105
107
  evaluateMotionPathSegment: () => evaluateMotionPathSegment,
108
+ extendedPathForBrowser: () => extendedPathForBrowser,
106
109
  generateNewIds: () => generateNewIds,
107
110
  getAnimatorConfig: () => getAnimatorConfig,
108
111
  getBindings: () => getBindings,
@@ -111,9 +114,13 @@ var PixodeskAnimator = (() => {
111
114
  getNormalizedProps: () => getNormalizedProps,
112
115
  isPxElementFileFormat: () => isPxElementFileFormat,
113
116
  isPxElementFileFormatDeep: () => isPxElementFileFormatDeep,
117
+ jsonElementFactory: () => jsonElementFactory,
114
118
  loadTagAnimators: () => loadTagAnimators,
115
119
  materialiseAllInTree: () => materialiseAllInTree,
116
120
  materialiseAnimatedUseInstances: () => materialiseAnimatedUseInstances,
121
+ materialiseGlyphText: () => materialiseGlyphText,
122
+ materialiseGlyphTextAlongPath: () => materialiseGlyphTextAlongPath,
123
+ materialiseGlyphTextHorizontal: () => materialiseGlyphTextHorizontal,
117
124
  materialiseInternalLoopsInPropAnim: () => materialiseInternalLoopsInPropAnim,
118
125
  materialiseInternalLoopsInTree: () => materialiseInternalLoopsInTree,
119
126
  materialiseMotionPathInPropAnim: () => materialiseMotionPathInPropAnim,
@@ -124,6 +131,7 @@ var PixodeskAnimator = (() => {
124
131
  renderNode: () => renderNode,
125
132
  schemaKeys: () => schemaKeys,
126
133
  setupAnimationTriggers: () => setupAnimationTriggers,
134
+ shiftAnimatable: () => shiftAnimatable,
127
135
  toRGBA: () => toRGBA,
128
136
  validateNodeEffects: () => validateNodeEffects,
129
137
  visualModelAt: () => visualModelAt
@@ -1005,10 +1013,22 @@ var PixodeskAnimator = (() => {
1005
1013
  outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1006
1014
  scrollIntoViewThreshold: px.number().optional()
1007
1015
  }));
1016
+ var PxGlyphSchema = implementsInterface()(px.object({
1017
+ width: px.number(),
1018
+ d: px.string()
1019
+ }));
1020
+ var PxGlyphFontSchema = implementsInterface()(px.object({
1021
+ fFamily: px.string(),
1022
+ style: px.string(),
1023
+ ascent: px.number(),
1024
+ unitsPerEm: px.number(),
1025
+ glyphs: px.record(PxGlyphSchema)
1026
+ }));
1008
1027
  var PxDefsSchema = implementsInterface()(px.object({
1009
1028
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
1010
1029
  animations: px.record(PxAnimationDefinitionSchema).optional(),
1011
- styles: px.record(px.any()).optional()
1030
+ styles: px.record(px.any()).optional(),
1031
+ glyphs: px.record(PxGlyphFontSchema).optional()
1012
1032
  }));
1013
1033
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
1014
1034
  mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.webapi, PxAnimatorMode.frames]).optional(),
@@ -1121,14 +1141,18 @@ var PixodeskAnimator = (() => {
1121
1141
  gradientTransform: px.string().optional()
1122
1142
  }));
1123
1143
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1124
- var PxTextAlongPathEffectSchema = implementsInterface()(px.object({
1125
- href: px.string(),
1144
+ var PxTextPathEffectSchema = implementsInterface()(px.object({
1145
+ path: px.string(),
1146
+ pathOverflow: px.string().optional(),
1126
1147
  lengthAdjust: px.string().optional(),
1127
1148
  method: px.string().optional(),
1128
1149
  spacing: px.string().optional(),
1129
1150
  startOffset: PxAnimatableNumberSchema.optional(),
1130
1151
  textLength: PxAnimatableNumberSchema.optional()
1131
1152
  }));
1153
+ var PxTextEffectSchema = implementsInterface()(px.object({
1154
+ useGlyphs: px.boolean().optional()
1155
+ }));
1132
1156
  var PxEffectsSchema = implementsInterface()(px.object({
1133
1157
  transformation: PxTransformationEffectSchema.optional(),
1134
1158
  repeater: PxRepeaterEffectSchema.optional(),
@@ -1138,7 +1162,8 @@ var PixodeskAnimator = (() => {
1138
1162
  isCombinedShape: px.boolean().optional(),
1139
1163
  fillGradient: PxFillGradientEffectSchema.optional(),
1140
1164
  strokeGradient: PxStrokeGradientEffectSchema.optional(),
1141
- textAlongPath: PxTextAlongPathEffectSchema.optional()
1165
+ textPath: PxTextPathEffectSchema.optional(),
1166
+ text: PxTextEffectSchema.optional()
1142
1167
  }));
1143
1168
  function validateNodeEffects(root, opts) {
1144
1169
  const warnings = [];
@@ -2010,48 +2035,6 @@ var PixodeskAnimator = (() => {
2010
2035
  }
2011
2036
  }
2012
2037
 
2013
- // src/effects/textAlongPathEffect.ts
2014
- function applyTextAlongPathEffect(node, fx, _ctx) {
2015
- var _a;
2016
- if (!fx) return node;
2017
- const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
2018
- const textPath = {
2019
- type: "textPath",
2020
- href,
2021
- children: (_a = node.children) != null ? _a : []
2022
- };
2023
- if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
2024
- if (fx.method !== void 0) textPath.method = fx.method;
2025
- if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
2026
- applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
2027
- applyAnimatableNumber(textPath, "textLength", fx.textLength);
2028
- node.children = [textPath];
2029
- return node;
2030
- }
2031
- function applyAnimatableNumber(node, attrName, raw) {
2032
- if (raw === void 0 || raw === null) return;
2033
- if (typeof raw === "number") {
2034
- node[attrName] = String(raw);
2035
- return;
2036
- }
2037
- if (typeof raw === "object" && raw !== null) {
2038
- const obj = raw;
2039
- if (Array.isArray(obj.keyframes)) {
2040
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
2041
- const animate = __spreadValues({}, prevAnimate || {});
2042
- const block = { keyframes: obj.keyframes };
2043
- if (obj.loop !== void 0) block.loop = obj.loop;
2044
- animate[attrName] = block;
2045
- node.animate = animate;
2046
- return;
2047
- }
2048
- if (typeof obj.value === "number") {
2049
- node[attrName] = String(obj.value);
2050
- return;
2051
- }
2052
- }
2053
- }
2054
-
2055
2038
  // src/PxAnimatorUtil.ts
2056
2039
  function bezierToSvgPath(path) {
2057
2040
  var _a, _b, _c, _d;
@@ -2424,6 +2407,24 @@ var PixodeskAnimator = (() => {
2424
2407
  }
2425
2408
  return { ts, ds };
2426
2409
  }
2410
+ function bezier2D_tForDistance(lut, distance) {
2411
+ const { ts, ds } = lut;
2412
+ const last = ds.length - 1;
2413
+ if (distance <= 0) return ts[0];
2414
+ if (distance >= ds[last]) return ts[last];
2415
+ let lo = 1;
2416
+ let hi = last;
2417
+ while (lo < hi) {
2418
+ const mid = lo + hi >>> 1;
2419
+ if (ds[mid] < distance) lo = mid + 1;
2420
+ else hi = mid;
2421
+ }
2422
+ const dPrev = ds[hi - 1];
2423
+ const dCur = ds[hi];
2424
+ const span = dCur - dPrev;
2425
+ const frac = span > 0 ? (distance - dPrev) / span : 0;
2426
+ return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
2427
+ }
2427
2428
  function bezier2D_arcAtT(lut, t) {
2428
2429
  const { ts, ds } = lut;
2429
2430
  const last = ts.length - 1;
@@ -2446,6 +2447,623 @@ var PixodeskAnimator = (() => {
2446
2447
  return cubicBezier(flipped);
2447
2448
  }
2448
2449
 
2450
+ // src/effects/pathSampler.ts
2451
+ var LUT_STEPS = 48;
2452
+ var CMD_RE = /[MmLlHhVvCcSsQqTtAaZz]/;
2453
+ function tokenize(d) {
2454
+ const tokens = [];
2455
+ const re = /([MmLlHhVvCcSsQqTtAaZz])|(-?\d*\.?\d+(?:[eE][-+]?\d+)?)/g;
2456
+ let m;
2457
+ while ((m = re.exec(d)) !== null) tokens.push(m[0]);
2458
+ return tokens;
2459
+ }
2460
+ function quadToCubic(P0, Qc, P3) {
2461
+ return {
2462
+ P1: [P0[0] + 2 / 3 * (Qc[0] - P0[0]), P0[1] + 2 / 3 * (Qc[1] - P0[1])],
2463
+ P2: [P3[0] + 2 / 3 * (Qc[0] - P3[0]), P3[1] + 2 / 3 * (Qc[1] - P3[1])]
2464
+ };
2465
+ }
2466
+ function parseCubics(d) {
2467
+ const tokens = tokenize(d);
2468
+ const segs = [];
2469
+ let i = 0;
2470
+ let cx = 0, cy = 0;
2471
+ let sx = 0, sy = 0;
2472
+ let pcx = 0, pcy = 0;
2473
+ let pqx = 0, pqy = 0;
2474
+ let prevCmd = "";
2475
+ const num2 = () => parseFloat(tokens[i++]);
2476
+ const push = (P1, P2, P3) => {
2477
+ const P0 = [cx, cy];
2478
+ const lut = bezier2D_arcLengthLUT(P0, P1, P2, P3, LUT_STEPS);
2479
+ segs.push({ P0, P1, P2, P3, lut, len: lut.ds[lut.ds.length - 1] });
2480
+ cx = P3[0];
2481
+ cy = P3[1];
2482
+ };
2483
+ const pushLine = (x, y) => {
2484
+ push(
2485
+ [cx + (x - cx) / 3, cy + (y - cy) / 3],
2486
+ [cx + 2 * (x - cx) / 3, cy + 2 * (y - cy) / 3],
2487
+ [x, y]
2488
+ );
2489
+ };
2490
+ while (i < tokens.length) {
2491
+ let cmd = tokens[i];
2492
+ if (CMD_RE.test(cmd)) i++;
2493
+ else cmd = prevCmd === "M" ? "L" : prevCmd === "m" ? "l" : prevCmd;
2494
+ const rel = cmd >= "a";
2495
+ const U = cmd.toUpperCase();
2496
+ if (U === "Z") {
2497
+ pushLine(sx, sy);
2498
+ cx = sx;
2499
+ cy = sy;
2500
+ prevCmd = cmd;
2501
+ continue;
2502
+ }
2503
+ if (U === "M") {
2504
+ const x = num2() + (rel ? cx : 0), y = num2() + (rel ? cy : 0);
2505
+ cx = x;
2506
+ cy = y;
2507
+ sx = x;
2508
+ sy = y;
2509
+ prevCmd = cmd;
2510
+ continue;
2511
+ }
2512
+ if (U === "L") {
2513
+ pushLine(num2() + (rel ? cx : 0), num2() + (rel ? cy : 0));
2514
+ } else if (U === "H") {
2515
+ pushLine(num2() + (rel ? cx : 0), cy);
2516
+ } else if (U === "V") {
2517
+ pushLine(cx, num2() + (rel ? cy : 0));
2518
+ } else if (U === "C") {
2519
+ const p1 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2520
+ const p2 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2521
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2522
+ pcx = p2[0];
2523
+ pcy = p2[1];
2524
+ push(p1, p2, p3);
2525
+ } else if (U === "S") {
2526
+ const smooth = prevCmd.toUpperCase() === "C" || prevCmd.toUpperCase() === "S";
2527
+ const p1 = smooth ? [2 * cx - pcx, 2 * cy - pcy] : [cx, cy];
2528
+ const p2 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2529
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2530
+ pcx = p2[0];
2531
+ pcy = p2[1];
2532
+ push(p1, p2, p3);
2533
+ } else if (U === "Q") {
2534
+ const qc = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2535
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2536
+ pqx = qc[0];
2537
+ pqy = qc[1];
2538
+ const { P1, P2 } = quadToCubic([cx, cy], qc, p3);
2539
+ push(P1, P2, p3);
2540
+ } else if (U === "T") {
2541
+ const smooth = prevCmd.toUpperCase() === "Q" || prevCmd.toUpperCase() === "T";
2542
+ const qc = smooth ? [2 * cx - pqx, 2 * cy - pqy] : [cx, cy];
2543
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2544
+ pqx = qc[0];
2545
+ pqy = qc[1];
2546
+ const { P1, P2 } = quadToCubic([cx, cy], qc, p3);
2547
+ push(P1, P2, p3);
2548
+ } else if (U === "A") {
2549
+ i += 5;
2550
+ pushLine(num2() + (rel ? cx : 0), num2() + (rel ? cy : 0));
2551
+ } else {
2552
+ i++;
2553
+ continue;
2554
+ }
2555
+ prevCmd = cmd;
2556
+ }
2557
+ return segs.length ? segs : null;
2558
+ }
2559
+ function clamp2(v, lo, hi) {
2560
+ return v < lo ? lo : v > hi ? hi : v;
2561
+ }
2562
+ function createPathSampler(d) {
2563
+ const segs = parseCubics(d);
2564
+ if (!segs) return null;
2565
+ const cum = new Float64Array(segs.length + 1);
2566
+ for (let k = 0; k < segs.length; k++) cum[k + 1] = cum[k] + segs[k].len;
2567
+ const totalLength = cum[segs.length];
2568
+ const start = segs[0].P0, end = segs[segs.length - 1].P3;
2569
+ const closed = Math.hypot(end[0] - start[0], end[1] - start[1]) < 1e-3;
2570
+ const sampleOn = (dist) => {
2571
+ let k = 0;
2572
+ while (k < segs.length - 1 && dist > cum[k + 1]) k++;
2573
+ const seg = segs[k];
2574
+ const local = dist - cum[k];
2575
+ const t = seg.len > 0 ? bezier2D_tForDistance(seg.lut, local) : 0;
2576
+ const [x, y] = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
2577
+ const [dx, dy] = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
2578
+ return { x, y, angle: Math.atan2(dy, dx) };
2579
+ };
2580
+ return {
2581
+ totalLength,
2582
+ closed,
2583
+ sampleAtDistance(dist) {
2584
+ if (!closed && (dist < 0 || dist > totalLength)) {
2585
+ const edge = dist < 0 ? 0 : totalLength;
2586
+ const p = sampleOn(edge);
2587
+ const over = dist - edge;
2588
+ return { x: p.x + Math.cos(p.angle) * over, y: p.y + Math.sin(p.angle) * over, angle: p.angle };
2589
+ }
2590
+ return sampleOn(clamp2(dist, 0, totalLength));
2591
+ }
2592
+ };
2593
+ }
2594
+
2595
+ // src/effects/textPathEffect.ts
2596
+ var EXTEND_MARGIN_FRAC = 0.15;
2597
+ function numRange(v) {
2598
+ if (typeof v === "number") return { min: v, max: v };
2599
+ if (v && typeof v === "object") {
2600
+ const o = v;
2601
+ if (typeof o.value === "number") return { min: o.value, max: o.value };
2602
+ if (Array.isArray(o.keyframes) && o.keyframes.length) {
2603
+ const vals = o.keyframes.map((k) => Number(k.value) || 0);
2604
+ return { min: Math.min(...vals), max: Math.max(...vals) };
2605
+ }
2606
+ }
2607
+ return { min: 0, max: 0 };
2608
+ }
2609
+ function estimateTextAdvance(node) {
2610
+ let chars = 0, maxFont = 16;
2611
+ const walk = (el) => {
2612
+ var _a, _b;
2613
+ const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
2614
+ if (fs) maxFont = Math.max(maxFont, fs);
2615
+ const t = (_b = el.text) != null ? _b : el.textContent;
2616
+ if (typeof t === "string") chars += t.length;
2617
+ if (el.children) for (const c of el.children) walk(c);
2618
+ };
2619
+ walk(node);
2620
+ return chars * maxFont;
2621
+ }
2622
+ var r3 = (n) => Math.round(n * 1e3) / 1e3;
2623
+ function shiftAnimatable(v, by) {
2624
+ if (!by || v === void 0 || v === null) return v;
2625
+ if (typeof v === "number") return v + by;
2626
+ const o = v;
2627
+ if (typeof o.value === "number") return __spreadProps(__spreadValues({}, o), { value: o.value + by });
2628
+ if (Array.isArray(o.keyframes)) return __spreadProps(__spreadValues({}, o), { keyframes: o.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by })) });
2629
+ return v;
2630
+ }
2631
+ function extendedPathForBrowser(pathD, opts) {
2632
+ var _a;
2633
+ if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
2634
+ const sampler = createPathSampler(pathD);
2635
+ if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
2636
+ const L = sampler.totalLength;
2637
+ const margin = EXTEND_MARGIN_FRAC * L;
2638
+ const so = numRange(opts.startOffset);
2639
+ const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
2640
+ const startOverflow = Math.max(0, -so.min);
2641
+ const endOverflow = Math.max(0, so.max + runWidth - L);
2642
+ const startExt = startOverflow > 0 ? startOverflow + margin : 0;
2643
+ const endExt = endOverflow > 0 ? endOverflow + margin : 0;
2644
+ if (endExt <= 0 && startExt <= 0) return { d: pathD, startShift: 0 };
2645
+ const s = sampler.sampleAtDistance(0);
2646
+ const e = sampler.sampleAtDistance(L);
2647
+ let d = pathD;
2648
+ if (startExt > 0) {
2649
+ const sx = s.x - Math.cos(s.angle) * startExt, sy = s.y - Math.sin(s.angle) * startExt;
2650
+ const rest = pathD.replace(/^\s*[Mm]\s*-?[\d.]+[\s,]+-?[\d.]+/, "");
2651
+ d = "M" + r3(sx) + "," + r3(sy) + "L" + r3(s.x) + "," + r3(s.y) + rest;
2652
+ }
2653
+ if (endExt > 0) {
2654
+ const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
2655
+ d += "L" + r3(ex) + "," + r3(ey);
2656
+ }
2657
+ return { d, startShift: startExt };
2658
+ }
2659
+ function applyTextPathEffect(node, fx, ctx) {
2660
+ var _a;
2661
+ if (!fx || typeof fx.path !== "string" || !fx.path) return node;
2662
+ const pathId = genId(ctx, "tpath");
2663
+ const { d, startShift } = extendedPathForBrowser(fx.path, {
2664
+ pathOverflow: fx.pathOverflow,
2665
+ startOffset: fx.startOffset,
2666
+ textLength: fx.textLength,
2667
+ advance: estimateTextAdvance(node)
2668
+ });
2669
+ ctx.defs.push({ type: "path", id: pathId, d });
2670
+ const textPath = {
2671
+ type: "textPath",
2672
+ href: "#" + pathId,
2673
+ children: (_a = node.children) != null ? _a : []
2674
+ };
2675
+ if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
2676
+ if (fx.method !== void 0) textPath.method = fx.method;
2677
+ if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
2678
+ applyAnimatableNumber(textPath, "startOffset", shiftAnimatable(fx.startOffset, startShift));
2679
+ applyAnimatableNumber(textPath, "textLength", fx.textLength);
2680
+ node.children = [textPath];
2681
+ return node;
2682
+ }
2683
+ function applyAnimatableNumber(node, attrName, raw) {
2684
+ if (raw === void 0 || raw === null) return;
2685
+ if (typeof raw === "number") {
2686
+ node[attrName] = String(raw);
2687
+ return;
2688
+ }
2689
+ if (typeof raw === "object" && raw !== null) {
2690
+ const obj = raw;
2691
+ if (Array.isArray(obj.keyframes)) {
2692
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
2693
+ const animate = __spreadValues({}, prevAnimate || {});
2694
+ const block = { keyframes: obj.keyframes };
2695
+ if (obj.loop !== void 0) block.loop = obj.loop;
2696
+ animate[attrName] = block;
2697
+ node.animate = animate;
2698
+ return;
2699
+ }
2700
+ if (typeof obj.value === "number") {
2701
+ node[attrName] = String(obj.value);
2702
+ return;
2703
+ }
2704
+ }
2705
+ }
2706
+
2707
+ // src/effects/elementFactory.ts
2708
+ var jsonElementFactory = (type, props, children) => {
2709
+ const node = { type };
2710
+ for (const k in props) if (props[k] !== void 0) node[k] = props[k];
2711
+ const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
2712
+ if (arr.length) node.children = arr;
2713
+ return node;
2714
+ };
2715
+
2716
+ // src/effects/glyphPathBake.ts
2717
+ function fmt(v, decimals) {
2718
+ return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
2719
+ }
2720
+ function pack(nums, decimals) {
2721
+ let s = "";
2722
+ for (let i = 0; i < nums.length; i++) {
2723
+ const str2 = fmt(nums[i], decimals);
2724
+ if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
2725
+ s += str2;
2726
+ }
2727
+ return s;
2728
+ }
2729
+ function apply(m, x, y) {
2730
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
2731
+ }
2732
+ var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
2733
+ function transformPathData(d, m, decimals = 2) {
2734
+ const tokens = [];
2735
+ let match;
2736
+ TOKEN_RE.lastIndex = 0;
2737
+ while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
2738
+ let out = "";
2739
+ let i = 0;
2740
+ const num2 = () => parseFloat(tokens[i++]);
2741
+ while (i < tokens.length) {
2742
+ const cmd = tokens[i++];
2743
+ if (cmd === "M" || cmd === "L") {
2744
+ const [x, y] = apply(m, num2(), num2());
2745
+ out += cmd + pack([x, y], decimals);
2746
+ } else if (cmd === "C") {
2747
+ const [x1, y1] = apply(m, num2(), num2());
2748
+ const [x2, y2] = apply(m, num2(), num2());
2749
+ const [x, y] = apply(m, num2(), num2());
2750
+ out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
2751
+ } else if (cmd === "Q") {
2752
+ const [x1, y1] = apply(m, num2(), num2());
2753
+ const [x, y] = apply(m, num2(), num2());
2754
+ out += "Q" + pack([x1, y1, x, y], decimals);
2755
+ } else if (cmd === "Z" || cmd === "z") {
2756
+ out += "Z";
2757
+ }
2758
+ }
2759
+ return out;
2760
+ }
2761
+
2762
+ // src/effects/textGlyphsEffect.ts
2763
+ var DEFAULT_FONT_SIZE = 16;
2764
+ var TEXT_ATTR_KEYS = [
2765
+ "fontFamily",
2766
+ "fontSize",
2767
+ "fontWeight",
2768
+ "fontStyle",
2769
+ "textAnchor",
2770
+ "letterSpacing",
2771
+ "wordSpacing",
2772
+ "textDecoration",
2773
+ "textTransform",
2774
+ "whiteSpace",
2775
+ "x",
2776
+ "y",
2777
+ "dx",
2778
+ "dy",
2779
+ "lengthAdjust",
2780
+ "fill",
2781
+ "stroke",
2782
+ "strokeWidth",
2783
+ "effects",
2784
+ TEXT_ATTR,
2785
+ TEXT_CONTENT_ATTR,
2786
+ "xml:space"
2787
+ ];
2788
+ function parseLen(v) {
2789
+ if (typeof v === "number") return v;
2790
+ if (typeof v === "string") {
2791
+ const n = parseFloat(v);
2792
+ return isNaN(n) ? void 0 : n;
2793
+ }
2794
+ return void 0;
2795
+ }
2796
+ function str(v) {
2797
+ return typeof v === "string" ? v : void 0;
2798
+ }
2799
+ function resolveStyle(node, parent) {
2800
+ var _a, _b, _c, _d, _e, _f, _g;
2801
+ return {
2802
+ fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
2803
+ fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
2804
+ fill: (_c = node.fill) != null ? _c : parent.fill,
2805
+ stroke: (_d = node.stroke) != null ? _d : parent.stroke,
2806
+ strokeWidth: (_e = node.strokeWidth) != null ? _e : parent.strokeWidth,
2807
+ letterSpacing: (_f = parseLen(node.letterSpacing)) != null ? _f : parent.letterSpacing,
2808
+ wordSpacing: (_g = parseLen(node.wordSpacing)) != null ? _g : parent.wordSpacing
2809
+ };
2810
+ }
2811
+ function rootStyleOf(node) {
2812
+ var _a, _b, _c;
2813
+ return {
2814
+ fontFamily: str(node.fontFamily),
2815
+ fontSize: (_a = parseLen(node.fontSize)) != null ? _a : DEFAULT_FONT_SIZE,
2816
+ fill: node.fill,
2817
+ stroke: node.stroke,
2818
+ strokeWidth: node.strokeWidth,
2819
+ letterSpacing: (_b = parseLen(node.letterSpacing)) != null ? _b : 0,
2820
+ wordSpacing: (_c = parseLen(node.wordSpacing)) != null ? _c : 0
2821
+ };
2822
+ }
2823
+ function paintOf(s) {
2824
+ const p = {};
2825
+ if (s.fill !== void 0) p.fill = s.fill;
2826
+ if (s.stroke !== void 0) p.stroke = s.stroke;
2827
+ if (s.strokeWidth !== void 0) p.strokeWidth = s.strokeWidth;
2828
+ return p;
2829
+ }
2830
+ function glyphFontFor(s, glyphs, soleFont, warnings) {
2831
+ var _a;
2832
+ const gf = s.fontFamily ? glyphs[s.fontFamily] : soleFont;
2833
+ if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a = s.fontFamily) != null ? _a : "") + '"');
2834
+ return gf;
2835
+ }
2836
+ function soleFontOf(glyphs) {
2837
+ const names = Object.keys(glyphs);
2838
+ return names.length === 1 ? glyphs[names[0]] : void 0;
2839
+ }
2840
+ function materialiseGlyphTextHorizontal(node, opts) {
2841
+ var _a, _b, _c, _d;
2842
+ const { glyphs, create = jsonElementFactory, warnings } = opts;
2843
+ const soleFont = soleFontOf(glyphs);
2844
+ const pen = { x: (_a = parseLen(node.x)) != null ? _a : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
2845
+ const placements = [];
2846
+ const lines = [{ start: pen.x, end: pen.x }];
2847
+ let line = 0;
2848
+ const renderChars = (content, s) => {
2849
+ const gf = glyphFontFor(s, glyphs, soleFont, warnings);
2850
+ if (!gf) return;
2851
+ const scale = s.fontSize / gf.unitsPerEm;
2852
+ const paint = paintOf(s);
2853
+ for (let i = 0; i < content.length; i++) {
2854
+ const ch = content.charAt(i);
2855
+ const g = gf.glyphs[ch];
2856
+ if (g && g.d) placements.push({ glyphD: g.d, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
2857
+ pen.x += (g ? g.width : 0) * scale + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
2858
+ lines[line].end = pen.x;
2859
+ }
2860
+ };
2861
+ const walk = (el, parentStyle) => {
2862
+ var _a2, _b2, _c2, _d2;
2863
+ const s = resolveStyle(el, parentStyle);
2864
+ const x = parseLen(el.x);
2865
+ const y = parseLen(el.y);
2866
+ if (x !== void 0) {
2867
+ pen.x = x;
2868
+ line = lines.length;
2869
+ lines.push({ start: pen.x, end: pen.x });
2870
+ }
2871
+ if (y !== void 0) pen.y = y;
2872
+ pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
2873
+ pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
2874
+ const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
2875
+ if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
2876
+ if (el.children) for (const ch of el.children) walk(ch, s);
2877
+ };
2878
+ const rootStyle = rootStyleOf(node);
2879
+ if (node.children) for (const ch of node.children) walk(ch, rootStyle);
2880
+ const rootContent = (_c = str(node[TEXT_ATTR])) != null ? _c : str(node[TEXT_CONTENT_ATTR]);
2881
+ if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
2882
+ const anchor = str(node.textAnchor);
2883
+ if (anchor === "middle" || anchor === "end") {
2884
+ for (const p of placements) {
2885
+ const w = lines[p.line].end - lines[p.line].start;
2886
+ const shift = anchor === "middle" ? -w / 2 : -w;
2887
+ p.m = [p.scale, 0, 0, p.scale, p.x + shift, p.y];
2888
+ }
2889
+ }
2890
+ return toGroup(node, buildPaths(placements, create, warnings), create);
2891
+ }
2892
+ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
2893
+ const cells = [];
2894
+ let adv = 0;
2895
+ const walk = (el, parentStyle) => {
2896
+ var _a, _b;
2897
+ const s = resolveStyle(el, parentStyle);
2898
+ const content = (_a = str(el[TEXT_ATTR])) != null ? _a : str(el[TEXT_CONTENT_ATTR]);
2899
+ if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
2900
+ const gf = glyphFontFor(s, glyphs, soleFont, warnings);
2901
+ if (gf) {
2902
+ const scale = s.fontSize / gf.unitsPerEm;
2903
+ const paint = paintOf(s);
2904
+ for (let i = 0; i < content.length; i++) {
2905
+ const ch = content.charAt(i);
2906
+ const g = gf.glyphs[ch];
2907
+ const glyphAdv = (g ? g.width : 0) * scale;
2908
+ if (g && g.d) cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
2909
+ adv += glyphAdv + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
2910
+ }
2911
+ }
2912
+ }
2913
+ if (el.children) for (const ch of el.children) walk(ch, s);
2914
+ };
2915
+ walk(node, rootStyleOf(node));
2916
+ return { cells, width: adv };
2917
+ }
2918
+ function alongAffine(sampler, dist, scale, widthEm) {
2919
+ const { x, y, angle } = sampler.sampleAtDistance(dist);
2920
+ const cos = Math.cos(angle), sin = Math.sin(angle), hw = widthEm / 2;
2921
+ return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw, y - scale * sin * hw];
2922
+ }
2923
+ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
2924
+ var _a;
2925
+ const { glyphs, create = jsonElementFactory, warnings } = opts;
2926
+ const sampler = pathD ? createPathSampler(pathD) : null;
2927
+ if (!sampler) {
2928
+ warnings == null ? void 0 : warnings.push("textGlyphs: unparsable along-path geometry");
2929
+ return null;
2930
+ }
2931
+ const soleFont = soleFontOf(glyphs);
2932
+ const { cells, width } = collectAlongPathCells(node, glyphs, soleFont, warnings);
2933
+ if (!cells.length) return toGroup(node, [], create);
2934
+ if (textLength && textLength > 0 && width > 0) {
2935
+ const k = textLength / width;
2936
+ for (const c of cells) c.midBase *= k;
2937
+ }
2938
+ const isClip = pathOverflow === "clip" && !sampler.closed;
2939
+ const so = readAnimatable(startOffset);
2940
+ if (so.kind === "animated" /* Animated */ && so.keyframes.length >= 2) {
2941
+ return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create, isClip), create);
2942
+ }
2943
+ const base = so.kind === "animated" /* Animated */ ? Number((_a = so.keyframes[0]) == null ? void 0 : _a.value) || 0 : so.kind === "static" /* Static */ ? Number(so.value) || 0 : 0;
2944
+ const placeCells = isClip ? cells.filter((c) => {
2945
+ const d = base + c.midBase;
2946
+ return d >= 0 && d <= sampler.totalLength;
2947
+ }) : cells;
2948
+ const placements = placeCells.map((c) => ({
2949
+ glyphD: c.glyphD,
2950
+ paint: c.paint,
2951
+ m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm)
2952
+ }));
2953
+ return toGroup(node, buildPaths(placements, create, warnings), create);
2954
+ }
2955
+ var ALONG_PATH_MAX_STEPS = 48;
2956
+ var ALONG_PATH_MAX_STEPS_PER_SEGMENT = 64;
2957
+ function roundN(v, n) {
2958
+ const f = __pow(10, n);
2959
+ return Math.round(v * f) / f;
2960
+ }
2961
+ function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create, isClip) {
2962
+ const step = Math.max(sampler.totalLength / ALONG_PATH_MAX_STEPS, 0.5);
2963
+ const timeOf = (kf) => Number(kf.time) || 0;
2964
+ const offOf = (kf) => Number(kf.value) || 0;
2965
+ const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
2966
+ const out = [];
2967
+ for (const c of cells) {
2968
+ const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
2969
+ const d = transformPathData(c.glyphD, centred);
2970
+ const sampleKf = (dist, time) => {
2971
+ const { x, y, angle } = sampler.sampleAtDistance(dist);
2972
+ return {
2973
+ time,
2974
+ value: {
2975
+ ["translate" /* Translate */]: [roundN(x, 3), roundN(y, 3)],
2976
+ ["rotate" /* Rotate */]: roundN(angle * 180 / Math.PI, 3)
2977
+ }
2978
+ };
2979
+ };
2980
+ const kfs = [];
2981
+ const opKfs = [];
2982
+ const pushKf = (dist, time) => {
2983
+ kfs.push(sampleKf(dist, time));
2984
+ if (isClip) opKfs.push({ time, value: onPath(dist) ? 1 : 0 });
2985
+ };
2986
+ pushKf(offOf(sokfs[0]) + c.midBase, timeOf(sokfs[0]));
2987
+ for (let k = 1; k < sokfs.length; k++) {
2988
+ const t0 = timeOf(sokfs[k - 1]), t1 = timeOf(sokfs[k]);
2989
+ const o0 = offOf(sokfs[k - 1]), o1 = offOf(sokfs[k]);
2990
+ const n = Math.min(ALONG_PATH_MAX_STEPS_PER_SEGMENT, Math.max(1, Math.ceil(Math.abs(o1 - o0) / step)));
2991
+ for (let s = 1; s <= n; s++) {
2992
+ const f = s / n;
2993
+ pushKf(o0 + f * (o1 - o0) + c.midBase, t0 + f * (t1 - t0));
2994
+ }
2995
+ }
2996
+ const transform = { keyframes: kfs };
2997
+ if (loop !== void 0) transform.loop = loop;
2998
+ const animate = { transform };
2999
+ if (isClip && opKfs.some((k) => k.value === 0)) {
3000
+ const op = { keyframes: opKfs };
3001
+ if (loop !== void 0) op.loop = loop;
3002
+ animate.opacity = op;
3003
+ }
3004
+ out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
3005
+ }
3006
+ return out;
3007
+ }
3008
+ function paintProps(paint) {
3009
+ const p = {};
3010
+ if (paint.fill !== void 0) p.fill = paint.fill;
3011
+ if (paint.stroke !== void 0) p.stroke = paint.stroke;
3012
+ if (paint.strokeWidth !== void 0) p.strokeWidth = paint.strokeWidth;
3013
+ return p;
3014
+ }
3015
+ function buildPaths(placements, create, warnings) {
3016
+ var _a, _b, _c;
3017
+ if (!placements.length) {
3018
+ warnings == null ? void 0 : warnings.push("textGlyphs: nothing to render");
3019
+ return [];
3020
+ }
3021
+ const byPaint = /* @__PURE__ */ new Map();
3022
+ for (const p of placements) {
3023
+ const key = JSON.stringify([(_a = p.paint.fill) != null ? _a : null, (_b = p.paint.stroke) != null ? _b : null, (_c = p.paint.strokeWidth) != null ? _c : null]);
3024
+ const baked = transformPathData(p.glyphD, p.m);
3025
+ const entry = byPaint.get(key);
3026
+ if (entry) entry.d += baked;
3027
+ else byPaint.set(key, { paint: p.paint, d: baked });
3028
+ }
3029
+ const out = [];
3030
+ for (const { paint, d } of byPaint.values()) out.push(create("path", __spreadValues({ d }, paintProps(paint)), []));
3031
+ return out;
3032
+ }
3033
+ function toGroup(node, children, create) {
3034
+ const gProps = {};
3035
+ for (const k of Object.keys(node)) {
3036
+ if (k === "type" || k === "children" || TEXT_ATTR_KEYS.indexOf(k) !== -1) continue;
3037
+ gProps[k] = node[k];
3038
+ }
3039
+ if (gProps.style && typeof gProps.style === "object") {
3040
+ const style = __spreadValues({}, gProps.style);
3041
+ delete style["white-space"];
3042
+ if (Object.keys(style).length) gProps.style = style;
3043
+ else delete gProps.style;
3044
+ }
3045
+ return create("g", gProps, children);
3046
+ }
3047
+ function materialiseGlyphText(node, opts) {
3048
+ if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
3049
+ return materialiseGlyphTextHorizontal(node, opts);
3050
+ }
3051
+ function applyTextGlyphsEffect(node, fx, ctx) {
3052
+ if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
3053
+ if (!ctx.glyphs) {
3054
+ ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
3055
+ return node;
3056
+ }
3057
+ return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
3058
+ }
3059
+ function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
3060
+ if (!ctx.glyphs) {
3061
+ ctx.warnings.push("textGlyphs: no definitions.glyphs");
3062
+ return null;
3063
+ }
3064
+ return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
3065
+ }
3066
+
2449
3067
  // src/PxMotionPath.ts
2450
3068
  function getKfTranslate(kf) {
2451
3069
  var _a;
@@ -2889,12 +3507,12 @@ var PixodeskAnimator = (() => {
2889
3507
  }
2890
3508
  return res;
2891
3509
  }
2892
- function extractPathData(str) {
2893
- if (str.startsWith("path(") && str.endsWith(")")) {
2894
- return str.slice(5, -1);
3510
+ function extractPathData(str2) {
3511
+ if (str2.startsWith("path(") && str2.endsWith(")")) {
3512
+ return str2.slice(5, -1);
2895
3513
  }
2896
- if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str)) {
2897
- return str;
3514
+ if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str2)) {
3515
+ return str2;
2898
3516
  }
2899
3517
  return void 0;
2900
3518
  }
@@ -3819,7 +4437,7 @@ var PixodeskAnimator = (() => {
3819
4437
 
3820
4438
  // src/effects/PlayerEffectsUtil.ts
3821
4439
  function applyPlayerEffects(root) {
3822
- var _a;
4440
+ var _a, _b;
3823
4441
  const ctx = {
3824
4442
  defs: [],
3825
4443
  warnings: [],
@@ -3830,7 +4448,8 @@ var PixodeskAnimator = (() => {
3830
4448
  maskAncestorChains: /* @__PURE__ */ new Map(),
3831
4449
  // Resolved engine: `frames` ONLY when explicitly set; auto/webapi/unset →
3832
4450
  // webapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
3833
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi
4451
+ engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi,
4452
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
3834
4453
  };
3835
4454
  const working = clone(root);
3836
4455
  indexById(working, ctx.idMap);
@@ -3842,16 +4461,33 @@ var PixodeskAnimator = (() => {
3842
4461
  return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
3843
4462
  }
3844
4463
  function applyPlayerEffects_exceptRetime(node, ctx) {
4464
+ var _a;
3845
4465
  if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
3846
4466
  const fx = node.effects;
3847
4467
  const originalId = typeof node.id === "string" ? node.id : void 0;
3848
4468
  const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
3849
4469
  if (!fx && !innerIdForContentRef) return node;
3850
- const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textAlongPath } = fx != null ? fx : {};
4470
+ const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
3851
4471
  const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
3852
4472
  if (fx) delete node.effects;
3853
4473
  let n = node;
3854
- n = applyTextAlongPathEffect(n, textAlongPath, ctx);
4474
+ let consumedByGlyphs = false;
4475
+ if (text == null ? void 0 : text.useGlyphs) {
4476
+ if (textPath) {
4477
+ const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
4478
+ const rawTL = textPath.textLength;
4479
+ const textLength = typeof rawTL === "number" ? rawTL : rawTL && typeof rawTL === "object" ? typeof rawTL.value === "number" ? rawTL.value : Array.isArray(rawTL.keyframes) && rawTL.keyframes.length ? Number((_a = rawTL.keyframes[0]) == null ? void 0 : _a.value) : void 0 : void 0;
4480
+ const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textLength, textPath.pathOverflow);
4481
+ if (glyphed) {
4482
+ n = glyphed;
4483
+ consumedByGlyphs = true;
4484
+ }
4485
+ } else {
4486
+ n = applyTextGlyphsEffect(n, text, ctx);
4487
+ consumedByGlyphs = true;
4488
+ }
4489
+ }
4490
+ if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
3855
4491
  n = applyFillGradientEffect(n, fillGradient, ctx);
3856
4492
  n = applyStrokeGradientEffect(n, strokeGradient, ctx);
3857
4493
  n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
@@ -4094,8 +4730,8 @@ var PixodeskAnimator = (() => {
4094
4730
  var DATA_SVG_IMAGE_RE = /^data:image\/svg\+xml(?:;[^,]*)?,/i;
4095
4731
  var DATA_IMAGE_BASE64_PAYLOAD_RE = /^data:image\/[^;,]*;base64,([A-Za-z0-9+/]{8})/i;
4096
4732
  var BASE64_RASTER_MAGICS = ["iVBORw0K", "/9j/", "R0lGOD", "UklGR", "Qk"];
4097
- function isContentSniffedRasterImage(str) {
4098
- const m = DATA_IMAGE_BASE64_PAYLOAD_RE.exec(str);
4733
+ function isContentSniffedRasterImage(str2) {
4734
+ const m = DATA_IMAGE_BASE64_PAYLOAD_RE.exec(str2);
4099
4735
  return !!m && BASE64_RASTER_MAGICS.some((magic) => m[1].startsWith(magic));
4100
4736
  }
4101
4737
  function isDangerousAttrName(nameLower) {
@@ -4109,18 +4745,18 @@ var PixodeskAnimator = (() => {
4109
4745
  return void 0;
4110
4746
  }
4111
4747
  if (nameLower === "fill" || nameLower === "stroke" || nameLower === "stopcolor") {
4112
- const str = String(value);
4113
- if (str.includes("url(") && !/^url\(#[^)]+\)$/.test(str)) {
4748
+ const str2 = String(value);
4749
+ if (str2.includes("url(") && !/^url\(#[^)]+\)$/.test(str2)) {
4114
4750
  console.warn('Attribute "' + nameLower + '" blocked: url() must be internal url(#id), got:', value);
4115
4751
  return void 0;
4116
4752
  }
4117
4753
  return value;
4118
4754
  }
4119
4755
  if (URL_VALUE_ATTRS_LOWER.has(nameLower)) {
4120
- const str = String(value);
4121
- if (str.startsWith("#")) return value;
4122
- if (/^url\(#[^)]+\)$/.test(str)) return value;
4123
- if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && (DATA_RASTER_IMAGE_RE.test(str) || DATA_SVG_IMAGE_RE.test(str) || isContentSniffedRasterImage(str))) return value;
4756
+ const str2 = String(value);
4757
+ if (str2.startsWith("#")) return value;
4758
+ if (/^url\(#[^)]+\)$/.test(str2)) return value;
4759
+ if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && (DATA_RASTER_IMAGE_RE.test(str2) || DATA_SVG_IMAGE_RE.test(str2) || isContentSniffedRasterImage(str2))) return value;
4124
4760
  console.warn('Attribute "' + nameLower + '" blocked: must be #id, url(#id), or data:image/\u2026 URI, got:', value);
4125
4761
  return void 0;
4126
4762
  }
@@ -4150,7 +4786,7 @@ var PixodeskAnimator = (() => {
4150
4786
  if (textContent) element.textContent = textContent;
4151
4787
  return element;
4152
4788
  }
4153
- function resolveStyle(style, defs) {
4789
+ function resolveStyle2(style, defs) {
4154
4790
  var _a;
4155
4791
  if (!style) return void 0;
4156
4792
  if (typeof style === "string") {
@@ -4186,7 +4822,7 @@ var PixodeskAnimator = (() => {
4186
4822
  if (!node) return null;
4187
4823
  const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
4188
4824
  const nodeDefs = getDefs(node) || defs;
4189
- const resolvedStyle = resolveStyle(style, nodeDefs);
4825
+ const resolvedStyle = resolveStyle2(style, nodeDefs);
4190
4826
  let childElements;
4191
4827
  if (children) {
4192
4828
  for (const ch of children) {