@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.js CHANGED
@@ -4,6 +4,7 @@ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
6
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __pow = Math.pow;
7
8
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
9
  var __spreadValues = (a, b) => {
9
10
  for (var prop in b || (b = {}))
@@ -906,10 +907,22 @@ var PxTriggerSchema = implementsInterface()(px.object({
906
907
  outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
907
908
  scrollIntoViewThreshold: px.number().optional()
908
909
  }));
910
+ var PxGlyphSchema = implementsInterface()(px.object({
911
+ width: px.number(),
912
+ d: px.string()
913
+ }));
914
+ var PxGlyphFontSchema = implementsInterface()(px.object({
915
+ fFamily: px.string(),
916
+ style: px.string(),
917
+ ascent: px.number(),
918
+ unitsPerEm: px.number(),
919
+ glyphs: px.record(PxGlyphSchema)
920
+ }));
909
921
  var PxDefsSchema = implementsInterface()(px.object({
910
922
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
911
923
  animations: px.record(PxAnimationDefinitionSchema).optional(),
912
- styles: px.record(px.any()).optional()
924
+ styles: px.record(px.any()).optional(),
925
+ glyphs: px.record(PxGlyphFontSchema).optional()
913
926
  }));
914
927
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
915
928
  mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.webapi, PxAnimatorMode.frames]).optional(),
@@ -1022,14 +1035,18 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
1022
1035
  gradientTransform: px.string().optional()
1023
1036
  }));
1024
1037
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1025
- var PxTextAlongPathEffectSchema = implementsInterface()(px.object({
1026
- href: px.string(),
1038
+ var PxTextPathEffectSchema = implementsInterface()(px.object({
1039
+ path: px.string(),
1040
+ pathOverflow: px.string().optional(),
1027
1041
  lengthAdjust: px.string().optional(),
1028
1042
  method: px.string().optional(),
1029
1043
  spacing: px.string().optional(),
1030
1044
  startOffset: PxAnimatableNumberSchema.optional(),
1031
1045
  textLength: PxAnimatableNumberSchema.optional()
1032
1046
  }));
1047
+ var PxTextEffectSchema = implementsInterface()(px.object({
1048
+ useGlyphs: px.boolean().optional()
1049
+ }));
1033
1050
  var PxEffectsSchema = implementsInterface()(px.object({
1034
1051
  transformation: PxTransformationEffectSchema.optional(),
1035
1052
  repeater: PxRepeaterEffectSchema.optional(),
@@ -1039,7 +1056,8 @@ var PxEffectsSchema = implementsInterface()(px.object({
1039
1056
  isCombinedShape: px.boolean().optional(),
1040
1057
  fillGradient: PxFillGradientEffectSchema.optional(),
1041
1058
  strokeGradient: PxStrokeGradientEffectSchema.optional(),
1042
- textAlongPath: PxTextAlongPathEffectSchema.optional()
1059
+ textPath: PxTextPathEffectSchema.optional(),
1060
+ text: PxTextEffectSchema.optional()
1043
1061
  }));
1044
1062
  function validateNodeEffects(root, opts) {
1045
1063
  const warnings = [];
@@ -1911,48 +1929,6 @@ function remapKeyframeTimesOnly(node, start, stretch) {
1911
1929
  }
1912
1930
  }
1913
1931
 
1914
- // src/effects/textAlongPathEffect.ts
1915
- function applyTextAlongPathEffect(node, fx, _ctx) {
1916
- var _a;
1917
- if (!fx) return node;
1918
- const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
1919
- const textPath = {
1920
- type: "textPath",
1921
- href,
1922
- children: (_a = node.children) != null ? _a : []
1923
- };
1924
- if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
1925
- if (fx.method !== void 0) textPath.method = fx.method;
1926
- if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
1927
- applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
1928
- applyAnimatableNumber(textPath, "textLength", fx.textLength);
1929
- node.children = [textPath];
1930
- return node;
1931
- }
1932
- function applyAnimatableNumber(node, attrName, raw) {
1933
- if (raw === void 0 || raw === null) return;
1934
- if (typeof raw === "number") {
1935
- node[attrName] = String(raw);
1936
- return;
1937
- }
1938
- if (typeof raw === "object" && raw !== null) {
1939
- const obj = raw;
1940
- if (Array.isArray(obj.keyframes)) {
1941
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
1942
- const animate = __spreadValues({}, prevAnimate || {});
1943
- const block = { keyframes: obj.keyframes };
1944
- if (obj.loop !== void 0) block.loop = obj.loop;
1945
- animate[attrName] = block;
1946
- node.animate = animate;
1947
- return;
1948
- }
1949
- if (typeof obj.value === "number") {
1950
- node[attrName] = String(obj.value);
1951
- return;
1952
- }
1953
- }
1954
- }
1955
-
1956
1932
  // src/PxAnimatorUtil.ts
1957
1933
  function bezierToSvgPath(path) {
1958
1934
  var _a, _b, _c, _d;
@@ -2325,6 +2301,24 @@ function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
2325
2301
  }
2326
2302
  return { ts, ds };
2327
2303
  }
2304
+ function bezier2D_tForDistance(lut, distance) {
2305
+ const { ts, ds } = lut;
2306
+ const last = ds.length - 1;
2307
+ if (distance <= 0) return ts[0];
2308
+ if (distance >= ds[last]) return ts[last];
2309
+ let lo = 1;
2310
+ let hi = last;
2311
+ while (lo < hi) {
2312
+ const mid = lo + hi >>> 1;
2313
+ if (ds[mid] < distance) lo = mid + 1;
2314
+ else hi = mid;
2315
+ }
2316
+ const dPrev = ds[hi - 1];
2317
+ const dCur = ds[hi];
2318
+ const span = dCur - dPrev;
2319
+ const frac = span > 0 ? (distance - dPrev) / span : 0;
2320
+ return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
2321
+ }
2328
2322
  function bezier2D_arcAtT(lut, t) {
2329
2323
  const { ts, ds } = lut;
2330
2324
  const last = ts.length - 1;
@@ -2347,6 +2341,623 @@ function invertEasing(easing) {
2347
2341
  return cubicBezier(flipped);
2348
2342
  }
2349
2343
 
2344
+ // src/effects/pathSampler.ts
2345
+ var LUT_STEPS = 48;
2346
+ var CMD_RE = /[MmLlHhVvCcSsQqTtAaZz]/;
2347
+ function tokenize(d) {
2348
+ const tokens = [];
2349
+ const re = /([MmLlHhVvCcSsQqTtAaZz])|(-?\d*\.?\d+(?:[eE][-+]?\d+)?)/g;
2350
+ let m;
2351
+ while ((m = re.exec(d)) !== null) tokens.push(m[0]);
2352
+ return tokens;
2353
+ }
2354
+ function quadToCubic(P0, Qc, P3) {
2355
+ return {
2356
+ P1: [P0[0] + 2 / 3 * (Qc[0] - P0[0]), P0[1] + 2 / 3 * (Qc[1] - P0[1])],
2357
+ P2: [P3[0] + 2 / 3 * (Qc[0] - P3[0]), P3[1] + 2 / 3 * (Qc[1] - P3[1])]
2358
+ };
2359
+ }
2360
+ function parseCubics(d) {
2361
+ const tokens = tokenize(d);
2362
+ const segs = [];
2363
+ let i = 0;
2364
+ let cx = 0, cy = 0;
2365
+ let sx = 0, sy = 0;
2366
+ let pcx = 0, pcy = 0;
2367
+ let pqx = 0, pqy = 0;
2368
+ let prevCmd = "";
2369
+ const num2 = () => parseFloat(tokens[i++]);
2370
+ const push = (P1, P2, P3) => {
2371
+ const P0 = [cx, cy];
2372
+ const lut = bezier2D_arcLengthLUT(P0, P1, P2, P3, LUT_STEPS);
2373
+ segs.push({ P0, P1, P2, P3, lut, len: lut.ds[lut.ds.length - 1] });
2374
+ cx = P3[0];
2375
+ cy = P3[1];
2376
+ };
2377
+ const pushLine = (x, y) => {
2378
+ push(
2379
+ [cx + (x - cx) / 3, cy + (y - cy) / 3],
2380
+ [cx + 2 * (x - cx) / 3, cy + 2 * (y - cy) / 3],
2381
+ [x, y]
2382
+ );
2383
+ };
2384
+ while (i < tokens.length) {
2385
+ let cmd = tokens[i];
2386
+ if (CMD_RE.test(cmd)) i++;
2387
+ else cmd = prevCmd === "M" ? "L" : prevCmd === "m" ? "l" : prevCmd;
2388
+ const rel = cmd >= "a";
2389
+ const U = cmd.toUpperCase();
2390
+ if (U === "Z") {
2391
+ pushLine(sx, sy);
2392
+ cx = sx;
2393
+ cy = sy;
2394
+ prevCmd = cmd;
2395
+ continue;
2396
+ }
2397
+ if (U === "M") {
2398
+ const x = num2() + (rel ? cx : 0), y = num2() + (rel ? cy : 0);
2399
+ cx = x;
2400
+ cy = y;
2401
+ sx = x;
2402
+ sy = y;
2403
+ prevCmd = cmd;
2404
+ continue;
2405
+ }
2406
+ if (U === "L") {
2407
+ pushLine(num2() + (rel ? cx : 0), num2() + (rel ? cy : 0));
2408
+ } else if (U === "H") {
2409
+ pushLine(num2() + (rel ? cx : 0), cy);
2410
+ } else if (U === "V") {
2411
+ pushLine(cx, num2() + (rel ? cy : 0));
2412
+ } else if (U === "C") {
2413
+ const p1 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2414
+ const p2 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2415
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2416
+ pcx = p2[0];
2417
+ pcy = p2[1];
2418
+ push(p1, p2, p3);
2419
+ } else if (U === "S") {
2420
+ const smooth = prevCmd.toUpperCase() === "C" || prevCmd.toUpperCase() === "S";
2421
+ const p1 = smooth ? [2 * cx - pcx, 2 * cy - pcy] : [cx, cy];
2422
+ const p2 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2423
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2424
+ pcx = p2[0];
2425
+ pcy = p2[1];
2426
+ push(p1, p2, p3);
2427
+ } else if (U === "Q") {
2428
+ const qc = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2429
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2430
+ pqx = qc[0];
2431
+ pqy = qc[1];
2432
+ const { P1, P2 } = quadToCubic([cx, cy], qc, p3);
2433
+ push(P1, P2, p3);
2434
+ } else if (U === "T") {
2435
+ const smooth = prevCmd.toUpperCase() === "Q" || prevCmd.toUpperCase() === "T";
2436
+ const qc = smooth ? [2 * cx - pqx, 2 * cy - pqy] : [cx, cy];
2437
+ const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
2438
+ pqx = qc[0];
2439
+ pqy = qc[1];
2440
+ const { P1, P2 } = quadToCubic([cx, cy], qc, p3);
2441
+ push(P1, P2, p3);
2442
+ } else if (U === "A") {
2443
+ i += 5;
2444
+ pushLine(num2() + (rel ? cx : 0), num2() + (rel ? cy : 0));
2445
+ } else {
2446
+ i++;
2447
+ continue;
2448
+ }
2449
+ prevCmd = cmd;
2450
+ }
2451
+ return segs.length ? segs : null;
2452
+ }
2453
+ function clamp2(v, lo, hi) {
2454
+ return v < lo ? lo : v > hi ? hi : v;
2455
+ }
2456
+ function createPathSampler(d) {
2457
+ const segs = parseCubics(d);
2458
+ if (!segs) return null;
2459
+ const cum = new Float64Array(segs.length + 1);
2460
+ for (let k = 0; k < segs.length; k++) cum[k + 1] = cum[k] + segs[k].len;
2461
+ const totalLength = cum[segs.length];
2462
+ const start = segs[0].P0, end = segs[segs.length - 1].P3;
2463
+ const closed = Math.hypot(end[0] - start[0], end[1] - start[1]) < 1e-3;
2464
+ const sampleOn = (dist) => {
2465
+ let k = 0;
2466
+ while (k < segs.length - 1 && dist > cum[k + 1]) k++;
2467
+ const seg = segs[k];
2468
+ const local = dist - cum[k];
2469
+ const t = seg.len > 0 ? bezier2D_tForDistance(seg.lut, local) : 0;
2470
+ const [x, y] = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
2471
+ const [dx, dy] = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
2472
+ return { x, y, angle: Math.atan2(dy, dx) };
2473
+ };
2474
+ return {
2475
+ totalLength,
2476
+ closed,
2477
+ sampleAtDistance(dist) {
2478
+ if (!closed && (dist < 0 || dist > totalLength)) {
2479
+ const edge = dist < 0 ? 0 : totalLength;
2480
+ const p = sampleOn(edge);
2481
+ const over = dist - edge;
2482
+ return { x: p.x + Math.cos(p.angle) * over, y: p.y + Math.sin(p.angle) * over, angle: p.angle };
2483
+ }
2484
+ return sampleOn(clamp2(dist, 0, totalLength));
2485
+ }
2486
+ };
2487
+ }
2488
+
2489
+ // src/effects/textPathEffect.ts
2490
+ var EXTEND_MARGIN_FRAC = 0.15;
2491
+ function numRange(v) {
2492
+ if (typeof v === "number") return { min: v, max: v };
2493
+ if (v && typeof v === "object") {
2494
+ const o = v;
2495
+ if (typeof o.value === "number") return { min: o.value, max: o.value };
2496
+ if (Array.isArray(o.keyframes) && o.keyframes.length) {
2497
+ const vals = o.keyframes.map((k) => Number(k.value) || 0);
2498
+ return { min: Math.min(...vals), max: Math.max(...vals) };
2499
+ }
2500
+ }
2501
+ return { min: 0, max: 0 };
2502
+ }
2503
+ function estimateTextAdvance(node) {
2504
+ let chars = 0, maxFont = 16;
2505
+ const walk = (el) => {
2506
+ var _a, _b;
2507
+ const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
2508
+ if (fs) maxFont = Math.max(maxFont, fs);
2509
+ const t = (_b = el.text) != null ? _b : el.textContent;
2510
+ if (typeof t === "string") chars += t.length;
2511
+ if (el.children) for (const c of el.children) walk(c);
2512
+ };
2513
+ walk(node);
2514
+ return chars * maxFont;
2515
+ }
2516
+ var r3 = (n) => Math.round(n * 1e3) / 1e3;
2517
+ function shiftAnimatable(v, by) {
2518
+ if (!by || v === void 0 || v === null) return v;
2519
+ if (typeof v === "number") return v + by;
2520
+ const o = v;
2521
+ if (typeof o.value === "number") return __spreadProps(__spreadValues({}, o), { value: o.value + by });
2522
+ if (Array.isArray(o.keyframes)) return __spreadProps(__spreadValues({}, o), { keyframes: o.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by })) });
2523
+ return v;
2524
+ }
2525
+ function extendedPathForBrowser(pathD, opts) {
2526
+ var _a;
2527
+ if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
2528
+ const sampler = createPathSampler(pathD);
2529
+ if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
2530
+ const L = sampler.totalLength;
2531
+ const margin = EXTEND_MARGIN_FRAC * L;
2532
+ const so = numRange(opts.startOffset);
2533
+ const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
2534
+ const startOverflow = Math.max(0, -so.min);
2535
+ const endOverflow = Math.max(0, so.max + runWidth - L);
2536
+ const startExt = startOverflow > 0 ? startOverflow + margin : 0;
2537
+ const endExt = endOverflow > 0 ? endOverflow + margin : 0;
2538
+ if (endExt <= 0 && startExt <= 0) return { d: pathD, startShift: 0 };
2539
+ const s = sampler.sampleAtDistance(0);
2540
+ const e = sampler.sampleAtDistance(L);
2541
+ let d = pathD;
2542
+ if (startExt > 0) {
2543
+ const sx = s.x - Math.cos(s.angle) * startExt, sy = s.y - Math.sin(s.angle) * startExt;
2544
+ const rest = pathD.replace(/^\s*[Mm]\s*-?[\d.]+[\s,]+-?[\d.]+/, "");
2545
+ d = "M" + r3(sx) + "," + r3(sy) + "L" + r3(s.x) + "," + r3(s.y) + rest;
2546
+ }
2547
+ if (endExt > 0) {
2548
+ const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
2549
+ d += "L" + r3(ex) + "," + r3(ey);
2550
+ }
2551
+ return { d, startShift: startExt };
2552
+ }
2553
+ function applyTextPathEffect(node, fx, ctx) {
2554
+ var _a;
2555
+ if (!fx || typeof fx.path !== "string" || !fx.path) return node;
2556
+ const pathId = genId(ctx, "tpath");
2557
+ const { d, startShift } = extendedPathForBrowser(fx.path, {
2558
+ pathOverflow: fx.pathOverflow,
2559
+ startOffset: fx.startOffset,
2560
+ textLength: fx.textLength,
2561
+ advance: estimateTextAdvance(node)
2562
+ });
2563
+ ctx.defs.push({ type: "path", id: pathId, d });
2564
+ const textPath = {
2565
+ type: "textPath",
2566
+ href: "#" + pathId,
2567
+ children: (_a = node.children) != null ? _a : []
2568
+ };
2569
+ if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
2570
+ if (fx.method !== void 0) textPath.method = fx.method;
2571
+ if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
2572
+ applyAnimatableNumber(textPath, "startOffset", shiftAnimatable(fx.startOffset, startShift));
2573
+ applyAnimatableNumber(textPath, "textLength", fx.textLength);
2574
+ node.children = [textPath];
2575
+ return node;
2576
+ }
2577
+ function applyAnimatableNumber(node, attrName, raw) {
2578
+ if (raw === void 0 || raw === null) return;
2579
+ if (typeof raw === "number") {
2580
+ node[attrName] = String(raw);
2581
+ return;
2582
+ }
2583
+ if (typeof raw === "object" && raw !== null) {
2584
+ const obj = raw;
2585
+ if (Array.isArray(obj.keyframes)) {
2586
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
2587
+ const animate = __spreadValues({}, prevAnimate || {});
2588
+ const block = { keyframes: obj.keyframes };
2589
+ if (obj.loop !== void 0) block.loop = obj.loop;
2590
+ animate[attrName] = block;
2591
+ node.animate = animate;
2592
+ return;
2593
+ }
2594
+ if (typeof obj.value === "number") {
2595
+ node[attrName] = String(obj.value);
2596
+ return;
2597
+ }
2598
+ }
2599
+ }
2600
+
2601
+ // src/effects/elementFactory.ts
2602
+ var jsonElementFactory = (type, props, children) => {
2603
+ const node = { type };
2604
+ for (const k in props) if (props[k] !== void 0) node[k] = props[k];
2605
+ const arr = Array.isArray(children) ? children.filter((c) => c != null) : children != null ? [children] : [];
2606
+ if (arr.length) node.children = arr;
2607
+ return node;
2608
+ };
2609
+
2610
+ // src/effects/glyphPathBake.ts
2611
+ function fmt(v, decimals) {
2612
+ return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
2613
+ }
2614
+ function pack(nums, decimals) {
2615
+ let s = "";
2616
+ for (let i = 0; i < nums.length; i++) {
2617
+ const str2 = fmt(nums[i], decimals);
2618
+ if (i > 0 && str2.charCodeAt(0) !== 45) s += " ";
2619
+ s += str2;
2620
+ }
2621
+ return s;
2622
+ }
2623
+ function apply(m, x, y) {
2624
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
2625
+ }
2626
+ var TOKEN_RE = /([MLCQZ])|(-?\d*\.?\d+(?:e[-+]?\d+)?)/gi;
2627
+ function transformPathData(d, m, decimals = 2) {
2628
+ const tokens = [];
2629
+ let match;
2630
+ TOKEN_RE.lastIndex = 0;
2631
+ while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
2632
+ let out = "";
2633
+ let i = 0;
2634
+ const num2 = () => parseFloat(tokens[i++]);
2635
+ while (i < tokens.length) {
2636
+ const cmd = tokens[i++];
2637
+ if (cmd === "M" || cmd === "L") {
2638
+ const [x, y] = apply(m, num2(), num2());
2639
+ out += cmd + pack([x, y], decimals);
2640
+ } else if (cmd === "C") {
2641
+ const [x1, y1] = apply(m, num2(), num2());
2642
+ const [x2, y2] = apply(m, num2(), num2());
2643
+ const [x, y] = apply(m, num2(), num2());
2644
+ out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
2645
+ } else if (cmd === "Q") {
2646
+ const [x1, y1] = apply(m, num2(), num2());
2647
+ const [x, y] = apply(m, num2(), num2());
2648
+ out += "Q" + pack([x1, y1, x, y], decimals);
2649
+ } else if (cmd === "Z" || cmd === "z") {
2650
+ out += "Z";
2651
+ }
2652
+ }
2653
+ return out;
2654
+ }
2655
+
2656
+ // src/effects/textGlyphsEffect.ts
2657
+ var DEFAULT_FONT_SIZE = 16;
2658
+ var TEXT_ATTR_KEYS = [
2659
+ "fontFamily",
2660
+ "fontSize",
2661
+ "fontWeight",
2662
+ "fontStyle",
2663
+ "textAnchor",
2664
+ "letterSpacing",
2665
+ "wordSpacing",
2666
+ "textDecoration",
2667
+ "textTransform",
2668
+ "whiteSpace",
2669
+ "x",
2670
+ "y",
2671
+ "dx",
2672
+ "dy",
2673
+ "lengthAdjust",
2674
+ "fill",
2675
+ "stroke",
2676
+ "strokeWidth",
2677
+ "effects",
2678
+ TEXT_ATTR,
2679
+ TEXT_CONTENT_ATTR,
2680
+ "xml:space"
2681
+ ];
2682
+ function parseLen(v) {
2683
+ if (typeof v === "number") return v;
2684
+ if (typeof v === "string") {
2685
+ const n = parseFloat(v);
2686
+ return isNaN(n) ? void 0 : n;
2687
+ }
2688
+ return void 0;
2689
+ }
2690
+ function str(v) {
2691
+ return typeof v === "string" ? v : void 0;
2692
+ }
2693
+ function resolveStyle(node, parent) {
2694
+ var _a, _b, _c, _d, _e, _f, _g;
2695
+ return {
2696
+ fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
2697
+ fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
2698
+ fill: (_c = node.fill) != null ? _c : parent.fill,
2699
+ stroke: (_d = node.stroke) != null ? _d : parent.stroke,
2700
+ strokeWidth: (_e = node.strokeWidth) != null ? _e : parent.strokeWidth,
2701
+ letterSpacing: (_f = parseLen(node.letterSpacing)) != null ? _f : parent.letterSpacing,
2702
+ wordSpacing: (_g = parseLen(node.wordSpacing)) != null ? _g : parent.wordSpacing
2703
+ };
2704
+ }
2705
+ function rootStyleOf(node) {
2706
+ var _a, _b, _c;
2707
+ return {
2708
+ fontFamily: str(node.fontFamily),
2709
+ fontSize: (_a = parseLen(node.fontSize)) != null ? _a : DEFAULT_FONT_SIZE,
2710
+ fill: node.fill,
2711
+ stroke: node.stroke,
2712
+ strokeWidth: node.strokeWidth,
2713
+ letterSpacing: (_b = parseLen(node.letterSpacing)) != null ? _b : 0,
2714
+ wordSpacing: (_c = parseLen(node.wordSpacing)) != null ? _c : 0
2715
+ };
2716
+ }
2717
+ function paintOf(s) {
2718
+ const p = {};
2719
+ if (s.fill !== void 0) p.fill = s.fill;
2720
+ if (s.stroke !== void 0) p.stroke = s.stroke;
2721
+ if (s.strokeWidth !== void 0) p.strokeWidth = s.strokeWidth;
2722
+ return p;
2723
+ }
2724
+ function glyphFontFor(s, glyphs, soleFont, warnings) {
2725
+ var _a;
2726
+ const gf = s.fontFamily ? glyphs[s.fontFamily] : soleFont;
2727
+ if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a = s.fontFamily) != null ? _a : "") + '"');
2728
+ return gf;
2729
+ }
2730
+ function soleFontOf(glyphs) {
2731
+ const names = Object.keys(glyphs);
2732
+ return names.length === 1 ? glyphs[names[0]] : void 0;
2733
+ }
2734
+ function materialiseGlyphTextHorizontal(node, opts) {
2735
+ var _a, _b, _c, _d;
2736
+ const { glyphs, create = jsonElementFactory, warnings } = opts;
2737
+ const soleFont = soleFontOf(glyphs);
2738
+ const pen = { x: (_a = parseLen(node.x)) != null ? _a : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
2739
+ const placements = [];
2740
+ const lines = [{ start: pen.x, end: pen.x }];
2741
+ let line = 0;
2742
+ const renderChars = (content, s) => {
2743
+ const gf = glyphFontFor(s, glyphs, soleFont, warnings);
2744
+ if (!gf) return;
2745
+ const scale = s.fontSize / gf.unitsPerEm;
2746
+ const paint = paintOf(s);
2747
+ for (let i = 0; i < content.length; i++) {
2748
+ const ch = content.charAt(i);
2749
+ const g = gf.glyphs[ch];
2750
+ 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 });
2751
+ pen.x += (g ? g.width : 0) * scale + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
2752
+ lines[line].end = pen.x;
2753
+ }
2754
+ };
2755
+ const walk = (el, parentStyle) => {
2756
+ var _a2, _b2, _c2, _d2;
2757
+ const s = resolveStyle(el, parentStyle);
2758
+ const x = parseLen(el.x);
2759
+ const y = parseLen(el.y);
2760
+ if (x !== void 0) {
2761
+ pen.x = x;
2762
+ line = lines.length;
2763
+ lines.push({ start: pen.x, end: pen.x });
2764
+ }
2765
+ if (y !== void 0) pen.y = y;
2766
+ pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
2767
+ pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
2768
+ const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
2769
+ if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
2770
+ if (el.children) for (const ch of el.children) walk(ch, s);
2771
+ };
2772
+ const rootStyle = rootStyleOf(node);
2773
+ if (node.children) for (const ch of node.children) walk(ch, rootStyle);
2774
+ const rootContent = (_c = str(node[TEXT_ATTR])) != null ? _c : str(node[TEXT_CONTENT_ATTR]);
2775
+ if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
2776
+ const anchor = str(node.textAnchor);
2777
+ if (anchor === "middle" || anchor === "end") {
2778
+ for (const p of placements) {
2779
+ const w = lines[p.line].end - lines[p.line].start;
2780
+ const shift = anchor === "middle" ? -w / 2 : -w;
2781
+ p.m = [p.scale, 0, 0, p.scale, p.x + shift, p.y];
2782
+ }
2783
+ }
2784
+ return toGroup(node, buildPaths(placements, create, warnings), create);
2785
+ }
2786
+ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
2787
+ const cells = [];
2788
+ let adv = 0;
2789
+ const walk = (el, parentStyle) => {
2790
+ var _a, _b;
2791
+ const s = resolveStyle(el, parentStyle);
2792
+ const content = (_a = str(el[TEXT_ATTR])) != null ? _a : str(el[TEXT_CONTENT_ATTR]);
2793
+ if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
2794
+ const gf = glyphFontFor(s, glyphs, soleFont, warnings);
2795
+ if (gf) {
2796
+ const scale = s.fontSize / gf.unitsPerEm;
2797
+ const paint = paintOf(s);
2798
+ for (let i = 0; i < content.length; i++) {
2799
+ const ch = content.charAt(i);
2800
+ const g = gf.glyphs[ch];
2801
+ const glyphAdv = (g ? g.width : 0) * scale;
2802
+ if (g && g.d) cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
2803
+ adv += glyphAdv + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
2804
+ }
2805
+ }
2806
+ }
2807
+ if (el.children) for (const ch of el.children) walk(ch, s);
2808
+ };
2809
+ walk(node, rootStyleOf(node));
2810
+ return { cells, width: adv };
2811
+ }
2812
+ function alongAffine(sampler, dist, scale, widthEm) {
2813
+ const { x, y, angle } = sampler.sampleAtDistance(dist);
2814
+ const cos = Math.cos(angle), sin = Math.sin(angle), hw = widthEm / 2;
2815
+ return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw, y - scale * sin * hw];
2816
+ }
2817
+ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
2818
+ var _a;
2819
+ const { glyphs, create = jsonElementFactory, warnings } = opts;
2820
+ const sampler = pathD ? createPathSampler(pathD) : null;
2821
+ if (!sampler) {
2822
+ warnings == null ? void 0 : warnings.push("textGlyphs: unparsable along-path geometry");
2823
+ return null;
2824
+ }
2825
+ const soleFont = soleFontOf(glyphs);
2826
+ const { cells, width } = collectAlongPathCells(node, glyphs, soleFont, warnings);
2827
+ if (!cells.length) return toGroup(node, [], create);
2828
+ if (textLength && textLength > 0 && width > 0) {
2829
+ const k = textLength / width;
2830
+ for (const c of cells) c.midBase *= k;
2831
+ }
2832
+ const isClip = pathOverflow === "clip" && !sampler.closed;
2833
+ const so = readAnimatable(startOffset);
2834
+ if (so.kind === "animated" /* Animated */ && so.keyframes.length >= 2) {
2835
+ return toGroup(node, buildAnimatedAlongPath(cells, sampler, so.keyframes, so.loop, create, isClip), create);
2836
+ }
2837
+ 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;
2838
+ const placeCells = isClip ? cells.filter((c) => {
2839
+ const d = base + c.midBase;
2840
+ return d >= 0 && d <= sampler.totalLength;
2841
+ }) : cells;
2842
+ const placements = placeCells.map((c) => ({
2843
+ glyphD: c.glyphD,
2844
+ paint: c.paint,
2845
+ m: alongAffine(sampler, base + c.midBase, c.scale, c.widthEm)
2846
+ }));
2847
+ return toGroup(node, buildPaths(placements, create, warnings), create);
2848
+ }
2849
+ var ALONG_PATH_MAX_STEPS = 48;
2850
+ var ALONG_PATH_MAX_STEPS_PER_SEGMENT = 64;
2851
+ function roundN(v, n) {
2852
+ const f = __pow(10, n);
2853
+ return Math.round(v * f) / f;
2854
+ }
2855
+ function buildAnimatedAlongPath(cells, sampler, sokfs, loop, create, isClip) {
2856
+ const step = Math.max(sampler.totalLength / ALONG_PATH_MAX_STEPS, 0.5);
2857
+ const timeOf = (kf) => Number(kf.time) || 0;
2858
+ const offOf = (kf) => Number(kf.value) || 0;
2859
+ const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
2860
+ const out = [];
2861
+ for (const c of cells) {
2862
+ const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
2863
+ const d = transformPathData(c.glyphD, centred);
2864
+ const sampleKf = (dist, time) => {
2865
+ const { x, y, angle } = sampler.sampleAtDistance(dist);
2866
+ return {
2867
+ time,
2868
+ value: {
2869
+ ["translate" /* Translate */]: [roundN(x, 3), roundN(y, 3)],
2870
+ ["rotate" /* Rotate */]: roundN(angle * 180 / Math.PI, 3)
2871
+ }
2872
+ };
2873
+ };
2874
+ const kfs = [];
2875
+ const opKfs = [];
2876
+ const pushKf = (dist, time) => {
2877
+ kfs.push(sampleKf(dist, time));
2878
+ if (isClip) opKfs.push({ time, value: onPath(dist) ? 1 : 0 });
2879
+ };
2880
+ pushKf(offOf(sokfs[0]) + c.midBase, timeOf(sokfs[0]));
2881
+ for (let k = 1; k < sokfs.length; k++) {
2882
+ const t0 = timeOf(sokfs[k - 1]), t1 = timeOf(sokfs[k]);
2883
+ const o0 = offOf(sokfs[k - 1]), o1 = offOf(sokfs[k]);
2884
+ const n = Math.min(ALONG_PATH_MAX_STEPS_PER_SEGMENT, Math.max(1, Math.ceil(Math.abs(o1 - o0) / step)));
2885
+ for (let s = 1; s <= n; s++) {
2886
+ const f = s / n;
2887
+ pushKf(o0 + f * (o1 - o0) + c.midBase, t0 + f * (t1 - t0));
2888
+ }
2889
+ }
2890
+ const transform = { keyframes: kfs };
2891
+ if (loop !== void 0) transform.loop = loop;
2892
+ const animate = { transform };
2893
+ if (isClip && opKfs.some((k) => k.value === 0)) {
2894
+ const op = { keyframes: opKfs };
2895
+ if (loop !== void 0) op.loop = loop;
2896
+ animate.opacity = op;
2897
+ }
2898
+ out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
2899
+ }
2900
+ return out;
2901
+ }
2902
+ function paintProps(paint) {
2903
+ const p = {};
2904
+ if (paint.fill !== void 0) p.fill = paint.fill;
2905
+ if (paint.stroke !== void 0) p.stroke = paint.stroke;
2906
+ if (paint.strokeWidth !== void 0) p.strokeWidth = paint.strokeWidth;
2907
+ return p;
2908
+ }
2909
+ function buildPaths(placements, create, warnings) {
2910
+ var _a, _b, _c;
2911
+ if (!placements.length) {
2912
+ warnings == null ? void 0 : warnings.push("textGlyphs: nothing to render");
2913
+ return [];
2914
+ }
2915
+ const byPaint = /* @__PURE__ */ new Map();
2916
+ for (const p of placements) {
2917
+ 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]);
2918
+ const baked = transformPathData(p.glyphD, p.m);
2919
+ const entry = byPaint.get(key);
2920
+ if (entry) entry.d += baked;
2921
+ else byPaint.set(key, { paint: p.paint, d: baked });
2922
+ }
2923
+ const out = [];
2924
+ for (const { paint, d } of byPaint.values()) out.push(create("path", __spreadValues({ d }, paintProps(paint)), []));
2925
+ return out;
2926
+ }
2927
+ function toGroup(node, children, create) {
2928
+ const gProps = {};
2929
+ for (const k of Object.keys(node)) {
2930
+ if (k === "type" || k === "children" || TEXT_ATTR_KEYS.indexOf(k) !== -1) continue;
2931
+ gProps[k] = node[k];
2932
+ }
2933
+ if (gProps.style && typeof gProps.style === "object") {
2934
+ const style = __spreadValues({}, gProps.style);
2935
+ delete style["white-space"];
2936
+ if (Object.keys(style).length) gProps.style = style;
2937
+ else delete gProps.style;
2938
+ }
2939
+ return create("g", gProps, children);
2940
+ }
2941
+ function materialiseGlyphText(node, opts) {
2942
+ if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
2943
+ return materialiseGlyphTextHorizontal(node, opts);
2944
+ }
2945
+ function applyTextGlyphsEffect(node, fx, ctx) {
2946
+ if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
2947
+ if (!ctx.glyphs) {
2948
+ ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
2949
+ return node;
2950
+ }
2951
+ return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
2952
+ }
2953
+ function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
2954
+ if (!ctx.glyphs) {
2955
+ ctx.warnings.push("textGlyphs: no definitions.glyphs");
2956
+ return null;
2957
+ }
2958
+ return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
2959
+ }
2960
+
2350
2961
  // src/PxMotionPath.ts
2351
2962
  function getKfTranslate(kf) {
2352
2963
  var _a;
@@ -2790,12 +3401,12 @@ function parseSvgPathToBezier(d) {
2790
3401
  }
2791
3402
  return res;
2792
3403
  }
2793
- function extractPathData(str) {
2794
- if (str.startsWith("path(") && str.endsWith(")")) {
2795
- return str.slice(5, -1);
3404
+ function extractPathData(str2) {
3405
+ if (str2.startsWith("path(") && str2.endsWith(")")) {
3406
+ return str2.slice(5, -1);
2796
3407
  }
2797
- if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str)) {
2798
- return str;
3408
+ if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str2)) {
3409
+ return str2;
2799
3410
  }
2800
3411
  return void 0;
2801
3412
  }
@@ -3720,7 +4331,7 @@ function rectToPathD(node) {
3720
4331
 
3721
4332
  // src/effects/PlayerEffectsUtil.ts
3722
4333
  function applyPlayerEffects(root) {
3723
- var _a;
4334
+ var _a, _b;
3724
4335
  const ctx = {
3725
4336
  defs: [],
3726
4337
  warnings: [],
@@ -3731,7 +4342,8 @@ function applyPlayerEffects(root) {
3731
4342
  maskAncestorChains: /* @__PURE__ */ new Map(),
3732
4343
  // Resolved engine: `frames` ONLY when explicitly set; auto/webapi/unset →
3733
4344
  // webapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
3734
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi
4345
+ engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi,
4346
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
3735
4347
  };
3736
4348
  const working = clone(root);
3737
4349
  indexById(working, ctx.idMap);
@@ -3743,16 +4355,33 @@ function applyPlayerEffects(root) {
3743
4355
  return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
3744
4356
  }
3745
4357
  function applyPlayerEffects_exceptRetime(node, ctx) {
4358
+ var _a;
3746
4359
  if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
3747
4360
  const fx = node.effects;
3748
4361
  const originalId = typeof node.id === "string" ? node.id : void 0;
3749
4362
  const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
3750
4363
  if (!fx && !innerIdForContentRef) return node;
3751
- const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textAlongPath } = fx != null ? fx : {};
4364
+ const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
3752
4365
  const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
3753
4366
  if (fx) delete node.effects;
3754
4367
  let n = node;
3755
- n = applyTextAlongPathEffect(n, textAlongPath, ctx);
4368
+ let consumedByGlyphs = false;
4369
+ if (text == null ? void 0 : text.useGlyphs) {
4370
+ if (textPath) {
4371
+ const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
4372
+ const rawTL = textPath.textLength;
4373
+ 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;
4374
+ const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textLength, textPath.pathOverflow);
4375
+ if (glyphed) {
4376
+ n = glyphed;
4377
+ consumedByGlyphs = true;
4378
+ }
4379
+ } else {
4380
+ n = applyTextGlyphsEffect(n, text, ctx);
4381
+ consumedByGlyphs = true;
4382
+ }
4383
+ }
4384
+ if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
3756
4385
  n = applyFillGradientEffect(n, fillGradient, ctx);
3757
4386
  n = applyStrokeGradientEffect(n, strokeGradient, ctx);
3758
4387
  n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
@@ -3995,8 +4624,8 @@ var DATA_RASTER_IMAGE_RE = /^data:image\/(?:png|jpe?g|gif|webp|bmp);base64,/i;
3995
4624
  var DATA_SVG_IMAGE_RE = /^data:image\/svg\+xml(?:;[^,]*)?,/i;
3996
4625
  var DATA_IMAGE_BASE64_PAYLOAD_RE = /^data:image\/[^;,]*;base64,([A-Za-z0-9+/]{8})/i;
3997
4626
  var BASE64_RASTER_MAGICS = ["iVBORw0K", "/9j/", "R0lGOD", "UklGR", "Qk"];
3998
- function isContentSniffedRasterImage(str) {
3999
- const m = DATA_IMAGE_BASE64_PAYLOAD_RE.exec(str);
4627
+ function isContentSniffedRasterImage(str2) {
4628
+ const m = DATA_IMAGE_BASE64_PAYLOAD_RE.exec(str2);
4000
4629
  return !!m && BASE64_RASTER_MAGICS.some((magic) => m[1].startsWith(magic));
4001
4630
  }
4002
4631
  function isDangerousAttrName(nameLower) {
@@ -4010,18 +4639,18 @@ function sanitiseAttributeValue(name, value) {
4010
4639
  return void 0;
4011
4640
  }
4012
4641
  if (nameLower === "fill" || nameLower === "stroke" || nameLower === "stopcolor") {
4013
- const str = String(value);
4014
- if (str.includes("url(") && !/^url\(#[^)]+\)$/.test(str)) {
4642
+ const str2 = String(value);
4643
+ if (str2.includes("url(") && !/^url\(#[^)]+\)$/.test(str2)) {
4015
4644
  console.warn('Attribute "' + nameLower + '" blocked: url() must be internal url(#id), got:', value);
4016
4645
  return void 0;
4017
4646
  }
4018
4647
  return value;
4019
4648
  }
4020
4649
  if (URL_VALUE_ATTRS_LOWER.has(nameLower)) {
4021
- const str = String(value);
4022
- if (str.startsWith("#")) return value;
4023
- if (/^url\(#[^)]+\)$/.test(str)) return value;
4024
- if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && (DATA_RASTER_IMAGE_RE.test(str) || DATA_SVG_IMAGE_RE.test(str) || isContentSniffedRasterImage(str))) return value;
4650
+ const str2 = String(value);
4651
+ if (str2.startsWith("#")) return value;
4652
+ if (/^url\(#[^)]+\)$/.test(str2)) return value;
4653
+ if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && (DATA_RASTER_IMAGE_RE.test(str2) || DATA_SVG_IMAGE_RE.test(str2) || isContentSniffedRasterImage(str2))) return value;
4025
4654
  console.warn('Attribute "' + nameLower + '" blocked: must be #id, url(#id), or data:image/\u2026 URI, got:', value);
4026
4655
  return void 0;
4027
4656
  }
@@ -4051,7 +4680,7 @@ function createElement(tagName, normalisedProps, style, children, textContent) {
4051
4680
  if (textContent) element.textContent = textContent;
4052
4681
  return element;
4053
4682
  }
4054
- function resolveStyle(style, defs) {
4683
+ function resolveStyle2(style, defs) {
4055
4684
  var _a;
4056
4685
  if (!style) return void 0;
4057
4686
  if (typeof style === "string") {
@@ -4087,7 +4716,7 @@ function renderNode(node, defs) {
4087
4716
  if (!node) return null;
4088
4717
  const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
4089
4718
  const nodeDefs = getDefs(node) || defs;
4090
- const resolvedStyle = resolveStyle(style, nodeDefs);
4719
+ const resolvedStyle = resolveStyle2(style, nodeDefs);
4091
4720
  let childElements;
4092
4721
  if (children) {
4093
4722
  for (const ch of children) {
@@ -5139,7 +5768,8 @@ export {
5139
5768
  PxRetimeEffectSchema,
5140
5769
  PxStrokeGradientEffectSchema,
5141
5770
  PxSvgNodeExtra,
5142
- PxTextAlongPathEffectSchema,
5771
+ PxTextEffectSchema,
5772
+ PxTextPathEffectSchema,
5143
5773
  PxTransformPartsSchema,
5144
5774
  PxTransformValueSchema,
5145
5775
  PxTransformationEffectSchema,
@@ -5159,6 +5789,7 @@ export {
5159
5789
  describeSchema,
5160
5790
  diffInEffect,
5161
5791
  evaluateMotionPathSegment,
5792
+ extendedPathForBrowser,
5162
5793
  generateNewIds,
5163
5794
  getAnimatorConfig,
5164
5795
  getBindings,
@@ -5167,9 +5798,13 @@ export {
5167
5798
  getNormalizedProps,
5168
5799
  isPxElementFileFormat,
5169
5800
  isPxElementFileFormatDeep,
5801
+ jsonElementFactory,
5170
5802
  loadTagAnimators,
5171
5803
  materialiseAllInTree,
5172
5804
  materialiseAnimatedUseInstances,
5805
+ materialiseGlyphText,
5806
+ materialiseGlyphTextAlongPath,
5807
+ materialiseGlyphTextHorizontal,
5173
5808
  materialiseInternalLoopsInPropAnim,
5174
5809
  materialiseInternalLoopsInTree,
5175
5810
  materialiseMotionPathInPropAnim,
@@ -5180,6 +5815,7 @@ export {
5180
5815
  renderNode,
5181
5816
  schemaKeys,
5182
5817
  setupAnimationTriggers,
5818
+ shiftAnimatable,
5183
5819
  toRGBA,
5184
5820
  validateNodeEffects,
5185
5821
  visualModelAt