@pixodesk/svg-animator-web 1.0.24 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -909,8 +909,10 @@ var PxNodeSchema = px.openObject(__spreadProps2(__spreadValues2({}, PxNodeBase._
909
909
  children: px.lazy(() => px.array(PxNodeSchema), []).optional()
910
910
  }), PxAttrValueSchema);
911
911
  var PxSvgNodeExtra = px.object({
912
- width: px.number().optional(),
913
- height: px.number().optional(),
912
+ // `"100%"` and other SVG length strings are legal here — a number-only slot rejected
913
+ // real documents (e.g. apple-store-look-14-main.json) at the root <svg>.
914
+ width: px.union([px.number(), px.string()]).optional(),
915
+ height: px.union([px.number(), px.string()]).optional(),
914
916
  viewBox: px.string().optional(),
915
917
  animator: PxAnimatorConfigSchema.optional()
916
918
  });
@@ -1943,7 +1945,7 @@ function walkAndMaterialise(node, opts) {
1943
1945
  if (newAnimate) cloned.animate = newAnimate;
1944
1946
  return cloned;
1945
1947
  }
1946
- var LOOP_JUMP_SHIFT_MS = 10;
1948
+ var LOOP_JUMP_SHIFT_MS = 1;
1947
1949
  function deepEqualValue(a, b) {
1948
1950
  if (a === b) return true;
1949
1951
  if (typeof a !== typeof b || a === null || b === null || typeof a !== "object") return false;
@@ -2192,6 +2194,8 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2192
2194
  const looped = [];
2193
2195
  const separateBoundary = loop.extend !== PxLoopExtend.before;
2194
2196
  const originalTerminalKf = keyframes[keyframes.length - 1];
2197
+ let terminalEasingOverride;
2198
+ let hasTerminalEasingOverride = false;
2195
2199
  function appendRep(repStart, isReversed, partial) {
2196
2200
  var _a2;
2197
2201
  let entries;
@@ -2232,7 +2236,16 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2232
2236
  const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2233
2237
  const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2234
2238
  if (isBoundary) {
2235
- if (deepEqualValue(prevKf.v, entry.v)) continue;
2239
+ if (deepEqualValue(prevKf.v, entry.v)) {
2240
+ if (looped.length > 0) {
2241
+ prevKf.e = entry.e;
2242
+ prevKf.tangentOut = entry.tangentOut;
2243
+ } else {
2244
+ terminalEasingOverride = entry.e;
2245
+ hasTerminalEasingOverride = true;
2246
+ }
2247
+ continue;
2248
+ }
2236
2249
  if (looped.length > 0) {
2237
2250
  delete prevKf.tangentIn;
2238
2251
  delete prevKf.tangentOut;
@@ -2313,6 +2326,11 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2313
2326
  if (loop.extend === PxLoopExtend.before) {
2314
2327
  return [...looped, ...keyframes];
2315
2328
  } else {
2329
+ if (hasTerminalEasingOverride && keyframes.length > 0) {
2330
+ const head = keyframes.slice(0, -1);
2331
+ const tail = __spreadProps2(__spreadValues2({}, keyframes[keyframes.length - 1]), { e: terminalEasingOverride });
2332
+ return [...head, tail, ...looped];
2333
+ }
2316
2334
  return [...keyframes, ...looped];
2317
2335
  }
2318
2336
  }
@@ -2429,6 +2447,9 @@ function generateElementId() {
2429
2447
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2430
2448
  const normalized = {};
2431
2449
  for (const [propName, propAnim] of Object.entries(animDef)) {
2450
+ if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
2451
+ continue;
2452
+ }
2432
2453
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
2433
2454
  if (normalizedKfs.length > 0) {
2434
2455
  const out = { kfs: normalizedKfs };
@@ -5240,9 +5261,138 @@ function applyPlayerEffects_retime(node, ctx) {
5240
5261
  applyAllRetimeEffects(node, ctx);
5241
5262
  return node;
5242
5263
  }
5264
+ var kfTime = (kf) => {
5265
+ var _a, _b;
5266
+ return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
5267
+ };
5268
+ var kfValue = (kf) => {
5269
+ var _a;
5270
+ return (_a = kf.v) != null ? _a : kf.value;
5271
+ };
5272
+ var kfEasing = (kf) => {
5273
+ var _a;
5274
+ return (_a = kf.e) != null ? _a : kf.easing;
5275
+ };
5276
+ var kfTangentIn = (kf) => {
5277
+ var _a;
5278
+ return (_a = kf.tangentIn) != null ? _a : kf.ti;
5279
+ };
5280
+ var kfTangentOut = (kf) => {
5281
+ var _a;
5282
+ return (_a = kf.tangentOut) != null ? _a : kf.to;
5283
+ };
5284
+ function cubicAt(p0, c1, c2, p1, t) {
5285
+ const u = 1 - t;
5286
+ const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
5287
+ return [
5288
+ a * p0[0] + b * c1[0] + c * c2[0] + d * p1[0],
5289
+ a * p0[1] + b * c1[1] + c * c2[1] + d * p1[1]
5290
+ ];
5291
+ }
5292
+ function cubicLength(p0, c1, c2, p1, steps = 64) {
5293
+ let len = 0;
5294
+ let prev = p0;
5295
+ for (let i = 1; i <= steps; i++) {
5296
+ const pt = cubicAt(p0, c1, c2, p1, i / steps);
5297
+ len += Math.hypot(pt[0] - prev[0], pt[1] - prev[1]);
5298
+ prev = pt;
5299
+ }
5300
+ return len;
5301
+ }
5302
+ var fmt2 = (n) => {
5303
+ const r = Math.round(n * 1e4) / 1e4;
5304
+ return Object.is(r, -0) ? "0" : String(r);
5305
+ };
5306
+ function buildOffsetPath(propAnim) {
5307
+ var _a, _b, _c, _d;
5308
+ if (propAnim.alongPathMode !== "offsetPath") return void 0;
5309
+ const kfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
5310
+ if (!kfs || kfs.length < 2) return void 0;
5311
+ const first = kfValue(kfs[0]);
5312
+ const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
5313
+ const points = [];
5314
+ for (const kf of kfs) {
5315
+ const v = kfValue(kf);
5316
+ const tr = v == null ? void 0 : v.translate;
5317
+ if (!tr || tr.length < 2) return void 0;
5318
+ const parts = Object.keys(v);
5319
+ if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5320
+ const o = (_b = v == null ? void 0 : v.origin) != null ? _b : [0, 0];
5321
+ if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5322
+ points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5323
+ }
5324
+ if (!kfs.some((kf) => kfTangentIn(kf) || kfTangentOut(kf))) return void 0;
5325
+ let d = "M" + fmt2(points[0][0]) + "," + fmt2(points[0][1]);
5326
+ const segLens = [];
5327
+ for (let i = 0; i < points.length - 1; i++) {
5328
+ const p0 = points[i], p1 = points[i + 1];
5329
+ const to = (_c = kfTangentOut(kfs[i])) != null ? _c : [0, 0];
5330
+ const ti = (_d = kfTangentIn(kfs[i + 1])) != null ? _d : [0, 0];
5331
+ const c1 = [p0[0] + to[0], p0[1] + to[1]];
5332
+ const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
5333
+ d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
5334
+ segLens.push(cubicLength(p0, c1, c2, p1));
5335
+ }
5336
+ const total = segLens.reduce((a, b) => a + b, 0);
5337
+ if (!(total > 0)) return void 0;
5338
+ const distanceKfs = [];
5339
+ let cum = 0;
5340
+ for (let i = 0; i < kfs.length; i++) {
5341
+ if (i > 0) cum += segLens[i - 1];
5342
+ const out = { t: kfTime(kfs[i]), v: cum / total };
5343
+ const e = kfEasing(kfs[i]);
5344
+ if (e !== void 0) out.e = e;
5345
+ distanceKfs.push(out);
5346
+ }
5347
+ return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
5348
+ }
5349
+ function materialiseOffsetPathsInTree(root) {
5350
+ const walk = (node) => {
5351
+ var _a;
5352
+ let out = node;
5353
+ const anim = node.animate;
5354
+ const transform = anim == null ? void 0 : anim["transform"];
5355
+ if (transform) {
5356
+ const built = buildOffsetPath(transform);
5357
+ if (built) {
5358
+ const newAnimate = __spreadValues2({}, anim);
5359
+ delete newAnimate["transform"];
5360
+ const distance = { keyframes: built.distanceKfs };
5361
+ if (transform.loop !== void 0) distance.loop = transform.loop;
5362
+ newAnimate["offsetDistance"] = distance;
5363
+ const staticTr = node.transform;
5364
+ let newTransform = staticTr;
5365
+ if (staticTr && typeof staticTr === "object") {
5366
+ const t = __spreadValues2({}, staticTr);
5367
+ delete t["translate"];
5368
+ delete t["origin"];
5369
+ newTransform = Object.keys(t).length ? t : void 0;
5370
+ }
5371
+ out = __spreadProps2(__spreadValues2({}, node), {
5372
+ animate: newAnimate,
5373
+ style: __spreadProps2(__spreadValues2({}, node.style), {
5374
+ offsetPath: "path('" + built.pathStr + "')",
5375
+ offsetAnchor: fmt2(built.anchor[0]) + "px " + fmt2(built.anchor[1]) + "px",
5376
+ offsetRotate: built.autoOrient ? "auto" : "0deg",
5377
+ offsetDistance: "0%"
5378
+ })
5379
+ });
5380
+ if (newTransform !== void 0) out.transform = newTransform;
5381
+ else delete out.transform;
5382
+ }
5383
+ }
5384
+ if ((_a = out.children) == null ? void 0 : _a.length) {
5385
+ const children = out.children.map(walk);
5386
+ if (children.some((c, i) => c !== out.children[i])) out = __spreadProps2(__spreadValues2({}, out), { children });
5387
+ }
5388
+ return out;
5389
+ };
5390
+ return walk(root);
5391
+ }
5243
5392
  function materialiseAllInTree(doc, engine, opts) {
5244
5393
  var _a, _b;
5245
5394
  let root = applyPlayerEffects(doc).root;
5395
+ root = materialiseOffsetPathsInTree(root);
5246
5396
  const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5247
5397
  root = materialiseInternalLoopsInTree(root, duration);
5248
5398
  if (engine === PxAnimatorEngine.waapi) {
@@ -5951,6 +6101,8 @@ function createCssKf(kf, t, propName, unsupportedSet) {
5951
6101
  } else if (propName === "d") {
5952
6102
  const paths = value && typeof value === "object" && Array.isArray(value.paths) ? value.paths : [];
5953
6103
  cssValue = 'path("' + paths.map((bz) => bezierToSvgPath(bz, true)).join("") + '")';
6104
+ } else if (PCT_BASED_ATTR_NAMES.has(propName) && typeof value === "number") {
6105
+ cssValue = value * 100 + "%";
5954
6106
  } else {
5955
6107
  cssValue = "" + value;
5956
6108
  }