@pixodesk/svg-animator-core 1.0.44 → 1.0.46

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.
@@ -43,19 +43,31 @@ function pathStr(path) {
43
43
  return result;
44
44
  }
45
45
  var Base = class {
46
+ /** Structural schemas (objects, arrays, unions of objects…) pass `false`: they state no scalar default. */
47
+ constructor(_statesDefault) {
48
+ this._statesDefault = _statesDefault;
49
+ }
46
50
  _canSanitize(raw) {
47
51
  return this.isValid(raw);
48
52
  }
53
+ /** A REQUIRED field is never absent; its default is the repair value. */
54
+ absentDefault() {
55
+ return this._default;
56
+ }
49
57
  optional() {
50
58
  return new Optional(this);
51
59
  }
52
60
  };
53
61
  var Optional = class extends Base {
54
62
  constructor(inner) {
55
- super();
63
+ super(inner._statesDefault);
56
64
  this.inner = inner;
57
65
  this._default = void 0;
58
66
  }
67
+ /** Absent means the inner schema's STATED default — or nothing at all when it states none. */
68
+ absentDefault() {
69
+ return this.inner._statesDefault ? this.inner._default : void 0;
70
+ }
59
71
  sanitize(raw) {
60
72
  if (raw === void 0 || raw === null) return void 0;
61
73
  return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
@@ -69,8 +81,8 @@ var Optional = class extends Base {
69
81
  }
70
82
  };
71
83
  var Str = class extends Base {
72
- constructor(_default = "") {
73
- super();
84
+ constructor(_default, statesDefault) {
85
+ super(statesDefault);
74
86
  this._default = _default;
75
87
  }
76
88
  sanitize(raw) {
@@ -83,8 +95,8 @@ var Str = class extends Base {
83
95
  }
84
96
  };
85
97
  var Num = class extends Base {
86
- constructor(_default = 0) {
87
- super();
98
+ constructor(_default, statesDefault) {
99
+ super(statesDefault);
88
100
  this._default = _default;
89
101
  }
90
102
  sanitize(raw) {
@@ -97,8 +109,8 @@ var Num = class extends Base {
97
109
  }
98
110
  };
99
111
  var Bool = class extends Base {
100
- constructor(_default = false) {
101
- super();
112
+ constructor(_default, statesDefault) {
113
+ super(statesDefault);
102
114
  this._default = _default;
103
115
  }
104
116
  sanitize(raw) {
@@ -111,8 +123,9 @@ var Bool = class extends Base {
111
123
  }
112
124
  };
113
125
  var Literal = class extends Base {
126
+ /** A literal IS its own value: absent means it. */
114
127
  constructor(value) {
115
- super();
128
+ super(true);
116
129
  this.value = value;
117
130
  this._default = value;
118
131
  }
@@ -126,8 +139,8 @@ var Literal = class extends Base {
126
139
  }
127
140
  };
128
141
  var Enum = class extends Base {
129
- constructor(values, defaultVal) {
130
- super();
142
+ constructor(values, defaultVal, statesDefault) {
143
+ super(statesDefault);
131
144
  this.values = values;
132
145
  this._default = defaultVal != null ? defaultVal : values[0];
133
146
  }
@@ -142,8 +155,8 @@ var Enum = class extends Base {
142
155
  };
143
156
  var UNION_MEMBER_ERROR_LIMIT = 4;
144
157
  var Union = class extends Base {
145
- constructor(schemas, defaultVal) {
146
- super();
158
+ constructor(schemas, defaultVal, statesDefault) {
159
+ super(statesDefault);
147
160
  this.schemas = schemas;
148
161
  /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Union from Tuple. */
149
162
  this._kind = "union";
@@ -197,7 +210,7 @@ var Union = class extends Base {
197
210
  var DiscriminatedUnion = class extends Base {
198
211
  constructor(_key, _schemas, defaultVal) {
199
212
  var _a2;
200
- super();
213
+ super(false);
201
214
  this._key = _key;
202
215
  this._schemas = _schemas;
203
216
  /** Structural tag read by {@link describeSchema}. */
@@ -237,13 +250,19 @@ var DiscriminatedUnion = class extends Base {
237
250
  return schema ? schema._canSanitize(raw) : this._schemas[0]._canSanitize(raw);
238
251
  }
239
252
  };
253
+ function statedDefaults(shape) {
254
+ const out = {};
255
+ for (const key of Object.keys(shape)) if (shape[key]._statesDefault) out[key] = shape[key].absentDefault();
256
+ return Object.freeze(out);
257
+ }
240
258
  var Obj = class extends Base {
241
259
  constructor(_shape) {
242
- super();
260
+ super(false);
243
261
  this._shape = _shape;
244
262
  const d = {};
245
263
  for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
246
264
  this._default = d;
265
+ this.defaults = statedDefaults(_shape);
247
266
  }
248
267
  sanitize(raw) {
249
268
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -285,12 +304,13 @@ var Obj = class extends Base {
285
304
  };
286
305
  var OpenObj = class extends Base {
287
306
  constructor(_shape, _openSchema) {
288
- super();
307
+ super(false);
289
308
  this._shape = _shape;
290
309
  this._openSchema = _openSchema;
291
310
  const d = {};
292
311
  for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
293
312
  this._default = d;
313
+ this.defaults = statedDefaults(_shape);
294
314
  }
295
315
  sanitize(raw) {
296
316
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -335,7 +355,7 @@ var OpenObj = class extends Base {
335
355
  };
336
356
  var Arr = class extends Base {
337
357
  constructor(item) {
338
- super();
358
+ super(false);
339
359
  this.item = item;
340
360
  this._default = [];
341
361
  }
@@ -367,7 +387,7 @@ var Arr = class extends Base {
367
387
  };
368
388
  var Rec = class extends Base {
369
389
  constructor(value) {
370
- super();
390
+ super(false);
371
391
  this.value = value;
372
392
  /** Structural tag read by {@link describeSchema}. */
373
393
  this._kind = "record";
@@ -401,7 +421,7 @@ var Rec = class extends Base {
401
421
  };
402
422
  var Any = class extends Base {
403
423
  constructor() {
404
- super(...arguments);
424
+ super(false);
405
425
  this._default = void 0;
406
426
  }
407
427
  sanitize(raw) {
@@ -416,7 +436,7 @@ var Any = class extends Base {
416
436
  };
417
437
  var Defined = class extends Base {
418
438
  constructor() {
419
- super(...arguments);
439
+ super(false);
420
440
  this._default = void 0;
421
441
  }
422
442
  sanitize(raw) {
@@ -433,7 +453,7 @@ var Defined = class extends Base {
433
453
  };
434
454
  var Lazy = class extends Base {
435
455
  constructor(fn, _default) {
436
- super();
456
+ super(false);
437
457
  this.fn = fn;
438
458
  this._default = _default;
439
459
  this.resolved = null;
@@ -454,7 +474,7 @@ var Lazy = class extends Base {
454
474
  };
455
475
  var Tuple = class extends Base {
456
476
  constructor(schemas) {
457
- super();
477
+ super(false);
458
478
  this.schemas = schemas;
459
479
  /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Tuple from Union. */
460
480
  this._kind = "tuple";
@@ -510,22 +530,29 @@ function describeSchema(schema) {
510
530
  if ("fn" in s) return { kind: "lazy", resolved: (_a2 = s.resolved) != null ? _a2 : s.resolved = s.fn() };
511
531
  return { kind: "leaf" };
512
532
  }
533
+ function string(defaultVal) {
534
+ return defaultVal === void 0 ? new Str("", false) : new Str(defaultVal, true);
535
+ }
536
+ function number(defaultVal) {
537
+ return defaultVal === void 0 ? new Num(0, false) : new Num(defaultVal, true);
538
+ }
539
+ function boolean(defaultVal) {
540
+ return defaultVal === void 0 ? new Bool(false, false) : new Bool(defaultVal, true);
541
+ }
542
+ function oneOf(values, defaultVal) {
543
+ return defaultVal === void 0 ? new Enum(values, void 0, false) : new Enum(values, defaultVal, true);
544
+ }
545
+ function unionOf(schemas, defaultVal) {
546
+ return defaultVal === void 0 ? new Union(schemas, void 0, false) : new Union(schemas, defaultVal, true);
547
+ }
513
548
  var px = {
514
- /** Matches a string. Default: '' or provided value. */
515
- string: (defaultVal = "") => new Str(defaultVal),
516
- /** Matches a finite number. Default: 0 or provided value. */
517
- number: (defaultVal = 0) => new Num(defaultVal),
518
- /** Matches a boolean. Default: false or provided value. */
519
- boolean: (defaultVal = false) => new Bool(defaultVal),
520
- /** Matches one exact primitive value; its default is the value itself. */
549
+ string,
550
+ number,
551
+ boolean,
552
+ /** Matches one exact primitive value; absent means the value itself. */
521
553
  literal: (value) => new Literal(value),
522
- /** Matches one of a fixed set of string/number values. Default: first value. */
523
- enum: (values, defaultVal) => new Enum(values, defaultVal),
524
- /**
525
- * Returns the first schema whose isValid passes.
526
- * TypeScript infers the union of all member types automatically.
527
- */
528
- union: (schemas, defaultVal) => new Union(schemas, defaultVal),
554
+ enum: oneOf,
555
+ union: unionOf,
529
556
  /**
530
557
  * Discriminated union — reads `raw[key]`, finds the member schema whose
531
558
  * literal at `key` matches, then delegates sanitize/isValid to that member.
@@ -533,7 +560,8 @@ var px = {
533
560
  * TypeScript infers the union of all member types automatically.
534
561
  */
535
562
  discriminatedUnion: (key, schemas) => new DiscriminatedUnion(key, schemas),
536
- /** Typed object — unknown keys are stripped. Required fields fall back to their default. */
563
+ /** Typed object — unknown keys are stripped. Required fields fall back to their default.
564
+ * Its `defaults` say what each stated field means when a document leaves it out. */
537
565
  object: (shape) => new Obj(shape),
538
566
  /**
539
567
  * Open object — validates known keys; passes unknown keys through as-is,
@@ -879,8 +907,11 @@ var PX_TRIGGER_DEFAULTS = {
879
907
  offScreen: "pause",
880
908
  mouseOut: "continue",
881
909
  visibilityThreshold: 0.5,
882
- visibilityDebounce: 150
910
+ visibilityDebounce: 150,
911
+ finish: "hold"
883
912
  };
913
+ var PX_DEFAULT_DURATION_MS = 1e3;
914
+ var PX_DEFAULT_ITERATIONS = 1;
884
915
  var PxControlMode = {
885
916
  /** No control props — the document's trigger decides, and nothing is taken over. */
886
917
  static: "static",
@@ -1195,15 +1226,15 @@ var keyframeTangentIn = (kf) => anyKf(kf).tangentIn;
1195
1226
  var keyframeTangentOut = (kf) => anyKf(kf).tangentOut;
1196
1227
  var PxLoopSchema = implementsInterface()(px.object({
1197
1228
  segmentCount: px.number().optional(),
1198
- repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
1199
- direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
1229
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end], PxLoopRepeatAt.end).optional(),
1230
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate], PxLoopDirection.normal).optional()
1200
1231
  }));
1201
1232
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1202
1233
  value: PxKeyframeValueSchema.optional(),
1203
1234
  keyframes: px.array(PxKeyframeSchema).optional(),
1204
1235
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1205
1236
  autoOrient: px.boolean().optional(),
1206
- alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
1237
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath], PxAlongPathMode.sampled).optional()
1207
1238
  }));
1208
1239
  var PxTransformPartsSchema = implementsInterface()(px.object({
1209
1240
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1233,9 +1264,9 @@ var PxTriggerSchema = implementsInterface()(px.object({
1233
1264
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1234
1265
  // `fill`) or `'reset'` (snap back to the start state). One of four occasion keys
1235
1266
  // (`start`, `offScreen`, `mouseOut`, `finish`), all named the same way.
1236
- finish: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
1237
- visibilityThreshold: px.number().optional(),
1238
- visibilityDebounce: px.number().optional()
1267
+ finish: px.enum([PxFinishAction.hold, PxFinishAction.reset], PX_TRIGGER_DEFAULTS.finish).optional(),
1268
+ visibilityThreshold: px.number(PX_TRIGGER_DEFAULTS.visibilityThreshold).optional(),
1269
+ visibilityDebounce: px.number(PX_TRIGGER_DEFAULTS.visibilityDebounce).optional()
1239
1270
  }));
1240
1271
  var PxGlyphSchema = implementsInterface()(px.object({
1241
1272
  width: px.number(),
@@ -1261,7 +1292,7 @@ var PxScrollRangePointSchema = implementsInterface()(px.object({
1261
1292
  PxScrollPhase.exit,
1262
1293
  PxScrollPhase.entryCrossing,
1263
1294
  PxScrollPhase.exitCrossing
1264
- ]).optional(),
1295
+ ], PxScrollPhase.cover).optional(),
1265
1296
  fraction: px.number().optional()
1266
1297
  }));
1267
1298
  var PxScrollRangeSchema = px.object({
@@ -1269,37 +1300,37 @@ var PxScrollRangeSchema = px.object({
1269
1300
  end: PxScrollRangePointSchema.optional()
1270
1301
  });
1271
1302
  var PxScrollSchema = implementsInterface()(px.object({
1272
- kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
1273
- axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1274
- source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1303
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll], PxScrollKind.view).optional(),
1304
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y], PxScrollAxis.block).optional(),
1305
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root], PxScrollSource.nearest).optional(),
1275
1306
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1276
1307
  subject: px.string().optional(),
1277
1308
  smoothing: px.number().optional(),
1278
- pin: px.boolean().optional(),
1279
- pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1309
+ pin: px.boolean(false).optional(),
1310
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom], PxPinAlign.top).optional(),
1280
1311
  pinOffset: px.number().optional(),
1281
1312
  pinDistance: px.number().optional(),
1282
1313
  range: PxScrollRangeSchema.optional()
1283
1314
  }));
1284
1315
  var PxTimelinePinSchema = implementsInterface()(px.object({
1285
- align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1316
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom], PxPinAlign.top).optional(),
1286
1317
  offset: px.number().optional(),
1287
1318
  distance: px.number().optional()
1288
1319
  }));
1289
- var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js]).optional();
1320
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js], PxTimelineEngineSetting.auto).optional();
1290
1321
  var PxTimeTimelineSchema = implementsInterface()(px.object({
1291
1322
  type: px.literal("time").optional(),
1292
1323
  engine: PxTimelineEngineSchema,
1293
1324
  frameRate: px.number().optional(),
1294
1325
  // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1295
- duration: px.number().optional(),
1326
+ duration: px.number(PX_DEFAULT_DURATION_MS).optional(),
1296
1327
  trigger: PxTriggerSchema.optional(),
1297
- delay: px.number().optional(),
1298
- iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1328
+ delay: px.number(0).optional(),
1329
+ iterations: px.union([px.number(PX_DEFAULT_ITERATIONS), px.literal("infinite")], PX_DEFAULT_ITERATIONS).optional(),
1299
1330
  // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1300
1331
  // — never `fill`, which is paint everywhere else in the format.
1301
- fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
1302
- direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
1332
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none], PxFillMode.forwards).optional(),
1333
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse], PxPlaybackDirection.normal).optional()
1303
1334
  }));
1304
1335
  var scrollishTimelineShape = {
1305
1336
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
@@ -1310,8 +1341,8 @@ var scrollishTimelineShape = {
1310
1341
  iterations: px.number().optional(),
1311
1342
  engine: PxTimelineEngineSchema,
1312
1343
  frameRate: px.number().optional(),
1313
- axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1314
- source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1344
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y], PxScrollAxis.block).optional(),
1345
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root], PxScrollSource.nearest).optional(),
1315
1346
  subject: px.string().optional(),
1316
1347
  // 'parent' | 'scroller' | any CSS selector
1317
1348
  smoothing: px.number().optional(),
@@ -1391,9 +1422,10 @@ var PxRepeaterEffectSchema = implementsInterface()(px.object({
1391
1422
  }));
1392
1423
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1393
1424
  source: px.string().optional(),
1394
- maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1395
- maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1396
- maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1425
+ // SVG's own initial values — what a <mask> does when the attribute is not there.
1426
+ maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha], PxMaskType.luminance).optional(),
1427
+ maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.objectBoundingBox).optional(),
1428
+ maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.userSpaceOnUse).optional(),
1397
1429
  x: px.number().optional(),
1398
1430
  y: px.number().optional(),
1399
1431
  width: px.number().optional(),
@@ -1405,7 +1437,7 @@ var PxClipPathEffectSchema = implementsInterface()(px.object({
1405
1437
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1406
1438
  offset: PxAnimatableNumberSchema.optional(),
1407
1439
  range: PxAnimatableVec2Schema.optional(),
1408
- subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
1440
+ subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined], PxStrokeTrimSubPaths.separate).optional()
1409
1441
  }));
1410
1442
  var PxRetimeEffectSchema = implementsInterface()(px.object({
1411
1443
  start: px.number().optional(),
@@ -1437,17 +1469,20 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
1437
1469
  radius: PxAnimatableNumberSchema.optional(),
1438
1470
  focal: PxAnimatableVec2Schema.optional(),
1439
1471
  stops: PxAnimatableGradientStopsSchema.optional(),
1440
- gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1441
- spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1472
+ // SVG's own initial values — what a gradient does when the attribute is not there.
1473
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.objectBoundingBox).optional(),
1474
+ spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat], PxGradientSpreadMethod.pad).optional(),
1442
1475
  gradientTransform: px.string().optional()
1443
1476
  }));
1444
1477
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1445
1478
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1446
1479
  pathData: px.string(),
1447
- pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1448
- lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1449
- method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
1450
- spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
1480
+ // `extend` is what an omitted pathOverflow means (glyphs continue along the tangent); the
1481
+ // other three are SVG's own initial values for the native <textPath> attributes.
1482
+ pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend], PxPathOverflow.extend).optional(),
1483
+ lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs], PxLengthAdjust.spacing).optional(),
1484
+ method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch], PxTextPathMethod.align).optional(),
1485
+ spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact], PxTextPathSpacing.exact).optional(),
1451
1486
  startOffset: PxAnimatableNumberSchema.optional(),
1452
1487
  textLength: PxAnimatableNumberSchema.optional()
1453
1488
  }));
@@ -2015,7 +2050,6 @@ function parseTransformParts(str2) {
2015
2050
  return Object.keys(out).length ? out : void 0;
2016
2051
  }
2017
2052
  var PX_STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
2018
- var PX_DEFAULT_DURATION_MS = 1e3;
2019
2053
  function kebabToCamelCaseWord(kebab) {
2020
2054
  return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
2021
2055
  }
@@ -2268,6 +2302,38 @@ function toDomProps(props) {
2268
2302
  return propsCopy;
2269
2303
  }
2270
2304
 
2305
+ // src/animation/PxStaticTransformMerge.ts
2306
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2307
+ if (!animDef) return animDef;
2308
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2309
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
2310
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2311
+ const transformAnim = animDef[TRANSFORM_ATTR];
2312
+ if (transformAnim && typeof transformAnim === "object") {
2313
+ const anim = transformAnim;
2314
+ if (Array.isArray(anim.keyframes)) {
2315
+ const out = __spreadProps(__spreadValues({}, anim), {
2316
+ keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
2317
+ });
2318
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
2319
+ return __spreadProps(__spreadValues({}, animDef), { transform: out });
2320
+ }
2321
+ return animDef;
2322
+ }
2323
+ const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2324
+ if (channels.length !== 1) return animDef;
2325
+ const ch = channels[0];
2326
+ const chAnim = animDef[ch];
2327
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2328
+ const lifted = __spreadProps(__spreadValues({}, chAnim), {
2329
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
2330
+ });
2331
+ if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
2332
+ const rest = __spreadValues({}, animDef);
2333
+ delete rest[ch];
2334
+ return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2335
+ }
2336
+
2271
2337
  // src/materialize/PxMotionPath.ts
2272
2338
  function getKfTranslate(kf) {
2273
2339
  const v = keyframeValue(kf);
@@ -2637,7 +2703,7 @@ function walkAndMaterialize(node, opts) {
2637
2703
  let newAnimate;
2638
2704
  const animBucket = node.animate;
2639
2705
  if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
2640
- const animDef = animBucket;
2706
+ const animDef = mergeStaticTransformIntoAnimDef(animBucket, node.transform);
2641
2707
  const transformAnim = animDef.transform;
2642
2708
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
2643
2709
  const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
@@ -3151,36 +3217,6 @@ var _elementIdCounter = 0;
3151
3217
  function generateElementId() {
3152
3218
  return "_px_el_" + ++_elementIdCounter;
3153
3219
  }
3154
- function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
3155
- if (!animDef) return animDef;
3156
- const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
3157
- if (!staticParts || !Object.keys(staticParts).length) return animDef;
3158
- const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
3159
- const transformAnim = animDef[TRANSFORM_ATTR];
3160
- if (transformAnim && typeof transformAnim === "object") {
3161
- const anim = transformAnim;
3162
- if (Array.isArray(anim.keyframes)) {
3163
- const out = __spreadProps(__spreadValues({}, anim), {
3164
- keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
3165
- });
3166
- if (out.value !== void 0) out.value = mergeKfValue(out.value);
3167
- return __spreadProps(__spreadValues({}, animDef), { transform: out });
3168
- }
3169
- return animDef;
3170
- }
3171
- const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
3172
- if (channels.length !== 1) return animDef;
3173
- const ch = channels[0];
3174
- const chAnim = animDef[ch];
3175
- if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
3176
- const lifted = __spreadProps(__spreadValues({}, chAnim), {
3177
- keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
3178
- });
3179
- if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
3180
- const rest = __spreadValues({}, animDef);
3181
- delete rest[ch];
3182
- return __spreadProps(__spreadValues({}, rest), { transform: lifted });
3183
- }
3184
3220
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
3185
3221
  const normalized = {};
3186
3222
  for (const [propName, propAnim] of Object.entries(animDef)) {
@@ -3263,7 +3299,7 @@ function getKeyframesPair(keyframes, progress) {
3263
3299
  return { prevKf, nextKf };
3264
3300
  }
3265
3301
  function calcPropertyValue(propName, propAnim, progress) {
3266
- var _a2, _b, _c, _d;
3302
+ var _a2, _b, _c, _d, _e;
3267
3303
  const keyframes = propAnim.keyframes || [];
3268
3304
  if (keyframes.length === 0) return null;
3269
3305
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
@@ -3332,7 +3368,7 @@ function calcPropertyValue(propName, propAnim, progress) {
3332
3368
  !!propAnim.autoOrient
3333
3369
  );
3334
3370
  partsResult.translate = [sample.translate[0], sample.translate[1]];
3335
- if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
3371
+ if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg + ((_e = partsResult.rotate) != null ? _e : 0);
3336
3372
  }
3337
3373
  }
3338
3374
  cssValue = composeTransformParts(partsResult, { withUnits: false });
@@ -3618,12 +3654,12 @@ function deepClonePxNode(value) {
3618
3654
  for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
3619
3655
  return out;
3620
3656
  }
3621
- function regenerateIdsAndRewriteRefs(root, genId2) {
3657
+ function regenerateIdsAndRewriteRefs(root, genId3) {
3622
3658
  const oldToNew = /* @__PURE__ */ new Map();
3623
3659
  const walkAssign = (n) => {
3624
3660
  var _a2;
3625
3661
  if (typeof n.id === "string") {
3626
- const newId = genId2();
3662
+ const newId = genId3();
3627
3663
  oldToNew.set(n.id, newId);
3628
3664
  n.id = newId;
3629
3665
  }
@@ -4409,6 +4445,1956 @@ function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pat
4409
4445
  return materializeGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
4410
4446
  }
4411
4447
 
4448
+ // src/effects/transform/transformationEffect.ts
4449
+ function applyTransformByEffect(node, fx, ctx) {
4450
+ if (!fx) return node;
4451
+ delete node.transform;
4452
+ let n = node;
4453
+ n = wrapOrigin(
4454
+ n,
4455
+ fx.origin,
4456
+ /*invert=*/
4457
+ true
4458
+ );
4459
+ n = wrapTransformPart(n, "scale" /* Scale */, normalizeScale(fx.scale), ctx);
4460
+ n = wrapTransformPart(n, "skew" /* Skew */, fx.skew, ctx);
4461
+ n = wrapTransformPart(n, "rotate" /* Rotate */, fx.rotate, ctx);
4462
+ n = wrapOrigin(
4463
+ n,
4464
+ fx.origin,
4465
+ /*invert=*/
4466
+ false
4467
+ );
4468
+ if (translateHasAutoOrient(fx.translate)) {
4469
+ n = wrapOrigin(
4470
+ n,
4471
+ fx.origin,
4472
+ /*invert=*/
4473
+ true
4474
+ );
4475
+ n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
4476
+ n = wrapOrigin(
4477
+ n,
4478
+ fx.origin,
4479
+ /*invert=*/
4480
+ false
4481
+ );
4482
+ } else {
4483
+ n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
4484
+ }
4485
+ if (n !== node && node.id) {
4486
+ n.id = node.id;
4487
+ delete node.id;
4488
+ }
4489
+ return n;
4490
+ }
4491
+ function translateHasAutoOrient(translate) {
4492
+ if (!translate || typeof translate !== "object") return false;
4493
+ const obj = translate;
4494
+ if (obj.autoOrient) return true;
4495
+ return Array.isArray(obj.keyframes) && obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
4496
+ }
4497
+ function normalizeScale(raw) {
4498
+ return raw;
4499
+ }
4500
+ function wrapTransformPart(inner, part, raw, ctx) {
4501
+ if (raw === void 0) return inner;
4502
+ const v = readAnimatable(raw);
4503
+ if (v.kind === "static" /* Static */) {
4504
+ return { type: "g", transform: { value: partsRecord(part, v.value, void 0) }, children: [inner] };
4505
+ }
4506
+ if (v.kind === "animated" /* Animated */) {
4507
+ const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
4508
+ if (v.autoOrient) animTr.autoOrient = true;
4509
+ if (v.loop !== void 0) animTr.loop = v.loop;
4510
+ return {
4511
+ type: "g",
4512
+ animate: { transform: animTr },
4513
+ children: [inner]
4514
+ };
4515
+ }
4516
+ return inner;
4517
+ }
4518
+ function wrapOrigin(inner, raw, invert) {
4519
+ if (raw === void 0) return inner;
4520
+ const v = readAnimatable(raw);
4521
+ const sign = (value) => invert ? [-value[0], -value[1]] : value;
4522
+ if (v.kind === "absent" /* Absent */) return inner;
4523
+ if (v.kind === "static" /* Static */) {
4524
+ if (v.value[0] === 0 && v.value[1] === 0) return inner;
4525
+ return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
4526
+ }
4527
+ if (v.kind === "animated" /* Animated */) {
4528
+ const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) };
4529
+ if (v.loop !== void 0) animTr.loop = v.loop;
4530
+ return {
4531
+ type: "g",
4532
+ animate: { transform: animTr },
4533
+ children: [inner]
4534
+ };
4535
+ }
4536
+ return inner;
4537
+ }
4538
+
4539
+ // src/effects/reference/contentRefSplit.ts
4540
+ function identifyContentRefTargets(node, ctx, allocator) {
4541
+ var _a2, _b, _c;
4542
+ if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
4543
+ const sourceId = stripHash(node.effects.clone.source);
4544
+ if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
4545
+ ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
4546
+ }
4547
+ }
4548
+ (_c = node.children) == null ? void 0 : _c.forEach((c) => identifyContentRefTargets(c, ctx, allocator));
4549
+ }
4550
+ function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
4551
+ const outerBody = liftBodyTranslate(node, transformBy);
4552
+ if (typeof node.id === "string") delete node.id;
4553
+ const { outer: outerTr, inner: innerTr } = splitTransformByEffect(transformBy);
4554
+ let innerNode = node;
4555
+ innerNode = applyTransformByEffect(innerNode, innerTr, ctx);
4556
+ const innerWrapper = { type: "g", id: innerId, children: [innerNode] };
4557
+ let outerWrapper = { type: "g", id: originalId, children: [innerWrapper] };
4558
+ if (outerBody.transform !== void 0) outerWrapper.transform = outerBody.transform;
4559
+ if (outerBody.animate !== void 0) outerWrapper.animate = outerBody.animate;
4560
+ if (outerTr) {
4561
+ delete outerWrapper.id;
4562
+ outerWrapper = applyTransformByEffect(outerWrapper, outerTr, ctx);
4563
+ outerWrapper.id = originalId;
4564
+ }
4565
+ return outerWrapper;
4566
+ }
4567
+ function liftBodyTranslate(node, transformBy) {
4568
+ var _a2, _b, _c;
4569
+ const out = {};
4570
+ let didLiftAnimate = false;
4571
+ const animTr = (_a2 = node.animate) == null ? void 0 : _a2.transform;
4572
+ if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
4573
+ const kfs = animTr.keyframes;
4574
+ const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
4575
+ if (hasTranslate) {
4576
+ const outerHasOrigin = needsOriginOnOuter(animTr);
4577
+ const outerKfs = kfs.map((kf) => {
4578
+ const v = kf.value || {};
4579
+ const newValue = {};
4580
+ if (v.translate !== void 0) newValue.translate = v.translate;
4581
+ if (outerHasOrigin && v.origin !== void 0) newValue.origin = v.origin;
4582
+ const outerKf = { value: newValue };
4583
+ if (kf.time !== void 0) outerKf.time = kf.time;
4584
+ if (kf.easing !== void 0) outerKf.easing = kf.easing;
4585
+ if (kf.tangentOut !== void 0) outerKf.tangentOut = kf.tangentOut;
4586
+ if (kf.tangentIn !== void 0) outerKf.tangentIn = kf.tangentIn;
4587
+ return outerKf;
4588
+ });
4589
+ const outerAnimTr = { keyframes: outerKfs };
4590
+ if (animTr.autoOrient) outerAnimTr.autoOrient = true;
4591
+ const srcLoop = animTr.loop;
4592
+ if (srcLoop !== void 0) outerAnimTr.loop = srcLoop;
4593
+ out.animate = { transform: outerAnimTr };
4594
+ const innerHasPivotedPart = kfs.some((kf) => {
4595
+ const v = kf.value || {};
4596
+ return v.rotate !== void 0 || v.scale !== void 0;
4597
+ });
4598
+ const innerKfs = kfs.map((kf) => {
4599
+ const v = kf.value || {};
4600
+ const newValue = {};
4601
+ if (v.rotate !== void 0) newValue.rotate = v.rotate;
4602
+ if (v.scale !== void 0) newValue.scale = v.scale;
4603
+ if (v.origin !== void 0 && (!outerHasOrigin || innerHasPivotedPart)) newValue.origin = v.origin;
4604
+ const innerKf = { value: newValue };
4605
+ if (kf.time !== void 0) innerKf.time = kf.time;
4606
+ if (kf.easing !== void 0) innerKf.easing = kf.easing;
4607
+ return innerKf;
4608
+ });
4609
+ const allInnerEmpty = innerKfs.every((kf) => Object.keys(kf.value).length === 0);
4610
+ if (allInnerEmpty) {
4611
+ delete node.animate.transform;
4612
+ if (node.animate && Object.keys(node.animate).length === 0) delete node.animate;
4613
+ } else {
4614
+ const innerAnimTr = { keyframes: innerKfs };
4615
+ if (srcLoop !== void 0) innerAnimTr.loop = srcLoop;
4616
+ node.animate.transform = innerAnimTr;
4617
+ }
4618
+ didLiftAnimate = true;
4619
+ }
4620
+ }
4621
+ const transformationHasTranslate = (transformBy == null ? void 0 : transformBy.translate) !== void 0;
4622
+ const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
4623
+ 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);
4624
+ if (typeof node.transform === "string") {
4625
+ const split = splitTransformString(node.transform);
4626
+ if (stripBodyTranslateOnly) {
4627
+ if (split.translate !== void 0) {
4628
+ if (split.rest) node.transform = split.rest;
4629
+ else delete node.transform;
4630
+ } else if (isPureTranslateBody(node.transform)) {
4631
+ delete node.transform;
4632
+ } else if (liftedAnimateIsAutoOriented && isSingleMatrixBody(node.transform)) {
4633
+ delete node.transform;
4634
+ }
4635
+ } else if (split.translate) {
4636
+ out.transform = split.translate;
4637
+ if (split.rest) node.transform = split.rest;
4638
+ else delete node.transform;
4639
+ }
4640
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes) {
4641
+ const wrapped = node.transform.value;
4642
+ const isWrapped = !!(wrapped && typeof wrapped === "object");
4643
+ const value = isWrapped ? wrapped : node.transform;
4644
+ const rewrap = (rec) => isWrapped ? { value: rec } : rec;
4645
+ if (Array.isArray(value.translate)) {
4646
+ const rest = __spreadValues({}, value);
4647
+ delete rest.translate;
4648
+ const hasRest = Object.keys(rest).length > 0;
4649
+ if (stripBodyTranslateOnly) {
4650
+ if (hasRest) node.transform = rewrap(rest);
4651
+ else delete node.transform;
4652
+ } else {
4653
+ out.transform = rewrap({ translate: value.translate });
4654
+ if (hasRest) node.transform = rewrap(rest);
4655
+ else delete node.transform;
4656
+ }
4657
+ }
4658
+ }
4659
+ return out;
4660
+ }
4661
+ function isSingleMatrixBody(s) {
4662
+ const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
4663
+ let count = 0;
4664
+ let isMatrix = false;
4665
+ let m;
4666
+ while (m = re.exec(s)) {
4667
+ count++;
4668
+ if (m[1] === "matrix") isMatrix = true;
4669
+ }
4670
+ return count === 1 && isMatrix;
4671
+ }
4672
+ function isPureTranslateBody(s) {
4673
+ const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
4674
+ const ops = [];
4675
+ let m;
4676
+ while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
4677
+ if (ops.length !== 1) return false;
4678
+ if (ops[0].name === "translate") return true;
4679
+ if (ops[0].name !== "matrix") return false;
4680
+ const args = /matrix\(([^)]*)\)/.exec(ops[0].full);
4681
+ if (!args) return false;
4682
+ const nums = args[1].split(/[\s,]+/).filter(Boolean).map(Number);
4683
+ return nums.length >= 4 && nums[0] === 1 && nums[1] === 0 && nums[2] === 0 && nums[3] === 1;
4684
+ }
4685
+ function splitTransformString(s) {
4686
+ const ops = [];
4687
+ const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
4688
+ let m;
4689
+ while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
4690
+ if (!ops.length) return { rest: s || void 0 };
4691
+ if (ops.every((o) => o.name === "translate")) {
4692
+ return { translate: ops.map((o) => o.full).join("") };
4693
+ }
4694
+ const leading = ops[0];
4695
+ const trailing = ops[ops.length - 1];
4696
+ if (trailing.name === "translate" && leading.name === "translate") {
4697
+ const trailingVec = parseTranslateArgs(trailing.full);
4698
+ const leadingVec = parseTranslateArgs(leading.full);
4699
+ const ox = -trailingVec[0];
4700
+ const oy = -trailingVec[1];
4701
+ const userTx = leadingVec[0] - ox;
4702
+ const userTy = leadingVec[1] - oy;
4703
+ if (userTx === 0 && userTy === 0) return { rest: s };
4704
+ const middleAndTrailing = "translate(" + ox + "," + oy + ")" + ops.slice(1).map((o) => o.full).join("");
4705
+ return { translate: "translate(" + userTx + "," + userTy + ")", rest: middleAndTrailing };
4706
+ }
4707
+ if (trailing.name === "translate") return { rest: s };
4708
+ const lifted = [];
4709
+ let i = 0;
4710
+ while (i < ops.length && ops[i].name === "translate") {
4711
+ lifted.push(ops[i].full);
4712
+ i++;
4713
+ }
4714
+ if (!lifted.length) return { rest: s };
4715
+ const rest = ops.slice(i).map((o) => o.full).join("");
4716
+ return {
4717
+ translate: lifted.join(""),
4718
+ rest: rest || void 0
4719
+ };
4720
+ }
4721
+ function parseTranslateArgs(translateOp) {
4722
+ const m = /translate\(([^)]*)\)/.exec(translateOp);
4723
+ if (!m) return [0, 0];
4724
+ const nums = m[1].split(/[\s,]+/).filter(Boolean).map(Number);
4725
+ return [nums[0] || 0, nums[1] || 0];
4726
+ }
4727
+ function splitTransformByEffect(fx) {
4728
+ if (!fx) return {};
4729
+ const originOnOuter = needsOriginOnOuter(fx.translate);
4730
+ const innerHasPivotedPart = fx.rotate !== void 0 || fx.scale !== void 0;
4731
+ const outer = {};
4732
+ const inner = {};
4733
+ if (fx.translate !== void 0) outer.translate = fx.translate;
4734
+ if (originOnOuter && fx.origin !== void 0) outer.origin = fx.origin;
4735
+ if (fx.rotate !== void 0) inner.rotate = fx.rotate;
4736
+ if (fx.scale !== void 0) inner.scale = fx.scale;
4737
+ if (fx.skew !== void 0) inner.skew = fx.skew;
4738
+ if (fx.origin !== void 0 && (!originOnOuter || innerHasPivotedPart)) inner.origin = fx.origin;
4739
+ return {
4740
+ outer: Object.keys(outer).length ? outer : void 0,
4741
+ inner: Object.keys(inner).length ? inner : void 0
4742
+ };
4743
+ }
4744
+ function needsOriginOnOuter(translateAnim) {
4745
+ if (!translateAnim || typeof translateAnim !== "object") return false;
4746
+ const obj = translateAnim;
4747
+ if (obj.autoOrient) return true;
4748
+ if (Array.isArray(obj.keyframes)) {
4749
+ return obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
4750
+ }
4751
+ return false;
4752
+ }
4753
+
4754
+ // src/effects/paint/gradientEffect.ts
4755
+ function applyFillGradientEffect(node, fx, ctx) {
4756
+ return applyGradient(node, fx, ctx, "fill");
4757
+ }
4758
+ function applyStrokeGradientEffect(node, fx, ctx) {
4759
+ return applyGradient(node, fx, ctx, "stroke");
4760
+ }
4761
+ function applyGradient(node, fx, ctx, attr) {
4762
+ if (!fx) return node;
4763
+ const id = genId(ctx, "grad");
4764
+ const def = synthesiseGradientDef(fx, id, ctx);
4765
+ ctx.defs.push(def);
4766
+ node[attr] = "url(#" + id + ")";
4767
+ return node;
4768
+ }
4769
+ function synthesiseGradientDef(fx, id, ctx) {
4770
+ const out = {
4771
+ type: fx.type === PxGradientType.radial ? "radialGradient" : "linearGradient",
4772
+ id
4773
+ };
4774
+ if (fx.type === PxGradientType.linear) {
4775
+ applyGeomVec(out, "x1", "y1", fx.start);
4776
+ applyGeomVec(out, "x2", "y2", fx.end);
4777
+ } else {
4778
+ applyGeomVec(out, "cx", "cy", fx.center);
4779
+ applyGeomNumber(out, "r", fx.radius);
4780
+ applyGeomVec(out, "fx", "fy", fx.focal);
4781
+ }
4782
+ if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
4783
+ if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
4784
+ if (fx.gradientTransform) out.gradientTransform = fx.gradientTransform;
4785
+ out.children = buildStopChildren(fx.stops, ctx);
4786
+ return out;
4787
+ }
4788
+ function applyGeomVec(out, xAttr, yAttr, raw) {
4789
+ var _a2, _b, _c;
4790
+ const read = readAnimatable(raw);
4791
+ if (read.kind === "absent" /* Absent */) return;
4792
+ if (read.kind === "static" /* Static */) {
4793
+ out[xAttr] = String(read.value[0]);
4794
+ out[yAttr] = String(read.value[1]);
4795
+ return;
4796
+ }
4797
+ const axisChannel = (idx) => {
4798
+ const block = {
4799
+ keyframes: read.keyframes.map((kf) => {
4800
+ const axisKf = { time: kf.time, value: Array.isArray(kf.value) ? kf.value[idx] : void 0 };
4801
+ if (kf.easing !== void 0) axisKf.easing = kf.easing;
4802
+ return axisKf;
4803
+ })
4804
+ };
4805
+ if (read.loop !== void 0) block.loop = read.loop;
4806
+ return block;
4807
+ };
4808
+ const animate = (_a2 = out.animate) != null ? _a2 : {};
4809
+ animate[xAttr] = axisChannel(0);
4810
+ animate[yAttr] = axisChannel(1);
4811
+ out.animate = animate;
4812
+ const baseline = (_c = read.base) != null ? _c : (_b = read.keyframes[0]) == null ? void 0 : _b.value;
4813
+ if (Array.isArray(baseline)) {
4814
+ out[xAttr] = String(baseline[0]);
4815
+ out[yAttr] = String(baseline[1]);
4816
+ }
4817
+ }
4818
+ function applyGeomNumber(out, attrName, raw) {
4819
+ const read = readAnimatable(raw);
4820
+ if (read.kind === "absent" /* Absent */) return;
4821
+ writeAnimatableChannel(out, attrName, read, { asString: true });
4822
+ }
4823
+ function buildStopChildren(stops, ctx) {
4824
+ var _a2, _b;
4825
+ if (!stops) return [];
4826
+ const read = readAnimatable(stops);
4827
+ if (read.kind === "absent" /* Absent */) return [];
4828
+ if (read.kind === "static" /* Static */) return Array.isArray(read.value) ? read.value.map(staticStopNode) : [];
4829
+ const kfs = read.keyframes;
4830
+ if (!kfs.length) return [];
4831
+ const loopFromSource = read.loop;
4832
+ let stopCount = 0;
4833
+ for (const kf of kfs) {
4834
+ const v = keyframeValue(kf);
4835
+ if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
4836
+ }
4837
+ if (!stopCount) return [];
4838
+ const firstKfValue = keyframeValue(kfs[0]);
4839
+ const baselineStops = [];
4840
+ for (let i = 0; i < stopCount; i++) {
4841
+ const s = (_b = (_a2 = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _a2 : prevDefinedStop(kfs, 0, i)) != null ? _b : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
4842
+ baselineStops.push({ offset: s.offset, color: s.color });
4843
+ }
4844
+ return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
4845
+ }
4846
+ function staticStopNode(s) {
4847
+ return {
4848
+ type: "stop",
4849
+ offset: formatOffset(s.offset),
4850
+ stopColor: s.color
4851
+ };
4852
+ }
4853
+ function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
4854
+ var _a2;
4855
+ const colorKfs = [];
4856
+ const offsetKfs = [];
4857
+ let offsetVaries = false;
4858
+ for (const kf of kfs) {
4859
+ const t = keyframeTime(kf);
4860
+ const arr = keyframeValue(kf);
4861
+ const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
4862
+ if (!sliced) continue;
4863
+ const easing = keyframeEasing(kf);
4864
+ const colorOut = { time: t, value: sliced.color };
4865
+ if (easing !== void 0) colorOut.easing = easing;
4866
+ colorKfs.push(colorOut);
4867
+ const offsetOut = { time: t, value: sliced.offset };
4868
+ if (easing !== void 0) offsetOut.easing = easing;
4869
+ offsetKfs.push(offsetOut);
4870
+ if (sliced.offset !== baseline.offset) offsetVaries = true;
4871
+ }
4872
+ const stop = {
4873
+ type: "stop",
4874
+ offset: formatOffset(baseline.offset),
4875
+ stopColor: baseline.color
4876
+ };
4877
+ const animate = {};
4878
+ if (colorKfs.length) {
4879
+ animate.stopColor = { keyframes: colorKfs };
4880
+ if (loop !== void 0) animate.stopColor.loop = loop;
4881
+ }
4882
+ if (offsetVaries && offsetKfs.length) {
4883
+ animate.offset = { keyframes: offsetKfs };
4884
+ if (loop !== void 0) animate.offset.loop = loop;
4885
+ }
4886
+ if (Object.keys(animate).length) stop.animate = animate;
4887
+ return stop;
4888
+ }
4889
+ function prevDefinedStop(kfs, fromIdx, stopIdx) {
4890
+ for (let i = fromIdx; i >= 0; i--) {
4891
+ const arr = keyframeValue(kfs[i]);
4892
+ if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
4893
+ }
4894
+ for (let i = fromIdx + 1; i < kfs.length; i++) {
4895
+ const arr = keyframeValue(kfs[i]);
4896
+ if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
4897
+ }
4898
+ return void 0;
4899
+ }
4900
+ function formatOffset(o) {
4901
+ const pct = Math.round(o * 1e3) / 10;
4902
+ return pct + "%";
4903
+ }
4904
+
4905
+ // src/effects/clipping/clipPathEffect.ts
4906
+ function applyClipPathEffect(node, fx, ctx) {
4907
+ if (!(fx == null ? void 0 : fx.pathData)) return node;
4908
+ const clipId = genId(ctx, "clip");
4909
+ const pathChild = { type: "path" };
4910
+ const read = readAnimatable(fx.pathData);
4911
+ if (read.kind !== "absent" /* Absent */) {
4912
+ if (read.kind === "static" /* Static */) {
4913
+ pathChild.d = pathString(read.value);
4914
+ } else {
4915
+ writeAnimatableChannel(pathChild, "d", read);
4916
+ if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
4917
+ }
4918
+ }
4919
+ ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
4920
+ node.clipPath = "url(#" + clipId + ")";
4921
+ return node;
4922
+ }
4923
+ function pathString(v) {
4924
+ if (typeof v === "string") return v;
4925
+ if (v && typeof v === "object" && typeof v.pathData === "string") return v.pathData;
4926
+ return void 0;
4927
+ }
4928
+
4929
+ // src/effects/clipping/maskedByEffect.ts
4930
+ function applyMaskedByEffect(node, fx, transformBy, ctx) {
4931
+ if (!fx) return node;
4932
+ const sourceId = stripHash(fx.source);
4933
+ if (!sourceId) {
4934
+ ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
4935
+ return node;
4936
+ }
4937
+ const maskId = genId(ctx, "mask");
4938
+ let content = { type: "use", href: "#" + sourceId };
4939
+ if (transformBy) {
4940
+ content = wrapInverseTransform(content, transformBy, ctx);
4941
+ } else if (hasAnimateTransform(node)) {
4942
+ content = wrapInverseAnimatedBodyTransform(content, node, ctx);
4943
+ } else {
4944
+ const bodyStatic = readTransformationFromBody(node);
4945
+ if (bodyStatic) content = wrapInverseTransform(content, bodyStatic, ctx);
4946
+ }
4947
+ const includeTargetOwn = transformBy === void 0 && !nodeHasBodyTransform(node);
4948
+ content = wrapAncestorChainCompensation(content, node, sourceId, ctx, includeTargetOwn);
4949
+ const mask = { type: "mask", id: maskId, children: [content] };
4950
+ if (fx.maskType) mask.maskType = fx.maskType;
4951
+ if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
4952
+ if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
4953
+ if (fx.x !== void 0) mask.x = String(fx.x);
4954
+ if (fx.y !== void 0) mask.y = String(fx.y);
4955
+ if (fx.width !== void 0) mask.width = String(fx.width);
4956
+ if (fx.height !== void 0) mask.height = String(fx.height);
4957
+ ctx.defs.push(mask);
4958
+ node.mask = "url(#" + maskId + ")";
4959
+ return node;
4960
+ }
4961
+ function wrapInverseTransform(inner, fx, ctx) {
4962
+ if (!fx) return inner;
4963
+ const origin = readStaticOrigin(fx.origin, ctx);
4964
+ let n = inner;
4965
+ n = wrapInversePart(n, "translate" /* Translate */, fx.translate, void 0, ctx);
4966
+ n = wrapInversePart(n, "rotate" /* Rotate */, fx.rotate, origin, ctx);
4967
+ n = wrapInversePart(n, "scale" /* Scale */, fx.scale, origin, ctx);
4968
+ return n;
4969
+ }
4970
+ function wrapInversePart(inner, part, raw, origin, ctx) {
4971
+ if (raw === void 0) return inner;
4972
+ const normalizedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
4973
+ const v = readAnimatable(normalizedRaw);
4974
+ if (v.kind === "static" /* Static */) {
4975
+ return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
4976
+ }
4977
+ if (v.kind === "animated" /* Animated */) {
4978
+ const animTr = { keyframes: v.keyframes.map((kf) => {
4979
+ const out = keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin));
4980
+ return part === "translate" /* Translate */ ? __spreadValues(__spreadValues({}, out), negatedSpatialTangents(kf)) : out;
4981
+ }) };
4982
+ if (v.loop !== void 0) animTr.loop = v.loop;
4983
+ return {
4984
+ type: "g",
4985
+ animate: { transform: animTr },
4986
+ children: [inner]
4987
+ };
4988
+ }
4989
+ return inner;
4990
+ }
4991
+ function invertPartValue(part, value) {
4992
+ if (part === "translate" /* Translate */) return [-value[0], -value[1]];
4993
+ if (part === "rotate" /* Rotate */) return -value;
4994
+ return [1 / value[0], 1 / value[1]];
4995
+ }
4996
+ function negatedSpatialTangents(kf) {
4997
+ var _a2, _b;
4998
+ const out = {};
4999
+ const to = (_a2 = kf.tangentOut) != null ? _a2 : kf.to;
5000
+ const ti = (_b = kf.tangentIn) != null ? _b : kf.ti;
5001
+ if (Array.isArray(to)) out.tangentOut = [-to[0], -to[1]];
5002
+ if (Array.isArray(ti)) out.tangentIn = [-ti[0], -ti[1]];
5003
+ return out;
5004
+ }
5005
+ function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
5006
+ var _a2;
5007
+ const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
5008
+ const animTr = animate == null ? void 0 : animate.transform;
5009
+ const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
5010
+ if (!kfs || !kfs.length) return inner;
5011
+ const translateKfs = [];
5012
+ const rotateKfs = [];
5013
+ const scaleKfs = [];
5014
+ for (const kf of kfs) {
5015
+ const v = ((_a2 = kf.value) != null ? _a2 : kf.v) || {};
5016
+ const baseKf = keyframeWith(kf, void 0);
5017
+ if (Array.isArray(v.translate)) {
5018
+ translateKfs.push(__spreadProps(__spreadValues(__spreadValues({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
5019
+ }
5020
+ if (typeof v.rotate === "number") {
5021
+ const rec = { rotate: -v.rotate };
5022
+ if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
5023
+ rotateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
5024
+ }
5025
+ if (Array.isArray(v.scale)) {
5026
+ const rec = { scale: [1 / v.scale[0], 1 / v.scale[1]] };
5027
+ if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
5028
+ scaleKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
5029
+ }
5030
+ }
5031
+ const srcLoop = animTr == null ? void 0 : animTr.loop;
5032
+ const withLoop = (kfs2) => {
5033
+ const block = { keyframes: kfs2 };
5034
+ if (srcLoop !== void 0) block.loop = srcLoop;
5035
+ return block;
5036
+ };
5037
+ let n = inner;
5038
+ if (translateKfs.length) n = { type: "g", animate: { transform: withLoop(translateKfs) }, children: [n] };
5039
+ if (rotateKfs.length) n = { type: "g", animate: { transform: withLoop(rotateKfs) }, children: [n] };
5040
+ if (scaleKfs.length) n = { type: "g", animate: { transform: withLoop(scaleKfs) }, children: [n] };
5041
+ return n;
5042
+ }
5043
+ function nodeHasBodyTransform(node) {
5044
+ if (typeof node.transform === "string") return true;
5045
+ if (node.transform && typeof node.transform === "object") return true;
5046
+ return hasAnimateTransform(node);
5047
+ }
5048
+ function hasAnimateTransform(node) {
5049
+ const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
5050
+ return !!(animate && animate.transform);
5051
+ }
5052
+ function readTransformationFromBody(node) {
5053
+ if (typeof node.transform === "string") {
5054
+ const parts = parseTransformStringToParts(node.transform);
5055
+ if (!parts) return void 0;
5056
+ const out = {};
5057
+ if (parts.translate) out.translate = parts.translate;
5058
+ if (parts.rotate !== void 0) out.rotate = parts.rotate;
5059
+ if (parts.scale) out.scale = { value: parts.scale };
5060
+ if (parts.origin) out.origin = parts.origin;
5061
+ return Object.keys(out).length ? out : void 0;
5062
+ }
5063
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes) {
5064
+ const wrapped = node.transform.value;
5065
+ const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
5066
+ if (value && typeof value === "object") {
5067
+ const out = {};
5068
+ if (Array.isArray(value.translate)) out.translate = value.translate;
5069
+ if (typeof value.rotate === "number") out.rotate = value.rotate;
5070
+ if (typeof value.skew === "number") out.skew = value.skew;
5071
+ if (Array.isArray(value.scale)) out.scale = { value: value.scale };
5072
+ if (Array.isArray(value.origin)) out.origin = value.origin;
5073
+ return Object.keys(out).length ? out : void 0;
5074
+ }
5075
+ }
5076
+ return void 0;
5077
+ }
5078
+ function parseTransformStringToParts(s) {
5079
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
5080
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
5081
+ let m;
5082
+ const ops = [];
5083
+ while ((m = re.exec(s)) !== null) {
5084
+ const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
5085
+ ops.push({ name: m[1], args });
5086
+ }
5087
+ if (!ops.length) return void 0;
5088
+ const last = ops[ops.length - 1];
5089
+ if (last.name === "translate") {
5090
+ for (let j = ops.length - 2; j >= 0; j--) {
5091
+ const cand = ops[j];
5092
+ if (cand.name !== "translate") continue;
5093
+ const ox = (_a2 = cand.args[0]) != null ? _a2 : 0;
5094
+ const oy = (_b = cand.args[1]) != null ? _b : 0;
5095
+ const lx = (_c = last.args[0]) != null ? _c : 0;
5096
+ const ly = (_d = last.args[1]) != null ? _d : 0;
5097
+ if (lx !== -ox || ly !== -oy) continue;
5098
+ const out2 = {};
5099
+ out2.origin = [ox, oy];
5100
+ for (let k = 0; k < j; k++) {
5101
+ if (ops[k].name === "translate") {
5102
+ const tx = (_e = ops[k].args[0]) != null ? _e : 0;
5103
+ const ty = (_f = ops[k].args[1]) != null ? _f : 0;
5104
+ out2.translate = out2.translate ? [out2.translate[0] + tx, out2.translate[1] + ty] : [tx, ty];
5105
+ }
5106
+ }
5107
+ for (let k = j + 1; k < ops.length - 1; k++) {
5108
+ const op = ops[k];
5109
+ if (op.name === "rotate") out2.rotate = ((_g = out2.rotate) != null ? _g : 0) + ((_h = op.args[0]) != null ? _h : 0);
5110
+ else if (op.name === "scale") {
5111
+ const sx = (_i = op.args[0]) != null ? _i : 1;
5112
+ const sy = op.args.length > 1 ? op.args[1] : sx;
5113
+ out2.scale = out2.scale ? [out2.scale[0] * sx, out2.scale[1] * sy] : [sx, sy];
5114
+ }
5115
+ }
5116
+ return out2;
5117
+ }
5118
+ }
5119
+ let translate;
5120
+ let rotate;
5121
+ let scale;
5122
+ for (const op of ops) {
5123
+ if (op.name === "translate") {
5124
+ const dx = (_j = op.args[0]) != null ? _j : 0;
5125
+ const dy = (_k = op.args[1]) != null ? _k : 0;
5126
+ translate = translate ? [translate[0] + dx, translate[1] + dy] : [dx, dy];
5127
+ } else if (op.name === "rotate") {
5128
+ rotate = (rotate != null ? rotate : 0) + ((_l = op.args[0]) != null ? _l : 0);
5129
+ } else if (op.name === "scale") {
5130
+ const sx = (_m = op.args[0]) != null ? _m : 1;
5131
+ const sy = op.args.length > 1 ? op.args[1] : sx;
5132
+ scale = scale ? [scale[0] * sx, scale[1] * sy] : [sx, sy];
5133
+ }
5134
+ }
5135
+ const out = {};
5136
+ if (translate) out.translate = translate;
5137
+ if (rotate !== void 0) out.rotate = rotate;
5138
+ if (scale) out.scale = scale;
5139
+ return Object.keys(out).length ? out : void 0;
5140
+ }
5141
+ function wrapAncestorChainCompensation(inner, maskedNode, sourceId, ctx, includeTargetOwn) {
5142
+ const sourceNode = ctx.idMap.get(sourceId);
5143
+ const targetAncestors = ctx.maskAncestorChains.get(maskedNode) || [];
5144
+ const targetOwn = includeTargetOwn ? extractTranslateOnly(maskedNode, ctx) : void 0;
5145
+ const targetChain = targetOwn ? [...targetAncestors, targetOwn] : targetAncestors;
5146
+ const sourceChain = sourceNode && ctx.maskAncestorChains.get(sourceNode) || [];
5147
+ if (!targetChain.length && !sourceChain.length) return inner;
5148
+ const times = /* @__PURE__ */ new Set();
5149
+ for (const a of targetChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
5150
+ for (const a of sourceChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
5151
+ const animated = times.size > 0;
5152
+ if (!animated) {
5153
+ const tgt = sumStaticTranslate(targetChain);
5154
+ const src = sumStaticTranslate(sourceChain);
5155
+ const dx = src[0] - tgt[0];
5156
+ const dy = src[1] - tgt[1];
5157
+ if (dx === 0 && dy === 0) return inner;
5158
+ return { type: "g", transform: "translate(" + dx + "," + dy + ")", children: [inner] };
5159
+ }
5160
+ const sortedTimes = Array.from(times).sort((a, b) => a - b);
5161
+ const keyframes = sortedTimes.map((t) => {
5162
+ const tgt = sumTranslateAt(targetChain, t);
5163
+ const src = sumTranslateAt(sourceChain, t);
5164
+ return { time: t, value: { translate: [src[0] - tgt[0], src[1] - tgt[1]] } };
5165
+ });
5166
+ return { type: "g", animate: { transform: { keyframes } }, children: [inner] };
5167
+ }
5168
+ function sumStaticTranslate(chain) {
5169
+ let x = 0, y = 0;
5170
+ for (const a of chain) {
5171
+ if (a.translate) {
5172
+ x += a.translate[0];
5173
+ y += a.translate[1];
5174
+ }
5175
+ }
5176
+ return [x, y];
5177
+ }
5178
+ function sumTranslateAt(chain, t) {
5179
+ let x = 0, y = 0;
5180
+ for (const a of chain) {
5181
+ if (a.translateKeyframes && a.translateKeyframes.length) {
5182
+ const v = interpKfs(a.translateKeyframes, t);
5183
+ x += v[0];
5184
+ y += v[1];
5185
+ } else if (a.translate) {
5186
+ x += a.translate[0];
5187
+ y += a.translate[1];
5188
+ }
5189
+ }
5190
+ return [x, y];
5191
+ }
5192
+ function interpKfs(kfs, t) {
5193
+ if (t <= kfs[0].time) return kfs[0].value;
5194
+ if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
5195
+ for (let i = 1; i < kfs.length; i++) {
5196
+ if (t <= kfs[i].time) {
5197
+ const prev = kfs[i - 1];
5198
+ const cur = kfs[i];
5199
+ const a = (t - prev.time) / (cur.time - prev.time);
5200
+ return [prev.value[0] + (cur.value[0] - prev.value[0]) * a, prev.value[1] + (cur.value[1] - prev.value[1]) * a];
5201
+ }
5202
+ }
5203
+ return kfs[kfs.length - 1].value;
5204
+ }
5205
+ function collectMaskAncestorChains(root, ctx) {
5206
+ const interestingNodes = /* @__PURE__ */ new Set();
5207
+ const collectInterestingNodes = (n) => {
5208
+ var _a2, _b;
5209
+ const maskSourceId = stripHash((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
5210
+ if (typeof maskSourceId === "string") {
5211
+ interestingNodes.add(n);
5212
+ const sourceNode = ctx.idMap.get(maskSourceId);
5213
+ if (sourceNode) interestingNodes.add(sourceNode);
5214
+ }
5215
+ if (Array.isArray(n.children)) for (const ch of n.children) collectInterestingNodes(ch);
5216
+ };
5217
+ collectInterestingNodes(root);
5218
+ if (interestingNodes.size === 0) return;
5219
+ const walk = (node, chain) => {
5220
+ if (interestingNodes.has(node)) ctx.maskAncestorChains.set(node, chain);
5221
+ if (Array.isArray(node.children)) {
5222
+ const own = extractTranslateOnly(node, ctx);
5223
+ const next = own ? [...chain, own] : chain;
5224
+ for (const ch of node.children) walk(ch, next);
5225
+ }
5226
+ };
5227
+ walk(root, []);
5228
+ }
5229
+ function extractTranslateOnly(node, ctx) {
5230
+ var _a2, _b, _c;
5231
+ const tr = node.transform;
5232
+ const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
5233
+ if (tr === void 0 && !animateBlock) return void 0;
5234
+ const out = {};
5235
+ if (typeof tr === "string") {
5236
+ const parts = parseTranslateOnlyFromString(tr, ctx);
5237
+ if (parts) out.translate = parts;
5238
+ } else if (tr && typeof tr === "object" && !tr.keyframes) {
5239
+ const wrapped = tr.value;
5240
+ const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
5241
+ if (value && typeof value === "object" && Array.isArray(value.translate)) {
5242
+ out.translate = [value.translate[0] || 0, value.translate[1] || 0];
5243
+ }
5244
+ if (value && (value.rotate !== void 0 || value.scale !== void 0 || value.skew !== void 0)) {
5245
+ ctx.warnings.push("maskedBy ancestor: non-translate transform parts ignored (rotate/scale not yet supported)");
5246
+ }
5247
+ }
5248
+ if (animateBlock && Array.isArray(animateBlock.keyframes)) {
5249
+ const kfs = animateBlock.keyframes;
5250
+ const translateKfs = [];
5251
+ for (const kf of kfs) {
5252
+ const v = (_a2 = kf.value) != null ? _a2 : kf.v;
5253
+ const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
5254
+ if (v && typeof v === "object" && Array.isArray(v.translate)) {
5255
+ translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
5256
+ if (v.rotate !== void 0 || v.scale !== void 0 || v.skew !== void 0) {
5257
+ ctx.warnings.push("maskedBy ancestor: animated non-translate parts ignored");
5258
+ }
5259
+ }
5260
+ }
5261
+ if (translateKfs.length) out.translateKeyframes = translateKfs;
5262
+ }
5263
+ return out.translate || out.translateKeyframes ? out : void 0;
5264
+ }
5265
+ function parseTranslateOnlyFromString(s, ctx) {
5266
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
5267
+ let m;
5268
+ let x = 0, y = 0;
5269
+ let seen = false;
5270
+ let droppedNonTranslate = false;
5271
+ while ((m = re.exec(s)) !== null) {
5272
+ const name = m[1];
5273
+ const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
5274
+ if (name === "translate") {
5275
+ x += args[0] || 0;
5276
+ y += args[1] || 0;
5277
+ seen = true;
5278
+ } else {
5279
+ droppedNonTranslate = true;
5280
+ }
5281
+ }
5282
+ if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
5283
+ return seen ? [x, y] : void 0;
5284
+ }
5285
+
5286
+ // src/effects/reference/refEffect.ts
5287
+ function applyRefHref(node, clone2, ctx) {
5288
+ if (!clone2) return;
5289
+ const sourceId = stripHash(clone2.source);
5290
+ if (!sourceId) {
5291
+ if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
5292
+ return;
5293
+ }
5294
+ const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
5295
+ node.href = "#" + targetId;
5296
+ }
5297
+ function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
5298
+ applyRefHref(node, clone2, ctx);
5299
+ return applyTransformByEffect(node, transformBy, ctx);
5300
+ }
5301
+
5302
+ // src/effects/transform/repeaterEffect.ts
5303
+ function applyRepeaterEffect(node, fx, ctx) {
5304
+ var _a2, _b;
5305
+ if (!fx) return node;
5306
+ const copies = (_a2 = fx.copies) != null ? _a2 : 1;
5307
+ if (copies < 1) {
5308
+ ctx.errors.push("repeater.copies invalid: " + fx.copies);
5309
+ return node;
5310
+ }
5311
+ const sharedTransform = node.transform;
5312
+ const sharedAnimTransform = (_b = node.animate) == null ? void 0 : _b.transform;
5313
+ const base = clone(node);
5314
+ delete base.transform;
5315
+ if (base.animate) {
5316
+ delete base.animate.transform;
5317
+ if (Object.keys(base.animate).length === 0) delete base.animate;
5318
+ }
5319
+ delete base.id;
5320
+ const children = [base];
5321
+ for (let i = 1; i < copies; i++) {
5322
+ const baseClone = clone(base);
5323
+ const synthFx = synthesisePerCopyFx(fx, i);
5324
+ const wrapped = synthFx ? applyTransformByEffect(baseClone, synthFx, ctx) : baseClone;
5325
+ children.push(wrapped);
5326
+ }
5327
+ const wrapper = { type: "g", children };
5328
+ if (node.id) wrapper.id = node.id;
5329
+ if (sharedTransform !== void 0) wrapper.transform = sharedTransform;
5330
+ if (sharedAnimTransform !== void 0) wrapper.animate = { transform: sharedAnimTransform };
5331
+ return wrapper;
5332
+ }
5333
+ function synthesisePerCopyFx(fx, i) {
5334
+ const out = {};
5335
+ if (fx.translate !== void 0) {
5336
+ out.translate = mapAnimatable(fx.translate, (v) => [v[0] * i, v[1] * i]);
5337
+ }
5338
+ if (fx.rotate !== void 0) {
5339
+ out.rotate = mapAnimatable(fx.rotate, (v) => v * i);
5340
+ }
5341
+ if (fx.skew !== void 0) {
5342
+ out.skew = mapAnimatable(fx.skew, (v) => v * i);
5343
+ }
5344
+ if (fx.scale !== void 0) {
5345
+ out.scale = synthesiseScale(fx.scale, i);
5346
+ }
5347
+ if (fx.origin !== void 0) {
5348
+ out.origin = fx.origin;
5349
+ }
5350
+ return Object.keys(out).length ? out : void 0;
5351
+ }
5352
+ function mapAnimatable(raw, fn, wrapStatic = false) {
5353
+ const read = readAnimatable(raw);
5354
+ if (read.kind === "absent" /* Absent */) return raw;
5355
+ if (read.kind === "static" /* Static */) {
5356
+ const mapped = fn(read.value);
5357
+ const wasRawStatic = typeof raw === "number" || Array.isArray(raw);
5358
+ return wasRawStatic && !wrapStatic ? mapped : { value: mapped };
5359
+ }
5360
+ const out = {
5361
+ keyframes: read.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
5362
+ };
5363
+ if (read.loop !== void 0) out.loop = read.loop;
5364
+ if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
5365
+ if (read.base !== void 0) out.value = fn(read.base);
5366
+ return out;
5367
+ }
5368
+ function synthesiseScale(raw, i) {
5369
+ const scalePower = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
5370
+ return mapAnimatable(raw, scalePower, true);
5371
+ }
5372
+
5373
+ // src/effects/reference/retimeEffect.ts
5374
+ var RETIME_MATERIALIZATION_MODE_INLINE_G = false;
5375
+ function asRetime(r) {
5376
+ var _a2, _b;
5377
+ return { start: (_a2 = r.start) != null ? _a2 : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
5378
+ }
5379
+ var CROP_EDGE_MS = 1;
5380
+ function applyTimeCrop(useNode, crop, ctx) {
5381
+ const [start, end] = crop;
5382
+ if (!Number.isFinite(start) || !Number.isFinite(end)) {
5383
+ ctx.warnings.push("retime: timeCrop is not a pair of finite numbers \u2014 ignored");
5384
+ return;
5385
+ }
5386
+ const keyframes = end <= start ? [{ time: 0, value: 0 }] : [
5387
+ ...start > 0 ? [{ time: Math.max(0, start - CROP_EDGE_MS), value: 0 }] : [],
5388
+ { time: Math.max(0, start), value: 1 },
5389
+ { time: end, value: 1 },
5390
+ { time: end + CROP_EDGE_MS, value: 0 }
5391
+ ];
5392
+ const inner = __spreadValues({}, useNode);
5393
+ for (const k of Object.keys(useNode)) delete useNode[k];
5394
+ useNode.type = "g";
5395
+ useNode.children = [inner];
5396
+ useNode.animate = { opacity: { keyframes } };
5397
+ }
5398
+ function concatRetime(child, parent) {
5399
+ return {
5400
+ start: parent.start + parent.stretch * child.start,
5401
+ stretch: parent.stretch * child.stretch
5402
+ };
5403
+ }
5404
+ function readCloneRetime(n) {
5405
+ var _a2, _b;
5406
+ return (_b = (_a2 = n.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.retime;
5407
+ }
5408
+ function clearCloneRetime(n) {
5409
+ var _a2;
5410
+ const clone2 = (_a2 = n.effects) == null ? void 0 : _a2.clone;
5411
+ if (!clone2) return;
5412
+ delete clone2.retime;
5413
+ if (Object.keys(clone2).length === 0) delete n.effects.clone;
5414
+ if (n.effects && Object.keys(n.effects).length === 0) delete n.effects;
5415
+ }
5416
+ function applyAllRetimeEffects(root, ctx) {
5417
+ ctx.idMap.clear();
5418
+ indexById(root, ctx.idMap);
5419
+ const sites = [];
5420
+ const collect = (n) => {
5421
+ var _a2;
5422
+ if (readCloneRetime(n)) sites.push(n);
5423
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(collect);
5424
+ };
5425
+ collect(root);
5426
+ const reachCount = /* @__PURE__ */ new Map();
5427
+ for (const site of sites) {
5428
+ let count = 0;
5429
+ const visited = /* @__PURE__ */ new Set();
5430
+ const walk = (n) => {
5431
+ var _a2;
5432
+ if (!n) return;
5433
+ if (n !== site && readCloneRetime(n)) count++;
5434
+ if (n.type === "use" && n.href) {
5435
+ const id = stripHash(n.href);
5436
+ if (id && !visited.has(id)) {
5437
+ visited.add(id);
5438
+ walk(ctx.idMap.get(id));
5439
+ }
5440
+ }
5441
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
5442
+ };
5443
+ const rootId = stripHash(site.href);
5444
+ if (rootId) {
5445
+ visited.add(rootId);
5446
+ walk(ctx.idMap.get(rootId));
5447
+ }
5448
+ reachCount.set(site, count);
5449
+ }
5450
+ sites.sort((a, b) => {
5451
+ var _a2, _b;
5452
+ return ((_a2 = reachCount.get(b)) != null ? _a2 : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
5453
+ });
5454
+ for (const useNode of sites) {
5455
+ const retime = readCloneRetime(useNode);
5456
+ if (!retime) continue;
5457
+ const crop = retime.timeCrop;
5458
+ clearCloneRetime(useNode);
5459
+ materializeRetime(useNode, asRetime(retime), ctx);
5460
+ if (crop) applyTimeCrop(useNode, crop, ctx);
5461
+ }
5462
+ }
5463
+ function materializeRetime(useNode, retime, ctx) {
5464
+ const targetId = stripHash(useNode.href);
5465
+ if (!targetId) {
5466
+ ctx.errors.push("retime: <use> has no href to follow");
5467
+ return;
5468
+ }
5469
+ const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
5470
+ if (!chainRootId) return;
5471
+ if (RETIME_MATERIALIZATION_MODE_INLINE_G) {
5472
+ const cloneNode = ctx.idMap.get(chainRootId);
5473
+ useNode.type = "g";
5474
+ delete useNode.href;
5475
+ useNode.children = [cloneNode];
5476
+ applyUseOffsetToG(useNode);
5477
+ ctx.defs = ctx.defs.filter((d) => d !== cloneNode);
5478
+ } else {
5479
+ useNode.href = "#" + chainRootId;
5480
+ }
5481
+ }
5482
+ function buildChainClone(targetId, accum, ctx, chain) {
5483
+ if (chain.has(targetId)) {
5484
+ ctx.errors.push('retime: loop via "' + targetId + '"');
5485
+ return void 0;
5486
+ }
5487
+ const target = ctx.idMap.get(targetId);
5488
+ if (!target) {
5489
+ ctx.warnings.push('retime: target "' + targetId + '" not found');
5490
+ return void 0;
5491
+ }
5492
+ const cloneNode = clone(target);
5493
+ regenerateIdsInClone(cloneNode, ctx);
5494
+ if (target.type === "use") {
5495
+ remapKeyframeTimesOnly(cloneNode, accum.start, accum.stretch);
5496
+ } else {
5497
+ remapKeyframeTimes(cloneNode, accum.start, accum.stretch);
5498
+ }
5499
+ clearCloneRetime(cloneNode);
5500
+ if (target.type === "use" && target.href) {
5501
+ const subId = stripHash(target.href);
5502
+ if (subId) {
5503
+ const innerRetime = readCloneRetime(target);
5504
+ const subAccum = innerRetime ? concatRetime(asRetime(innerRetime), accum) : accum;
5505
+ const subChain = new Set(chain);
5506
+ subChain.add(targetId);
5507
+ const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
5508
+ if (subId2) cloneNode.href = "#" + subId2;
5509
+ }
5510
+ } else {
5511
+ materializeNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
5512
+ }
5513
+ ctx.defs.push(cloneNode);
5514
+ if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
5515
+ return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
5516
+ }
5517
+ function materializeNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
5518
+ const visit = (n) => {
5519
+ var _a2;
5520
+ const retime = readCloneRetime(n);
5521
+ if (n.type === "use" && retime && n.href) {
5522
+ const subId = stripHash(n.href);
5523
+ if (subId) {
5524
+ const subAccum = concatRetime(asRetime(retime), accum);
5525
+ const subChain = new Set(chain);
5526
+ subChain.add(parentTargetId);
5527
+ const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
5528
+ if (subId2) n.href = "#" + subId2;
5529
+ }
5530
+ clearCloneRetime(n);
5531
+ }
5532
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
5533
+ };
5534
+ visit(node);
5535
+ }
5536
+ function remapKeyframeTimes(node, start, stretch) {
5537
+ var _a2;
5538
+ remapKeyframeTimesOnly(node, start, stretch);
5539
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => remapKeyframeTimes(c, start, stretch));
5540
+ }
5541
+ function remapKeyframeTimesOnly(node, start, stretch) {
5542
+ const remap2 = (kfs) => {
5543
+ for (const kf of kfs) if (typeof kf.time === "number") kf.time = start + kf.time * stretch;
5544
+ };
5545
+ if (node.transform && typeof node.transform === "object" && Array.isArray(node.transform.keyframes)) {
5546
+ remap2(node.transform.keyframes);
5547
+ }
5548
+ if (node.animate && typeof node.animate === "object") {
5549
+ for (const prop of Object.keys(node.animate)) {
5550
+ const anim = node.animate[prop];
5551
+ if (anim && Array.isArray(anim.keyframes)) remap2(anim.keyframes);
5552
+ }
5553
+ }
5554
+ }
5555
+
5556
+ // src/effects/stroke/strokeTrimEffect.ts
5557
+ function applyStrokeTrimEffect(node, strokeTrim, ctx) {
5558
+ if (!strokeTrim) return node;
5559
+ const combined = strokeTrim.subPaths === PxStrokeTrimSubPaths.combined;
5560
+ const leafEntries = [];
5561
+ const measure = (n) => {
5562
+ if (Array.isArray(n.children) && n.children.length > 0) {
5563
+ for (const ch of n.children) measure(ch);
5564
+ return;
5565
+ }
5566
+ const d = typeof n.d === "string" ? n.d : shapeToPathD(n);
5567
+ if (d === void 0) return;
5568
+ const subpaths = parseSvgPathToBezier(d);
5569
+ if (!subpaths.length) return;
5570
+ const entry = { leaf: n, subpaths: [] };
5571
+ for (const sp of subpaths) {
5572
+ const lengthPx = pxBezierPathLength(sp);
5573
+ entry.subpaths.push({ subpath: sp, lengthPx, startOffsetPx: 0 });
5574
+ }
5575
+ leafEntries.push(entry);
5576
+ };
5577
+ measure(node);
5578
+ if (!leafEntries.length) return node;
5579
+ let acc = 0;
5580
+ const iterOrder = combined ? [...leafEntries].reverse() : leafEntries;
5581
+ for (const entry of iterOrder) {
5582
+ for (const sp of entry.subpaths) {
5583
+ if (!combined) acc = 0;
5584
+ sp.startOffsetPx = acc;
5585
+ acc += sp.lengthPx;
5586
+ }
5587
+ }
5588
+ const chainLengthPx = acc;
5589
+ if (combined && chainLengthPx < 1e-3) return node;
5590
+ const offsetReadRaw = readAnimatable(strokeTrim.offset);
5591
+ const offsetRead = offsetReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: 0 } : offsetReadRaw;
5592
+ const rangeReadRaw = readRangeWithCrossings(strokeTrim.range);
5593
+ const rangeRead = rangeReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: [0, 1] } : rangeReadRaw;
5594
+ const offsetValues = readScalarValues(offsetRead);
5595
+ const minOffset = offsetValues.length ? Math.min(...offsetValues) : 0;
5596
+ const maxOffset = offsetValues.length ? Math.max(...offsetValues) : 0;
5597
+ const minMaxOffset = [minOffset, maxOffset];
5598
+ if (leafEntries.length === 1 && leafEntries[0].leaf === node && leafEntries[0].subpaths.length === 1) {
5599
+ const entry = leafEntries[0];
5600
+ const sp = entry.subpaths[0];
5601
+ const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
5602
+ if (pathLengthPx < 1e-3) return node;
5603
+ const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
5604
+ return collapseLeafWithTrim(entry.leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead);
5605
+ }
5606
+ const replacements = /* @__PURE__ */ new Map();
5607
+ for (const entry of leafEntries) {
5608
+ const newChildren = [];
5609
+ for (const sp of entry.subpaths) {
5610
+ const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
5611
+ if (pathLengthPx < 1e-3) continue;
5612
+ const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
5613
+ newChildren.push(...buildSubpathNodes(entry.leaf, sp.subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx));
5614
+ }
5615
+ replacements.set(entry.leaf, wrapLeafAsGroup(entry.leaf, newChildren));
5616
+ }
5617
+ const swap = (n) => {
5618
+ const r = replacements.get(n);
5619
+ if (r) return r;
5620
+ if (Array.isArray(n.children) && n.children.length > 0) {
5621
+ return __spreadProps(__spreadValues({}, n), { children: n.children.map(swap) });
5622
+ }
5623
+ return n;
5624
+ };
5625
+ return swap(node);
5626
+ }
5627
+ function wrapLeafAsGroup(leaf, children) {
5628
+ const wrapper = __spreadProps(__spreadValues({}, leaf), { type: "g", children });
5629
+ delete wrapper.d;
5630
+ delete wrapper.strokeDasharray;
5631
+ delete wrapper.strokeDashoffset;
5632
+ delete wrapper.effects;
5633
+ return wrapper;
5634
+ }
5635
+ function buildSubpathNodes(leaf, subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx) {
5636
+ const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
5637
+ const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
5638
+ const dashOffsetAttr = computeAnimAttr(offsetRead, offsetToDashOffset);
5639
+ const dashArrayAttr = computeAnimAttr(rangeRead, rangeToDasharray);
5640
+ const strokeOpacityAttr = computeOpacityFromRange(rangeRead);
5641
+ const dStr = bezierToSvgPath(subpath);
5642
+ const base = makeBareSubpath(dStr);
5643
+ applyAttr(base, "strokeDasharray", dashArrayAttr);
5644
+ applyAttr(base, "strokeDashoffset", dashOffsetAttr);
5645
+ applyAttr(base, "strokeOpacity", strokeOpacityAttr);
5646
+ return [base];
5647
+ }
5648
+ function collapseLeafWithTrim(leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead) {
5649
+ const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
5650
+ const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
5651
+ const node = __spreadValues({}, leaf);
5652
+ delete node.effects;
5653
+ applyAttr(node, "strokeDasharray", computeAnimAttr(rangeRead, rangeToDasharray));
5654
+ applyAttr(node, "strokeDashoffset", computeAnimAttr(offsetRead, offsetToDashOffset));
5655
+ applyAttr(node, "strokeOpacity", computeOpacityFromRange(rangeRead));
5656
+ return node;
5657
+ }
5658
+ function makeBareSubpath(dStr) {
5659
+ return { type: "path", d: dStr };
5660
+ }
5661
+ var SMALL_PADDING_PX = 1;
5662
+ function makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset) {
5663
+ const [minIdx] = getOffsetIndexRange(minMaxOffset);
5664
+ return (offsetVal) => pathLengthPx * (-offsetVal - minIdx + startOffsetPct) + SMALL_PADDING_PX;
5665
+ }
5666
+ function makeRangeToDasharray(pathLengthPx, minMaxOffset) {
5667
+ const [minIdx, maxIdx] = getOffsetIndexRange(minMaxOffset);
5668
+ const repeats = maxIdx - minIdx + 1;
5669
+ return (rangeVal) => {
5670
+ const a = clamp(rangeVal[0], 0, 1);
5671
+ const b = clamp(rangeVal[1], 0, 1);
5672
+ const minR = Math.min(a, b);
5673
+ const maxR = Math.max(a, b);
5674
+ const out = [0];
5675
+ let gap = SMALL_PADDING_PX;
5676
+ for (let i = 0; i < repeats; i++) {
5677
+ out.push(gap + minR * pathLengthPx);
5678
+ out.push((maxR - minR) * pathLengthPx);
5679
+ gap = (1 - maxR) * pathLengthPx;
5680
+ }
5681
+ out.push(gap + SMALL_PADDING_PX);
5682
+ return out;
5683
+ };
5684
+ }
5685
+ function getOffsetIndexRange(minMaxOffset) {
5686
+ return [
5687
+ Math.floor(Math.min(-minMaxOffset[0], -minMaxOffset[1])),
5688
+ Math.ceil(Math.max(-minMaxOffset[0], -minMaxOffset[1]))
5689
+ ];
5690
+ }
5691
+ function readScalarValues(r) {
5692
+ if (r.kind === "absent" /* Absent */) return [];
5693
+ if (r.kind === "static" /* Static */) return [r.value];
5694
+ const out = [];
5695
+ for (const kf of r.keyframes) {
5696
+ const v = keyframeValue(kf);
5697
+ if (typeof v === "number") out.push(v);
5698
+ }
5699
+ return out;
5700
+ }
5701
+ function computeAnimAttr(read, map) {
5702
+ if (read.kind === "absent" /* Absent */) return void 0;
5703
+ if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
5704
+ return {
5705
+ kind: "animated" /* Animated */,
5706
+ keyframes: read.keyframes.map((kf) => ({
5707
+ time: keyframeTime(kf),
5708
+ value: map(keyframeValue(kf)),
5709
+ easing: keyframeEasing(kf)
5710
+ })),
5711
+ loop: read.loop
5712
+ };
5713
+ }
5714
+ function applyAttr(node, attrName, attr) {
5715
+ if (!attr) return;
5716
+ writeAnimatableChannel(node, attrName, attr);
5717
+ }
5718
+ var OPACITY_STEP_MS = 10;
5719
+ function computeOpacityFromRange(rangeRead) {
5720
+ const hide = (v) => v[0] === v[1];
5721
+ if (rangeRead.kind === "absent" /* Absent */) return void 0;
5722
+ if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
5723
+ const kfs = rangeRead.keyframes;
5724
+ let anyHide = false;
5725
+ let allHide = true;
5726
+ for (const kf of kfs) {
5727
+ if (hide(keyframeValue(kf))) anyHide = true;
5728
+ else allHide = false;
5729
+ }
5730
+ if (!anyHide) return void 0;
5731
+ if (allHide) return { kind: "static" /* Static */, value: 0 };
5732
+ const out = [];
5733
+ for (let i = 0; i < kfs.length; i++) {
5734
+ const kf = kfs[i];
5735
+ const prevKf = i > 0 ? kfs[i - 1] : void 0;
5736
+ const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5737
+ const t = keyframeTime(kf);
5738
+ const thisHide = hide(keyframeValue(kf));
5739
+ const prevHide = prevKf ? thisHide && hide(keyframeValue(prevKf)) : thisHide;
5740
+ const nextHide = nextKf ? thisHide && hide(keyframeValue(nextKf)) : thisHide;
5741
+ if (prevHide && !nextHide) {
5742
+ out.push({ time: t, value: 0 });
5743
+ out.push({ time: t + OPACITY_STEP_MS, value: 1 });
5744
+ } else if (!prevHide && nextHide) {
5745
+ out.push({ time: t - OPACITY_STEP_MS, value: 1 });
5746
+ out.push({ time: t, value: 0 });
5747
+ }
5748
+ }
5749
+ if (out.length <= 1) return void 0;
5750
+ return { kind: "animated" /* Animated */, keyframes: out };
5751
+ }
5752
+ function readRangeWithCrossings(raw) {
5753
+ const r = readAnimatable(raw);
5754
+ if (r.kind !== "animated" /* Animated */) return r;
5755
+ const kfs = r.keyframes.map((kf) => ({
5756
+ time: keyframeTime(kf),
5757
+ value: keyframeValue(kf),
5758
+ easing: keyframeEasing(kf)
5759
+ }));
5760
+ const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5761
+ if (!hasReverse) {
5762
+ return {
5763
+ kind: "animated" /* Animated */,
5764
+ keyframes: kfs.map((kf) => ({ time: kf.time, value: kf.value, easing: kf.easing }))
5765
+ };
5766
+ }
5767
+ const crossingTimes = [];
5768
+ for (let i = 1; i < kfs.length; i++) {
5769
+ const prev = kfs[i - 1];
5770
+ const cur = kfs[i];
5771
+ const dPrev = prev.value[1] - prev.value[0];
5772
+ const dCur = cur.value[1] - cur.value[0];
5773
+ if (dPrev * dCur < 0) {
5774
+ const t = bisectionForRangeCrossing(prev, cur);
5775
+ if (t !== null && t > prev.time && t < cur.time) {
5776
+ crossingTimes.push(Math.round(t));
5777
+ }
5778
+ }
5779
+ }
5780
+ const uniqueTs = Array.from(new Set(crossingTimes)).sort((a, b) => a - b);
5781
+ const out = [];
5782
+ let j = 0;
5783
+ for (const kf of kfs) {
5784
+ while (j < uniqueTs.length && uniqueTs[j] < kf.time) {
5785
+ const t = uniqueTs[j++];
5786
+ const v2 = interpolateRangeAt(kfs, t);
5787
+ const m = (v2[0] + v2[1]) / 2;
5788
+ out.push({ time: t, value: [m, m] });
5789
+ }
5790
+ const v = kf.value[0] > kf.value[1] ? [kf.value[1], kf.value[0]] : kf.value;
5791
+ out.push({ time: kf.time, value: v, easing: kf.easing });
5792
+ }
5793
+ while (j < uniqueTs.length) {
5794
+ const t = uniqueTs[j++];
5795
+ const v = interpolateRangeAt(kfs, t);
5796
+ const m = (v[0] + v[1]) / 2;
5797
+ out.push({ time: t, value: [m, m] });
5798
+ }
5799
+ return { kind: "animated" /* Animated */, keyframes: out };
5800
+ }
5801
+ function bisectionForRangeCrossing(prev, cur) {
5802
+ const f = (t) => {
5803
+ const a = (t - prev.time) / (cur.time - prev.time);
5804
+ const v0 = prev.value[0] + (cur.value[0] - prev.value[0]) * a;
5805
+ const v1 = prev.value[1] + (cur.value[1] - prev.value[1]) * a;
5806
+ return v1 - v0;
5807
+ };
5808
+ let lo = prev.time, hi = cur.time;
5809
+ let fLo = f(lo);
5810
+ if (fLo === 0) return lo;
5811
+ const fHi = f(hi);
5812
+ if (fHi === 0) return hi;
5813
+ if (fLo * fHi > 0) return null;
5814
+ for (let i = 0; i < 100; i++) {
5815
+ const mid = (lo + hi) / 2;
5816
+ const fMid = f(mid);
5817
+ if (fMid === 0 || Math.abs(hi - lo) < 1e-4) return mid;
5818
+ if (fLo * fMid < 0) {
5819
+ hi = mid;
5820
+ } else {
5821
+ lo = mid;
5822
+ fLo = fMid;
5823
+ }
5824
+ }
5825
+ return (lo + hi) / 2;
5826
+ }
5827
+ function interpolateRangeAt(kfs, t) {
5828
+ if (t <= kfs[0].time) return kfs[0].value;
5829
+ if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
5830
+ for (let i = 1; i < kfs.length; i++) {
5831
+ if (t <= kfs[i].time) {
5832
+ const prev = kfs[i - 1];
5833
+ const cur = kfs[i];
5834
+ const a = (t - prev.time) / (cur.time - prev.time);
5835
+ return [
5836
+ prev.value[0] + (cur.value[0] - prev.value[0]) * a,
5837
+ prev.value[1] + (cur.value[1] - prev.value[1]) * a
5838
+ ];
5839
+ }
5840
+ }
5841
+ return kfs[kfs.length - 1].value;
5842
+ }
5843
+ function pxBezierPathLength(path) {
5844
+ const v = path.v;
5845
+ if (!v || v.length < 2) return 0;
5846
+ let total = 0;
5847
+ for (let i = 0; i < v.length - 1; i++) {
5848
+ total += segmentLength(path, i, i + 1);
5849
+ }
5850
+ if (path.c && v.length > 1) {
5851
+ total += segmentLength(path, v.length - 1, 0);
5852
+ }
5853
+ return total;
5854
+ }
5855
+ function segmentLength(path, from, to) {
5856
+ var _a2, _b, _c, _d;
5857
+ const v = path.v;
5858
+ const p0 = v[from];
5859
+ const p3 = v[to];
5860
+ const p1 = (_b = (_a2 = path.o) == null ? void 0 : _a2[from]) != null ? _b : p0;
5861
+ const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
5862
+ const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
5863
+ return lut.ds[lut.ds.length - 1];
5864
+ }
5865
+ var ARC_KAPPA = 0.5522847498307936;
5866
+ function shapeToPathD(node) {
5867
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5868
+ if (node.type === "rect") {
5869
+ const x = Number((_a2 = node.x) != null ? _a2 : 0), y = Number((_b = node.y) != null ? _b : 0);
5870
+ const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
5871
+ return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
5872
+ }
5873
+ if (node.type === "ellipse" || node.type === "circle") {
5874
+ const cx = Number((_e = node.cx) != null ? _e : 0), cy = Number((_f = node.cy) != null ? _f : 0);
5875
+ const rx = node.type === "circle" ? Number((_g = node.r) != null ? _g : 0) : Number((_h = node.rx) != null ? _h : 0);
5876
+ const ry = node.type === "circle" ? Number((_i = node.r) != null ? _i : 0) : Number((_j = node.ry) != null ? _j : 0);
5877
+ if (!(rx > 0) || !(ry > 0)) return void 0;
5878
+ const kx = rx * ARC_KAPPA, ky = ry * ARC_KAPPA;
5879
+ const c = (x1, y1, x2, y2, x, y) => "C" + x1 + "," + y1 + " " + x2 + "," + y2 + " " + x + "," + y;
5880
+ return "M" + (cx + rx) + "," + cy + c(cx + rx, cy + ky, cx + kx, cy + ry, cx, cy + ry) + c(cx - kx, cy + ry, cx - rx, cy + ky, cx - rx, cy) + c(cx - rx, cy - ky, cx - kx, cy - ry, cx, cy - ry) + c(cx + kx, cy - ry, cx + rx, cy - ky, cx + rx, cy) + "z";
5881
+ }
5882
+ return void 0;
5883
+ }
5884
+
5885
+ // src/effects/PlayerEffectsUtil.ts
5886
+ function materializeNodeEffects(root) {
5887
+ var _a2, _b;
5888
+ const ctx = {
5889
+ defs: [],
5890
+ warnings: [],
5891
+ errors: [],
5892
+ idMap: /* @__PURE__ */ new Map(),
5893
+ nextId: 0,
5894
+ contentRefInnerIds: /* @__PURE__ */ new Map(),
5895
+ maskAncestorChains: /* @__PURE__ */ new Map(),
5896
+ // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5897
+ // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5898
+ engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
5899
+ glyphs: (_b = getDefinitions(root)) == null ? void 0 : _b.fonts
5900
+ };
5901
+ const working = clone(root);
5902
+ indexById(working, ctx.idMap);
5903
+ identifyContentRefTargets(working, ctx, () => genId(ctx, "inner"));
5904
+ collectMaskAncestorChains(working, ctx);
5905
+ const afterPass1 = applyPlayerEffects_exceptRetime(working, ctx);
5906
+ const out = applyPlayerEffects_retime(afterPass1, ctx);
5907
+ spliceDefs(out, ctx.defs);
5908
+ return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
5909
+ }
5910
+ function applyPlayerEffects_exceptRetime(node, ctx) {
5911
+ if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
5912
+ const fx = node.effects;
5913
+ const originalId = typeof node.id === "string" ? node.id : void 0;
5914
+ const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
5915
+ if (!fx && !innerIdForContentRef) return node;
5916
+ const { transformBy, repeater, maskedBy, clipPath, strokeTrim, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
5917
+ if (fx) delete node.effects;
5918
+ let n = node;
5919
+ let consumedByGlyphs = false;
5920
+ if (text == null ? void 0 : text.useGlyphs) {
5921
+ if (textPath) {
5922
+ const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
5923
+ const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
5924
+ if (glyphed) {
5925
+ n = glyphed;
5926
+ consumedByGlyphs = true;
5927
+ }
5928
+ } else {
5929
+ n = applyTextGlyphsEffect(n, text, ctx);
5930
+ consumedByGlyphs = true;
5931
+ }
5932
+ }
5933
+ if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
5934
+ n = applyFillGradientEffect(n, fillGradient, ctx);
5935
+ n = applyStrokeGradientEffect(n, strokeGradient, ctx);
5936
+ n = applyStrokeTrimEffect(n, strokeTrim, ctx);
5937
+ n = applyRepeaterEffect(n, repeater, ctx);
5938
+ n = applyMaskedByEffect(n, maskedBy, transformBy, ctx);
5939
+ n = applyClipPathEffect(n, clipPath, ctx);
5940
+ if (innerIdForContentRef) {
5941
+ applyRefHref(n, cloneFx, ctx);
5942
+ n = splitForContentRef(n, transformBy, originalId, innerIdForContentRef, ctx);
5943
+ } else {
5944
+ n = applyRefAndTransformationEffect(n, cloneFx, transformBy, ctx);
5945
+ }
5946
+ if (cloneFx == null ? void 0 : cloneFx.retime) node.effects = { clone: { retime: cloneFx.retime } };
5947
+ if (originalId) ctx.idMap.set(originalId, n);
5948
+ return n;
5949
+ }
5950
+ function applyPlayerEffects_retime(node, ctx) {
5951
+ applyAllRetimeEffects(node, ctx);
5952
+ return node;
5953
+ }
5954
+
5955
+ // src/materialize/PxOffsetPathMaterializer.ts
5956
+ function cubicAt(p0, c1, c2, p1, t) {
5957
+ const u = 1 - t;
5958
+ const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
5959
+ return [
5960
+ a * p0[0] + b * c1[0] + c * c2[0] + d * p1[0],
5961
+ a * p0[1] + b * c1[1] + c * c2[1] + d * p1[1]
5962
+ ];
5963
+ }
5964
+ function cubicLength(p0, c1, c2, p1, steps = 64) {
5965
+ let len = 0;
5966
+ let prev = p0;
5967
+ for (let i = 1; i <= steps; i++) {
5968
+ const pt = cubicAt(p0, c1, c2, p1, i / steps);
5969
+ len += Math.hypot(pt[0] - prev[0], pt[1] - prev[1]);
5970
+ prev = pt;
5971
+ }
5972
+ return len;
5973
+ }
5974
+ var fmt2 = (n) => {
5975
+ const r = Math.round(n * 1e4) / 1e4;
5976
+ return Object.is(r, -0) ? "0" : String(r);
5977
+ };
5978
+ function buildOffsetPath(propAnim) {
5979
+ var _a2, _b, _c;
5980
+ if (propAnim.alongPathMode !== "offsetPath") return void 0;
5981
+ const kfs = propAnim.keyframes;
5982
+ if (!kfs || kfs.length < 2) return void 0;
5983
+ const first = keyframeValue(kfs[0]);
5984
+ const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
5985
+ const points = [];
5986
+ let keyframesCarryRotate = false;
5987
+ for (const kf of kfs) {
5988
+ const v = keyframeValue(kf);
5989
+ const tr = v == null ? void 0 : v.translate;
5990
+ if (!tr || tr.length < 2) return void 0;
5991
+ const parts = Object.keys(v);
5992
+ if (parts.some((p) => p !== TRANSFORM_PART.translate && p !== TRANSFORM_PART.origin && p !== TRANSFORM_PART.rotate)) return void 0;
5993
+ if ((v == null ? void 0 : v.rotate) !== void 0) {
5994
+ if (v.rotate !== 0) return void 0;
5995
+ keyframesCarryRotate = true;
5996
+ }
5997
+ const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5998
+ if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5999
+ points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
6000
+ }
6001
+ if (!kfs.some((kf) => keyframeTangentIn(kf) || keyframeTangentOut(kf))) return void 0;
6002
+ let d = "M" + fmt2(points[0][0]) + "," + fmt2(points[0][1]);
6003
+ const segLens = [];
6004
+ for (let i = 0; i < points.length - 1; i++) {
6005
+ const p0 = points[i], p1 = points[i + 1];
6006
+ const to = (_b = keyframeTangentOut(kfs[i])) != null ? _b : [0, 0];
6007
+ const ti = (_c = keyframeTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
6008
+ const c1 = [p0[0] + to[0], p0[1] + to[1]];
6009
+ const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
6010
+ d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
6011
+ segLens.push(cubicLength(p0, c1, c2, p1));
6012
+ }
6013
+ const total = segLens.reduce((a, b) => a + b, 0);
6014
+ if (!(total > 0)) return void 0;
6015
+ const distanceKfs = [];
6016
+ let cum = 0;
6017
+ for (let i = 0; i < kfs.length; i++) {
6018
+ if (i > 0) cum += segLens[i - 1];
6019
+ const out = { t: keyframeTime(kfs[i]), v: cum / total };
6020
+ const e = keyframeEasing(kfs[i]);
6021
+ if (e !== void 0) out.e = e;
6022
+ distanceKfs.push(out);
6023
+ }
6024
+ return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor, keyframesCarryRotate };
6025
+ }
6026
+ function materializeOffsetPathsInTree(root) {
6027
+ const walk = (node) => {
6028
+ var _a2;
6029
+ let out = node;
6030
+ const anim = node.animate;
6031
+ const transform = anim == null ? void 0 : anim["transform"];
6032
+ if (transform) {
6033
+ const built = buildOffsetPath(transform);
6034
+ if (built) {
6035
+ const newAnimate = __spreadValues({}, anim);
6036
+ delete newAnimate[TRANSFORM_ATTR];
6037
+ const distance = { keyframes: built.distanceKfs };
6038
+ if (transform.loop !== void 0) distance.loop = transform.loop;
6039
+ newAnimate[OFFSET_DISTANCE_ATTR] = distance;
6040
+ const staticTr = node.transform;
6041
+ let newTransform = staticTr;
6042
+ if (staticTr && typeof staticTr === "object") {
6043
+ const t = __spreadValues({}, staticTr);
6044
+ delete t[TRANSFORM_PART.translate];
6045
+ delete t[TRANSFORM_PART.origin];
6046
+ if (built.keyframesCarryRotate) delete t[TRANSFORM_PART.rotate];
6047
+ newTransform = Object.keys(t).length ? t : void 0;
6048
+ }
6049
+ out = __spreadProps(__spreadValues({}, node), {
6050
+ animate: newAnimate,
6051
+ style: __spreadProps(__spreadValues({}, node.style), {
6052
+ offsetPath: "path('" + built.pathStr + "')",
6053
+ offsetAnchor: fmt2(built.anchor[0]) + "px " + fmt2(built.anchor[1]) + "px",
6054
+ offsetRotate: built.autoOrient ? "auto" : "0deg",
6055
+ offsetDistance: "0%"
6056
+ })
6057
+ });
6058
+ if (newTransform !== void 0) out.transform = newTransform;
6059
+ else delete out.transform;
6060
+ }
6061
+ }
6062
+ if ((_a2 = out.children) == null ? void 0 : _a2.length) {
6063
+ const children = out.children.map(walk);
6064
+ if (children.some((c, i) => c !== out.children[i])) out = __spreadProps(__spreadValues({}, out), { children });
6065
+ }
6066
+ return out;
6067
+ };
6068
+ return walk(root);
6069
+ }
6070
+
6071
+ // src/materialize/PxAnimatorUseMaterializer.ts
6072
+ function materializeAnimatedUseInstances(root) {
6073
+ var _a2;
6074
+ const idMap = buildIdMap(root);
6075
+ const animatedIds = computeAnimatedSubtreeIds(root, idMap);
6076
+ if (animatedIds.size === 0) return root;
6077
+ let idCounter = 0;
6078
+ const genId3 = () => "_lw_use_mat_" + ++idCounter;
6079
+ const rootViewport = readRootViewport(root);
6080
+ const defsCollector = [];
6081
+ const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
6082
+ if (defsCollector.length === 0) return walked;
6083
+ const defsNode = { type: "defs", children: defsCollector };
6084
+ const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
6085
+ return __spreadProps(__spreadValues({}, walked), { children: newChildren });
6086
+ }
6087
+ function readRootViewport(root) {
6088
+ const vb = parseViewBox(root.viewBox);
6089
+ if (vb) return [vb[2], vb[3]];
6090
+ const w = numericAttr(root.width);
6091
+ const h = numericAttr(root.height);
6092
+ if (w !== void 0 && h !== void 0) return [w, h];
6093
+ return [1, 1];
6094
+ }
6095
+ function numericAttr(v) {
6096
+ if (typeof v === "number") return v;
6097
+ if (typeof v === "string") {
6098
+ const n = parseFloat(v);
6099
+ return Number.isFinite(n) ? n : void 0;
6100
+ }
6101
+ return void 0;
6102
+ }
6103
+ function buildIdMap(root) {
6104
+ const map = /* @__PURE__ */ new Map();
6105
+ const visit = (n) => {
6106
+ var _a2;
6107
+ if (typeof n.id === "string") map.set(n.id, n);
6108
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
6109
+ };
6110
+ visit(root);
6111
+ return map;
6112
+ }
6113
+ function computeAnimatedSubtreeIds(root, idMap) {
6114
+ const cache = /* @__PURE__ */ new WeakMap();
6115
+ const result = /* @__PURE__ */ new Set();
6116
+ const hasAnim = (n, visiting) => {
6117
+ const cached = cache.get(n);
6118
+ if (cached !== void 0) return cached;
6119
+ if (visiting.has(n)) return false;
6120
+ visiting.add(n);
6121
+ let r = false;
6122
+ if (n.animate && typeof n.animate === "object" && !Array.isArray(n.animate)) {
6123
+ for (const _ in n.animate) {
6124
+ r = true;
6125
+ break;
6126
+ }
6127
+ }
6128
+ if (!r && n.children) {
6129
+ for (const ch of n.children) {
6130
+ if (hasAnim(ch, visiting)) {
6131
+ r = true;
6132
+ break;
6133
+ }
6134
+ }
6135
+ }
6136
+ if (!r && n.type === "use" && typeof n.href === "string") {
6137
+ const targetId = stripHash2(n.href);
6138
+ const target = targetId ? idMap.get(targetId) : void 0;
6139
+ if (target) r = hasAnim(target, visiting);
6140
+ }
6141
+ visiting.delete(n);
6142
+ cache.set(n, r);
6143
+ return r;
6144
+ };
6145
+ for (const [id, node] of idMap) {
6146
+ if (hasAnim(node, /* @__PURE__ */ new Set())) result.add(id);
6147
+ }
6148
+ return result;
6149
+ }
6150
+ function stripHash2(href) {
6151
+ if (typeof href !== "string") return void 0;
6152
+ return href.startsWith("#") ? href.slice(1) : href;
6153
+ }
6154
+ function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
6155
+ var _a2, _b, _c, _d;
6156
+ const clone2 = deepClonePxNode(target);
6157
+ regenerateIdsAndRewriteRefs(clone2, genId3);
6158
+ const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
6159
+ const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
6160
+ const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
6161
+ const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
6162
+ const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
6163
+ const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materializedClone] });
6164
+ delete newNode.href;
6165
+ delete newNode.width;
6166
+ delete newNode.height;
6167
+ return applyUseOffsetToG(newNode);
6168
+ }
6169
+ function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
6170
+ const viewBox = parseViewBox(symbolNode.viewBox);
6171
+ const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
6172
+ delete g.viewBox;
6173
+ delete g.preserveAspectRatio;
6174
+ delete g.width;
6175
+ delete g.height;
6176
+ if (!viewBox) return g;
6177
+ const [vbX, vbY, vbW, vbH] = viewBox;
6178
+ const scale = vbW > 0 && vbH > 0 ? Math.min(useW / vbW, useH / vbH) : 1;
6179
+ const xOff = (useW - vbW * scale) / 2;
6180
+ const yOff = (useH - vbH * scale) / 2;
6181
+ const parts = [];
6182
+ if (xOff !== 0 || yOff !== 0) parts.push("translate(" + xOff + "," + yOff + ")");
6183
+ if (scale !== 1) parts.push("scale(" + scale + ")");
6184
+ if (vbX !== 0 || vbY !== 0) parts.push("translate(" + -vbX + "," + -vbY + ")");
6185
+ if (parts.length) g.transform = parts.join("");
6186
+ const clipId = genId3();
6187
+ defsCollector.push({
6188
+ type: "clipPath",
6189
+ id: clipId,
6190
+ children: [{ type: "rect", x: vbX, y: vbY, width: vbW, height: vbH }]
6191
+ });
6192
+ g.clipPath = "url(#" + clipId + ")";
6193
+ return g;
6194
+ }
6195
+ function parseViewBox(v) {
6196
+ if (typeof v !== "string") return void 0;
6197
+ const parts = v.trim().split(/[\s,]+/).map(Number);
6198
+ if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
6199
+ return [parts[0], parts[1], parts[2], parts[3]];
6200
+ }
6201
+ function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
6202
+ if (node.type === "use" && typeof node.href === "string") {
6203
+ const targetId = stripHash2(node.href);
6204
+ if (targetId && animatedIds.has(targetId)) {
6205
+ const target = idMap.get(targetId);
6206
+ if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
6207
+ }
6208
+ }
6209
+ if (!node.children) return node;
6210
+ let changed = false;
6211
+ const newChildren = node.children.map((ch) => {
6212
+ const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
6213
+ if (m !== ch) changed = true;
6214
+ return m;
6215
+ });
6216
+ return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
6217
+ }
6218
+
6219
+ // src/materialize/PxRestPose.ts
6220
+ var TRANSFORM_CHANNEL = "transform";
6221
+ var REVERSED_DIRECTIONS = /* @__PURE__ */ new Set(["reverse", "alternate-reverse"]);
6222
+ var VERIFY_SAMPLE_FRACTIONS = [0, 0.25, 0.5, 0.75, 1];
6223
+ var SCRATCH_ID_PREFIX = "__px_rest_";
6224
+ function materializeRestPosesInTree(root, engine) {
6225
+ var _a2, _b;
6226
+ const out = deepClone(root);
6227
+ const config = getAnimatorConfig(out) || {};
6228
+ const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
6229
+ const firstFrameTime = REVERSED_DIRECTIONS.has(String(config.direction)) ? duration : 0;
6230
+ const nodes = animatedNodes(out);
6231
+ if (!nodes.size) return out;
6232
+ const before = bindingsOf(out, engine);
6233
+ const added = /* @__PURE__ */ new Map();
6234
+ for (const [key, animate] of before) {
6235
+ const node = nodes.get(key);
6236
+ if (!node) continue;
6237
+ const channels = Object.keys(animate);
6238
+ for (const channel of channels) {
6239
+ if (PX_TRANSFORM_FN_NAMES.has(channel)) continue;
6240
+ if (!mayCarryRestPose(node, channel)) continue;
6241
+ const value = firstFrameValue(animate, channel, firstFrameTime);
6242
+ if (value === void 0) continue;
6243
+ node[channel] = value;
6244
+ added.set(key, [...(_a2 = added.get(key)) != null ? _a2 : [], channel]);
6245
+ }
6246
+ if (channels.some((channel) => PX_TRANSFORM_FN_NAMES.has(channel)) && mayCarryTransformRestPose(node)) {
6247
+ const parts = firstFrameTransformParts(animate, firstFrameTime);
6248
+ if (parts) {
6249
+ node[TRANSFORM_CHANNEL] = parts;
6250
+ added.set(key, [...(_b = added.get(key)) != null ? _b : [], TRANSFORM_CHANNEL]);
6251
+ }
6252
+ }
6253
+ }
6254
+ if (added.size) {
6255
+ const after = bindingsOf(out, engine);
6256
+ for (const [key, channels] of added) {
6257
+ if (writesTheSameFrames(before.get(key), after.get(key), duration)) continue;
6258
+ const node = nodes.get(key);
6259
+ if (node) for (const channel of channels) delete node[channel];
6260
+ }
6261
+ }
6262
+ return out;
6263
+ }
6264
+ function mayCarryRestPose(node, channel) {
6265
+ if (node[channel] !== void 0) return false;
6266
+ if (channel === TRANSFORM_CHANNEL) return mayCarryTransformRestPose(node);
6267
+ return true;
6268
+ }
6269
+ function mayCarryTransformRestPose(node) {
6270
+ if (node[TRANSFORM_CHANNEL] !== void 0) return false;
6271
+ for (const part of PX_TRANSFORM_FN_NAMES) if (node[part] !== void 0) return false;
6272
+ return true;
6273
+ }
6274
+ function firstFrameValue(animate, channel, timeMs) {
6275
+ const values = Object.values(calcAnimationValues({ [channel]: animate[channel] }, timeMs));
6276
+ return values.length === 1 && values[0] !== "" ? values[0] : void 0;
6277
+ }
6278
+ function firstFrameTransformParts(animate, timeMs) {
6279
+ const family = {};
6280
+ for (const channel of Object.keys(animate)) if (PX_TRANSFORM_FN_NAMES.has(channel)) family[channel] = animate[channel];
6281
+ const written = calcAnimationValues(family, timeMs)[TRANSFORM_CHANNEL];
6282
+ if (!written) return void 0;
6283
+ const parts = parseTransformParts(written.replace(/(px|deg)\b/g, ""));
6284
+ return parts && Object.keys(parts).length ? parts : void 0;
6285
+ }
6286
+ function writesTheSameFrames(a, b, durationMs) {
6287
+ if (!a || !b) return a === b;
6288
+ const frame = (animate, t) => JSON.stringify(calcAnimationValues(animate, t)).replace(/\s+/g, "");
6289
+ return VERIFY_SAMPLE_FRACTIONS.every((fraction) => frame(a, fraction * durationMs) === frame(b, fraction * durationMs));
6290
+ }
6291
+ function bindingsOf(tree, engine) {
6292
+ const scratch = deepClone(tree);
6293
+ const keyById = /* @__PURE__ */ new Map();
6294
+ for (const [key, node] of animatedNodes(scratch)) {
6295
+ if (node.id === void 0) node.id = SCRATCH_ID_PREFIX + key;
6296
+ keyById.set(String(node.id), key);
6297
+ }
6298
+ const out = /* @__PURE__ */ new Map();
6299
+ for (const binding of normalizeBindings(scratch, engine)) {
6300
+ const key = keyById.get(binding.id);
6301
+ if (key !== void 0) out.set(key, binding.animate);
6302
+ }
6303
+ return out;
6304
+ }
6305
+ function animatedNodes(tree) {
6306
+ const out = /* @__PURE__ */ new Map();
6307
+ let counter = 0;
6308
+ const visit = (node) => {
6309
+ if (node.animate) out.set(String(counter++), node);
6310
+ if (node.children) for (const child of node.children) visit(child);
6311
+ };
6312
+ if (tree.children) for (const child of tree.children) visit(child);
6313
+ return out;
6314
+ }
6315
+
6316
+ // src/materialize/PxAnimatorMaterializeAll.ts
6317
+ function materializeAllInTree(doc, engine, options) {
6318
+ var _a2, _b;
6319
+ let root = materializeNodeEffects(doc).root;
6320
+ root = materializeOffsetPathsInTree(root);
6321
+ const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : PX_DEFAULT_DURATION_MS;
6322
+ root = materializeInternalLoopsInTree(root, duration);
6323
+ if (engine === PxTimelineEngine.native) {
6324
+ root = materializeMotionPathsInTree(root, options == null ? void 0 : options.motionPath);
6325
+ root = materializeAnimatedUseInstances(root);
6326
+ root = pruneUnreferencedDefs(root);
6327
+ }
6328
+ root = materializeRestPosesInTree(root, engine);
6329
+ return root;
6330
+ }
6331
+ function prepareDocumentForRender(doc) {
6332
+ var _a2;
6333
+ const engine = resolveTimelineEngine((_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.engine);
6334
+ return generateNewIds(materializeAllInTree(doc, engine));
6335
+ }
6336
+ function pruneUnreferencedDefs(root) {
6337
+ const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
6338
+ const walk = (n, fn) => {
6339
+ var _a2;
6340
+ fn(n);
6341
+ (_a2 = n.children) == null ? void 0 : _a2.forEach((c) => walk(c, fn));
6342
+ };
6343
+ let changed = true;
6344
+ while (changed) {
6345
+ changed = false;
6346
+ const referenced = /* @__PURE__ */ new Set();
6347
+ walk(root, (n) => {
6348
+ if (n.type === "use" && typeof n.href === "string") referenced.add(stripHash3(n.href));
6349
+ });
6350
+ walk(root, (n) => {
6351
+ if (!n.children) return;
6352
+ let kept = n.children;
6353
+ if (n.type === "defs") {
6354
+ kept = kept.filter((c) => !((c.type === "g" || c.type === "symbol") && typeof c.id === "string" && !referenced.has(c.id)));
6355
+ }
6356
+ kept = kept.filter((c) => !(c.type === "defs" && (!c.children || c.children.length === 0)));
6357
+ if (kept.length !== n.children.length) {
6358
+ n.children = kept;
6359
+ changed = true;
6360
+ }
6361
+ });
6362
+ }
6363
+ return root;
6364
+ }
6365
+
6366
+ // src/playback/PxDiagnosticCode.ts
6367
+ var PxDiagnosticCode = /* @__PURE__ */ ((PxDiagnosticCode2) => {
6368
+ PxDiagnosticCode2[PxDiagnosticCode2["buildFailed"] = 1001] = "buildFailed";
6369
+ PxDiagnosticCode2[PxDiagnosticCode2["invalidDocumentAtSrc"] = 1002] = "invalidDocumentAtSrc";
6370
+ PxDiagnosticCode2[PxDiagnosticCode2["loadFailed"] = 1003] = "loadFailed";
6371
+ PxDiagnosticCode2[PxDiagnosticCode2["animationBuildFailed"] = 1004] = "animationBuildFailed";
6372
+ PxDiagnosticCode2[PxDiagnosticCode2["effectsShape"] = 1101] = "effectsShape";
6373
+ PxDiagnosticCode2[PxDiagnosticCode2["timelineOverrideIgnored"] = 1102] = "timelineOverrideIgnored";
6374
+ PxDiagnosticCode2[PxDiagnosticCode2["blockedTag"] = 1103] = "blockedTag";
6375
+ PxDiagnosticCode2[PxDiagnosticCode2["unsupportedAnimatedAttrs"] = 1104] = "unsupportedAnimatedAttrs";
6376
+ PxDiagnosticCode2[PxDiagnosticCode2["noBindings"] = 1105] = "noBindings";
6377
+ PxDiagnosticCode2[PxDiagnosticCode2["unresolvedBinding"] = 1106] = "unresolvedBinding";
6378
+ PxDiagnosticCode2[PxDiagnosticCode2["triggersNoRoot"] = 1201] = "triggersNoRoot";
6379
+ PxDiagnosticCode2[PxDiagnosticCode2["noRootForSelector"] = 1202] = "noRootForSelector";
6380
+ PxDiagnosticCode2[PxDiagnosticCode2["noRootElement"] = 1203] = "noRootElement";
6381
+ PxDiagnosticCode2[PxDiagnosticCode2["noElementsForSelector"] = 1206] = "noElementsForSelector";
6382
+ PxDiagnosticCode2[PxDiagnosticCode2["setAttributeNoElement"] = 1207] = "setAttributeNoElement";
6383
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollSmoothingNeedsOwnDriver"] = 1301] = "scrollSmoothingNeedsOwnDriver";
6384
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollNativeUnavailable"] = 1302] = "scrollNativeUnavailable";
6385
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollSubjectInvalid"] = 1303] = "scrollSubjectInvalid";
6386
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollSubjectNoMatch"] = 1304] = "scrollSubjectNoMatch";
6387
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollNoRootToObserve"] = 1305] = "scrollNoRootToObserve";
6388
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollTriggerIgnored"] = 1306] = "scrollTriggerIgnored";
6389
+ PxDiagnosticCode2[PxDiagnosticCode2["rateRejected"] = 1401] = "rateRejected";
6390
+ PxDiagnosticCode2[PxDiagnosticCode2["controlPropsConflict"] = 1501] = "controlPropsConflict";
6391
+ PxDiagnosticCode2[PxDiagnosticCode2["rnCompileFailed"] = 1601] = "rnCompileFailed";
6392
+ PxDiagnosticCode2[PxDiagnosticCode2["rnRenderFailed"] = 1602] = "rnRenderFailed";
6393
+ PxDiagnosticCode2[PxDiagnosticCode2["rnBoundaryCaught"] = 1603] = "rnBoundaryCaught";
6394
+ PxDiagnosticCode2[PxDiagnosticCode2["rnUnsupported"] = 1604] = "rnUnsupported";
6395
+ return PxDiagnosticCode2;
6396
+ })(PxDiagnosticCode || {});
6397
+
4412
6398
  // src/playback/PxDiagnostics.ts
4413
6399
  var PxDiagnosticKind = {
4414
6400
  /** The document is wrong — regenerate or repair the file. */
@@ -4476,6 +6462,7 @@ function reportDocumentDiagnostics(doc, where) {
4476
6462
  export {
4477
6463
  __spreadValues,
4478
6464
  __spreadProps,
6465
+ __objRest,
4479
6466
  PX_UNKNOWN_KEY_ERROR,
4480
6467
  schemaKeys,
4481
6468
  describeSchema,
@@ -4517,6 +6504,8 @@ export {
4517
6504
  isNativeForced,
4518
6505
  mayUseNativeScrollTimeline,
4519
6506
  PX_TRIGGER_DEFAULTS,
6507
+ PX_DEFAULT_DURATION_MS,
6508
+ PX_DEFAULT_ITERATIONS,
4520
6509
  PxControlMode,
4521
6510
  resolveControlMode,
4522
6511
  controlModeTakesOverTrigger,
@@ -4532,9 +6521,6 @@ export {
4532
6521
  PxTextPathSpacing,
4533
6522
  PxStrokeTrimSubPaths,
4534
6523
  PX_TEXT_CONTENT_ATTR,
4535
- TRANSFORM_ATTR,
4536
- OFFSET_DISTANCE_ATTR,
4537
- TRANSFORM_PART,
4538
6524
  PX_TRANSFORM_PART_KEYS,
4539
6525
  PxGradientSpreadMethod,
4540
6526
  PxGradientType,
@@ -4547,11 +6533,8 @@ export {
4547
6533
  getChildren,
4548
6534
  PxKeyframeValueSchema,
4549
6535
  PxKeyframeSchema,
4550
- keyframeTime,
4551
6536
  keyframeValue,
4552
6537
  keyframeEasing,
4553
- keyframeTangentIn,
4554
- keyframeTangentOut,
4555
6538
  PxLoopSchema,
4556
6539
  PxPropertyAnimationSchema,
4557
6540
  PxTransformPartsSchema,
@@ -4562,6 +6545,7 @@ export {
4562
6545
  PxScrollRangePointSchema,
4563
6546
  PxScrollRangeSchema,
4564
6547
  PxScrollSchema,
6548
+ PxTimeTimelineSchema,
4565
6549
  PxTimelineSchema,
4566
6550
  PxAnimatorConfigSchema,
4567
6551
  PxAttrValueSchema,
@@ -4599,49 +6583,31 @@ export {
4599
6583
  PX_PCT_BASED_ATTR_NAMES,
4600
6584
  composeTransformParts,
4601
6585
  PX_STYLE_ATTR_NAMES,
4602
- PX_DEFAULT_DURATION_MS,
4603
6586
  kebabToCamelCaseWord,
4604
6587
  camelCaseToKebabWordIfNeeded,
4605
6588
  clamp,
4606
- bezier2D_arcLengthLUT,
4607
6589
  PX_DISALLOWED_SVG_TAGS_LOWER,
4608
6590
  PX_CSS_ONLY_STYLE_PROPS,
4609
6591
  sanitizeAttributeValue,
4610
6592
  toDomProps,
6593
+ mergeStaticTransformIntoAnimDef,
4611
6594
  materializeMotionPathInPropAnim,
4612
- materializeMotionPathsInTree,
4613
6595
  PX_LOOP_JUMP_SHIFT_MS,
4614
- parseSvgPathToBezier,
4615
6596
  interpolateValue,
4616
- materializeInternalLoopsInTree,
4617
- mergeStaticTransformIntoAnimDef,
4618
6597
  normalizeBindings,
4619
6598
  calcAnimationValues,
4620
- partsRecord,
4621
- readAnimatable,
4622
- writeAnimatableChannel,
4623
- readStaticOrigin,
4624
- keyframeWith,
4625
- deepClonePxNode,
4626
- regenerateIdsAndRewriteRefs,
4627
- applyUseOffsetToG,
4628
- genId,
4629
- stripHash,
4630
- indexById,
4631
- spliceDefs,
4632
- clone,
4633
- regenerateIdsInClone,
4634
6599
  createPathSampler,
4635
6600
  extendedPathForBrowser,
4636
- applyTextPathEffect,
4637
6601
  layoutGlyphTextChars,
4638
6602
  materializeGlyphTextAlongPath,
4639
6603
  materializeGlyphText,
4640
- applyTextGlyphsEffect,
4641
- applyTextGlyphsAlongPath,
6604
+ materializeNodeEffects,
6605
+ materializeAllInTree,
6606
+ prepareDocumentForRender,
6607
+ PxDiagnosticCode,
4642
6608
  PxDiagnosticKind,
4643
6609
  createDiagnostics,
4644
6610
  diagnoseDocument,
4645
6611
  reportDocumentDiagnostics
4646
6612
  };
4647
- //# sourceMappingURL=chunk-EFQLDGFY.js.map
6613
+ //# sourceMappingURL=chunk-37OFJ3RX.js.map