@pixodesk/svg-animator-vue 1.0.15 → 1.0.17

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
@@ -56768,7 +56768,6 @@ ${codeFrame}` : message);
56768
56768
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
56769
56769
  var __hasOwnProp2 = Object.prototype.hasOwnProperty;
56770
56770
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
56771
- var __pow = Math.pow;
56772
56771
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
56773
56772
  var __spreadValues = (a, b) => {
56774
56773
  for (var prop in b || (b = {}))
@@ -56803,12 +56802,15 @@ ${codeFrame}` : message);
56803
56802
  return rec;
56804
56803
  }
56805
56804
  function readAnimatable(raw) {
56806
- if (raw === void 0) return { kind: "absent" };
56805
+ if (raw === void 0) return {
56806
+ kind: "absent"
56807
+ /* Absent */
56808
+ };
56807
56809
  if (Array.isArray(raw)) return { kind: "static", value: raw };
56808
56810
  if (typeof raw === "object") {
56809
56811
  const obj = raw;
56810
56812
  if (obj.keyframes) {
56811
- return { kind: "animated", keyframes: obj.keyframes, autoOrient: obj.autoOrient };
56813
+ return { kind: "animated", keyframes: obj.keyframes, autoOrient: obj.autoOrient, loop: obj.loop };
56812
56814
  }
56813
56815
  if (obj.value !== void 0) return { kind: "static", value: obj.value };
56814
56816
  }
@@ -56896,6 +56898,7 @@ ${codeFrame}` : message);
56896
56898
  if (v.kind === "animated") {
56897
56899
  const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
56898
56900
  if (v.autoOrient) animTr.autoOrient = true;
56901
+ if (v.loop !== void 0) animTr.loop = v.loop;
56899
56902
  return {
56900
56903
  type: "g",
56901
56904
  animate: { transform: animTr },
@@ -56914,9 +56917,11 @@ ${codeFrame}` : message);
56914
56917
  return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
56915
56918
  }
56916
56919
  if (v.kind === "animated") {
56920
+ const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) };
56921
+ if (v.loop !== void 0) animTr.loop = v.loop;
56917
56922
  return {
56918
56923
  type: "g",
56919
- animate: { transform: { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) } },
56924
+ animate: { transform: animTr },
56920
56925
  children: [inner]
56921
56926
  };
56922
56927
  }
@@ -56924,8 +56929,8 @@ ${codeFrame}` : message);
56924
56929
  }
56925
56930
  function identifyContentRefTargets(node, ctx, allocator) {
56926
56931
  var _a, _b, _c;
56927
- if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.ref) == null ? void 0 : _b.type) === "content") {
56928
- const baseId = node.effects.ref.baseId;
56932
+ if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
56933
+ const baseId = node.effects.clone.baseId;
56929
56934
  if (typeof baseId === "string" && baseId && !ctx.contentRefInnerIds.has(baseId)) {
56930
56935
  ctx.contentRefInnerIds.set(baseId, allocator(baseId));
56931
56936
  }
@@ -56950,7 +56955,7 @@ ${codeFrame}` : message);
56950
56955
  return outerWrapper;
56951
56956
  }
56952
56957
  function liftBodyTranslate(node, transformation) {
56953
- var _a;
56958
+ var _a, _b, _c;
56954
56959
  const out = {};
56955
56960
  let didLiftAnimate = false;
56956
56961
  const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
@@ -56973,6 +56978,8 @@ ${codeFrame}` : message);
56973
56978
  });
56974
56979
  const outerAnimTr = { keyframes: outerKfs };
56975
56980
  if (animTr.autoOrient) outerAnimTr.autoOrient = true;
56981
+ const srcLoop = animTr.loop;
56982
+ if (srcLoop !== void 0) outerAnimTr.loop = srcLoop;
56976
56983
  out.animate = { transform: outerAnimTr };
56977
56984
  const innerHasPivotedPart = kfs.some((kf) => {
56978
56985
  const v = kf.value || {};
@@ -56994,13 +57001,16 @@ ${codeFrame}` : message);
56994
57001
  delete node.animate.transform;
56995
57002
  if (node.animate && Object.keys(node.animate).length === 0) delete node.animate;
56996
57003
  } else {
56997
- node.animate.transform = { keyframes: innerKfs };
57004
+ const innerAnimTr = { keyframes: innerKfs };
57005
+ if (srcLoop !== void 0) innerAnimTr.loop = srcLoop;
57006
+ node.animate.transform = innerAnimTr;
56998
57007
  }
56999
57008
  didLiftAnimate = true;
57000
57009
  }
57001
57010
  }
57002
57011
  const transformationHasTranslate = (transformation == null ? void 0 : transformation.translate) !== void 0;
57003
57012
  const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
57013
+ const liftedAnimateIsAutoOriented = didLiftAnimate && needsOriginOnOuter(((_b = node.animate) == null ? void 0 : _b.transform) || void 0) || didLiftAnimate && needsOriginOnOuter(((_c = out.animate) == null ? void 0 : _c.transform) || void 0);
57004
57014
  if (typeof node.transform === "string") {
57005
57015
  const split = splitTransformString(node.transform);
57006
57016
  if (stripBodyTranslateOnly) {
@@ -57009,6 +57019,8 @@ ${codeFrame}` : message);
57009
57019
  else delete node.transform;
57010
57020
  } else if (isPureTranslateBody(node.transform)) {
57011
57021
  delete node.transform;
57022
+ } else if (liftedAnimateIsAutoOriented && isSingleMatrixBody(node.transform)) {
57023
+ delete node.transform;
57012
57024
  }
57013
57025
  } else if (split.translate) {
57014
57026
  out.transform = split.translate;
@@ -57018,6 +57030,17 @@ ${codeFrame}` : message);
57018
57030
  }
57019
57031
  return out;
57020
57032
  }
57033
+ function isSingleMatrixBody(s) {
57034
+ const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
57035
+ let count = 0;
57036
+ let isMatrix = false;
57037
+ let m;
57038
+ while (m = re.exec(s)) {
57039
+ count++;
57040
+ if (m[1] === "matrix") isMatrix = true;
57041
+ }
57042
+ return count === 1 && isMatrix;
57043
+ }
57021
57044
  function isPureTranslateBody(s) {
57022
57045
  const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
57023
57046
  const ops = [];
@@ -57099,280 +57122,6 @@ ${codeFrame}` : message);
57099
57122
  }
57100
57123
  return false;
57101
57124
  }
57102
- function genId(ctx, prefix) {
57103
- return "_lw_" + prefix + "_" + ctx.nextId++;
57104
- }
57105
- function indexById(node, map) {
57106
- var _a;
57107
- if (typeof node.id === "string") map.set(node.id, node);
57108
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
57109
- }
57110
- function spliceDefs(root, defs) {
57111
- if (!defs.length) return;
57112
- const existing = root.children || (root.children = []);
57113
- existing.unshift({ type: "defs", children: defs });
57114
- }
57115
- function clone(value) {
57116
- if (value === null || typeof value !== "object") return value;
57117
- if (Array.isArray(value)) return value.map(clone);
57118
- const out = {};
57119
- for (const k of Object.keys(value)) out[k] = clone(value[k]);
57120
- return out;
57121
- }
57122
- function regenerateIdsInClone(root, ctx) {
57123
- const oldToNew = /* @__PURE__ */ new Map();
57124
- const walkAssign = (n) => {
57125
- var _a;
57126
- if (typeof n.id === "string") {
57127
- const newId = genId(ctx, "retimed");
57128
- oldToNew.set(n.id, newId);
57129
- n.id = newId;
57130
- }
57131
- (_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
57132
- };
57133
- walkAssign(root);
57134
- const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
57135
- const newId = oldToNew.get(oldId);
57136
- return newId ? "url(#" + newId + ")" : m;
57137
- });
57138
- const walkRewrite = (n) => {
57139
- var _a;
57140
- if (typeof n.href === "string" && n.href.startsWith("#")) {
57141
- const newId = oldToNew.get(n.href.slice(1));
57142
- if (newId) n.href = "#" + newId;
57143
- }
57144
- for (const k of Object.keys(n)) {
57145
- if (k === "children" || k === "effects" || k === "meta" || k === "href" || k === "id") continue;
57146
- const v = n[k];
57147
- if (typeof v === "string" && v.indexOf("url(#") !== -1) n[k] = rewriteUrl(v);
57148
- }
57149
- (_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
57150
- };
57151
- walkRewrite(root);
57152
- return oldToNew;
57153
- }
57154
- function applyMaskedByEffect(node, fx, transformation, ctx) {
57155
- if (!fx) return node;
57156
- if (!fx.href) {
57157
- ctx.errors.push("maskedBy.href missing \u2014 cannot build mask");
57158
- return node;
57159
- }
57160
- const maskId = genId(ctx, "mask");
57161
- let content = { type: "use", href: "#" + fx.href };
57162
- content = wrapInverseTransform(content, transformation, ctx);
57163
- const mask = { type: "mask", id: maskId, children: [content] };
57164
- if (fx.maskType) mask.maskType = fx.maskType;
57165
- if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
57166
- if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
57167
- ctx.defs.push(mask);
57168
- node.mask = "url(#" + maskId + ")";
57169
- return node;
57170
- }
57171
- function wrapInverseTransform(inner, fx, ctx) {
57172
- if (!fx) return inner;
57173
- const origin = readStaticOrigin(fx.origin, ctx);
57174
- let n = inner;
57175
- n = wrapInversePart(n, "translate", fx.translate, void 0, ctx);
57176
- n = wrapInversePart(n, "rotate", fx.rotate, origin, ctx);
57177
- n = wrapInversePart(n, "scale", fx.scale, origin, ctx);
57178
- return n;
57179
- }
57180
- function wrapInversePart(inner, part, raw, origin, ctx) {
57181
- if (raw === void 0) return inner;
57182
- const v = readAnimatable(raw);
57183
- if (v.kind === "static") {
57184
- return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
57185
- }
57186
- if (v.kind === "animated") {
57187
- return {
57188
- type: "g",
57189
- animate: { transform: { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin))) } },
57190
- children: [inner]
57191
- };
57192
- }
57193
- return inner;
57194
- }
57195
- function invertPartValue(part, value) {
57196
- if (part === "translate") return [-value[0], -value[1]];
57197
- if (part === "rotate") return -value;
57198
- return [1 / value[0], 1 / value[1]];
57199
- }
57200
- var CONTENT_SUBREF = "content";
57201
- function applyRefAndTransformationEffect(node, ref3, transformation, ctx) {
57202
- if (ref3) {
57203
- const baseId = ref3.baseId;
57204
- if (!baseId) {
57205
- ctx.errors.push("ref: missing baseId");
57206
- } else {
57207
- const targetId = ref3.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
57208
- node.href = "#" + targetId;
57209
- }
57210
- }
57211
- return applyTransformationEffect(node, transformation, ctx);
57212
- }
57213
- function applyRepeaterEffect(node, fx, ctx) {
57214
- var _a, _b;
57215
- if (!fx) return node;
57216
- const copies = (_a = fx.copies) != null ? _a : 1;
57217
- if (copies < 1) {
57218
- ctx.errors.push("repeater.copies invalid: " + fx.copies);
57219
- return node;
57220
- }
57221
- const sharedTransform = node.transform;
57222
- const sharedAnimTransform = (_b = node.animate) == null ? void 0 : _b.transform;
57223
- const base = clone(node);
57224
- delete base.transform;
57225
- if (base.animate) {
57226
- delete base.animate.transform;
57227
- if (Object.keys(base.animate).length === 0) delete base.animate;
57228
- }
57229
- const children = [base];
57230
- for (let i = 1; i < copies; i++) {
57231
- const copy = clone(base);
57232
- copy.transform = { value: perCopyParts(fx, i) };
57233
- children.push(copy);
57234
- }
57235
- const wrapper = { type: "g", children };
57236
- if (sharedTransform !== void 0) wrapper.transform = sharedTransform;
57237
- if (sharedAnimTransform !== void 0) wrapper.animate = { transform: sharedAnimTransform };
57238
- return wrapper;
57239
- }
57240
- function perCopyParts(fx, i) {
57241
- const parts = {};
57242
- if (fx.translate) parts.translate = [fx.translate[0] * i, fx.translate[1] * i];
57243
- if (fx.rotate !== void 0) parts.rotate = fx.rotate * i;
57244
- if (fx.scale) parts.scale = [__pow(fx.scale[0] / 100, i), __pow(fx.scale[1] / 100, i)];
57245
- if (fx.origin) parts.origin = [fx.origin[0] * i, fx.origin[1] * i];
57246
- return parts;
57247
- }
57248
- var RETIME_AS_SYMBOL = true;
57249
- function applyRetimeEffect(node, retime, ctx) {
57250
- var _a, _b, _c, _d;
57251
- if (!retime) return node;
57252
- const baseId = retime.baseId;
57253
- if (!baseId) {
57254
- ctx.errors.push("retime: missing baseId");
57255
- return node;
57256
- }
57257
- const target = ctx.idMap.get(baseId);
57258
- if (!target) {
57259
- ctx.warnings.push('retime: target "' + baseId + '" not found');
57260
- return node;
57261
- }
57262
- const start = (_a = retime.start) != null ? _a : 0;
57263
- const stretch = (_b = retime.stretch) != null ? _b : 1;
57264
- if (RETIME_AS_SYMBOL) {
57265
- const symbolClone = clone(target);
57266
- regenerateIdsInClone(symbolClone, ctx);
57267
- const cloneId = genId(ctx, "retime");
57268
- symbolClone.id = cloneId;
57269
- remapKeyframeTimes(symbolClone, start, stretch);
57270
- ctx.defs.push(symbolClone);
57271
- node.href = "#" + cloneId;
57272
- return node;
57273
- }
57274
- const sourceNodes = target.type === "symbol" ? target.children || [] : [target];
57275
- const content = sourceNodes.map((child) => {
57276
- const c = clone(child);
57277
- regenerateIdsInClone(c, ctx);
57278
- remapKeyframeTimes(c, start, stretch);
57279
- return c;
57280
- });
57281
- const g = __spreadProps(__spreadValues({}, node), { type: "g", children: content });
57282
- delete g.href;
57283
- const x = Number((_c = node.x) != null ? _c : 0), y = Number((_d = node.y) != null ? _d : 0);
57284
- if (x || y) {
57285
- const offset = "translate(" + x + "," + y + ")";
57286
- g.transform = typeof g.transform === "string" ? offset + g.transform : offset;
57287
- delete g.x;
57288
- delete g.y;
57289
- }
57290
- return g;
57291
- }
57292
- function remapKeyframeTimes(node, start, stretch) {
57293
- var _a;
57294
- const remap2 = (kfs) => {
57295
- for (const kf of kfs) if (typeof kf.time === "number") kf.time = start + kf.time * stretch;
57296
- };
57297
- if (node.transform && typeof node.transform === "object" && Array.isArray(node.transform.keyframes)) {
57298
- remap2(node.transform.keyframes);
57299
- }
57300
- if (node.animate && typeof node.animate === "object") {
57301
- for (const prop of Object.keys(node.animate)) {
57302
- const anim = node.animate[prop];
57303
- if (anim && Array.isArray(anim.keyframes)) remap2(anim.keyframes);
57304
- }
57305
- }
57306
- (_a = node.children) == null ? void 0 : _a.forEach((child) => remapKeyframeTimes(child, start, stretch));
57307
- }
57308
- function applyTrimPathEffect(node, trimPath, isCombinedShape) {
57309
- var _a;
57310
- if (!trimPath && !isCombinedShape) return node;
57311
- const d = (_a = node.d) != null ? _a : rectToPathD(node);
57312
- if (d === void 0) return node;
57313
- const g = __spreadProps(__spreadValues({}, node), { type: "g" });
57314
- delete g.d;
57315
- const meta = g.meta = __spreadValues({}, g.meta || {});
57316
- const effects = meta.effects = __spreadValues({}, meta.effects || {});
57317
- if (trimPath) effects.trimPath = trimPath;
57318
- effects.isCombinedShape = true;
57319
- g.children = [{ type: "path", d }];
57320
- return g;
57321
- }
57322
- function rectToPathD(node) {
57323
- var _a, _b, _c, _d;
57324
- if (node.type !== "rect") return void 0;
57325
- const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
57326
- const w = Number((_c = node.width) != null ? _c : 0), h3 = Number((_d = node.height) != null ? _d : 0);
57327
- return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h3) + "L" + x + "," + (y + h3) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
57328
- }
57329
- function applyPlayerEffects(root) {
57330
- const ctx = {
57331
- defs: [],
57332
- warnings: [],
57333
- errors: [],
57334
- idMap: /* @__PURE__ */ new Map(),
57335
- nextId: 0,
57336
- contentRefInnerIds: /* @__PURE__ */ new Map()
57337
- };
57338
- const working = clone(root);
57339
- indexById(working, ctx.idMap);
57340
- identifyContentRefTargets(working, ctx, () => genId(ctx, "inner"));
57341
- const afterPass1 = applyPlayerEffects_exceptRetime(working, ctx);
57342
- const out = applyPlayerEffects_retime(afterPass1, ctx);
57343
- spliceDefs(out, ctx.defs);
57344
- return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
57345
- }
57346
- function applyPlayerEffects_exceptRetime(node, ctx) {
57347
- if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
57348
- const fx = node.effects;
57349
- const originalId = typeof node.id === "string" ? node.id : void 0;
57350
- const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
57351
- if (!fx && !innerIdForContentRef) return node;
57352
- const { transformation, repeater, maskedBy, trimPath, retime, ref: ref3 } = fx != null ? fx : {};
57353
- const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
57354
- if (fx) delete node.effects;
57355
- let n = node;
57356
- n = applyTrimPathEffect(n, trimPath, isCombinedShape);
57357
- n = applyRepeaterEffect(n, repeater, ctx);
57358
- n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
57359
- if (innerIdForContentRef) {
57360
- n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
57361
- } else {
57362
- n = applyRefAndTransformationEffect(n, ref3, transformation, ctx);
57363
- }
57364
- if (retime) node.effects = { retime };
57365
- if (originalId) ctx.idMap.set(originalId, n);
57366
- return n;
57367
- }
57368
- function applyPlayerEffects_retime(node, ctx) {
57369
- var _a;
57370
- if (node.children) node.children = node.children.map((child) => applyPlayerEffects_retime(child, ctx));
57371
- const retime = (_a = node.effects) == null ? void 0 : _a.retime;
57372
- if (!retime) return node;
57373
- delete node.effects;
57374
- return applyRetimeEffect(node, retime, ctx);
57375
- }
57376
57125
  function pathStr(path) {
57377
57126
  if (!path.length) return ".";
57378
57127
  let result = "";
@@ -57815,6 +57564,15 @@ ${codeFrame}` : message);
57815
57564
  };
57816
57565
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
57817
57566
  var PX_ANIM_ATTR_NAME = "_px_animator";
57567
+ var PxAnimatorMode = {
57568
+ auto: "auto",
57569
+ webapi: "webapi",
57570
+ frames: "frames"
57571
+ };
57572
+ var PxAnimatorEngine = {
57573
+ webapi: PxAnimatorMode.webapi,
57574
+ frames: PxAnimatorMode.frames
57575
+ };
57818
57576
  var TEXT_ATTR = "text";
57819
57577
  var TEXT_CONTENT_ATTR = "textContent";
57820
57578
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
@@ -57896,7 +57654,7 @@ ${codeFrame}` : message);
57896
57654
  styles: px.record(px.any()).optional()
57897
57655
  }));
57898
57656
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
57899
- mode: px.enum(["auto", "webapi", "frames"]).optional(),
57657
+ mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.webapi, PxAnimatorMode.frames]).optional(),
57900
57658
  duration: px.number().optional(),
57901
57659
  delay: px.number().optional(),
57902
57660
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
@@ -57935,47 +57693,87 @@ ${codeFrame}` : message);
57935
57693
  autoOrient: px.boolean().optional()
57936
57694
  })
57937
57695
  ]);
57938
- var PxTransformationEffectSchema = px.object({
57696
+ var PxTransformationEffectSchema = implementsInterface()(px.object({
57939
57697
  translate: PxAnimatableVec2Schema.optional(),
57940
57698
  rotate: PxAnimatableNumberSchema.optional(),
57941
57699
  scale: PxAnimatableVec2Schema.optional(),
57942
57700
  skew: PxAnimatableVec2Schema.optional(),
57943
57701
  origin: PxAnimatableVec2Schema.optional()
57944
- });
57945
- var PxRepeaterEffectSchema = px.object({
57702
+ }));
57703
+ var PxRepeaterEffectSchema = implementsInterface()(px.object({
57946
57704
  copies: px.number().optional(),
57947
- translate: px.tuple([px.number(), px.number()]).optional(),
57948
- rotate: px.number().optional(),
57949
- scale: px.tuple([px.number(), px.number()]).optional(),
57950
- // per-copy scale, PERCENT (85 → 0.85)
57951
- origin: px.tuple([px.number(), px.number()]).optional()
57952
- });
57953
- var PxMaskedByEffectSchema = px.object({
57705
+ translate: PxAnimatableVec2Schema.optional(),
57706
+ rotate: PxAnimatableNumberSchema.optional(),
57707
+ scale: PxAnimatableVec2Schema.optional(),
57708
+ origin: PxAnimatableVec2Schema.optional()
57709
+ }));
57710
+ var PxMaskedByEffectSchema = implementsInterface()(px.object({
57954
57711
  href: px.string().optional(),
57955
57712
  maskType: px.string().optional(),
57956
57713
  maskUnits: px.string().optional(),
57957
57714
  maskContentUnits: px.string().optional()
57958
- });
57959
- var PxTrimPathEffectSchema = px.any();
57960
- var PxRetimeEffectSchema = px.object({
57715
+ }));
57716
+ var PxTrimPathEffectSchema = implementsInterface()(px.object({
57717
+ offset: PxAnimatableNumberSchema.optional(),
57718
+ range: PxAnimatableVec2Schema.optional(),
57719
+ trimAllAsOne: px.boolean().optional()
57720
+ }));
57721
+ var PxRetimeEffectSchema = implementsInterface()(px.object({
57961
57722
  baseId: px.string().optional(),
57962
57723
  start: px.number().optional(),
57963
57724
  stretch: px.number().optional(),
57964
57725
  timeCrop: px.tuple([px.number(), px.number()]).optional()
57965
- });
57966
- var PxRefEffectSchema = px.object({
57726
+ }));
57727
+ var PxCloneEffectSchema = implementsInterface()(px.object({
57728
+ type: px.string().optional(),
57967
57729
  baseId: px.string().optional(),
57968
- type: px.string().optional()
57969
- });
57970
- var PxEffectsSchema = px.object({
57730
+ retime: PxRetimeEffectSchema.optional()
57731
+ }));
57732
+ var PxGradientType = {
57733
+ linear: "linear",
57734
+ radial: "radial"
57735
+ };
57736
+ var PxGradientStopSchema = implementsInterface()(px.object({
57737
+ offset: px.number(),
57738
+ color: px.string()
57739
+ }));
57740
+ var PxAnimatableGradientStopsSchema = px.union([
57741
+ px.array(PxGradientStopSchema),
57742
+ px.object({ value: px.array(PxGradientStopSchema) }),
57743
+ px.object({ keyframes: px.array(PxKeyframeSchema) })
57744
+ ]);
57745
+ var PxFillGradientEffectSchema = implementsInterface()(px.object({
57746
+ type: px.enum([PxGradientType.linear, PxGradientType.radial]),
57747
+ p1: px.tuple([px.number(), px.number()]).optional(),
57748
+ p2: px.tuple([px.number(), px.number()]).optional(),
57749
+ c: px.tuple([px.number(), px.number()]).optional(),
57750
+ r: px.number().optional(),
57751
+ fp: px.tuple([px.number(), px.number()]).optional(),
57752
+ stops: PxAnimatableGradientStopsSchema.optional(),
57753
+ gradientUnits: px.string().optional(),
57754
+ spreadMethod: px.string().optional(),
57755
+ gradientTransform: px.string().optional()
57756
+ }));
57757
+ var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
57758
+ var PxTextAlongPathEffectSchema = implementsInterface()(px.object({
57759
+ href: px.string(),
57760
+ lengthAdjust: px.string().optional(),
57761
+ method: px.string().optional(),
57762
+ spacing: px.string().optional(),
57763
+ startOffset: PxAnimatableNumberSchema.optional(),
57764
+ textLength: PxAnimatableNumberSchema.optional()
57765
+ }));
57766
+ var PxEffectsSchema = implementsInterface()(px.object({
57971
57767
  transformation: PxTransformationEffectSchema.optional(),
57972
57768
  repeater: PxRepeaterEffectSchema.optional(),
57973
57769
  maskedBy: PxMaskedByEffectSchema.optional(),
57974
57770
  trimPath: PxTrimPathEffectSchema.optional(),
57975
- retime: PxRetimeEffectSchema.optional(),
57771
+ clone: PxCloneEffectSchema.optional(),
57976
57772
  isCombinedShape: px.boolean().optional(),
57977
- ref: PxRefEffectSchema.optional()
57978
- });
57773
+ fillGradient: PxFillGradientEffectSchema.optional(),
57774
+ strokeGradient: PxStrokeGradientEffectSchema.optional(),
57775
+ textAlongPath: PxTextAlongPathEffectSchema.optional()
57776
+ }));
57979
57777
  function validateNodeEffects(root, opts) {
57980
57778
  const warnings = [];
57981
57779
  const walk = (node, path) => {
@@ -58001,7 +57799,10 @@ ${codeFrame}` : message);
58001
57799
  // Consumed and removed by `applyPlayerEffects` before any other normalisation
58002
57800
  // (see `createAnimatorImpl`), so downstream code never sees it.
58003
57801
  effects: PxEffectsSchema.optional(),
58004
- animate: PxAnimationDefinitionSchema.optional(),
57802
+ // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
57803
+ // string ref / array of refs / inline definition / mixed array; mirrors
57804
+ // `animator.animate` map values and what `processNode` resolves at runtime.
57805
+ animate: PxElementAnimationSchema.optional(),
58005
57806
  style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
58006
57807
  }, PxAttrValueSchema);
58007
57808
  var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBase._shape), {
@@ -58046,1255 +57847,3040 @@ ${codeFrame}` : message);
58046
57847
  if (!animate) return void 0;
58047
57848
  return Object.entries(animate).map(([id, anim]) => ({ id, animate: anim }));
58048
57849
  }
58049
- function bezierToSvgPath(path) {
58050
- var _a, _b, _c, _d;
58051
- const v = path.v;
58052
- const i = path.i;
58053
- const o = path.o;
58054
- const c = path.c;
58055
- if (!v.length) return "";
58056
- const d = [];
58057
- const len = v.length;
58058
- d.push("M" + v[0][0] + "," + v[0][1]);
58059
- for (let idx = 1; idx < len; idx++) {
58060
- const prevV = v[idx - 1];
58061
- const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
58062
- const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
58063
- const currV = v[idx];
58064
- const isLine = prevO[0] === prevV[0] && prevO[1] === prevV[1] && (currI[0] === currV[0] && currI[1] === currV[1]);
58065
- if (isLine) {
58066
- d.push("L" + currV[0] + "," + currV[1]);
58067
- } else {
58068
- d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
58069
- }
58070
- }
58071
- if (c && len > 0) {
58072
- const lastV = v[len - 1];
58073
- const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
58074
- const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
58075
- const firstV = v[0];
58076
- const isLine = lastO[0] === lastV[0] && lastO[1] === lastV[1] && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
58077
- if (!isLine) {
58078
- d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
57850
+ function deepClonePxNode(value) {
57851
+ if (value === null || typeof value !== "object") return value;
57852
+ if (Array.isArray(value)) return value.map(deepClonePxNode);
57853
+ const out = {};
57854
+ for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
57855
+ return out;
57856
+ }
57857
+ function regenerateIdsAndRewriteRefs(root, genId3) {
57858
+ const oldToNew = /* @__PURE__ */ new Map();
57859
+ const walkAssign = (n) => {
57860
+ var _a;
57861
+ if (typeof n.id === "string") {
57862
+ const newId = genId3();
57863
+ oldToNew.set(n.id, newId);
57864
+ n.id = newId;
58079
57865
  }
58080
- d.push("z");
58081
- }
58082
- return d.join("");
57866
+ (_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
57867
+ };
57868
+ walkAssign(root);
57869
+ const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
57870
+ const newId = oldToNew.get(oldId);
57871
+ return newId ? "url(#" + newId + ")" : m;
57872
+ });
57873
+ const walkRewrite = (n) => {
57874
+ var _a;
57875
+ if (typeof n.href === "string" && n.href.startsWith("#")) {
57876
+ const newId = oldToNew.get(n.href.slice(1));
57877
+ if (newId) n.href = "#" + newId;
57878
+ }
57879
+ for (const k of Object.keys(n)) {
57880
+ if (k === "children" || k === "effects" || k === "meta" || k === "animate" || k === "href" || k === "id") continue;
57881
+ const v = n[k];
57882
+ if (typeof v === "string" && v.indexOf("url(#") !== -1) {
57883
+ n[k] = rewriteUrl(v);
57884
+ }
57885
+ }
57886
+ (_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
57887
+ };
57888
+ walkRewrite(root);
57889
+ return oldToNew;
58083
57890
  }
58084
- function interpolateNum(a, b, t) {
58085
- return a + (b - a) * t;
57891
+ function toFiniteNum(v) {
57892
+ const n = typeof v === "number" ? v : typeof v === "string" ? parseFloat(v) : NaN;
57893
+ return Number.isFinite(n) ? n : 0;
58086
57894
  }
58087
- function interpolateVec(a, b, t) {
58088
- const res = [];
58089
- const count = Math.max(a.length, b.length);
58090
- for (let i = 0; i < count; i++) {
58091
- res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
57895
+ function applyUseOffsetToG(gNode) {
57896
+ var _a;
57897
+ const x = toFiniteNum(gNode.x);
57898
+ const y = toFiniteNum(gNode.y);
57899
+ delete gNode.x;
57900
+ delete gNode.y;
57901
+ if (!x && !y) return gNode;
57902
+ const offset = "translate(" + x + "," + y + ")";
57903
+ const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
57904
+ if (carriesTransform) {
57905
+ const inner = { type: "g", transform: offset, children: (_a = gNode.children) != null ? _a : [] };
57906
+ gNode.children = [inner];
57907
+ } else {
57908
+ gNode.transform = offset;
58092
57909
  }
58093
- return res;
57910
+ return gNode;
58094
57911
  }
58095
- function interpolateColor(a, b, t) {
58096
- return [
58097
- interpolateNum(a[0] || 0, b[0] || 0, t),
58098
- interpolateNum(a[1] || 0, b[1] || 0, t),
58099
- interpolateNum(a[2] || 0, b[2] || 0, t),
58100
- interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
58101
- ];
57912
+ function genId(ctx, prefix) {
57913
+ return "_lw_" + prefix + "_" + ctx.nextId++;
58102
57914
  }
58103
- function interpolateBeziers(paths1, paths2, progress) {
58104
- const count = Math.max(paths1.length, paths2.length);
58105
- const res = [];
58106
- for (let i = 0; i < count; i++) {
58107
- res.push(interpolateBezier(paths1[i], paths2[i], progress));
58108
- }
58109
- return res;
57915
+ function stripHash(href) {
57916
+ return typeof href === "string" ? href.replace(/^#/, "") : void 0;
58110
57917
  }
58111
- function interpolateBezier(path1, path2, progress) {
58112
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
58113
- if (!path1 || !path2) return path1 || path2 || { v: [] };
58114
- const t = Math.min(Math.max(progress, 0), 1);
58115
- const len = Math.min(path1.v.length, path2.v.length);
58116
- const v = [];
58117
- const i = [];
58118
- const o = [];
58119
- for (let idx = 0; idx < len; idx++) {
58120
- const v1 = path1.v[idx];
58121
- const v2 = path2.v[idx];
58122
- v.push(interpolateVec(v1, v2, t));
58123
- const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
58124
- const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
58125
- i.push(interpolateVec(i1, i2, t));
58126
- const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
58127
- const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
58128
- o.push(interpolateVec(o1, o2, t));
58129
- }
58130
- return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
57918
+ function indexById(node, map) {
57919
+ var _a;
57920
+ if (typeof node.id === "string") map.set(node.id, node);
57921
+ (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
58131
57922
  }
58132
- function remap(value, inMin, inMax, outMin, outMax) {
58133
- if (inMax === inMin) return outMin;
58134
- const t = (value - inMin) / (inMax - inMin);
58135
- return outMin + t * (outMax - outMin);
57923
+ function spliceDefs(root, defs) {
57924
+ if (!defs.length) return;
57925
+ const existing = root.children || (root.children = []);
57926
+ existing.unshift({ type: "defs", children: defs });
58136
57927
  }
58137
- function solveCubicBezierX(p1x, p2x, x) {
58138
- if (x <= 0) return 0;
58139
- if (x >= 1) return 1;
58140
- const cx = 3 * p1x;
58141
- const bx = 3 * (p2x - p1x) - cx;
58142
- const ax = 1 - cx - bx;
58143
- function sampleX(t) {
58144
- return ((ax * t + bx) * t + cx) * t;
58145
- }
58146
- function sampleDX(t) {
58147
- return (3 * ax * t + 2 * bx) * t + cx;
57928
+ var clone = deepClonePxNode;
57929
+ function regenerateIdsInClone(root, ctx) {
57930
+ return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
57931
+ }
57932
+ function applyFillGradientEffect(node, fx, ctx) {
57933
+ return applyGradient(node, fx, ctx, "fill");
57934
+ }
57935
+ function applyStrokeGradientEffect(node, fx, ctx) {
57936
+ return applyGradient(node, fx, ctx, "stroke");
57937
+ }
57938
+ function applyGradient(node, fx, ctx, attr) {
57939
+ if (!fx) return node;
57940
+ const id = genId(ctx, "grad");
57941
+ const def = synthesiseGradientDef(fx, id, ctx);
57942
+ ctx.defs.push(def);
57943
+ node[attr] = "url(#" + id + ")";
57944
+ return node;
57945
+ }
57946
+ function synthesiseGradientDef(fx, id, ctx) {
57947
+ const out = {
57948
+ type: fx.type === PxGradientType.radial ? "radialGradient" : "linearGradient",
57949
+ id
57950
+ };
57951
+ if (fx.type === PxGradientType.linear) {
57952
+ if (fx.p1) {
57953
+ out.x1 = String(fx.p1[0]);
57954
+ out.y1 = String(fx.p1[1]);
57955
+ }
57956
+ if (fx.p2) {
57957
+ out.x2 = String(fx.p2[0]);
57958
+ out.y2 = String(fx.p2[1]);
57959
+ }
57960
+ } else {
57961
+ if (fx.c) {
57962
+ out.cx = String(fx.c[0]);
57963
+ out.cy = String(fx.c[1]);
57964
+ }
57965
+ if (fx.r !== void 0) out.r = String(fx.r);
57966
+ if (fx.fp) {
57967
+ out.fx = String(fx.fp[0]);
57968
+ out.fy = String(fx.fp[1]);
57969
+ }
58148
57970
  }
58149
- let t2 = x;
58150
- let t0 = 0;
58151
- let t1 = 1;
58152
- for (let i = 0; i < 8; i++) {
58153
- const x2 = sampleX(t2) - x;
58154
- if (Math.abs(x2) < 1e-6) return t2;
58155
- const d2 = sampleDX(t2);
58156
- if (Math.abs(d2) < 1e-6) break;
58157
- t2 -= x2 / d2;
57971
+ if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
57972
+ if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
57973
+ if (fx.gradientTransform) out.gradientTransform = fx.gradientTransform;
57974
+ out.children = buildStopChildren(fx.stops, ctx);
57975
+ return out;
57976
+ }
57977
+ function buildStopChildren(stops, ctx) {
57978
+ var _a, _b, _c, _d;
57979
+ if (!stops) return [];
57980
+ if (Array.isArray(stops)) return stops.map(staticStopNode);
57981
+ if (typeof stops === "object" && Array.isArray(stops.value)) {
57982
+ return stops.value.map(staticStopNode);
58158
57983
  }
58159
- t2 = x;
58160
- while (t0 < t1) {
58161
- const x2 = sampleX(t2);
58162
- if (Math.abs(x2 - x) < 1e-6) return t2;
58163
- if (x > x2) t0 = t2;
58164
- else t1 = t2;
58165
- t2 = (t1 + t0) / 2;
57984
+ const animBlock = stops;
57985
+ const kfs = animBlock.keyframes;
57986
+ if (!Array.isArray(kfs) || !kfs.length) return [];
57987
+ const loopFromSource = animBlock.loop;
57988
+ let stopCount = 0;
57989
+ for (const kf of kfs) {
57990
+ const v = (_a = kf.value) != null ? _a : kf.v;
57991
+ if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
58166
57992
  }
58167
- return t2;
58168
- }
58169
- function cubicBezier(easing) {
58170
- const [p1x, p1y, p2x, p2y] = easing;
58171
- const cy = 3 * p1y;
58172
- const by = 3 * (p2y - p1y) - cy;
58173
- const ay = 1 - cy - by;
58174
- function sampleCurveY(t) {
58175
- return ((ay * t + by) * t + cy) * t;
57993
+ if (!stopCount) return [];
57994
+ const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
57995
+ const baselineStops = [];
57996
+ for (let i = 0; i < stopCount; i++) {
57997
+ const s = (_d = (_c = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _c : prevDefinedStop(kfs, 0, i)) != null ? _d : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
57998
+ baselineStops.push({ offset: s.offset, color: s.color });
58176
57999
  }
58177
- return function(x) {
58178
- return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
58179
- };
58000
+ return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
58180
58001
  }
58181
- function lerp2(a, b, t) {
58182
- return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
58183
- }
58184
- function subdivideCubicBezier(p0, p1, p2, p3, t) {
58185
- const q0 = lerp2(p0, p1, t);
58186
- const q1 = lerp2(p1, p2, t);
58187
- const q2 = lerp2(p2, p3, t);
58188
- const r0 = lerp2(q0, q1, t);
58189
- const r1 = lerp2(q1, q2, t);
58190
- const s = lerp2(r0, r1, t);
58002
+ function staticStopNode(s) {
58191
58003
  return {
58192
- left: [p0, q0, r0, s],
58193
- right: [s, r1, q2, p3]
58004
+ type: "stop",
58005
+ offset: formatOffset(s.offset),
58006
+ stopColor: s.color
58194
58007
  };
58195
58008
  }
58196
- function splitEasing(easing, xFraction) {
58197
- if (!easing) return { left: void 0, right: void 0 };
58198
- if (xFraction <= 0) return { left: void 0, right: easing };
58199
- if (xFraction >= 1) return { left: easing, right: void 0 };
58200
- const [x1, y1, x2, y2] = easing;
58201
- const t = solveCubicBezierX(x1, x2, xFraction);
58202
- const p0 = [0, 0];
58203
- const p1 = [x1, y1];
58204
- const p2 = [x2, y2];
58205
- const p3 = [1, 1];
58206
- const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
58207
- const sx = left[3][0];
58208
- const sy = left[3][1];
58209
- let leftEasing;
58210
- if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
58211
- leftEasing = [
58212
- left[1][0] / sx,
58213
- left[1][1] / sy,
58214
- left[2][0] / sx,
58215
- left[2][1] / sy
58216
- ];
58009
+ function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
58010
+ var _a, _b, _c, _d, _e;
58011
+ const colorKfs = [];
58012
+ const offsetKfs = [];
58013
+ let offsetVaries = false;
58014
+ for (const kf of kfs) {
58015
+ const t = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
58016
+ const arr = (_c = kf.value) != null ? _c : kf.v;
58017
+ const sliced = (_d = arr == null ? void 0 : arr[stopIdx]) != null ? _d : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
58018
+ if (!sliced) continue;
58019
+ const easing = (_e = kf.easing) != null ? _e : kf.e;
58020
+ const colorOut = { time: t, value: sliced.color };
58021
+ if (easing !== void 0) colorOut.easing = easing;
58022
+ colorKfs.push(colorOut);
58023
+ const offsetOut = { time: t, value: sliced.offset };
58024
+ if (easing !== void 0) offsetOut.easing = easing;
58025
+ offsetKfs.push(offsetOut);
58026
+ if (sliced.offset !== baseline.offset) offsetVaries = true;
58217
58027
  }
58218
- let rightEasing;
58219
- const rx = 1 - sx;
58220
- const ry = 1 - sy;
58221
- if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
58222
- rightEasing = [
58223
- (right[1][0] - sx) / rx,
58224
- (right[1][1] - sy) / ry,
58225
- (right[2][0] - sx) / rx,
58226
- (right[2][1] - sy) / ry
58227
- ];
58028
+ const stop = {
58029
+ type: "stop",
58030
+ offset: formatOffset(baseline.offset),
58031
+ stopColor: baseline.color
58032
+ };
58033
+ const animate = {};
58034
+ if (colorKfs.length) {
58035
+ animate.stopColor = { keyframes: colorKfs };
58036
+ if (loop !== void 0) animate.stopColor.loop = loop;
58228
58037
  }
58229
- return { left: leftEasing, right: rightEasing };
58230
- }
58231
- function reverseEasing(easing) {
58232
- if (!easing) return void 0;
58233
- return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
58038
+ if (offsetVaries && offsetKfs.length) {
58039
+ animate.offset = { keyframes: offsetKfs };
58040
+ if (loop !== void 0) animate.offset.loop = loop;
58041
+ }
58042
+ if (Object.keys(animate).length) stop.animate = animate;
58043
+ return stop;
58234
58044
  }
58235
- function toRGBA(color) {
58236
- const r = Math.round(color[0] * 255);
58237
- const g = Math.round(color[1] * 255);
58238
- const b = Math.round(color[2] * 255);
58239
- return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
58045
+ function prevDefinedStop(kfs, fromIdx, stopIdx) {
58046
+ var _a, _b;
58047
+ for (let i = fromIdx; i >= 0; i--) {
58048
+ const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
58049
+ if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
58050
+ }
58051
+ for (let i = fromIdx + 1; i < kfs.length; i++) {
58052
+ const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
58053
+ if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
58054
+ }
58055
+ return void 0;
58240
58056
  }
58241
- function parseRgba(s) {
58242
- var _a;
58243
- const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
58244
- if (!inner) throw new Error("Invalid rgb/rgba format");
58245
- const parts = inner.split(",").map((v) => +v.trim());
58246
- return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
58057
+ function formatOffset(o) {
58058
+ const pct = Math.round(o * 1e3) / 10;
58059
+ return pct + "%";
58247
58060
  }
58248
- function parseHex(s) {
58249
- const hex = s.slice(1);
58250
- const isShort = hex.length <= 4;
58251
- const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
58252
- const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
58253
- const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
58254
- const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
58255
- const result = [
58256
- parseInt(r, 16) / 255,
58257
- parseInt(g, 16) / 255,
58258
- parseInt(b, 16) / 255
58259
- ];
58260
- if (a !== null) {
58261
- result.push(parseInt(a, 16) / 255);
58061
+ function applyMaskedByEffect(node, fx, transformation, ctx) {
58062
+ if (!fx) return node;
58063
+ if (!fx.href) {
58064
+ ctx.errors.push("maskedBy.href missing \u2014 cannot build mask");
58065
+ return node;
58262
58066
  }
58263
- return result;
58264
- }
58265
- function parseColor(s) {
58266
- if (!s) return void 0;
58267
- if (Array.isArray(s)) return s;
58268
- if (typeof s !== "string") return void 0;
58269
- if (s.startsWith("#")) {
58270
- return parseHex(s);
58271
- } else if (s.startsWith("rgb")) {
58272
- return parseRgba(s);
58067
+ const maskId = genId(ctx, "mask");
58068
+ let content = { type: "use", href: "#" + fx.href };
58069
+ if (transformation) {
58070
+ content = wrapInverseTransform(content, transformation, ctx);
58071
+ } else if (hasAnimateTransform(node)) {
58072
+ content = wrapInverseAnimatedBodyTransform(content, node, ctx);
58273
58073
  } else {
58274
- console.warn("Unsupported color format: " + s);
58074
+ const bodyStatic = readTransformationFromBody(node);
58075
+ if (bodyStatic) content = wrapInverseTransform(content, bodyStatic, ctx);
58275
58076
  }
58276
- return void 0;
58277
- }
58278
- var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
58279
- var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
58280
- var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
58281
- function composeTransformParts(parts, opts) {
58282
- var _a;
58283
- if (!parts) return "";
58284
- const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
58285
- const segs = [];
58286
- const t = parts.translate;
58287
- const o = parts.origin;
58288
- const r = parts.rotate;
58289
- const s = parts.scale;
58290
- const tu = withUnits ? "px" : "";
58291
- const ru = withUnits ? "deg" : "";
58292
- if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
58293
- if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
58294
- if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
58295
- if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
58296
- if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
58297
- return segs.join("");
58298
- }
58299
- var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
58300
- var DEFAULT_DURATION_MS = 1e3;
58301
- function kebabToCamelCaseWord(kebab) {
58302
- return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
58303
- }
58304
- function isCamelCaseWord(word) {
58305
- return !word.includes("-") && /[a-z][A-Z]/.test(word);
58077
+ const includeTargetOwn = transformation === void 0 && !nodeHasBodyTransform(node);
58078
+ content = wrapAncestorChainCompensation(content, node, fx.href, ctx, includeTargetOwn);
58079
+ const mask = { type: "mask", id: maskId, children: [content] };
58080
+ if (fx.maskType) mask.maskType = fx.maskType;
58081
+ if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
58082
+ if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
58083
+ ctx.defs.push(mask);
58084
+ node.mask = "url(#" + maskId + ")";
58085
+ return node;
58306
58086
  }
58307
- var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
58308
- // Transform/positioning
58309
- "viewBox",
58310
- "preserveAspectRatio",
58311
- // Gradient
58312
- "gradientUnits",
58313
- "gradientTransform",
58314
- "spreadMethod",
58315
- // Pattern
58316
- "patternUnits",
58317
- "patternContentUnits",
58318
- "patternTransform",
58319
- // Clipping/masking
58320
- "clipPathUnits",
58321
- "maskUnits",
58322
- "maskContentUnits",
58323
- // Text
58324
- "textLength",
58325
- "lengthAdjust",
58326
- "startOffset",
58327
- // Filter
58328
- "filterUnits",
58329
- "primitiveUnits",
58330
- "stdDeviation",
58331
- "baseFrequency",
58332
- "numOctaves",
58333
- "surfaceScale",
58334
- "diffuseConstant",
58335
- "specularConstant",
58336
- "specularExponent",
58337
- "kernelMatrix",
58338
- "kernelUnitLength",
58339
- "edgeMode",
58340
- "preserveAlpha",
58341
- "targetX",
58342
- "targetY"
58343
- // // Animation
58344
- // 'attributeName',
58345
- // 'attributeType',
58346
- // 'calcMode',
58347
- // 'keyTimes',
58348
- // 'keySplines',
58349
- // 'repeatCount',
58350
- // 'repeatDur'
58351
- ]);
58352
- function camelCaseToKebabWordIfNeeded(camel) {
58353
- return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
58087
+ function wrapInverseTransform(inner, fx, ctx) {
58088
+ if (!fx) return inner;
58089
+ const origin = readStaticOrigin(fx.origin, ctx);
58090
+ let n = inner;
58091
+ n = wrapInversePart(n, "translate", fx.translate, void 0, ctx);
58092
+ n = wrapInversePart(n, "rotate", fx.rotate, origin, ctx);
58093
+ n = wrapInversePart(n, "scale", fx.scale, origin, ctx);
58094
+ return n;
58354
58095
  }
58355
- function clamp(value, min, max) {
58356
- return Math.max(min, Math.min(value, max));
58096
+ function wrapInversePart(inner, part, raw, origin, ctx) {
58097
+ if (raw === void 0) return inner;
58098
+ const normalisedRaw = part === "scale" && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
58099
+ const v = readAnimatable(normalisedRaw);
58100
+ if (v.kind === "static") {
58101
+ return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
58102
+ }
58103
+ if (v.kind === "animated") {
58104
+ const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin))) };
58105
+ if (v.loop !== void 0) animTr.loop = v.loop;
58106
+ return {
58107
+ type: "g",
58108
+ animate: { transform: animTr },
58109
+ children: [inner]
58110
+ };
58111
+ }
58112
+ return inner;
58357
58113
  }
58358
- function bezier2D_pointAt(P0, P1, P2, P3, t) {
58359
- if (t <= 0) return [P0[0], P0[1]];
58360
- if (t >= 1) return [P3[0], P3[1]];
58361
- const u = 1 - t;
58362
- const u2 = u * u;
58363
- const u3 = u2 * u;
58364
- const t2 = t * t;
58365
- const t3 = t2 * t;
58366
- const w0 = u3;
58367
- const w1 = 3 * t * u2;
58368
- const w2 = 3 * t2 * u;
58369
- const w3 = t3;
58370
- return [
58371
- w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
58372
- w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
58373
- ];
58114
+ function invertPartValue(part, value) {
58115
+ if (part === "translate") return [-value[0], -value[1]];
58116
+ if (part === "rotate") return -value;
58117
+ return [1 / value[0], 1 / value[1]];
58374
58118
  }
58375
- var BEZIER_T_NUDGE = 1e-4;
58376
- function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
58377
- const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
58378
- if (result[0] === 0 && result[1] === 0) {
58379
- const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
58380
- return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
58119
+ function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
58120
+ var _a;
58121
+ const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
58122
+ const animTr = animate == null ? void 0 : animate.transform;
58123
+ const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
58124
+ if (!kfs || !kfs.length) return inner;
58125
+ const translateKfs = [];
58126
+ const rotateKfs = [];
58127
+ const scaleKfs = [];
58128
+ for (const kf of kfs) {
58129
+ const v = ((_a = kf.value) != null ? _a : kf.v) || {};
58130
+ const baseKf = keyframeWith(kf, void 0);
58131
+ if (Array.isArray(v.translate)) {
58132
+ translateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
58133
+ }
58134
+ if (typeof v.rotate === "number") {
58135
+ const rec = { rotate: -v.rotate };
58136
+ if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
58137
+ rotateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
58138
+ }
58139
+ if (Array.isArray(v.scale)) {
58140
+ const rec = { scale: [1 / v.scale[0], 1 / v.scale[1]] };
58141
+ if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
58142
+ scaleKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
58143
+ }
58381
58144
  }
58382
- return result;
58145
+ const srcLoop = animTr == null ? void 0 : animTr.loop;
58146
+ const withLoop = (kfs2) => {
58147
+ const block = { keyframes: kfs2 };
58148
+ if (srcLoop !== void 0) block.loop = srcLoop;
58149
+ return block;
58150
+ };
58151
+ let n = inner;
58152
+ if (translateKfs.length) n = { type: "g", animate: { transform: withLoop(translateKfs) }, children: [n] };
58153
+ if (rotateKfs.length) n = { type: "g", animate: { transform: withLoop(rotateKfs) }, children: [n] };
58154
+ if (scaleKfs.length) n = { type: "g", animate: { transform: withLoop(scaleKfs) }, children: [n] };
58155
+ return n;
58383
58156
  }
58384
- function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
58385
- const u = 1 - t;
58386
- const a = 3 * u * u;
58387
- const b = 6 * t * u;
58388
- const c = 3 * t * t;
58389
- return [
58390
- a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
58391
- a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
58392
- ];
58157
+ function nodeHasBodyTransform(node) {
58158
+ if (typeof node.transform === "string") return true;
58159
+ if (node.transform && typeof node.transform === "object") return true;
58160
+ return hasAnimateTransform(node);
58393
58161
  }
58394
- function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
58395
- const n = steps + 1;
58396
- const ts = new Float64Array(n);
58397
- const ds = new Float64Array(n);
58398
- let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
58399
- ts[0] = 0;
58400
- ds[0] = 0;
58401
- let cum = 0;
58402
- for (let i = 1; i < n; i++) {
58403
- const t = i / steps;
58404
- const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
58405
- const dx = cur[0] - prev[0];
58406
- const dy = cur[1] - prev[1];
58407
- cum += Math.sqrt(dx * dx + dy * dy);
58408
- ts[i] = t;
58409
- ds[i] = cum;
58410
- prev = cur;
58411
- }
58412
- return { ts, ds };
58162
+ function hasAnimateTransform(node) {
58163
+ const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
58164
+ return !!(animate && animate.transform);
58413
58165
  }
58414
- function bezier2D_tForDistance(lut, distance) {
58415
- const { ts, ds } = lut;
58416
- const last = ds.length - 1;
58417
- if (distance <= 0) return ts[0];
58418
- if (distance >= ds[last]) return ts[last];
58419
- let lo = 1;
58420
- let hi = last;
58421
- while (lo < hi) {
58422
- const mid = lo + hi >>> 1;
58423
- if (ds[mid] < distance) lo = mid + 1;
58424
- else hi = mid;
58166
+ function readTransformationFromBody(node) {
58167
+ if (typeof node.transform === "string") {
58168
+ const parts = parseTransformStringToParts(node.transform);
58169
+ if (!parts) return void 0;
58170
+ const out = {};
58171
+ if (parts.translate) out.translate = parts.translate;
58172
+ if (parts.rotate !== void 0) out.rotate = parts.rotate;
58173
+ if (parts.scale) out.scale = { value: parts.scale };
58174
+ if (parts.origin) out.origin = parts.origin;
58175
+ return Object.keys(out).length ? out : void 0;
58425
58176
  }
58426
- const dPrev = ds[hi - 1];
58427
- const dCur = ds[hi];
58428
- const span = dCur - dPrev;
58429
- const frac = span > 0 ? (distance - dPrev) / span : 0;
58430
- return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
58177
+ return void 0;
58431
58178
  }
58432
- var SVG_NS = "http://www.w3.org/2000/svg";
58433
- var ALLOWED_SVG_TAGS_LOWER_CASE = new Set([
58434
- "svg",
58435
- "g",
58436
- "path",
58437
- "circle",
58438
- "ellipse",
58439
- "rect",
58440
- "line",
58441
- "polyline",
58442
- "polygon",
58443
- "text",
58444
- "tspan",
58445
- "textPath",
58446
- "defs",
58447
- "clipPath",
58448
- "mask",
58449
- "pattern",
58450
- "linearGradient",
58451
- "radialGradient",
58452
- "stop",
58453
- "use",
58454
- "symbol",
58455
- "marker",
58456
- "filter",
58457
- "feGaussianBlur",
58458
- "feOffset",
58459
- "feBlend",
58460
- "feColorMatrix",
58461
- "feMerge",
58462
- "feMergeNode"
58463
- ].map((tagName) => tagName.toLowerCase()));
58464
- var ALLOWED_RESOURCE_ATTRIBUTES = [
58465
- "href",
58466
- // <use>
58467
- "src",
58468
- // <image>
58469
- "filter",
58470
- // url(#filterId)
58471
- "clipPath",
58472
- // clip-path="url(#clipPathId)"
58473
- "mask",
58474
- // url(#maskId)
58475
- "markerStart",
58476
- // marker-start="url(#markerId)"
58477
- "markerMid",
58478
- // marker-mid="url(#markerId)"
58479
- "markerEnd"
58480
- // marker-end="url(#markerId)"
58481
- // 'fill', // url(#gradientId) or url(#patternId)
58482
- // 'stroke', // url(#gradientId) or url(#patternId)
58483
- // Don't allow 'cursor', can use external SVG, // url(cursor.svg)
58484
- ];
58485
- var ALLOWED_RESOURCE_ATTRIBUTES_SET = new Set(ALLOWED_RESOURCE_ATTRIBUTES);
58486
- var ALLOWED_ATTRIBUTES = [
58487
- "href",
58488
- "src",
58489
- // Presentation
58490
- "fill",
58491
- "fillOpacity",
58492
- "fillRule",
58493
- "stroke",
58494
- "strokeWidth",
58495
- "strokeOpacity",
58496
- "strokeLinecap",
58497
- "strokeLinejoin",
58498
- "strokeMiterlimit",
58499
- "strokeDasharray",
58500
- "strokeDashoffset",
58501
- "opacity",
58502
- "transform",
58503
- // Geometry
58504
- "x",
58505
- "y",
58506
- "cx",
58507
- "cy",
58508
- "r",
58509
- "rx",
58510
- "ry",
58511
- "width",
58512
- "height",
58513
- "d",
58514
- "x1",
58515
- "y1",
58516
- "x2",
58517
- "y2",
58518
- "points",
58519
- "dx",
58520
- "dy",
58521
- // Font
58522
- "fontSize",
58523
- "fontFamily",
58524
- "fontWeight",
58525
- "fontStyle",
58526
- // Text
58527
- "textAnchor",
58528
- "letterSpacing",
58529
- "wordSpacing",
58530
- "space",
58531
- "xml:space",
58532
- "textDecoration",
58533
- "textTransform",
58534
- "whiteSpace",
58535
- "white-space",
58536
- "dominantBaseline",
58537
- "alignmentBaseline",
58538
- "rotate",
58539
- // per-glyph rotation array, currently not supported
58540
- // Structure
58541
- "id",
58542
- "class",
58543
- "viewBox",
58544
- "preserveAspectRatio",
58545
- // Gradient/Pattern
58546
- "offset",
58547
- "stopColor",
58548
- "stopOpacity",
58549
- "gradientTransform",
58550
- // Clippath/Mask
58551
- "clipPath",
58552
- "mask",
58553
- // Motion path
58554
- "offsetPath",
58555
- "offsetDistance",
58556
- "offsetRotate",
58557
- "offsetAnchor",
58558
- "offsetPosition",
58559
- // Text path
58560
- "startOffset",
58561
- "textLength",
58562
- "lengthAdjust",
58563
- // Filter
58564
- "filter",
58565
- "stdDeviation",
58566
- "in",
58567
- "in2",
58568
- "result",
58569
- "mode",
58570
- ...ALLOWED_RESOURCE_ATTRIBUTES
58571
- ];
58572
- var ALLOWED_ATTRIBUTES_LOW_SET = new Set(ALLOWED_ATTRIBUTES.map((str) => str.toLowerCase()));
58573
- function sanitiseAttributeValue(name, value) {
58574
- const nameLower = name.toLowerCase();
58575
- if (!ALLOWED_ATTRIBUTES_LOW_SET.has(nameLower)) {
58576
- console.warn("Attribute not in whitelist: ", nameLower);
58577
- return void 0;
58179
+ function parseTransformStringToParts(s) {
58180
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
58181
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
58182
+ let m;
58183
+ const ops = [];
58184
+ while ((m = re.exec(s)) !== null) {
58185
+ const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
58186
+ ops.push({ name: m[1], args });
58578
58187
  }
58579
- if (nameLower === "fill" || nameLower === "stroke" || nameLower === "stopColor") {
58580
- const str = String(value);
58581
- if (str.includes("url(") && !/^url\(#[^)]+\)$/.test(str)) {
58582
- console.warn('Attribute "' + nameLower + '" blocked: url() references must be internal url(#id), got:', value);
58583
- return void 0;
58188
+ if (!ops.length) return void 0;
58189
+ const last = ops[ops.length - 1];
58190
+ if (last.name === "translate") {
58191
+ for (let j = ops.length - 2; j >= 0; j--) {
58192
+ const cand = ops[j];
58193
+ if (cand.name !== "translate") continue;
58194
+ const ox = (_a = cand.args[0]) != null ? _a : 0;
58195
+ const oy = (_b = cand.args[1]) != null ? _b : 0;
58196
+ const lx = (_c = last.args[0]) != null ? _c : 0;
58197
+ const ly = (_d = last.args[1]) != null ? _d : 0;
58198
+ if (lx !== -ox || ly !== -oy) continue;
58199
+ const out2 = {};
58200
+ out2.origin = [ox, oy];
58201
+ for (let k = 0; k < j; k++) {
58202
+ if (ops[k].name === "translate") {
58203
+ const tx = (_e = ops[k].args[0]) != null ? _e : 0;
58204
+ const ty = (_f = ops[k].args[1]) != null ? _f : 0;
58205
+ out2.translate = out2.translate ? [out2.translate[0] + tx, out2.translate[1] + ty] : [tx, ty];
58206
+ }
58207
+ }
58208
+ for (let k = j + 1; k < ops.length - 1; k++) {
58209
+ const op = ops[k];
58210
+ if (op.name === "rotate") out2.rotate = ((_g = out2.rotate) != null ? _g : 0) + ((_h = op.args[0]) != null ? _h : 0);
58211
+ else if (op.name === "scale") {
58212
+ const sx = (_i = op.args[0]) != null ? _i : 1;
58213
+ const sy = op.args.length > 1 ? op.args[1] : sx;
58214
+ out2.scale = out2.scale ? [out2.scale[0] * sx, out2.scale[1] * sy] : [sx, sy];
58215
+ }
58216
+ }
58217
+ return out2;
58584
58218
  }
58585
- return value;
58586
58219
  }
58587
- if (ALLOWED_RESOURCE_ATTRIBUTES_SET.has(nameLower)) {
58588
- const str = String(value);
58589
- if (str.startsWith("#")) {
58590
- return value;
58591
- }
58592
- if (/^url\(#[^)]+\)$/.test(str)) {
58593
- return value;
58220
+ let translate;
58221
+ let rotate;
58222
+ let scale;
58223
+ for (const op of ops) {
58224
+ if (op.name === "translate") {
58225
+ const dx = (_j = op.args[0]) != null ? _j : 0;
58226
+ const dy = (_k = op.args[1]) != null ? _k : 0;
58227
+ translate = translate ? [translate[0] + dx, translate[1] + dy] : [dx, dy];
58228
+ } else if (op.name === "rotate") {
58229
+ rotate = (rotate != null ? rotate : 0) + ((_l = op.args[0]) != null ? _l : 0);
58230
+ } else if (op.name === "scale") {
58231
+ const sx = (_m = op.args[0]) != null ? _m : 1;
58232
+ const sy = op.args.length > 1 ? op.args[1] : sx;
58233
+ scale = scale ? [scale[0] * sx, scale[1] * sy] : [sx, sy];
58594
58234
  }
58595
- return void 0;
58596
58235
  }
58597
- return value;
58236
+ const out = {};
58237
+ if (translate) out.translate = translate;
58238
+ if (rotate !== void 0) out.rotate = rotate;
58239
+ if (scale) out.scale = scale;
58240
+ return Object.keys(out).length ? out : void 0;
58598
58241
  }
58599
- function createElement(tagName, normalisedProps, style, children, textContent) {
58600
- if (!ALLOWED_SVG_TAGS_LOWER_CASE.has(tagName.toLowerCase())) {
58601
- console.warn("Attribute not in whitelist: ", tagName);
58602
- return null;
58242
+ function wrapAncestorChainCompensation(inner, maskedNode, sourceId, ctx, includeTargetOwn) {
58243
+ const sourceNode = ctx.idMap.get(sourceId);
58244
+ const targetAncestors = ctx.maskAncestorChains.get(maskedNode) || [];
58245
+ const targetOwn = includeTargetOwn ? extractTranslateOnly(maskedNode, ctx) : void 0;
58246
+ const targetChain = targetOwn ? [...targetAncestors, targetOwn] : targetAncestors;
58247
+ const sourceChain = sourceNode && ctx.maskAncestorChains.get(sourceNode) || [];
58248
+ if (!targetChain.length && !sourceChain.length) return inner;
58249
+ const times = /* @__PURE__ */ new Set();
58250
+ for (const a of targetChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
58251
+ for (const a of sourceChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
58252
+ const animated = times.size > 0;
58253
+ if (!animated) {
58254
+ const tgt = sumStaticTranslate(targetChain);
58255
+ const src = sumStaticTranslate(sourceChain);
58256
+ const dx = src[0] - tgt[0];
58257
+ const dy = src[1] - tgt[1];
58258
+ if (dx === 0 && dy === 0) return inner;
58259
+ return { type: "g", transform: "translate(" + dx + "," + dy + ")", children: [inner] };
58603
58260
  }
58604
- const element = document.createElementNS(SVG_NS, tagName);
58605
- for (const propName in normalisedProps) {
58606
- element.setAttribute(
58607
- camelCaseToKebabWordIfNeeded(propName),
58608
- sanitiseAttributeValue(propName, normalisedProps[propName])
58609
- );
58261
+ const sortedTimes = Array.from(times).sort((a, b) => a - b);
58262
+ const keyframes = sortedTimes.map((t) => {
58263
+ const tgt = sumTranslateAt(targetChain, t);
58264
+ const src = sumTranslateAt(sourceChain, t);
58265
+ return { time: t, value: { translate: [src[0] - tgt[0], src[1] - tgt[1]] } };
58266
+ });
58267
+ return { type: "g", animate: { transform: { keyframes } }, children: [inner] };
58268
+ }
58269
+ function sumStaticTranslate(chain) {
58270
+ let x = 0, y = 0;
58271
+ for (const a of chain) {
58272
+ if (a.translate) {
58273
+ x += a.translate[0];
58274
+ y += a.translate[1];
58275
+ }
58610
58276
  }
58611
- if (style) {
58612
- for (const styleProp in style) {
58613
- element.style[styleProp] = String(style[styleProp]);
58277
+ return [x, y];
58278
+ }
58279
+ function sumTranslateAt(chain, t) {
58280
+ let x = 0, y = 0;
58281
+ for (const a of chain) {
58282
+ if (a.translateKeyframes && a.translateKeyframes.length) {
58283
+ const v = interpKfs(a.translateKeyframes, t);
58284
+ x += v[0];
58285
+ y += v[1];
58286
+ } else if (a.translate) {
58287
+ x += a.translate[0];
58288
+ y += a.translate[1];
58614
58289
  }
58615
58290
  }
58616
- if (children) {
58617
- for (const child of children) {
58618
- element.appendChild(child);
58291
+ return [x, y];
58292
+ }
58293
+ function interpKfs(kfs, t) {
58294
+ if (t <= kfs[0].time) return kfs[0].value;
58295
+ if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
58296
+ for (let i = 1; i < kfs.length; i++) {
58297
+ if (t <= kfs[i].time) {
58298
+ const prev = kfs[i - 1];
58299
+ const cur = kfs[i];
58300
+ const a = (t - prev.time) / (cur.time - prev.time);
58301
+ return [prev.value[0] + (cur.value[0] - prev.value[0]) * a, prev.value[1] + (cur.value[1] - prev.value[1]) * a];
58619
58302
  }
58620
58303
  }
58621
- if (textContent) element.textContent = textContent;
58622
- return element;
58304
+ return kfs[kfs.length - 1].value;
58623
58305
  }
58624
- function resolveStyle(style, defs) {
58625
- var _a;
58626
- if (!style) return void 0;
58627
- if (typeof style === "string") {
58628
- return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
58306
+ function collectMaskAncestorChains(root, ctx) {
58307
+ const interestingNodes = /* @__PURE__ */ new Set();
58308
+ const collectInterestingNodes = (n) => {
58309
+ var _a, _b;
58310
+ const href = (_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.href;
58311
+ if (typeof href === "string") {
58312
+ interestingNodes.add(n);
58313
+ const sourceNode = ctx.idMap.get(href);
58314
+ if (sourceNode) interestingNodes.add(sourceNode);
58315
+ }
58316
+ if (Array.isArray(n.children)) for (const ch of n.children) collectInterestingNodes(ch);
58317
+ };
58318
+ collectInterestingNodes(root);
58319
+ if (interestingNodes.size === 0) return;
58320
+ const walk = (node, chain) => {
58321
+ if (interestingNodes.has(node)) ctx.maskAncestorChains.set(node, chain);
58322
+ if (Array.isArray(node.children)) {
58323
+ const own = extractTranslateOnly(node, ctx);
58324
+ const next = own ? [...chain, own] : chain;
58325
+ for (const ch of node.children) walk(ch, next);
58326
+ }
58327
+ };
58328
+ walk(root, []);
58329
+ }
58330
+ function extractTranslateOnly(node, ctx) {
58331
+ var _a, _b, _c;
58332
+ const tr = node.transform;
58333
+ const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
58334
+ if (tr === void 0 && !animateBlock) return void 0;
58335
+ const out = {};
58336
+ if (typeof tr === "string") {
58337
+ const parts = parseTranslateOnlyFromString(tr, ctx);
58338
+ if (parts) out.translate = parts;
58339
+ } else if (tr && typeof tr === "object") {
58340
+ const value = tr.value;
58341
+ if (value && typeof value === "object" && Array.isArray(value.translate)) {
58342
+ out.translate = [value.translate[0] || 0, value.translate[1] || 0];
58343
+ }
58344
+ if (value && (value.rotate !== void 0 || value.scale !== void 0 || value.skew !== void 0)) {
58345
+ ctx.warnings.push("maskedBy ancestor: non-translate transform parts ignored (rotate/scale not yet supported)");
58346
+ }
58629
58347
  }
58630
- return style;
58348
+ if (animateBlock && Array.isArray(animateBlock.keyframes)) {
58349
+ const kfs = animateBlock.keyframes;
58350
+ const translateKfs = [];
58351
+ for (const kf of kfs) {
58352
+ const v = (_a = kf.value) != null ? _a : kf.v;
58353
+ const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
58354
+ if (v && typeof v === "object" && Array.isArray(v.translate)) {
58355
+ translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
58356
+ if (v.rotate !== void 0 || v.scale !== void 0 || v.skew !== void 0) {
58357
+ ctx.warnings.push("maskedBy ancestor: animated non-translate parts ignored");
58358
+ }
58359
+ }
58360
+ }
58361
+ if (translateKfs.length) out.translateKeyframes = translateKfs;
58362
+ }
58363
+ return out.translate || out.translateKeyframes ? out : void 0;
58631
58364
  }
58632
- function getNormalizedProps(props) {
58633
- const propsCopy = {};
58634
- for (const key of Object.keys(props)) {
58635
- if (INTERNAL_ATTRS.has(key)) continue;
58636
- if (key === "style") continue;
58637
- let value = props[key];
58638
- if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
58639
- propsCopy[key] = toRGBA(value);
58640
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && value.value && typeof value.value === "object") {
58641
- propsCopy["transform"] = composeTransformParts(value.value, { withUnits: false });
58642
- } else if (TRANSFORM_FN_NAMES.has(key)) {
58643
- if (Array.isArray(value)) {
58644
- if (key === "translate") value = value.map((v) => v + "px");
58645
- value = value.join(",");
58365
+ function parseTranslateOnlyFromString(s, ctx) {
58366
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
58367
+ let m;
58368
+ let x = 0, y = 0;
58369
+ let seen = false;
58370
+ let droppedNonTranslate = false;
58371
+ while ((m = re.exec(s)) !== null) {
58372
+ const name = m[1];
58373
+ const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
58374
+ if (name === "translate") {
58375
+ x += args[0] || 0;
58376
+ y += args[1] || 0;
58377
+ seen = true;
58378
+ } else {
58379
+ droppedNonTranslate = true;
58380
+ }
58381
+ }
58382
+ if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
58383
+ return seen ? [x, y] : void 0;
58384
+ }
58385
+ var CONTENT_SUBREF = "content";
58386
+ function applyRefHref(node, clone2, ctx) {
58387
+ if (!clone2) return;
58388
+ const baseId = clone2.baseId;
58389
+ if (!baseId) {
58390
+ if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing baseId");
58391
+ return;
58392
+ }
58393
+ const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
58394
+ node.href = "#" + targetId;
58395
+ }
58396
+ function applyRefAndTransformationEffect(node, clone2, transformation, ctx) {
58397
+ applyRefHref(node, clone2, ctx);
58398
+ return applyTransformationEffect(node, transformation, ctx);
58399
+ }
58400
+ function applyRepeaterEffect(node, fx, ctx) {
58401
+ var _a, _b;
58402
+ if (!fx) return node;
58403
+ const copies = (_a = fx.copies) != null ? _a : 1;
58404
+ if (copies < 1) {
58405
+ ctx.errors.push("repeater.copies invalid: " + fx.copies);
58406
+ return node;
58407
+ }
58408
+ const sharedTransform = node.transform;
58409
+ const sharedAnimTransform = (_b = node.animate) == null ? void 0 : _b.transform;
58410
+ const base = clone(node);
58411
+ delete base.transform;
58412
+ if (base.animate) {
58413
+ delete base.animate.transform;
58414
+ if (Object.keys(base.animate).length === 0) delete base.animate;
58415
+ }
58416
+ const children = [base];
58417
+ for (let i = 1; i < copies; i++) {
58418
+ const baseClone = clone(base);
58419
+ const synthFx = synthesisePerCopyFx(fx, i);
58420
+ const wrapped = synthFx ? applyTransformationEffect(baseClone, synthFx, ctx) : baseClone;
58421
+ children.push(wrapped);
58422
+ }
58423
+ const wrapper = { type: "g", children };
58424
+ if (sharedTransform !== void 0) wrapper.transform = sharedTransform;
58425
+ if (sharedAnimTransform !== void 0) wrapper.animate = { transform: sharedAnimTransform };
58426
+ return wrapper;
58427
+ }
58428
+ function synthesisePerCopyFx(fx, i) {
58429
+ const out = {};
58430
+ if (fx.translate !== void 0) {
58431
+ out.translate = mapAnimatableVec2(fx.translate, (v) => [v[0] * i, v[1] * i]);
58432
+ }
58433
+ if (fx.rotate !== void 0) {
58434
+ out.rotate = mapAnimatableNumber(fx.rotate, (v) => v * i);
58435
+ }
58436
+ if (fx.scale !== void 0) {
58437
+ out.scale = synthesiseScale(fx.scale, i);
58438
+ }
58439
+ if (fx.origin !== void 0) {
58440
+ out.origin = fx.origin;
58441
+ }
58442
+ return Object.keys(out).length ? out : void 0;
58443
+ }
58444
+ function mapAnimatableVec2(raw, fn) {
58445
+ if (Array.isArray(raw)) return fn(raw);
58446
+ if (raw && typeof raw === "object") {
58447
+ const obj = raw;
58448
+ if (Array.isArray(obj.keyframes)) {
58449
+ return __spreadProps(__spreadValues({}, obj), {
58450
+ keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
58451
+ });
58452
+ }
58453
+ if (obj.value !== void 0) {
58454
+ return __spreadProps(__spreadValues({}, obj), { value: fn(obj.value) });
58455
+ }
58456
+ }
58457
+ return raw;
58458
+ }
58459
+ function mapAnimatableNumber(raw, fn) {
58460
+ if (typeof raw === "number") return fn(raw);
58461
+ if (raw && typeof raw === "object") {
58462
+ const obj = raw;
58463
+ if (Array.isArray(obj.keyframes)) {
58464
+ return __spreadProps(__spreadValues({}, obj), {
58465
+ keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
58466
+ });
58467
+ }
58468
+ if (obj.value !== void 0) {
58469
+ return __spreadProps(__spreadValues({}, obj), { value: fn(obj.value) });
58470
+ }
58471
+ }
58472
+ return raw;
58473
+ }
58474
+ function synthesiseScale(raw, i) {
58475
+ const scalePowerFromPercent = (v) => [Math.pow(v[0] / 100, i), Math.pow(v[1] / 100, i)];
58476
+ const scalePowerFromUnits = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
58477
+ if (Array.isArray(raw)) {
58478
+ return { value: scalePowerFromPercent(raw) };
58479
+ }
58480
+ if (raw && typeof raw === "object") {
58481
+ const obj = raw;
58482
+ if (Array.isArray(obj.keyframes)) {
58483
+ return __spreadProps(__spreadValues({}, obj), {
58484
+ keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: scalePowerFromUnits(kf.value) }) : kf)
58485
+ });
58486
+ }
58487
+ if (obj.value !== void 0) {
58488
+ return __spreadProps(__spreadValues({}, obj), { value: scalePowerFromPercent(obj.value) });
58489
+ }
58490
+ }
58491
+ return raw;
58492
+ }
58493
+ var RETIME_MATERIALISATION_MODE_INLINE_G = false;
58494
+ function asRetime(r) {
58495
+ var _a, _b;
58496
+ return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
58497
+ }
58498
+ function concatRetime(child, parent) {
58499
+ return {
58500
+ start: parent.start + parent.stretch * child.start,
58501
+ stretch: parent.stretch * child.stretch
58502
+ };
58503
+ }
58504
+ function readCloneRetime(n) {
58505
+ var _a, _b;
58506
+ return (_b = (_a = n.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.retime;
58507
+ }
58508
+ function clearCloneRetime(n) {
58509
+ var _a;
58510
+ const clone2 = (_a = n.effects) == null ? void 0 : _a.clone;
58511
+ if (!clone2) return;
58512
+ delete clone2.retime;
58513
+ if (Object.keys(clone2).length === 0) delete n.effects.clone;
58514
+ if (n.effects && Object.keys(n.effects).length === 0) delete n.effects;
58515
+ }
58516
+ function applyAllRetimeEffects(root, ctx) {
58517
+ ctx.idMap.clear();
58518
+ indexById(root, ctx.idMap);
58519
+ const sites = [];
58520
+ const collect = (n) => {
58521
+ var _a;
58522
+ if (readCloneRetime(n)) sites.push(n);
58523
+ (_a = n.children) == null ? void 0 : _a.forEach(collect);
58524
+ };
58525
+ collect(root);
58526
+ for (const useNode of sites) {
58527
+ const retime = readCloneRetime(useNode);
58528
+ if (!retime) continue;
58529
+ clearCloneRetime(useNode);
58530
+ materialiseRetime(useNode, asRetime(retime), ctx);
58531
+ }
58532
+ }
58533
+ function materialiseRetime(useNode, retime, ctx) {
58534
+ const targetId = stripHash(useNode.href);
58535
+ if (!targetId) {
58536
+ ctx.errors.push("retime: <use> has no href to follow");
58537
+ return;
58538
+ }
58539
+ const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
58540
+ if (!chainRootId) return;
58541
+ if (RETIME_MATERIALISATION_MODE_INLINE_G) {
58542
+ const cloneNode = ctx.idMap.get(chainRootId);
58543
+ useNode.type = "g";
58544
+ delete useNode.href;
58545
+ useNode.children = [cloneNode];
58546
+ applyUseOffsetToG(useNode);
58547
+ ctx.defs = ctx.defs.filter((d) => d !== cloneNode);
58548
+ } else {
58549
+ useNode.href = "#" + chainRootId;
58550
+ }
58551
+ }
58552
+ function buildChainClone(targetId, accum, ctx, chain) {
58553
+ if (chain.has(targetId)) {
58554
+ ctx.errors.push('retime: loop via "' + targetId + '"');
58555
+ return void 0;
58556
+ }
58557
+ const target = ctx.idMap.get(targetId);
58558
+ if (!target) {
58559
+ ctx.warnings.push('retime: target "' + targetId + '" not found');
58560
+ return void 0;
58561
+ }
58562
+ const cloneNode = clone(target);
58563
+ regenerateIdsInClone(cloneNode, ctx);
58564
+ if (target.type === "use") {
58565
+ remapKeyframeTimesOnly(cloneNode, accum.start, accum.stretch);
58566
+ } else {
58567
+ remapKeyframeTimes(cloneNode, accum.start, accum.stretch);
58568
+ }
58569
+ clearCloneRetime(cloneNode);
58570
+ if (target.type === "use" && target.href) {
58571
+ const subId = stripHash(target.href);
58572
+ if (subId) {
58573
+ const innerRetime = readCloneRetime(target);
58574
+ const subAccum = innerRetime ? concatRetime(asRetime(innerRetime), accum) : accum;
58575
+ const subChain = new Set(chain);
58576
+ subChain.add(targetId);
58577
+ const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
58578
+ if (subId2) cloneNode.href = "#" + subId2;
58579
+ }
58580
+ } else {
58581
+ materialiseNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
58582
+ }
58583
+ ctx.defs.push(cloneNode);
58584
+ if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
58585
+ return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
58586
+ }
58587
+ function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
58588
+ const visit = (n) => {
58589
+ var _a;
58590
+ const retime = readCloneRetime(n);
58591
+ if (n.type === "use" && retime && n.href) {
58592
+ const subId = stripHash(n.href);
58593
+ if (subId) {
58594
+ const subAccum = concatRetime(asRetime(retime), accum);
58595
+ const subChain = new Set(chain);
58596
+ subChain.add(parentTargetId);
58597
+ const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
58598
+ if (subId2) n.href = "#" + subId2;
58599
+ }
58600
+ clearCloneRetime(n);
58601
+ }
58602
+ (_a = n.children) == null ? void 0 : _a.forEach(visit);
58603
+ };
58604
+ visit(node);
58605
+ }
58606
+ function remapKeyframeTimes(node, start, stretch) {
58607
+ var _a;
58608
+ remapKeyframeTimesOnly(node, start, stretch);
58609
+ (_a = node.children) == null ? void 0 : _a.forEach((c) => remapKeyframeTimes(c, start, stretch));
58610
+ }
58611
+ function remapKeyframeTimesOnly(node, start, stretch) {
58612
+ const remap2 = (kfs) => {
58613
+ for (const kf of kfs) if (typeof kf.time === "number") kf.time = start + kf.time * stretch;
58614
+ };
58615
+ if (node.transform && typeof node.transform === "object" && Array.isArray(node.transform.keyframes)) {
58616
+ remap2(node.transform.keyframes);
58617
+ }
58618
+ if (node.animate && typeof node.animate === "object") {
58619
+ for (const prop of Object.keys(node.animate)) {
58620
+ const anim = node.animate[prop];
58621
+ if (anim && Array.isArray(anim.keyframes)) remap2(anim.keyframes);
58622
+ }
58623
+ }
58624
+ }
58625
+ function applyTextAlongPathEffect(node, fx, _ctx) {
58626
+ var _a;
58627
+ if (!fx) return node;
58628
+ const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
58629
+ const textPath = {
58630
+ type: "textPath",
58631
+ href,
58632
+ children: (_a = node.children) != null ? _a : []
58633
+ };
58634
+ if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
58635
+ if (fx.method !== void 0) textPath.method = fx.method;
58636
+ if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
58637
+ applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
58638
+ applyAnimatableNumber(textPath, "textLength", fx.textLength);
58639
+ node.children = [textPath];
58640
+ return node;
58641
+ }
58642
+ function applyAnimatableNumber(node, attrName, raw) {
58643
+ if (raw === void 0 || raw === null) return;
58644
+ if (typeof raw === "number") {
58645
+ node[attrName] = String(raw);
58646
+ return;
58647
+ }
58648
+ if (typeof raw === "object" && raw !== null) {
58649
+ const obj = raw;
58650
+ if (Array.isArray(obj.keyframes)) {
58651
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
58652
+ const animate = __spreadValues({}, prevAnimate || {});
58653
+ const block = { keyframes: obj.keyframes };
58654
+ if (obj.loop !== void 0) block.loop = obj.loop;
58655
+ animate[attrName] = block;
58656
+ node.animate = animate;
58657
+ return;
58658
+ }
58659
+ if (typeof obj.value === "number") {
58660
+ node[attrName] = String(obj.value);
58661
+ return;
58662
+ }
58663
+ }
58664
+ }
58665
+ function bezierToSvgPath(path) {
58666
+ var _a, _b, _c, _d;
58667
+ const v = path.v;
58668
+ const i = path.i;
58669
+ const o = path.o;
58670
+ const c = path.c;
58671
+ if (!v.length) return "";
58672
+ const d = [];
58673
+ const len = v.length;
58674
+ d.push("M" + v[0][0] + "," + v[0][1]);
58675
+ for (let idx = 1; idx < len; idx++) {
58676
+ const prevV = v[idx - 1];
58677
+ const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
58678
+ const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
58679
+ const currV = v[idx];
58680
+ const isLine = prevO[0] === prevV[0] && prevO[1] === prevV[1] && (currI[0] === currV[0] && currI[1] === currV[1]);
58681
+ if (isLine) {
58682
+ d.push("L" + currV[0] + "," + currV[1]);
58683
+ } else {
58684
+ d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
58685
+ }
58686
+ }
58687
+ if (c && len > 0) {
58688
+ const lastV = v[len - 1];
58689
+ const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
58690
+ const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
58691
+ const firstV = v[0];
58692
+ const isLine = lastO[0] === lastV[0] && lastO[1] === lastV[1] && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
58693
+ if (!isLine) {
58694
+ d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
58695
+ }
58696
+ d.push("z");
58697
+ }
58698
+ return d.join("");
58699
+ }
58700
+ function interpolateNum(a, b, t) {
58701
+ return a + (b - a) * t;
58702
+ }
58703
+ function interpolateVec(a, b, t) {
58704
+ const res = [];
58705
+ const count = Math.max(a.length, b.length);
58706
+ for (let i = 0; i < count; i++) {
58707
+ res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
58708
+ }
58709
+ return res;
58710
+ }
58711
+ function interpolateColor(a, b, t) {
58712
+ return [
58713
+ interpolateNum(a[0] || 0, b[0] || 0, t),
58714
+ interpolateNum(a[1] || 0, b[1] || 0, t),
58715
+ interpolateNum(a[2] || 0, b[2] || 0, t),
58716
+ interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
58717
+ ];
58718
+ }
58719
+ function interpolateBeziers(paths1, paths2, progress) {
58720
+ const count = Math.max(paths1.length, paths2.length);
58721
+ const res = [];
58722
+ for (let i = 0; i < count; i++) {
58723
+ res.push(interpolateBezier(paths1[i], paths2[i], progress));
58724
+ }
58725
+ return res;
58726
+ }
58727
+ function interpolateBezier(path1, path2, progress) {
58728
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
58729
+ if (!path1 || !path2) return path1 || path2 || { v: [] };
58730
+ const t = Math.min(Math.max(progress, 0), 1);
58731
+ const len = Math.min(path1.v.length, path2.v.length);
58732
+ const v = [];
58733
+ const i = [];
58734
+ const o = [];
58735
+ for (let idx = 0; idx < len; idx++) {
58736
+ const v1 = path1.v[idx];
58737
+ const v2 = path2.v[idx];
58738
+ v.push(interpolateVec(v1, v2, t));
58739
+ const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
58740
+ const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
58741
+ i.push(interpolateVec(i1, i2, t));
58742
+ const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
58743
+ const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
58744
+ o.push(interpolateVec(o1, o2, t));
58745
+ }
58746
+ return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
58747
+ }
58748
+ function remap(value, inMin, inMax, outMin, outMax) {
58749
+ if (inMax === inMin) return outMin;
58750
+ const t = (value - inMin) / (inMax - inMin);
58751
+ return outMin + t * (outMax - outMin);
58752
+ }
58753
+ function solveCubicBezierX(p1x, p2x, x) {
58754
+ if (x <= 0) return 0;
58755
+ if (x >= 1) return 1;
58756
+ const cx = 3 * p1x;
58757
+ const bx = 3 * (p2x - p1x) - cx;
58758
+ const ax = 1 - cx - bx;
58759
+ function sampleX(t) {
58760
+ return ((ax * t + bx) * t + cx) * t;
58761
+ }
58762
+ function sampleDX(t) {
58763
+ return (3 * ax * t + 2 * bx) * t + cx;
58764
+ }
58765
+ let t2 = x;
58766
+ let t0 = 0;
58767
+ let t1 = 1;
58768
+ for (let i = 0; i < 8; i++) {
58769
+ const x2 = sampleX(t2) - x;
58770
+ if (Math.abs(x2) < 1e-6) return t2;
58771
+ const d2 = sampleDX(t2);
58772
+ if (Math.abs(d2) < 1e-6) break;
58773
+ t2 -= x2 / d2;
58774
+ }
58775
+ t2 = x;
58776
+ while (t0 < t1) {
58777
+ const x2 = sampleX(t2);
58778
+ if (Math.abs(x2 - x) < 1e-6) return t2;
58779
+ if (x > x2) t0 = t2;
58780
+ else t1 = t2;
58781
+ t2 = (t1 + t0) / 2;
58782
+ }
58783
+ return t2;
58784
+ }
58785
+ function cubicBezier(easing) {
58786
+ const [p1x, p1y, p2x, p2y] = easing;
58787
+ const cy = 3 * p1y;
58788
+ const by = 3 * (p2y - p1y) - cy;
58789
+ const ay = 1 - cy - by;
58790
+ function sampleCurveY(t) {
58791
+ return ((ay * t + by) * t + cy) * t;
58792
+ }
58793
+ return function(x) {
58794
+ return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
58795
+ };
58796
+ }
58797
+ function lerp2(a, b, t) {
58798
+ return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
58799
+ }
58800
+ function subdivideCubicBezier(p0, p1, p2, p3, t) {
58801
+ const q0 = lerp2(p0, p1, t);
58802
+ const q1 = lerp2(p1, p2, t);
58803
+ const q2 = lerp2(p2, p3, t);
58804
+ const r0 = lerp2(q0, q1, t);
58805
+ const r1 = lerp2(q1, q2, t);
58806
+ const s = lerp2(r0, r1, t);
58807
+ return {
58808
+ left: [p0, q0, r0, s],
58809
+ right: [s, r1, q2, p3]
58810
+ };
58811
+ }
58812
+ function splitEasing(easing, xFraction) {
58813
+ if (!easing) return { left: void 0, right: void 0 };
58814
+ if (xFraction <= 0) return { left: void 0, right: easing };
58815
+ if (xFraction >= 1) return { left: easing, right: void 0 };
58816
+ const [x1, y1, x2, y2] = easing;
58817
+ const t = solveCubicBezierX(x1, x2, xFraction);
58818
+ const p0 = [0, 0];
58819
+ const p1 = [x1, y1];
58820
+ const p2 = [x2, y2];
58821
+ const p3 = [1, 1];
58822
+ const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
58823
+ const sx = left[3][0];
58824
+ const sy = left[3][1];
58825
+ let leftEasing;
58826
+ if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
58827
+ leftEasing = [
58828
+ left[1][0] / sx,
58829
+ left[1][1] / sy,
58830
+ left[2][0] / sx,
58831
+ left[2][1] / sy
58832
+ ];
58833
+ }
58834
+ let rightEasing;
58835
+ const rx = 1 - sx;
58836
+ const ry = 1 - sy;
58837
+ if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
58838
+ rightEasing = [
58839
+ (right[1][0] - sx) / rx,
58840
+ (right[1][1] - sy) / ry,
58841
+ (right[2][0] - sx) / rx,
58842
+ (right[2][1] - sy) / ry
58843
+ ];
58844
+ }
58845
+ return { left: leftEasing, right: rightEasing };
58846
+ }
58847
+ function reverseEasing(easing) {
58848
+ if (!easing) return void 0;
58849
+ return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
58850
+ }
58851
+ function toRGBA(color) {
58852
+ const r = Math.round(color[0] * 255);
58853
+ const g = Math.round(color[1] * 255);
58854
+ const b = Math.round(color[2] * 255);
58855
+ return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
58856
+ }
58857
+ function parseRgba(s) {
58858
+ var _a;
58859
+ const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
58860
+ if (!inner) throw new Error("Invalid rgb/rgba format");
58861
+ const parts = inner.split(",").map((v) => +v.trim());
58862
+ return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
58863
+ }
58864
+ function parseHex(s) {
58865
+ const hex = s.slice(1);
58866
+ const isShort = hex.length <= 4;
58867
+ const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
58868
+ const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
58869
+ const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
58870
+ const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
58871
+ const result = [
58872
+ parseInt(r, 16) / 255,
58873
+ parseInt(g, 16) / 255,
58874
+ parseInt(b, 16) / 255
58875
+ ];
58876
+ if (a !== null) {
58877
+ result.push(parseInt(a, 16) / 255);
58878
+ }
58879
+ return result;
58880
+ }
58881
+ function parseColor(s) {
58882
+ if (!s) return void 0;
58883
+ if (Array.isArray(s)) return s;
58884
+ if (typeof s !== "string") return void 0;
58885
+ if (s.startsWith("#")) {
58886
+ return parseHex(s);
58887
+ } else if (s.startsWith("rgb")) {
58888
+ return parseRgba(s);
58889
+ } else {
58890
+ console.warn("Unsupported color format: " + s);
58891
+ }
58892
+ return void 0;
58893
+ }
58894
+ var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
58895
+ var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
58896
+ var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
58897
+ function composeTransformParts(parts, opts) {
58898
+ var _a;
58899
+ if (!parts) return "";
58900
+ const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
58901
+ const segs = [];
58902
+ const t = parts.translate;
58903
+ const o = parts.origin;
58904
+ const r = parts.rotate;
58905
+ const s = parts.scale;
58906
+ const tu = withUnits ? "px" : "";
58907
+ const ru = withUnits ? "deg" : "";
58908
+ if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
58909
+ if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
58910
+ if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
58911
+ if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
58912
+ if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
58913
+ return segs.join("");
58914
+ }
58915
+ var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
58916
+ var DEFAULT_DURATION_MS = 1e3;
58917
+ function kebabToCamelCaseWord(kebab) {
58918
+ return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
58919
+ }
58920
+ function isCamelCaseWord(word) {
58921
+ return !word.includes("-") && /[a-z][A-Z]/.test(word);
58922
+ }
58923
+ var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
58924
+ // Transform/positioning
58925
+ "viewBox",
58926
+ "preserveAspectRatio",
58927
+ // Gradient
58928
+ "gradientUnits",
58929
+ "gradientTransform",
58930
+ "spreadMethod",
58931
+ // Pattern
58932
+ "patternUnits",
58933
+ "patternContentUnits",
58934
+ "patternTransform",
58935
+ // Clipping/masking
58936
+ "clipPathUnits",
58937
+ "maskUnits",
58938
+ "maskContentUnits",
58939
+ // Marker (SVG spec keeps these camelCase, like viewBox)
58940
+ "markerUnits",
58941
+ "markerWidth",
58942
+ "markerHeight",
58943
+ "refX",
58944
+ "refY",
58945
+ // Text
58946
+ "textLength",
58947
+ "lengthAdjust",
58948
+ "startOffset",
58949
+ // Filter
58950
+ "filterUnits",
58951
+ "primitiveUnits",
58952
+ "stdDeviation",
58953
+ "baseFrequency",
58954
+ "numOctaves",
58955
+ "surfaceScale",
58956
+ "diffuseConstant",
58957
+ "specularConstant",
58958
+ "specularExponent",
58959
+ "kernelMatrix",
58960
+ "kernelUnitLength",
58961
+ "edgeMode",
58962
+ "preserveAlpha",
58963
+ "targetX",
58964
+ "targetY"
58965
+ // // Animation
58966
+ // 'attributeName',
58967
+ // 'attributeType',
58968
+ // 'calcMode',
58969
+ // 'keyTimes',
58970
+ // 'keySplines',
58971
+ // 'repeatCount',
58972
+ // 'repeatDur'
58973
+ ]);
58974
+ function camelCaseToKebabWordIfNeeded(camel) {
58975
+ return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
58976
+ }
58977
+ function clamp(value, min, max) {
58978
+ return Math.max(min, Math.min(value, max));
58979
+ }
58980
+ function bezier2D_pointAt(P0, P1, P2, P3, t) {
58981
+ if (t <= 0) return [P0[0], P0[1]];
58982
+ if (t >= 1) return [P3[0], P3[1]];
58983
+ const u = 1 - t;
58984
+ const u2 = u * u;
58985
+ const u3 = u2 * u;
58986
+ const t2 = t * t;
58987
+ const t3 = t2 * t;
58988
+ const w0 = u3;
58989
+ const w1 = 3 * t * u2;
58990
+ const w2 = 3 * t2 * u;
58991
+ const w3 = t3;
58992
+ return [
58993
+ w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
58994
+ w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
58995
+ ];
58996
+ }
58997
+ var BEZIER_T_NUDGE = 1e-4;
58998
+ function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
58999
+ const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
59000
+ if (result[0] === 0 && result[1] === 0) {
59001
+ const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
59002
+ return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
59003
+ }
59004
+ return result;
59005
+ }
59006
+ function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
59007
+ const u = 1 - t;
59008
+ const a = 3 * u * u;
59009
+ const b = 6 * t * u;
59010
+ const c = 3 * t * t;
59011
+ return [
59012
+ a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
59013
+ a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
59014
+ ];
59015
+ }
59016
+ function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
59017
+ const n = steps + 1;
59018
+ const ts = new Float64Array(n);
59019
+ const ds = new Float64Array(n);
59020
+ let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
59021
+ ts[0] = 0;
59022
+ ds[0] = 0;
59023
+ let cum = 0;
59024
+ for (let i = 1; i < n; i++) {
59025
+ const t = i / steps;
59026
+ const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
59027
+ const dx = cur[0] - prev[0];
59028
+ const dy = cur[1] - prev[1];
59029
+ cum += Math.sqrt(dx * dx + dy * dy);
59030
+ ts[i] = t;
59031
+ ds[i] = cum;
59032
+ prev = cur;
59033
+ }
59034
+ return { ts, ds };
59035
+ }
59036
+ function bezier2D_arcAtT(lut, t) {
59037
+ const { ts, ds } = lut;
59038
+ const last = ts.length - 1;
59039
+ if (t <= ts[0]) return ds[0];
59040
+ if (t >= ts[last]) return ds[last];
59041
+ let lo = 1, hi = last;
59042
+ while (lo < hi) {
59043
+ const mid = lo + hi >>> 1;
59044
+ if (ts[mid] < t) lo = mid + 1;
59045
+ else hi = mid;
59046
+ }
59047
+ const tPrev = ts[hi - 1];
59048
+ const span = ts[hi] - tPrev;
59049
+ const frac = span > 0 ? (t - tPrev) / span : 0;
59050
+ return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
59051
+ }
59052
+ function invertEasing(easing) {
59053
+ if (!easing) return (y) => y;
59054
+ const flipped = [easing[1], easing[0], easing[3], easing[2]];
59055
+ return cubicBezier(flipped);
59056
+ }
59057
+ function getKfTranslate(kf) {
59058
+ var _a;
59059
+ const v = (_a = kf.value) != null ? _a : kf.v;
59060
+ if (!v) return void 0;
59061
+ if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
59062
+ return [v[0], v[1]];
59063
+ }
59064
+ const tr = v.translate;
59065
+ if (Array.isArray(tr) && tr.length >= 2) return [tr[0], tr[1]];
59066
+ return void 0;
59067
+ }
59068
+ function getKfTime(kf) {
59069
+ var _a, _b;
59070
+ return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
59071
+ }
59072
+ function getKfEasing(kf) {
59073
+ var _a;
59074
+ return (_a = kf.easing) != null ? _a : kf.e;
59075
+ }
59076
+ function propAnimIsMotionPath(anim) {
59077
+ var _a, _b, _c;
59078
+ const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
59079
+ if (!Array.isArray(kfs)) return false;
59080
+ if (anim.autoOrient) return true;
59081
+ for (const kf of kfs) {
59082
+ if (((_b = kf.tangentIn) != null ? _b : kf.ti) || ((_c = kf.tangentOut) != null ? _c : kf.to)) return true;
59083
+ }
59084
+ return false;
59085
+ }
59086
+ var _segmentCache = /* @__PURE__ */ new WeakMap();
59087
+ function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
59088
+ var _a, _b;
59089
+ const existing = _segmentCache.get(prevKf);
59090
+ if (existing) return existing;
59091
+ const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
59092
+ const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
59093
+ const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
59094
+ const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
59095
+ const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
59096
+ const entry = {
59097
+ P0: prevPos,
59098
+ P1,
59099
+ P2,
59100
+ P3: nextPos,
59101
+ lut,
59102
+ totalArc: lut.ds[lut.ds.length - 1]
59103
+ };
59104
+ _segmentCache.set(prevKf, entry);
59105
+ return entry;
59106
+ }
59107
+ function evaluateMotionPathSegment(prevKf, nextKf, prevPos, nextPos, localProgress, autoOrient) {
59108
+ const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
59109
+ const t = seg.totalArc === 0 ? localProgress : tFromArcFraction(seg.lut, localProgress);
59110
+ const point = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
59111
+ if (!autoOrient) return { translate: point };
59112
+ const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
59113
+ const rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
59114
+ return { translate: point, rotateDeg };
59115
+ }
59116
+ function tFromArcFraction(lut, arcFrac) {
59117
+ const total = lut.ds[lut.ds.length - 1];
59118
+ const target = arcFrac * total;
59119
+ const { ts, ds } = lut;
59120
+ const last = ds.length - 1;
59121
+ if (target <= 0) return ts[0];
59122
+ if (target >= ds[last]) return ts[last];
59123
+ let lo = 1, hi = last;
59124
+ while (lo < hi) {
59125
+ const mid = lo + hi >>> 1;
59126
+ if (ds[mid] < target) lo = mid + 1;
59127
+ else hi = mid;
59128
+ }
59129
+ const dPrev = ds[hi - 1];
59130
+ const span = ds[hi] - dPrev;
59131
+ const frac = span > 0 ? (target - dPrev) / span : 0;
59132
+ return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
59133
+ }
59134
+ var DEFAULT_FLATNESS_TOL = 0.5;
59135
+ var DEFAULT_ROTATION_TOL = 5;
59136
+ var DEFAULT_MAX_SAMPLES = 32;
59137
+ function materialiseMotionPathInPropAnim(anim, opts) {
59138
+ var _a, _b, _c, _d;
59139
+ if (!propAnimIsMotionPath(anim)) return anim;
59140
+ const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
59141
+ if (!Array.isArray(kfs) || kfs.length < 2) return anim;
59142
+ const autoOrient = !!anim.autoOrient;
59143
+ const flatnessTol = (_b = opts == null ? void 0 : opts.flatnessTolerance) != null ? _b : DEFAULT_FLATNESS_TOL;
59144
+ const rotationTol = (_c = opts == null ? void 0 : opts.rotationTolerance) != null ? _c : DEFAULT_ROTATION_TOL;
59145
+ const maxSamples = (_d = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _d : DEFAULT_MAX_SAMPLES;
59146
+ const out = [];
59147
+ const firstPos = getKfTranslate(kfs[0]);
59148
+ if (!firstPos) return anim;
59149
+ const firstRotate = autoOrient ? derivAngleForFirstKf(kfs[0], kfs[1]) : void 0;
59150
+ out.push(makeOutKf(
59151
+ getKfTime(kfs[0]),
59152
+ buildOutKfValue(getKfValueParts(kfs[0]), getKfValueParts(kfs[0]), 0, firstPos, firstRotate, autoOrient)
59153
+ ));
59154
+ for (let i = 0; i < kfs.length - 1; i++) {
59155
+ const prevKf = kfs[i];
59156
+ const nextKf = kfs[i + 1];
59157
+ const prevPos = getKfTranslate(prevKf);
59158
+ const nextPos = getKfTranslate(nextKf);
59159
+ if (!prevPos || !nextPos) {
59160
+ out.push(makeOutKf(
59161
+ getKfTime(nextKf),
59162
+ buildOutKfValue(getKfValueParts(nextKf), getKfValueParts(nextKf), 1, nextPos != null ? nextPos : [0, 0], void 0, autoOrient)
59163
+ ));
59164
+ continue;
59165
+ }
59166
+ if (autoOrient && i > 0) {
59167
+ insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol);
59168
+ }
59169
+ materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
59170
+ }
59171
+ const lastInE = getKfEasing(kfs[kfs.length - 1]);
59172
+ if (lastInE) out[out.length - 1].e = lastInE;
59173
+ if (autoOrient) unwrapAutoOrientRotations(out);
59174
+ const result = { kfs: out };
59175
+ if (anim.loop !== void 0) result.loop = anim.loop;
59176
+ return result;
59177
+ }
59178
+ function unwrapAutoOrientRotations(kfs) {
59179
+ var _a;
59180
+ let prev;
59181
+ for (const kf of kfs) {
59182
+ const v = (_a = kf.v) != null ? _a : kf.value;
59183
+ if (!v || typeof v.rotate !== "number") continue;
59184
+ if (prev === void 0) {
59185
+ prev = v.rotate;
59186
+ continue;
59187
+ }
59188
+ let r = v.rotate;
59189
+ while (r - prev > 180) r -= 360;
59190
+ while (r - prev < -180) r += 360;
59191
+ v.rotate = r;
59192
+ prev = r;
59193
+ }
59194
+ }
59195
+ function makeOutKf(time, value) {
59196
+ return { t: time, v: value };
59197
+ }
59198
+ function getKfValueParts(kf) {
59199
+ var _a;
59200
+ const v = (_a = kf.value) != null ? _a : kf.v;
59201
+ if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
59202
+ return v;
59203
+ }
59204
+ function interpolatePart(prev, next, p) {
59205
+ if (prev === void 0) return next;
59206
+ if (next === void 0) return prev;
59207
+ if (typeof prev === "number" && typeof next === "number") {
59208
+ return prev + (next - prev) * p;
59209
+ }
59210
+ if (Array.isArray(prev) && Array.isArray(next) && prev.length === next.length) {
59211
+ const out = new Array(prev.length);
59212
+ for (let i = 0; i < prev.length; i++) {
59213
+ const a = typeof prev[i] === "number" ? prev[i] : 0;
59214
+ const b = typeof next[i] === "number" ? next[i] : 0;
59215
+ out[i] = a + (b - a) * p;
59216
+ }
59217
+ return out;
59218
+ }
59219
+ return p < 0.5 ? prev : next;
59220
+ }
59221
+ function buildOutKfValue(prevV, nextV, p, translate, rotateDegFromAutoOrient, autoOrient) {
59222
+ const value = { translate };
59223
+ const keys = /* @__PURE__ */ new Set();
59224
+ if (prevV) for (const k of Object.keys(prevV)) keys.add(k);
59225
+ if (nextV) for (const k of Object.keys(nextV)) keys.add(k);
59226
+ for (const k of keys) {
59227
+ if (k === "translate") continue;
59228
+ if (k === "rotate" && autoOrient) continue;
59229
+ const pv = prevV == null ? void 0 : prevV[k];
59230
+ const nv = nextV == null ? void 0 : nextV[k];
59231
+ if (pv === void 0 && nv === void 0) continue;
59232
+ value[k] = interpolatePart(pv, nv, p);
59233
+ }
59234
+ if (rotateDegFromAutoOrient !== void 0) value.rotate = rotateDegFromAutoOrient;
59235
+ return value;
59236
+ }
59237
+ function derivAngleForFirstKf(kf0, kf1) {
59238
+ const p0 = getKfTranslate(kf0);
59239
+ const p1 = getKfTranslate(kf1);
59240
+ if (!p0 || !p1) return 0;
59241
+ const seg = getSegmentCache(kf0, kf1, p0, p1);
59242
+ const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, 0);
59243
+ return Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
59244
+ }
59245
+ function wrappedAngleDelta(a, b) {
59246
+ let d = a - b;
59247
+ while (d > 180) d -= 360;
59248
+ while (d < -180) d += 360;
59249
+ return d;
59250
+ }
59251
+ function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
59252
+ var _a;
59253
+ const lastKf = out[out.length - 1];
59254
+ const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
59255
+ const prevExit = lastV == null ? void 0 : lastV.rotate;
59256
+ if (typeof prevExit !== "number") return;
59257
+ const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
59258
+ const tanAtStart = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, 0);
59259
+ const nextEntry = Math.atan2(tanAtStart[1], tanAtStart[0]) * 180 / Math.PI;
59260
+ const delta = wrappedAngleDelta(nextEntry, prevExit);
59261
+ if (Math.abs(delta) <= rotationTol) return;
59262
+ const dupValue = buildOutKfValue(
59263
+ getKfValueParts(prevKf),
59264
+ getKfValueParts(prevKf),
59265
+ 0,
59266
+ prevPos,
59267
+ nextEntry,
59268
+ true
59269
+ );
59270
+ out.push(makeOutKf(getKfTime(prevKf), dupValue));
59271
+ }
59272
+ function materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
59273
+ const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
59274
+ const prevTime = getKfTime(prevKf);
59275
+ const nextTime = getKfTime(nextKf);
59276
+ const prevEasing = getKfEasing(prevKf);
59277
+ const invertFn = invertEasing(prevEasing);
59278
+ const prevV = getKfValueParts(prevKf);
59279
+ const nextV = getKfValueParts(nextKf);
59280
+ const interiorTs = computeSampleTs(seg, autoOrient, flatnessTol, rotationTol, maxSamples);
59281
+ const samples = [];
59282
+ for (const t of interiorTs) {
59283
+ const arc = bezier2D_arcAtT(seg.lut, t);
59284
+ const p = clamp(seg.totalArc > 0 ? arc / seg.totalArc : t, 0, 1);
59285
+ const u = clamp(invertFn(p), 0, 1);
59286
+ const pos = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
59287
+ const sample = { u, p, pos };
59288
+ if (autoOrient) {
59289
+ const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
59290
+ sample.rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
59291
+ }
59292
+ samples.push(sample);
59293
+ }
59294
+ let remaining = prevEasing;
59295
+ let prevU = 0;
59296
+ const startIdx = out.length - 1;
59297
+ for (let i = 0; i < samples.length; i++) {
59298
+ const s = samples[i];
59299
+ const xFrac = prevU < 1 ? clamp((s.u - prevU) / (1 - prevU), 0, 1) : 1;
59300
+ const { left, right } = splitEasing(remaining, xFrac);
59301
+ const ownerIdx = i === 0 ? startIdx : out.length - 1;
59302
+ if (left) out[ownerIdx].e = left;
59303
+ else delete out[ownerIdx].e;
59304
+ const tGlobal = prevTime + s.u * (nextTime - prevTime);
59305
+ const value = buildOutKfValue(prevV, nextV, s.p, s.pos, s.rotateDeg, autoOrient);
59306
+ out.push(makeOutKf(tGlobal, value));
59307
+ remaining = right;
59308
+ prevU = s.u;
59309
+ }
59310
+ }
59311
+ function computeSampleTs(seg, autoOrient, flatnessTol, rotationTol, maxSamples) {
59312
+ const extremes = [];
59313
+ addAxisExtremes(seg.P0[0], seg.P1[0], seg.P2[0], seg.P3[0], extremes);
59314
+ addAxisExtremes(seg.P0[1], seg.P1[1], seg.P2[1], seg.P3[1], extremes);
59315
+ extremes.sort((a, b) => a - b);
59316
+ const critical = [0];
59317
+ for (const t of extremes) {
59318
+ if (t > critical[critical.length - 1] + 1e-6 && t < 1 - 1e-6) {
59319
+ critical.push(t);
59320
+ }
59321
+ }
59322
+ critical.push(1);
59323
+ const out = [];
59324
+ const budget = { remaining: maxSamples - critical.length };
59325
+ for (let i = 0; i < critical.length - 1; i++) {
59326
+ bisect(critical[i], critical[i + 1], out, seg, autoOrient, flatnessTol, rotationTol, budget);
59327
+ }
59328
+ return out;
59329
+ }
59330
+ function addAxisExtremes(p0, p1, p2, p3, out) {
59331
+ const a = p1 - p0;
59332
+ const b = p2 - p1;
59333
+ const c = p3 - p2;
59334
+ const A = a - 2 * b + c;
59335
+ const B = 2 * (b - a);
59336
+ const C = a;
59337
+ if (Math.abs(A) < 1e-10) {
59338
+ if (Math.abs(B) > 1e-10) {
59339
+ const t = -C / B;
59340
+ if (t > 1e-6 && t < 1 - 1e-6) out.push(t);
59341
+ }
59342
+ return;
59343
+ }
59344
+ const disc = B * B - 4 * A * C;
59345
+ if (disc < 0) return;
59346
+ const sq = Math.sqrt(disc);
59347
+ const t1 = (-B - sq) / (2 * A);
59348
+ const t2 = (-B + sq) / (2 * A);
59349
+ if (t1 > 1e-6 && t1 < 1 - 1e-6) out.push(t1);
59350
+ if (t2 > 1e-6 && t2 < 1 - 1e-6) out.push(t2);
59351
+ }
59352
+ function bisect(tA, tB, out, seg, autoOrient, flatnessTol, rotationTol, budget) {
59353
+ const tMid = (tA + tB) / 2;
59354
+ const pA = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tA);
59355
+ const pB = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tB);
59356
+ const span = tB - tA;
59357
+ const p25 = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tA + span * 0.25);
59358
+ const p50 = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tMid);
59359
+ const p75 = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tA + span * 0.75);
59360
+ const dev = Math.max(
59361
+ perpDist(p25, pA, pB),
59362
+ perpDist(p50, pA, pB),
59363
+ perpDist(p75, pA, pB)
59364
+ );
59365
+ let rotOk = true;
59366
+ if (autoOrient) {
59367
+ const tanA = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, tA);
59368
+ const tanB = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, tB);
59369
+ const angA = Math.atan2(tanA[1], tanA[0]) * 180 / Math.PI;
59370
+ const angB = Math.atan2(tanB[1], tanB[0]) * 180 / Math.PI;
59371
+ let delta = Math.abs(angA - angB);
59372
+ if (delta > 180) delta = 360 - delta;
59373
+ if (delta > rotationTol) rotOk = false;
59374
+ }
59375
+ if (dev <= flatnessTol && rotOk || budget.remaining <= 0 || span < 1e-6) {
59376
+ out.push(tB);
59377
+ return;
59378
+ }
59379
+ budget.remaining -= 1;
59380
+ bisect(tA, tMid, out, seg, autoOrient, flatnessTol, rotationTol, budget);
59381
+ bisect(tMid, tB, out, seg, autoOrient, flatnessTol, rotationTol, budget);
59382
+ }
59383
+ function perpDist(q, pA, pB) {
59384
+ const dx = pB[0] - pA[0];
59385
+ const dy = pB[1] - pA[1];
59386
+ const len2 = dx * dx + dy * dy;
59387
+ if (len2 < 1e-20) {
59388
+ const qdx = q[0] - pA[0];
59389
+ const qdy = q[1] - pA[1];
59390
+ return Math.sqrt(qdx * qdx + qdy * qdy);
59391
+ }
59392
+ const cross = (q[0] - pA[0]) * dy - (q[1] - pA[1]) * dx;
59393
+ return Math.abs(cross) / Math.sqrt(len2);
59394
+ }
59395
+ function materialiseMotionPathsInTree(root, opts) {
59396
+ const out = walkAndMaterialise(root, opts);
59397
+ return out != null ? out : root;
59398
+ }
59399
+ function walkAndMaterialise(node, opts) {
59400
+ let newChildren;
59401
+ if (node.children) {
59402
+ for (let i = 0; i < node.children.length; i++) {
59403
+ const ch = node.children[i];
59404
+ const ret = walkAndMaterialise(ch, opts);
59405
+ if (ret !== null) {
59406
+ if (!newChildren) newChildren = node.children.slice();
59407
+ newChildren[i] = ret;
59408
+ }
59409
+ }
59410
+ }
59411
+ let newAnimate;
59412
+ const animBucket = node.animate;
59413
+ if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
59414
+ const animDef = animBucket;
59415
+ const transformAnim = animDef.transform;
59416
+ if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
59417
+ const materialised = materialiseMotionPathInPropAnim(transformAnim, opts);
59418
+ if (materialised !== transformAnim) {
59419
+ newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialised });
59420
+ }
59421
+ }
59422
+ }
59423
+ if (!newChildren && !newAnimate) return null;
59424
+ const cloned = __spreadValues({}, node);
59425
+ if (newChildren) cloned.children = newChildren;
59426
+ if (newAnimate) cloned.animate = newAnimate;
59427
+ return cloned;
59428
+ }
59429
+ function parsePathCommands(d) {
59430
+ const tokens = d.split(/([MLCZmlcz]|[\s,]+)/).map((t) => t.trim()).filter((t) => t && t !== ",");
59431
+ const commands = [];
59432
+ let currentCommand = null;
59433
+ for (const token of tokens) {
59434
+ if (/[MLCZmlcz]/.test(token)) {
59435
+ currentCommand = { type: token, values: [] };
59436
+ commands.push(currentCommand);
59437
+ } else if (currentCommand) {
59438
+ const value = +token;
59439
+ currentCommand.values.push(Number.isNaN(value) ? 0 : value);
59440
+ }
59441
+ }
59442
+ return commands;
59443
+ }
59444
+ function parseSvgPathToBezier(d) {
59445
+ const res = [];
59446
+ let currentPath;
59447
+ const commands = parsePathCommands(d);
59448
+ for (const command of commands) {
59449
+ const type = command.type;
59450
+ const values = command.values;
59451
+ if (type === "M" || type === "m") {
59452
+ const x = values[0] || 0;
59453
+ const y = values[1] || 0;
59454
+ currentPath = {
59455
+ v: [[x, y]],
59456
+ i: [[x, y]],
59457
+ o: [[x, y]],
59458
+ c: false
59459
+ };
59460
+ res.push(currentPath);
59461
+ continue;
59462
+ }
59463
+ if (!currentPath) {
59464
+ currentPath = {
59465
+ v: [[0, 0]],
59466
+ i: [[0, 0]],
59467
+ o: [[0, 0]],
59468
+ c: false
59469
+ };
59470
+ res.push(currentPath);
59471
+ }
59472
+ if (type === "L") {
59473
+ const x = values[0] || 0;
59474
+ const y = values[1] || 0;
59475
+ currentPath.v.push([x, y]);
59476
+ currentPath.i.push([x, y]);
59477
+ currentPath.o.push([x, y]);
59478
+ } else if (type === "C") {
59479
+ const outX = values[0] || 0;
59480
+ const outY = values[1] || 0;
59481
+ const inX2 = values[2] || 0;
59482
+ const inY2 = values[3] || 0;
59483
+ const x2 = values[4] || 0;
59484
+ const y2 = values[5] || 0;
59485
+ currentPath.o[currentPath.o.length - 1] = [outX, outY];
59486
+ currentPath.v.push([x2, y2]);
59487
+ currentPath.i.push([inX2, inY2]);
59488
+ currentPath.o.push([x2, y2]);
59489
+ } else if (type === "Z" || type === "z") {
59490
+ currentPath.c = true;
59491
+ } else {
59492
+ console.warn('Unsupported path command "' + type + '"');
59493
+ }
59494
+ }
59495
+ return res;
59496
+ }
59497
+ function extractPathData(str) {
59498
+ if (str.startsWith("path(") && str.endsWith(")")) {
59499
+ return str.slice(5, -1);
59500
+ }
59501
+ if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str)) {
59502
+ return str;
59503
+ }
59504
+ return void 0;
59505
+ }
59506
+ function isPathString(value) {
59507
+ return typeof value === "string" && extractPathData(value) !== void 0;
59508
+ }
59509
+ function normalizePathValue(value) {
59510
+ if (value && typeof value === "object" && typeof value.path === "string") {
59511
+ const d = extractPathData(value.path);
59512
+ return d ? { paths: parseSvgPathToBezier(d) } : value;
59513
+ }
59514
+ if (value && typeof value === "object" && "paths" in value) {
59515
+ const pathsArray = value.paths;
59516
+ if (Array.isArray(pathsArray) && pathsArray.length > 0) {
59517
+ if (isPathString(pathsArray[0])) {
59518
+ const paths = [];
59519
+ for (const pathStr2 of pathsArray) {
59520
+ const d = extractPathData(pathStr2);
59521
+ if (d) {
59522
+ paths.push(...parseSvgPathToBezier(d));
59523
+ }
59524
+ }
59525
+ return { paths };
58646
59526
  }
58647
- if (key === "rotate") value = value + "deg";
58648
- propsCopy["transform"] = key + "(" + value + ")";
58649
- } else if (value !== void 0 && value !== null) {
58650
- propsCopy[key] = String(value);
58651
59527
  }
59528
+ return value;
59529
+ }
59530
+ if (Array.isArray(value)) {
59531
+ if (value.length > 0 && isPathString(value[0])) {
59532
+ const paths = [];
59533
+ for (const pathStr2 of value) {
59534
+ const d = extractPathData(pathStr2);
59535
+ if (d) {
59536
+ paths.push(...parseSvgPathToBezier(d));
59537
+ }
59538
+ }
59539
+ return { paths };
59540
+ }
59541
+ return { paths: value };
59542
+ }
59543
+ if (isPathString(value)) {
59544
+ const d = extractPathData(value);
59545
+ return { paths: parseSvgPathToBezier(d) };
59546
+ }
59547
+ return value;
59548
+ }
59549
+ function resolveEasing(easing, defs) {
59550
+ var _a;
59551
+ if (!easing) return void 0;
59552
+ if (Array.isArray(easing)) {
59553
+ return easing;
59554
+ }
59555
+ if ((_a = defs == null ? void 0 : defs.easings) == null ? void 0 : _a[easing]) {
59556
+ return defs.easings[easing];
59557
+ }
59558
+ console.warn("Unknown easing name: " + easing);
59559
+ return void 0;
59560
+ }
59561
+ function resolveAnimation(animRef, defs) {
59562
+ var _a;
59563
+ if (typeof animRef === "string") {
59564
+ const resolved = (_a = defs == null ? void 0 : defs.animations) == null ? void 0 : _a[animRef];
59565
+ if (!resolved) {
59566
+ console.warn("Unknown animation name: " + animRef);
59567
+ }
59568
+ return resolved;
59569
+ }
59570
+ return animRef;
59571
+ }
59572
+ function resolveElementAnimation(animate, defs) {
59573
+ if (!animate) return [];
59574
+ const results = [];
59575
+ if (typeof animate === "string") {
59576
+ const resolved = resolveAnimation(animate, defs);
59577
+ if (resolved) results.push(resolved);
59578
+ } else if (Array.isArray(animate)) {
59579
+ for (const item of animate) {
59580
+ const resolved = resolveAnimation(item, defs);
59581
+ if (resolved) results.push(resolved);
59582
+ }
59583
+ } else {
59584
+ results.push(animate);
59585
+ }
59586
+ return results;
59587
+ }
59588
+ function interpolateValue(propName, a, b, t) {
59589
+ var _a, _b;
59590
+ if (propName === "d") {
59591
+ const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
59592
+ const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
59593
+ return { paths: interpolateBeziers(aPaths, bPaths, t) };
59594
+ }
59595
+ if (COLOUR_ATTR_NAMES.has(propName)) {
59596
+ return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
59597
+ }
59598
+ if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
59599
+ return interpolateTransformParts(a, b, t);
59600
+ }
59601
+ if (propName === "rotate" && typeof a === "number" && typeof b === "number") {
59602
+ return interpolateNum(a, b, t);
59603
+ }
59604
+ if (TRANSFORM_FN_NAMES.has(propName) || propName === "stroke-dasharray" || propName === "strokeDasharray") {
59605
+ return interpolateVec(a || [], b || [], t);
59606
+ }
59607
+ return interpolateNum(+(a || 0), +(b || 0), t);
59608
+ }
59609
+ function interpolateTransformParts(a, b, t) {
59610
+ const keys = /* @__PURE__ */ new Set([...Object.keys(a != null ? a : {}), ...Object.keys(b != null ? b : {})]);
59611
+ const out = {};
59612
+ for (const k of keys) {
59613
+ const av = a == null ? void 0 : a[k];
59614
+ const bv = b == null ? void 0 : b[k];
59615
+ if (k === "rotate") {
59616
+ out[k] = interpolateNum(+(av != null ? av : 0), +(bv != null ? bv : 0), t);
59617
+ } else if (k === "translate" || k === "scale" || k === "origin") {
59618
+ const fallback = k === "scale" ? [1, 1] : [0, 0];
59619
+ out[k] = interpolateVec(av || fallback, bv || fallback, t);
59620
+ } else {
59621
+ out[k] = bv != null ? bv : av;
59622
+ }
59623
+ }
59624
+ return out;
59625
+ }
59626
+ function expandLoopKeyframes(propName, keyframes, loop, duration) {
59627
+ var _a, _b, _c, _d, _e;
59628
+ const totalIntervals = keyframes.length - 1;
59629
+ const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
59630
+ let segKfs;
59631
+ if (loop.before) {
59632
+ segKfs = keyframes.slice(0, segCount + 1);
59633
+ } else {
59634
+ segKfs = keyframes.slice(totalIntervals - segCount);
59635
+ }
59636
+ const firstT = (_b = keyframes[0].t) != null ? _b : 0;
59637
+ const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
59638
+ let fillStart, fillEnd;
59639
+ if (loop.before) {
59640
+ fillStart = 0;
59641
+ fillEnd = firstT;
59642
+ } else {
59643
+ fillStart = lastT;
59644
+ fillEnd = duration;
59645
+ }
59646
+ const fillDuration = fillEnd - fillStart;
59647
+ if (fillDuration <= 0) return keyframes;
59648
+ const segStartT = (_d = segKfs[0].t) != null ? _d : 0;
59649
+ const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
59650
+ const segDuration = segEndT - segStartT;
59651
+ if (segDuration <= 0) return keyframes;
59652
+ const template = segKfs.map((kf) => {
59653
+ var _a2, _b2;
59654
+ return {
59655
+ relT: (kf.t - segStartT) / segDuration,
59656
+ v: kf.v,
59657
+ e: kf.e,
59658
+ tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
59659
+ tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
59660
+ };
59661
+ });
59662
+ const fullReps = Math.floor(fillDuration / segDuration);
59663
+ const remainder = fillDuration - fullReps * segDuration;
59664
+ const partialFraction = remainder / segDuration;
59665
+ const looped = [];
59666
+ function appendRep(repStart, isReversed, partial) {
59667
+ let entries;
59668
+ if (isReversed) {
59669
+ entries = [];
59670
+ for (let i = template.length - 1; i >= 0; i--) {
59671
+ entries.push({
59672
+ relT: 1 - template[i].relT,
59673
+ v: template[i].v,
59674
+ // Easing for reversed transition: use reversed easing from the forward "from" keyframe
59675
+ e: i > 0 ? reverseEasing(template[i - 1].e) : void 0,
59676
+ // Reversed traversal swaps each vertex's in/out spatial tangents
59677
+ // (geometry is identical, walked backwards), so curvature and
59678
+ // auto-orientation survive the reversed rep.
59679
+ tangentIn: template[i].tangentOut,
59680
+ tangentOut: template[i].tangentIn
59681
+ });
59682
+ }
59683
+ } else {
59684
+ entries = template;
59685
+ }
59686
+ const cutRelT = partial !== void 0 ? partial : 1;
59687
+ for (let i = 0; i < entries.length; i++) {
59688
+ const entry = entries[i];
59689
+ if (entry.relT > cutRelT + 1e-9) {
59690
+ const prev = entries[i - 1];
59691
+ const intervalSpan = entry.relT - prev.relT;
59692
+ const localFrac = (cutRelT - prev.relT) / intervalSpan;
59693
+ const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
59694
+ const cutValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
59695
+ const { left: leftEasing } = splitEasing(prev.e, localFrac);
59696
+ if (looped.length > 0 && prev.relT <= cutRelT) {
59697
+ looped[looped.length - 1].e = leftEasing;
59698
+ }
59699
+ looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
59700
+ return;
59701
+ }
59702
+ const pushed = {
59703
+ t: repStart + entry.relT * segDuration,
59704
+ v: entry.v,
59705
+ e: i < entries.length - 1 ? entry.e : void 0
59706
+ };
59707
+ if (entry.tangentIn) pushed.tangentIn = entry.tangentIn;
59708
+ if (entry.tangentOut) pushed.tangentOut = entry.tangentOut;
59709
+ looped.push(pushed);
59710
+ }
59711
+ }
59712
+ function appendRepTail(repStart, isReversed, tailFraction) {
59713
+ let entries;
59714
+ if (isReversed) {
59715
+ entries = [];
59716
+ for (let i = template.length - 1; i >= 0; i--) {
59717
+ entries.push({
59718
+ relT: 1 - template[i].relT,
59719
+ v: template[i].v,
59720
+ e: i > 0 ? reverseEasing(template[i - 1].e) : void 0,
59721
+ tangentIn: template[i].tangentOut,
59722
+ tangentOut: template[i].tangentIn
59723
+ });
59724
+ }
59725
+ } else {
59726
+ entries = template;
59727
+ }
59728
+ const startRelT = 1 - tailFraction;
59729
+ for (let i = 0; i < entries.length; i++) {
59730
+ const entry = entries[i];
59731
+ if (entry.relT < startRelT - 1e-9) continue;
59732
+ const prev = entries[i - 1];
59733
+ if (prev && prev.relT < startRelT - 1e-9 && entry.relT > startRelT + 1e-9) {
59734
+ const intervalSpan = entry.relT - prev.relT;
59735
+ const localFrac = (startRelT - prev.relT) / intervalSpan;
59736
+ const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
59737
+ const startValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
59738
+ const { right: rightEasing } = splitEasing(prev.e, localFrac);
59739
+ looped.push({ t: repStart, v: startValue, e: rightEasing });
59740
+ }
59741
+ const pushed = {
59742
+ t: repStart + (entry.relT - startRelT) * segDuration,
59743
+ v: entry.v,
59744
+ e: i < entries.length - 1 ? entry.e : void 0
59745
+ };
59746
+ if (entry.tangentIn) pushed.tangentIn = entry.tangentIn;
59747
+ if (entry.tangentOut) pushed.tangentOut = entry.tangentOut;
59748
+ looped.push(pushed);
59749
+ }
59750
+ }
59751
+ if (loop.before) {
59752
+ if (partialFraction > 1e-9) {
59753
+ const isReversed = !!loop.alternate && fullReps % 2 === 0;
59754
+ appendRepTail(fillStart, isReversed, partialFraction);
59755
+ }
59756
+ for (let rep = 0; rep < fullReps; rep++) {
59757
+ const distFromBoundary = fullReps - 1 - rep;
59758
+ const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
59759
+ const repStart = fillStart + remainder + rep * segDuration;
59760
+ appendRep(repStart, isReversed);
59761
+ }
59762
+ } else {
59763
+ for (let rep = 0; rep < fullReps; rep++) {
59764
+ const isReversed = !!loop.alternate && rep % 2 === 0;
59765
+ const repStart = fillStart + rep * segDuration;
59766
+ appendRep(repStart, isReversed);
59767
+ }
59768
+ if (partialFraction > 1e-9) {
59769
+ const isReversed = !!loop.alternate && fullReps % 2 === 0;
59770
+ const repStart = fillStart + fullReps * segDuration;
59771
+ appendRep(repStart, isReversed, partialFraction);
59772
+ }
59773
+ }
59774
+ if (loop.before) {
59775
+ return [...looped, ...keyframes];
59776
+ } else {
59777
+ return [...keyframes, ...looped];
59778
+ }
59779
+ }
59780
+ function normalizeKeyframes(propName, propAnim, duration, defs) {
59781
+ var _a, _b, _c, _d, _e, _f, _g;
59782
+ const keyframes = propAnim.keyframes || propAnim.kfs || [];
59783
+ const normalized = [];
59784
+ for (const kf of keyframes) {
59785
+ const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
59786
+ let value = (_c = kf.value) != null ? _c : kf.v;
59787
+ const easing = (_d = kf.easing) != null ? _d : kf.e;
59788
+ if (propName === "d") {
59789
+ value = normalizePathValue(value);
59790
+ }
59791
+ const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
59792
+ if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
59793
+ value = (_e = parseColor(value)) != null ? _e : value;
59794
+ }
59795
+ const normKf = {
59796
+ t: timePct,
59797
+ v: value,
59798
+ e: resolveEasing(easing, defs)
59799
+ };
59800
+ const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
59801
+ const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
59802
+ if (tIn) normKf.tangentIn = tIn;
59803
+ if (tOut) normKf.tangentOut = tOut;
59804
+ normalized.push(normKf);
58652
59805
  }
58653
- return propsCopy;
59806
+ normalized.sort((a, b) => {
59807
+ var _a2, _b2;
59808
+ return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
59809
+ });
59810
+ const loopRaw = propAnim.loop;
59811
+ const loop = loopRaw === true ? {} : loopRaw || void 0;
59812
+ if (loop && normalized.length >= 2) {
59813
+ return expandLoopKeyframes(propName, normalized, loop, duration);
59814
+ }
59815
+ return normalized;
58654
59816
  }
58655
- function renderNode(node, defs) {
58656
- if (!node) return null;
58657
- const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
58658
- const nodeDefs = getDefs(node) || defs;
58659
- const resolvedStyle = resolveStyle(style, nodeDefs);
58660
- let childElements;
58661
- if (children) {
58662
- for (const ch of children) {
58663
- const child = renderNode(ch, nodeDefs);
58664
- if (child) {
58665
- if (!childElements) childElements = [];
58666
- childElements.push(child);
59817
+ function mergeAnimationDefinitions(animations) {
59818
+ const merged = {};
59819
+ for (const anim of animations) {
59820
+ for (const [prop, propAnim] of Object.entries(anim)) {
59821
+ merged[prop] = propAnim;
59822
+ }
59823
+ }
59824
+ return merged;
59825
+ }
59826
+ function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
59827
+ var _a;
59828
+ const loopRaw = propAnim.loop;
59829
+ if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
59830
+ const loop = loopRaw === true ? {} : loopRaw;
59831
+ const rawKfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
59832
+ if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
59833
+ const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
59834
+ const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
59835
+ const kfs = rawKfs.map((kf) => {
59836
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
59837
+ const t = (_a2 = kf.t) != null ? _a2 : kf.time;
59838
+ let v = (_b = kf.v) != null ? _b : kf.value;
59839
+ if (propName === "d") v = normalizePathValue(v);
59840
+ if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
59841
+ const e = (_d = kf.e) != null ? _d : kf.easing;
59842
+ const out2 = { t, v, e };
59843
+ if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
59844
+ if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
59845
+ return out2;
59846
+ });
59847
+ const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
59848
+ const out = { kfs: expanded };
59849
+ if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
59850
+ return out;
59851
+ }
59852
+ function materialiseInternalLoopsInTree(root, duration) {
59853
+ const ret = walkAndMaterialiseLoops(root, duration);
59854
+ return ret != null ? ret : root;
59855
+ }
59856
+ function walkAndMaterialiseLoops(node, duration) {
59857
+ let newChildren;
59858
+ if (node.children) {
59859
+ for (let i = 0; i < node.children.length; i++) {
59860
+ const ret = walkAndMaterialiseLoops(node.children[i], duration);
59861
+ if (ret !== null) {
59862
+ if (!newChildren) newChildren = node.children.slice();
59863
+ newChildren[i] = ret;
58667
59864
  }
58668
59865
  }
58669
59866
  }
58670
- return createElement(
58671
- type || "g",
58672
- getNormalizedProps(props),
58673
- resolvedStyle,
58674
- childElements,
58675
- props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
58676
- );
59867
+ let newAnimate;
59868
+ const animBucket = node.animate;
59869
+ if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
59870
+ const animDef = animBucket;
59871
+ for (const propName of Object.keys(animDef)) {
59872
+ const propAnim = animDef[propName];
59873
+ const materialised = materialiseInternalLoopsInPropAnim(propName, propAnim, duration);
59874
+ if (materialised !== propAnim) {
59875
+ if (!newAnimate) newAnimate = __spreadValues({}, animDef);
59876
+ newAnimate[propName] = materialised;
59877
+ }
59878
+ }
59879
+ }
59880
+ if (!newChildren && !newAnimate) return null;
59881
+ const cloned = __spreadValues({}, node);
59882
+ if (newChildren) cloned.children = newChildren;
59883
+ if (newAnimate) cloned.animate = newAnimate;
59884
+ return cloned;
58677
59885
  }
58678
- function setupAnimationTriggers(api, config) {
58679
- const { startOn, outAction = "continue", scrollIntoViewThreshold = 0.5 } = config;
58680
- const root = api.getRootElement();
58681
- if (!root) {
58682
- console.warn("setupAnimationTriggers: No root element found for animation.");
58683
- return api;
59886
+ var _elementIdCounter = 0;
59887
+ function generateElementId() {
59888
+ return "_px_el_" + ++_elementIdCounter;
59889
+ }
59890
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.webapi) {
59891
+ const normalized = {};
59892
+ for (const [propName, propAnim] of Object.entries(animDef)) {
59893
+ const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
59894
+ if (normalizedKfs.length > 0) {
59895
+ const out = { kfs: normalizedKfs };
59896
+ if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
59897
+ if (propAnim.loop !== void 0) out.loop = propAnim.loop;
59898
+ normalized[propName] = engine === PxAnimatorEngine.webapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
59899
+ }
58684
59900
  }
58685
- const start = () => {
58686
- api.play();
59901
+ return normalized;
59902
+ }
59903
+ function getNormalisedBindings(doc, engine = PxAnimatorEngine.webapi) {
59904
+ const animatorConfig = getAnimatorConfig(doc) || {};
59905
+ const defs = getDefs(doc);
59906
+ const duration = animatorConfig.duration || 1e3;
59907
+ const bindings = [];
59908
+ const processAnimation = (id, animate) => {
59909
+ if (!animate) return null;
59910
+ const animDefs = resolveElementAnimation(animate, defs);
59911
+ if (animDefs.length === 0) return null;
59912
+ const merged = mergeAnimationDefinitions(animDefs);
59913
+ const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
59914
+ if (Object.keys(normalizedAnim).length === 0) return null;
59915
+ return {
59916
+ id,
59917
+ animate: normalizedAnim
59918
+ };
58687
59919
  };
58688
- const handleEndAction = () => {
58689
- switch (outAction) {
58690
- case "pause":
58691
- api.pause();
58692
- break;
58693
- case "reset":
58694
- api.cancel();
58695
- break;
58696
- case "reverse":
58697
- api.play();
58698
- break;
58699
- case "continue":
58700
- default:
58701
- break;
59920
+ const docBindings = getBindings(doc);
59921
+ if (docBindings) {
59922
+ for (const binding of docBindings) {
59923
+ const normalized = processAnimation(binding.id, binding.animate);
59924
+ if (normalized) bindings.push(normalized);
58702
59925
  }
58703
- };
58704
- switch (startOn) {
58705
- case "load": {
58706
- const startHandler = () => start();
58707
- if (document.readyState === "complete") {
58708
- startHandler();
58709
- } else {
58710
- window.addEventListener("load", startHandler, { once: true });
59926
+ }
59927
+ const processNode = (node) => {
59928
+ const inlineAnim = node.animate;
59929
+ if (inlineAnim && Object.keys(inlineAnim).length > 0) {
59930
+ const nodeId = node.id || generateElementId();
59931
+ node.id = nodeId;
59932
+ const normalized = processAnimation(nodeId, inlineAnim);
59933
+ if (normalized) bindings.push(normalized);
59934
+ }
59935
+ if (node.children) {
59936
+ for (let i = 0; i < node.children.length; i++) {
59937
+ processNode(node.children[i]);
58711
59938
  }
59939
+ }
59940
+ };
59941
+ if (doc.children) {
59942
+ for (let i = 0; i < doc.children.length; i++) {
59943
+ processNode(doc.children[i]);
59944
+ }
59945
+ }
59946
+ return bindings;
59947
+ }
59948
+ function getKeyframesPair(keyframes, progress) {
59949
+ var _a, _b;
59950
+ let prevKf = keyframes[0];
59951
+ let nextKf = keyframes[keyframes.length - 1];
59952
+ for (let j = 0; j < keyframes.length - 1; j++) {
59953
+ const aOff = (_a = keyframes[j].t) != null ? _a : 0;
59954
+ const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
59955
+ if (aOff <= progress && progress <= bOff) {
59956
+ prevKf = keyframes[j];
59957
+ nextKf = keyframes[j + 1];
58712
59958
  break;
58713
59959
  }
58714
- case "mouseOver": {
58715
- const mouseOverHandler = () => start();
58716
- const mouseOutHandler = () => handleEndAction();
58717
- root.addEventListener("mouseenter", mouseOverHandler);
58718
- root.addEventListener("mouseleave", mouseOutHandler);
58719
- break;
59960
+ }
59961
+ return { prevKf, nextKf };
59962
+ }
59963
+ function calcPropertyValue(propName, propAnim, progress) {
59964
+ var _a, _b, _c, _d, _e, _f, _g;
59965
+ const keyframes = propAnim.kfs || propAnim.keyframes || [];
59966
+ if (keyframes.length === 0) return null;
59967
+ const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
59968
+ let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
59969
+ localProgress = clamp(localProgress, 0, 1);
59970
+ const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
59971
+ if (easing && Array.isArray(easing)) {
59972
+ try {
59973
+ localProgress = cubicBezier(easing)(localProgress);
59974
+ } catch (e) {
59975
+ }
59976
+ }
59977
+ let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
59978
+ let cssValue = null;
59979
+ const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
59980
+ const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
59981
+ if (cssAttrName === "d") {
59982
+ const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
59983
+ const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
59984
+ cssValue = interpolateBeziers(
59985
+ prevPaths,
59986
+ nextPaths,
59987
+ localProgress
59988
+ ).map((bz) => bezierToSvgPath(bz)).join("");
59989
+ } else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
59990
+ cssValue = toRGBA(interpolateColor(
59991
+ prevV || [0, 0, 0, 1],
59992
+ nextV || [0, 0, 0, 1],
59993
+ localProgress
59994
+ ));
59995
+ cssAttrName = propName;
59996
+ } else if (cssAttrName === "stroke-dasharray") {
59997
+ cssValue = interpolateVec(
59998
+ prevV || [],
59999
+ nextV || [],
60000
+ localProgress
60001
+ ).join(" ");
60002
+ cssAttrName = propName;
60003
+ } else if (cssAttrName === "transform" && prevV !== null && typeof prevV === "object" && !Array.isArray(prevV)) {
60004
+ const partKeys = /* @__PURE__ */ new Set([
60005
+ ...prevV ? Object.keys(prevV) : [],
60006
+ ...nextV ? Object.keys(nextV) : []
60007
+ ]);
60008
+ const partsResult = {};
60009
+ for (const partKey of partKeys) {
60010
+ const prevPart = prevV == null ? void 0 : prevV[partKey];
60011
+ const nextPart = nextV == null ? void 0 : nextV[partKey];
60012
+ if (partKey === "rotate") {
60013
+ partsResult.rotate = interpolateNum(+(prevPart != null ? prevPart : 0), +(nextPart != null ? nextPart : 0), localProgress);
60014
+ } else if (partKey === "translate" || partKey === "scale" || partKey === "origin") {
60015
+ const fallback = partKey === "scale" ? [1, 1] : [0, 0];
60016
+ const interp = interpolateVec(prevPart || fallback, nextPart || fallback, localProgress);
60017
+ partsResult[partKey] = interp;
60018
+ }
60019
+ }
60020
+ if (propAnimIsMotionPath(propAnim)) {
60021
+ const prevTr = prevV.translate;
60022
+ const nextTr = nextV.translate;
60023
+ if (Array.isArray(prevTr) && Array.isArray(nextTr)) {
60024
+ const sample = evaluateMotionPathSegment(
60025
+ prevKf,
60026
+ nextKf,
60027
+ [+prevTr[0], +prevTr[1]],
60028
+ [+nextTr[0], +nextTr[1]],
60029
+ localProgress,
60030
+ !!propAnim.autoOrient
60031
+ );
60032
+ partsResult.translate = [sample.translate[0], sample.translate[1]];
60033
+ if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
60034
+ }
60035
+ }
60036
+ cssValue = composeTransformParts(partsResult, { withUnits: false });
60037
+ cssAttrName = "transform";
60038
+ } else if (cssAttrName === "translate") {
60039
+ const v = interpolateVec(
60040
+ prevV || [0, 0],
60041
+ nextV || [0, 0],
60042
+ localProgress
60043
+ );
60044
+ cssValue = "translate(" + v.join(",") + ")";
60045
+ cssAttrName = "transform";
60046
+ } else if (cssAttrName === "rotate") {
60047
+ const v = interpolateNum(
60048
+ +(prevV || 0),
60049
+ +(nextV || 0),
60050
+ localProgress
60051
+ );
60052
+ cssValue = "rotate(" + v + ")";
60053
+ cssAttrName = "transform";
60054
+ } else if (cssAttrName === "scale") {
60055
+ const v = interpolateVec(
60056
+ prevV || [1, 1],
60057
+ nextV || [1, 1],
60058
+ localProgress
60059
+ );
60060
+ cssValue = "scale(" + v.join(",") + ")";
60061
+ cssAttrName = "transform";
60062
+ } else {
60063
+ const num2 = interpolateNum(
60064
+ +(prevV || 0),
60065
+ +(nextV || 0),
60066
+ localProgress
60067
+ );
60068
+ cssValue = num2;
60069
+ }
60070
+ if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
60071
+ cssValue = cssValue * 100 + "%";
60072
+ }
60073
+ return { k: cssAttrName, v: cssValue === null ? "" : "" + cssValue };
60074
+ }
60075
+ function calcAnimationValues(animDef, progress) {
60076
+ const result = {};
60077
+ for (const [propName, propAnim] of Object.entries(animDef)) {
60078
+ const computed3 = calcPropertyValue(propName, propAnim, progress);
60079
+ if (computed3) {
60080
+ result[computed3.k] = computed3.v;
60081
+ }
60082
+ }
60083
+ return result;
60084
+ }
60085
+ function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
60086
+ if (!trimPath) return node;
60087
+ const trimAllAsOne = !!trimPath.trimAllAsOne;
60088
+ const leafEntries = [];
60089
+ const measure = (n) => {
60090
+ if (Array.isArray(n.children) && n.children.length > 0) {
60091
+ for (const ch of n.children) measure(ch);
60092
+ return;
58720
60093
  }
58721
- case "click": {
58722
- const clickHandler = () => {
58723
- if (api.isPlaying()) {
58724
- handleEndAction();
58725
- } else {
58726
- start();
58727
- }
58728
- };
58729
- root.addEventListener("click", clickHandler);
58730
- break;
60094
+ const d = typeof n.d === "string" ? n.d : rectToPathD(n);
60095
+ if (d === void 0) return;
60096
+ const subpaths = parseSvgPathToBezier(d);
60097
+ if (!subpaths.length) return;
60098
+ const entry = { leaf: n, subpaths: [] };
60099
+ for (const sp of subpaths) {
60100
+ const lengthPx = pxBezierPathLength(sp);
60101
+ entry.subpaths.push({ subpath: sp, lengthPx, startOffsetPx: 0 });
58731
60102
  }
58732
- case "scrollIntoView": {
58733
- const observer = new IntersectionObserver(
58734
- (entries) => {
58735
- entries.forEach((entry) => {
58736
- if (entry.isIntersecting && entry.intersectionRatio >= scrollIntoViewThreshold) {
58737
- start();
58738
- } else {
58739
- handleEndAction();
58740
- }
58741
- });
58742
- },
58743
- { threshold: scrollIntoViewThreshold }
58744
- );
58745
- observer.observe(root);
58746
- break;
60103
+ leafEntries.push(entry);
60104
+ };
60105
+ measure(node);
60106
+ if (!leafEntries.length) return node;
60107
+ let acc = 0;
60108
+ const iterOrder = trimAllAsOne ? [...leafEntries].reverse() : leafEntries;
60109
+ for (const entry of iterOrder) {
60110
+ for (const sp of entry.subpaths) {
60111
+ if (!trimAllAsOne) acc = 0;
60112
+ sp.startOffsetPx = acc;
60113
+ acc += sp.lengthPx;
58747
60114
  }
58748
- case "programmatic":
58749
- break;
58750
60115
  }
58751
- return api;
58752
- }
58753
- function propAnimIsMotionPath(anim) {
58754
- var _a;
58755
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
58756
- if (!Array.isArray(kfs)) return false;
58757
- if (anim.autoOrient) return true;
58758
- for (const kf of kfs) {
58759
- if (kf.tangentIn || kf.tangentOut) return true;
60116
+ const chainLengthPx = acc;
60117
+ if (trimAllAsOne && chainLengthPx < 1e-3) return node;
60118
+ const offsetReadRaw = readAnimatable(trimPath.offset);
60119
+ const offsetRead = offsetReadRaw.kind === "absent" ? { kind: "static", value: 0 } : offsetReadRaw;
60120
+ const rangeReadRaw = readRangeWithCrossings(trimPath.range);
60121
+ const rangeRead = rangeReadRaw.kind === "absent" ? { kind: "static", value: [0, 1] } : rangeReadRaw;
60122
+ const offsetValues = readScalarValues(offsetRead);
60123
+ const minOffset = offsetValues.length ? Math.min(...offsetValues) : 0;
60124
+ const maxOffset = offsetValues.length ? Math.max(...offsetValues) : 0;
60125
+ const minMaxOffset = [minOffset, maxOffset];
60126
+ if (leafEntries.length === 1 && leafEntries[0].leaf === node && leafEntries[0].subpaths.length === 1) {
60127
+ const entry = leafEntries[0];
60128
+ const sp = entry.subpaths[0];
60129
+ const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
60130
+ if (pathLengthPx < 1e-3) return node;
60131
+ const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
60132
+ return collapseLeafWithTrim(entry.leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead);
58760
60133
  }
58761
- return false;
60134
+ const replacements = /* @__PURE__ */ new Map();
60135
+ for (const entry of leafEntries) {
60136
+ const newChildren = [];
60137
+ for (const sp of entry.subpaths) {
60138
+ const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
60139
+ if (pathLengthPx < 1e-3) continue;
60140
+ const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
60141
+ newChildren.push(...buildSubpathNodes(entry.leaf, sp.subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx));
60142
+ }
60143
+ replacements.set(entry.leaf, wrapLeafAsGroup(entry.leaf, newChildren));
60144
+ }
60145
+ const swap = (n) => {
60146
+ const r = replacements.get(n);
60147
+ if (r) return r;
60148
+ if (Array.isArray(n.children) && n.children.length > 0) {
60149
+ return __spreadProps(__spreadValues({}, n), { children: n.children.map(swap) });
60150
+ }
60151
+ return n;
60152
+ };
60153
+ return swap(node);
58762
60154
  }
58763
- var _segmentCache = /* @__PURE__ */ new WeakMap();
58764
- function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
58765
- const existing = _segmentCache.get(prevKf);
58766
- if (existing) return existing;
58767
- const to = prevKf.tangentOut;
58768
- const ti = nextKf.tangentIn;
58769
- const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
58770
- const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
58771
- const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
58772
- const entry = {
58773
- P0: prevPos,
58774
- P1,
58775
- P2,
58776
- P3: nextPos,
58777
- lut,
58778
- totalArc: lut.ds[lut.ds.length - 1]
60155
+ function wrapLeafAsGroup(leaf, children) {
60156
+ const wrapper = __spreadProps(__spreadValues({}, leaf), { type: "g", children });
60157
+ delete wrapper.d;
60158
+ delete wrapper.strokeDasharray;
60159
+ delete wrapper.strokeDashoffset;
60160
+ delete wrapper.effects;
60161
+ return wrapper;
60162
+ }
60163
+ function buildSubpathNodes(leaf, subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx) {
60164
+ const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
60165
+ const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
60166
+ const dashOffsetAttr = computeAnimAttr(offsetRead, offsetToDashOffset);
60167
+ const dashArrayAttr = computeAnimAttr(rangeRead, rangeToDasharray);
60168
+ const strokeOpacityAttr = computeOpacityFromRange(rangeRead);
60169
+ const dStr = bezierToSvgPath(subpath);
60170
+ const base = makeBareSubpath(dStr);
60171
+ applyAttr(base, "strokeDasharray", dashArrayAttr);
60172
+ applyAttr(base, "strokeDashoffset", dashOffsetAttr);
60173
+ applyAttr(base, "strokeOpacity", strokeOpacityAttr);
60174
+ return [base];
60175
+ }
60176
+ function collapseLeafWithTrim(leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead) {
60177
+ const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
60178
+ const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
60179
+ const node = __spreadValues({}, leaf);
60180
+ delete node.effects;
60181
+ applyAttr(node, "strokeDasharray", computeAnimAttr(rangeRead, rangeToDasharray));
60182
+ applyAttr(node, "strokeDashoffset", computeAnimAttr(offsetRead, offsetToDashOffset));
60183
+ applyAttr(node, "strokeOpacity", computeOpacityFromRange(rangeRead));
60184
+ return node;
60185
+ }
60186
+ function makeBareSubpath(dStr) {
60187
+ return { type: "path", d: dStr };
60188
+ }
60189
+ var SMALL_PADDING_PX = 1;
60190
+ function makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset) {
60191
+ const [minIdx] = getOffsetIndexRange(minMaxOffset);
60192
+ return (offsetVal) => pathLengthPx * (-offsetVal - minIdx + startOffsetPct) + SMALL_PADDING_PX;
60193
+ }
60194
+ function makeRangeToDasharray(pathLengthPx, minMaxOffset) {
60195
+ const [minIdx, maxIdx] = getOffsetIndexRange(minMaxOffset);
60196
+ const repeats = maxIdx - minIdx + 1;
60197
+ return (rangeVal) => {
60198
+ const a = clamp(rangeVal[0], 0, 1);
60199
+ const b = clamp(rangeVal[1], 0, 1);
60200
+ const minR = Math.min(a, b);
60201
+ const maxR = Math.max(a, b);
60202
+ const out = [0];
60203
+ let gap = SMALL_PADDING_PX;
60204
+ for (let i = 0; i < repeats; i++) {
60205
+ out.push(gap + minR * pathLengthPx);
60206
+ out.push((maxR - minR) * pathLengthPx);
60207
+ gap = (1 - maxR) * pathLengthPx;
60208
+ }
60209
+ out.push(gap + SMALL_PADDING_PX);
60210
+ return out;
58779
60211
  };
58780
- _segmentCache.set(prevKf, entry);
58781
- return entry;
58782
60212
  }
58783
- function evaluateMotionPathSegment(prevKf, nextKf, prevPos, nextPos, localProgress, autoOrient) {
58784
- const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
58785
- const t = seg.totalArc === 0 ? localProgress : bezier2D_tForDistance(seg.lut, localProgress * seg.totalArc);
58786
- const point = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
58787
- if (!autoOrient) return { translate: point };
58788
- const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
58789
- const rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
58790
- return { translate: point, rotateDeg };
60213
+ function getOffsetIndexRange(minMaxOffset) {
60214
+ return [
60215
+ Math.floor(Math.min(-minMaxOffset[0], -minMaxOffset[1])),
60216
+ Math.ceil(Math.max(-minMaxOffset[0], -minMaxOffset[1]))
60217
+ ];
58791
60218
  }
58792
- function parsePathCommands(d) {
58793
- const tokens = d.split(/([MLCZmlcz]|[\s,]+)/).map((t) => t.trim()).filter((t) => t && t !== ",");
58794
- const commands = [];
58795
- let currentCommand = null;
58796
- for (const token of tokens) {
58797
- if (/[MLCZmlcz]/.test(token)) {
58798
- currentCommand = { type: token, values: [] };
58799
- commands.push(currentCommand);
58800
- } else if (currentCommand) {
58801
- const value = +token;
58802
- currentCommand.values.push(Number.isNaN(value) ? 0 : value);
58803
- }
60219
+ function readScalarValues(r) {
60220
+ var _a;
60221
+ if (r.kind === "absent") return [];
60222
+ if (r.kind === "static") return [r.value];
60223
+ const out = [];
60224
+ for (const kf of r.keyframes) {
60225
+ const v = (_a = kf.value) != null ? _a : kf.v;
60226
+ if (typeof v === "number") out.push(v);
58804
60227
  }
58805
- return commands;
60228
+ return out;
58806
60229
  }
58807
- function parseSvgPathToBezier(d) {
58808
- const res = [];
58809
- let currentPath;
58810
- const commands = parsePathCommands(d);
58811
- for (const command of commands) {
58812
- const type = command.type;
58813
- const values = command.values;
58814
- if (type === "M" || type === "m") {
58815
- const x = values[0] || 0;
58816
- const y = values[1] || 0;
58817
- currentPath = {
58818
- v: [[x, y]],
58819
- i: [[x, y]],
58820
- o: [[x, y]],
58821
- c: false
58822
- };
58823
- res.push(currentPath);
58824
- continue;
58825
- }
58826
- if (!currentPath) {
58827
- currentPath = {
58828
- v: [[0, 0]],
58829
- i: [[0, 0]],
58830
- o: [[0, 0]],
58831
- c: false
60230
+ function computeAnimAttr(read, map) {
60231
+ if (read.kind === "absent") return void 0;
60232
+ if (read.kind === "static") return { kind: "static", value: map(read.value) };
60233
+ return {
60234
+ kind: "animated",
60235
+ keyframes: read.keyframes.map((kf) => {
60236
+ var _a, _b, _c, _d;
60237
+ return {
60238
+ time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
60239
+ value: map((_c = kf.value) != null ? _c : kf.v),
60240
+ easing: (_d = kf.easing) != null ? _d : kf.e
58832
60241
  };
58833
- res.push(currentPath);
58834
- }
58835
- if (type === "L") {
58836
- const x = values[0] || 0;
58837
- const y = values[1] || 0;
58838
- currentPath.v.push([x, y]);
58839
- currentPath.i.push([x, y]);
58840
- currentPath.o.push([x, y]);
58841
- } else if (type === "C") {
58842
- const outX = values[0] || 0;
58843
- const outY = values[1] || 0;
58844
- const inX2 = values[2] || 0;
58845
- const inY2 = values[3] || 0;
58846
- const x2 = values[4] || 0;
58847
- const y2 = values[5] || 0;
58848
- currentPath.o[currentPath.o.length - 1] = [outX, outY];
58849
- currentPath.v.push([x2, y2]);
58850
- currentPath.i.push([inX2, inY2]);
58851
- currentPath.o.push([x2, y2]);
58852
- } else if (type === "Z" || type === "z") {
58853
- currentPath.c = true;
58854
- } else {
58855
- console.warn('Unsupported path command "' + type + '"');
58856
- }
58857
- }
58858
- return res;
60242
+ }),
60243
+ loop: read.loop
60244
+ };
58859
60245
  }
58860
- function extractPathData(str) {
58861
- if (str.startsWith("path(") && str.endsWith(")")) {
58862
- return str.slice(5, -1);
60246
+ function applyAttr(node, attrName, attr) {
60247
+ var _a, _b;
60248
+ if (!attr) return;
60249
+ if (attr.kind === "static") {
60250
+ node[attrName] = attr.value;
60251
+ return;
58863
60252
  }
58864
- if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str)) {
58865
- return str;
60253
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
60254
+ const animate = __spreadValues({}, prevAnimate || {});
60255
+ const block = { keyframes: attr.keyframes };
60256
+ if (attr.loop !== void 0) block.loop = attr.loop;
60257
+ animate[attrName] = block;
60258
+ node.animate = animate;
60259
+ const firstKf = attr.keyframes[0];
60260
+ if (firstKf && ((_a = firstKf.value) != null ? _a : firstKf.v) !== void 0) {
60261
+ node[attrName] = (_b = firstKf.value) != null ? _b : firstKf.v;
58866
60262
  }
58867
- return void 0;
58868
- }
58869
- function isPathString(value) {
58870
- return typeof value === "string" && extractPathData(value) !== void 0;
58871
60263
  }
58872
- function normalizePathValue(value) {
58873
- if (value && typeof value === "object" && typeof value.path === "string") {
58874
- const d = extractPathData(value.path);
58875
- return d ? { paths: parseSvgPathToBezier(d) } : value;
60264
+ var OPACITY_STEP_MS = 10;
60265
+ function computeOpacityFromRange(rangeRead) {
60266
+ var _a, _b, _c, _d, _e, _f;
60267
+ const hide = (v) => v[0] === v[1];
60268
+ if (rangeRead.kind === "absent") return void 0;
60269
+ if (rangeRead.kind === "static") return hide(rangeRead.value) ? { kind: "static", value: 0 } : void 0;
60270
+ const kfs = rangeRead.keyframes;
60271
+ let anyHide = false;
60272
+ let allHide = true;
60273
+ for (const kf of kfs) {
60274
+ if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
60275
+ else allHide = false;
58876
60276
  }
58877
- if (value && typeof value === "object" && "paths" in value) {
58878
- const pathsArray = value.paths;
58879
- if (Array.isArray(pathsArray) && pathsArray.length > 0) {
58880
- if (isPathString(pathsArray[0])) {
58881
- const paths = [];
58882
- for (const pathStr2 of pathsArray) {
58883
- const d = extractPathData(pathStr2);
58884
- if (d) {
58885
- paths.push(...parseSvgPathToBezier(d));
58886
- }
58887
- }
58888
- return { paths };
58889
- }
60277
+ if (!anyHide) return void 0;
60278
+ if (allHide) return { kind: "static", value: 0 };
60279
+ const out = [];
60280
+ for (let i = 0; i < kfs.length; i++) {
60281
+ const kf = kfs[i];
60282
+ const prevKf = i > 0 ? kfs[i - 1] : void 0;
60283
+ const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
60284
+ const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
60285
+ const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
60286
+ const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
60287
+ const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
60288
+ if (prevHide && !nextHide) {
60289
+ out.push({ time: t, value: 0 });
60290
+ out.push({ time: t + OPACITY_STEP_MS, value: 1 });
60291
+ } else if (!prevHide && nextHide) {
60292
+ out.push({ time: t - OPACITY_STEP_MS, value: 1 });
60293
+ out.push({ time: t, value: 0 });
58890
60294
  }
58891
- return value;
58892
60295
  }
58893
- if (Array.isArray(value)) {
58894
- if (value.length > 0 && isPathString(value[0])) {
58895
- const paths = [];
58896
- for (const pathStr2 of value) {
58897
- const d = extractPathData(pathStr2);
58898
- if (d) {
58899
- paths.push(...parseSvgPathToBezier(d));
58900
- }
60296
+ if (out.length <= 1) return void 0;
60297
+ return { kind: "animated", keyframes: out };
60298
+ }
60299
+ function readRangeWithCrossings(raw) {
60300
+ const r = readAnimatable(raw);
60301
+ if (r.kind !== "animated") return r;
60302
+ const kfs = r.keyframes.map((kf) => {
60303
+ var _a, _b, _c, _d;
60304
+ return {
60305
+ time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
60306
+ value: (_c = kf.value) != null ? _c : kf.v,
60307
+ easing: (_d = kf.easing) != null ? _d : kf.e
60308
+ };
60309
+ });
60310
+ const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
60311
+ if (!hasReverse) {
60312
+ return {
60313
+ kind: "animated",
60314
+ keyframes: kfs.map((kf) => ({ time: kf.time, value: kf.value, easing: kf.easing }))
60315
+ };
60316
+ }
60317
+ const crossingTimes = [];
60318
+ for (let i = 1; i < kfs.length; i++) {
60319
+ const prev = kfs[i - 1];
60320
+ const cur = kfs[i];
60321
+ const dPrev = prev.value[1] - prev.value[0];
60322
+ const dCur = cur.value[1] - cur.value[0];
60323
+ if (dPrev * dCur < 0) {
60324
+ const t = bisectionForRangeCrossing(prev, cur);
60325
+ if (t !== null && t > prev.time && t < cur.time) {
60326
+ crossingTimes.push(Math.round(t));
58901
60327
  }
58902
- return { paths };
58903
60328
  }
58904
- return { paths: value };
58905
60329
  }
58906
- if (isPathString(value)) {
58907
- const d = extractPathData(value);
58908
- return { paths: parseSvgPathToBezier(d) };
58909
- }
58910
- return value;
58911
- }
58912
- function resolveEasing(easing, defs) {
58913
- var _a;
58914
- if (!easing) return void 0;
58915
- if (Array.isArray(easing)) {
58916
- return easing;
60330
+ const uniqueTs = Array.from(new Set(crossingTimes)).sort((a, b) => a - b);
60331
+ const out = [];
60332
+ let j = 0;
60333
+ for (const kf of kfs) {
60334
+ while (j < uniqueTs.length && uniqueTs[j] < kf.time) {
60335
+ const t = uniqueTs[j++];
60336
+ const v2 = interpolateRangeAt(kfs, t);
60337
+ const m = (v2[0] + v2[1]) / 2;
60338
+ out.push({ time: t, value: [m, m] });
60339
+ }
60340
+ const v = kf.value[0] > kf.value[1] ? [kf.value[1], kf.value[0]] : kf.value;
60341
+ out.push({ time: kf.time, value: v, easing: kf.easing });
58917
60342
  }
58918
- if ((_a = defs == null ? void 0 : defs.easings) == null ? void 0 : _a[easing]) {
58919
- return defs.easings[easing];
60343
+ while (j < uniqueTs.length) {
60344
+ const t = uniqueTs[j++];
60345
+ const v = interpolateRangeAt(kfs, t);
60346
+ const m = (v[0] + v[1]) / 2;
60347
+ out.push({ time: t, value: [m, m] });
58920
60348
  }
58921
- console.warn("Unknown easing name: " + easing);
58922
- return void 0;
60349
+ return { kind: "animated", keyframes: out };
58923
60350
  }
58924
- function resolveAnimation(animRef, defs) {
58925
- var _a;
58926
- if (typeof animRef === "string") {
58927
- const resolved = (_a = defs == null ? void 0 : defs.animations) == null ? void 0 : _a[animRef];
58928
- if (!resolved) {
58929
- console.warn("Unknown animation name: " + animRef);
60351
+ function bisectionForRangeCrossing(prev, cur) {
60352
+ const f = (t) => {
60353
+ const a = (t - prev.time) / (cur.time - prev.time);
60354
+ const v0 = prev.value[0] + (cur.value[0] - prev.value[0]) * a;
60355
+ const v1 = prev.value[1] + (cur.value[1] - prev.value[1]) * a;
60356
+ return v1 - v0;
60357
+ };
60358
+ let lo = prev.time, hi = cur.time;
60359
+ let fLo = f(lo);
60360
+ if (fLo === 0) return lo;
60361
+ const fHi = f(hi);
60362
+ if (fHi === 0) return hi;
60363
+ if (fLo * fHi > 0) return null;
60364
+ for (let i = 0; i < 100; i++) {
60365
+ const mid = (lo + hi) / 2;
60366
+ const fMid = f(mid);
60367
+ if (fMid === 0 || Math.abs(hi - lo) < 1e-4) return mid;
60368
+ if (fLo * fMid < 0) {
60369
+ hi = mid;
60370
+ } else {
60371
+ lo = mid;
60372
+ fLo = fMid;
58930
60373
  }
58931
- return resolved;
58932
60374
  }
58933
- return animRef;
60375
+ return (lo + hi) / 2;
58934
60376
  }
58935
- function resolveElementAnimation(animate, defs) {
58936
- if (!animate) return [];
58937
- const results = [];
58938
- if (typeof animate === "string") {
58939
- const resolved = resolveAnimation(animate, defs);
58940
- if (resolved) results.push(resolved);
58941
- } else if (Array.isArray(animate)) {
58942
- for (const item of animate) {
58943
- const resolved = resolveAnimation(item, defs);
58944
- if (resolved) results.push(resolved);
60377
+ function interpolateRangeAt(kfs, t) {
60378
+ if (t <= kfs[0].time) return kfs[0].value;
60379
+ if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
60380
+ for (let i = 1; i < kfs.length; i++) {
60381
+ if (t <= kfs[i].time) {
60382
+ const prev = kfs[i - 1];
60383
+ const cur = kfs[i];
60384
+ const a = (t - prev.time) / (cur.time - prev.time);
60385
+ return [
60386
+ prev.value[0] + (cur.value[0] - prev.value[0]) * a,
60387
+ prev.value[1] + (cur.value[1] - prev.value[1]) * a
60388
+ ];
58945
60389
  }
58946
- } else {
58947
- results.push(animate);
58948
60390
  }
58949
- return results;
60391
+ return kfs[kfs.length - 1].value;
58950
60392
  }
58951
- function interpolateValue(propName, a, b, t) {
58952
- var _a, _b;
58953
- if (propName === "d") {
58954
- const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
58955
- const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
58956
- return { paths: interpolateBeziers(aPaths, bPaths, t) };
58957
- }
58958
- if (COLOUR_ATTR_NAMES.has(propName)) {
58959
- return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
60393
+ function pxBezierPathLength(path) {
60394
+ const v = path.v;
60395
+ if (!v || v.length < 2) return 0;
60396
+ let total = 0;
60397
+ for (let i = 0; i < v.length - 1; i++) {
60398
+ total += segmentLength(path, i, i + 1);
58960
60399
  }
58961
- if (TRANSFORM_FN_NAMES.has(propName) || propName === "stroke-dasharray" || propName === "strokeDasharray") {
58962
- return interpolateVec(a || [], b || [], t);
60400
+ if (path.c && v.length > 1) {
60401
+ total += segmentLength(path, v.length - 1, 0);
58963
60402
  }
58964
- return interpolateNum(+(a || 0), +(b || 0), t);
60403
+ return total;
58965
60404
  }
58966
- function expandLoopKeyframes(propName, keyframes, loop, duration) {
58967
- var _a, _b, _c, _d, _e;
58968
- const totalIntervals = keyframes.length - 1;
58969
- const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
58970
- let segKfs;
58971
- if (loop.before) {
58972
- segKfs = keyframes.slice(0, segCount + 1);
60405
+ function segmentLength(path, from, to) {
60406
+ var _a, _b, _c, _d;
60407
+ const v = path.v;
60408
+ const p0 = v[from];
60409
+ const p3 = v[to];
60410
+ const p1 = (_b = (_a = path.o) == null ? void 0 : _a[from]) != null ? _b : p0;
60411
+ const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
60412
+ const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
60413
+ return lut.ds[lut.ds.length - 1];
60414
+ }
60415
+ function rectToPathD(node) {
60416
+ var _a, _b, _c, _d;
60417
+ if (node.type !== "rect") return void 0;
60418
+ const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
60419
+ const w = Number((_c = node.width) != null ? _c : 0), h3 = Number((_d = node.height) != null ? _d : 0);
60420
+ return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h3) + "L" + x + "," + (y + h3) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
60421
+ }
60422
+ function applyPlayerEffects(root) {
60423
+ var _a;
60424
+ const ctx = {
60425
+ defs: [],
60426
+ warnings: [],
60427
+ errors: [],
60428
+ idMap: /* @__PURE__ */ new Map(),
60429
+ nextId: 0,
60430
+ contentRefInnerIds: /* @__PURE__ */ new Map(),
60431
+ maskAncestorChains: /* @__PURE__ */ new Map(),
60432
+ // Resolved engine: `frames` ONLY when explicitly set; auto/webapi/unset →
60433
+ // webapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
60434
+ engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi
60435
+ };
60436
+ const working = clone(root);
60437
+ indexById(working, ctx.idMap);
60438
+ identifyContentRefTargets(working, ctx, () => genId(ctx, "inner"));
60439
+ collectMaskAncestorChains(working, ctx);
60440
+ const afterPass1 = applyPlayerEffects_exceptRetime(working, ctx);
60441
+ const out = applyPlayerEffects_retime(afterPass1, ctx);
60442
+ spliceDefs(out, ctx.defs);
60443
+ return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
60444
+ }
60445
+ function applyPlayerEffects_exceptRetime(node, ctx) {
60446
+ if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
60447
+ const fx = node.effects;
60448
+ const originalId = typeof node.id === "string" ? node.id : void 0;
60449
+ const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
60450
+ if (!fx && !innerIdForContentRef) return node;
60451
+ const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textAlongPath } = fx != null ? fx : {};
60452
+ const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
60453
+ if (fx) delete node.effects;
60454
+ let n = node;
60455
+ n = applyTextAlongPathEffect(n, textAlongPath, ctx);
60456
+ n = applyFillGradientEffect(n, fillGradient, ctx);
60457
+ n = applyStrokeGradientEffect(n, strokeGradient, ctx);
60458
+ n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
60459
+ n = applyRepeaterEffect(n, repeater, ctx);
60460
+ n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
60461
+ if (innerIdForContentRef) {
60462
+ applyRefHref(n, cloneFx, ctx);
60463
+ n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
58973
60464
  } else {
58974
- segKfs = keyframes.slice(totalIntervals - segCount);
60465
+ n = applyRefAndTransformationEffect(n, cloneFx, transformation, ctx);
58975
60466
  }
58976
- const firstT = (_b = keyframes[0].t) != null ? _b : 0;
58977
- const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
58978
- let fillStart, fillEnd;
58979
- if (loop.before) {
58980
- fillStart = 0;
58981
- fillEnd = firstT;
58982
- } else {
58983
- fillStart = lastT;
58984
- fillEnd = duration;
60467
+ if (cloneFx == null ? void 0 : cloneFx.retime) node.effects = { clone: { retime: cloneFx.retime } };
60468
+ if (originalId) ctx.idMap.set(originalId, n);
60469
+ return n;
60470
+ }
60471
+ function applyPlayerEffects_retime(node, ctx) {
60472
+ applyAllRetimeEffects(node, ctx);
60473
+ return node;
60474
+ }
60475
+ function materialiseAnimatedUseInstances(root) {
60476
+ var _a;
60477
+ const idMap = buildIdMap(root);
60478
+ const animatedIds = computeAnimatedSubtreeIds(root, idMap);
60479
+ if (animatedIds.size === 0) return root;
60480
+ let idCounter = 0;
60481
+ const genId3 = () => "_lw_use_mat_" + ++idCounter;
60482
+ const rootViewport = readRootViewport(root);
60483
+ const defsCollector = [];
60484
+ const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
60485
+ if (defsCollector.length === 0) return walked;
60486
+ const defsNode = { type: "defs", children: defsCollector };
60487
+ const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
60488
+ return __spreadProps(__spreadValues({}, walked), { children: newChildren });
60489
+ }
60490
+ function readRootViewport(root) {
60491
+ const vb = parseViewBox(root.viewBox);
60492
+ if (vb) return [vb[2], vb[3]];
60493
+ const w = numericAttr(root.width);
60494
+ const h3 = numericAttr(root.height);
60495
+ if (w !== void 0 && h3 !== void 0) return [w, h3];
60496
+ return [1, 1];
60497
+ }
60498
+ function numericAttr(v) {
60499
+ if (typeof v === "number") return v;
60500
+ if (typeof v === "string") {
60501
+ const n = parseFloat(v);
60502
+ return Number.isFinite(n) ? n : void 0;
58985
60503
  }
58986
- const fillDuration = fillEnd - fillStart;
58987
- if (fillDuration <= 0) return keyframes;
58988
- const segStartT = (_d = segKfs[0].t) != null ? _d : 0;
58989
- const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
58990
- const segDuration = segEndT - segStartT;
58991
- if (segDuration <= 0) return keyframes;
58992
- const template = segKfs.map((kf) => ({
58993
- relT: (kf.t - segStartT) / segDuration,
58994
- v: kf.v,
58995
- e: kf.e
58996
- }));
58997
- const fullReps = Math.floor(fillDuration / segDuration);
58998
- const remainder = fillDuration - fullReps * segDuration;
58999
- const partialFraction = remainder / segDuration;
59000
- const looped = [];
59001
- function appendRep(repStart, isReversed, partial) {
59002
- let entries;
59003
- if (isReversed) {
59004
- entries = [];
59005
- for (let i = template.length - 1; i >= 0; i--) {
59006
- entries.push({
59007
- relT: 1 - template[i].relT,
59008
- v: template[i].v,
59009
- // Easing for reversed transition: use reversed easing from the forward "from" keyframe
59010
- e: i > 0 ? reverseEasing(template[i - 1].e) : void 0
59011
- });
60504
+ return void 0;
60505
+ }
60506
+ function buildIdMap(root) {
60507
+ const map = /* @__PURE__ */ new Map();
60508
+ const visit = (n) => {
60509
+ var _a;
60510
+ if (typeof n.id === "string") map.set(n.id, n);
60511
+ (_a = n.children) == null ? void 0 : _a.forEach(visit);
60512
+ };
60513
+ visit(root);
60514
+ return map;
60515
+ }
60516
+ function computeAnimatedSubtreeIds(root, idMap) {
60517
+ const cache = /* @__PURE__ */ new WeakMap();
60518
+ const result = /* @__PURE__ */ new Set();
60519
+ const hasAnim = (n, visiting) => {
60520
+ const cached = cache.get(n);
60521
+ if (cached !== void 0) return cached;
60522
+ if (visiting.has(n)) return false;
60523
+ visiting.add(n);
60524
+ let r = false;
60525
+ if (n.animate && typeof n.animate === "object" && !Array.isArray(n.animate)) {
60526
+ for (const _ in n.animate) {
60527
+ r = true;
60528
+ break;
59012
60529
  }
59013
- } else {
59014
- entries = template;
59015
60530
  }
59016
- const cutRelT = partial !== void 0 ? partial : 1;
59017
- for (let i = 0; i < entries.length; i++) {
59018
- const entry = entries[i];
59019
- if (entry.relT > cutRelT + 1e-9) {
59020
- const prev = entries[i - 1];
59021
- const intervalSpan = entry.relT - prev.relT;
59022
- const localFrac = (cutRelT - prev.relT) / intervalSpan;
59023
- const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
59024
- const cutValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
59025
- const { left: leftEasing } = splitEasing(prev.e, localFrac);
59026
- if (looped.length > 0 && prev.relT <= cutRelT) {
59027
- looped[looped.length - 1].e = leftEasing;
60531
+ if (!r && n.children) {
60532
+ for (const ch of n.children) {
60533
+ if (hasAnim(ch, visiting)) {
60534
+ r = true;
60535
+ break;
59028
60536
  }
59029
- looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
59030
- return;
59031
60537
  }
59032
- looped.push({
59033
- t: repStart + entry.relT * segDuration,
59034
- v: entry.v,
59035
- e: i < entries.length - 1 ? entry.e : void 0
59036
- });
59037
60538
  }
60539
+ if (!r && n.type === "use" && typeof n.href === "string") {
60540
+ const targetId = stripHash2(n.href);
60541
+ const target = targetId ? idMap.get(targetId) : void 0;
60542
+ if (target) r = hasAnim(target, visiting);
60543
+ }
60544
+ visiting.delete(n);
60545
+ cache.set(n, r);
60546
+ return r;
60547
+ };
60548
+ for (const [id, node] of idMap) {
60549
+ if (hasAnim(node, /* @__PURE__ */ new Set())) result.add(id);
59038
60550
  }
59039
- for (let rep = 0; rep < fullReps; rep++) {
59040
- const distFromBoundary = loop.before ? fullReps - 1 - rep : rep;
59041
- const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
59042
- const repStart = fillStart + rep * segDuration;
59043
- appendRep(repStart, isReversed);
59044
- }
59045
- if (partialFraction > 1e-9) {
59046
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
59047
- const repStart = fillStart + fullReps * segDuration;
59048
- appendRep(repStart, isReversed, partialFraction);
59049
- }
59050
- if (loop.before) {
59051
- return [...looped, ...keyframes];
59052
- } else {
59053
- return [...keyframes, ...looped];
59054
- }
60551
+ return result;
59055
60552
  }
59056
- function normalizeKeyframes(propName, propAnim, duration, defs) {
59057
- var _a, _b, _c, _d, _e;
59058
- const keyframes = propAnim.keyframes || propAnim.kfs || [];
59059
- const normalized = [];
59060
- for (const kf of keyframes) {
59061
- const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
59062
- let value = (_c = kf.value) != null ? _c : kf.v;
59063
- const easing = (_d = kf.easing) != null ? _d : kf.e;
59064
- if (propName === "d") {
59065
- value = normalizePathValue(value);
59066
- }
59067
- if (COLOUR_ATTR_NAMES.has(propName)) {
59068
- value = (_e = parseColor(value)) != null ? _e : value;
60553
+ function stripHash2(href) {
60554
+ if (typeof href !== "string") return void 0;
60555
+ return href.startsWith("#") ? href.slice(1) : href;
60556
+ }
60557
+ function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
60558
+ var _a, _b, _c, _d;
60559
+ const clone2 = deepClonePxNode(target);
60560
+ regenerateIdsAndRewriteRefs(clone2, genId3);
60561
+ const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
60562
+ const useW = (_b = (_a = numericAttr(useNode.width)) != null ? _a : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
60563
+ const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
60564
+ const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
60565
+ const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
60566
+ const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materialisedClone] });
60567
+ delete newNode.href;
60568
+ delete newNode.width;
60569
+ delete newNode.height;
60570
+ return applyUseOffsetToG(newNode);
60571
+ }
60572
+ function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
60573
+ const viewBox = parseViewBox(symbolNode.viewBox);
60574
+ const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
60575
+ delete g.viewBox;
60576
+ delete g.preserveAspectRatio;
60577
+ delete g.width;
60578
+ delete g.height;
60579
+ if (!viewBox) return g;
60580
+ const [vbX, vbY, vbW, vbH] = viewBox;
60581
+ const scale = vbW > 0 && vbH > 0 ? Math.min(useW / vbW, useH / vbH) : 1;
60582
+ const xOff = (useW - vbW * scale) / 2;
60583
+ const yOff = (useH - vbH * scale) / 2;
60584
+ const parts = [];
60585
+ if (xOff !== 0 || yOff !== 0) parts.push("translate(" + xOff + "," + yOff + ")");
60586
+ if (scale !== 1) parts.push("scale(" + scale + ")");
60587
+ if (vbX !== 0 || vbY !== 0) parts.push("translate(" + -vbX + "," + -vbY + ")");
60588
+ if (parts.length) g.transform = parts.join("");
60589
+ const clipId = genId3();
60590
+ defsCollector.push({
60591
+ type: "clipPath",
60592
+ id: clipId,
60593
+ children: [{ type: "rect", x: vbX, y: vbY, width: vbW, height: vbH }]
60594
+ });
60595
+ g.clipPath = "url(#" + clipId + ")";
60596
+ return g;
60597
+ }
60598
+ function parseViewBox(v) {
60599
+ if (typeof v !== "string") return void 0;
60600
+ const parts = v.trim().split(/[\s,]+/).map(Number);
60601
+ if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
60602
+ return [parts[0], parts[1], parts[2], parts[3]];
60603
+ }
60604
+ function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
60605
+ if (node.type === "use" && typeof node.href === "string") {
60606
+ const targetId = stripHash2(node.href);
60607
+ if (targetId && animatedIds.has(targetId)) {
60608
+ const target = idMap.get(targetId);
60609
+ if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
59069
60610
  }
59070
- normalized.push({
59071
- t: timePct,
59072
- v: value,
59073
- e: resolveEasing(easing, defs)
59074
- });
59075
60611
  }
59076
- normalized.sort((a, b) => {
59077
- var _a2, _b2;
59078
- return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
60612
+ if (!node.children) return node;
60613
+ let changed = false;
60614
+ const newChildren = node.children.map((ch) => {
60615
+ const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
60616
+ if (m !== ch) changed = true;
60617
+ return m;
59079
60618
  });
59080
- const loopRaw = propAnim.loop;
59081
- const loop = loopRaw === true ? {} : loopRaw || void 0;
59082
- if (loop && normalized.length >= 2) {
59083
- return expandLoopKeyframes(propName, normalized, loop, duration);
60619
+ return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
60620
+ }
60621
+ function materialiseAllInTree(doc, engine, opts) {
60622
+ var _a, _b;
60623
+ let root = applyPlayerEffects(doc).root;
60624
+ const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
60625
+ root = materialiseInternalLoopsInTree(root, duration);
60626
+ if (engine === PxAnimatorEngine.webapi) {
60627
+ root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
60628
+ root = materialiseAnimatedUseInstances(root);
60629
+ root = pruneUnreferencedDefs(root);
59084
60630
  }
59085
- return normalized;
60631
+ return root;
59086
60632
  }
59087
- function mergeAnimationDefinitions(animations) {
59088
- const merged = {};
59089
- for (const anim of animations) {
59090
- for (const [prop, propAnim] of Object.entries(anim)) {
59091
- merged[prop] = propAnim;
59092
- }
60633
+ function pruneUnreferencedDefs(root) {
60634
+ const stripHash3 = (h3) => h3.startsWith("#") ? h3.slice(1) : h3;
60635
+ const walk = (n, fn) => {
60636
+ var _a;
60637
+ fn(n);
60638
+ (_a = n.children) == null ? void 0 : _a.forEach((c) => walk(c, fn));
60639
+ };
60640
+ let changed = true;
60641
+ while (changed) {
60642
+ changed = false;
60643
+ const referenced = /* @__PURE__ */ new Set();
60644
+ walk(root, (n) => {
60645
+ if (n.type === "use" && typeof n.href === "string") referenced.add(stripHash3(n.href));
60646
+ });
60647
+ walk(root, (n) => {
60648
+ if (!n.children) return;
60649
+ let kept = n.children;
60650
+ if (n.type === "defs") {
60651
+ kept = kept.filter((c) => !((c.type === "g" || c.type === "symbol") && typeof c.id === "string" && !referenced.has(c.id)));
60652
+ }
60653
+ kept = kept.filter((c) => !(c.type === "defs" && (!c.children || c.children.length === 0)));
60654
+ if (kept.length !== n.children.length) {
60655
+ n.children = kept;
60656
+ changed = true;
60657
+ }
60658
+ });
59093
60659
  }
59094
- return merged;
60660
+ return root;
59095
60661
  }
59096
- var _elementIdCounter = 0;
59097
- function generateElementId() {
59098
- return "_px_el_" + ++_elementIdCounter;
60662
+ var SVG_NS = "http://www.w3.org/2000/svg";
60663
+ var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
60664
+ "script",
60665
+ "foreignobject"
60666
+ ]);
60667
+ var URL_VALUE_ATTRS_LOWER = /* @__PURE__ */ new Set([
60668
+ "href",
60669
+ // <use>, <image>
60670
+ "xlink:href",
60671
+ // legacy <use>
60672
+ "src",
60673
+ // <image>
60674
+ "filter",
60675
+ // url(#filterId)
60676
+ "clippath",
60677
+ // clip-path="url(#…)"
60678
+ "mask",
60679
+ // url(#maskId)
60680
+ "markerstart",
60681
+ // marker-start="url(#…)"
60682
+ "markermid",
60683
+ // marker-mid="url(#…)"
60684
+ "markerend"
60685
+ // marker-end="url(#…)"
60686
+ ]);
60687
+ var IMAGE_REF_ATTRS_LOWER = /* @__PURE__ */ new Set(["href", "xlink:href", "src"]);
60688
+ var DATA_RASTER_IMAGE_RE = /^data:image\/(?:png|jpe?g|gif|webp|bmp);base64,/i;
60689
+ var DATA_SVG_IMAGE_RE = /^data:image\/svg\+xml(?:;[^,]*)?,/i;
60690
+ var DATA_IMAGE_BASE64_PAYLOAD_RE = /^data:image\/[^;,]*;base64,([A-Za-z0-9+/]{8})/i;
60691
+ var BASE64_RASTER_MAGICS = ["iVBORw0K", "/9j/", "R0lGOD", "UklGR", "Qk"];
60692
+ function isContentSniffedRasterImage(str) {
60693
+ const m = DATA_IMAGE_BASE64_PAYLOAD_RE.exec(str);
60694
+ return !!m && BASE64_RASTER_MAGICS.some((magic) => m[1].startsWith(magic));
59099
60695
  }
59100
- function normalizeAnimationDefinition(animDef, duration, defs) {
59101
- const normalized = {};
59102
- for (const [propName, propAnim] of Object.entries(animDef)) {
59103
- const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
59104
- if (normalizedKfs.length > 0) {
59105
- normalized[propName] = { kfs: normalizedKfs };
59106
- }
59107
- }
59108
- return normalized;
60696
+ function isDangerousAttrName(nameLower) {
60697
+ if (nameLower.startsWith("on")) return true;
60698
+ return false;
59109
60699
  }
59110
- function getNormalisedBindings(doc) {
59111
- const animatorConfig = getAnimatorConfig(doc) || {};
59112
- const defs = getDefs(doc);
59113
- const duration = animatorConfig.duration || 1e3;
59114
- const bindings = [];
59115
- const processAnimation = (id, animate) => {
59116
- if (!animate) return null;
59117
- const animDefs = resolveElementAnimation(animate, defs);
59118
- if (animDefs.length === 0) return null;
59119
- const merged = mergeAnimationDefinitions(animDefs);
59120
- const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs);
59121
- if (Object.keys(normalizedAnim).length === 0) return null;
59122
- return {
59123
- id,
59124
- animate: normalizedAnim
59125
- };
59126
- };
59127
- const docBindings = getBindings(doc);
59128
- if (docBindings) {
59129
- for (const binding of docBindings) {
59130
- const normalized = processAnimation(binding.id, binding.animate);
59131
- if (normalized) bindings.push(normalized);
59132
- }
60700
+ function sanitiseAttributeValue(name, value) {
60701
+ const nameLower = name.toLowerCase();
60702
+ if (isDangerousAttrName(nameLower)) {
60703
+ console.warn("Attribute blocked (event handler / dangerous): ", nameLower);
60704
+ return void 0;
59133
60705
  }
59134
- const processNode = (node) => {
59135
- const inlineAnim = node.animate;
59136
- if (inlineAnim && Object.keys(inlineAnim).length > 0) {
59137
- const nodeId = node.id || generateElementId();
59138
- node.id = nodeId;
59139
- const normalized = processAnimation(nodeId, inlineAnim);
59140
- if (normalized) bindings.push(normalized);
59141
- }
59142
- if (node.children) {
59143
- for (let i = 0; i < node.children.length; i++) {
59144
- processNode(node.children[i]);
59145
- }
60706
+ if (nameLower === "fill" || nameLower === "stroke" || nameLower === "stopcolor") {
60707
+ const str = String(value);
60708
+ if (str.includes("url(") && !/^url\(#[^)]+\)$/.test(str)) {
60709
+ console.warn('Attribute "' + nameLower + '" blocked: url() must be internal url(#id), got:', value);
60710
+ return void 0;
59146
60711
  }
59147
- };
59148
- if (doc.children) {
59149
- for (let i = 0; i < doc.children.length; i++) {
59150
- processNode(doc.children[i]);
60712
+ return value;
60713
+ }
60714
+ if (URL_VALUE_ATTRS_LOWER.has(nameLower)) {
60715
+ const str = String(value);
60716
+ if (str.startsWith("#")) return value;
60717
+ if (/^url\(#[^)]+\)$/.test(str)) return value;
60718
+ if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && (DATA_RASTER_IMAGE_RE.test(str) || DATA_SVG_IMAGE_RE.test(str) || isContentSniffedRasterImage(str))) return value;
60719
+ console.warn('Attribute "' + nameLower + '" blocked: must be #id, url(#id), or data:image/\u2026 URI, got:', value);
60720
+ return void 0;
60721
+ }
60722
+ return value;
60723
+ }
60724
+ function createElement(tagName, normalisedProps, style, children, textContent) {
60725
+ if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
60726
+ console.warn("SVG tag blocked (dangerous): ", tagName);
60727
+ return null;
60728
+ }
60729
+ const element = document.createElementNS(SVG_NS, tagName);
60730
+ for (const propName in normalisedProps) {
60731
+ const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
60732
+ if (sanitised === void 0) continue;
60733
+ element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
60734
+ }
60735
+ if (style) {
60736
+ for (const styleProp in style) {
60737
+ element.style[styleProp] = String(style[styleProp]);
59151
60738
  }
59152
60739
  }
59153
- return bindings;
59154
- }
59155
- function getKeyframesPair(keyframes, progress) {
59156
- var _a, _b;
59157
- let prevKf = keyframes[0];
59158
- let nextKf = keyframes[keyframes.length - 1];
59159
- for (let j = 0; j < keyframes.length - 1; j++) {
59160
- const aOff = (_a = keyframes[j].t) != null ? _a : 0;
59161
- const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
59162
- if (aOff <= progress && progress <= bOff) {
59163
- prevKf = keyframes[j];
59164
- nextKf = keyframes[j + 1];
59165
- break;
60740
+ if (children) {
60741
+ for (const child of children) {
60742
+ element.appendChild(child);
59166
60743
  }
59167
60744
  }
59168
- return { prevKf, nextKf };
60745
+ if (textContent) element.textContent = textContent;
60746
+ return element;
59169
60747
  }
59170
- function calcPropertyValue(propName, propAnim, progress) {
59171
- var _a, _b, _c, _d, _e, _f, _g;
59172
- const keyframes = propAnim.kfs || propAnim.keyframes || [];
59173
- if (keyframes.length === 0) return null;
59174
- const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
59175
- let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
59176
- localProgress = clamp(localProgress, 0, 1);
59177
- const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
59178
- if (easing && Array.isArray(easing)) {
59179
- try {
59180
- localProgress = cubicBezier(easing)(localProgress);
59181
- } catch (e) {
59182
- }
60748
+ function resolveStyle(style, defs) {
60749
+ var _a;
60750
+ if (!style) return void 0;
60751
+ if (typeof style === "string") {
60752
+ return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
59183
60753
  }
59184
- let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
59185
- let cssValue = null;
59186
- const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
59187
- const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
59188
- if (cssAttrName === "d") {
59189
- const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
59190
- const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
59191
- cssValue = interpolateBeziers(
59192
- prevPaths,
59193
- nextPaths,
59194
- localProgress
59195
- ).map((bz) => bezierToSvgPath(bz)).join("");
59196
- } else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
59197
- cssValue = toRGBA(interpolateColor(
59198
- prevV || [0, 0, 0, 1],
59199
- nextV || [0, 0, 0, 1],
59200
- localProgress
59201
- ));
59202
- cssAttrName = propName;
59203
- } else if (cssAttrName === "stroke-dasharray") {
59204
- cssValue = interpolateVec(
59205
- prevV || [],
59206
- nextV || [],
59207
- localProgress
59208
- ).join(" ");
59209
- cssAttrName = propName;
59210
- } else if (cssAttrName === "transform" && prevV !== null && typeof prevV === "object" && !Array.isArray(prevV)) {
59211
- const partKeys = /* @__PURE__ */ new Set([
59212
- ...prevV ? Object.keys(prevV) : [],
59213
- ...nextV ? Object.keys(nextV) : []
59214
- ]);
59215
- const partsResult = {};
59216
- for (const partKey of partKeys) {
59217
- const prevPart = prevV == null ? void 0 : prevV[partKey];
59218
- const nextPart = nextV == null ? void 0 : nextV[partKey];
59219
- if (partKey === "rotate") {
59220
- partsResult.rotate = interpolateNum(+(prevPart != null ? prevPart : 0), +(nextPart != null ? nextPart : 0), localProgress);
59221
- } else if (partKey === "translate" || partKey === "scale" || partKey === "origin") {
59222
- const fallback = partKey === "scale" ? [1, 1] : [0, 0];
59223
- const interp = interpolateVec(prevPart || fallback, nextPart || fallback, localProgress);
59224
- partsResult[partKey] = interp;
60754
+ return style;
60755
+ }
60756
+ function getNormalizedProps(props) {
60757
+ const propsCopy = {};
60758
+ for (const rawKey of Object.keys(props)) {
60759
+ const key = kebabToCamelCaseWord(rawKey);
60760
+ if (INTERNAL_ATTRS.has(key)) continue;
60761
+ if (key === "style") continue;
60762
+ let value = props[rawKey];
60763
+ if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
60764
+ propsCopy[key] = toRGBA(value);
60765
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && value.value && typeof value.value === "object") {
60766
+ propsCopy["transform"] = composeTransformParts(value.value, { withUnits: false });
60767
+ } else if (TRANSFORM_FN_NAMES.has(key)) {
60768
+ if (Array.isArray(value)) {
60769
+ if (key === "translate") value = value.map((v) => v + "px");
60770
+ value = value.join(",");
59225
60771
  }
60772
+ if (key === "rotate") value = value + "deg";
60773
+ propsCopy["transform"] = key + "(" + value + ")";
60774
+ } else if (value !== void 0 && value !== null) {
60775
+ propsCopy[key] = String(value);
59226
60776
  }
59227
- if (propAnimIsMotionPath(propAnim)) {
59228
- const prevTr = prevV.translate;
59229
- const nextTr = nextV.translate;
59230
- if (Array.isArray(prevTr) && Array.isArray(nextTr)) {
59231
- const sample = evaluateMotionPathSegment(
59232
- prevKf,
59233
- nextKf,
59234
- [+prevTr[0], +prevTr[1]],
59235
- [+nextTr[0], +nextTr[1]],
59236
- localProgress,
59237
- !!propAnim.autoOrient
59238
- );
59239
- partsResult.translate = [sample.translate[0], sample.translate[1]];
59240
- if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
60777
+ }
60778
+ return propsCopy;
60779
+ }
60780
+ function renderNode(node, defs) {
60781
+ if (!node) return null;
60782
+ const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
60783
+ const nodeDefs = getDefs(node) || defs;
60784
+ const resolvedStyle = resolveStyle(style, nodeDefs);
60785
+ let childElements;
60786
+ if (children) {
60787
+ for (const ch of children) {
60788
+ const child = renderNode(ch, nodeDefs);
60789
+ if (child) {
60790
+ if (!childElements) childElements = [];
60791
+ childElements.push(child);
59241
60792
  }
59242
60793
  }
59243
- cssValue = composeTransformParts(partsResult, { withUnits: false });
59244
- cssAttrName = "transform";
59245
- } else if (cssAttrName === "translate") {
59246
- const v = interpolateVec(
59247
- prevV || [0, 0],
59248
- nextV || [0, 0],
59249
- localProgress
59250
- );
59251
- cssValue = "translate(" + v.join(",") + ")";
59252
- cssAttrName = "transform";
59253
- } else if (cssAttrName === "rotate") {
59254
- const v = interpolateNum(
59255
- +(prevV || 0),
59256
- +(nextV || 0),
59257
- localProgress
59258
- );
59259
- cssValue = "rotate(" + v + ")";
59260
- cssAttrName = "transform";
59261
- } else if (cssAttrName === "scale") {
59262
- const v = interpolateVec(
59263
- prevV || [1, 1],
59264
- nextV || [1, 1],
59265
- localProgress
59266
- );
59267
- cssValue = "scale(" + v.join(",") + ")";
59268
- cssAttrName = "transform";
59269
- } else {
59270
- const num2 = interpolateNum(
59271
- +(prevV || 0),
59272
- +(nextV || 0),
59273
- localProgress
59274
- );
59275
- cssValue = num2;
59276
- }
59277
- if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
59278
- cssValue = cssValue * 100 + "%";
59279
60794
  }
59280
- return { k: cssAttrName, v: cssValue === null ? "" : "" + cssValue };
60795
+ return createElement(
60796
+ type || "g",
60797
+ getNormalizedProps(props),
60798
+ resolvedStyle,
60799
+ childElements,
60800
+ props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
60801
+ );
59281
60802
  }
59282
- function calcAnimationValues(animDef, progress) {
59283
- const result = {};
59284
- for (const [propName, propAnim] of Object.entries(animDef)) {
59285
- const computed3 = calcPropertyValue(propName, propAnim, progress);
59286
- if (computed3) {
59287
- result[computed3.k] = computed3.v;
60803
+ function setupAnimationTriggers(api, config) {
60804
+ const { startOn, outAction = "continue", scrollIntoViewThreshold = 0.5 } = config;
60805
+ const root = api.getRootElement();
60806
+ if (!root) {
60807
+ console.warn("setupAnimationTriggers: No root element found for animation.");
60808
+ return api;
60809
+ }
60810
+ const start = () => {
60811
+ api.play();
60812
+ };
60813
+ const handleEndAction = () => {
60814
+ switch (outAction) {
60815
+ case "pause":
60816
+ api.pause();
60817
+ break;
60818
+ case "reset":
60819
+ api.cancel();
60820
+ break;
60821
+ case "reverse":
60822
+ api.play();
60823
+ break;
60824
+ case "continue":
60825
+ default:
60826
+ break;
60827
+ }
60828
+ };
60829
+ switch (startOn) {
60830
+ case "load": {
60831
+ const startHandler = () => start();
60832
+ if (document.readyState === "complete") {
60833
+ startHandler();
60834
+ } else {
60835
+ window.addEventListener("load", startHandler, { once: true });
60836
+ }
60837
+ break;
60838
+ }
60839
+ case "mouseOver": {
60840
+ const mouseOverHandler = () => start();
60841
+ const mouseOutHandler = () => handleEndAction();
60842
+ root.addEventListener("mouseenter", mouseOverHandler);
60843
+ root.addEventListener("mouseleave", mouseOutHandler);
60844
+ break;
59288
60845
  }
60846
+ case "click": {
60847
+ const clickHandler = () => {
60848
+ if (api.isPlaying()) {
60849
+ handleEndAction();
60850
+ } else {
60851
+ start();
60852
+ }
60853
+ };
60854
+ root.addEventListener("click", clickHandler);
60855
+ break;
60856
+ }
60857
+ case "scrollIntoView": {
60858
+ const observer = new IntersectionObserver(
60859
+ (entries) => {
60860
+ entries.forEach((entry) => {
60861
+ if (entry.isIntersecting && entry.intersectionRatio >= scrollIntoViewThreshold) {
60862
+ start();
60863
+ } else {
60864
+ handleEndAction();
60865
+ }
60866
+ });
60867
+ },
60868
+ { threshold: scrollIntoViewThreshold }
60869
+ );
60870
+ observer.observe(root);
60871
+ break;
60872
+ }
60873
+ case "programmatic":
60874
+ break;
59289
60875
  }
59290
- return result;
60876
+ return api;
59291
60877
  }
59292
60878
  function getSelector(id) {
59293
60879
  return "#" + id;
59294
60880
  }
59295
60881
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
59296
60882
  const config = getAnimatorConfig(doc) || {};
59297
- const bindings = getNormalisedBindings(doc);
60883
+ const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
59298
60884
  const _iterations = config.iterations;
59299
60885
  let iterations = 1;
59300
60886
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -59412,6 +60998,10 @@ ${codeFrame}` : message);
59412
60998
  };
59413
60999
  const startAnim = () => {
59414
61000
  if (playing) return;
61001
+ if (Number.isFinite(totalDuration) && timeBeforeLastStartMs >= totalDuration) {
61002
+ timeBeforeLastStartMs = 0;
61003
+ finishCalled = false;
61004
+ }
59415
61005
  playing = true;
59416
61006
  lastStartedTs = Date.now();
59417
61007
  loopAnim(true);
@@ -59642,7 +61232,6 @@ ${codeFrame}` : message);
59642
61232
  function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs) {
59643
61233
  var _a;
59644
61234
  const config = getAnimatorConfig(doc) || {};
59645
- const bindings = getNormalisedBindings(doc);
59646
61235
  if (!rootElement) {
59647
61236
  if (doc.id) {
59648
61237
  const rootSelector = getSelector(doc.id);
@@ -59652,6 +61241,7 @@ ${codeFrame}` : message);
59652
61241
  console.warn("createFrameLoopAnimator: No root element provided");
59653
61242
  }
59654
61243
  }
61244
+ const bindings = getNormalisedBindings(doc, PxAnimatorEngine.webapi);
59655
61245
  const animations = [];
59656
61246
  const _iterations = config.iterations;
59657
61247
  let iterations;
@@ -59781,15 +61371,15 @@ ${codeFrame}` : message);
59781
61371
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
59782
61372
  const animatorConfig = getAnimatorConfig(doc) || {};
59783
61373
  let res;
59784
- if (animatorConfig.mode === "frames") {
61374
+ if (animatorConfig.mode === PxAnimatorMode.frames) {
59785
61375
  res = createFrameLoopAnimator(doc, adapter, callbacks, rootElement);
59786
61376
  } else {
59787
61377
  res = createWebApiAnimator(
59788
61378
  doc,
59789
61379
  callbacks,
59790
61380
  rootElement,
59791
- animatorConfig.mode === "webapi"
59792
- // Forcing "webapi"
61381
+ animatorConfig.mode === PxAnimatorMode.webapi
61382
+ // forcing webapi
59793
61383
  ) || createFrameLoopAnimator(doc, adapter, callbacks, rootElement);
59794
61384
  }
59795
61385
  if (animatorConfig.debugInstName) {
@@ -59911,9 +61501,10 @@ ${codeFrame}` : message);
59911
61501
  function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
59912
61502
  const effectsWarnings = validateNodeEffects(doc);
59913
61503
  for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
59914
- doc = applyPlayerEffects(doc).root;
59915
61504
  const animatorConfig = getAnimatorConfig(doc) || {};
59916
61505
  animatorConfig.debug = true;
61506
+ const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi;
61507
+ doc = materialiseAllInTree(doc, engine);
59917
61508
  let rootElement = null;
59918
61509
  if (containerElement && doc.children) {
59919
61510
  doc = generateNewIds(doc);