@pixodesk/svg-animator-web 1.0.16 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +266 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -53
- package/dist/index.d.ts +65 -53
- package/dist/index.js +265 -76
- 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 +265 -76
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ function readAnimatable(raw) {
|
|
|
45
45
|
if (typeof raw === "object") {
|
|
46
46
|
const obj = raw;
|
|
47
47
|
if (obj.keyframes) {
|
|
48
|
-
return { kind: "animated" /* Animated */, keyframes: obj.keyframes, autoOrient: obj.autoOrient };
|
|
48
|
+
return { kind: "animated" /* Animated */, keyframes: obj.keyframes, autoOrient: obj.autoOrient, loop: obj.loop };
|
|
49
49
|
}
|
|
50
50
|
if (obj.value !== void 0) return { kind: "static" /* Static */, value: obj.value };
|
|
51
51
|
}
|
|
@@ -135,6 +135,7 @@ function wrapTransformPart(inner, part, raw, ctx) {
|
|
|
135
135
|
if (v.kind === "animated" /* Animated */) {
|
|
136
136
|
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
|
|
137
137
|
if (v.autoOrient) animTr.autoOrient = true;
|
|
138
|
+
if (v.loop !== void 0) animTr.loop = v.loop;
|
|
138
139
|
return {
|
|
139
140
|
type: "g",
|
|
140
141
|
animate: { transform: animTr },
|
|
@@ -153,9 +154,11 @@ function wrapOrigin(inner, raw, invert) {
|
|
|
153
154
|
return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
|
|
154
155
|
}
|
|
155
156
|
if (v.kind === "animated" /* Animated */) {
|
|
157
|
+
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) };
|
|
158
|
+
if (v.loop !== void 0) animTr.loop = v.loop;
|
|
156
159
|
return {
|
|
157
160
|
type: "g",
|
|
158
|
-
animate: { transform:
|
|
161
|
+
animate: { transform: animTr },
|
|
159
162
|
children: [inner]
|
|
160
163
|
};
|
|
161
164
|
}
|
|
@@ -165,8 +168,8 @@ function wrapOrigin(inner, raw, invert) {
|
|
|
165
168
|
// src/effects/contentRefSplit.ts
|
|
166
169
|
function identifyContentRefTargets(node, ctx, allocator) {
|
|
167
170
|
var _a, _b, _c;
|
|
168
|
-
if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.
|
|
169
|
-
const baseId = node.effects.
|
|
171
|
+
if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
|
|
172
|
+
const baseId = node.effects.clone.baseId;
|
|
170
173
|
if (typeof baseId === "string" && baseId && !ctx.contentRefInnerIds.has(baseId)) {
|
|
171
174
|
ctx.contentRefInnerIds.set(baseId, allocator(baseId));
|
|
172
175
|
}
|
|
@@ -214,6 +217,8 @@ function liftBodyTranslate(node, transformation) {
|
|
|
214
217
|
});
|
|
215
218
|
const outerAnimTr = { keyframes: outerKfs };
|
|
216
219
|
if (animTr.autoOrient) outerAnimTr.autoOrient = true;
|
|
220
|
+
const srcLoop = animTr.loop;
|
|
221
|
+
if (srcLoop !== void 0) outerAnimTr.loop = srcLoop;
|
|
217
222
|
out.animate = { transform: outerAnimTr };
|
|
218
223
|
const innerHasPivotedPart = kfs.some((kf) => {
|
|
219
224
|
const v = kf.value || {};
|
|
@@ -235,7 +240,9 @@ function liftBodyTranslate(node, transformation) {
|
|
|
235
240
|
delete node.animate.transform;
|
|
236
241
|
if (node.animate && Object.keys(node.animate).length === 0) delete node.animate;
|
|
237
242
|
} else {
|
|
238
|
-
|
|
243
|
+
const innerAnimTr = { keyframes: innerKfs };
|
|
244
|
+
if (srcLoop !== void 0) innerAnimTr.loop = srcLoop;
|
|
245
|
+
node.animate.transform = innerAnimTr;
|
|
239
246
|
}
|
|
240
247
|
didLiftAnimate = true;
|
|
241
248
|
}
|
|
@@ -975,9 +982,10 @@ var PxRetimeEffectSchema = implementsInterface()(px.object({
|
|
|
975
982
|
stretch: px.number().optional(),
|
|
976
983
|
timeCrop: px.tuple([px.number(), px.number()]).optional()
|
|
977
984
|
}));
|
|
978
|
-
var
|
|
985
|
+
var PxCloneEffectSchema = implementsInterface()(px.object({
|
|
986
|
+
type: px.string().optional(),
|
|
979
987
|
baseId: px.string().optional(),
|
|
980
|
-
|
|
988
|
+
retime: PxRetimeEffectSchema.optional()
|
|
981
989
|
}));
|
|
982
990
|
var PxGradientUnits = {
|
|
983
991
|
userSpaceOnUse: "userSpaceOnUse",
|
|
@@ -1027,9 +1035,8 @@ var PxEffectsSchema = implementsInterface()(px.object({
|
|
|
1027
1035
|
repeater: PxRepeaterEffectSchema.optional(),
|
|
1028
1036
|
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
1029
1037
|
trimPath: PxTrimPathEffectSchema.optional(),
|
|
1030
|
-
|
|
1038
|
+
clone: PxCloneEffectSchema.optional(),
|
|
1031
1039
|
isCombinedShape: px.boolean().optional(),
|
|
1032
|
-
ref: PxRefEffectSchema.optional(),
|
|
1033
1040
|
fillGradient: PxFillGradientEffectSchema.optional(),
|
|
1034
1041
|
strokeGradient: PxStrokeGradientEffectSchema.optional(),
|
|
1035
1042
|
textAlongPath: PxTextAlongPathEffectSchema.optional()
|
|
@@ -1257,6 +1264,7 @@ function buildStopChildren(stops, ctx) {
|
|
|
1257
1264
|
const animBlock = stops;
|
|
1258
1265
|
const kfs = animBlock.keyframes;
|
|
1259
1266
|
if (!Array.isArray(kfs) || !kfs.length) return [];
|
|
1267
|
+
const loopFromSource = animBlock.loop;
|
|
1260
1268
|
let stopCount = 0;
|
|
1261
1269
|
for (const kf of kfs) {
|
|
1262
1270
|
const v = (_a = kf.value) != null ? _a : kf.v;
|
|
@@ -1269,7 +1277,7 @@ function buildStopChildren(stops, ctx) {
|
|
|
1269
1277
|
const s = (_d = (_c = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _c : prevDefinedStop(kfs, 0, i)) != null ? _d : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
|
|
1270
1278
|
baselineStops.push({ offset: s.offset, color: s.color });
|
|
1271
1279
|
}
|
|
1272
|
-
return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx));
|
|
1280
|
+
return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
|
|
1273
1281
|
}
|
|
1274
1282
|
function staticStopNode(s) {
|
|
1275
1283
|
return {
|
|
@@ -1278,7 +1286,7 @@ function staticStopNode(s) {
|
|
|
1278
1286
|
stopColor: s.color
|
|
1279
1287
|
};
|
|
1280
1288
|
}
|
|
1281
|
-
function animatedStopNode(baseline, kfs, stopIdx, _ctx) {
|
|
1289
|
+
function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
|
|
1282
1290
|
var _a, _b, _c, _d, _e;
|
|
1283
1291
|
const colorKfs = [];
|
|
1284
1292
|
const offsetKfs = [];
|
|
@@ -1303,8 +1311,14 @@ function animatedStopNode(baseline, kfs, stopIdx, _ctx) {
|
|
|
1303
1311
|
stopColor: baseline.color
|
|
1304
1312
|
};
|
|
1305
1313
|
const animate = {};
|
|
1306
|
-
if (colorKfs.length)
|
|
1307
|
-
|
|
1314
|
+
if (colorKfs.length) {
|
|
1315
|
+
animate.stopColor = { keyframes: colorKfs };
|
|
1316
|
+
if (loop !== void 0) animate.stopColor.loop = loop;
|
|
1317
|
+
}
|
|
1318
|
+
if (offsetVaries && offsetKfs.length) {
|
|
1319
|
+
animate.offset = { keyframes: offsetKfs };
|
|
1320
|
+
if (loop !== void 0) animate.offset.loop = loop;
|
|
1321
|
+
}
|
|
1308
1322
|
if (Object.keys(animate).length) stop.animate = animate;
|
|
1309
1323
|
return stop;
|
|
1310
1324
|
}
|
|
@@ -1369,9 +1383,11 @@ function wrapInversePart(inner, part, raw, origin, ctx) {
|
|
|
1369
1383
|
return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
|
|
1370
1384
|
}
|
|
1371
1385
|
if (v.kind === "animated" /* Animated */) {
|
|
1386
|
+
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin))) };
|
|
1387
|
+
if (v.loop !== void 0) animTr.loop = v.loop;
|
|
1372
1388
|
return {
|
|
1373
1389
|
type: "g",
|
|
1374
|
-
animate: { transform:
|
|
1390
|
+
animate: { transform: animTr },
|
|
1375
1391
|
children: [inner]
|
|
1376
1392
|
};
|
|
1377
1393
|
}
|
|
@@ -1408,10 +1424,16 @@ function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
|
|
|
1408
1424
|
scaleKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
|
|
1409
1425
|
}
|
|
1410
1426
|
}
|
|
1427
|
+
const srcLoop = animTr == null ? void 0 : animTr.loop;
|
|
1428
|
+
const withLoop = (kfs2) => {
|
|
1429
|
+
const block = { keyframes: kfs2 };
|
|
1430
|
+
if (srcLoop !== void 0) block.loop = srcLoop;
|
|
1431
|
+
return block;
|
|
1432
|
+
};
|
|
1411
1433
|
let n = inner;
|
|
1412
|
-
if (translateKfs.length) n = { type: "g", animate: { transform:
|
|
1413
|
-
if (rotateKfs.length) n = { type: "g", animate: { transform:
|
|
1414
|
-
if (scaleKfs.length) n = { type: "g", animate: { transform:
|
|
1434
|
+
if (translateKfs.length) n = { type: "g", animate: { transform: withLoop(translateKfs) }, children: [n] };
|
|
1435
|
+
if (rotateKfs.length) n = { type: "g", animate: { transform: withLoop(rotateKfs) }, children: [n] };
|
|
1436
|
+
if (scaleKfs.length) n = { type: "g", animate: { transform: withLoop(scaleKfs) }, children: [n] };
|
|
1415
1437
|
return n;
|
|
1416
1438
|
}
|
|
1417
1439
|
function nodeHasBodyTransform(node) {
|
|
@@ -1645,16 +1667,18 @@ function parseTranslateOnlyFromString(s, ctx) {
|
|
|
1645
1667
|
|
|
1646
1668
|
// src/effects/refEffect.ts
|
|
1647
1669
|
var CONTENT_SUBREF = "content";
|
|
1648
|
-
function
|
|
1649
|
-
if (
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
const targetId = ref.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
|
|
1655
|
-
node.href = "#" + targetId;
|
|
1656
|
-
}
|
|
1670
|
+
function applyRefHref(node, clone2, ctx) {
|
|
1671
|
+
if (!clone2) return;
|
|
1672
|
+
const baseId = clone2.baseId;
|
|
1673
|
+
if (!baseId) {
|
|
1674
|
+
if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing baseId");
|
|
1675
|
+
return;
|
|
1657
1676
|
}
|
|
1677
|
+
const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
|
|
1678
|
+
node.href = "#" + targetId;
|
|
1679
|
+
}
|
|
1680
|
+
function applyRefAndTransformationEffect(node, clone2, transformation, ctx) {
|
|
1681
|
+
applyRefHref(node, clone2, ctx);
|
|
1658
1682
|
return applyTransformationEffect(node, transformation, ctx);
|
|
1659
1683
|
}
|
|
1660
1684
|
|
|
@@ -1765,22 +1789,32 @@ function concatRetime(child, parent) {
|
|
|
1765
1789
|
stretch: parent.stretch * child.stretch
|
|
1766
1790
|
};
|
|
1767
1791
|
}
|
|
1768
|
-
function
|
|
1792
|
+
function readCloneRetime(n) {
|
|
1793
|
+
var _a, _b;
|
|
1794
|
+
return (_b = (_a = n.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.retime;
|
|
1795
|
+
}
|
|
1796
|
+
function clearCloneRetime(n) {
|
|
1769
1797
|
var _a;
|
|
1798
|
+
const clone2 = (_a = n.effects) == null ? void 0 : _a.clone;
|
|
1799
|
+
if (!clone2) return;
|
|
1800
|
+
delete clone2.retime;
|
|
1801
|
+
if (Object.keys(clone2).length === 0) delete n.effects.clone;
|
|
1802
|
+
if (n.effects && Object.keys(n.effects).length === 0) delete n.effects;
|
|
1803
|
+
}
|
|
1804
|
+
function applyAllRetimeEffects(root, ctx) {
|
|
1770
1805
|
ctx.idMap.clear();
|
|
1771
1806
|
indexById(root, ctx.idMap);
|
|
1772
1807
|
const sites = [];
|
|
1773
1808
|
const collect = (n) => {
|
|
1774
|
-
var
|
|
1775
|
-
if ((
|
|
1776
|
-
(
|
|
1809
|
+
var _a;
|
|
1810
|
+
if (readCloneRetime(n)) sites.push(n);
|
|
1811
|
+
(_a = n.children) == null ? void 0 : _a.forEach(collect);
|
|
1777
1812
|
};
|
|
1778
1813
|
collect(root);
|
|
1779
1814
|
for (const useNode of sites) {
|
|
1780
|
-
const retime = (
|
|
1815
|
+
const retime = readCloneRetime(useNode);
|
|
1781
1816
|
if (!retime) continue;
|
|
1782
|
-
|
|
1783
|
-
if (Object.keys(useNode.effects).length === 0) delete useNode.effects;
|
|
1817
|
+
clearCloneRetime(useNode);
|
|
1784
1818
|
materialiseRetime(useNode, asRetime(retime), ctx);
|
|
1785
1819
|
}
|
|
1786
1820
|
}
|
|
@@ -1804,7 +1838,6 @@ function materialiseRetime(useNode, retime, ctx) {
|
|
|
1804
1838
|
}
|
|
1805
1839
|
}
|
|
1806
1840
|
function buildChainClone(targetId, accum, ctx, chain) {
|
|
1807
|
-
var _a, _b;
|
|
1808
1841
|
if (chain.has(targetId)) {
|
|
1809
1842
|
ctx.errors.push('retime: loop via "' + targetId + '"');
|
|
1810
1843
|
return void 0;
|
|
@@ -1821,25 +1854,43 @@ function buildChainClone(targetId, accum, ctx, chain) {
|
|
|
1821
1854
|
} else {
|
|
1822
1855
|
remapKeyframeTimes(cloneNode, accum.start, accum.stretch);
|
|
1823
1856
|
}
|
|
1824
|
-
|
|
1825
|
-
delete cloneNode.effects.retime;
|
|
1826
|
-
if (Object.keys(cloneNode.effects).length === 0) delete cloneNode.effects;
|
|
1827
|
-
}
|
|
1857
|
+
clearCloneRetime(cloneNode);
|
|
1828
1858
|
if (target.type === "use" && target.href) {
|
|
1829
1859
|
const subId = stripHash(target.href);
|
|
1830
1860
|
if (subId) {
|
|
1831
|
-
const innerRetime = (
|
|
1861
|
+
const innerRetime = readCloneRetime(target);
|
|
1832
1862
|
const subAccum = innerRetime ? concatRetime(asRetime(innerRetime), accum) : accum;
|
|
1833
1863
|
const subChain = new Set(chain);
|
|
1834
1864
|
subChain.add(targetId);
|
|
1835
1865
|
const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
|
|
1836
1866
|
if (subId2) cloneNode.href = "#" + subId2;
|
|
1837
1867
|
}
|
|
1868
|
+
} else {
|
|
1869
|
+
materialiseNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
|
|
1838
1870
|
}
|
|
1839
1871
|
ctx.defs.push(cloneNode);
|
|
1840
1872
|
if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
|
|
1841
1873
|
return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
|
|
1842
1874
|
}
|
|
1875
|
+
function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
|
|
1876
|
+
const visit = (n) => {
|
|
1877
|
+
var _a;
|
|
1878
|
+
const retime = readCloneRetime(n);
|
|
1879
|
+
if (n.type === "use" && retime && n.href) {
|
|
1880
|
+
const subId = stripHash(n.href);
|
|
1881
|
+
if (subId) {
|
|
1882
|
+
const subAccum = concatRetime(asRetime(retime), accum);
|
|
1883
|
+
const subChain = new Set(chain);
|
|
1884
|
+
subChain.add(parentTargetId);
|
|
1885
|
+
const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
|
|
1886
|
+
if (subId2) n.href = "#" + subId2;
|
|
1887
|
+
}
|
|
1888
|
+
clearCloneRetime(n);
|
|
1889
|
+
}
|
|
1890
|
+
(_a = n.children) == null ? void 0 : _a.forEach(visit);
|
|
1891
|
+
};
|
|
1892
|
+
visit(node);
|
|
1893
|
+
}
|
|
1843
1894
|
function remapKeyframeTimes(node, start, stretch) {
|
|
1844
1895
|
var _a;
|
|
1845
1896
|
remapKeyframeTimesOnly(node, start, stretch);
|
|
@@ -1884,12 +1935,14 @@ function applyAnimatableNumber(node, attrName, raw) {
|
|
|
1884
1935
|
node[attrName] = String(raw);
|
|
1885
1936
|
return;
|
|
1886
1937
|
}
|
|
1887
|
-
if (typeof raw === "object") {
|
|
1938
|
+
if (typeof raw === "object" && raw !== null) {
|
|
1888
1939
|
const obj = raw;
|
|
1889
1940
|
if (Array.isArray(obj.keyframes)) {
|
|
1890
1941
|
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
1891
1942
|
const animate = __spreadValues({}, prevAnimate || {});
|
|
1892
|
-
|
|
1943
|
+
const block = { keyframes: obj.keyframes };
|
|
1944
|
+
if (obj.loop !== void 0) block.loop = obj.loop;
|
|
1945
|
+
animate[attrName] = block;
|
|
1893
1946
|
node.animate = animate;
|
|
1894
1947
|
return;
|
|
1895
1948
|
}
|
|
@@ -2952,16 +3005,67 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
2952
3005
|
looped.push(pushed);
|
|
2953
3006
|
}
|
|
2954
3007
|
}
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
3008
|
+
function appendRepTail(repStart, isReversed, tailFraction) {
|
|
3009
|
+
let entries;
|
|
3010
|
+
if (isReversed) {
|
|
3011
|
+
entries = [];
|
|
3012
|
+
for (let i = template.length - 1; i >= 0; i--) {
|
|
3013
|
+
entries.push({
|
|
3014
|
+
relT: 1 - template[i].relT,
|
|
3015
|
+
v: template[i].v,
|
|
3016
|
+
e: i > 0 ? reverseEasing(template[i - 1].e) : void 0,
|
|
3017
|
+
tangentIn: template[i].tangentOut,
|
|
3018
|
+
tangentOut: template[i].tangentIn
|
|
3019
|
+
});
|
|
3020
|
+
}
|
|
3021
|
+
} else {
|
|
3022
|
+
entries = template;
|
|
3023
|
+
}
|
|
3024
|
+
const startRelT = 1 - tailFraction;
|
|
3025
|
+
for (let i = 0; i < entries.length; i++) {
|
|
3026
|
+
const entry = entries[i];
|
|
3027
|
+
if (entry.relT < startRelT - 1e-9) continue;
|
|
3028
|
+
const prev = entries[i - 1];
|
|
3029
|
+
if (prev && prev.relT < startRelT - 1e-9 && entry.relT > startRelT + 1e-9) {
|
|
3030
|
+
const intervalSpan = entry.relT - prev.relT;
|
|
3031
|
+
const localFrac = (startRelT - prev.relT) / intervalSpan;
|
|
3032
|
+
const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
|
|
3033
|
+
const startValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
|
|
3034
|
+
const { right: rightEasing } = splitEasing(prev.e, localFrac);
|
|
3035
|
+
looped.push({ t: repStart, v: startValue, e: rightEasing });
|
|
3036
|
+
}
|
|
3037
|
+
const pushed = {
|
|
3038
|
+
t: repStart + (entry.relT - startRelT) * segDuration,
|
|
3039
|
+
v: entry.v,
|
|
3040
|
+
e: i < entries.length - 1 ? entry.e : void 0
|
|
3041
|
+
};
|
|
3042
|
+
if (entry.tangentIn) pushed.tangentIn = entry.tangentIn;
|
|
3043
|
+
if (entry.tangentOut) pushed.tangentOut = entry.tangentOut;
|
|
3044
|
+
looped.push(pushed);
|
|
3045
|
+
}
|
|
2960
3046
|
}
|
|
2961
|
-
if (
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
3047
|
+
if (loop.before) {
|
|
3048
|
+
if (partialFraction > 1e-9) {
|
|
3049
|
+
const isReversed = !!loop.alternate && fullReps % 2 === 0;
|
|
3050
|
+
appendRepTail(fillStart, isReversed, partialFraction);
|
|
3051
|
+
}
|
|
3052
|
+
for (let rep = 0; rep < fullReps; rep++) {
|
|
3053
|
+
const distFromBoundary = fullReps - 1 - rep;
|
|
3054
|
+
const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
|
|
3055
|
+
const repStart = fillStart + remainder + rep * segDuration;
|
|
3056
|
+
appendRep(repStart, isReversed);
|
|
3057
|
+
}
|
|
3058
|
+
} else {
|
|
3059
|
+
for (let rep = 0; rep < fullReps; rep++) {
|
|
3060
|
+
const isReversed = !!loop.alternate && rep % 2 === 0;
|
|
3061
|
+
const repStart = fillStart + rep * segDuration;
|
|
3062
|
+
appendRep(repStart, isReversed);
|
|
3063
|
+
}
|
|
3064
|
+
if (partialFraction > 1e-9) {
|
|
3065
|
+
const isReversed = !!loop.alternate && fullReps % 2 === 0;
|
|
3066
|
+
const repStart = fillStart + fullReps * segDuration;
|
|
3067
|
+
appendRep(repStart, isReversed, partialFraction);
|
|
3068
|
+
}
|
|
2965
3069
|
}
|
|
2966
3070
|
if (loop.before) {
|
|
2967
3071
|
return [...looped, ...keyframes];
|
|
@@ -3280,7 +3384,6 @@ function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
|
|
|
3280
3384
|
if (!trimPath) return node;
|
|
3281
3385
|
const trimAllAsOne = !!trimPath.trimAllAsOne;
|
|
3282
3386
|
const leafEntries = [];
|
|
3283
|
-
let acc = 0;
|
|
3284
3387
|
const measure = (n) => {
|
|
3285
3388
|
if (Array.isArray(n.children) && n.children.length > 0) {
|
|
3286
3389
|
for (const ch of n.children) measure(ch);
|
|
@@ -3292,15 +3395,22 @@ function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
|
|
|
3292
3395
|
if (!subpaths.length) return;
|
|
3293
3396
|
const entry = { leaf: n, subpaths: [] };
|
|
3294
3397
|
for (const sp of subpaths) {
|
|
3295
|
-
if (!trimAllAsOne) acc = 0;
|
|
3296
3398
|
const lengthPx = pxBezierPathLength(sp);
|
|
3297
|
-
entry.subpaths.push({ subpath: sp, lengthPx, startOffsetPx:
|
|
3298
|
-
acc += lengthPx;
|
|
3399
|
+
entry.subpaths.push({ subpath: sp, lengthPx, startOffsetPx: 0 });
|
|
3299
3400
|
}
|
|
3300
3401
|
leafEntries.push(entry);
|
|
3301
3402
|
};
|
|
3302
3403
|
measure(node);
|
|
3303
3404
|
if (!leafEntries.length) return node;
|
|
3405
|
+
let acc = 0;
|
|
3406
|
+
const iterOrder = trimAllAsOne ? [...leafEntries].reverse() : leafEntries;
|
|
3407
|
+
for (const entry of iterOrder) {
|
|
3408
|
+
for (const sp of entry.subpaths) {
|
|
3409
|
+
if (!trimAllAsOne) acc = 0;
|
|
3410
|
+
sp.startOffsetPx = acc;
|
|
3411
|
+
acc += sp.lengthPx;
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3304
3414
|
const chainLengthPx = acc;
|
|
3305
3415
|
if (trimAllAsOne && chainLengthPx < 1e-3) return node;
|
|
3306
3416
|
const offsetReadRaw = readAnimatable(trimPath.offset);
|
|
@@ -3427,10 +3537,12 @@ function computeAnimAttr(read, map) {
|
|
|
3427
3537
|
value: map((_c = kf.value) != null ? _c : kf.v),
|
|
3428
3538
|
easing: (_d = kf.easing) != null ? _d : kf.e
|
|
3429
3539
|
};
|
|
3430
|
-
})
|
|
3540
|
+
}),
|
|
3541
|
+
loop: read.loop
|
|
3431
3542
|
};
|
|
3432
3543
|
}
|
|
3433
3544
|
function applyAttr(node, attrName, attr) {
|
|
3545
|
+
var _a, _b;
|
|
3434
3546
|
if (!attr) return;
|
|
3435
3547
|
if (attr.kind === "static" /* Static */) {
|
|
3436
3548
|
node[attrName] = attr.value;
|
|
@@ -3438,9 +3550,16 @@ function applyAttr(node, attrName, attr) {
|
|
|
3438
3550
|
}
|
|
3439
3551
|
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
3440
3552
|
const animate = __spreadValues({}, prevAnimate || {});
|
|
3441
|
-
|
|
3553
|
+
const block = { keyframes: attr.keyframes };
|
|
3554
|
+
if (attr.loop !== void 0) block.loop = attr.loop;
|
|
3555
|
+
animate[attrName] = block;
|
|
3442
3556
|
node.animate = animate;
|
|
3557
|
+
const firstKf = attr.keyframes[0];
|
|
3558
|
+
if (firstKf && ((_a = firstKf.value) != null ? _a : firstKf.v) !== void 0) {
|
|
3559
|
+
node[attrName] = (_b = firstKf.value) != null ? _b : firstKf.v;
|
|
3560
|
+
}
|
|
3443
3561
|
}
|
|
3562
|
+
var OPACITY_STEP_MS = 10;
|
|
3444
3563
|
function computeOpacityFromRange(rangeRead) {
|
|
3445
3564
|
var _a, _b, _c, _d, _e, _f;
|
|
3446
3565
|
const hide = (v) => v[0] === v[1];
|
|
@@ -3466,9 +3585,9 @@ function computeOpacityFromRange(rangeRead) {
|
|
|
3466
3585
|
const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
|
|
3467
3586
|
if (prevHide && !nextHide) {
|
|
3468
3587
|
out.push({ time: t, value: 0 });
|
|
3469
|
-
out.push({ time: t +
|
|
3588
|
+
out.push({ time: t + OPACITY_STEP_MS, value: 1 });
|
|
3470
3589
|
} else if (!prevHide && nextHide) {
|
|
3471
|
-
out.push({ time: t -
|
|
3590
|
+
out.push({ time: t - OPACITY_STEP_MS, value: 1 });
|
|
3472
3591
|
out.push({ time: t, value: 0 });
|
|
3473
3592
|
}
|
|
3474
3593
|
}
|
|
@@ -3601,6 +3720,7 @@ function rectToPathD(node) {
|
|
|
3601
3720
|
|
|
3602
3721
|
// src/effects/PlayerEffectsUtil.ts
|
|
3603
3722
|
function applyPlayerEffects(root) {
|
|
3723
|
+
var _a;
|
|
3604
3724
|
const ctx = {
|
|
3605
3725
|
defs: [],
|
|
3606
3726
|
warnings: [],
|
|
@@ -3608,7 +3728,10 @@ function applyPlayerEffects(root) {
|
|
|
3608
3728
|
idMap: /* @__PURE__ */ new Map(),
|
|
3609
3729
|
nextId: 0,
|
|
3610
3730
|
contentRefInnerIds: /* @__PURE__ */ new Map(),
|
|
3611
|
-
maskAncestorChains: /* @__PURE__ */ new Map()
|
|
3731
|
+
maskAncestorChains: /* @__PURE__ */ new Map(),
|
|
3732
|
+
// Resolved engine: `frames` ONLY when explicitly set; auto/webapi/unset →
|
|
3733
|
+
// webapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
|
|
3734
|
+
engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi
|
|
3612
3735
|
};
|
|
3613
3736
|
const working = clone(root);
|
|
3614
3737
|
indexById(working, ctx.idMap);
|
|
@@ -3625,7 +3748,7 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
|
3625
3748
|
const originalId = typeof node.id === "string" ? node.id : void 0;
|
|
3626
3749
|
const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
|
|
3627
3750
|
if (!fx && !innerIdForContentRef) return node;
|
|
3628
|
-
const { transformation, repeater, maskedBy, trimPath,
|
|
3751
|
+
const { transformation, repeater, maskedBy, trimPath, clone: cloneFx, fillGradient, strokeGradient, textAlongPath } = fx != null ? fx : {};
|
|
3629
3752
|
const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
|
|
3630
3753
|
if (fx) delete node.effects;
|
|
3631
3754
|
let n = node;
|
|
@@ -3636,11 +3759,12 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
|
3636
3759
|
n = applyRepeaterEffect(n, repeater, ctx);
|
|
3637
3760
|
n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
|
|
3638
3761
|
if (innerIdForContentRef) {
|
|
3762
|
+
applyRefHref(n, cloneFx, ctx);
|
|
3639
3763
|
n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
|
|
3640
3764
|
} else {
|
|
3641
|
-
n = applyRefAndTransformationEffect(n,
|
|
3765
|
+
n = applyRefAndTransformationEffect(n, cloneFx, transformation, ctx);
|
|
3642
3766
|
}
|
|
3643
|
-
if (retime) node.effects = { retime };
|
|
3767
|
+
if (cloneFx == null ? void 0 : cloneFx.retime) node.effects = { clone: { retime: cloneFx.retime } };
|
|
3644
3768
|
if (originalId) ctx.idMap.set(originalId, n);
|
|
3645
3769
|
return n;
|
|
3646
3770
|
}
|
|
@@ -3657,13 +3781,30 @@ function materialiseAnimatedUseInstances(root) {
|
|
|
3657
3781
|
if (animatedIds.size === 0) return root;
|
|
3658
3782
|
let idCounter = 0;
|
|
3659
3783
|
const genId3 = () => "_lw_use_mat_" + ++idCounter;
|
|
3784
|
+
const rootViewport = readRootViewport(root);
|
|
3660
3785
|
const defsCollector = [];
|
|
3661
|
-
const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector);
|
|
3786
|
+
const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
3662
3787
|
if (defsCollector.length === 0) return walked;
|
|
3663
3788
|
const defsNode = { type: "defs", children: defsCollector };
|
|
3664
3789
|
const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
|
|
3665
3790
|
return __spreadProps(__spreadValues({}, walked), { children: newChildren });
|
|
3666
3791
|
}
|
|
3792
|
+
function readRootViewport(root) {
|
|
3793
|
+
const vb = parseViewBox(root.viewBox);
|
|
3794
|
+
if (vb) return [vb[2], vb[3]];
|
|
3795
|
+
const w = numericAttr(root.width);
|
|
3796
|
+
const h = numericAttr(root.height);
|
|
3797
|
+
if (w !== void 0 && h !== void 0) return [w, h];
|
|
3798
|
+
return [1, 1];
|
|
3799
|
+
}
|
|
3800
|
+
function numericAttr(v) {
|
|
3801
|
+
if (typeof v === "number") return v;
|
|
3802
|
+
if (typeof v === "string") {
|
|
3803
|
+
const n = parseFloat(v);
|
|
3804
|
+
return Number.isFinite(n) ? n : void 0;
|
|
3805
|
+
}
|
|
3806
|
+
return void 0;
|
|
3807
|
+
}
|
|
3667
3808
|
function buildIdMap(root) {
|
|
3668
3809
|
const map = /* @__PURE__ */ new Map();
|
|
3669
3810
|
const visit = (n) => {
|
|
@@ -3715,16 +3856,22 @@ function stripHash2(href) {
|
|
|
3715
3856
|
if (typeof href !== "string") return void 0;
|
|
3716
3857
|
return href.startsWith("#") ? href.slice(1) : href;
|
|
3717
3858
|
}
|
|
3718
|
-
function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector) {
|
|
3859
|
+
function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
|
|
3860
|
+
var _a, _b, _c, _d;
|
|
3719
3861
|
const clone2 = deepClonePxNode(target);
|
|
3720
3862
|
regenerateIdsAndRewriteRefs(clone2, genId3);
|
|
3721
|
-
const
|
|
3722
|
-
const
|
|
3863
|
+
const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
|
|
3864
|
+
const useW = (_b = (_a = numericAttr(useNode.width)) != null ? _a : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
|
|
3865
|
+
const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
|
|
3866
|
+
const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
|
|
3867
|
+
const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
3723
3868
|
const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materialisedClone] });
|
|
3724
3869
|
delete newNode.href;
|
|
3870
|
+
delete newNode.width;
|
|
3871
|
+
delete newNode.height;
|
|
3725
3872
|
return applyUseOffsetToG(newNode);
|
|
3726
3873
|
}
|
|
3727
|
-
function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector) {
|
|
3874
|
+
function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
|
|
3728
3875
|
const viewBox = parseViewBox(symbolNode.viewBox);
|
|
3729
3876
|
const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
|
|
3730
3877
|
delete g.viewBox;
|
|
@@ -3733,9 +3880,14 @@ function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector) {
|
|
|
3733
3880
|
delete g.height;
|
|
3734
3881
|
if (!viewBox) return g;
|
|
3735
3882
|
const [vbX, vbY, vbW, vbH] = viewBox;
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3883
|
+
const scale = vbW > 0 && vbH > 0 ? Math.min(useW / vbW, useH / vbH) : 1;
|
|
3884
|
+
const xOff = (useW - vbW * scale) / 2;
|
|
3885
|
+
const yOff = (useH - vbH * scale) / 2;
|
|
3886
|
+
const parts = [];
|
|
3887
|
+
if (xOff !== 0 || yOff !== 0) parts.push("translate(" + xOff + "," + yOff + ")");
|
|
3888
|
+
if (scale !== 1) parts.push("scale(" + scale + ")");
|
|
3889
|
+
if (vbX !== 0 || vbY !== 0) parts.push("translate(" + -vbX + "," + -vbY + ")");
|
|
3890
|
+
if (parts.length) g.transform = parts.join("");
|
|
3739
3891
|
const clipId = genId3();
|
|
3740
3892
|
defsCollector.push({
|
|
3741
3893
|
type: "clipPath",
|
|
@@ -3751,18 +3903,18 @@ function parseViewBox(v) {
|
|
|
3751
3903
|
if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
|
|
3752
3904
|
return [parts[0], parts[1], parts[2], parts[3]];
|
|
3753
3905
|
}
|
|
3754
|
-
function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector) {
|
|
3906
|
+
function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
|
|
3755
3907
|
if (node.type === "use" && typeof node.href === "string") {
|
|
3756
3908
|
const targetId = stripHash2(node.href);
|
|
3757
3909
|
if (targetId && animatedIds.has(targetId)) {
|
|
3758
3910
|
const target = idMap.get(targetId);
|
|
3759
|
-
if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector);
|
|
3911
|
+
if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
3760
3912
|
}
|
|
3761
3913
|
}
|
|
3762
3914
|
if (!node.children) return node;
|
|
3763
3915
|
let changed = false;
|
|
3764
3916
|
const newChildren = node.children.map((ch) => {
|
|
3765
|
-
const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector);
|
|
3917
|
+
const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
3766
3918
|
if (m !== ch) changed = true;
|
|
3767
3919
|
return m;
|
|
3768
3920
|
});
|
|
@@ -3778,6 +3930,36 @@ function materialiseAllInTree(doc, engine, opts) {
|
|
|
3778
3930
|
if (engine === PxAnimatorEngine.webapi) {
|
|
3779
3931
|
root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
|
|
3780
3932
|
root = materialiseAnimatedUseInstances(root);
|
|
3933
|
+
root = pruneUnreferencedDefs(root);
|
|
3934
|
+
}
|
|
3935
|
+
return root;
|
|
3936
|
+
}
|
|
3937
|
+
function pruneUnreferencedDefs(root) {
|
|
3938
|
+
const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
|
|
3939
|
+
const walk = (n, fn) => {
|
|
3940
|
+
var _a;
|
|
3941
|
+
fn(n);
|
|
3942
|
+
(_a = n.children) == null ? void 0 : _a.forEach((c) => walk(c, fn));
|
|
3943
|
+
};
|
|
3944
|
+
let changed = true;
|
|
3945
|
+
while (changed) {
|
|
3946
|
+
changed = false;
|
|
3947
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
3948
|
+
walk(root, (n) => {
|
|
3949
|
+
if (n.type === "use" && typeof n.href === "string") referenced.add(stripHash3(n.href));
|
|
3950
|
+
});
|
|
3951
|
+
walk(root, (n) => {
|
|
3952
|
+
if (!n.children) return;
|
|
3953
|
+
let kept = n.children;
|
|
3954
|
+
if (n.type === "defs") {
|
|
3955
|
+
kept = kept.filter((c) => !((c.type === "g" || c.type === "symbol") && typeof c.id === "string" && !referenced.has(c.id)));
|
|
3956
|
+
}
|
|
3957
|
+
kept = kept.filter((c) => !(c.type === "defs" && (!c.children || c.children.length === 0)));
|
|
3958
|
+
if (kept.length !== n.children.length) {
|
|
3959
|
+
n.children = kept;
|
|
3960
|
+
changed = true;
|
|
3961
|
+
}
|
|
3962
|
+
});
|
|
3781
3963
|
}
|
|
3782
3964
|
return root;
|
|
3783
3965
|
}
|
|
@@ -3810,6 +3992,13 @@ var URL_VALUE_ATTRS_LOWER = /* @__PURE__ */ new Set([
|
|
|
3810
3992
|
]);
|
|
3811
3993
|
var IMAGE_REF_ATTRS_LOWER = /* @__PURE__ */ new Set(["href", "xlink:href", "src"]);
|
|
3812
3994
|
var DATA_RASTER_IMAGE_RE = /^data:image\/(?:png|jpe?g|gif|webp|bmp);base64,/i;
|
|
3995
|
+
var DATA_SVG_IMAGE_RE = /^data:image\/svg\+xml(?:;[^,]*)?,/i;
|
|
3996
|
+
var DATA_IMAGE_BASE64_PAYLOAD_RE = /^data:image\/[^;,]*;base64,([A-Za-z0-9+/]{8})/i;
|
|
3997
|
+
var BASE64_RASTER_MAGICS = ["iVBORw0K", "/9j/", "R0lGOD", "UklGR", "Qk"];
|
|
3998
|
+
function isContentSniffedRasterImage(str) {
|
|
3999
|
+
const m = DATA_IMAGE_BASE64_PAYLOAD_RE.exec(str);
|
|
4000
|
+
return !!m && BASE64_RASTER_MAGICS.some((magic) => m[1].startsWith(magic));
|
|
4001
|
+
}
|
|
3813
4002
|
function isDangerousAttrName(nameLower) {
|
|
3814
4003
|
if (nameLower.startsWith("on")) return true;
|
|
3815
4004
|
return false;
|
|
@@ -3832,8 +4021,8 @@ function sanitiseAttributeValue(name, value) {
|
|
|
3832
4021
|
const str = String(value);
|
|
3833
4022
|
if (str.startsWith("#")) return value;
|
|
3834
4023
|
if (/^url\(#[^)]+\)$/.test(str)) return value;
|
|
3835
|
-
if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && DATA_RASTER_IMAGE_RE.test(str)) return value;
|
|
3836
|
-
console.warn('Attribute "' + nameLower + '" blocked: must be #id, url(#id), or
|
|
4024
|
+
if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && (DATA_RASTER_IMAGE_RE.test(str) || DATA_SVG_IMAGE_RE.test(str) || isContentSniffedRasterImage(str))) return value;
|
|
4025
|
+
console.warn('Attribute "' + nameLower + '" blocked: must be #id, url(#id), or data:image/\u2026 URI, got:', value);
|
|
3837
4026
|
return void 0;
|
|
3838
4027
|
}
|
|
3839
4028
|
return value;
|
|
@@ -4930,6 +5119,7 @@ export {
|
|
|
4930
5119
|
PxAttrValueSchema,
|
|
4931
5120
|
PxBezierPathSchema,
|
|
4932
5121
|
PxBindingSchema,
|
|
5122
|
+
PxCloneEffectSchema,
|
|
4933
5123
|
PxDefsSchema,
|
|
4934
5124
|
PxEasingOrRefSchema,
|
|
4935
5125
|
PxEffectsSchema,
|
|
@@ -4945,7 +5135,6 @@ export {
|
|
|
4945
5135
|
PxNodeBase,
|
|
4946
5136
|
PxNodeSchema,
|
|
4947
5137
|
PxPropertyAnimationSchema,
|
|
4948
|
-
PxRefEffectSchema,
|
|
4949
5138
|
PxRepeaterEffectSchema,
|
|
4950
5139
|
PxRetimeEffectSchema,
|
|
4951
5140
|
PxStrokeGradientEffectSchema,
|