@pixodesk/svg-animator-web 1.0.8 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2285 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2894 -155
- package/dist/index.d.ts +2894 -155
- package/dist/index.js +2249 -391
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.umd.js +2249 -391
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
7
7
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
9
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
+
var __pow = Math.pow;
|
|
10
11
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
12
|
var __spreadValues = (a, b) => {
|
|
12
13
|
for (var prop in b || (b = {}))
|
|
@@ -50,17 +51,48 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
50
51
|
var index_exports = {};
|
|
51
52
|
__export(index_exports, {
|
|
52
53
|
COLOUR_ATTR_NAMES: () => COLOUR_ATTR_NAMES,
|
|
54
|
+
PX_ANIMATOR_DATA_KEY: () => PX_ANIMATOR_DATA_KEY,
|
|
53
55
|
PX_ANIM_ATTR_NAME: () => PX_ANIM_ATTR_NAME,
|
|
54
56
|
PX_ANIM_SRC_ATTR_NAME: () => PX_ANIM_SRC_ATTR_NAME,
|
|
57
|
+
PX_TRANSFORM_PART_KEYS: () => PX_TRANSFORM_PART_KEYS,
|
|
58
|
+
PxAnimatedSvgDocumentSchema: () => PxAnimatedSvgDocumentSchema,
|
|
59
|
+
PxAnimationDefinitionSchema: () => PxAnimationDefinitionSchema,
|
|
60
|
+
PxAnimatorConfigSchema: () => PxAnimatorConfigSchema,
|
|
61
|
+
PxAttrValueSchema: () => PxAttrValueSchema,
|
|
62
|
+
PxBezierPathSchema: () => PxBezierPathSchema,
|
|
63
|
+
PxBindingSchema: () => PxBindingSchema,
|
|
64
|
+
PxDefsSchema: () => PxDefsSchema,
|
|
65
|
+
PxEasingOrRefSchema: () => PxEasingOrRefSchema,
|
|
66
|
+
PxEffectsSchema: () => PxEffectsSchema,
|
|
67
|
+
PxElementAnimationSchema: () => PxElementAnimationSchema,
|
|
68
|
+
PxKeyframeSchema: () => PxKeyframeSchema,
|
|
69
|
+
PxLoopSchema: () => PxLoopSchema,
|
|
70
|
+
PxMaskedByEffectSchema: () => PxMaskedByEffectSchema,
|
|
71
|
+
PxNodeBase: () => PxNodeBase,
|
|
72
|
+
PxNodeSchema: () => PxNodeSchema,
|
|
73
|
+
PxPropertyAnimationSchema: () => PxPropertyAnimationSchema,
|
|
74
|
+
PxRefEffectSchema: () => PxRefEffectSchema,
|
|
75
|
+
PxRepeaterEffectSchema: () => PxRepeaterEffectSchema,
|
|
76
|
+
PxRetimeEffectSchema: () => PxRetimeEffectSchema,
|
|
77
|
+
PxSvgNodeExtra: () => PxSvgNodeExtra,
|
|
78
|
+
PxTransformPartsSchema: () => PxTransformPartsSchema,
|
|
79
|
+
PxTransformValueSchema: () => PxTransformValueSchema,
|
|
80
|
+
PxTransformationEffectSchema: () => PxTransformationEffectSchema,
|
|
81
|
+
PxTriggerSchema: () => PxTriggerSchema,
|
|
82
|
+
PxTrimPathEffectSchema: () => PxTrimPathEffectSchema,
|
|
55
83
|
STYLE_ATTR_NAMES: () => STYLE_ATTR_NAMES,
|
|
56
84
|
TRANSFORM_FN_NAMES: () => TRANSFORM_FN_NAMES,
|
|
85
|
+
applyPlayerEffects: () => applyPlayerEffects,
|
|
57
86
|
calcAnimationValues: () => calcAnimationValues,
|
|
58
87
|
camelCaseToKebabWordIfNeeded: () => camelCaseToKebabWordIfNeeded,
|
|
88
|
+
collectSampleTimes: () => collectSampleTimes,
|
|
59
89
|
createAnimator: () => createAnimator,
|
|
60
90
|
createAnimatorImpl: () => createAnimatorImpl,
|
|
61
91
|
createBasicFrameLoopAnimator: () => createBasicFrameLoopAnimator,
|
|
62
92
|
createFrameLoopAnimator: () => createFrameLoopAnimator,
|
|
63
93
|
createWebApiAnimator: () => createWebApiAnimator,
|
|
94
|
+
describeSchema: () => describeSchema,
|
|
95
|
+
diffInEffect: () => diffInEffect,
|
|
64
96
|
generateNewIds: () => generateNewIds,
|
|
65
97
|
getAnimatorConfig: () => getAnimatorConfig,
|
|
66
98
|
getBindings: () => getBindings,
|
|
@@ -71,12 +103,1314 @@ __export(index_exports, {
|
|
|
71
103
|
isPxElementFileFormatDeep: () => isPxElementFileFormatDeep,
|
|
72
104
|
loadTagAnimators: () => loadTagAnimators,
|
|
73
105
|
normalizeDocument: () => getNormalisedBindings,
|
|
106
|
+
px: () => px,
|
|
74
107
|
renderNode: () => renderNode,
|
|
108
|
+
schemaKeys: () => schemaKeys,
|
|
75
109
|
setupAnimationTriggers: () => setupAnimationTriggers,
|
|
76
|
-
toRGBA: () => toRGBA
|
|
110
|
+
toRGBA: () => toRGBA,
|
|
111
|
+
validateNodeEffects: () => validateNodeEffects,
|
|
112
|
+
visualModelAt: () => visualModelAt
|
|
77
113
|
});
|
|
78
114
|
module.exports = __toCommonJS(index_exports);
|
|
79
115
|
|
|
116
|
+
// src/effects/transformParts.ts
|
|
117
|
+
function partsRecord(part, value, origin) {
|
|
118
|
+
const rec = {};
|
|
119
|
+
if (part === "translate") rec.translate = value;
|
|
120
|
+
else if (part === "rotate") rec.rotate = value;
|
|
121
|
+
else rec.scale = value;
|
|
122
|
+
if (origin && part !== "translate") rec.origin = origin;
|
|
123
|
+
return rec;
|
|
124
|
+
}
|
|
125
|
+
function readAnimatable(raw) {
|
|
126
|
+
if (raw === void 0) return { kind: "absent" };
|
|
127
|
+
if (Array.isArray(raw)) return { kind: "static", value: raw };
|
|
128
|
+
if (typeof raw === "object") {
|
|
129
|
+
const obj = raw;
|
|
130
|
+
if (obj.keyframes) {
|
|
131
|
+
return { kind: "animated", keyframes: obj.keyframes, autoOrient: obj.autoOrient };
|
|
132
|
+
}
|
|
133
|
+
if (obj.value !== void 0) return { kind: "static", value: obj.value };
|
|
134
|
+
}
|
|
135
|
+
return { kind: "static", value: raw };
|
|
136
|
+
}
|
|
137
|
+
function readStaticOrigin(raw, ctx) {
|
|
138
|
+
var _a;
|
|
139
|
+
const o = readAnimatable(raw);
|
|
140
|
+
if (o.kind === "absent") return void 0;
|
|
141
|
+
if (o.kind === "static") return o.value;
|
|
142
|
+
ctx.warnings.push("transformation.origin: animated origin approximated by its first keyframe");
|
|
143
|
+
return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
|
|
144
|
+
}
|
|
145
|
+
function keyframeWith(kf, value) {
|
|
146
|
+
const out = { value };
|
|
147
|
+
if (kf.time !== void 0) out.time = kf.time;
|
|
148
|
+
if (kf.easing !== void 0) out.easing = kf.easing;
|
|
149
|
+
if (kf.tangentOut !== void 0) out.tangentOut = kf.tangentOut;
|
|
150
|
+
if (kf.tangentIn !== void 0) out.tangentIn = kf.tangentIn;
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/effects/transformationEffect.ts
|
|
155
|
+
function applyTransformationEffect(node, fx, ctx) {
|
|
156
|
+
if (!fx) return node;
|
|
157
|
+
delete node.transform;
|
|
158
|
+
let n = node;
|
|
159
|
+
n = wrapTransformPart(n, "skew", fx.skew, ctx);
|
|
160
|
+
n = wrapOrigin(
|
|
161
|
+
n,
|
|
162
|
+
fx.origin,
|
|
163
|
+
/*invert=*/
|
|
164
|
+
true
|
|
165
|
+
);
|
|
166
|
+
n = wrapTransformPart(n, "scale", normalizeScale(fx.scale), ctx);
|
|
167
|
+
n = wrapTransformPart(n, "rotate", fx.rotate, ctx);
|
|
168
|
+
n = wrapOrigin(
|
|
169
|
+
n,
|
|
170
|
+
fx.origin,
|
|
171
|
+
/*invert=*/
|
|
172
|
+
false
|
|
173
|
+
);
|
|
174
|
+
if (translateHasAutoOrient(fx.translate)) {
|
|
175
|
+
n = wrapOrigin(
|
|
176
|
+
n,
|
|
177
|
+
fx.origin,
|
|
178
|
+
/*invert=*/
|
|
179
|
+
true
|
|
180
|
+
);
|
|
181
|
+
n = wrapTransformPart(n, "translate", fx.translate, ctx);
|
|
182
|
+
n = wrapOrigin(
|
|
183
|
+
n,
|
|
184
|
+
fx.origin,
|
|
185
|
+
/*invert=*/
|
|
186
|
+
false
|
|
187
|
+
);
|
|
188
|
+
} else {
|
|
189
|
+
n = wrapTransformPart(n, "translate", fx.translate, ctx);
|
|
190
|
+
}
|
|
191
|
+
return n;
|
|
192
|
+
}
|
|
193
|
+
function translateHasAutoOrient(translate) {
|
|
194
|
+
if (!translate || typeof translate !== "object") return false;
|
|
195
|
+
const obj = translate;
|
|
196
|
+
if (obj.autoOrient) return true;
|
|
197
|
+
return Array.isArray(obj.keyframes) && obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
|
|
198
|
+
}
|
|
199
|
+
function normalizeScale(raw) {
|
|
200
|
+
if (raw === void 0) return void 0;
|
|
201
|
+
if (Array.isArray(raw)) return [raw[0] / 100, raw[1] / 100];
|
|
202
|
+
return raw;
|
|
203
|
+
}
|
|
204
|
+
function wrapTransformPart(inner, part, raw, ctx) {
|
|
205
|
+
if (raw === void 0) return inner;
|
|
206
|
+
if (part === "skew") {
|
|
207
|
+
const skew = readAnimatable(raw);
|
|
208
|
+
if (skew.kind !== "static") {
|
|
209
|
+
ctx.warnings.push("transformation.skew: only static skew is supported");
|
|
210
|
+
return inner;
|
|
211
|
+
}
|
|
212
|
+
return { type: "g", transform: "skewX(" + skew.value[0] + ")skewY(" + skew.value[1] + ")", children: [inner] };
|
|
213
|
+
}
|
|
214
|
+
const v = readAnimatable(raw);
|
|
215
|
+
if (v.kind === "static") {
|
|
216
|
+
return { type: "g", transform: { value: partsRecord(part, v.value, void 0) }, children: [inner] };
|
|
217
|
+
}
|
|
218
|
+
if (v.kind === "animated") {
|
|
219
|
+
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
|
|
220
|
+
if (v.autoOrient) animTr.autoOrient = true;
|
|
221
|
+
return {
|
|
222
|
+
type: "g",
|
|
223
|
+
animate: { transform: animTr },
|
|
224
|
+
children: [inner]
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return inner;
|
|
228
|
+
}
|
|
229
|
+
function wrapOrigin(inner, raw, invert) {
|
|
230
|
+
if (raw === void 0) return inner;
|
|
231
|
+
const v = readAnimatable(raw);
|
|
232
|
+
const sign = (value) => invert ? [-value[0], -value[1]] : value;
|
|
233
|
+
if (v.kind === "absent") return inner;
|
|
234
|
+
if (v.kind === "static") {
|
|
235
|
+
if (v.value[0] === 0 && v.value[1] === 0) return inner;
|
|
236
|
+
return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
|
|
237
|
+
}
|
|
238
|
+
if (v.kind === "animated") {
|
|
239
|
+
return {
|
|
240
|
+
type: "g",
|
|
241
|
+
animate: { transform: { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) } },
|
|
242
|
+
children: [inner]
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return inner;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// src/effects/contentRefSplit.ts
|
|
249
|
+
function identifyContentRefTargets(node, ctx, allocator) {
|
|
250
|
+
var _a, _b, _c;
|
|
251
|
+
if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.ref) == null ? void 0 : _b.type) === "content") {
|
|
252
|
+
const baseId = node.effects.ref.baseId;
|
|
253
|
+
if (typeof baseId === "string" && baseId && !ctx.contentRefInnerIds.has(baseId)) {
|
|
254
|
+
ctx.contentRefInnerIds.set(baseId, allocator(baseId));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
(_c = node.children) == null ? void 0 : _c.forEach((c) => identifyContentRefTargets(c, ctx, allocator));
|
|
258
|
+
}
|
|
259
|
+
function splitForContentRef(node, transformation, originalId, innerId, ctx) {
|
|
260
|
+
const outerBody = liftBodyTranslate(node, transformation);
|
|
261
|
+
if (typeof node.id === "string") delete node.id;
|
|
262
|
+
const { outer: outerTr, inner: innerTr } = splitTransformationEffect(transformation);
|
|
263
|
+
let innerNode = node;
|
|
264
|
+
innerNode = applyTransformationEffect(innerNode, innerTr, ctx);
|
|
265
|
+
const innerWrapper = { type: "g", id: innerId, children: [innerNode] };
|
|
266
|
+
let outerWrapper = { type: "g", id: originalId, children: [innerWrapper] };
|
|
267
|
+
if (outerBody.transform !== void 0) outerWrapper.transform = outerBody.transform;
|
|
268
|
+
if (outerBody.animate !== void 0) outerWrapper.animate = outerBody.animate;
|
|
269
|
+
if (outerTr) {
|
|
270
|
+
delete outerWrapper.id;
|
|
271
|
+
outerWrapper = applyTransformationEffect(outerWrapper, outerTr, ctx);
|
|
272
|
+
outerWrapper.id = originalId;
|
|
273
|
+
}
|
|
274
|
+
return outerWrapper;
|
|
275
|
+
}
|
|
276
|
+
function liftBodyTranslate(node, transformation) {
|
|
277
|
+
var _a;
|
|
278
|
+
const out = {};
|
|
279
|
+
let didLiftAnimate = false;
|
|
280
|
+
const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
|
|
281
|
+
if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
|
|
282
|
+
const kfs = animTr.keyframes;
|
|
283
|
+
const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
|
|
284
|
+
if (hasTranslate) {
|
|
285
|
+
const outerHasOrigin = needsOriginOnOuter(animTr);
|
|
286
|
+
const outerKfs = kfs.map((kf) => {
|
|
287
|
+
const v = kf.value || {};
|
|
288
|
+
const newValue = {};
|
|
289
|
+
if (v.translate !== void 0) newValue.translate = v.translate;
|
|
290
|
+
if (outerHasOrigin && v.origin !== void 0) newValue.origin = v.origin;
|
|
291
|
+
const outerKf = { value: newValue };
|
|
292
|
+
if (kf.time !== void 0) outerKf.time = kf.time;
|
|
293
|
+
if (kf.easing !== void 0) outerKf.easing = kf.easing;
|
|
294
|
+
if (kf.tangentOut !== void 0) outerKf.tangentOut = kf.tangentOut;
|
|
295
|
+
if (kf.tangentIn !== void 0) outerKf.tangentIn = kf.tangentIn;
|
|
296
|
+
return outerKf;
|
|
297
|
+
});
|
|
298
|
+
const outerAnimTr = { keyframes: outerKfs };
|
|
299
|
+
if (animTr.autoOrient) outerAnimTr.autoOrient = true;
|
|
300
|
+
out.animate = { transform: outerAnimTr };
|
|
301
|
+
const innerHasPivotedPart = kfs.some((kf) => {
|
|
302
|
+
const v = kf.value || {};
|
|
303
|
+
return v.rotate !== void 0 || v.scale !== void 0;
|
|
304
|
+
});
|
|
305
|
+
const innerKfs = kfs.map((kf) => {
|
|
306
|
+
const v = kf.value || {};
|
|
307
|
+
const newValue = {};
|
|
308
|
+
if (v.rotate !== void 0) newValue.rotate = v.rotate;
|
|
309
|
+
if (v.scale !== void 0) newValue.scale = v.scale;
|
|
310
|
+
if (v.origin !== void 0 && (!outerHasOrigin || innerHasPivotedPart)) newValue.origin = v.origin;
|
|
311
|
+
const innerKf = { value: newValue };
|
|
312
|
+
if (kf.time !== void 0) innerKf.time = kf.time;
|
|
313
|
+
if (kf.easing !== void 0) innerKf.easing = kf.easing;
|
|
314
|
+
return innerKf;
|
|
315
|
+
});
|
|
316
|
+
const allInnerEmpty = innerKfs.every((kf) => Object.keys(kf.value).length === 0);
|
|
317
|
+
if (allInnerEmpty) {
|
|
318
|
+
delete node.animate.transform;
|
|
319
|
+
if (node.animate && Object.keys(node.animate).length === 0) delete node.animate;
|
|
320
|
+
} else {
|
|
321
|
+
node.animate.transform = { keyframes: innerKfs };
|
|
322
|
+
}
|
|
323
|
+
didLiftAnimate = true;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const transformationHasTranslate = (transformation == null ? void 0 : transformation.translate) !== void 0;
|
|
327
|
+
const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
|
|
328
|
+
if (typeof node.transform === "string") {
|
|
329
|
+
const split = splitTransformString(node.transform);
|
|
330
|
+
if (stripBodyTranslateOnly) {
|
|
331
|
+
if (split.translate !== void 0) {
|
|
332
|
+
if (split.rest) node.transform = split.rest;
|
|
333
|
+
else delete node.transform;
|
|
334
|
+
} else if (isPureTranslateBody(node.transform)) {
|
|
335
|
+
delete node.transform;
|
|
336
|
+
}
|
|
337
|
+
} else if (split.translate) {
|
|
338
|
+
out.transform = split.translate;
|
|
339
|
+
if (split.rest) node.transform = split.rest;
|
|
340
|
+
else delete node.transform;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return out;
|
|
344
|
+
}
|
|
345
|
+
function isPureTranslateBody(s) {
|
|
346
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
347
|
+
const ops = [];
|
|
348
|
+
let m;
|
|
349
|
+
while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
|
|
350
|
+
if (ops.length !== 1) return false;
|
|
351
|
+
if (ops[0].name === "translate") return true;
|
|
352
|
+
if (ops[0].name !== "matrix") return false;
|
|
353
|
+
const args = /matrix\(([^)]*)\)/.exec(ops[0].full);
|
|
354
|
+
if (!args) return false;
|
|
355
|
+
const nums = args[1].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
356
|
+
return nums.length >= 4 && nums[0] === 1 && nums[1] === 0 && nums[2] === 0 && nums[3] === 1;
|
|
357
|
+
}
|
|
358
|
+
function splitTransformString(s) {
|
|
359
|
+
const ops = [];
|
|
360
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
361
|
+
let m;
|
|
362
|
+
while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
|
|
363
|
+
if (!ops.length) return { rest: s || void 0 };
|
|
364
|
+
if (ops.every((o) => o.name === "translate")) {
|
|
365
|
+
return { translate: ops.map((o) => o.full).join("") };
|
|
366
|
+
}
|
|
367
|
+
const leading = ops[0];
|
|
368
|
+
const trailing = ops[ops.length - 1];
|
|
369
|
+
if (trailing.name === "translate" && leading.name === "translate") {
|
|
370
|
+
const trailingVec = parseTranslateArgs(trailing.full);
|
|
371
|
+
const leadingVec = parseTranslateArgs(leading.full);
|
|
372
|
+
const ox = -trailingVec[0];
|
|
373
|
+
const oy = -trailingVec[1];
|
|
374
|
+
const userTx = leadingVec[0] - ox;
|
|
375
|
+
const userTy = leadingVec[1] - oy;
|
|
376
|
+
if (userTx === 0 && userTy === 0) return { rest: s };
|
|
377
|
+
const middleAndTrailing = "translate(" + ox + "," + oy + ")" + ops.slice(1).map((o) => o.full).join("");
|
|
378
|
+
return { translate: "translate(" + userTx + "," + userTy + ")", rest: middleAndTrailing };
|
|
379
|
+
}
|
|
380
|
+
if (trailing.name === "translate") return { rest: s };
|
|
381
|
+
const lifted = [];
|
|
382
|
+
let i = 0;
|
|
383
|
+
while (i < ops.length && ops[i].name === "translate") {
|
|
384
|
+
lifted.push(ops[i].full);
|
|
385
|
+
i++;
|
|
386
|
+
}
|
|
387
|
+
if (!lifted.length) return { rest: s };
|
|
388
|
+
const rest = ops.slice(i).map((o) => o.full).join("");
|
|
389
|
+
return {
|
|
390
|
+
translate: lifted.join(""),
|
|
391
|
+
rest: rest || void 0
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function parseTranslateArgs(translateOp) {
|
|
395
|
+
const m = /translate\(([^)]*)\)/.exec(translateOp);
|
|
396
|
+
if (!m) return [0, 0];
|
|
397
|
+
const nums = m[1].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
398
|
+
return [nums[0] || 0, nums[1] || 0];
|
|
399
|
+
}
|
|
400
|
+
function splitTransformationEffect(fx) {
|
|
401
|
+
if (!fx) return {};
|
|
402
|
+
const originOnOuter = needsOriginOnOuter(fx.translate);
|
|
403
|
+
const innerHasPivotedPart = fx.rotate !== void 0 || fx.scale !== void 0;
|
|
404
|
+
const outer = {};
|
|
405
|
+
const inner = {};
|
|
406
|
+
if (fx.translate !== void 0) outer.translate = fx.translate;
|
|
407
|
+
if (originOnOuter && fx.origin !== void 0) outer.origin = fx.origin;
|
|
408
|
+
if (fx.rotate !== void 0) inner.rotate = fx.rotate;
|
|
409
|
+
if (fx.scale !== void 0) inner.scale = fx.scale;
|
|
410
|
+
if (fx.skew !== void 0) inner.skew = fx.skew;
|
|
411
|
+
if (fx.origin !== void 0 && (!originOnOuter || innerHasPivotedPart)) inner.origin = fx.origin;
|
|
412
|
+
return {
|
|
413
|
+
outer: Object.keys(outer).length ? outer : void 0,
|
|
414
|
+
inner: Object.keys(inner).length ? inner : void 0
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
function needsOriginOnOuter(translateAnim) {
|
|
418
|
+
if (!translateAnim || typeof translateAnim !== "object") return false;
|
|
419
|
+
const obj = translateAnim;
|
|
420
|
+
if (obj.autoOrient) return true;
|
|
421
|
+
if (Array.isArray(obj.keyframes)) {
|
|
422
|
+
return obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
|
|
423
|
+
}
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// src/effects/util.ts
|
|
428
|
+
function genId(ctx, prefix) {
|
|
429
|
+
return "_lw_" + prefix + "_" + ctx.nextId++;
|
|
430
|
+
}
|
|
431
|
+
function indexById(node, map) {
|
|
432
|
+
var _a;
|
|
433
|
+
if (typeof node.id === "string") map.set(node.id, node);
|
|
434
|
+
(_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
|
|
435
|
+
}
|
|
436
|
+
function spliceDefs(root, defs) {
|
|
437
|
+
if (!defs.length) return;
|
|
438
|
+
const existing = root.children || (root.children = []);
|
|
439
|
+
existing.unshift({ type: "defs", children: defs });
|
|
440
|
+
}
|
|
441
|
+
function clone(value) {
|
|
442
|
+
if (value === null || typeof value !== "object") return value;
|
|
443
|
+
if (Array.isArray(value)) return value.map(clone);
|
|
444
|
+
const out = {};
|
|
445
|
+
for (const k of Object.keys(value)) out[k] = clone(value[k]);
|
|
446
|
+
return out;
|
|
447
|
+
}
|
|
448
|
+
function regenerateIdsInClone(root, ctx) {
|
|
449
|
+
const oldToNew = /* @__PURE__ */ new Map();
|
|
450
|
+
const walkAssign = (n) => {
|
|
451
|
+
var _a;
|
|
452
|
+
if (typeof n.id === "string") {
|
|
453
|
+
const newId = genId(ctx, "retimed");
|
|
454
|
+
oldToNew.set(n.id, newId);
|
|
455
|
+
n.id = newId;
|
|
456
|
+
}
|
|
457
|
+
(_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
|
|
458
|
+
};
|
|
459
|
+
walkAssign(root);
|
|
460
|
+
const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
|
|
461
|
+
const newId = oldToNew.get(oldId);
|
|
462
|
+
return newId ? "url(#" + newId + ")" : m;
|
|
463
|
+
});
|
|
464
|
+
const walkRewrite = (n) => {
|
|
465
|
+
var _a;
|
|
466
|
+
if (typeof n.href === "string" && n.href.startsWith("#")) {
|
|
467
|
+
const newId = oldToNew.get(n.href.slice(1));
|
|
468
|
+
if (newId) n.href = "#" + newId;
|
|
469
|
+
}
|
|
470
|
+
for (const k of Object.keys(n)) {
|
|
471
|
+
if (k === "children" || k === "effects" || k === "meta" || k === "href" || k === "id") continue;
|
|
472
|
+
const v = n[k];
|
|
473
|
+
if (typeof v === "string" && v.indexOf("url(#") !== -1) n[k] = rewriteUrl(v);
|
|
474
|
+
}
|
|
475
|
+
(_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
|
|
476
|
+
};
|
|
477
|
+
walkRewrite(root);
|
|
478
|
+
return oldToNew;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// src/effects/maskedByEffect.ts
|
|
482
|
+
function applyMaskedByEffect(node, fx, transformation, ctx) {
|
|
483
|
+
if (!fx) return node;
|
|
484
|
+
if (!fx.href) {
|
|
485
|
+
ctx.errors.push("maskedBy.href missing \u2014 cannot build mask");
|
|
486
|
+
return node;
|
|
487
|
+
}
|
|
488
|
+
const maskId = genId(ctx, "mask");
|
|
489
|
+
let content = { type: "use", href: "#" + fx.href };
|
|
490
|
+
content = wrapInverseTransform(content, transformation, ctx);
|
|
491
|
+
const mask = { type: "mask", id: maskId, children: [content] };
|
|
492
|
+
if (fx.maskType) mask.maskType = fx.maskType;
|
|
493
|
+
if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
|
|
494
|
+
if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
|
|
495
|
+
ctx.defs.push(mask);
|
|
496
|
+
node.mask = "url(#" + maskId + ")";
|
|
497
|
+
return node;
|
|
498
|
+
}
|
|
499
|
+
function wrapInverseTransform(inner, fx, ctx) {
|
|
500
|
+
if (!fx) return inner;
|
|
501
|
+
const origin = readStaticOrigin(fx.origin, ctx);
|
|
502
|
+
let n = inner;
|
|
503
|
+
n = wrapInversePart(n, "translate", fx.translate, void 0, ctx);
|
|
504
|
+
n = wrapInversePart(n, "rotate", fx.rotate, origin, ctx);
|
|
505
|
+
n = wrapInversePart(n, "scale", fx.scale, origin, ctx);
|
|
506
|
+
return n;
|
|
507
|
+
}
|
|
508
|
+
function wrapInversePart(inner, part, raw, origin, ctx) {
|
|
509
|
+
if (raw === void 0) return inner;
|
|
510
|
+
const v = readAnimatable(raw);
|
|
511
|
+
if (v.kind === "static") {
|
|
512
|
+
return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
|
|
513
|
+
}
|
|
514
|
+
if (v.kind === "animated") {
|
|
515
|
+
return {
|
|
516
|
+
type: "g",
|
|
517
|
+
animate: { transform: { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin))) } },
|
|
518
|
+
children: [inner]
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
return inner;
|
|
522
|
+
}
|
|
523
|
+
function invertPartValue(part, value) {
|
|
524
|
+
if (part === "translate") return [-value[0], -value[1]];
|
|
525
|
+
if (part === "rotate") return -value;
|
|
526
|
+
return [1 / value[0], 1 / value[1]];
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// src/effects/refEffect.ts
|
|
530
|
+
var CONTENT_SUBREF = "content";
|
|
531
|
+
function applyRefAndTransformationEffect(node, ref, transformation, ctx) {
|
|
532
|
+
if (ref) {
|
|
533
|
+
const baseId = ref.baseId;
|
|
534
|
+
if (!baseId) {
|
|
535
|
+
ctx.errors.push("ref: missing baseId");
|
|
536
|
+
} else {
|
|
537
|
+
const targetId = ref.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
|
|
538
|
+
node.href = "#" + targetId;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return applyTransformationEffect(node, transformation, ctx);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// src/effects/repeaterEffect.ts
|
|
545
|
+
function applyRepeaterEffect(node, fx, ctx) {
|
|
546
|
+
var _a, _b;
|
|
547
|
+
if (!fx) return node;
|
|
548
|
+
const copies = (_a = fx.copies) != null ? _a : 1;
|
|
549
|
+
if (copies < 1) {
|
|
550
|
+
ctx.errors.push("repeater.copies invalid: " + fx.copies);
|
|
551
|
+
return node;
|
|
552
|
+
}
|
|
553
|
+
const sharedTransform = node.transform;
|
|
554
|
+
const sharedAnimTransform = (_b = node.animate) == null ? void 0 : _b.transform;
|
|
555
|
+
const base = clone(node);
|
|
556
|
+
delete base.transform;
|
|
557
|
+
if (base.animate) {
|
|
558
|
+
delete base.animate.transform;
|
|
559
|
+
if (Object.keys(base.animate).length === 0) delete base.animate;
|
|
560
|
+
}
|
|
561
|
+
const children = [base];
|
|
562
|
+
for (let i = 1; i < copies; i++) {
|
|
563
|
+
const copy = clone(base);
|
|
564
|
+
copy.transform = { value: perCopyParts(fx, i) };
|
|
565
|
+
children.push(copy);
|
|
566
|
+
}
|
|
567
|
+
const wrapper = { type: "g", children };
|
|
568
|
+
if (sharedTransform !== void 0) wrapper.transform = sharedTransform;
|
|
569
|
+
if (sharedAnimTransform !== void 0) wrapper.animate = { transform: sharedAnimTransform };
|
|
570
|
+
return wrapper;
|
|
571
|
+
}
|
|
572
|
+
function perCopyParts(fx, i) {
|
|
573
|
+
const parts = {};
|
|
574
|
+
if (fx.translate) parts.translate = [fx.translate[0] * i, fx.translate[1] * i];
|
|
575
|
+
if (fx.rotate !== void 0) parts.rotate = fx.rotate * i;
|
|
576
|
+
if (fx.scale) parts.scale = [__pow(fx.scale[0] / 100, i), __pow(fx.scale[1] / 100, i)];
|
|
577
|
+
if (fx.origin) parts.origin = [fx.origin[0] * i, fx.origin[1] * i];
|
|
578
|
+
return parts;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// src/effects/retimeEffect.ts
|
|
582
|
+
var RETIME_AS_SYMBOL = true;
|
|
583
|
+
function applyRetimeEffect(node, retime, ctx) {
|
|
584
|
+
var _a, _b, _c, _d;
|
|
585
|
+
if (!retime) return node;
|
|
586
|
+
const baseId = retime.baseId;
|
|
587
|
+
if (!baseId) {
|
|
588
|
+
ctx.errors.push("retime: missing baseId");
|
|
589
|
+
return node;
|
|
590
|
+
}
|
|
591
|
+
const target = ctx.idMap.get(baseId);
|
|
592
|
+
if (!target) {
|
|
593
|
+
ctx.warnings.push('retime: target "' + baseId + '" not found');
|
|
594
|
+
return node;
|
|
595
|
+
}
|
|
596
|
+
const start = (_a = retime.start) != null ? _a : 0;
|
|
597
|
+
const stretch = (_b = retime.stretch) != null ? _b : 1;
|
|
598
|
+
if (RETIME_AS_SYMBOL) {
|
|
599
|
+
const symbolClone = clone(target);
|
|
600
|
+
regenerateIdsInClone(symbolClone, ctx);
|
|
601
|
+
const cloneId = genId(ctx, "retime");
|
|
602
|
+
symbolClone.id = cloneId;
|
|
603
|
+
remapKeyframeTimes(symbolClone, start, stretch);
|
|
604
|
+
ctx.defs.push(symbolClone);
|
|
605
|
+
node.href = "#" + cloneId;
|
|
606
|
+
return node;
|
|
607
|
+
}
|
|
608
|
+
const sourceNodes = target.type === "symbol" ? target.children || [] : [target];
|
|
609
|
+
const content = sourceNodes.map((child) => {
|
|
610
|
+
const c = clone(child);
|
|
611
|
+
regenerateIdsInClone(c, ctx);
|
|
612
|
+
remapKeyframeTimes(c, start, stretch);
|
|
613
|
+
return c;
|
|
614
|
+
});
|
|
615
|
+
const g = __spreadProps(__spreadValues({}, node), { type: "g", children: content });
|
|
616
|
+
delete g.href;
|
|
617
|
+
const x = Number((_c = node.x) != null ? _c : 0), y = Number((_d = node.y) != null ? _d : 0);
|
|
618
|
+
if (x || y) {
|
|
619
|
+
const offset = "translate(" + x + "," + y + ")";
|
|
620
|
+
g.transform = typeof g.transform === "string" ? offset + g.transform : offset;
|
|
621
|
+
delete g.x;
|
|
622
|
+
delete g.y;
|
|
623
|
+
}
|
|
624
|
+
return g;
|
|
625
|
+
}
|
|
626
|
+
function remapKeyframeTimes(node, start, stretch) {
|
|
627
|
+
var _a;
|
|
628
|
+
const remap2 = (kfs) => {
|
|
629
|
+
for (const kf of kfs) if (typeof kf.time === "number") kf.time = start + kf.time * stretch;
|
|
630
|
+
};
|
|
631
|
+
if (node.transform && typeof node.transform === "object" && Array.isArray(node.transform.keyframes)) {
|
|
632
|
+
remap2(node.transform.keyframes);
|
|
633
|
+
}
|
|
634
|
+
if (node.animate && typeof node.animate === "object") {
|
|
635
|
+
for (const prop of Object.keys(node.animate)) {
|
|
636
|
+
const anim = node.animate[prop];
|
|
637
|
+
if (anim && Array.isArray(anim.keyframes)) remap2(anim.keyframes);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
(_a = node.children) == null ? void 0 : _a.forEach((child) => remapKeyframeTimes(child, start, stretch));
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// src/effects/trimPathEffect.ts
|
|
644
|
+
function applyTrimPathEffect(node, trimPath, isCombinedShape) {
|
|
645
|
+
var _a;
|
|
646
|
+
if (!trimPath && !isCombinedShape) return node;
|
|
647
|
+
const d = (_a = node.d) != null ? _a : rectToPathD(node);
|
|
648
|
+
if (d === void 0) return node;
|
|
649
|
+
const g = __spreadProps(__spreadValues({}, node), { type: "g" });
|
|
650
|
+
delete g.d;
|
|
651
|
+
const meta = g.meta = __spreadValues({}, g.meta || {});
|
|
652
|
+
const effects = meta.effects = __spreadValues({}, meta.effects || {});
|
|
653
|
+
if (trimPath) effects.trimPath = trimPath;
|
|
654
|
+
effects.isCombinedShape = true;
|
|
655
|
+
g.children = [{ type: "path", d }];
|
|
656
|
+
return g;
|
|
657
|
+
}
|
|
658
|
+
function rectToPathD(node) {
|
|
659
|
+
var _a, _b, _c, _d;
|
|
660
|
+
if (node.type !== "rect") return void 0;
|
|
661
|
+
const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
|
|
662
|
+
const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
|
|
663
|
+
return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// src/effects/PlayerEffectsUtil.ts
|
|
667
|
+
function applyPlayerEffects(root) {
|
|
668
|
+
const ctx = {
|
|
669
|
+
defs: [],
|
|
670
|
+
warnings: [],
|
|
671
|
+
errors: [],
|
|
672
|
+
idMap: /* @__PURE__ */ new Map(),
|
|
673
|
+
nextId: 0,
|
|
674
|
+
contentRefInnerIds: /* @__PURE__ */ new Map()
|
|
675
|
+
};
|
|
676
|
+
const working = clone(root);
|
|
677
|
+
indexById(working, ctx.idMap);
|
|
678
|
+
identifyContentRefTargets(working, ctx, () => genId(ctx, "inner"));
|
|
679
|
+
const afterPass1 = applyPlayerEffects_exceptRetime(working, ctx);
|
|
680
|
+
const out = applyPlayerEffects_retime(afterPass1, ctx);
|
|
681
|
+
spliceDefs(out, ctx.defs);
|
|
682
|
+
return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
|
|
683
|
+
}
|
|
684
|
+
function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
685
|
+
if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
|
|
686
|
+
const fx = node.effects;
|
|
687
|
+
const originalId = typeof node.id === "string" ? node.id : void 0;
|
|
688
|
+
const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
|
|
689
|
+
if (!fx && !innerIdForContentRef) return node;
|
|
690
|
+
const { transformation, repeater, maskedBy, trimPath, retime, ref } = fx != null ? fx : {};
|
|
691
|
+
const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
|
|
692
|
+
if (fx) delete node.effects;
|
|
693
|
+
let n = node;
|
|
694
|
+
n = applyTrimPathEffect(n, trimPath, isCombinedShape);
|
|
695
|
+
n = applyRepeaterEffect(n, repeater, ctx);
|
|
696
|
+
n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
|
|
697
|
+
if (innerIdForContentRef) {
|
|
698
|
+
n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
|
|
699
|
+
} else {
|
|
700
|
+
n = applyRefAndTransformationEffect(n, ref, transformation, ctx);
|
|
701
|
+
}
|
|
702
|
+
if (retime) node.effects = { retime };
|
|
703
|
+
if (originalId) ctx.idMap.set(originalId, n);
|
|
704
|
+
return n;
|
|
705
|
+
}
|
|
706
|
+
function applyPlayerEffects_retime(node, ctx) {
|
|
707
|
+
var _a;
|
|
708
|
+
if (node.children) node.children = node.children.map((child) => applyPlayerEffects_retime(child, ctx));
|
|
709
|
+
const retime = (_a = node.effects) == null ? void 0 : _a.retime;
|
|
710
|
+
if (!retime) return node;
|
|
711
|
+
delete node.effects;
|
|
712
|
+
return applyRetimeEffect(node, retime, ctx);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// src/PxSchema.ts
|
|
716
|
+
function pathStr(path) {
|
|
717
|
+
if (!path.length) return ".";
|
|
718
|
+
let result = "";
|
|
719
|
+
for (const seg of path) {
|
|
720
|
+
if (seg.startsWith("[")) result += seg;
|
|
721
|
+
else result += (result ? "." : "") + seg;
|
|
722
|
+
}
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
var Base = class {
|
|
726
|
+
_canSanitize(raw) {
|
|
727
|
+
return this.isValid(raw);
|
|
728
|
+
}
|
|
729
|
+
optional() {
|
|
730
|
+
return new Optional(this);
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
var Optional = class extends Base {
|
|
734
|
+
constructor(inner) {
|
|
735
|
+
super();
|
|
736
|
+
this.inner = inner;
|
|
737
|
+
this._default = void 0;
|
|
738
|
+
}
|
|
739
|
+
sanitize(raw) {
|
|
740
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
741
|
+
return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
|
|
742
|
+
}
|
|
743
|
+
isValid(raw, ctx, path) {
|
|
744
|
+
if (raw === void 0 || raw === null) return true;
|
|
745
|
+
return this.inner.isValid(raw, ctx, path);
|
|
746
|
+
}
|
|
747
|
+
_canSanitize(raw) {
|
|
748
|
+
return raw === void 0 || raw === null || this.inner._canSanitize(raw);
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
var Str = class extends Base {
|
|
752
|
+
constructor(_default = "") {
|
|
753
|
+
super();
|
|
754
|
+
this._default = _default;
|
|
755
|
+
}
|
|
756
|
+
sanitize(raw) {
|
|
757
|
+
return typeof raw === "string" ? raw : this._default;
|
|
758
|
+
}
|
|
759
|
+
isValid(raw, ctx, path) {
|
|
760
|
+
if (typeof raw === "string") return true;
|
|
761
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
|
|
762
|
+
return false;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
var Num = class extends Base {
|
|
766
|
+
constructor(_default = 0) {
|
|
767
|
+
super();
|
|
768
|
+
this._default = _default;
|
|
769
|
+
}
|
|
770
|
+
sanitize(raw) {
|
|
771
|
+
return typeof raw === "number" && isFinite(raw) ? raw : this._default;
|
|
772
|
+
}
|
|
773
|
+
isValid(raw, ctx, path) {
|
|
774
|
+
if (typeof raw === "number" && isFinite(raw)) return true;
|
|
775
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
|
|
776
|
+
return false;
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
var Bool = class extends Base {
|
|
780
|
+
constructor(_default = false) {
|
|
781
|
+
super();
|
|
782
|
+
this._default = _default;
|
|
783
|
+
}
|
|
784
|
+
sanitize(raw) {
|
|
785
|
+
return typeof raw === "boolean" ? raw : this._default;
|
|
786
|
+
}
|
|
787
|
+
isValid(raw, ctx, path) {
|
|
788
|
+
if (typeof raw === "boolean") return true;
|
|
789
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
var Literal = class extends Base {
|
|
794
|
+
constructor(value) {
|
|
795
|
+
super();
|
|
796
|
+
this.value = value;
|
|
797
|
+
this._default = value;
|
|
798
|
+
}
|
|
799
|
+
sanitize(raw) {
|
|
800
|
+
return raw === this.value ? this.value : this._default;
|
|
801
|
+
}
|
|
802
|
+
isValid(raw, ctx, path) {
|
|
803
|
+
if (raw === this.value) return true;
|
|
804
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected " + JSON.stringify(this.value) + ", got " + JSON.stringify(raw));
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
var Enum = class extends Base {
|
|
809
|
+
constructor(values, defaultVal) {
|
|
810
|
+
super();
|
|
811
|
+
this.values = values;
|
|
812
|
+
this._default = defaultVal != null ? defaultVal : values[0];
|
|
813
|
+
}
|
|
814
|
+
sanitize(raw) {
|
|
815
|
+
return this.values.includes(raw) ? raw : this._default;
|
|
816
|
+
}
|
|
817
|
+
isValid(raw, ctx, path) {
|
|
818
|
+
if (this.values.includes(raw)) return true;
|
|
819
|
+
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));
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
var Union = class extends Base {
|
|
824
|
+
constructor(schemas, defaultVal) {
|
|
825
|
+
super();
|
|
826
|
+
this.schemas = schemas;
|
|
827
|
+
this._default = defaultVal != null ? defaultVal : schemas[0]._default;
|
|
828
|
+
}
|
|
829
|
+
sanitize(raw) {
|
|
830
|
+
for (const s of this.schemas) {
|
|
831
|
+
if (s.isValid(raw)) return s.sanitize(raw);
|
|
832
|
+
}
|
|
833
|
+
return this._default;
|
|
834
|
+
}
|
|
835
|
+
isValid(raw, ctx, path) {
|
|
836
|
+
var _a;
|
|
837
|
+
if (this.schemas.some((s) => s.isValid(raw))) return true;
|
|
838
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no union member matched for value " + ((_a = JSON.stringify(raw)) != null ? _a : "").slice(0, 60));
|
|
839
|
+
return false;
|
|
840
|
+
}
|
|
841
|
+
_canSanitize(raw) {
|
|
842
|
+
return this.schemas.some((s) => s._canSanitize(raw));
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
var DiscriminatedUnion = class extends Base {
|
|
846
|
+
constructor(_key, _schemas, defaultVal) {
|
|
847
|
+
super();
|
|
848
|
+
this._key = _key;
|
|
849
|
+
this._schemas = _schemas;
|
|
850
|
+
this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
|
|
851
|
+
this._map = /* @__PURE__ */ new Map();
|
|
852
|
+
for (const s of _schemas) {
|
|
853
|
+
const keySchema = s._shape[_key];
|
|
854
|
+
if (keySchema) this._map.set(keySchema._default, s);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
_findSchema(raw) {
|
|
858
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
859
|
+
const val = raw[this._key];
|
|
860
|
+
if (val === void 0 || val === null) return void 0;
|
|
861
|
+
return this._map.get(val);
|
|
862
|
+
}
|
|
863
|
+
sanitize(raw) {
|
|
864
|
+
var _a;
|
|
865
|
+
return ((_a = this._findSchema(raw)) != null ? _a : this._schemas[0]).sanitize(raw);
|
|
866
|
+
}
|
|
867
|
+
isValid(raw, ctx, path) {
|
|
868
|
+
const schema = this._findSchema(raw);
|
|
869
|
+
if (!schema) {
|
|
870
|
+
const val = raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw[this._key] : void 0;
|
|
871
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no discriminated union member matched " + this._key + "=" + JSON.stringify(val));
|
|
872
|
+
return false;
|
|
873
|
+
}
|
|
874
|
+
return schema.isValid(raw, ctx, path);
|
|
875
|
+
}
|
|
876
|
+
_canSanitize(raw) {
|
|
877
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
878
|
+
const schema = this._findSchema(raw);
|
|
879
|
+
return schema ? schema._canSanitize(raw) : this._schemas[0]._canSanitize(raw);
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
var Obj = class extends Base {
|
|
883
|
+
constructor(_shape) {
|
|
884
|
+
super();
|
|
885
|
+
this._shape = _shape;
|
|
886
|
+
const d = {};
|
|
887
|
+
for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
|
|
888
|
+
this._default = d;
|
|
889
|
+
}
|
|
890
|
+
sanitize(raw) {
|
|
891
|
+
const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
892
|
+
const out = {};
|
|
893
|
+
for (const key of Object.keys(this._shape)) {
|
|
894
|
+
out[key] = this._shape[key].sanitize(src[key]);
|
|
895
|
+
}
|
|
896
|
+
return out;
|
|
897
|
+
}
|
|
898
|
+
isValid(raw, ctx, path) {
|
|
899
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
900
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object, got " + (Array.isArray(raw) ? "array" : typeof raw));
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
903
|
+
const obj = raw;
|
|
904
|
+
const p = path != null ? path : [];
|
|
905
|
+
let ok = true;
|
|
906
|
+
for (const key of Object.keys(this._shape)) {
|
|
907
|
+
p.push(key);
|
|
908
|
+
if (!this._shape[key].isValid(obj[key], ctx, p)) ok = false;
|
|
909
|
+
p.pop();
|
|
910
|
+
}
|
|
911
|
+
if (ctx == null ? void 0 : ctx.strict) {
|
|
912
|
+
for (const key of Object.keys(obj)) {
|
|
913
|
+
if (key in this._shape) continue;
|
|
914
|
+
p.push(key);
|
|
915
|
+
ctx.errors.push(pathStr(p) + ": unexpected extra key");
|
|
916
|
+
p.pop();
|
|
917
|
+
ok = false;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
return ok;
|
|
921
|
+
}
|
|
922
|
+
_canSanitize(raw) {
|
|
923
|
+
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
var OpenObj = class extends Base {
|
|
927
|
+
constructor(_shape, _openSchema) {
|
|
928
|
+
super();
|
|
929
|
+
this._shape = _shape;
|
|
930
|
+
this._openSchema = _openSchema;
|
|
931
|
+
const d = {};
|
|
932
|
+
for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
|
|
933
|
+
this._default = d;
|
|
934
|
+
}
|
|
935
|
+
sanitize(raw) {
|
|
936
|
+
const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
937
|
+
const out = __spreadValues({}, src);
|
|
938
|
+
for (const key of Object.keys(this._shape)) {
|
|
939
|
+
out[key] = this._shape[key].sanitize(src[key]);
|
|
940
|
+
}
|
|
941
|
+
if (this._openSchema) {
|
|
942
|
+
for (const key of Object.keys(src)) {
|
|
943
|
+
if (!(key in this._shape)) out[key] = this._openSchema.sanitize(src[key]);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return out;
|
|
947
|
+
}
|
|
948
|
+
isValid(raw, ctx, path) {
|
|
949
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
950
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object, got " + (Array.isArray(raw) ? "array" : typeof raw));
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
const obj = raw;
|
|
954
|
+
const p = path != null ? path : [];
|
|
955
|
+
let ok = true;
|
|
956
|
+
for (const key of Object.keys(this._shape)) {
|
|
957
|
+
p.push(key);
|
|
958
|
+
if (!this._shape[key].isValid(obj[key], ctx, p)) ok = false;
|
|
959
|
+
p.pop();
|
|
960
|
+
}
|
|
961
|
+
if (this._openSchema) {
|
|
962
|
+
for (const key of Object.keys(obj)) {
|
|
963
|
+
if (key in this._shape) continue;
|
|
964
|
+
p.push(key);
|
|
965
|
+
if (!this._openSchema.isValid(obj[key], ctx, p)) ok = false;
|
|
966
|
+
p.pop();
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
return ok;
|
|
970
|
+
}
|
|
971
|
+
_canSanitize(raw) {
|
|
972
|
+
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
var Arr = class extends Base {
|
|
976
|
+
constructor(item) {
|
|
977
|
+
super();
|
|
978
|
+
this.item = item;
|
|
979
|
+
this._default = [];
|
|
980
|
+
}
|
|
981
|
+
sanitize(raw) {
|
|
982
|
+
if (!Array.isArray(raw)) return [];
|
|
983
|
+
const out = [];
|
|
984
|
+
for (const el of raw) {
|
|
985
|
+
if (this.item._canSanitize(el)) out.push(this.item.sanitize(el));
|
|
986
|
+
}
|
|
987
|
+
return out;
|
|
988
|
+
}
|
|
989
|
+
isValid(raw, ctx, path) {
|
|
990
|
+
if (!Array.isArray(raw)) {
|
|
991
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected array, got " + typeof raw);
|
|
992
|
+
return false;
|
|
993
|
+
}
|
|
994
|
+
const p = path != null ? path : [];
|
|
995
|
+
let ok = true;
|
|
996
|
+
for (let i = 0; i < raw.length; i++) {
|
|
997
|
+
p.push("[" + i + "]");
|
|
998
|
+
if (!this.item.isValid(raw[i], ctx, p)) ok = false;
|
|
999
|
+
p.pop();
|
|
1000
|
+
}
|
|
1001
|
+
return ok;
|
|
1002
|
+
}
|
|
1003
|
+
_canSanitize(raw) {
|
|
1004
|
+
return Array.isArray(raw);
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
var Rec = class extends Base {
|
|
1008
|
+
constructor(value) {
|
|
1009
|
+
super();
|
|
1010
|
+
this.value = value;
|
|
1011
|
+
this._default = {};
|
|
1012
|
+
}
|
|
1013
|
+
sanitize(raw) {
|
|
1014
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
1015
|
+
const out = {};
|
|
1016
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
1017
|
+
if (this.value._canSanitize(v)) out[k] = this.value.sanitize(v);
|
|
1018
|
+
}
|
|
1019
|
+
return out;
|
|
1020
|
+
}
|
|
1021
|
+
isValid(raw, ctx, path) {
|
|
1022
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1023
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object/record, got " + (Array.isArray(raw) ? "array" : typeof raw));
|
|
1024
|
+
return false;
|
|
1025
|
+
}
|
|
1026
|
+
const p = path != null ? path : [];
|
|
1027
|
+
let ok = true;
|
|
1028
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
1029
|
+
p.push(k);
|
|
1030
|
+
if (!this.value.isValid(v, ctx, p)) ok = false;
|
|
1031
|
+
p.pop();
|
|
1032
|
+
}
|
|
1033
|
+
return ok;
|
|
1034
|
+
}
|
|
1035
|
+
_canSanitize(raw) {
|
|
1036
|
+
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
var Any = class extends Base {
|
|
1040
|
+
constructor() {
|
|
1041
|
+
super(...arguments);
|
|
1042
|
+
this._default = void 0;
|
|
1043
|
+
}
|
|
1044
|
+
sanitize(raw) {
|
|
1045
|
+
return raw;
|
|
1046
|
+
}
|
|
1047
|
+
isValid(_raw, _ctx, _path) {
|
|
1048
|
+
return true;
|
|
1049
|
+
}
|
|
1050
|
+
_canSanitize(_raw) {
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
var Lazy = class extends Base {
|
|
1055
|
+
constructor(fn, _default) {
|
|
1056
|
+
super();
|
|
1057
|
+
this.fn = fn;
|
|
1058
|
+
this._default = _default;
|
|
1059
|
+
this.resolved = null;
|
|
1060
|
+
}
|
|
1061
|
+
get schema() {
|
|
1062
|
+
var _a;
|
|
1063
|
+
return (_a = this.resolved) != null ? _a : this.resolved = this.fn();
|
|
1064
|
+
}
|
|
1065
|
+
sanitize(raw) {
|
|
1066
|
+
return this.schema.sanitize(raw);
|
|
1067
|
+
}
|
|
1068
|
+
isValid(raw, ctx, path) {
|
|
1069
|
+
return this.schema.isValid(raw, ctx, path);
|
|
1070
|
+
}
|
|
1071
|
+
_canSanitize(raw) {
|
|
1072
|
+
return this.schema._canSanitize(raw);
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
var Tuple = class extends Base {
|
|
1076
|
+
constructor(schemas) {
|
|
1077
|
+
super();
|
|
1078
|
+
this.schemas = schemas;
|
|
1079
|
+
this._default = schemas.map((s) => s._default);
|
|
1080
|
+
}
|
|
1081
|
+
sanitize(raw) {
|
|
1082
|
+
if (!Array.isArray(raw) || raw.length !== this.schemas.length) return this._default;
|
|
1083
|
+
return this.schemas.map((s, i) => s.sanitize(raw[i]));
|
|
1084
|
+
}
|
|
1085
|
+
isValid(raw, ctx, path) {
|
|
1086
|
+
if (!Array.isArray(raw) || raw.length !== this.schemas.length) {
|
|
1087
|
+
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));
|
|
1088
|
+
return false;
|
|
1089
|
+
}
|
|
1090
|
+
const p = path != null ? path : [];
|
|
1091
|
+
let ok = true;
|
|
1092
|
+
for (let i = 0; i < this.schemas.length; i++) {
|
|
1093
|
+
p.push("[" + i + "]");
|
|
1094
|
+
if (!this.schemas[i].isValid(raw[i], ctx, p)) ok = false;
|
|
1095
|
+
p.pop();
|
|
1096
|
+
}
|
|
1097
|
+
return ok;
|
|
1098
|
+
}
|
|
1099
|
+
// Require exact length so wrong-length arrays are dropped rather than repaired to default.
|
|
1100
|
+
_canSanitize(raw) {
|
|
1101
|
+
return Array.isArray(raw) && raw.length === this.schemas.length;
|
|
1102
|
+
}
|
|
1103
|
+
};
|
|
1104
|
+
function implementsInterface() {
|
|
1105
|
+
return (schema) => schema;
|
|
1106
|
+
}
|
|
1107
|
+
function schemaKeys(schema) {
|
|
1108
|
+
return Object.fromEntries(
|
|
1109
|
+
Object.keys(schema["_shape"]).map((k) => [k, k])
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
function describeSchema(schema) {
|
|
1113
|
+
var _a;
|
|
1114
|
+
const s = schema;
|
|
1115
|
+
if ("_shape" in s) return { kind: "shape", shape: s._shape };
|
|
1116
|
+
if ("item" in s) return { kind: "array", item: s.item };
|
|
1117
|
+
if ("inner" in s) return { kind: "optional", inner: s.inner };
|
|
1118
|
+
if ("fn" in s) return { kind: "lazy", resolved: (_a = s.resolved) != null ? _a : s.fn() };
|
|
1119
|
+
return { kind: "leaf" };
|
|
1120
|
+
}
|
|
1121
|
+
var px = {
|
|
1122
|
+
/** Matches a string. Default: '' or provided value. */
|
|
1123
|
+
string: (defaultVal = "") => new Str(defaultVal),
|
|
1124
|
+
/** Matches a finite number. Default: 0 or provided value. */
|
|
1125
|
+
number: (defaultVal = 0) => new Num(defaultVal),
|
|
1126
|
+
/** Matches a boolean. Default: false or provided value. */
|
|
1127
|
+
boolean: (defaultVal = false) => new Bool(defaultVal),
|
|
1128
|
+
/** Matches one exact primitive value; its default is the value itself. */
|
|
1129
|
+
literal: (value) => new Literal(value),
|
|
1130
|
+
/** Matches one of a fixed set of string/number values. Default: first value. */
|
|
1131
|
+
enum: (values, defaultVal) => new Enum(values, defaultVal),
|
|
1132
|
+
/**
|
|
1133
|
+
* Returns the first schema whose isValid passes.
|
|
1134
|
+
* TypeScript infers the union of all member types automatically.
|
|
1135
|
+
*/
|
|
1136
|
+
union: (schemas, defaultVal) => new Union(schemas, defaultVal),
|
|
1137
|
+
/**
|
|
1138
|
+
* Discriminated union — reads `raw[key]`, finds the member schema whose
|
|
1139
|
+
* literal at `key` matches, then delegates sanitize/isValid to that member.
|
|
1140
|
+
* Each member must be an object schema with a `px.literal(...)` at `key`.
|
|
1141
|
+
* TypeScript infers the union of all member types automatically.
|
|
1142
|
+
*/
|
|
1143
|
+
discriminatedUnion: (key, schemas) => new DiscriminatedUnion(key, schemas),
|
|
1144
|
+
/** Typed object — unknown keys are stripped. Required fields fall back to their default. */
|
|
1145
|
+
object: (shape) => new Obj(shape),
|
|
1146
|
+
/**
|
|
1147
|
+
* Open object — validates known keys; passes unknown keys through as-is,
|
|
1148
|
+
* or validates/sanitizes them against `openSchema` when provided.
|
|
1149
|
+
*/
|
|
1150
|
+
openObject: (shape, openSchema) => new OpenObj(shape, openSchema),
|
|
1151
|
+
/**
|
|
1152
|
+
* Creates a new closed object schema by merging a base schema's shape with additional fields.
|
|
1153
|
+
* The base can be the result of px.object() or px.openObject() — anything with a _shape property.
|
|
1154
|
+
*
|
|
1155
|
+
* @example
|
|
1156
|
+
* const PxSvgNodeSchema = px.extendedObject(PxNodeBase, { width: px.number().optional() });
|
|
1157
|
+
*/
|
|
1158
|
+
extendedObject: (base, extra) => new Obj(__spreadValues(__spreadValues({}, base._shape), extra)),
|
|
1159
|
+
/** Array whose unrecoverable items are filtered out. Default: []. */
|
|
1160
|
+
array: (item) => new Arr(item),
|
|
1161
|
+
/** String-keyed record whose unrecoverable values are dropped. Default: {}. */
|
|
1162
|
+
record: (value) => new Rec(value),
|
|
1163
|
+
/** Passes anything through unchanged — always valid. */
|
|
1164
|
+
any: () => new Any(),
|
|
1165
|
+
/** Fixed-length tuple — validates element count and each position individually. */
|
|
1166
|
+
tuple: (schemas) => new Tuple(schemas),
|
|
1167
|
+
/** Defers schema creation — required for recursive types. Must supply a default value. */
|
|
1168
|
+
lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
|
|
1169
|
+
};
|
|
1170
|
+
|
|
1171
|
+
// src/PxAnimatorTypes.ts
|
|
1172
|
+
var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
|
|
1173
|
+
var PX_ANIM_ATTR_NAME = "_px_animator";
|
|
1174
|
+
var TEXT_ATTR = "text";
|
|
1175
|
+
var TEXT_CONTENT_ATTR = "textContent";
|
|
1176
|
+
var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
|
|
1177
|
+
"type",
|
|
1178
|
+
"children",
|
|
1179
|
+
"animator",
|
|
1180
|
+
"meta",
|
|
1181
|
+
"animate",
|
|
1182
|
+
TEXT_ATTR,
|
|
1183
|
+
TEXT_CONTENT_ATTR
|
|
1184
|
+
]);
|
|
1185
|
+
var PxEasingOrRefSchema = px.union([
|
|
1186
|
+
px.string(),
|
|
1187
|
+
px.tuple([px.number(), px.number(), px.number(), px.number()])
|
|
1188
|
+
]);
|
|
1189
|
+
var PxKeyframeValueSchema = implementsInterface()(px.union([
|
|
1190
|
+
px.string(),
|
|
1191
|
+
// e.g. for colors
|
|
1192
|
+
px.number(),
|
|
1193
|
+
px.array(px.number()),
|
|
1194
|
+
px.lazy(() => PxTransformPartsSchema, {}),
|
|
1195
|
+
px.object({ path: px.string() }),
|
|
1196
|
+
px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] })
|
|
1197
|
+
]));
|
|
1198
|
+
var PxKeyframeSchema = implementsInterface()(px.object({
|
|
1199
|
+
time: px.number().optional(),
|
|
1200
|
+
t: px.number().optional(),
|
|
1201
|
+
value: px.any().optional(),
|
|
1202
|
+
v: px.any().optional(),
|
|
1203
|
+
easing: PxEasingOrRefSchema.optional(),
|
|
1204
|
+
e: PxEasingOrRefSchema.optional(),
|
|
1205
|
+
tangentOut: px.tuple([px.number(), px.number()]).optional(),
|
|
1206
|
+
to: px.tuple([px.number(), px.number()]).optional(),
|
|
1207
|
+
// short alias
|
|
1208
|
+
tangentIn: px.tuple([px.number(), px.number()]).optional(),
|
|
1209
|
+
ti: px.tuple([px.number(), px.number()]).optional(),
|
|
1210
|
+
// short alias
|
|
1211
|
+
selected: px.boolean().optional()
|
|
1212
|
+
// editor-side UI state (Player ignores it)
|
|
1213
|
+
}));
|
|
1214
|
+
var PxLoopSchema = implementsInterface()(px.object({
|
|
1215
|
+
segmentCount: px.number().optional(),
|
|
1216
|
+
before: px.boolean().optional(),
|
|
1217
|
+
alternate: px.boolean().optional()
|
|
1218
|
+
}));
|
|
1219
|
+
var PxPropertyAnimationSchema = implementsInterface()(px.object({
|
|
1220
|
+
keyframes: px.array(PxKeyframeSchema).optional(),
|
|
1221
|
+
kfs: px.array(PxKeyframeSchema).optional(),
|
|
1222
|
+
loop: px.union([PxLoopSchema, px.boolean()]).optional(),
|
|
1223
|
+
autoOrient: px.boolean().optional()
|
|
1224
|
+
}));
|
|
1225
|
+
var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
|
|
1226
|
+
var PxTransformPartsSchema = implementsInterface()(px.object({
|
|
1227
|
+
translate: px.tuple([px.number(), px.number()]).optional(),
|
|
1228
|
+
rotate: px.number().optional(),
|
|
1229
|
+
scale: px.tuple([px.number(), px.number()]).optional(),
|
|
1230
|
+
origin: px.tuple([px.number(), px.number()]).optional()
|
|
1231
|
+
}));
|
|
1232
|
+
var PxTransformValueSchema = px.union([
|
|
1233
|
+
px.string(),
|
|
1234
|
+
px.object({ value: PxTransformPartsSchema }),
|
|
1235
|
+
PxPropertyAnimationSchema
|
|
1236
|
+
]);
|
|
1237
|
+
var PxAnimationDefinitionSchema = implementsInterface()(
|
|
1238
|
+
px.record(PxPropertyAnimationSchema)
|
|
1239
|
+
);
|
|
1240
|
+
var PxElementAnimationSchema = implementsInterface()(px.union([
|
|
1241
|
+
px.string(),
|
|
1242
|
+
px.array(px.union([px.string(), PxAnimationDefinitionSchema])),
|
|
1243
|
+
PxAnimationDefinitionSchema
|
|
1244
|
+
]));
|
|
1245
|
+
var PxTriggerSchema = implementsInterface()(px.object({
|
|
1246
|
+
startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
|
|
1247
|
+
outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
|
|
1248
|
+
scrollIntoViewThreshold: px.number().optional()
|
|
1249
|
+
}));
|
|
1250
|
+
var PxDefsSchema = implementsInterface()(px.object({
|
|
1251
|
+
easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
|
|
1252
|
+
animations: px.record(PxAnimationDefinitionSchema).optional(),
|
|
1253
|
+
styles: px.record(px.any()).optional()
|
|
1254
|
+
}));
|
|
1255
|
+
var PxAnimatorConfigSchema = implementsInterface()(px.object({
|
|
1256
|
+
mode: px.enum(["auto", "webapi", "frames"]).optional(),
|
|
1257
|
+
duration: px.number().optional(),
|
|
1258
|
+
delay: px.number().optional(),
|
|
1259
|
+
iterations: px.union([px.number(), px.literal("infinite")]).optional(),
|
|
1260
|
+
fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
|
|
1261
|
+
direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
|
|
1262
|
+
frameRate: px.number().optional(),
|
|
1263
|
+
trigger: PxTriggerSchema.optional(),
|
|
1264
|
+
definitions: PxDefsSchema.optional(),
|
|
1265
|
+
animate: px.record(PxElementAnimationSchema).optional(),
|
|
1266
|
+
debug: px.boolean().optional(),
|
|
1267
|
+
debugInstName: px.string().optional()
|
|
1268
|
+
}));
|
|
1269
|
+
var PxBindingSchema = implementsInterface()(px.object({
|
|
1270
|
+
id: px.string(),
|
|
1271
|
+
animate: PxElementAnimationSchema
|
|
1272
|
+
}));
|
|
1273
|
+
var PxAttrValueSchema = px.union([
|
|
1274
|
+
px.string(),
|
|
1275
|
+
px.number(),
|
|
1276
|
+
px.object({ value: px.any() }),
|
|
1277
|
+
PxPropertyAnimationSchema
|
|
1278
|
+
]);
|
|
1279
|
+
var PxAnimatableNumberSchema = px.union([
|
|
1280
|
+
px.number(),
|
|
1281
|
+
px.object({ value: px.number() }),
|
|
1282
|
+
px.object({
|
|
1283
|
+
keyframes: px.array(PxKeyframeSchema),
|
|
1284
|
+
autoOrient: px.boolean().optional()
|
|
1285
|
+
})
|
|
1286
|
+
]);
|
|
1287
|
+
var PxAnimatableVec2Schema = px.union([
|
|
1288
|
+
px.tuple([px.number(), px.number()]),
|
|
1289
|
+
px.object({ value: px.tuple([px.number(), px.number()]) }),
|
|
1290
|
+
px.object({
|
|
1291
|
+
keyframes: px.array(PxKeyframeSchema),
|
|
1292
|
+
autoOrient: px.boolean().optional()
|
|
1293
|
+
})
|
|
1294
|
+
]);
|
|
1295
|
+
var PxTransformationEffectSchema = px.object({
|
|
1296
|
+
translate: PxAnimatableVec2Schema.optional(),
|
|
1297
|
+
rotate: PxAnimatableNumberSchema.optional(),
|
|
1298
|
+
scale: PxAnimatableVec2Schema.optional(),
|
|
1299
|
+
skew: PxAnimatableVec2Schema.optional(),
|
|
1300
|
+
origin: PxAnimatableVec2Schema.optional()
|
|
1301
|
+
});
|
|
1302
|
+
var PxRepeaterEffectSchema = px.object({
|
|
1303
|
+
copies: px.number().optional(),
|
|
1304
|
+
translate: px.tuple([px.number(), px.number()]).optional(),
|
|
1305
|
+
rotate: px.number().optional(),
|
|
1306
|
+
scale: px.tuple([px.number(), px.number()]).optional(),
|
|
1307
|
+
// per-copy scale, PERCENT (85 → 0.85)
|
|
1308
|
+
origin: px.tuple([px.number(), px.number()]).optional()
|
|
1309
|
+
});
|
|
1310
|
+
var PxMaskedByEffectSchema = px.object({
|
|
1311
|
+
href: px.string().optional(),
|
|
1312
|
+
maskType: px.string().optional(),
|
|
1313
|
+
maskUnits: px.string().optional(),
|
|
1314
|
+
maskContentUnits: px.string().optional()
|
|
1315
|
+
});
|
|
1316
|
+
var PxTrimPathEffectSchema = px.any();
|
|
1317
|
+
var PxRetimeEffectSchema = px.object({
|
|
1318
|
+
baseId: px.string().optional(),
|
|
1319
|
+
start: px.number().optional(),
|
|
1320
|
+
stretch: px.number().optional(),
|
|
1321
|
+
timeCrop: px.tuple([px.number(), px.number()]).optional()
|
|
1322
|
+
});
|
|
1323
|
+
var PxRefEffectSchema = px.object({
|
|
1324
|
+
baseId: px.string().optional(),
|
|
1325
|
+
type: px.string().optional()
|
|
1326
|
+
});
|
|
1327
|
+
var PxEffectsSchema = px.object({
|
|
1328
|
+
transformation: PxTransformationEffectSchema.optional(),
|
|
1329
|
+
repeater: PxRepeaterEffectSchema.optional(),
|
|
1330
|
+
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
1331
|
+
trimPath: PxTrimPathEffectSchema.optional(),
|
|
1332
|
+
retime: PxRetimeEffectSchema.optional(),
|
|
1333
|
+
isCombinedShape: px.boolean().optional(),
|
|
1334
|
+
ref: PxRefEffectSchema.optional()
|
|
1335
|
+
});
|
|
1336
|
+
function validateNodeEffects(root, opts) {
|
|
1337
|
+
const warnings = [];
|
|
1338
|
+
const walk = (node, path) => {
|
|
1339
|
+
if (node && node.effects) {
|
|
1340
|
+
const ctx = { errors: [], warnings: [], strict: !!(opts == null ? void 0 : opts.strict) };
|
|
1341
|
+
const ok = PxEffectsSchema.isValid(node.effects, ctx, [path + ".effects"]);
|
|
1342
|
+
if (!ok) {
|
|
1343
|
+
for (const err of ctx.errors) warnings.push(err);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
if (node && Array.isArray(node.children)) {
|
|
1347
|
+
node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]"));
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
walk(root, "root");
|
|
1351
|
+
return warnings;
|
|
1352
|
+
}
|
|
1353
|
+
var PxNodeBase = px.openObject({
|
|
1354
|
+
type: px.string(),
|
|
1355
|
+
id: px.string().optional(),
|
|
1356
|
+
meta: px.any().optional(),
|
|
1357
|
+
// Player-effects bucket emitted by the Editor's lightweight design format.
|
|
1358
|
+
// Consumed and removed by `applyPlayerEffects` before any other normalisation
|
|
1359
|
+
// (see `createAnimatorImpl`), so downstream code never sees it.
|
|
1360
|
+
effects: PxEffectsSchema.optional(),
|
|
1361
|
+
animate: PxAnimationDefinitionSchema.optional(),
|
|
1362
|
+
style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
|
|
1363
|
+
}, PxAttrValueSchema);
|
|
1364
|
+
var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBase._shape), {
|
|
1365
|
+
children: px.lazy(() => px.array(PxNodeSchema), []).optional()
|
|
1366
|
+
}), PxAttrValueSchema);
|
|
1367
|
+
var PxSvgNodeExtra = px.object({
|
|
1368
|
+
width: px.number().optional(),
|
|
1369
|
+
height: px.number().optional(),
|
|
1370
|
+
viewBox: px.string().optional(),
|
|
1371
|
+
animator: PxAnimatorConfigSchema.optional()
|
|
1372
|
+
});
|
|
1373
|
+
var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps(__spreadValues(__spreadValues({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
|
|
1374
|
+
type: px.literal("svg"),
|
|
1375
|
+
// override string → literal to require 'svg'
|
|
1376
|
+
children: px.array(PxNodeSchema).optional()
|
|
1377
|
+
}), PxAttrValueSchema);
|
|
1378
|
+
var PxBezierPathSchema = implementsInterface()(px.object({
|
|
1379
|
+
v: px.array(px.array(px.number())),
|
|
1380
|
+
i: px.array(px.array(px.number())).optional(),
|
|
1381
|
+
o: px.array(px.array(px.number())).optional(),
|
|
1382
|
+
c: px.boolean().optional()
|
|
1383
|
+
}));
|
|
1384
|
+
function isPxElementFileFormat(fileJson) {
|
|
1385
|
+
if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
return fileJson["type"] === "svg" || fileJson["tagName"] === "svg";
|
|
1389
|
+
}
|
|
1390
|
+
function isPxElementFileFormatDeep(fileJson) {
|
|
1391
|
+
const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
|
|
1392
|
+
return { valid, errors: valid ? [] : ["Document failed schema validation"] };
|
|
1393
|
+
}
|
|
1394
|
+
function getAnimatorConfig(doc) {
|
|
1395
|
+
var _a, _b;
|
|
1396
|
+
return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator) || (doc == null ? void 0 : doc.animation) || ((_b = doc == null ? void 0 : doc.meta) == null ? void 0 : _b.animation);
|
|
1397
|
+
}
|
|
1398
|
+
function getDefs(doc) {
|
|
1399
|
+
var _a;
|
|
1400
|
+
if (!doc) return void 0;
|
|
1401
|
+
return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
|
|
1402
|
+
}
|
|
1403
|
+
function getBindings(doc) {
|
|
1404
|
+
var _a;
|
|
1405
|
+
if (!doc) return void 0;
|
|
1406
|
+
const animate = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animate;
|
|
1407
|
+
if (!animate) return void 0;
|
|
1408
|
+
return Object.entries(animate).map(([id, anim]) => ({ id, animate: anim }));
|
|
1409
|
+
}
|
|
1410
|
+
function getChildren(doc) {
|
|
1411
|
+
return doc == null ? void 0 : doc.children;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
80
1414
|
// src/PxAnimatorUtil.ts
|
|
81
1415
|
function bezierToSvgPath(path) {
|
|
82
1416
|
var _a, _b, _c, _d;
|
|
@@ -166,50 +1500,104 @@ function remap(value, inMin, inMax, outMin, outMax) {
|
|
|
166
1500
|
const t = (value - inMin) / (inMax - inMin);
|
|
167
1501
|
return outMin + t * (outMax - outMin);
|
|
168
1502
|
}
|
|
169
|
-
function
|
|
170
|
-
|
|
1503
|
+
function solveCubicBezierX(p1x, p2x, x) {
|
|
1504
|
+
if (x <= 0) return 0;
|
|
1505
|
+
if (x >= 1) return 1;
|
|
171
1506
|
const cx = 3 * p1x;
|
|
172
1507
|
const bx = 3 * (p2x - p1x) - cx;
|
|
173
1508
|
const ax = 1 - cx - bx;
|
|
1509
|
+
function sampleX(t) {
|
|
1510
|
+
return ((ax * t + bx) * t + cx) * t;
|
|
1511
|
+
}
|
|
1512
|
+
function sampleDX(t) {
|
|
1513
|
+
return (3 * ax * t + 2 * bx) * t + cx;
|
|
1514
|
+
}
|
|
1515
|
+
let t2 = x;
|
|
1516
|
+
let t0 = 0;
|
|
1517
|
+
let t1 = 1;
|
|
1518
|
+
for (let i = 0; i < 8; i++) {
|
|
1519
|
+
const x2 = sampleX(t2) - x;
|
|
1520
|
+
if (Math.abs(x2) < 1e-6) return t2;
|
|
1521
|
+
const d2 = sampleDX(t2);
|
|
1522
|
+
if (Math.abs(d2) < 1e-6) break;
|
|
1523
|
+
t2 -= x2 / d2;
|
|
1524
|
+
}
|
|
1525
|
+
t2 = x;
|
|
1526
|
+
while (t0 < t1) {
|
|
1527
|
+
const x2 = sampleX(t2);
|
|
1528
|
+
if (Math.abs(x2 - x) < 1e-6) return t2;
|
|
1529
|
+
if (x > x2) t0 = t2;
|
|
1530
|
+
else t1 = t2;
|
|
1531
|
+
t2 = (t1 + t0) / 2;
|
|
1532
|
+
}
|
|
1533
|
+
return t2;
|
|
1534
|
+
}
|
|
1535
|
+
function cubicBezier(easing) {
|
|
1536
|
+
const [p1x, p1y, p2x, p2y] = easing;
|
|
174
1537
|
const cy = 3 * p1y;
|
|
175
1538
|
const by = 3 * (p2y - p1y) - cy;
|
|
176
1539
|
const ay = 1 - cy - by;
|
|
177
|
-
function sampleCurveX(t) {
|
|
178
|
-
return ((ax * t + bx) * t + cx) * t;
|
|
179
|
-
}
|
|
180
1540
|
function sampleCurveY(t) {
|
|
181
1541
|
return ((ay * t + by) * t + cy) * t;
|
|
182
1542
|
}
|
|
183
|
-
function sampleCurveDerivativeX(t) {
|
|
184
|
-
return (3 * ax * t + 2 * bx) * t + cx;
|
|
185
|
-
}
|
|
186
|
-
function solveCurveX(x) {
|
|
187
|
-
if (x <= 0) return 0;
|
|
188
|
-
if (x >= 1) return 1;
|
|
189
|
-
let t2 = x;
|
|
190
|
-
let t0 = 0;
|
|
191
|
-
let t1 = 1;
|
|
192
|
-
for (let i = 0; i < 8; i++) {
|
|
193
|
-
const x2 = sampleCurveX(t2) - x;
|
|
194
|
-
if (Math.abs(x2) < 1e-6) return t2;
|
|
195
|
-
const d2 = sampleCurveDerivativeX(t2);
|
|
196
|
-
if (Math.abs(d2) < 1e-6) break;
|
|
197
|
-
t2 -= x2 / d2;
|
|
198
|
-
}
|
|
199
|
-
t2 = x;
|
|
200
|
-
while (t0 < t1) {
|
|
201
|
-
const x2 = sampleCurveX(t2);
|
|
202
|
-
if (Math.abs(x2 - x) < 1e-6) return t2;
|
|
203
|
-
if (x > x2) t0 = t2;
|
|
204
|
-
else t1 = t2;
|
|
205
|
-
t2 = (t1 + t0) / 2;
|
|
206
|
-
}
|
|
207
|
-
return t2;
|
|
208
|
-
}
|
|
209
1543
|
return function(x) {
|
|
210
|
-
return sampleCurveY(
|
|
1544
|
+
return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
|
|
211
1545
|
};
|
|
212
1546
|
}
|
|
1547
|
+
function lerp2(a, b, t) {
|
|
1548
|
+
return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
|
|
1549
|
+
}
|
|
1550
|
+
function subdivideCubicBezier(p0, p1, p2, p3, t) {
|
|
1551
|
+
const q0 = lerp2(p0, p1, t);
|
|
1552
|
+
const q1 = lerp2(p1, p2, t);
|
|
1553
|
+
const q2 = lerp2(p2, p3, t);
|
|
1554
|
+
const r0 = lerp2(q0, q1, t);
|
|
1555
|
+
const r1 = lerp2(q1, q2, t);
|
|
1556
|
+
const s = lerp2(r0, r1, t);
|
|
1557
|
+
return {
|
|
1558
|
+
left: [p0, q0, r0, s],
|
|
1559
|
+
right: [s, r1, q2, p3]
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
function splitEasing(easing, xFraction) {
|
|
1563
|
+
if (!easing) return { left: void 0, right: void 0 };
|
|
1564
|
+
if (xFraction <= 0) return { left: void 0, right: easing };
|
|
1565
|
+
if (xFraction >= 1) return { left: easing, right: void 0 };
|
|
1566
|
+
const [x1, y1, x2, y2] = easing;
|
|
1567
|
+
const t = solveCubicBezierX(x1, x2, xFraction);
|
|
1568
|
+
const p0 = [0, 0];
|
|
1569
|
+
const p1 = [x1, y1];
|
|
1570
|
+
const p2 = [x2, y2];
|
|
1571
|
+
const p3 = [1, 1];
|
|
1572
|
+
const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
|
|
1573
|
+
const sx = left[3][0];
|
|
1574
|
+
const sy = left[3][1];
|
|
1575
|
+
let leftEasing;
|
|
1576
|
+
if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
|
|
1577
|
+
leftEasing = [
|
|
1578
|
+
left[1][0] / sx,
|
|
1579
|
+
left[1][1] / sy,
|
|
1580
|
+
left[2][0] / sx,
|
|
1581
|
+
left[2][1] / sy
|
|
1582
|
+
];
|
|
1583
|
+
}
|
|
1584
|
+
let rightEasing;
|
|
1585
|
+
const rx = 1 - sx;
|
|
1586
|
+
const ry = 1 - sy;
|
|
1587
|
+
if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
|
|
1588
|
+
rightEasing = [
|
|
1589
|
+
(right[1][0] - sx) / rx,
|
|
1590
|
+
(right[1][1] - sy) / ry,
|
|
1591
|
+
(right[2][0] - sx) / rx,
|
|
1592
|
+
(right[2][1] - sy) / ry
|
|
1593
|
+
];
|
|
1594
|
+
}
|
|
1595
|
+
return { left: leftEasing, right: rightEasing };
|
|
1596
|
+
}
|
|
1597
|
+
function reverseEasing(easing) {
|
|
1598
|
+
if (!easing) return void 0;
|
|
1599
|
+
return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
|
|
1600
|
+
}
|
|
213
1601
|
function toRGBA(color) {
|
|
214
1602
|
const r = Math.round(color[0] * 255);
|
|
215
1603
|
const g = Math.round(color[1] * 255);
|
|
@@ -256,6 +1644,24 @@ function parseColor(s) {
|
|
|
256
1644
|
var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
|
|
257
1645
|
var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
|
|
258
1646
|
var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
1647
|
+
function composeTransformParts(parts, opts) {
|
|
1648
|
+
var _a;
|
|
1649
|
+
if (!parts) return "";
|
|
1650
|
+
const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
|
|
1651
|
+
const segs = [];
|
|
1652
|
+
const t = parts.translate;
|
|
1653
|
+
const o = parts.origin;
|
|
1654
|
+
const r = parts.rotate;
|
|
1655
|
+
const s = parts.scale;
|
|
1656
|
+
const tu = withUnits ? "px" : "";
|
|
1657
|
+
const ru = withUnits ? "deg" : "";
|
|
1658
|
+
if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
|
|
1659
|
+
if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
|
|
1660
|
+
if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
|
|
1661
|
+
if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
|
|
1662
|
+
if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
|
|
1663
|
+
return segs.join("");
|
|
1664
|
+
}
|
|
259
1665
|
var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
260
1666
|
var DEFAULT_DURATION_MS = 1e3;
|
|
261
1667
|
function kebabToCamelCaseWord(kebab) {
|
|
@@ -315,14 +1721,260 @@ function camelCaseToKebabWordIfNeeded(camel) {
|
|
|
315
1721
|
function clamp(value, min, max) {
|
|
316
1722
|
return Math.max(min, Math.min(value, max));
|
|
317
1723
|
}
|
|
1724
|
+
function bezier2D_pointAt(P0, P1, P2, P3, t) {
|
|
1725
|
+
if (t <= 0) return [P0[0], P0[1]];
|
|
1726
|
+
if (t >= 1) return [P3[0], P3[1]];
|
|
1727
|
+
const u = 1 - t;
|
|
1728
|
+
const u2 = u * u;
|
|
1729
|
+
const u3 = u2 * u;
|
|
1730
|
+
const t2 = t * t;
|
|
1731
|
+
const t3 = t2 * t;
|
|
1732
|
+
const w0 = u3;
|
|
1733
|
+
const w1 = 3 * t * u2;
|
|
1734
|
+
const w2 = 3 * t2 * u;
|
|
1735
|
+
const w3 = t3;
|
|
1736
|
+
return [
|
|
1737
|
+
w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
|
|
1738
|
+
w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
|
|
1739
|
+
];
|
|
1740
|
+
}
|
|
1741
|
+
var BEZIER_T_NUDGE = 1e-4;
|
|
1742
|
+
function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
|
|
1743
|
+
const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
|
|
1744
|
+
if (result[0] === 0 && result[1] === 0) {
|
|
1745
|
+
const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
|
|
1746
|
+
return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
|
|
1747
|
+
}
|
|
1748
|
+
return result;
|
|
1749
|
+
}
|
|
1750
|
+
function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
|
|
1751
|
+
const u = 1 - t;
|
|
1752
|
+
const a = 3 * u * u;
|
|
1753
|
+
const b = 6 * t * u;
|
|
1754
|
+
const c = 3 * t * t;
|
|
1755
|
+
return [
|
|
1756
|
+
a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
|
|
1757
|
+
a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
|
|
1758
|
+
];
|
|
1759
|
+
}
|
|
1760
|
+
function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
|
|
1761
|
+
const n = steps + 1;
|
|
1762
|
+
const ts = new Float64Array(n);
|
|
1763
|
+
const ds = new Float64Array(n);
|
|
1764
|
+
let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
|
|
1765
|
+
ts[0] = 0;
|
|
1766
|
+
ds[0] = 0;
|
|
1767
|
+
let cum = 0;
|
|
1768
|
+
for (let i = 1; i < n; i++) {
|
|
1769
|
+
const t = i / steps;
|
|
1770
|
+
const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
|
|
1771
|
+
const dx = cur[0] - prev[0];
|
|
1772
|
+
const dy = cur[1] - prev[1];
|
|
1773
|
+
cum += Math.sqrt(dx * dx + dy * dy);
|
|
1774
|
+
ts[i] = t;
|
|
1775
|
+
ds[i] = cum;
|
|
1776
|
+
prev = cur;
|
|
1777
|
+
}
|
|
1778
|
+
return { ts, ds };
|
|
1779
|
+
}
|
|
1780
|
+
function bezier2D_tForDistance(lut, distance) {
|
|
1781
|
+
const { ts, ds } = lut;
|
|
1782
|
+
const last = ds.length - 1;
|
|
1783
|
+
if (distance <= 0) return ts[0];
|
|
1784
|
+
if (distance >= ds[last]) return ts[last];
|
|
1785
|
+
let lo = 1;
|
|
1786
|
+
let hi = last;
|
|
1787
|
+
while (lo < hi) {
|
|
1788
|
+
const mid = lo + hi >>> 1;
|
|
1789
|
+
if (ds[mid] < distance) lo = mid + 1;
|
|
1790
|
+
else hi = mid;
|
|
1791
|
+
}
|
|
1792
|
+
const dPrev = ds[hi - 1];
|
|
1793
|
+
const dCur = ds[hi];
|
|
1794
|
+
const span = dCur - dPrev;
|
|
1795
|
+
const frac = span > 0 ? (distance - dPrev) / span : 0;
|
|
1796
|
+
return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
|
|
1797
|
+
}
|
|
318
1798
|
|
|
319
1799
|
// src/PxAnimatorDOM.ts
|
|
320
1800
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
321
|
-
var
|
|
322
|
-
|
|
1801
|
+
var ALLOWED_SVG_TAGS_LOWER_CASE = new Set([
|
|
1802
|
+
"svg",
|
|
1803
|
+
"g",
|
|
1804
|
+
"path",
|
|
1805
|
+
"circle",
|
|
1806
|
+
"ellipse",
|
|
1807
|
+
"rect",
|
|
1808
|
+
"line",
|
|
1809
|
+
"polyline",
|
|
1810
|
+
"polygon",
|
|
1811
|
+
"text",
|
|
1812
|
+
"tspan",
|
|
1813
|
+
"textPath",
|
|
1814
|
+
"defs",
|
|
1815
|
+
"clipPath",
|
|
1816
|
+
"mask",
|
|
1817
|
+
"pattern",
|
|
1818
|
+
"linearGradient",
|
|
1819
|
+
"radialGradient",
|
|
1820
|
+
"stop",
|
|
1821
|
+
"use",
|
|
1822
|
+
"symbol",
|
|
1823
|
+
"marker",
|
|
1824
|
+
"filter",
|
|
1825
|
+
"feGaussianBlur",
|
|
1826
|
+
"feOffset",
|
|
1827
|
+
"feBlend",
|
|
1828
|
+
"feColorMatrix",
|
|
1829
|
+
"feMerge",
|
|
1830
|
+
"feMergeNode"
|
|
1831
|
+
].map((tagName) => tagName.toLowerCase()));
|
|
1832
|
+
var ALLOWED_RESOURCE_ATTRIBUTES = [
|
|
1833
|
+
"href",
|
|
1834
|
+
// <use>
|
|
1835
|
+
"src",
|
|
1836
|
+
// <image>
|
|
1837
|
+
"filter",
|
|
1838
|
+
// url(#filterId)
|
|
1839
|
+
"clipPath",
|
|
1840
|
+
// clip-path="url(#clipPathId)"
|
|
1841
|
+
"mask",
|
|
1842
|
+
// url(#maskId)
|
|
1843
|
+
"markerStart",
|
|
1844
|
+
// marker-start="url(#markerId)"
|
|
1845
|
+
"markerMid",
|
|
1846
|
+
// marker-mid="url(#markerId)"
|
|
1847
|
+
"markerEnd"
|
|
1848
|
+
// marker-end="url(#markerId)"
|
|
1849
|
+
// 'fill', // url(#gradientId) or url(#patternId)
|
|
1850
|
+
// 'stroke', // url(#gradientId) or url(#patternId)
|
|
1851
|
+
// Don't allow 'cursor', can use external SVG, // url(cursor.svg)
|
|
1852
|
+
];
|
|
1853
|
+
var ALLOWED_RESOURCE_ATTRIBUTES_SET = new Set(ALLOWED_RESOURCE_ATTRIBUTES);
|
|
1854
|
+
var ALLOWED_ATTRIBUTES = [
|
|
1855
|
+
"href",
|
|
1856
|
+
"src",
|
|
1857
|
+
// Presentation
|
|
1858
|
+
"fill",
|
|
1859
|
+
"fillOpacity",
|
|
1860
|
+
"fillRule",
|
|
1861
|
+
"stroke",
|
|
1862
|
+
"strokeWidth",
|
|
1863
|
+
"strokeOpacity",
|
|
1864
|
+
"strokeLinecap",
|
|
1865
|
+
"strokeLinejoin",
|
|
1866
|
+
"strokeMiterlimit",
|
|
1867
|
+
"strokeDasharray",
|
|
1868
|
+
"strokeDashoffset",
|
|
1869
|
+
"opacity",
|
|
1870
|
+
"transform",
|
|
1871
|
+
// Geometry
|
|
1872
|
+
"x",
|
|
1873
|
+
"y",
|
|
1874
|
+
"cx",
|
|
1875
|
+
"cy",
|
|
1876
|
+
"r",
|
|
1877
|
+
"rx",
|
|
1878
|
+
"ry",
|
|
1879
|
+
"width",
|
|
1880
|
+
"height",
|
|
1881
|
+
"d",
|
|
1882
|
+
"x1",
|
|
1883
|
+
"y1",
|
|
1884
|
+
"x2",
|
|
1885
|
+
"y2",
|
|
1886
|
+
"points",
|
|
1887
|
+
"dx",
|
|
1888
|
+
"dy",
|
|
1889
|
+
// Font
|
|
1890
|
+
"fontSize",
|
|
1891
|
+
"fontFamily",
|
|
1892
|
+
"fontWeight",
|
|
1893
|
+
"fontStyle",
|
|
1894
|
+
// Text
|
|
1895
|
+
"textAnchor",
|
|
1896
|
+
"letterSpacing",
|
|
1897
|
+
"wordSpacing",
|
|
1898
|
+
"space",
|
|
1899
|
+
"xml:space",
|
|
1900
|
+
"textDecoration",
|
|
1901
|
+
"textTransform",
|
|
1902
|
+
"whiteSpace",
|
|
1903
|
+
"white-space",
|
|
1904
|
+
"dominantBaseline",
|
|
1905
|
+
"alignmentBaseline",
|
|
1906
|
+
"rotate",
|
|
1907
|
+
// per-glyph rotation array, currently not supported
|
|
1908
|
+
// Structure
|
|
1909
|
+
"id",
|
|
1910
|
+
"class",
|
|
1911
|
+
"viewBox",
|
|
1912
|
+
"preserveAspectRatio",
|
|
1913
|
+
// Gradient/Pattern
|
|
1914
|
+
"offset",
|
|
1915
|
+
"stopColor",
|
|
1916
|
+
"stopOpacity",
|
|
1917
|
+
"gradientTransform",
|
|
1918
|
+
// Clippath/Mask
|
|
1919
|
+
"clipPath",
|
|
1920
|
+
"mask",
|
|
1921
|
+
// Motion path
|
|
1922
|
+
"offsetPath",
|
|
1923
|
+
"offsetDistance",
|
|
1924
|
+
"offsetRotate",
|
|
1925
|
+
"offsetAnchor",
|
|
1926
|
+
"offsetPosition",
|
|
1927
|
+
// Text path
|
|
1928
|
+
"startOffset",
|
|
1929
|
+
"textLength",
|
|
1930
|
+
"lengthAdjust",
|
|
1931
|
+
// Filter
|
|
1932
|
+
"filter",
|
|
1933
|
+
"stdDeviation",
|
|
1934
|
+
"in",
|
|
1935
|
+
"in2",
|
|
1936
|
+
"result",
|
|
1937
|
+
"mode",
|
|
1938
|
+
...ALLOWED_RESOURCE_ATTRIBUTES
|
|
1939
|
+
];
|
|
1940
|
+
var ALLOWED_ATTRIBUTES_LOW_SET = new Set(ALLOWED_ATTRIBUTES.map((str) => str.toLowerCase()));
|
|
1941
|
+
function sanitiseAttributeValue(name, value) {
|
|
1942
|
+
const nameLower = name.toLowerCase();
|
|
1943
|
+
if (!ALLOWED_ATTRIBUTES_LOW_SET.has(nameLower)) {
|
|
1944
|
+
console.warn("Attribute not in whitelist: ", nameLower);
|
|
1945
|
+
return void 0;
|
|
1946
|
+
}
|
|
1947
|
+
if (nameLower === "fill" || nameLower === "stroke" || nameLower === "stopColor") {
|
|
1948
|
+
const str = String(value);
|
|
1949
|
+
if (str.includes("url(") && !/^url\(#[^)]+\)$/.test(str)) {
|
|
1950
|
+
console.warn('Attribute "' + nameLower + '" blocked: url() references must be internal url(#id), got:', value);
|
|
1951
|
+
return void 0;
|
|
1952
|
+
}
|
|
1953
|
+
return value;
|
|
1954
|
+
}
|
|
1955
|
+
if (ALLOWED_RESOURCE_ATTRIBUTES_SET.has(nameLower)) {
|
|
1956
|
+
const str = String(value);
|
|
1957
|
+
if (str.startsWith("#")) {
|
|
1958
|
+
return value;
|
|
1959
|
+
}
|
|
1960
|
+
if (/^url\(#[^)]+\)$/.test(str)) {
|
|
1961
|
+
return value;
|
|
1962
|
+
}
|
|
1963
|
+
return void 0;
|
|
1964
|
+
}
|
|
1965
|
+
return value;
|
|
1966
|
+
}
|
|
1967
|
+
function createElement(tagName, normalisedProps, style, children, textContent) {
|
|
1968
|
+
if (!ALLOWED_SVG_TAGS_LOWER_CASE.has(tagName.toLowerCase())) {
|
|
1969
|
+
console.warn("Attribute not in whitelist: ", tagName);
|
|
1970
|
+
return null;
|
|
1971
|
+
}
|
|
323
1972
|
const element = document.createElementNS(SVG_NS, tagName);
|
|
324
|
-
for (const propName in
|
|
325
|
-
element.setAttribute(
|
|
1973
|
+
for (const propName in normalisedProps) {
|
|
1974
|
+
element.setAttribute(
|
|
1975
|
+
camelCaseToKebabWordIfNeeded(propName),
|
|
1976
|
+
sanitiseAttributeValue(propName, normalisedProps[propName])
|
|
1977
|
+
);
|
|
326
1978
|
}
|
|
327
1979
|
if (style) {
|
|
328
1980
|
for (const styleProp in style) {
|
|
@@ -334,6 +1986,7 @@ function createElement(tagName, props, style, children) {
|
|
|
334
1986
|
element.appendChild(child);
|
|
335
1987
|
}
|
|
336
1988
|
}
|
|
1989
|
+
if (textContent) element.textContent = textContent;
|
|
337
1990
|
return element;
|
|
338
1991
|
}
|
|
339
1992
|
function resolveStyle(style, defs) {
|
|
@@ -348,9 +2001,12 @@ function getNormalizedProps(props) {
|
|
|
348
2001
|
const propsCopy = {};
|
|
349
2002
|
for (const key of Object.keys(props)) {
|
|
350
2003
|
if (INTERNAL_ATTRS.has(key)) continue;
|
|
2004
|
+
if (key === "style") continue;
|
|
351
2005
|
let value = props[key];
|
|
352
2006
|
if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
|
|
353
2007
|
propsCopy[key] = toRGBA(value);
|
|
2008
|
+
} else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && value.value && typeof value.value === "object") {
|
|
2009
|
+
propsCopy["transform"] = composeTransformParts(value.value, { withUnits: false });
|
|
354
2010
|
} else if (TRANSFORM_FN_NAMES.has(key)) {
|
|
355
2011
|
if (Array.isArray(value)) {
|
|
356
2012
|
if (key === "translate") value = value.map((v) => v + "px");
|
|
@@ -366,8 +2022,8 @@ function getNormalizedProps(props) {
|
|
|
366
2022
|
}
|
|
367
2023
|
function renderNode(node, defs) {
|
|
368
2024
|
if (!node) return null;
|
|
369
|
-
const _a = node, { type, children,
|
|
370
|
-
const nodeDefs = node
|
|
2025
|
+
const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
|
|
2026
|
+
const nodeDefs = getDefs(node) || defs;
|
|
371
2027
|
const resolvedStyle = resolveStyle(style, nodeDefs);
|
|
372
2028
|
let childElements;
|
|
373
2029
|
if (children) {
|
|
@@ -383,7 +2039,8 @@ function renderNode(node, defs) {
|
|
|
383
2039
|
type || "g",
|
|
384
2040
|
getNormalizedProps(props),
|
|
385
2041
|
resolvedStyle,
|
|
386
|
-
childElements
|
|
2042
|
+
childElements,
|
|
2043
|
+
props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
|
|
387
2044
|
);
|
|
388
2045
|
}
|
|
389
2046
|
|
|
@@ -464,284 +2121,45 @@ function setupAnimationTriggers(api, config) {
|
|
|
464
2121
|
return api;
|
|
465
2122
|
}
|
|
466
2123
|
|
|
467
|
-
// src/
|
|
468
|
-
|
|
469
|
-
var
|
|
470
|
-
|
|
471
|
-
if (!
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
function isObject(v) {
|
|
477
|
-
return v && typeof v === "object" && !Array.isArray(v);
|
|
478
|
-
}
|
|
479
|
-
function validateFillMode(v, path, errors) {
|
|
480
|
-
if (v === "forwards" || v === "backwards" || v === "both" || v === "none") return true;
|
|
481
|
-
errors.push(path + ': invalid FillMode "' + v + `", expected 'forwards'|'backwards'|'both'|'none'`);
|
|
482
|
-
return false;
|
|
483
|
-
}
|
|
484
|
-
function validatePlaybackDirection(v, path, errors) {
|
|
485
|
-
if (v === "normal" || v === "reverse" || v === "alternate" || v === "alternate-reverse") return true;
|
|
486
|
-
errors.push(path + ': invalid PlaybackDirection "' + v + `", expected 'normal'|'reverse'|'alternate'|'alternate-reverse'`);
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
function validatePxEasingOrRef(v, path, errors) {
|
|
490
|
-
if (typeof v === "string") return true;
|
|
491
|
-
if (Array.isArray(v) && v.length === 4 && v.every((n) => typeof n === "number")) return true;
|
|
492
|
-
errors.push(path + ": invalid easing, expected string or [number, number, number, number]");
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
function validatePxKeyframe(v, path, errors) {
|
|
496
|
-
if (!isObject(v)) {
|
|
497
|
-
errors.push(path + ": expected object");
|
|
498
|
-
return false;
|
|
499
|
-
}
|
|
500
|
-
let valid = true;
|
|
501
|
-
if (v.time !== void 0 && typeof v.time !== "number") {
|
|
502
|
-
errors.push(path + ".time: expected number, got " + typeof v.time);
|
|
503
|
-
valid = false;
|
|
504
|
-
}
|
|
505
|
-
if (v.t !== void 0 && typeof v.t !== "number") {
|
|
506
|
-
errors.push(path + ".t: expected number, got " + typeof v.t);
|
|
507
|
-
valid = false;
|
|
508
|
-
}
|
|
509
|
-
if (v.easing !== void 0 && !validatePxEasingOrRef(v.easing, path + ".easing", errors)) valid = false;
|
|
510
|
-
if (v.e !== void 0 && !validatePxEasingOrRef(v.e, path + ".e", errors)) valid = false;
|
|
511
|
-
return valid;
|
|
512
|
-
}
|
|
513
|
-
function validatePxPropertyAnimation(v, path, errors) {
|
|
514
|
-
if (!isObject(v)) {
|
|
515
|
-
errors.push(path + ": expected object");
|
|
516
|
-
return false;
|
|
517
|
-
}
|
|
518
|
-
let valid = true;
|
|
519
|
-
if (v.keyframes !== void 0) {
|
|
520
|
-
if (!Array.isArray(v.keyframes)) {
|
|
521
|
-
errors.push(path + ".keyframes: expected array");
|
|
522
|
-
valid = false;
|
|
523
|
-
} else {
|
|
524
|
-
v.keyframes.forEach((kf, i) => {
|
|
525
|
-
if (!validatePxKeyframe(kf, path + ".keyframes[" + i + "]", errors)) valid = false;
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (v.kfs !== void 0) {
|
|
530
|
-
if (!Array.isArray(v.kfs)) {
|
|
531
|
-
errors.push(path + ".kfs: expected array");
|
|
532
|
-
valid = false;
|
|
533
|
-
} else {
|
|
534
|
-
v.kfs.forEach((kf, i) => {
|
|
535
|
-
if (!validatePxKeyframe(kf, path + ".kfs[" + i + "]", errors)) valid = false;
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
return valid;
|
|
540
|
-
}
|
|
541
|
-
function validatePxAnimationDefinition(v, path, errors) {
|
|
542
|
-
if (!isObject(v)) {
|
|
543
|
-
errors.push(path + ": expected object");
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
let valid = true;
|
|
547
|
-
for (const key of Object.keys(v)) {
|
|
548
|
-
if (!validatePxPropertyAnimation(v[key], path + "." + key, errors)) valid = false;
|
|
549
|
-
}
|
|
550
|
-
return valid;
|
|
551
|
-
}
|
|
552
|
-
function validatePxElementAnimation(v, path, errors) {
|
|
553
|
-
if (typeof v === "string") return true;
|
|
554
|
-
if (Array.isArray(v)) {
|
|
555
|
-
let valid = true;
|
|
556
|
-
v.forEach((item, i) => {
|
|
557
|
-
if (typeof item !== "string" && !validatePxAnimationDefinition(item, path + "[" + i + "]", errors)) {
|
|
558
|
-
valid = false;
|
|
559
|
-
}
|
|
560
|
-
});
|
|
561
|
-
return valid;
|
|
2124
|
+
// src/PxMotionPath.ts
|
|
2125
|
+
function propAnimIsMotionPath(anim) {
|
|
2126
|
+
var _a;
|
|
2127
|
+
const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
|
|
2128
|
+
if (!Array.isArray(kfs)) return false;
|
|
2129
|
+
if (anim.autoOrient) return true;
|
|
2130
|
+
for (const kf of kfs) {
|
|
2131
|
+
if (kf.tangentIn || kf.tangentOut) return true;
|
|
562
2132
|
}
|
|
563
|
-
if (isObject(v)) return validatePxAnimationDefinition(v, path, errors);
|
|
564
|
-
errors.push(path + ": expected string, array, or PxAnimationDefinition object");
|
|
565
2133
|
return false;
|
|
566
2134
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
let valid = true;
|
|
597
|
-
if (v.mode !== void 0 && !["auto", "webapi", "frames"].includes(v.mode)) {
|
|
598
|
-
errors.push(path + '.mode: invalid value "' + v.mode + `", expected 'auto'|'webapi'|'frames'`);
|
|
599
|
-
valid = false;
|
|
600
|
-
}
|
|
601
|
-
if (v.duration !== void 0 && typeof v.duration !== "number") {
|
|
602
|
-
errors.push(path + ".duration: expected number, got " + typeof v.duration);
|
|
603
|
-
valid = false;
|
|
604
|
-
}
|
|
605
|
-
if (v.delay !== void 0 && typeof v.delay !== "number") {
|
|
606
|
-
errors.push(path + ".delay: expected number, got " + typeof v.delay);
|
|
607
|
-
valid = false;
|
|
608
|
-
}
|
|
609
|
-
if (v.iterations !== void 0 && typeof v.iterations !== "number" && v.iterations !== "infinite") {
|
|
610
|
-
errors.push(path + ".iterations: expected number or 'infinite', got " + typeof v.iterations);
|
|
611
|
-
valid = false;
|
|
612
|
-
}
|
|
613
|
-
if (v.fill !== void 0 && !validateFillMode(v.fill, path + ".fill", errors)) valid = false;
|
|
614
|
-
if (v.direction !== void 0 && !validatePlaybackDirection(v.direction, path + ".direction", errors)) valid = false;
|
|
615
|
-
if (v.frameRate !== void 0 && typeof v.frameRate !== "number") {
|
|
616
|
-
errors.push(path + ".frameRate: expected number, got " + typeof v.frameRate);
|
|
617
|
-
valid = false;
|
|
618
|
-
}
|
|
619
|
-
if (v.trigger !== void 0 && !validatePxTrigger(v.trigger, path + ".trigger", errors)) valid = false;
|
|
620
|
-
return valid;
|
|
621
|
-
}
|
|
622
|
-
function validatePxDefs(v, path, errors) {
|
|
623
|
-
if (!isObject(v)) {
|
|
624
|
-
errors.push(path + ": expected object");
|
|
625
|
-
return false;
|
|
626
|
-
}
|
|
627
|
-
let valid = true;
|
|
628
|
-
if (v.easings !== void 0) {
|
|
629
|
-
if (!isObject(v.easings)) {
|
|
630
|
-
errors.push(path + ".easings: expected object");
|
|
631
|
-
valid = false;
|
|
632
|
-
} else {
|
|
633
|
-
for (const key of Object.keys(v.easings)) {
|
|
634
|
-
if (!validatePxEasingOrRef(v.easings[key], path + ".easings." + key, errors)) valid = false;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
if (v.animations !== void 0) {
|
|
639
|
-
if (!isObject(v.animations)) {
|
|
640
|
-
errors.push(path + ".animations: expected object");
|
|
641
|
-
valid = false;
|
|
642
|
-
} else {
|
|
643
|
-
for (const key of Object.keys(v.animations)) {
|
|
644
|
-
if (!validatePxAnimationDefinition(v.animations[key], path + ".animations." + key, errors)) valid = false;
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
if (v.styles !== void 0 && !isObject(v.styles)) {
|
|
649
|
-
errors.push(path + ".styles: expected object");
|
|
650
|
-
valid = false;
|
|
651
|
-
}
|
|
652
|
-
return valid;
|
|
653
|
-
}
|
|
654
|
-
function validatePxBinding(v, path, errors) {
|
|
655
|
-
if (!isObject(v)) {
|
|
656
|
-
errors.push(path + ": expected object");
|
|
657
|
-
return false;
|
|
658
|
-
}
|
|
659
|
-
let valid = true;
|
|
660
|
-
if (typeof v.id !== "string") {
|
|
661
|
-
errors.push(path + ".id: expected string, got " + typeof v.id);
|
|
662
|
-
valid = false;
|
|
663
|
-
}
|
|
664
|
-
if (!validatePxElementAnimation(v.animate, path + ".animate", errors)) valid = false;
|
|
665
|
-
return valid;
|
|
666
|
-
}
|
|
667
|
-
function validatePxNode(v, path, errors) {
|
|
668
|
-
if (!isObject(v)) {
|
|
669
|
-
errors.push(path + ": expected object");
|
|
670
|
-
return false;
|
|
671
|
-
}
|
|
672
|
-
let valid = true;
|
|
673
|
-
if (typeof v.type !== "string") {
|
|
674
|
-
errors.push(path + ".type: expected string, got " + typeof v.type);
|
|
675
|
-
valid = false;
|
|
676
|
-
}
|
|
677
|
-
if (v.children !== void 0) {
|
|
678
|
-
if (!Array.isArray(v.children)) {
|
|
679
|
-
errors.push(path + ".children: expected array");
|
|
680
|
-
valid = false;
|
|
681
|
-
} else {
|
|
682
|
-
v.children.forEach((child, i) => {
|
|
683
|
-
if (!validatePxNode(child, path + ".children[" + i + "]", errors)) valid = false;
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
if (v.animate !== void 0 && !validatePxElementAnimation(v.animate, path + ".animate", errors)) valid = false;
|
|
688
|
-
return valid;
|
|
689
|
-
}
|
|
690
|
-
function validatePxSvgNode(v, path, errors) {
|
|
691
|
-
if (!validatePxNode(v, path, errors)) return false;
|
|
692
|
-
let valid = true;
|
|
693
|
-
if (v.type !== "svg") {
|
|
694
|
-
errors.push(path + ".type: expected 'svg', got '" + v.type + "'");
|
|
695
|
-
valid = false;
|
|
696
|
-
}
|
|
697
|
-
if (v.width !== void 0 && typeof v.width !== "number") {
|
|
698
|
-
errors.push(path + ".width: expected number, got " + typeof v.width);
|
|
699
|
-
valid = false;
|
|
700
|
-
}
|
|
701
|
-
if (v.height !== void 0 && typeof v.height !== "number") {
|
|
702
|
-
errors.push(path + ".height: expected number, got " + typeof v.height);
|
|
703
|
-
valid = false;
|
|
704
|
-
}
|
|
705
|
-
if (v.viewBox !== void 0 && typeof v.viewBox !== "string") {
|
|
706
|
-
errors.push(path + ".viewBox: expected string, got " + typeof v.viewBox);
|
|
707
|
-
valid = false;
|
|
708
|
-
}
|
|
709
|
-
if (v.animator !== void 0 && !validatePxAnimatorConfig(v.animator, path + ".animator", errors)) valid = false;
|
|
710
|
-
if (v.defs !== void 0 && !validatePxDefs(v.defs, path + ".defs", errors)) valid = false;
|
|
711
|
-
if (v.bindings !== void 0) {
|
|
712
|
-
if (!Array.isArray(v.bindings)) {
|
|
713
|
-
errors.push(path + ".bindings: expected array");
|
|
714
|
-
valid = false;
|
|
715
|
-
} else {
|
|
716
|
-
v.bindings.forEach((binding, i) => {
|
|
717
|
-
if (!validatePxBinding(binding, path + ".bindings[" + i + "]", errors)) valid = false;
|
|
718
|
-
});
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
if (v.design !== void 0 && !validatePxNode(v.design, path + ".design", errors)) valid = false;
|
|
722
|
-
return valid;
|
|
723
|
-
}
|
|
724
|
-
function isPxElementFileFormatDeep(fileJson) {
|
|
725
|
-
const errors = [];
|
|
726
|
-
const valid = validatePxSvgNode(fileJson, "root", errors);
|
|
727
|
-
return { valid, errors };
|
|
728
|
-
}
|
|
729
|
-
function getAnimatorConfig(doc) {
|
|
730
|
-
var _a, _b;
|
|
731
|
-
return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator) || (doc == null ? void 0 : doc.animation) || ((_b = doc == null ? void 0 : doc.meta) == null ? void 0 : _b.animation);
|
|
732
|
-
}
|
|
733
|
-
function getDefs(doc) {
|
|
734
|
-
var _a;
|
|
735
|
-
if (!doc) return void 0;
|
|
736
|
-
return doc.defs || ((_a = doc.meta) == null ? void 0 : _a.defs);
|
|
737
|
-
}
|
|
738
|
-
function getBindings(doc) {
|
|
739
|
-
var _a;
|
|
740
|
-
if (!doc) return void 0;
|
|
741
|
-
return doc.bindings || ((_a = doc.meta) == null ? void 0 : _a.bindings);
|
|
742
|
-
}
|
|
743
|
-
function getChildren(doc) {
|
|
744
|
-
return doc == null ? void 0 : doc.children;
|
|
2135
|
+
var _segmentCache = /* @__PURE__ */ new WeakMap();
|
|
2136
|
+
function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
|
|
2137
|
+
const existing = _segmentCache.get(prevKf);
|
|
2138
|
+
if (existing) return existing;
|
|
2139
|
+
const to = prevKf.tangentOut;
|
|
2140
|
+
const ti = nextKf.tangentIn;
|
|
2141
|
+
const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
|
|
2142
|
+
const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
|
|
2143
|
+
const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
|
|
2144
|
+
const entry = {
|
|
2145
|
+
P0: prevPos,
|
|
2146
|
+
P1,
|
|
2147
|
+
P2,
|
|
2148
|
+
P3: nextPos,
|
|
2149
|
+
lut,
|
|
2150
|
+
totalArc: lut.ds[lut.ds.length - 1]
|
|
2151
|
+
};
|
|
2152
|
+
_segmentCache.set(prevKf, entry);
|
|
2153
|
+
return entry;
|
|
2154
|
+
}
|
|
2155
|
+
function evaluateMotionPathSegment(prevKf, nextKf, prevPos, nextPos, localProgress, autoOrient) {
|
|
2156
|
+
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
2157
|
+
const t = seg.totalArc === 0 ? localProgress : bezier2D_tForDistance(seg.lut, localProgress * seg.totalArc);
|
|
2158
|
+
const point = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
2159
|
+
if (!autoOrient) return { translate: point };
|
|
2160
|
+
const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
2161
|
+
const rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
|
|
2162
|
+
return { translate: point, rotateDeg };
|
|
745
2163
|
}
|
|
746
2164
|
|
|
747
2165
|
// src/PxDefinitions.ts
|
|
@@ -807,6 +2225,8 @@ function parseSvgPathToBezier(d) {
|
|
|
807
2225
|
currentPath.o.push([x2, y2]);
|
|
808
2226
|
} else if (type === "Z" || type === "z") {
|
|
809
2227
|
currentPath.c = true;
|
|
2228
|
+
} else {
|
|
2229
|
+
console.warn('Unsupported path command "' + type + '"');
|
|
810
2230
|
}
|
|
811
2231
|
}
|
|
812
2232
|
return res;
|
|
@@ -824,13 +2244,17 @@ function isPathString(value) {
|
|
|
824
2244
|
return typeof value === "string" && extractPathData(value) !== void 0;
|
|
825
2245
|
}
|
|
826
2246
|
function normalizePathValue(value) {
|
|
2247
|
+
if (value && typeof value === "object" && typeof value.path === "string") {
|
|
2248
|
+
const d = extractPathData(value.path);
|
|
2249
|
+
return d ? { paths: parseSvgPathToBezier(d) } : value;
|
|
2250
|
+
}
|
|
827
2251
|
if (value && typeof value === "object" && "paths" in value) {
|
|
828
2252
|
const pathsArray = value.paths;
|
|
829
2253
|
if (Array.isArray(pathsArray) && pathsArray.length > 0) {
|
|
830
2254
|
if (isPathString(pathsArray[0])) {
|
|
831
2255
|
const paths = [];
|
|
832
|
-
for (const
|
|
833
|
-
const d = extractPathData(
|
|
2256
|
+
for (const pathStr2 of pathsArray) {
|
|
2257
|
+
const d = extractPathData(pathStr2);
|
|
834
2258
|
if (d) {
|
|
835
2259
|
paths.push(...parseSvgPathToBezier(d));
|
|
836
2260
|
}
|
|
@@ -843,8 +2267,8 @@ function normalizePathValue(value) {
|
|
|
843
2267
|
if (Array.isArray(value)) {
|
|
844
2268
|
if (value.length > 0 && isPathString(value[0])) {
|
|
845
2269
|
const paths = [];
|
|
846
|
-
for (const
|
|
847
|
-
const d = extractPathData(
|
|
2270
|
+
for (const pathStr2 of value) {
|
|
2271
|
+
const d = extractPathData(pathStr2);
|
|
848
2272
|
if (d) {
|
|
849
2273
|
paths.push(...parseSvgPathToBezier(d));
|
|
850
2274
|
}
|
|
@@ -898,6 +2322,111 @@ function resolveElementAnimation(animate, defs) {
|
|
|
898
2322
|
}
|
|
899
2323
|
return results;
|
|
900
2324
|
}
|
|
2325
|
+
function interpolateValue(propName, a, b, t) {
|
|
2326
|
+
var _a, _b;
|
|
2327
|
+
if (propName === "d") {
|
|
2328
|
+
const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
|
|
2329
|
+
const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
|
|
2330
|
+
return { paths: interpolateBeziers(aPaths, bPaths, t) };
|
|
2331
|
+
}
|
|
2332
|
+
if (COLOUR_ATTR_NAMES.has(propName)) {
|
|
2333
|
+
return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
|
|
2334
|
+
}
|
|
2335
|
+
if (TRANSFORM_FN_NAMES.has(propName) || propName === "stroke-dasharray" || propName === "strokeDasharray") {
|
|
2336
|
+
return interpolateVec(a || [], b || [], t);
|
|
2337
|
+
}
|
|
2338
|
+
return interpolateNum(+(a || 0), +(b || 0), t);
|
|
2339
|
+
}
|
|
2340
|
+
function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
2341
|
+
var _a, _b, _c, _d, _e;
|
|
2342
|
+
const totalIntervals = keyframes.length - 1;
|
|
2343
|
+
const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
|
|
2344
|
+
let segKfs;
|
|
2345
|
+
if (loop.before) {
|
|
2346
|
+
segKfs = keyframes.slice(0, segCount + 1);
|
|
2347
|
+
} else {
|
|
2348
|
+
segKfs = keyframes.slice(totalIntervals - segCount);
|
|
2349
|
+
}
|
|
2350
|
+
const firstT = (_b = keyframes[0].t) != null ? _b : 0;
|
|
2351
|
+
const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
|
|
2352
|
+
let fillStart, fillEnd;
|
|
2353
|
+
if (loop.before) {
|
|
2354
|
+
fillStart = 0;
|
|
2355
|
+
fillEnd = firstT;
|
|
2356
|
+
} else {
|
|
2357
|
+
fillStart = lastT;
|
|
2358
|
+
fillEnd = duration;
|
|
2359
|
+
}
|
|
2360
|
+
const fillDuration = fillEnd - fillStart;
|
|
2361
|
+
if (fillDuration <= 0) return keyframes;
|
|
2362
|
+
const segStartT = (_d = segKfs[0].t) != null ? _d : 0;
|
|
2363
|
+
const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
|
|
2364
|
+
const segDuration = segEndT - segStartT;
|
|
2365
|
+
if (segDuration <= 0) return keyframes;
|
|
2366
|
+
const template = segKfs.map((kf) => ({
|
|
2367
|
+
relT: (kf.t - segStartT) / segDuration,
|
|
2368
|
+
v: kf.v,
|
|
2369
|
+
e: kf.e
|
|
2370
|
+
}));
|
|
2371
|
+
const fullReps = Math.floor(fillDuration / segDuration);
|
|
2372
|
+
const remainder = fillDuration - fullReps * segDuration;
|
|
2373
|
+
const partialFraction = remainder / segDuration;
|
|
2374
|
+
const looped = [];
|
|
2375
|
+
function appendRep(repStart, isReversed, partial) {
|
|
2376
|
+
let entries;
|
|
2377
|
+
if (isReversed) {
|
|
2378
|
+
entries = [];
|
|
2379
|
+
for (let i = template.length - 1; i >= 0; i--) {
|
|
2380
|
+
entries.push({
|
|
2381
|
+
relT: 1 - template[i].relT,
|
|
2382
|
+
v: template[i].v,
|
|
2383
|
+
// Easing for reversed transition: use reversed easing from the forward "from" keyframe
|
|
2384
|
+
e: i > 0 ? reverseEasing(template[i - 1].e) : void 0
|
|
2385
|
+
});
|
|
2386
|
+
}
|
|
2387
|
+
} else {
|
|
2388
|
+
entries = template;
|
|
2389
|
+
}
|
|
2390
|
+
const cutRelT = partial !== void 0 ? partial : 1;
|
|
2391
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2392
|
+
const entry = entries[i];
|
|
2393
|
+
if (entry.relT > cutRelT + 1e-9) {
|
|
2394
|
+
const prev = entries[i - 1];
|
|
2395
|
+
const intervalSpan = entry.relT - prev.relT;
|
|
2396
|
+
const localFrac = (cutRelT - prev.relT) / intervalSpan;
|
|
2397
|
+
const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
|
|
2398
|
+
const cutValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
|
|
2399
|
+
const { left: leftEasing } = splitEasing(prev.e, localFrac);
|
|
2400
|
+
if (looped.length > 0 && prev.relT <= cutRelT) {
|
|
2401
|
+
looped[looped.length - 1].e = leftEasing;
|
|
2402
|
+
}
|
|
2403
|
+
looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2406
|
+
looped.push({
|
|
2407
|
+
t: repStart + entry.relT * segDuration,
|
|
2408
|
+
v: entry.v,
|
|
2409
|
+
e: i < entries.length - 1 ? entry.e : void 0
|
|
2410
|
+
});
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
for (let rep = 0; rep < fullReps; rep++) {
|
|
2414
|
+
const distFromBoundary = loop.before ? fullReps - 1 - rep : rep;
|
|
2415
|
+
const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
|
|
2416
|
+
const repStart = fillStart + rep * segDuration;
|
|
2417
|
+
appendRep(repStart, isReversed);
|
|
2418
|
+
}
|
|
2419
|
+
if (partialFraction > 1e-9) {
|
|
2420
|
+
const isReversed = !!loop.alternate && fullReps % 2 === 0;
|
|
2421
|
+
const repStart = fillStart + fullReps * segDuration;
|
|
2422
|
+
appendRep(repStart, isReversed, partialFraction);
|
|
2423
|
+
}
|
|
2424
|
+
if (loop.before) {
|
|
2425
|
+
return [...looped, ...keyframes];
|
|
2426
|
+
} else {
|
|
2427
|
+
return [...keyframes, ...looped];
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
901
2430
|
function normalizeKeyframes(propName, propAnim, duration, defs) {
|
|
902
2431
|
var _a, _b, _c, _d, _e;
|
|
903
2432
|
const keyframes = propAnim.keyframes || propAnim.kfs || [];
|
|
@@ -922,6 +2451,11 @@ function normalizeKeyframes(propName, propAnim, duration, defs) {
|
|
|
922
2451
|
var _a2, _b2;
|
|
923
2452
|
return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
|
|
924
2453
|
});
|
|
2454
|
+
const loopRaw = propAnim.loop;
|
|
2455
|
+
const loop = loopRaw === true ? {} : loopRaw || void 0;
|
|
2456
|
+
if (loop && normalized.length >= 2) {
|
|
2457
|
+
return expandLoopKeyframes(propName, normalized, loop, duration);
|
|
2458
|
+
}
|
|
925
2459
|
return normalized;
|
|
926
2460
|
}
|
|
927
2461
|
function mergeAnimationDefinitions(animations) {
|
|
@@ -972,10 +2506,11 @@ function getNormalisedBindings(doc) {
|
|
|
972
2506
|
}
|
|
973
2507
|
}
|
|
974
2508
|
const processNode = (node) => {
|
|
975
|
-
|
|
2509
|
+
const inlineAnim = node.animate;
|
|
2510
|
+
if (inlineAnim && Object.keys(inlineAnim).length > 0) {
|
|
976
2511
|
const nodeId = node.id || generateElementId();
|
|
977
2512
|
node.id = nodeId;
|
|
978
|
-
const normalized = processAnimation(nodeId,
|
|
2513
|
+
const normalized = processAnimation(nodeId, inlineAnim);
|
|
979
2514
|
if (normalized) bindings.push(normalized);
|
|
980
2515
|
}
|
|
981
2516
|
if (node.children) {
|
|
@@ -1046,6 +2581,41 @@ function calcPropertyValue(propName, propAnim, progress) {
|
|
|
1046
2581
|
localProgress
|
|
1047
2582
|
).join(" ");
|
|
1048
2583
|
cssAttrName = propName;
|
|
2584
|
+
} else if (cssAttrName === "transform" && prevV !== null && typeof prevV === "object" && !Array.isArray(prevV)) {
|
|
2585
|
+
const partKeys = /* @__PURE__ */ new Set([
|
|
2586
|
+
...prevV ? Object.keys(prevV) : [],
|
|
2587
|
+
...nextV ? Object.keys(nextV) : []
|
|
2588
|
+
]);
|
|
2589
|
+
const partsResult = {};
|
|
2590
|
+
for (const partKey of partKeys) {
|
|
2591
|
+
const prevPart = prevV == null ? void 0 : prevV[partKey];
|
|
2592
|
+
const nextPart = nextV == null ? void 0 : nextV[partKey];
|
|
2593
|
+
if (partKey === "rotate") {
|
|
2594
|
+
partsResult.rotate = interpolateNum(+(prevPart != null ? prevPart : 0), +(nextPart != null ? nextPart : 0), localProgress);
|
|
2595
|
+
} else if (partKey === "translate" || partKey === "scale" || partKey === "origin") {
|
|
2596
|
+
const fallback = partKey === "scale" ? [1, 1] : [0, 0];
|
|
2597
|
+
const interp = interpolateVec(prevPart || fallback, nextPart || fallback, localProgress);
|
|
2598
|
+
partsResult[partKey] = interp;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
if (propAnimIsMotionPath(propAnim)) {
|
|
2602
|
+
const prevTr = prevV.translate;
|
|
2603
|
+
const nextTr = nextV.translate;
|
|
2604
|
+
if (Array.isArray(prevTr) && Array.isArray(nextTr)) {
|
|
2605
|
+
const sample = evaluateMotionPathSegment(
|
|
2606
|
+
prevKf,
|
|
2607
|
+
nextKf,
|
|
2608
|
+
[+prevTr[0], +prevTr[1]],
|
|
2609
|
+
[+nextTr[0], +nextTr[1]],
|
|
2610
|
+
localProgress,
|
|
2611
|
+
!!propAnim.autoOrient
|
|
2612
|
+
);
|
|
2613
|
+
partsResult.translate = [sample.translate[0], sample.translate[1]];
|
|
2614
|
+
if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
cssValue = composeTransformParts(partsResult, { withUnits: false });
|
|
2618
|
+
cssAttrName = "transform";
|
|
1049
2619
|
} else if (cssAttrName === "translate") {
|
|
1050
2620
|
const v = interpolateVec(
|
|
1051
2621
|
prevV || [0, 0],
|
|
@@ -1071,12 +2641,12 @@ function calcPropertyValue(propName, propAnim, progress) {
|
|
|
1071
2641
|
cssValue = "scale(" + v.join(",") + ")";
|
|
1072
2642
|
cssAttrName = "transform";
|
|
1073
2643
|
} else {
|
|
1074
|
-
const
|
|
2644
|
+
const num2 = interpolateNum(
|
|
1075
2645
|
+(prevV || 0),
|
|
1076
2646
|
+(nextV || 0),
|
|
1077
2647
|
localProgress
|
|
1078
2648
|
);
|
|
1079
|
-
cssValue =
|
|
2649
|
+
cssValue = num2;
|
|
1080
2650
|
}
|
|
1081
2651
|
if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
|
|
1082
2652
|
cssValue = cssValue * 100 + "%";
|
|
@@ -1356,41 +2926,91 @@ function createDomAdapter(rootElement) {
|
|
|
1356
2926
|
}
|
|
1357
2927
|
|
|
1358
2928
|
// src/PxAnimatorWebApi.ts
|
|
2929
|
+
function createCssKf(kf, t, propName, unsupportedSet) {
|
|
2930
|
+
var _a, _b;
|
|
2931
|
+
let value = (_a = kf.v) != null ? _a : kf.value;
|
|
2932
|
+
const e = (_b = kf.e) != null ? _b : kf.easing;
|
|
2933
|
+
const cssKf = {
|
|
2934
|
+
offset: t,
|
|
2935
|
+
easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
|
|
2936
|
+
};
|
|
2937
|
+
let cssValue;
|
|
2938
|
+
let cssKey = propName;
|
|
2939
|
+
if (COLOUR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
|
|
2940
|
+
cssValue = toRGBA(value);
|
|
2941
|
+
} else if (propName === "transform" && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
2942
|
+
cssValue = composeTransformParts(value, { withUnits: true });
|
|
2943
|
+
cssKey = "transform";
|
|
2944
|
+
} else if (TRANSFORM_FN_NAMES.has(propName)) {
|
|
2945
|
+
if (Array.isArray(value)) {
|
|
2946
|
+
if (propName === "translate") value = value.map((v) => v + "px");
|
|
2947
|
+
value = value.join(",");
|
|
2948
|
+
}
|
|
2949
|
+
if (propName === "rotate") value = value + "deg";
|
|
2950
|
+
cssValue = propName + "(" + value + ")";
|
|
2951
|
+
cssKey = "transform";
|
|
2952
|
+
} else {
|
|
2953
|
+
cssValue = "" + value;
|
|
2954
|
+
}
|
|
2955
|
+
if (!CSS.supports(cssKey, cssValue)) unsupportedSet.add(cssKey);
|
|
2956
|
+
cssKey = kebabToCamelCaseWord(cssKey);
|
|
2957
|
+
cssKf[cssKey] = cssValue;
|
|
2958
|
+
return cssKf;
|
|
2959
|
+
}
|
|
2960
|
+
function clipKeyframesToDuration(propName, keyframes, duration) {
|
|
2961
|
+
var _a, _b, _c, _d, _e;
|
|
2962
|
+
const result = [];
|
|
2963
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
2964
|
+
const kf = keyframes[i];
|
|
2965
|
+
const t = (_a = kf.t) != null ? _a : 0;
|
|
2966
|
+
if (t < 0) {
|
|
2967
|
+
const next = keyframes[i + 1];
|
|
2968
|
+
if (next && ((_b = next.t) != null ? _b : 0) >= 0) {
|
|
2969
|
+
const nextT = (_c = next.t) != null ? _c : 0;
|
|
2970
|
+
const localFrac = (0 - t) / (nextT - t);
|
|
2971
|
+
const easedFrac = kf.e ? cubicBezier(kf.e)(localFrac) : localFrac;
|
|
2972
|
+
const { right: rightEasing } = splitEasing(kf.e, localFrac);
|
|
2973
|
+
result.push({ t: 0, v: interpolateValue(propName, kf.v, next.v, easedFrac), e: rightEasing });
|
|
2974
|
+
}
|
|
2975
|
+
continue;
|
|
2976
|
+
}
|
|
2977
|
+
if (t > duration) {
|
|
2978
|
+
const prev = keyframes[i - 1];
|
|
2979
|
+
if (prev && ((_d = prev.t) != null ? _d : 0) <= duration) {
|
|
2980
|
+
const prevT = (_e = prev.t) != null ? _e : 0;
|
|
2981
|
+
const localFrac = (duration - prevT) / (t - prevT);
|
|
2982
|
+
const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
|
|
2983
|
+
const { left: leftEasing } = splitEasing(prev.e, localFrac);
|
|
2984
|
+
if (result.length > 0) result[result.length - 1] = __spreadProps(__spreadValues({}, result[result.length - 1]), { e: leftEasing });
|
|
2985
|
+
result.push({ t: duration, v: interpolateValue(propName, prev.v, kf.v, easedFrac), e: void 0 });
|
|
2986
|
+
}
|
|
2987
|
+
break;
|
|
2988
|
+
}
|
|
2989
|
+
result.push(kf);
|
|
2990
|
+
}
|
|
2991
|
+
return result;
|
|
2992
|
+
}
|
|
1359
2993
|
function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
|
|
1360
|
-
var _a
|
|
2994
|
+
var _a;
|
|
1361
2995
|
const result = /* @__PURE__ */ new Map();
|
|
1362
2996
|
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
1363
|
-
const
|
|
2997
|
+
const duration = config.duration || 1;
|
|
2998
|
+
const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.kfs || propAnim.keyframes || [], duration);
|
|
1364
2999
|
const cssKeyframes = [];
|
|
1365
|
-
for (
|
|
1366
|
-
|
|
1367
|
-
t = clamp(
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
offset: t,
|
|
1372
|
-
easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
|
|
1373
|
-
};
|
|
1374
|
-
let cssValue;
|
|
1375
|
-
let cssKey = propName;
|
|
1376
|
-
if (COLOUR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
|
|
1377
|
-
cssValue = toRGBA(value);
|
|
1378
|
-
} else if (TRANSFORM_FN_NAMES.has(propName)) {
|
|
1379
|
-
if (Array.isArray(value)) {
|
|
1380
|
-
if (propName === "translate") value = value.map((v) => v + "px");
|
|
1381
|
-
value = value.join(",");
|
|
1382
|
-
}
|
|
1383
|
-
if (propName === "rotate") value = value + "deg";
|
|
1384
|
-
cssValue = propName + "(" + value + ")";
|
|
1385
|
-
cssKey = "transform";
|
|
1386
|
-
} else {
|
|
1387
|
-
cssValue = "" + value;
|
|
3000
|
+
for (let i = 0; i < clippedKeyframes.length; i++) {
|
|
3001
|
+
const kf = clippedKeyframes[i];
|
|
3002
|
+
const t = clamp(((_a = kf.t) != null ? _a : 0) / duration, 0, 1);
|
|
3003
|
+
const cssKf = createCssKf(kf, t, propName, unsupportedSet);
|
|
3004
|
+
if (i === 0 && (cssKf.offset || 0) > 0) {
|
|
3005
|
+
cssKeyframes.push(__spreadProps(__spreadValues({}, cssKf), { offset: 0 }));
|
|
1388
3006
|
}
|
|
1389
|
-
if (!CSS.supports(cssKey, cssValue)) unsupportedSet.add(cssKey);
|
|
1390
|
-
cssKey = kebabToCamelCaseWord(cssKey);
|
|
1391
|
-
cssKf[cssKey] = cssValue;
|
|
1392
3007
|
cssKeyframes.push(cssKf);
|
|
1393
3008
|
}
|
|
3009
|
+
if (cssKeyframes.length > 0 && (cssKeyframes[cssKeyframes.length - 1].offset || 0) < 1) {
|
|
3010
|
+
cssKeyframes.push(__spreadProps(__spreadValues({}, cssKeyframes[cssKeyframes.length - 1]), {
|
|
3011
|
+
offset: 1
|
|
3012
|
+
}));
|
|
3013
|
+
}
|
|
1394
3014
|
if (cssKeyframes.length > 0) {
|
|
1395
3015
|
result.set(propName, cssKeyframes);
|
|
1396
3016
|
}
|
|
@@ -1398,6 +3018,7 @@ function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
|
|
|
1398
3018
|
return result;
|
|
1399
3019
|
}
|
|
1400
3020
|
function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs) {
|
|
3021
|
+
var _a;
|
|
1401
3022
|
const config = getAnimatorConfig(doc) || {};
|
|
1402
3023
|
const bindings = getNormalisedBindings(doc);
|
|
1403
3024
|
if (!rootElement) {
|
|
@@ -1430,29 +3051,33 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1430
3051
|
console.warn('createWebApiAnimator: No elements found for selector "' + selector + '"');
|
|
1431
3052
|
}
|
|
1432
3053
|
const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
|
|
3054
|
+
const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
|
|
3055
|
+
const seekPosition = config.delay && config.delay < 0 && config.duration ? -config.delay % config.duration : void 0;
|
|
3056
|
+
const effectOptions = {
|
|
3057
|
+
duration: config.duration,
|
|
3058
|
+
delay: positiveDelay,
|
|
3059
|
+
// Default to 'forwards' so elements hold their final state after the
|
|
3060
|
+
// animation ends — consistent with Lottie and other animation runtimes.
|
|
3061
|
+
// Without this, seeking to the last frame reverts elements to their
|
|
3062
|
+
// pre-animation state (the Web Animations API "after" phase with fill:'none').
|
|
3063
|
+
fill: (_a = config.fill) != null ? _a : "forwards",
|
|
3064
|
+
direction: config.direction,
|
|
3065
|
+
iterations
|
|
3066
|
+
};
|
|
1433
3067
|
for (let i = 0; i < elements.length; i++) {
|
|
1434
3068
|
const element = elements[i];
|
|
1435
|
-
const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
|
|
1436
|
-
const seekPosition = config.delay && config.delay < 0 && config.duration ? -config.delay % config.duration : void 0;
|
|
1437
|
-
const effectOptions = {
|
|
1438
|
-
duration: config.duration,
|
|
1439
|
-
delay: positiveDelay,
|
|
1440
|
-
fill: config.fill,
|
|
1441
|
-
direction: config.direction,
|
|
1442
|
-
iterations
|
|
1443
|
-
};
|
|
1444
3069
|
for (const [, keyframes] of keyframesMap) {
|
|
1445
3070
|
if (keyframes.length > 0) {
|
|
1446
3071
|
try {
|
|
1447
3072
|
const effect = new KeyframeEffect(element, keyframes, effectOptions);
|
|
1448
3073
|
const anim = new Animation(effect, document.timeline);
|
|
1449
3074
|
if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
|
|
1450
|
-
var
|
|
1451
|
-
return (
|
|
3075
|
+
var _a2;
|
|
3076
|
+
return (_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
1452
3077
|
};
|
|
1453
3078
|
if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
|
|
1454
|
-
var
|
|
1455
|
-
return (
|
|
3079
|
+
var _a2;
|
|
3080
|
+
return (_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
1456
3081
|
};
|
|
1457
3082
|
if (seekPosition) {
|
|
1458
3083
|
anim.currentTime = seekPosition;
|
|
@@ -1473,34 +3098,47 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1473
3098
|
"isReady": () => true,
|
|
1474
3099
|
"getRootElement": () => rootElement || null,
|
|
1475
3100
|
"isPlaying": () => {
|
|
1476
|
-
var
|
|
1477
|
-
return ((
|
|
3101
|
+
var _a2;
|
|
3102
|
+
return ((_a2 = animations[0]) == null ? void 0 : _a2.playState) === "running";
|
|
1478
3103
|
},
|
|
1479
3104
|
"play": () => {
|
|
1480
|
-
var
|
|
3105
|
+
var _a2;
|
|
1481
3106
|
animations.forEach((a) => a.play());
|
|
1482
|
-
(
|
|
3107
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
|
|
1483
3108
|
},
|
|
1484
3109
|
"pause": () => {
|
|
1485
|
-
var
|
|
3110
|
+
var _a2;
|
|
1486
3111
|
animations.forEach((a) => a.pause());
|
|
1487
|
-
(
|
|
3112
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
|
|
1488
3113
|
},
|
|
1489
3114
|
"cancel": () => {
|
|
1490
|
-
var
|
|
3115
|
+
var _a2;
|
|
1491
3116
|
animations.forEach((a) => a.cancel());
|
|
1492
|
-
(
|
|
3117
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
|
|
1493
3118
|
},
|
|
1494
3119
|
"finish": () => {
|
|
1495
|
-
|
|
3120
|
+
var _a2;
|
|
3121
|
+
for (const a of animations) {
|
|
3122
|
+
try {
|
|
3123
|
+
if (((_a2 = a.effect) == null ? void 0 : _a2.getTiming().iterations) === Infinity) {
|
|
3124
|
+
a.effect.updateTiming({ iterations: 1 });
|
|
3125
|
+
a.finish();
|
|
3126
|
+
a.effect.updateTiming({ iterations: Infinity });
|
|
3127
|
+
} else {
|
|
3128
|
+
a.finish();
|
|
3129
|
+
}
|
|
3130
|
+
} catch (e) {
|
|
3131
|
+
a.cancel();
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
1496
3134
|
},
|
|
1497
3135
|
"setPlaybackRate": (rate) => {
|
|
1498
3136
|
animations.forEach((a) => a.playbackRate = rate);
|
|
1499
3137
|
return api;
|
|
1500
3138
|
},
|
|
1501
3139
|
"getCurrentTime": () => {
|
|
1502
|
-
var
|
|
1503
|
-
const res = (_b = (
|
|
3140
|
+
var _a2, _b;
|
|
3141
|
+
const res = (_b = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b : null;
|
|
1504
3142
|
return res !== null ? +res : null;
|
|
1505
3143
|
},
|
|
1506
3144
|
"setCurrentTime": (time) => {
|
|
@@ -1557,6 +3195,7 @@ function deepClone(value) {
|
|
|
1557
3195
|
return cloned;
|
|
1558
3196
|
}
|
|
1559
3197
|
function generateNewIds(doc) {
|
|
3198
|
+
var _a, _b;
|
|
1560
3199
|
const cloned = deepClone(doc);
|
|
1561
3200
|
const idMap = /* @__PURE__ */ new Map();
|
|
1562
3201
|
const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
|
|
@@ -1582,6 +3221,8 @@ function generateNewIds(doc) {
|
|
|
1582
3221
|
const newId = generateUniqueId();
|
|
1583
3222
|
idMap.set(oldId, newId);
|
|
1584
3223
|
node.id = newId;
|
|
3224
|
+
} else if (node.animate) {
|
|
3225
|
+
node.id = generateUniqueId();
|
|
1585
3226
|
}
|
|
1586
3227
|
if (Array.isArray(node.children)) {
|
|
1587
3228
|
for (const child of node.children) {
|
|
@@ -1623,23 +3264,21 @@ function generateNewIds(doc) {
|
|
|
1623
3264
|
value[styleProp] = replaceUrlRefs(styleValue, idMap);
|
|
1624
3265
|
}
|
|
1625
3266
|
}
|
|
1626
|
-
} else if (typeof value === "object" && value !== null
|
|
3267
|
+
} else if (typeof value === "object" && value !== null) {
|
|
1627
3268
|
updateRefs(value);
|
|
1628
3269
|
}
|
|
1629
3270
|
}
|
|
1630
3271
|
}
|
|
1631
3272
|
collectIds(cloned);
|
|
1632
3273
|
updateRefs(cloned);
|
|
1633
|
-
const
|
|
1634
|
-
if (
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
binding.id = newId;
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
3274
|
+
const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animate;
|
|
3275
|
+
if (docAnimate && typeof docAnimate === "object") {
|
|
3276
|
+
const updatedAnimate = {};
|
|
3277
|
+
for (const [id, anim] of Object.entries(docAnimate)) {
|
|
3278
|
+
const newId = (_b = idMap.get(id)) != null ? _b : id;
|
|
3279
|
+
updatedAnimate[newId] = anim;
|
|
1642
3280
|
}
|
|
3281
|
+
cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { animate: updatedAnimate });
|
|
1643
3282
|
}
|
|
1644
3283
|
return cloned;
|
|
1645
3284
|
}
|
|
@@ -1650,6 +3289,9 @@ function replaceUrlRefs(value, idMap) {
|
|
|
1650
3289
|
});
|
|
1651
3290
|
}
|
|
1652
3291
|
function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
|
|
3292
|
+
const effectsWarnings = validateNodeEffects(doc);
|
|
3293
|
+
for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
|
|
3294
|
+
doc = applyPlayerEffects(doc).root;
|
|
1653
3295
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
1654
3296
|
animatorConfig.debug = true;
|
|
1655
3297
|
let rootElement = null;
|
|
@@ -1665,14 +3307,22 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
|
|
|
1665
3307
|
}
|
|
1666
3308
|
return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
|
|
1667
3309
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
3310
|
+
var PX_ANIMATOR_DATA_KEY = "data";
|
|
3311
|
+
function createAnimator(options) {
|
|
3312
|
+
const { src, data, adapter, callbacks, container } = options;
|
|
3313
|
+
if (data !== void 0 && src !== void 0) {
|
|
3314
|
+
throw new Error("createAnimator: provide either `src` or `data`, not both");
|
|
3315
|
+
}
|
|
3316
|
+
if (data === void 0 && src === void 0) {
|
|
3317
|
+
throw new Error("createAnimator: either `src` or `data` is required");
|
|
3318
|
+
}
|
|
3319
|
+
if (data !== void 0) {
|
|
3320
|
+
return createAnimatorImpl(data, adapter, callbacks, container);
|
|
1671
3321
|
}
|
|
1672
3322
|
let animator = null;
|
|
1673
|
-
fetch(
|
|
3323
|
+
fetch(src).then((res) => res.json()).then((json) => {
|
|
1674
3324
|
if (isPxElementFileFormat(json)) {
|
|
1675
|
-
animator = createAnimatorImpl(json, adapter, callbacks,
|
|
3325
|
+
animator = createAnimatorImpl(json, adapter, callbacks, container);
|
|
1676
3326
|
} else {
|
|
1677
3327
|
console.error("Invalid animation document format");
|
|
1678
3328
|
}
|
|
@@ -1712,7 +3362,7 @@ function loadTagAnimators() {
|
|
|
1712
3362
|
if (!element[PX_ANIM_ATTR_NAME]) {
|
|
1713
3363
|
const src = element.getAttribute(PX_ANIM_SRC_ATTR_NAME);
|
|
1714
3364
|
if (src) {
|
|
1715
|
-
element[PX_ANIM_ATTR_NAME] = createAnimator(src,
|
|
3365
|
+
element[PX_ANIM_ATTR_NAME] = createAnimator({ src, container: element });
|
|
1716
3366
|
}
|
|
1717
3367
|
}
|
|
1718
3368
|
}
|
|
@@ -1722,20 +3372,259 @@ if (typeof window !== "undefined") {
|
|
|
1722
3372
|
window["createAnimator"] = createAnimator;
|
|
1723
3373
|
window["setupAnimationTriggers"] = setupAnimationTriggers;
|
|
1724
3374
|
}
|
|
3375
|
+
|
|
3376
|
+
// src/effects/PlayerEffectsUtil.visualModel.ts
|
|
3377
|
+
var IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
3378
|
+
function mul(m, n) {
|
|
3379
|
+
return [
|
|
3380
|
+
m[0] * n[0] + m[2] * n[1],
|
|
3381
|
+
m[1] * n[0] + m[3] * n[1],
|
|
3382
|
+
m[0] * n[2] + m[2] * n[3],
|
|
3383
|
+
m[1] * n[2] + m[3] * n[3],
|
|
3384
|
+
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
3385
|
+
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
3386
|
+
];
|
|
3387
|
+
}
|
|
3388
|
+
var translateM = (x, y) => [1, 0, 0, 1, x, y];
|
|
3389
|
+
var scaleM = (sx, sy) => [sx, 0, 0, sy, 0, 0];
|
|
3390
|
+
function rotateM(deg) {
|
|
3391
|
+
const r = deg * Math.PI / 180;
|
|
3392
|
+
return [Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0];
|
|
3393
|
+
}
|
|
3394
|
+
var skewXM = (deg) => [1, 0, Math.tan(deg * Math.PI / 180), 1, 0, 0];
|
|
3395
|
+
var skewYM = (deg) => [1, Math.tan(deg * Math.PI / 180), 0, 1, 0, 0];
|
|
3396
|
+
function parseTransformString(s) {
|
|
3397
|
+
let m = IDENTITY;
|
|
3398
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
3399
|
+
let hit;
|
|
3400
|
+
while (hit = re.exec(s)) {
|
|
3401
|
+
const fn = hit[1];
|
|
3402
|
+
const a = hit[2].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
3403
|
+
if (fn === "translate") m = mul(m, translateM(a[0] || 0, a[1] || 0));
|
|
3404
|
+
else if (fn === "scale") m = mul(m, scaleM(a[0], a.length > 1 ? a[1] : a[0]));
|
|
3405
|
+
else if (fn === "rotate") m = mul(m, rotateM(a[0]));
|
|
3406
|
+
else if (fn === "skewX") m = mul(m, skewXM(a[0]));
|
|
3407
|
+
else if (fn === "skewY") m = mul(m, skewYM(a[0]));
|
|
3408
|
+
else if (fn === "matrix") m = mul(m, [a[0], a[1], a[2], a[3], a[4], a[5]]);
|
|
3409
|
+
}
|
|
3410
|
+
return m;
|
|
3411
|
+
}
|
|
3412
|
+
function partsToMatrix(p) {
|
|
3413
|
+
let m = IDENTITY;
|
|
3414
|
+
if (p.translate) m = mul(m, translateM(p.translate[0], p.translate[1]));
|
|
3415
|
+
const pivot = p.origin && (p.rotate !== void 0 || p.scale);
|
|
3416
|
+
if (pivot) m = mul(m, translateM(p.origin[0], p.origin[1]));
|
|
3417
|
+
if (p.rotate !== void 0) m = mul(m, rotateM(p.rotate));
|
|
3418
|
+
if (p.scale) m = mul(m, scaleM(p.scale[0], p.scale[1]));
|
|
3419
|
+
if (pivot) m = mul(m, translateM(-p.origin[0], -p.origin[1]));
|
|
3420
|
+
return m;
|
|
3421
|
+
}
|
|
3422
|
+
function lerp(a, b, f) {
|
|
3423
|
+
return a + (b - a) * f;
|
|
3424
|
+
}
|
|
3425
|
+
function interpParts(kfs, t) {
|
|
3426
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3427
|
+
if (!kfs.length) return {};
|
|
3428
|
+
if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
|
|
3429
|
+
if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
|
|
3430
|
+
let i = 0;
|
|
3431
|
+
while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
|
|
3432
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
3433
|
+
const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
|
|
3434
|
+
const va = a.value || {}, vb = b.value || {};
|
|
3435
|
+
const out = {};
|
|
3436
|
+
if (va.translate && vb.translate) out.translate = [lerp(va.translate[0], vb.translate[0], f), lerp(va.translate[1], vb.translate[1], f)];
|
|
3437
|
+
else out.translate = va.translate || vb.translate;
|
|
3438
|
+
if (va.rotate !== void 0 && vb.rotate !== void 0) out.rotate = lerp(va.rotate, vb.rotate, f);
|
|
3439
|
+
else out.rotate = (_g = va.rotate) != null ? _g : vb.rotate;
|
|
3440
|
+
if (va.scale && vb.scale) out.scale = [lerp(va.scale[0], vb.scale[0], f), lerp(va.scale[1], vb.scale[1], f)];
|
|
3441
|
+
else out.scale = va.scale || vb.scale;
|
|
3442
|
+
out.origin = va.origin || vb.origin;
|
|
3443
|
+
return out;
|
|
3444
|
+
}
|
|
3445
|
+
function evalTransformValue(v, t) {
|
|
3446
|
+
if (v === void 0 || v === null) return IDENTITY;
|
|
3447
|
+
if (typeof v === "string") return parseTransformString(v);
|
|
3448
|
+
if (v.keyframes) return partsToMatrix(interpParts(v.keyframes, t));
|
|
3449
|
+
if (v.value) return partsToMatrix(v.value);
|
|
3450
|
+
return IDENTITY;
|
|
3451
|
+
}
|
|
3452
|
+
function nodeMatrix(node, t) {
|
|
3453
|
+
if (node.animate && node.animate.transform) return evalTransformValue(node.animate.transform, t);
|
|
3454
|
+
if (node.transform !== void 0) return evalTransformValue(node.transform, t);
|
|
3455
|
+
return IDENTITY;
|
|
3456
|
+
}
|
|
3457
|
+
function evalScalar(animated, staticVal, fallback, t) {
|
|
3458
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3459
|
+
if (animated && animated.keyframes && animated.keyframes.length) {
|
|
3460
|
+
const kfs = animated.keyframes;
|
|
3461
|
+
if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
|
|
3462
|
+
if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
|
|
3463
|
+
let i = 0;
|
|
3464
|
+
while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
|
|
3465
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
3466
|
+
const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
|
|
3467
|
+
return lerp(a.value, b.value, f);
|
|
3468
|
+
}
|
|
3469
|
+
return staticVal !== void 0 ? Number(staticVal) : fallback;
|
|
3470
|
+
}
|
|
3471
|
+
var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
|
|
3472
|
+
var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
|
|
3473
|
+
function buildIdMap(node, map) {
|
|
3474
|
+
var _a;
|
|
3475
|
+
if (typeof node.id === "string") map.set(node.id, node);
|
|
3476
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap(c, map));
|
|
3477
|
+
}
|
|
3478
|
+
function num(v) {
|
|
3479
|
+
return v === void 0 || v === null ? 0 : Number(v);
|
|
3480
|
+
}
|
|
3481
|
+
function round(n) {
|
|
3482
|
+
return Math.round(n * 100) / 100 + 0;
|
|
3483
|
+
}
|
|
3484
|
+
function geomKey(node) {
|
|
3485
|
+
var _a;
|
|
3486
|
+
switch (node.type) {
|
|
3487
|
+
case "rect":
|
|
3488
|
+
return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
|
|
3489
|
+
case "ellipse":
|
|
3490
|
+
return num(node.rx) + "," + num(node.ry) + "," + num(node.cx) + "," + num(node.cy);
|
|
3491
|
+
case "circle":
|
|
3492
|
+
return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
|
|
3493
|
+
case "path":
|
|
3494
|
+
return String((_a = node.d) != null ? _a : "");
|
|
3495
|
+
default:
|
|
3496
|
+
return "";
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
function describePrimitive(node, m, t) {
|
|
3500
|
+
var _a, _b, _c, _d, _e;
|
|
3501
|
+
const fill = (_a = node.fill) != null ? _a : "";
|
|
3502
|
+
const stroke = (_b = node.stroke) != null ? _b : "";
|
|
3503
|
+
const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
|
|
3504
|
+
const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
|
|
3505
|
+
const masked = node.mask ? 1 : 0;
|
|
3506
|
+
const mat = m.map(round).join(",");
|
|
3507
|
+
return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
|
|
3508
|
+
}
|
|
3509
|
+
function flatten(node, parent, t, idMap, out) {
|
|
3510
|
+
var _a;
|
|
3511
|
+
const type = node.type || "";
|
|
3512
|
+
if (SKIP_TYPES.has(type)) return;
|
|
3513
|
+
const m = mul(parent, nodeMatrix(node, t));
|
|
3514
|
+
if (type === "use") {
|
|
3515
|
+
const targetId = typeof node.href === "string" ? node.href.replace(/^#/, "") : "";
|
|
3516
|
+
const target = idMap.get(targetId);
|
|
3517
|
+
const useM = mul(m, translateM(num(node.x), num(node.y)));
|
|
3518
|
+
if (target) flatten(target, useM, t, idMap, out);
|
|
3519
|
+
else out.push("UNRESOLVED_USE:#" + targetId);
|
|
3520
|
+
return;
|
|
3521
|
+
}
|
|
3522
|
+
if (CONTAINER_TYPES.has(type)) {
|
|
3523
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
|
|
3524
|
+
return;
|
|
3525
|
+
}
|
|
3526
|
+
out.push(describePrimitive(node, m, t));
|
|
3527
|
+
}
|
|
3528
|
+
function collectSampleTimes(node, into) {
|
|
3529
|
+
var _a;
|
|
3530
|
+
into.add(0);
|
|
3531
|
+
const scanAnim = (anim) => {
|
|
3532
|
+
var _a2;
|
|
3533
|
+
if (!anim || typeof anim !== "object") return;
|
|
3534
|
+
for (const key of Object.keys(anim)) {
|
|
3535
|
+
const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
|
|
3536
|
+
if (Array.isArray(kfs)) kfs.forEach((kf) => {
|
|
3537
|
+
var _a3;
|
|
3538
|
+
return into.add((_a3 = kf.time) != null ? _a3 : 0);
|
|
3539
|
+
});
|
|
3540
|
+
}
|
|
3541
|
+
};
|
|
3542
|
+
scanAnim(node.animate);
|
|
3543
|
+
if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
|
|
3544
|
+
node.transform.keyframes.forEach((kf) => {
|
|
3545
|
+
var _a2;
|
|
3546
|
+
return into.add((_a2 = kf.time) != null ? _a2 : 0);
|
|
3547
|
+
});
|
|
3548
|
+
}
|
|
3549
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
|
|
3550
|
+
}
|
|
3551
|
+
function visualModelAt(root, t) {
|
|
3552
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
3553
|
+
buildIdMap(root, idMap);
|
|
3554
|
+
const out = [];
|
|
3555
|
+
flatten(root, IDENTITY, t, idMap, out);
|
|
3556
|
+
return out.sort();
|
|
3557
|
+
}
|
|
3558
|
+
function diffInEffect(a, b) {
|
|
3559
|
+
const times = /* @__PURE__ */ new Set();
|
|
3560
|
+
collectSampleTimes(a, times);
|
|
3561
|
+
collectSampleTimes(b, times);
|
|
3562
|
+
const diffs = [];
|
|
3563
|
+
for (const t of Array.from(times).sort((x, y) => x - y)) {
|
|
3564
|
+
const ma = visualModelAt(a, t);
|
|
3565
|
+
const mb = visualModelAt(b, t);
|
|
3566
|
+
const onlyInA = subtractMultiset(ma, mb);
|
|
3567
|
+
const onlyInB = subtractMultiset(mb, ma);
|
|
3568
|
+
if (onlyInA.length || onlyInB.length) diffs.push({ time: t, onlyInA, onlyInB });
|
|
3569
|
+
}
|
|
3570
|
+
return diffs;
|
|
3571
|
+
}
|
|
3572
|
+
function subtractMultiset(a, b) {
|
|
3573
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3574
|
+
for (const x of b) counts.set(x, (counts.get(x) || 0) + 1);
|
|
3575
|
+
const extra = [];
|
|
3576
|
+
for (const x of a) {
|
|
3577
|
+
const c = counts.get(x) || 0;
|
|
3578
|
+
if (c > 0) counts.set(x, c - 1);
|
|
3579
|
+
else extra.push(x);
|
|
3580
|
+
}
|
|
3581
|
+
return extra;
|
|
3582
|
+
}
|
|
1725
3583
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1726
3584
|
0 && (module.exports = {
|
|
1727
3585
|
COLOUR_ATTR_NAMES,
|
|
3586
|
+
PX_ANIMATOR_DATA_KEY,
|
|
1728
3587
|
PX_ANIM_ATTR_NAME,
|
|
1729
3588
|
PX_ANIM_SRC_ATTR_NAME,
|
|
3589
|
+
PX_TRANSFORM_PART_KEYS,
|
|
3590
|
+
PxAnimatedSvgDocumentSchema,
|
|
3591
|
+
PxAnimationDefinitionSchema,
|
|
3592
|
+
PxAnimatorConfigSchema,
|
|
3593
|
+
PxAttrValueSchema,
|
|
3594
|
+
PxBezierPathSchema,
|
|
3595
|
+
PxBindingSchema,
|
|
3596
|
+
PxDefsSchema,
|
|
3597
|
+
PxEasingOrRefSchema,
|
|
3598
|
+
PxEffectsSchema,
|
|
3599
|
+
PxElementAnimationSchema,
|
|
3600
|
+
PxKeyframeSchema,
|
|
3601
|
+
PxLoopSchema,
|
|
3602
|
+
PxMaskedByEffectSchema,
|
|
3603
|
+
PxNodeBase,
|
|
3604
|
+
PxNodeSchema,
|
|
3605
|
+
PxPropertyAnimationSchema,
|
|
3606
|
+
PxRefEffectSchema,
|
|
3607
|
+
PxRepeaterEffectSchema,
|
|
3608
|
+
PxRetimeEffectSchema,
|
|
3609
|
+
PxSvgNodeExtra,
|
|
3610
|
+
PxTransformPartsSchema,
|
|
3611
|
+
PxTransformValueSchema,
|
|
3612
|
+
PxTransformationEffectSchema,
|
|
3613
|
+
PxTriggerSchema,
|
|
3614
|
+
PxTrimPathEffectSchema,
|
|
1730
3615
|
STYLE_ATTR_NAMES,
|
|
1731
3616
|
TRANSFORM_FN_NAMES,
|
|
3617
|
+
applyPlayerEffects,
|
|
1732
3618
|
calcAnimationValues,
|
|
1733
3619
|
camelCaseToKebabWordIfNeeded,
|
|
3620
|
+
collectSampleTimes,
|
|
1734
3621
|
createAnimator,
|
|
1735
3622
|
createAnimatorImpl,
|
|
1736
3623
|
createBasicFrameLoopAnimator,
|
|
1737
3624
|
createFrameLoopAnimator,
|
|
1738
3625
|
createWebApiAnimator,
|
|
3626
|
+
describeSchema,
|
|
3627
|
+
diffInEffect,
|
|
1739
3628
|
generateNewIds,
|
|
1740
3629
|
getAnimatorConfig,
|
|
1741
3630
|
getBindings,
|
|
@@ -1746,8 +3635,12 @@ if (typeof window !== "undefined") {
|
|
|
1746
3635
|
isPxElementFileFormatDeep,
|
|
1747
3636
|
loadTagAnimators,
|
|
1748
3637
|
normalizeDocument,
|
|
3638
|
+
px,
|
|
1749
3639
|
renderNode,
|
|
3640
|
+
schemaKeys,
|
|
1750
3641
|
setupAnimationTriggers,
|
|
1751
|
-
toRGBA
|
|
3642
|
+
toRGBA,
|
|
3643
|
+
validateNodeEffects,
|
|
3644
|
+
visualModelAt
|
|
1752
3645
|
});
|
|
1753
3646
|
//# sourceMappingURL=index.cjs.map
|