@pixodesk/svg-animator-web 1.0.43 → 1.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/internal.cjs CHANGED
@@ -20,14 +20,1176 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/internal.ts
21
21
  var internal_exports = {};
22
22
  __export(internal_exports, {
23
- PX_ANIMATOR_DOC_KEY: () => PX_ANIMATOR_DOC_KEY
23
+ PLAY_WHEN_VISIBLE_DEFAULTS: () => PLAY_WHEN_VISIBLE_DEFAULTS,
24
+ PX_ANIMATOR_DOC_KEY: () => PX_ANIMATOR_DOC_KEY,
25
+ createVisibilityGate: () => createVisibilityGate
24
26
  });
25
27
  module.exports = __toCommonJS(internal_exports);
26
28
 
27
29
  // src/shared/PxAnimatorKeys.ts
28
30
  var PX_ANIMATOR_DOC_KEY = "doc";
31
+
32
+ // ../svg-animator-core/dist/chunk-EFQLDGFY.js
33
+ var __defProp2 = Object.defineProperty;
34
+ var __defProps = Object.defineProperties;
35
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
36
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
37
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
38
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
39
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
40
+ var __spreadValues = (a, b) => {
41
+ for (var prop in b || (b = {}))
42
+ if (__hasOwnProp2.call(b, prop))
43
+ __defNormalProp(a, prop, b[prop]);
44
+ if (__getOwnPropSymbols)
45
+ for (var prop of __getOwnPropSymbols(b)) {
46
+ if (__propIsEnum.call(b, prop))
47
+ __defNormalProp(a, prop, b[prop]);
48
+ }
49
+ return a;
50
+ };
51
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
52
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
53
+ function pathStr(path) {
54
+ if (!path.length) return ".";
55
+ let result = "";
56
+ for (const seg of path) {
57
+ if (seg.startsWith("[")) result += seg;
58
+ else result += (result ? "." : "") + seg;
59
+ }
60
+ return result;
61
+ }
62
+ var Base = class {
63
+ _canSanitize(raw) {
64
+ return this.isValid(raw);
65
+ }
66
+ optional() {
67
+ return new Optional(this);
68
+ }
69
+ };
70
+ var Optional = class extends Base {
71
+ constructor(inner) {
72
+ super();
73
+ this.inner = inner;
74
+ this._default = void 0;
75
+ }
76
+ sanitize(raw) {
77
+ if (raw === void 0 || raw === null) return void 0;
78
+ return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
79
+ }
80
+ isValid(raw, ctx, path) {
81
+ if (raw === void 0 || raw === null) return true;
82
+ return this.inner.isValid(raw, ctx, path);
83
+ }
84
+ _canSanitize(raw) {
85
+ return raw === void 0 || raw === null || this.inner._canSanitize(raw);
86
+ }
87
+ };
88
+ var Str = class extends Base {
89
+ constructor(_default = "") {
90
+ super();
91
+ this._default = _default;
92
+ }
93
+ sanitize(raw) {
94
+ return typeof raw === "string" ? raw : this._default;
95
+ }
96
+ isValid(raw, ctx, path) {
97
+ if (typeof raw === "string") return true;
98
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
99
+ return false;
100
+ }
101
+ };
102
+ var Num = class extends Base {
103
+ constructor(_default = 0) {
104
+ super();
105
+ this._default = _default;
106
+ }
107
+ sanitize(raw) {
108
+ return typeof raw === "number" && isFinite(raw) ? raw : this._default;
109
+ }
110
+ isValid(raw, ctx, path) {
111
+ if (typeof raw === "number" && isFinite(raw)) return true;
112
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
113
+ return false;
114
+ }
115
+ };
116
+ var Bool = class extends Base {
117
+ constructor(_default = false) {
118
+ super();
119
+ this._default = _default;
120
+ }
121
+ sanitize(raw) {
122
+ return typeof raw === "boolean" ? raw : this._default;
123
+ }
124
+ isValid(raw, ctx, path) {
125
+ if (typeof raw === "boolean") return true;
126
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
127
+ return false;
128
+ }
129
+ };
130
+ var Literal = class extends Base {
131
+ constructor(value) {
132
+ super();
133
+ this.value = value;
134
+ this._default = value;
135
+ }
136
+ sanitize(raw) {
137
+ return raw === this.value ? this.value : this._default;
138
+ }
139
+ isValid(raw, ctx, path) {
140
+ if (raw === this.value) return true;
141
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected " + JSON.stringify(this.value) + ", got " + JSON.stringify(raw));
142
+ return false;
143
+ }
144
+ };
145
+ var Enum = class extends Base {
146
+ constructor(values, defaultVal) {
147
+ super();
148
+ this.values = values;
149
+ this._default = defaultVal != null ? defaultVal : values[0];
150
+ }
151
+ sanitize(raw) {
152
+ return this.values.includes(raw) ? raw : this._default;
153
+ }
154
+ isValid(raw, ctx, path) {
155
+ if (this.values.includes(raw)) return true;
156
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected one of " + this.values.map((v) => JSON.stringify(v)).join(" | ") + ", got " + JSON.stringify(raw));
157
+ return false;
158
+ }
159
+ };
160
+ var UNION_MEMBER_ERROR_LIMIT = 4;
161
+ var Union = class extends Base {
162
+ constructor(schemas, defaultVal) {
163
+ super();
164
+ this.schemas = schemas;
165
+ this._kind = "union";
166
+ this._default = defaultVal != null ? defaultVal : schemas[0]._default;
167
+ }
168
+ sanitize(raw) {
169
+ for (const s of this.schemas) {
170
+ if (s.isValid(raw)) return s.sanitize(raw);
171
+ }
172
+ return this._default;
173
+ }
174
+ isValid(raw, ctx, path) {
175
+ var _a2;
176
+ const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
177
+ if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
178
+ if (!ctx) return false;
179
+ const base = pathStr(path != null ? path : []);
180
+ ctx.errors.push(base + ": no union member matched for value " + ((_a2 = JSON.stringify(raw)) != null ? _a2 : "").slice(0, 240));
181
+ let best;
182
+ let bestDepth = -1;
183
+ const leafExpectations = [];
184
+ for (const member of this.schemas) {
185
+ const sink = { errors: [], warnings: [], strict: ctx.strict };
186
+ member.isValid(raw, sink, path ? [...path] : void 0);
187
+ if (!sink.errors.length) continue;
188
+ const depth = Math.max(...sink.errors.map((e) => e.slice(0, e.indexOf(":")).length));
189
+ if (depth > bestDepth || depth === bestDepth && best && sink.errors.length < best.length) {
190
+ bestDepth = depth;
191
+ best = sink.errors;
192
+ }
193
+ if (depth <= base.length) {
194
+ for (const e of sink.errors) {
195
+ const m = /: expected (.+?), got /.exec(e);
196
+ if (m && !leafExpectations.includes(m[1])) leafExpectations.push(m[1]);
197
+ }
198
+ }
199
+ }
200
+ if (best && bestDepth > base.length) {
201
+ for (const e of best.slice(0, UNION_MEMBER_ERROR_LIMIT)) {
202
+ if (!ctx.errors.includes(e)) ctx.errors.push(e);
203
+ }
204
+ } else if (leafExpectations.length) {
205
+ ctx.errors.push(base + ": expected " + leafExpectations.join(" | "));
206
+ }
207
+ return false;
208
+ }
209
+ _canSanitize(raw) {
210
+ return this.schemas.some((s) => s._canSanitize(raw));
211
+ }
212
+ };
213
+ var DiscriminatedUnion = class extends Base {
214
+ constructor(_key, _schemas, defaultVal) {
215
+ var _a2;
216
+ super();
217
+ this._key = _key;
218
+ this._schemas = _schemas;
219
+ this._kind = "discriminatedUnion";
220
+ this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
221
+ this._map = /* @__PURE__ */ new Map();
222
+ for (const s of _schemas) {
223
+ const keySchema = s._shape[_key];
224
+ if (!keySchema) continue;
225
+ const literal = (_a2 = keySchema.inner) != null ? _a2 : keySchema;
226
+ this._map.set(literal._default, s);
227
+ if (keySchema.inner) this._absentMember = s;
228
+ }
229
+ }
230
+ _findSchema(raw) {
231
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
232
+ const val = raw[this._key];
233
+ if (val === void 0 || val === null) return this._absentMember;
234
+ return this._map.get(val);
235
+ }
236
+ sanitize(raw) {
237
+ var _a2;
238
+ return ((_a2 = this._findSchema(raw)) != null ? _a2 : this._schemas[0]).sanitize(raw);
239
+ }
240
+ isValid(raw, ctx, path) {
241
+ const schema = this._findSchema(raw);
242
+ if (!schema) {
243
+ const val = raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw[this._key] : void 0;
244
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no discriminated union member matched " + this._key + "=" + JSON.stringify(val));
245
+ return false;
246
+ }
247
+ return schema.isValid(raw, ctx, path);
248
+ }
249
+ _canSanitize(raw) {
250
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return false;
251
+ const schema = this._findSchema(raw);
252
+ return schema ? schema._canSanitize(raw) : this._schemas[0]._canSanitize(raw);
253
+ }
254
+ };
255
+ var Obj = class extends Base {
256
+ constructor(_shape) {
257
+ super();
258
+ this._shape = _shape;
259
+ const d = {};
260
+ for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
261
+ this._default = d;
262
+ }
263
+ sanitize(raw) {
264
+ const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
265
+ const out = {};
266
+ for (const key of Object.keys(this._shape)) {
267
+ const v = this._shape[key].sanitize(src[key]);
268
+ if (v !== void 0) out[key] = v;
269
+ }
270
+ return out;
271
+ }
272
+ isValid(raw, ctx, path) {
273
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
274
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object, got " + (Array.isArray(raw) ? "array" : typeof raw));
275
+ return false;
276
+ }
277
+ const obj = raw;
278
+ const p = path != null ? path : [];
279
+ let ok = true;
280
+ for (const key of Object.keys(this._shape)) {
281
+ p.push(key);
282
+ if (!this._shape[key].isValid(obj[key], ctx, p)) ok = false;
283
+ p.pop();
284
+ }
285
+ if (ctx == null ? void 0 : ctx.strict) {
286
+ for (const key of Object.keys(obj)) {
287
+ if (key in this._shape) continue;
288
+ if (obj[key] === void 0) continue;
289
+ p.push(key);
290
+ ctx.errors.push(pathStr(p) + ": " + PX_UNKNOWN_KEY_ERROR);
291
+ p.pop();
292
+ ok = false;
293
+ }
294
+ }
295
+ return ok;
296
+ }
297
+ _canSanitize(raw) {
298
+ return !!raw && typeof raw === "object" && !Array.isArray(raw);
299
+ }
300
+ };
301
+ var OpenObj = class extends Base {
302
+ constructor(_shape, _openSchema) {
303
+ super();
304
+ this._shape = _shape;
305
+ this._openSchema = _openSchema;
306
+ const d = {};
307
+ for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
308
+ this._default = d;
309
+ }
310
+ sanitize(raw) {
311
+ const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
312
+ const out = __spreadValues({}, src);
313
+ for (const key of Object.keys(this._shape)) {
314
+ const v = this._shape[key].sanitize(src[key]);
315
+ if (v !== void 0) out[key] = v;
316
+ }
317
+ if (this._openSchema) {
318
+ for (const key of Object.keys(src)) {
319
+ if (!(key in this._shape)) out[key] = this._openSchema.sanitize(src[key]);
320
+ }
321
+ }
322
+ return out;
323
+ }
324
+ isValid(raw, ctx, path) {
325
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
326
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object, got " + (Array.isArray(raw) ? "array" : typeof raw));
327
+ return false;
328
+ }
329
+ const obj = raw;
330
+ const p = path != null ? path : [];
331
+ let ok = true;
332
+ for (const key of Object.keys(this._shape)) {
333
+ p.push(key);
334
+ if (!this._shape[key].isValid(obj[key], ctx, p)) ok = false;
335
+ p.pop();
336
+ }
337
+ if (this._openSchema) {
338
+ for (const key of Object.keys(obj)) {
339
+ if (key in this._shape) continue;
340
+ p.push(key);
341
+ if (!this._openSchema.isValid(obj[key], ctx, p)) ok = false;
342
+ p.pop();
343
+ }
344
+ }
345
+ return ok;
346
+ }
347
+ _canSanitize(raw) {
348
+ return !!raw && typeof raw === "object" && !Array.isArray(raw);
349
+ }
350
+ };
351
+ var Arr = class extends Base {
352
+ constructor(item) {
353
+ super();
354
+ this.item = item;
355
+ this._default = [];
356
+ }
357
+ sanitize(raw) {
358
+ if (!Array.isArray(raw)) return [];
359
+ const out = [];
360
+ for (const el of raw) {
361
+ if (this.item._canSanitize(el)) out.push(this.item.sanitize(el));
362
+ }
363
+ return out;
364
+ }
365
+ isValid(raw, ctx, path) {
366
+ if (!Array.isArray(raw)) {
367
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected array, got " + typeof raw);
368
+ return false;
369
+ }
370
+ const p = path != null ? path : [];
371
+ let ok = true;
372
+ for (let i = 0; i < raw.length; i++) {
373
+ p.push("[" + i + "]");
374
+ if (!this.item.isValid(raw[i], ctx, p)) ok = false;
375
+ p.pop();
376
+ }
377
+ return ok;
378
+ }
379
+ _canSanitize(raw) {
380
+ return Array.isArray(raw);
381
+ }
382
+ };
383
+ var Rec = class extends Base {
384
+ constructor(value) {
385
+ super();
386
+ this.value = value;
387
+ this._kind = "record";
388
+ this._default = {};
389
+ }
390
+ sanitize(raw) {
391
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
392
+ const out = {};
393
+ for (const [k, v] of Object.entries(raw)) {
394
+ if (this.value._canSanitize(v)) out[k] = this.value.sanitize(v);
395
+ }
396
+ return out;
397
+ }
398
+ isValid(raw, ctx, path) {
399
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
400
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object/record, got " + (Array.isArray(raw) ? "array" : typeof raw));
401
+ return false;
402
+ }
403
+ const p = path != null ? path : [];
404
+ let ok = true;
405
+ for (const [k, v] of Object.entries(raw)) {
406
+ p.push(k);
407
+ if (!this.value.isValid(v, ctx, p)) ok = false;
408
+ p.pop();
409
+ }
410
+ return ok;
411
+ }
412
+ _canSanitize(raw) {
413
+ return !!raw && typeof raw === "object" && !Array.isArray(raw);
414
+ }
415
+ };
416
+ var Any = class extends Base {
417
+ constructor() {
418
+ super(...arguments);
419
+ this._default = void 0;
420
+ }
421
+ sanitize(raw) {
422
+ return raw;
423
+ }
424
+ isValid(_raw, _ctx, _path) {
425
+ return true;
426
+ }
427
+ _canSanitize(_raw) {
428
+ return true;
429
+ }
430
+ };
431
+ var Defined = class extends Base {
432
+ constructor() {
433
+ super(...arguments);
434
+ this._default = void 0;
435
+ }
436
+ sanitize(raw) {
437
+ return raw;
438
+ }
439
+ isValid(raw, ctx, path) {
440
+ if (raw !== void 0) return true;
441
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": required value is missing");
442
+ return false;
443
+ }
444
+ _canSanitize(raw) {
445
+ return raw !== void 0;
446
+ }
447
+ };
448
+ var Lazy = class extends Base {
449
+ constructor(fn, _default) {
450
+ super();
451
+ this.fn = fn;
452
+ this._default = _default;
453
+ this.resolved = null;
454
+ }
455
+ get schema() {
456
+ var _a2;
457
+ return (_a2 = this.resolved) != null ? _a2 : this.resolved = this.fn();
458
+ }
459
+ sanitize(raw) {
460
+ return this.schema.sanitize(raw);
461
+ }
462
+ isValid(raw, ctx, path) {
463
+ return this.schema.isValid(raw, ctx, path);
464
+ }
465
+ _canSanitize(raw) {
466
+ return this.schema._canSanitize(raw);
467
+ }
468
+ };
469
+ var Tuple = class extends Base {
470
+ constructor(schemas) {
471
+ super();
472
+ this.schemas = schemas;
473
+ this._kind = "tuple";
474
+ this._default = schemas.map((s) => s._default);
475
+ }
476
+ sanitize(raw) {
477
+ if (!Array.isArray(raw) || raw.length !== this.schemas.length) return this._default;
478
+ return this.schemas.map((s, i) => s.sanitize(raw[i]));
479
+ }
480
+ isValid(raw, ctx, path) {
481
+ if (!Array.isArray(raw) || raw.length !== this.schemas.length) {
482
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected tuple of length " + this.schemas.length + ", got " + (Array.isArray(raw) ? "array[" + raw.length + "]" : typeof raw));
483
+ return false;
484
+ }
485
+ const p = path != null ? path : [];
486
+ let ok = true;
487
+ for (let i = 0; i < this.schemas.length; i++) {
488
+ p.push("[" + i + "]");
489
+ if (!this.schemas[i].isValid(raw[i], ctx, p)) ok = false;
490
+ p.pop();
491
+ }
492
+ return ok;
493
+ }
494
+ // Require exact length so wrong-length arrays are dropped rather than repaired to default.
495
+ _canSanitize(raw) {
496
+ return Array.isArray(raw) && raw.length === this.schemas.length;
497
+ }
498
+ };
499
+ function implementsInterface() {
500
+ return (schema) => schema;
501
+ }
502
+ var px = {
503
+ /** Matches a string. Default: '' or provided value. */
504
+ string: (defaultVal = "") => new Str(defaultVal),
505
+ /** Matches a finite number. Default: 0 or provided value. */
506
+ number: (defaultVal = 0) => new Num(defaultVal),
507
+ /** Matches a boolean. Default: false or provided value. */
508
+ boolean: (defaultVal = false) => new Bool(defaultVal),
509
+ /** Matches one exact primitive value; its default is the value itself. */
510
+ literal: (value) => new Literal(value),
511
+ /** Matches one of a fixed set of string/number values. Default: first value. */
512
+ enum: (values, defaultVal) => new Enum(values, defaultVal),
513
+ /**
514
+ * Returns the first schema whose isValid passes.
515
+ * TypeScript infers the union of all member types automatically.
516
+ */
517
+ union: (schemas, defaultVal) => new Union(schemas, defaultVal),
518
+ /**
519
+ * Discriminated union — reads `raw[key]`, finds the member schema whose
520
+ * literal at `key` matches, then delegates sanitize/isValid to that member.
521
+ * Each member must be an object schema with a `px.literal(...)` at `key`.
522
+ * TypeScript infers the union of all member types automatically.
523
+ */
524
+ discriminatedUnion: (key, schemas) => new DiscriminatedUnion(key, schemas),
525
+ /** Typed object — unknown keys are stripped. Required fields fall back to their default. */
526
+ object: (shape) => new Obj(shape),
527
+ /**
528
+ * Open object — validates known keys; passes unknown keys through as-is,
529
+ * or validates/sanitizes them against `openSchema` when provided.
530
+ */
531
+ openObject: (shape, openSchema) => new OpenObj(shape, openSchema),
532
+ /**
533
+ * Creates a new closed object schema by merging a base schema's shape with additional fields.
534
+ * The base can be the result of px.object() or px.openObject() — anything with a _shape property.
535
+ *
536
+ * @example
537
+ * const PxSvgNodeSchema = px.extendedObject(PxNodeBaseSchema, { width: px.number().optional() });
538
+ */
539
+ extendedObject: (base, extra) => new Obj(__spreadValues(__spreadValues({}, base._shape), extra)),
540
+ /** Array whose unrecoverable items are filtered out. Default: []. */
541
+ array: (item) => new Arr(item),
542
+ /** String-keyed record whose unrecoverable values are dropped. Default: {}. */
543
+ record: (value) => new Rec(value),
544
+ /** Passes anything through unchanged — always valid. */
545
+ any: () => new Any(),
546
+ /** Anything EXCEPT `undefined` — an open type whose presence is required (V6). */
547
+ defined: () => new Defined(),
548
+ /** Fixed-length tuple — validates element count and each position individually. */
549
+ tuple: (schemas) => new Tuple(schemas),
550
+ /** Defers schema creation — required for recursive types. Must supply a default value. */
551
+ lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
552
+ };
553
+ var PX_WIRE_SCHEMA_VERSION = "1.2";
554
+ var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
555
+ function parseWireVersion(raw) {
556
+ if (typeof raw !== "string") return void 0;
557
+ const m = VERSION_RE.exec(raw.trim());
558
+ if (!m) return void 0;
559
+ return { a: Number(m[1]), b: Number(m[2]), c: m[3] === void 0 ? 0 : Number(m[3]) };
560
+ }
561
+ var _a;
562
+ var PX_WIRE_VERSION = (_a = parseWireVersion(PX_WIRE_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
563
+ var PxFillMode = {
564
+ forwards: "forwards",
565
+ backwards: "backwards",
566
+ both: "both",
567
+ none: "none"
568
+ };
569
+ var PxPlaybackDirection = {
570
+ normal: "normal",
571
+ reverse: "reverse",
572
+ alternate: "alternate",
573
+ alternateReverse: "alternate-reverse"
574
+ };
575
+ var PxTriggerStart = {
576
+ load: "load",
577
+ mouseOver: "mouseOver",
578
+ click: "click",
579
+ none: "none"
580
+ };
581
+ var PxOffScreenAction = {
582
+ pause: "pause",
583
+ continue: "continue",
584
+ reset: "reset"
585
+ };
586
+ var PxMouseOutAction = {
587
+ continue: "continue",
588
+ pause: "pause",
589
+ reset: "reset",
590
+ reverse: "reverse"
591
+ };
592
+ var PxFinishAction = {
593
+ hold: "hold",
594
+ reset: "reset"
595
+ };
596
+ var PxScrollKind = {
597
+ view: "view",
598
+ scroll: "scroll"
599
+ };
600
+ var PxScrollAxis = {
601
+ block: "block",
602
+ inline: "inline",
603
+ x: "x",
604
+ y: "y"
605
+ };
606
+ var PxScrollSource = {
607
+ nearest: "nearest",
608
+ root: "root"
609
+ };
610
+ var PxPinAlign = {
611
+ top: "top",
612
+ center: "center",
613
+ bottom: "bottom"
614
+ };
615
+ var PxScrollPhase = {
616
+ cover: "cover",
617
+ contain: "contain",
618
+ entry: "entry",
619
+ exit: "exit",
620
+ entryCrossing: "entry-crossing",
621
+ exitCrossing: "exit-crossing"
622
+ };
623
+ var PxAlongPathMode = {
624
+ sampled: "sampled",
625
+ offsetPath: "offsetPath"
626
+ };
627
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
628
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
629
+ var PX_FLAT_RUNTIME_VIEW_KEYS = [
630
+ ...PX_TIMELINE_SHARED_KEYS,
631
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
632
+ "fill",
633
+ "resetOnFinish",
634
+ "timelineSource",
635
+ "scroll"
636
+ ];
637
+ var PxTimelineEngine = {
638
+ native: "native",
639
+ js: "js"
640
+ };
641
+ var PxTimelineEngineSetting = __spreadProps(__spreadValues({}, PxTimelineEngine), {
642
+ auto: "auto"
643
+ });
644
+ var PX_TRIGGER_DEFAULTS = {
645
+ start: "load",
646
+ offScreen: "pause",
647
+ mouseOut: "continue",
648
+ visibilityThreshold: 0.5,
649
+ visibilityDebounce: 150
650
+ };
651
+ var PxLoopRepeatAt = {
652
+ /** Segment from the START; the repetition runs BEFORE the first keyframe
653
+ * (intro loops that play until the main timeline begins). */
654
+ start: "start",
655
+ /** DEFAULT — segment from the END; the repetition runs AFTER the last keyframe
656
+ * (idle/outro loops that continue once the main timeline has finished). */
657
+ end: "end"
658
+ };
659
+ var PxLoopDirection = {
660
+ /** DEFAULT — cycle: every repetition replays the segment the same way round. */
661
+ normal: "normal",
662
+ /** Ping-pong: repetitions alternate forward / backward. */
663
+ alternate: "alternate"
664
+ };
665
+ var PxMaskType = {
666
+ luminance: "luminance",
667
+ alpha: "alpha"
668
+ };
669
+ var PxUnits = {
670
+ userSpaceOnUse: "userSpaceOnUse",
671
+ objectBoundingBox: "objectBoundingBox"
672
+ };
673
+ var PxCloneWithout = {
674
+ translate: "translate"
675
+ // transform: 'transform', // future: drop rotate/scale too (content only)
676
+ };
677
+ var PxPathOverflow = {
678
+ clip: "clip",
679
+ extend: "extend"
680
+ };
681
+ var PxLengthAdjust = {
682
+ spacing: "spacing",
683
+ spacingAndGlyphs: "spacingAndGlyphs"
684
+ };
685
+ var PxTextPathMethod = {
686
+ align: "align",
687
+ stretch: "stretch"
688
+ };
689
+ var PxTextPathSpacing = {
690
+ auto: "auto",
691
+ exact: "exact"
692
+ };
693
+ var PxStrokeTrimSubPaths = {
694
+ separate: "separate",
695
+ combined: "combined"
696
+ };
697
+ var TRANSFORM_PART = {
698
+ translate: "translate",
699
+ rotate: "rotate",
700
+ scale: "scale",
701
+ origin: "origin"
702
+ };
703
+ var PX_TRANSFORM_PART_KEYS = [
704
+ TRANSFORM_PART.translate,
705
+ TRANSFORM_PART.rotate,
706
+ TRANSFORM_PART.scale,
707
+ TRANSFORM_PART.origin
708
+ ];
709
+ var PxGradientSpreadMethod = {
710
+ pad: "pad",
711
+ reflect: "reflect",
712
+ repeat: "repeat"
713
+ };
714
+ var PxGradientType = {
715
+ linear: "linear",
716
+ radial: "radial"
717
+ };
718
+ var PxEasingOrRefSchema = px.union([
719
+ px.string(),
720
+ px.tuple([px.number(), px.number(), px.number(), px.number()])
721
+ ]);
722
+ var PxKeyframeValueSchema = implementsInterface()(px.union([
723
+ px.string(),
724
+ // e.g. for colors
725
+ px.number(),
726
+ px.array(px.number()),
727
+ // ORDER LAW: the key-discriminated object shape (`{pathData}`) comes BEFORE the
728
+ // all-optional transform-parts record. In default (non-strict) mode that record accepts
729
+ // ANY object (every key optional, unknown keys ignored), so listing it earlier made
730
+ // Union.sanitize route `{pathData}` values into it and strip them to `{}` —
731
+ // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
732
+ // order-independent (`some()`); only sanitize routing depends on this order.
733
+ px.object({ pathData: px.string() }),
734
+ // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
735
+ px.lazy(() => px.array(PxGradientStopSchema), []),
736
+ px.lazy(() => PxTransformPartsSchema, {})
737
+ ]));
738
+ var PxKeyframeSchema = implementsInterface()(px.object({
739
+ time: px.number().optional(),
740
+ value: PxKeyframeValueSchema.optional(),
741
+ easing: PxEasingOrRefSchema.optional(),
742
+ tangentOut: px.tuple([px.number(), px.number()]).optional(),
743
+ tangentIn: px.tuple([px.number(), px.number()]).optional()
744
+ // (`selected` — editor timeline-selection UI state — was REMOVED from the wire
745
+ // (review §1.3): editor data lives under `meta`. The editor still carries it on
746
+ // its internal COPY-PASTE payload, which never validates against this schema.)
747
+ }));
748
+ var PxLoopSchema = implementsInterface()(px.object({
749
+ segmentCount: px.number().optional(),
750
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
751
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
752
+ }));
753
+ var PxPropertyAnimationSchema = implementsInterface()(px.object({
754
+ value: PxKeyframeValueSchema.optional(),
755
+ keyframes: px.array(PxKeyframeSchema).optional(),
756
+ loop: px.union([PxLoopSchema, px.boolean()]).optional(),
757
+ autoOrient: px.boolean().optional(),
758
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
759
+ }));
760
+ var PxTransformPartsSchema = implementsInterface()(px.object({
761
+ translate: px.tuple([px.number(), px.number()]).optional(),
762
+ rotate: px.number().optional(),
763
+ skew: px.number().optional(),
764
+ scale: px.tuple([px.number(), px.number()]).optional(),
765
+ origin: px.tuple([px.number(), px.number()]).optional()
766
+ }));
767
+ var PxTransformValueSchema = px.union([
768
+ px.string(),
769
+ PxTransformPartsSchema,
770
+ px.object({ value: PxTransformPartsSchema }),
771
+ PxPropertyAnimationSchema
772
+ ]);
773
+ var PxAnimationDefinitionSchema = implementsInterface()(
774
+ px.record(PxPropertyAnimationSchema)
775
+ );
776
+ var PxElementAnimationSchema = implementsInterface()(px.union([
777
+ px.string(),
778
+ px.array(px.union([px.string(), PxAnimationDefinitionSchema])),
779
+ PxAnimationDefinitionSchema
780
+ ]));
781
+ var PxTriggerSchema = implementsInterface()(px.object({
782
+ start: px.enum([PxTriggerStart.load, PxTriggerStart.mouseOver, PxTriggerStart.click, PxTriggerStart.none], PX_TRIGGER_DEFAULTS.start).optional(),
783
+ offScreen: px.enum([PxOffScreenAction.pause, PxOffScreenAction.continue, PxOffScreenAction.reset], PX_TRIGGER_DEFAULTS.offScreen).optional(),
784
+ mouseOut: px.enum([PxMouseOutAction.continue, PxMouseOutAction.pause, PxMouseOutAction.reset, PxMouseOutAction.reverse], PX_TRIGGER_DEFAULTS.mouseOut).optional(),
785
+ // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
786
+ // `fill`) or `'reset'` (snap back to the start state). One of four occasion keys
787
+ // (`start`, `offScreen`, `mouseOut`, `finish`), all named the same way.
788
+ finish: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
789
+ visibilityThreshold: px.number().optional(),
790
+ visibilityDebounce: px.number().optional()
791
+ }));
792
+ var PxGlyphSchema = implementsInterface()(px.object({
793
+ width: px.number(),
794
+ pathData: px.string()
795
+ }));
796
+ var PxGlyphFontSchema = implementsInterface()(px.object({
797
+ fontFamily: px.string(),
798
+ fontStyle: px.string(),
799
+ ascent: px.number(),
800
+ unitsPerEm: px.number(),
801
+ glyphs: px.record(PxGlyphSchema)
802
+ }));
803
+ var PxDefinitionsSchema = implementsInterface()(px.object({
804
+ easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
805
+ animations: px.record(PxAnimationDefinitionSchema).optional(),
806
+ fonts: px.record(PxGlyphFontSchema).optional()
807
+ }));
808
+ var PxScrollRangePointSchema = implementsInterface()(px.object({
809
+ phase: px.enum([
810
+ PxScrollPhase.cover,
811
+ PxScrollPhase.contain,
812
+ PxScrollPhase.entry,
813
+ PxScrollPhase.exit,
814
+ PxScrollPhase.entryCrossing,
815
+ PxScrollPhase.exitCrossing
816
+ ]).optional(),
817
+ fraction: px.number().optional()
818
+ }));
819
+ var PxScrollRangeSchema = px.object({
820
+ start: PxScrollRangePointSchema.optional(),
821
+ end: PxScrollRangePointSchema.optional()
822
+ });
823
+ var PxScrollSchema = implementsInterface()(px.object({
824
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
825
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
826
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
827
+ // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
828
+ subject: px.string().optional(),
829
+ smoothing: px.number().optional(),
830
+ pin: px.boolean().optional(),
831
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
832
+ pinOffset: px.number().optional(),
833
+ pinDistance: px.number().optional(),
834
+ range: PxScrollRangeSchema.optional()
835
+ }));
836
+ var PxTimelinePinSchema = implementsInterface()(px.object({
837
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
838
+ offset: px.number().optional(),
839
+ distance: px.number().optional()
840
+ }));
841
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js]).optional();
842
+ var PxTimeTimelineSchema = implementsInterface()(px.object({
843
+ type: px.literal("time").optional(),
844
+ engine: PxTimelineEngineSchema,
845
+ frameRate: px.number().optional(),
846
+ // §2.8: duration is a property of the TIMELINE — how long one pass takes.
847
+ duration: px.number().optional(),
848
+ trigger: PxTriggerSchema.optional(),
849
+ delay: px.number().optional(),
850
+ iterations: px.union([px.number(), px.literal("infinite")]).optional(),
851
+ // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
852
+ // — never `fill`, which is paint everywhere else in the format.
853
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
854
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
855
+ }));
856
+ var scrollishTimelineShape = {
857
+ // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
858
+ // span the scroll range maps onto.
859
+ duration: px.number().optional(),
860
+ // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
861
+ // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
862
+ iterations: px.number().optional(),
863
+ engine: PxTimelineEngineSchema,
864
+ frameRate: px.number().optional(),
865
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
866
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
867
+ subject: px.string().optional(),
868
+ // 'parent' | 'scroller' | any CSS selector
869
+ smoothing: px.number().optional(),
870
+ // ms
871
+ pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
872
+ range: PxScrollRangeSchema.optional()
873
+ };
874
+ var PxScrollTimelineSchema = implementsInterface()(
875
+ px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape))
876
+ );
877
+ var PxViewTimelineSchema = implementsInterface()(
878
+ px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape))
879
+ );
880
+ var PxTimelineSchema = px.discriminatedUnion("type", [
881
+ PxTimeTimelineSchema,
882
+ // first = the member an absent `type` selects
883
+ PxScrollTimelineSchema,
884
+ PxViewTimelineSchema
885
+ ]);
886
+ var PxBindingSchema = implementsInterface()(px.object({
887
+ target: px.string(),
888
+ animateWith: px.array(px.string())
889
+ }));
890
+ var PxAnimatorConfigSchema = implementsInterface()(px.object({
891
+ // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
892
+ // at this level only on the runtime view, like the rest of the playback dynamics.)
893
+ // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
894
+ timeline: PxTimelineSchema.optional(),
895
+ definitions: PxDefinitionsSchema.optional(),
896
+ bindings: px.array(PxBindingSchema).optional(),
897
+ debugGlobalName: px.string().optional(),
898
+ // Declared HERE because this is a closed object: an undeclared key would be stripped by
899
+ // `sanitize` and flagged by strict validation on our own files.
900
+ version: px.string().optional()
901
+ }));
902
+ var PxAttrValueSchema = px.union([
903
+ px.string(),
904
+ px.number(),
905
+ px.array(px.number()),
906
+ // Structured static — `{value: …}` (read-accepted transitional spelling, S1).
907
+ // `defined`, not `any`: the KEY's presence is what identifies this branch (V6).
908
+ px.object({ value: px.defined() }),
909
+ // Bare transform parts record — the canonical static `transform` on the wire (T2).
910
+ PxTransformPartsSchema
911
+ ]);
912
+ var PxAnimatableNumberSchema = px.union([
913
+ px.number(),
914
+ PxPropertyAnimationSchema,
915
+ px.object({ value: px.number() })
916
+ ]);
917
+ var PxAnimatableVec2Schema = px.union([
918
+ px.tuple([px.number(), px.number()]),
919
+ PxPropertyAnimationSchema,
920
+ px.object({ value: px.tuple([px.number(), px.number()]) })
921
+ ]);
922
+ var PxAnimatableStringSchema = px.union([
923
+ px.string(),
924
+ PxPropertyAnimationSchema,
925
+ px.object({ value: px.string() })
926
+ ]);
927
+ var PxTransformByEffectSchema = implementsInterface()(px.object({
928
+ translate: PxAnimatableVec2Schema.optional(),
929
+ rotate: PxAnimatableNumberSchema.optional(),
930
+ scale: PxAnimatableVec2Schema.optional(),
931
+ skew: PxAnimatableNumberSchema.optional(),
932
+ origin: PxAnimatableVec2Schema.optional()
933
+ }));
934
+ var PxRepeaterEffectSchema = implementsInterface()(px.object({
935
+ // STATIC config, not a channel (V2/SCHEMA-DESIGN R5): the copy COUNT is read
936
+ // once at expansion time and never sampled — plain number, no `keyframes`.
937
+ copies: px.number().optional(),
938
+ translate: PxAnimatableVec2Schema.optional(),
939
+ rotate: PxAnimatableNumberSchema.optional(),
940
+ skew: PxAnimatableNumberSchema.optional(),
941
+ scale: PxAnimatableVec2Schema.optional(),
942
+ origin: PxAnimatableVec2Schema.optional()
943
+ }));
944
+ var PxMaskedByEffectSchema = implementsInterface()(px.object({
945
+ source: px.string().optional(),
946
+ maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
947
+ maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
948
+ maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
949
+ x: px.number().optional(),
950
+ y: px.number().optional(),
951
+ width: px.number().optional(),
952
+ height: px.number().optional()
953
+ }));
954
+ var PxClipPathEffectSchema = implementsInterface()(px.object({
955
+ pathData: PxAnimatableStringSchema.optional()
956
+ }));
957
+ var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
958
+ offset: PxAnimatableNumberSchema.optional(),
959
+ range: PxAnimatableVec2Schema.optional(),
960
+ subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
961
+ }));
962
+ var PxRetimeEffectSchema = implementsInterface()(px.object({
963
+ start: px.number().optional(),
964
+ stretch: px.number().optional(),
965
+ timeCrop: px.tuple([px.number(), px.number()]).optional()
966
+ }));
967
+ var PxCloneEffectSchema = implementsInterface()(px.object({
968
+ // Subtractive on purpose: the `<use>` can only point at one wrapper layer of the
969
+ // source, so the choices form a ladder — 'translate' now, maybe 'transform' later.
970
+ without: px.enum([PxCloneWithout.translate]).optional(),
971
+ source: px.string().optional(),
972
+ retime: PxRetimeEffectSchema.optional()
973
+ }));
974
+ var PxGradientStopSchema = implementsInterface()(px.object({
975
+ offset: px.number(),
976
+ color: px.string()
977
+ }));
978
+ var PxAnimatableGradientStopsSchema = px.union([
979
+ px.array(PxGradientStopSchema),
980
+ px.object({ value: px.array(PxGradientStopSchema) }),
981
+ PxPropertyAnimationSchema
982
+ ]);
983
+ var PxFillGradientEffectSchema = implementsInterface()(px.object({
984
+ // Contextual kind — the `type` convention, see `PxNodeBaseSchema.type`.
985
+ type: px.enum([PxGradientType.linear, PxGradientType.radial]),
986
+ start: PxAnimatableVec2Schema.optional(),
987
+ end: PxAnimatableVec2Schema.optional(),
988
+ center: PxAnimatableVec2Schema.optional(),
989
+ radius: PxAnimatableNumberSchema.optional(),
990
+ focal: PxAnimatableVec2Schema.optional(),
991
+ stops: PxAnimatableGradientStopsSchema.optional(),
992
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
993
+ spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
994
+ gradientTransform: px.string().optional()
995
+ }));
996
+ var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
997
+ var PxTextPathEffectSchema = implementsInterface()(px.object({
998
+ pathData: px.string(),
999
+ pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1000
+ lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1001
+ method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
1002
+ spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
1003
+ startOffset: PxAnimatableNumberSchema.optional(),
1004
+ textLength: PxAnimatableNumberSchema.optional()
1005
+ }));
1006
+ var PxTextEffectSchema = implementsInterface()(px.object({
1007
+ useGlyphs: px.boolean().optional()
1008
+ }));
1009
+ var PxEffectsSchema = implementsInterface()(px.object({
1010
+ transformBy: PxTransformByEffectSchema.optional(),
1011
+ repeater: PxRepeaterEffectSchema.optional(),
1012
+ maskedBy: PxMaskedByEffectSchema.optional(),
1013
+ clipPath: PxClipPathEffectSchema.optional(),
1014
+ strokeTrim: PxStrokeTrimEffectSchema.optional(),
1015
+ clone: PxCloneEffectSchema.optional(),
1016
+ fillGradient: PxFillGradientEffectSchema.optional(),
1017
+ strokeGradient: PxStrokeGradientEffectSchema.optional(),
1018
+ textPath: PxTextPathEffectSchema.optional(),
1019
+ text: PxTextEffectSchema.optional()
1020
+ }));
1021
+ var PxNodeBaseSchema = px.openObject({
1022
+ // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1023
+ // kind of thing is this", discriminated by its CARRIER — here the node TAG
1024
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1025
+ // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1026
+ // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1027
+ // would add words that all mean "type" and still need the carrier to read.
1028
+ // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1029
+ // (issues V3), never of distinct key names.
1030
+ type: px.string(),
1031
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1032
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1033
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1034
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1035
+ // documented — because a wire key that is not in a schema is invisible to the
1036
+ // minifier's reserve list and gets renamed (dev-docs/plans/minification-boundary.md §1.1).
1037
+ domType: px.string().optional(),
1038
+ // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
1039
+ // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
1040
+ textContent: px.string().optional(),
1041
+ id: px.string().optional(),
1042
+ meta: px.any().optional(),
1043
+ // Player-effects bucket emitted by the Editor's lightweight design format.
1044
+ // Consumed and removed by `materializeNodeEffects` before any other normalization
1045
+ // (see `createAnimatorImpl`), so downstream code never sees it.
1046
+ effects: PxEffectsSchema.optional(),
1047
+ // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
1048
+ // string ref / array of refs / inline definition / mixed array; mirrors
1049
+ // `node.animate` values and what `processNode` resolves at runtime.
1050
+ animate: PxElementAnimationSchema.optional(),
1051
+ style: px.record(px.union([px.string(), px.number()])).optional()
1052
+ }, PxAttrValueSchema);
1053
+ var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBaseSchema._shape), {
1054
+ children: px.lazy(() => px.array(PxNodeSchema), []).optional()
1055
+ }), PxAttrValueSchema);
1056
+ var PxSvgNodeRootSchema = px.object({
1057
+ // `"100%"` and other SVG length strings are legal here — a number-only slot rejected
1058
+ // real documents (e.g. apple-store-look-14-main.json) at the root <svg>.
1059
+ width: px.union([px.number(), px.string()]).optional(),
1060
+ height: px.union([px.number(), px.string()]).optional(),
1061
+ viewBox: px.string().optional(),
1062
+ animator: PxAnimatorConfigSchema.optional()
1063
+ });
1064
+ var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps(__spreadValues(__spreadValues({}, PxNodeBaseSchema._shape), PxSvgNodeRootSchema._shape), {
1065
+ type: px.literal("svg"),
1066
+ // override string → literal to require 'svg'
1067
+ children: px.array(PxNodeSchema).optional()
1068
+ }), PxAttrValueSchema);
1069
+ var PxBezierPathSchema = implementsInterface()(px.object({
1070
+ v: px.array(px.array(px.number())),
1071
+ i: px.array(px.array(px.number())).optional(),
1072
+ o: px.array(px.array(px.number())).optional(),
1073
+ c: px.boolean().optional()
1074
+ }));
1075
+
1076
+ // src/triggers/PxVisibilityGate.ts
1077
+ var PLAY_WHEN_VISIBLE_DEFAULTS = {
1078
+ offScreen: PX_TRIGGER_DEFAULTS.offScreen,
1079
+ visibilityThreshold: PX_TRIGGER_DEFAULTS.visibilityThreshold,
1080
+ visibilityDebounce: PX_TRIGGER_DEFAULTS.visibilityDebounce
1081
+ };
1082
+ var THRESHOLD_STEPS = Array.from({ length: 21 }, (_, i) => i / 20);
1083
+ function effectiveRatio(entry) {
1084
+ var _a2, _b;
1085
+ const target = entry.boundingClientRect;
1086
+ const visible = entry.intersectionRect;
1087
+ if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
1088
+ const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
1089
+ const declared = (_b = (_a2 = entry.rootBounds) == null ? void 0 : _a2.height) != null ? _b : Infinity;
1090
+ const viewport = Math.min(live, declared);
1091
+ const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
1092
+ return denom > 0 ? visible.height / denom : entry.intersectionRatio;
1093
+ }
1094
+ function openGate(host) {
1095
+ return {
1096
+ requestStart: () => host.play(),
1097
+ dispose: () => {
1098
+ }
1099
+ };
1100
+ }
1101
+ function isGated(offScreen) {
1102
+ return offScreen !== PxOffScreenAction.continue;
1103
+ }
1104
+ function createVisibilityGate(root, trigger, host) {
1105
+ if (!isGated(trigger.offScreen)) return openGate(host);
1106
+ if (typeof IntersectionObserver === "undefined") return openGate(host);
1107
+ const threshold = trigger.visibilityThreshold;
1108
+ const debounceMs = trigger.visibilityDebounce;
1109
+ let isOpen = void 0;
1110
+ let startPending = false;
1111
+ let pausedByGate = false;
1112
+ let lastRatio = 0;
1113
+ let openTimer;
1114
+ const cancelPendingOpen = () => {
1115
+ if (openTimer !== void 0) {
1116
+ clearTimeout(openTimer);
1117
+ openTimer = void 0;
1118
+ }
1119
+ };
1120
+ const open = () => {
1121
+ openTimer = void 0;
1122
+ if (isOpen === true) return;
1123
+ isOpen = true;
1124
+ if (startPending || pausedByGate) {
1125
+ startPending = false;
1126
+ pausedByGate = false;
1127
+ host.play();
1128
+ }
1129
+ };
1130
+ const close = () => {
1131
+ cancelPendingOpen();
1132
+ if (isOpen === false) return;
1133
+ isOpen = false;
1134
+ if (!host.isPlaying()) return;
1135
+ if (trigger.offScreen === PxOffScreenAction.reset) {
1136
+ host.cancel();
1137
+ } else {
1138
+ host.pause();
1139
+ }
1140
+ pausedByGate = true;
1141
+ };
1142
+ const apply = (ratio) => {
1143
+ lastRatio = ratio;
1144
+ if (typeof document !== "undefined" && document.visibilityState === "hidden") {
1145
+ close();
1146
+ return;
1147
+ }
1148
+ if (ratio >= threshold) {
1149
+ if (isOpen === true || openTimer !== void 0) return;
1150
+ if (debounceMs > 0) openTimer = setTimeout(open, debounceMs);
1151
+ else open();
1152
+ return;
1153
+ }
1154
+ if (ratio <= 0) {
1155
+ close();
1156
+ return;
1157
+ }
1158
+ if (isOpen !== true) cancelPendingOpen();
1159
+ };
1160
+ const observer = new IntersectionObserver((entries) => {
1161
+ const last = entries[entries.length - 1];
1162
+ if (last) apply(last.isIntersecting ? effectiveRatio(last) : 0);
1163
+ }, { threshold: THRESHOLD_STEPS });
1164
+ observer.observe(root);
1165
+ const onVisibilityChange = () => {
1166
+ apply(lastRatio);
1167
+ };
1168
+ const hasDocument = typeof document !== "undefined";
1169
+ if (hasDocument) document.addEventListener("visibilitychange", onVisibilityChange);
1170
+ return {
1171
+ requestStart: (immediate) => {
1172
+ if (immediate || isOpen === true) {
1173
+ cancelPendingOpen();
1174
+ isOpen = true;
1175
+ startPending = false;
1176
+ pausedByGate = false;
1177
+ host.play();
1178
+ return;
1179
+ }
1180
+ startPending = true;
1181
+ },
1182
+ dispose: () => {
1183
+ cancelPendingOpen();
1184
+ observer.disconnect();
1185
+ if (hasDocument) document.removeEventListener("visibilitychange", onVisibilityChange);
1186
+ }
1187
+ };
1188
+ }
29
1189
  // Annotate the CommonJS export names for ESM import in node:
30
1190
  0 && (module.exports = {
31
- PX_ANIMATOR_DOC_KEY
1191
+ PLAY_WHEN_VISIBLE_DEFAULTS,
1192
+ PX_ANIMATOR_DOC_KEY,
1193
+ createVisibilityGate
32
1194
  });
33
1195
  //# sourceMappingURL=internal.cjs.map