@pixodesk/svg-animator-core 1.0.43 → 1.0.45
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/README.md +1 -1
- package/dist/{PxDocumentDiagnostic-DkBZYJ7X.d.cts → PxDocumentDiagnostic-CBhVyNEi.d.cts} +127 -91
- package/dist/{PxDocumentDiagnostic-DkBZYJ7X.d.ts → PxDocumentDiagnostic-CBhVyNEi.d.ts} +127 -91
- package/dist/chunk-5HEVTP2N.min.js +1 -0
- package/dist/{chunk-BOTZI36B.js → chunk-YVKMPBHE.js} +2043 -88
- package/dist/chunk-YVKMPBHE.js.map +1 -0
- package/dist/index.cjs +197 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +15 -1881
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/dist/internal.cjs +3228 -150
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +60 -3
- package/dist/internal.d.ts +60 -3
- package/dist/internal.js +53 -1
- package/dist/internal.js.map +1 -1
- package/dist/internal.min.cjs +1 -1
- package/dist/internal.min.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-BOTZI36B.js.map +0 -1
- package/dist/chunk-CAZFG2HW.min.js +0 -1
package/dist/internal.cjs
CHANGED
|
@@ -85,7 +85,9 @@ __export(internal_exports, {
|
|
|
85
85
|
materializeMotionPathInPropAnim: () => materializeMotionPathInPropAnim,
|
|
86
86
|
mergeStaticTransformIntoAnimDef: () => mergeStaticTransformIntoAnimDef,
|
|
87
87
|
planSchemaRelease: () => planSchemaRelease,
|
|
88
|
+
prepareDocumentForRender: () => prepareDocumentForRender,
|
|
88
89
|
releaseLogProblems: () => releaseLogProblems,
|
|
90
|
+
renderPxTree: () => renderPxTree,
|
|
89
91
|
reportDocumentDiagnostics: () => reportDocumentDiagnostics,
|
|
90
92
|
reverseEasing: () => reverseEasing,
|
|
91
93
|
sanitizeAttributeValue: () => sanitizeAttributeValue,
|
|
@@ -642,14 +644,18 @@ var PxPlaybackDirection = {
|
|
|
642
644
|
};
|
|
643
645
|
var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
|
|
644
646
|
var PX_ANIM_ATTR_NAME = "_px_animator";
|
|
645
|
-
var
|
|
647
|
+
var PxTriggerStart = {
|
|
646
648
|
load: "load",
|
|
647
649
|
mouseOver: "mouseOver",
|
|
648
650
|
click: "click",
|
|
649
|
-
|
|
650
|
-
|
|
651
|
+
none: "none"
|
|
652
|
+
};
|
|
653
|
+
var PxOffScreenAction = {
|
|
654
|
+
pause: "pause",
|
|
655
|
+
continue: "continue",
|
|
656
|
+
reset: "reset"
|
|
651
657
|
};
|
|
652
|
-
var
|
|
658
|
+
var PxMouseOutAction = {
|
|
653
659
|
continue: "continue",
|
|
654
660
|
pause: "pause",
|
|
655
661
|
reset: "reset",
|
|
@@ -707,10 +713,15 @@ var PxTimelineEngine = {
|
|
|
707
713
|
var PxTimelineEngineSetting = __spreadProps(__spreadValues({}, PxTimelineEngine), {
|
|
708
714
|
auto: "auto"
|
|
709
715
|
});
|
|
716
|
+
function resolveTimelineEngine(engine) {
|
|
717
|
+
return engine === PxTimelineEngineSetting.js ? PxTimelineEngine.js : PxTimelineEngine.native;
|
|
718
|
+
}
|
|
710
719
|
var PX_TRIGGER_DEFAULTS = {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
720
|
+
start: "load",
|
|
721
|
+
offScreen: "pause",
|
|
722
|
+
mouseOut: "continue",
|
|
723
|
+
visibilityThreshold: 0.5,
|
|
724
|
+
visibilityDebounce: 150
|
|
714
725
|
};
|
|
715
726
|
var PxLoopRepeatAt = {
|
|
716
727
|
/** Segment from the START; the repetition runs BEFORE the first keyframe
|
|
@@ -761,6 +772,16 @@ var PxStrokeTrimSubPaths = {
|
|
|
761
772
|
var PX_TEXT_CONTENT_ATTR = "textContent";
|
|
762
773
|
var CLASS_ATTR = "class";
|
|
763
774
|
var TRANSFORM_ATTR = "transform";
|
|
775
|
+
var OFFSET_DISTANCE_ATTR = "offsetDistance";
|
|
776
|
+
var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
|
|
777
|
+
"type",
|
|
778
|
+
"children",
|
|
779
|
+
"animator",
|
|
780
|
+
"meta",
|
|
781
|
+
"animate",
|
|
782
|
+
"effects",
|
|
783
|
+
PX_TEXT_CONTENT_ATTR
|
|
784
|
+
]);
|
|
764
785
|
var TRANSFORM_PART = {
|
|
765
786
|
translate: "translate",
|
|
766
787
|
rotate: "rotate",
|
|
@@ -829,9 +850,9 @@ function flattenAnimatorTimeline(cfg) {
|
|
|
829
850
|
} else {
|
|
830
851
|
if (timeline.duration !== void 0) flat.duration = timeline.duration;
|
|
831
852
|
if (timeline.trigger !== void 0) {
|
|
832
|
-
const _b = timeline.trigger, {
|
|
853
|
+
const _b = timeline.trigger, { finish } = _b, restTrigger = __objRest(_b, ["finish"]);
|
|
833
854
|
if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
|
|
834
|
-
if (
|
|
855
|
+
if (finish !== void 0) flat.resetOnFinish = finish === "reset";
|
|
835
856
|
}
|
|
836
857
|
if (timeline.delay !== void 0) flat.delay = timeline.delay;
|
|
837
858
|
if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
|
|
@@ -841,9 +862,19 @@ function flattenAnimatorTimeline(cfg) {
|
|
|
841
862
|
flattenMemo.set(cfg, flat);
|
|
842
863
|
return flat;
|
|
843
864
|
}
|
|
865
|
+
function getDefinitions(doc) {
|
|
866
|
+
var _a2;
|
|
867
|
+
if (!doc) return void 0;
|
|
868
|
+
return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
|
|
869
|
+
}
|
|
870
|
+
function getBindings(doc) {
|
|
871
|
+
var _a2;
|
|
872
|
+
if (!doc) return void 0;
|
|
873
|
+
return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.bindings;
|
|
874
|
+
}
|
|
844
875
|
|
|
845
876
|
// src/version/PxSchemaVersion.ts
|
|
846
|
-
var PX_WIRE_SCHEMA_VERSION = "1.
|
|
877
|
+
var PX_WIRE_SCHEMA_VERSION = "1.2";
|
|
847
878
|
|
|
848
879
|
// src/version/PxWireVersion.ts
|
|
849
880
|
var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
|
|
@@ -936,13 +967,15 @@ var PxElementAnimationSchema = implementsInterface()(px.union([
|
|
|
936
967
|
PxAnimationDefinitionSchema
|
|
937
968
|
]));
|
|
938
969
|
var PxTriggerSchema = implementsInterface()(px.object({
|
|
939
|
-
|
|
940
|
-
|
|
970
|
+
start: px.enum([PxTriggerStart.load, PxTriggerStart.mouseOver, PxTriggerStart.click, PxTriggerStart.none], PX_TRIGGER_DEFAULTS.start).optional(),
|
|
971
|
+
offScreen: px.enum([PxOffScreenAction.pause, PxOffScreenAction.continue, PxOffScreenAction.reset], PX_TRIGGER_DEFAULTS.offScreen).optional(),
|
|
972
|
+
mouseOut: px.enum([PxMouseOutAction.continue, PxMouseOutAction.pause, PxMouseOutAction.reset, PxMouseOutAction.reverse], PX_TRIGGER_DEFAULTS.mouseOut).optional(),
|
|
941
973
|
// What happens after a NATURAL finish — `'hold'` (default: keep the end state per
|
|
942
|
-
// `fill`) or `'reset'` (snap back to the start state).
|
|
943
|
-
//
|
|
944
|
-
|
|
945
|
-
|
|
974
|
+
// `fill`) or `'reset'` (snap back to the start state). One of four occasion keys
|
|
975
|
+
// (`start`, `offScreen`, `mouseOut`, `finish`), all named the same way.
|
|
976
|
+
finish: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
|
|
977
|
+
visibilityThreshold: px.number().optional(),
|
|
978
|
+
visibilityDebounce: px.number().optional()
|
|
946
979
|
}));
|
|
947
980
|
var PxGlyphSchema = implementsInterface()(px.object({
|
|
948
981
|
width: px.number(),
|
|
@@ -1399,6 +1432,11 @@ function interpolateBezier(path1, path2, progress) {
|
|
|
1399
1432
|
}
|
|
1400
1433
|
return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
|
|
1401
1434
|
}
|
|
1435
|
+
function remap(value, inMin, inMax, outMin, outMax) {
|
|
1436
|
+
if (inMax === inMin) return outMin;
|
|
1437
|
+
const t = (value - inMin) / (inMax - inMin);
|
|
1438
|
+
return outMin + t * (outMax - outMin);
|
|
1439
|
+
}
|
|
1402
1440
|
function solveCubicBezierX(p1x, p2x, x) {
|
|
1403
1441
|
if (x <= 0) return 0;
|
|
1404
1442
|
if (x >= 1) return 1;
|
|
@@ -1503,6 +1541,43 @@ function toRGBA(color) {
|
|
|
1503
1541
|
const b = Math.round(color[2] * 255);
|
|
1504
1542
|
return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
|
|
1505
1543
|
}
|
|
1544
|
+
function parseRgba(s) {
|
|
1545
|
+
var _a2;
|
|
1546
|
+
const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
|
|
1547
|
+
if (!inner) throw new Error("Invalid rgb/rgba format");
|
|
1548
|
+
const parts = inner.split(",").map((v) => +v.trim());
|
|
1549
|
+
return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
|
|
1550
|
+
}
|
|
1551
|
+
function parseHex(s) {
|
|
1552
|
+
const hex = s.slice(1);
|
|
1553
|
+
const isShort = hex.length <= 4;
|
|
1554
|
+
const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
|
|
1555
|
+
const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
|
|
1556
|
+
const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
|
|
1557
|
+
const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
|
|
1558
|
+
const result = [
|
|
1559
|
+
parseInt(r, 16) / 255,
|
|
1560
|
+
parseInt(g, 16) / 255,
|
|
1561
|
+
parseInt(b, 16) / 255
|
|
1562
|
+
];
|
|
1563
|
+
if (a !== null) {
|
|
1564
|
+
result.push(parseInt(a, 16) / 255);
|
|
1565
|
+
}
|
|
1566
|
+
return result;
|
|
1567
|
+
}
|
|
1568
|
+
function parseColor(s) {
|
|
1569
|
+
if (!s) return void 0;
|
|
1570
|
+
if (Array.isArray(s)) return s;
|
|
1571
|
+
if (typeof s !== "string") return void 0;
|
|
1572
|
+
if (s.startsWith("#")) {
|
|
1573
|
+
return parseHex(s);
|
|
1574
|
+
} else if (s.startsWith("rgb")) {
|
|
1575
|
+
return parseRgba(s);
|
|
1576
|
+
} else {
|
|
1577
|
+
console.warn("Unsupported color format: " + s);
|
|
1578
|
+
}
|
|
1579
|
+
return void 0;
|
|
1580
|
+
}
|
|
1506
1581
|
var PX_COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
|
|
1507
1582
|
var PX_TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
|
|
1508
1583
|
var PX_PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
@@ -1563,6 +1638,9 @@ var PX_DEFAULT_DURATION_MS = 1e3;
|
|
|
1563
1638
|
function kebabToCamelCaseWord(kebab) {
|
|
1564
1639
|
return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
|
|
1565
1640
|
}
|
|
1641
|
+
function isCamelCaseWord(word) {
|
|
1642
|
+
return !word.includes("-") && /[a-z][A-Z]/.test(word);
|
|
1643
|
+
}
|
|
1566
1644
|
var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
|
|
1567
1645
|
// Transform/positioning
|
|
1568
1646
|
"viewBox",
|
|
@@ -1718,6 +1796,38 @@ function invertEasing(easing) {
|
|
|
1718
1796
|
return cubicBezier(flipped);
|
|
1719
1797
|
}
|
|
1720
1798
|
|
|
1799
|
+
// src/animation/PxStaticTransformMerge.ts
|
|
1800
|
+
function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
|
|
1801
|
+
if (!animDef) return animDef;
|
|
1802
|
+
const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
|
|
1803
|
+
if (!staticParts || !Object.keys(staticParts).length) return animDef;
|
|
1804
|
+
const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
|
|
1805
|
+
const transformAnim = animDef[TRANSFORM_ATTR];
|
|
1806
|
+
if (transformAnim && typeof transformAnim === "object") {
|
|
1807
|
+
const anim = transformAnim;
|
|
1808
|
+
if (Array.isArray(anim.keyframes)) {
|
|
1809
|
+
const out = __spreadProps(__spreadValues({}, anim), {
|
|
1810
|
+
keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
|
|
1811
|
+
});
|
|
1812
|
+
if (out.value !== void 0) out.value = mergeKfValue(out.value);
|
|
1813
|
+
return __spreadProps(__spreadValues({}, animDef), { transform: out });
|
|
1814
|
+
}
|
|
1815
|
+
return animDef;
|
|
1816
|
+
}
|
|
1817
|
+
const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
|
|
1818
|
+
if (channels.length !== 1) return animDef;
|
|
1819
|
+
const ch = channels[0];
|
|
1820
|
+
const chAnim = animDef[ch];
|
|
1821
|
+
if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
|
|
1822
|
+
const lifted = __spreadProps(__spreadValues({}, chAnim), {
|
|
1823
|
+
keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
|
|
1824
|
+
});
|
|
1825
|
+
if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
|
|
1826
|
+
const rest = __spreadValues({}, animDef);
|
|
1827
|
+
delete rest[ch];
|
|
1828
|
+
return __spreadProps(__spreadValues({}, rest), { transform: lifted });
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1721
1831
|
// src/materialize/PxMotionPath.ts
|
|
1722
1832
|
function getKfTranslate(kf) {
|
|
1723
1833
|
const v = keyframeValue(kf);
|
|
@@ -1769,6 +1879,33 @@ function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
|
|
|
1769
1879
|
byNext.set(nextKf, entry);
|
|
1770
1880
|
return entry;
|
|
1771
1881
|
}
|
|
1882
|
+
function evaluateMotionPathSegment(prevKf, nextKf, prevPos, nextPos, localProgress, autoOrient) {
|
|
1883
|
+
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
1884
|
+
const t = seg.totalArc === 0 ? localProgress : tFromArcFraction(seg.lut, localProgress);
|
|
1885
|
+
const point = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
1886
|
+
if (!autoOrient) return { translate: point };
|
|
1887
|
+
const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
1888
|
+
const rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
|
|
1889
|
+
return { translate: point, rotateDeg };
|
|
1890
|
+
}
|
|
1891
|
+
function tFromArcFraction(lut, arcFrac) {
|
|
1892
|
+
const total = lut.ds[lut.ds.length - 1];
|
|
1893
|
+
const target = arcFrac * total;
|
|
1894
|
+
const { ts, ds } = lut;
|
|
1895
|
+
const last = ds.length - 1;
|
|
1896
|
+
if (target <= 0) return ts[0];
|
|
1897
|
+
if (target >= ds[last]) return ts[last];
|
|
1898
|
+
let lo = 1, hi = last;
|
|
1899
|
+
while (lo < hi) {
|
|
1900
|
+
const mid = lo + hi >>> 1;
|
|
1901
|
+
if (ds[mid] < target) lo = mid + 1;
|
|
1902
|
+
else hi = mid;
|
|
1903
|
+
}
|
|
1904
|
+
const dPrev = ds[hi - 1];
|
|
1905
|
+
const span = ds[hi] - dPrev;
|
|
1906
|
+
const frac = span > 0 ? (target - dPrev) / span : 0;
|
|
1907
|
+
return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
|
|
1908
|
+
}
|
|
1772
1909
|
var DEFAULT_FLATNESS_TOL = 0.5;
|
|
1773
1910
|
var DEFAULT_ROTATION_TOL = 5;
|
|
1774
1911
|
var DEFAULT_MAX_SAMPLES = 32;
|
|
@@ -2041,9 +2178,211 @@ function perpDist(q, pA, pB) {
|
|
|
2041
2178
|
const cross = (q[0] - pA[0]) * dy - (q[1] - pA[1]) * dx;
|
|
2042
2179
|
return Math.abs(cross) / Math.sqrt(len2);
|
|
2043
2180
|
}
|
|
2181
|
+
function materializeMotionPathsInTree(root, opts) {
|
|
2182
|
+
const out = walkAndMaterialize(root, opts);
|
|
2183
|
+
return out != null ? out : root;
|
|
2184
|
+
}
|
|
2185
|
+
function walkAndMaterialize(node, opts) {
|
|
2186
|
+
let newChildren;
|
|
2187
|
+
if (node.children) {
|
|
2188
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
2189
|
+
const ch = node.children[i];
|
|
2190
|
+
const ret = walkAndMaterialize(ch, opts);
|
|
2191
|
+
if (ret !== null) {
|
|
2192
|
+
if (!newChildren) newChildren = node.children.slice();
|
|
2193
|
+
newChildren[i] = ret;
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
let newAnimate;
|
|
2198
|
+
const animBucket = node.animate;
|
|
2199
|
+
if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
|
|
2200
|
+
const animDef = mergeStaticTransformIntoAnimDef(animBucket, node.transform);
|
|
2201
|
+
const transformAnim = animDef.transform;
|
|
2202
|
+
if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
|
|
2203
|
+
const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
|
|
2204
|
+
if (materialized !== transformAnim) {
|
|
2205
|
+
newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialized });
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
if (!newChildren && !newAnimate) return null;
|
|
2210
|
+
const cloned = __spreadValues({}, node);
|
|
2211
|
+
if (newChildren) cloned.children = newChildren;
|
|
2212
|
+
if (newAnimate) cloned.animate = newAnimate;
|
|
2213
|
+
return cloned;
|
|
2214
|
+
}
|
|
2044
2215
|
|
|
2045
2216
|
// src/animation/PxDefinitions.ts
|
|
2046
2217
|
var PX_LOOP_JUMP_SHIFT_MS = 1;
|
|
2218
|
+
function deepEqualValue(a, b) {
|
|
2219
|
+
if (a === b) return true;
|
|
2220
|
+
if (typeof a !== typeof b || a === null || b === null || typeof a !== "object") return false;
|
|
2221
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
2222
|
+
const ka = Object.keys(a);
|
|
2223
|
+
const kb = Object.keys(b);
|
|
2224
|
+
if (ka.length !== kb.length) return false;
|
|
2225
|
+
return ka.every((k) => deepEqualValue(a[k], b[k]));
|
|
2226
|
+
}
|
|
2227
|
+
function parsePathCommands(d) {
|
|
2228
|
+
const tokens = d.split(/([MLCZmlcz]|[\s,]+)/).map((t) => t.trim()).filter((t) => t && t !== ",");
|
|
2229
|
+
const commands = [];
|
|
2230
|
+
let currentCommand = null;
|
|
2231
|
+
for (const token of tokens) {
|
|
2232
|
+
if (/[MLCZmlcz]/.test(token)) {
|
|
2233
|
+
currentCommand = { type: token, values: [] };
|
|
2234
|
+
commands.push(currentCommand);
|
|
2235
|
+
} else if (currentCommand) {
|
|
2236
|
+
const value = +token;
|
|
2237
|
+
currentCommand.values.push(Number.isNaN(value) ? 0 : value);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
return commands;
|
|
2241
|
+
}
|
|
2242
|
+
function parseSvgPathToBezier(d) {
|
|
2243
|
+
const res = [];
|
|
2244
|
+
let currentPath;
|
|
2245
|
+
const commands = parsePathCommands(d);
|
|
2246
|
+
for (const command of commands) {
|
|
2247
|
+
const type = command.type;
|
|
2248
|
+
const values = command.values;
|
|
2249
|
+
if (type === "M" || type === "m") {
|
|
2250
|
+
const x = values[0] || 0;
|
|
2251
|
+
const y = values[1] || 0;
|
|
2252
|
+
currentPath = {
|
|
2253
|
+
v: [[x, y]],
|
|
2254
|
+
i: [[x, y]],
|
|
2255
|
+
o: [[x, y]],
|
|
2256
|
+
c: false
|
|
2257
|
+
};
|
|
2258
|
+
res.push(currentPath);
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2261
|
+
if (!currentPath) {
|
|
2262
|
+
currentPath = {
|
|
2263
|
+
v: [[0, 0]],
|
|
2264
|
+
i: [[0, 0]],
|
|
2265
|
+
o: [[0, 0]],
|
|
2266
|
+
c: false
|
|
2267
|
+
};
|
|
2268
|
+
res.push(currentPath);
|
|
2269
|
+
}
|
|
2270
|
+
if (type === "L") {
|
|
2271
|
+
const x = values[0] || 0;
|
|
2272
|
+
const y = values[1] || 0;
|
|
2273
|
+
currentPath.v.push([x, y]);
|
|
2274
|
+
currentPath.i.push([x, y]);
|
|
2275
|
+
currentPath.o.push([x, y]);
|
|
2276
|
+
} else if (type === "C") {
|
|
2277
|
+
const outX = values[0] || 0;
|
|
2278
|
+
const outY = values[1] || 0;
|
|
2279
|
+
const inX2 = values[2] || 0;
|
|
2280
|
+
const inY2 = values[3] || 0;
|
|
2281
|
+
const x2 = values[4] || 0;
|
|
2282
|
+
const y2 = values[5] || 0;
|
|
2283
|
+
currentPath.o[currentPath.o.length - 1] = [outX, outY];
|
|
2284
|
+
currentPath.v.push([x2, y2]);
|
|
2285
|
+
currentPath.i.push([inX2, inY2]);
|
|
2286
|
+
currentPath.o.push([x2, y2]);
|
|
2287
|
+
} else if (type === "Z" || type === "z") {
|
|
2288
|
+
currentPath.c = true;
|
|
2289
|
+
} else {
|
|
2290
|
+
console.warn('Unsupported path command "' + type + '"');
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
return res;
|
|
2294
|
+
}
|
|
2295
|
+
function extractPathData(str2) {
|
|
2296
|
+
if (str2.startsWith("path(") && str2.endsWith(")")) {
|
|
2297
|
+
return str2.slice(5, -1);
|
|
2298
|
+
}
|
|
2299
|
+
if (/^[MmZzLlHhVvCcSsQqTtAa]/.test(str2)) {
|
|
2300
|
+
return str2;
|
|
2301
|
+
}
|
|
2302
|
+
return void 0;
|
|
2303
|
+
}
|
|
2304
|
+
function isPathString(value) {
|
|
2305
|
+
return typeof value === "string" && extractPathData(value) !== void 0;
|
|
2306
|
+
}
|
|
2307
|
+
function normalizePathValue(value) {
|
|
2308
|
+
if (value && typeof value === "object" && typeof value.pathData === "string") {
|
|
2309
|
+
const d = extractPathData(value.pathData);
|
|
2310
|
+
return d ? { paths: parseSvgPathToBezier(d) } : value;
|
|
2311
|
+
}
|
|
2312
|
+
if (value && typeof value === "object" && "paths" in value) {
|
|
2313
|
+
const pathsArray = value.paths;
|
|
2314
|
+
if (Array.isArray(pathsArray) && pathsArray.length > 0) {
|
|
2315
|
+
if (isPathString(pathsArray[0])) {
|
|
2316
|
+
const paths = [];
|
|
2317
|
+
for (const pathStr2 of pathsArray) {
|
|
2318
|
+
const d = extractPathData(pathStr2);
|
|
2319
|
+
if (d) {
|
|
2320
|
+
paths.push(...parseSvgPathToBezier(d));
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
return { paths };
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
return value;
|
|
2327
|
+
}
|
|
2328
|
+
if (Array.isArray(value)) {
|
|
2329
|
+
if (value.length > 0 && isPathString(value[0])) {
|
|
2330
|
+
const paths = [];
|
|
2331
|
+
for (const pathStr2 of value) {
|
|
2332
|
+
const d = extractPathData(pathStr2);
|
|
2333
|
+
if (d) {
|
|
2334
|
+
paths.push(...parseSvgPathToBezier(d));
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
return { paths };
|
|
2338
|
+
}
|
|
2339
|
+
return { paths: value };
|
|
2340
|
+
}
|
|
2341
|
+
if (isPathString(value)) {
|
|
2342
|
+
const d = extractPathData(value);
|
|
2343
|
+
return { paths: parseSvgPathToBezier(d) };
|
|
2344
|
+
}
|
|
2345
|
+
return value;
|
|
2346
|
+
}
|
|
2347
|
+
function resolveEasing(easing, defs) {
|
|
2348
|
+
var _a2;
|
|
2349
|
+
if (!easing) return void 0;
|
|
2350
|
+
if (Array.isArray(easing)) {
|
|
2351
|
+
return easing;
|
|
2352
|
+
}
|
|
2353
|
+
if ((_a2 = defs == null ? void 0 : defs.easings) == null ? void 0 : _a2[easing]) {
|
|
2354
|
+
return defs.easings[easing];
|
|
2355
|
+
}
|
|
2356
|
+
console.warn("Unknown easing name: " + easing);
|
|
2357
|
+
return void 0;
|
|
2358
|
+
}
|
|
2359
|
+
function resolveAnimation(animRef, defs) {
|
|
2360
|
+
var _a2;
|
|
2361
|
+
if (typeof animRef === "string") {
|
|
2362
|
+
const resolved = (_a2 = defs == null ? void 0 : defs.animations) == null ? void 0 : _a2[animRef];
|
|
2363
|
+
if (!resolved) {
|
|
2364
|
+
console.warn("Unknown animation name: " + animRef);
|
|
2365
|
+
}
|
|
2366
|
+
return resolved;
|
|
2367
|
+
}
|
|
2368
|
+
return animRef;
|
|
2369
|
+
}
|
|
2370
|
+
function resolveElementAnimation(animate, defs) {
|
|
2371
|
+
if (!animate) return [];
|
|
2372
|
+
const results = [];
|
|
2373
|
+
if (typeof animate === "string") {
|
|
2374
|
+
const resolved = resolveAnimation(animate, defs);
|
|
2375
|
+
if (resolved) results.push(resolved);
|
|
2376
|
+
} else if (Array.isArray(animate)) {
|
|
2377
|
+
for (const item of animate) {
|
|
2378
|
+
const resolved = resolveAnimation(item, defs);
|
|
2379
|
+
if (resolved) results.push(resolved);
|
|
2380
|
+
}
|
|
2381
|
+
} else {
|
|
2382
|
+
results.push(animate);
|
|
2383
|
+
}
|
|
2384
|
+
return results;
|
|
2385
|
+
}
|
|
2047
2386
|
function interpolateValue(propName, a, b, t) {
|
|
2048
2387
|
var _a2, _b;
|
|
2049
2388
|
if (propName === "d") {
|
|
@@ -2082,35 +2421,498 @@ function interpolateTransformParts(a, b, t) {
|
|
|
2082
2421
|
}
|
|
2083
2422
|
return out;
|
|
2084
2423
|
}
|
|
2085
|
-
function
|
|
2086
|
-
|
|
2087
|
-
const
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2424
|
+
function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
2425
|
+
var _a2, _b, _c, _d, _e;
|
|
2426
|
+
const totalIntervals = keyframes.length - 1;
|
|
2427
|
+
const segCount = clamp((_a2 = loop.segmentCount) != null ? _a2 : totalIntervals, 1, totalIntervals);
|
|
2428
|
+
let segKfs;
|
|
2429
|
+
if (loop.repeatAt === PxLoopRepeatAt.start) {
|
|
2430
|
+
segKfs = keyframes.slice(0, segCount + 1);
|
|
2431
|
+
} else {
|
|
2432
|
+
segKfs = keyframes.slice(totalIntervals - segCount);
|
|
2433
|
+
}
|
|
2434
|
+
const firstT = (_b = keyframes[0].t) != null ? _b : 0;
|
|
2435
|
+
const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
|
|
2436
|
+
let fillStart, fillEnd;
|
|
2437
|
+
if (loop.repeatAt === PxLoopRepeatAt.start) {
|
|
2438
|
+
fillStart = 0;
|
|
2439
|
+
fillEnd = firstT;
|
|
2440
|
+
} else {
|
|
2441
|
+
fillStart = lastT;
|
|
2442
|
+
fillEnd = duration;
|
|
2443
|
+
}
|
|
2444
|
+
const fillDuration = fillEnd - fillStart;
|
|
2445
|
+
if (fillDuration <= 0) return keyframes;
|
|
2446
|
+
const segStartT = (_d = segKfs[0].t) != null ? _d : 0;
|
|
2447
|
+
const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
|
|
2448
|
+
const segDuration = segEndT - segStartT;
|
|
2449
|
+
if (segDuration <= 0) return keyframes;
|
|
2450
|
+
const template = segKfs.map((kf) => ({
|
|
2451
|
+
relT: (kf.t - segStartT) / segDuration,
|
|
2452
|
+
v: kf.v,
|
|
2453
|
+
e: kf.e,
|
|
2454
|
+
tangentIn: keyframeTangentIn(kf),
|
|
2455
|
+
tangentOut: keyframeTangentOut(kf)
|
|
2456
|
+
}));
|
|
2457
|
+
const fullReps = Math.floor(fillDuration / segDuration);
|
|
2458
|
+
const remainder = fillDuration - fullReps * segDuration;
|
|
2459
|
+
const partialFraction = remainder / segDuration;
|
|
2460
|
+
const looped = [];
|
|
2461
|
+
const separateBoundary = loop.repeatAt !== PxLoopRepeatAt.start;
|
|
2462
|
+
const originalTerminalKf = keyframes[keyframes.length - 1];
|
|
2463
|
+
let terminalEasingOverride;
|
|
2464
|
+
let hasTerminalEasingOverride = false;
|
|
2465
|
+
function appendRep(repStart, isReversed, partial) {
|
|
2466
|
+
var _a3;
|
|
2467
|
+
let entries;
|
|
2468
|
+
if (isReversed) {
|
|
2469
|
+
entries = [];
|
|
2470
|
+
for (let i = template.length - 1; i >= 0; i--) {
|
|
2471
|
+
entries.push({
|
|
2472
|
+
relT: 1 - template[i].relT,
|
|
2473
|
+
v: template[i].v,
|
|
2474
|
+
// Easing for reversed transition: use reversed easing from the forward "from" keyframe
|
|
2475
|
+
e: i > 0 ? reverseEasing(template[i - 1].e) : void 0,
|
|
2476
|
+
// Reversed traversal swaps each vertex's in/out spatial tangents
|
|
2477
|
+
// (geometry is identical, walked backwards), so curvature and
|
|
2478
|
+
// auto-orientation survive the reversed rep.
|
|
2479
|
+
tangentIn: template[i].tangentOut,
|
|
2480
|
+
tangentOut: template[i].tangentIn
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
} else {
|
|
2484
|
+
entries = template;
|
|
2485
|
+
}
|
|
2486
|
+
const cutRelT = partial !== void 0 ? partial : 1;
|
|
2487
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2488
|
+
const entry = entries[i];
|
|
2489
|
+
if (entry.relT > cutRelT + 1e-9) {
|
|
2490
|
+
const prev = entries[i - 1];
|
|
2491
|
+
const intervalSpan = entry.relT - prev.relT;
|
|
2492
|
+
const localFrac = (cutRelT - prev.relT) / intervalSpan;
|
|
2493
|
+
const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
|
|
2494
|
+
const cutValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
|
|
2495
|
+
const { left: leftEasing } = splitEasing(prev.e, localFrac);
|
|
2496
|
+
if (looped.length > 0 && prev.relT <= cutRelT) {
|
|
2497
|
+
looped[looped.length - 1].e = leftEasing;
|
|
2498
|
+
}
|
|
2499
|
+
looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
|
|
2503
|
+
const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a3 = prevKf.t) != null ? _a3 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
|
|
2504
|
+
if (isBoundary) {
|
|
2505
|
+
if (deepEqualValue(prevKf.v, entry.v)) {
|
|
2506
|
+
if (looped.length > 0) {
|
|
2507
|
+
prevKf.e = entry.e;
|
|
2508
|
+
prevKf.tangentOut = entry.tangentOut;
|
|
2509
|
+
} else {
|
|
2510
|
+
terminalEasingOverride = entry.e;
|
|
2511
|
+
hasTerminalEasingOverride = true;
|
|
2512
|
+
}
|
|
2513
|
+
continue;
|
|
2514
|
+
}
|
|
2515
|
+
if (looped.length > 0) {
|
|
2516
|
+
delete prevKf.tangentIn;
|
|
2517
|
+
delete prevKf.tangentOut;
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
const pushed = {
|
|
2521
|
+
t: repStart + entry.relT * segDuration + (isBoundary ? PX_LOOP_JUMP_SHIFT_MS : 0),
|
|
2522
|
+
v: entry.v,
|
|
2523
|
+
e: i < entries.length - 1 ? entry.e : void 0
|
|
2524
|
+
};
|
|
2525
|
+
if (entry.tangentIn) pushed.tangentIn = entry.tangentIn;
|
|
2526
|
+
if (entry.tangentOut) pushed.tangentOut = entry.tangentOut;
|
|
2527
|
+
looped.push(pushed);
|
|
2099
2528
|
}
|
|
2100
|
-
return animDef;
|
|
2101
2529
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2530
|
+
function appendRepTail(repStart, isReversed, tailFraction) {
|
|
2531
|
+
let entries;
|
|
2532
|
+
if (isReversed) {
|
|
2533
|
+
entries = [];
|
|
2534
|
+
for (let i = template.length - 1; i >= 0; i--) {
|
|
2535
|
+
entries.push({
|
|
2536
|
+
relT: 1 - template[i].relT,
|
|
2537
|
+
v: template[i].v,
|
|
2538
|
+
e: i > 0 ? reverseEasing(template[i - 1].e) : void 0,
|
|
2539
|
+
tangentIn: template[i].tangentOut,
|
|
2540
|
+
tangentOut: template[i].tangentIn
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
} else {
|
|
2544
|
+
entries = template;
|
|
2545
|
+
}
|
|
2546
|
+
const startRelT = 1 - tailFraction;
|
|
2547
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2548
|
+
const entry = entries[i];
|
|
2549
|
+
if (entry.relT < startRelT - 1e-9) continue;
|
|
2550
|
+
const prev = entries[i - 1];
|
|
2551
|
+
if (prev && prev.relT < startRelT - 1e-9 && entry.relT > startRelT + 1e-9) {
|
|
2552
|
+
const intervalSpan = entry.relT - prev.relT;
|
|
2553
|
+
const localFrac = (startRelT - prev.relT) / intervalSpan;
|
|
2554
|
+
const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
|
|
2555
|
+
const startValue = interpolateValue(propName, prev.v, entry.v, easedFrac);
|
|
2556
|
+
const { right: rightEasing } = splitEasing(prev.e, localFrac);
|
|
2557
|
+
looped.push({ t: repStart, v: startValue, e: rightEasing });
|
|
2558
|
+
}
|
|
2559
|
+
const pushed = {
|
|
2560
|
+
t: repStart + (entry.relT - startRelT) * segDuration,
|
|
2561
|
+
v: entry.v,
|
|
2562
|
+
e: i < entries.length - 1 ? entry.e : void 0
|
|
2563
|
+
};
|
|
2564
|
+
if (entry.tangentIn) pushed.tangentIn = entry.tangentIn;
|
|
2565
|
+
if (entry.tangentOut) pushed.tangentOut = entry.tangentOut;
|
|
2566
|
+
looped.push(pushed);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
if (loop.repeatAt === PxLoopRepeatAt.start) {
|
|
2570
|
+
if (partialFraction > 1e-9) {
|
|
2571
|
+
const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
|
|
2572
|
+
appendRepTail(fillStart, isReversed, partialFraction);
|
|
2573
|
+
}
|
|
2574
|
+
for (let rep = 0; rep < fullReps; rep++) {
|
|
2575
|
+
const distFromBoundary = fullReps - 1 - rep;
|
|
2576
|
+
const isReversed = loop.direction === PxLoopDirection.alternate && distFromBoundary % 2 === 0;
|
|
2577
|
+
const repStart = fillStart + remainder + rep * segDuration;
|
|
2578
|
+
appendRep(repStart, isReversed);
|
|
2579
|
+
}
|
|
2580
|
+
} else {
|
|
2581
|
+
for (let rep = 0; rep < fullReps; rep++) {
|
|
2582
|
+
const isReversed = loop.direction === PxLoopDirection.alternate && rep % 2 === 0;
|
|
2583
|
+
const repStart = fillStart + rep * segDuration;
|
|
2584
|
+
appendRep(repStart, isReversed);
|
|
2585
|
+
}
|
|
2586
|
+
if (partialFraction > 1e-9) {
|
|
2587
|
+
const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
|
|
2588
|
+
const repStart = fillStart + fullReps * segDuration;
|
|
2589
|
+
appendRep(repStart, isReversed, partialFraction);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
if (loop.repeatAt === PxLoopRepeatAt.start) {
|
|
2593
|
+
return [...looped, ...keyframes];
|
|
2594
|
+
} else {
|
|
2595
|
+
if (hasTerminalEasingOverride && keyframes.length > 0) {
|
|
2596
|
+
const head = keyframes.slice(0, -1);
|
|
2597
|
+
const tail = __spreadProps(__spreadValues({}, keyframes[keyframes.length - 1]), { e: terminalEasingOverride });
|
|
2598
|
+
return [...head, tail, ...looped];
|
|
2599
|
+
}
|
|
2600
|
+
return [...keyframes, ...looped];
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
function normalizeKeyframes(propName, propAnim, duration, defs) {
|
|
2604
|
+
var _a2;
|
|
2605
|
+
const keyframes = propAnim.keyframes || [];
|
|
2606
|
+
const normalized = [];
|
|
2607
|
+
for (const kf of keyframes) {
|
|
2608
|
+
const timePct = keyframeTime(kf);
|
|
2609
|
+
let value = keyframeValue(kf);
|
|
2610
|
+
const easing = keyframeEasing(kf);
|
|
2611
|
+
if (propName === "d") {
|
|
2612
|
+
value = normalizePathValue(value);
|
|
2613
|
+
}
|
|
2614
|
+
const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
|
|
2615
|
+
if (PX_COLOR_ATTR_NAMES.has(propNameKebab)) {
|
|
2616
|
+
value = (_a2 = parseColor(value)) != null ? _a2 : value;
|
|
2617
|
+
}
|
|
2618
|
+
const normKf = {
|
|
2619
|
+
t: timePct,
|
|
2620
|
+
v: value,
|
|
2621
|
+
e: resolveEasing(easing, defs)
|
|
2622
|
+
};
|
|
2623
|
+
const tIn = keyframeTangentIn(kf);
|
|
2624
|
+
const tOut = keyframeTangentOut(kf);
|
|
2625
|
+
if (tIn) normKf.tangentIn = tIn;
|
|
2626
|
+
if (tOut) normKf.tangentOut = tOut;
|
|
2627
|
+
normalized.push(normKf);
|
|
2628
|
+
}
|
|
2629
|
+
normalized.sort((a, b) => {
|
|
2630
|
+
var _a3, _b;
|
|
2631
|
+
return ((_a3 = a.t) != null ? _a3 : 0) - ((_b = b.t) != null ? _b : 0);
|
|
2109
2632
|
});
|
|
2110
|
-
|
|
2111
|
-
const
|
|
2112
|
-
|
|
2113
|
-
|
|
2633
|
+
const loopRaw = propAnim.loop;
|
|
2634
|
+
const loop = loopRaw === true ? {} : loopRaw || void 0;
|
|
2635
|
+
if (loop && normalized.length >= 2) {
|
|
2636
|
+
return expandLoopKeyframes(propName, normalized, loop, duration);
|
|
2637
|
+
}
|
|
2638
|
+
return normalized;
|
|
2639
|
+
}
|
|
2640
|
+
function mergeAnimationDefinitions(animations) {
|
|
2641
|
+
const merged = {};
|
|
2642
|
+
for (const anim of animations) {
|
|
2643
|
+
for (const [prop, propAnim] of Object.entries(anim)) {
|
|
2644
|
+
merged[prop] = propAnim;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
return merged;
|
|
2648
|
+
}
|
|
2649
|
+
function materializeInternalLoopsInPropAnim(propName, propAnim, duration) {
|
|
2650
|
+
const loopRaw = propAnim.loop;
|
|
2651
|
+
if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
|
|
2652
|
+
const loop = loopRaw === true ? {} : loopRaw;
|
|
2653
|
+
const rawKfs = propAnim.keyframes;
|
|
2654
|
+
if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
|
|
2655
|
+
const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
|
|
2656
|
+
const isColor = PX_COLOR_ATTR_NAMES.has(propNameKebab);
|
|
2657
|
+
const kfs = rawKfs.map((kf) => {
|
|
2658
|
+
var _a2;
|
|
2659
|
+
const t = keyframeTime(kf);
|
|
2660
|
+
let v = keyframeValue(kf);
|
|
2661
|
+
if (propName === "d") v = normalizePathValue(v);
|
|
2662
|
+
if (isColor) v = (_a2 = parseColor(v)) != null ? _a2 : v;
|
|
2663
|
+
const e = keyframeEasing(kf);
|
|
2664
|
+
const out2 = { t, v, e };
|
|
2665
|
+
const tIn = keyframeTangentIn(kf);
|
|
2666
|
+
const tOut = keyframeTangentOut(kf);
|
|
2667
|
+
if (tIn) out2.tangentIn = tIn;
|
|
2668
|
+
if (tOut) out2.tangentOut = tOut;
|
|
2669
|
+
return out2;
|
|
2670
|
+
});
|
|
2671
|
+
const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
|
|
2672
|
+
const out = { keyframes: expanded };
|
|
2673
|
+
if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
|
|
2674
|
+
return out;
|
|
2675
|
+
}
|
|
2676
|
+
function materializeInternalLoopsInTree(root, duration) {
|
|
2677
|
+
const ret = walkAndMaterializeLoops(root, duration);
|
|
2678
|
+
return ret != null ? ret : root;
|
|
2679
|
+
}
|
|
2680
|
+
function walkAndMaterializeLoops(node, duration) {
|
|
2681
|
+
let newChildren;
|
|
2682
|
+
if (node.children) {
|
|
2683
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
2684
|
+
const ret = walkAndMaterializeLoops(node.children[i], duration);
|
|
2685
|
+
if (ret !== null) {
|
|
2686
|
+
if (!newChildren) newChildren = node.children.slice();
|
|
2687
|
+
newChildren[i] = ret;
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
let newAnimate;
|
|
2692
|
+
const animBucket = node.animate;
|
|
2693
|
+
if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
|
|
2694
|
+
const animDef = animBucket;
|
|
2695
|
+
for (const propName of Object.keys(animDef)) {
|
|
2696
|
+
const propAnim = animDef[propName];
|
|
2697
|
+
const materialized = materializeInternalLoopsInPropAnim(propName, propAnim, duration);
|
|
2698
|
+
if (materialized !== propAnim) {
|
|
2699
|
+
if (!newAnimate) newAnimate = __spreadValues({}, animDef);
|
|
2700
|
+
newAnimate[propName] = materialized;
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
if (!newChildren && !newAnimate) return null;
|
|
2705
|
+
const cloned = __spreadValues({}, node);
|
|
2706
|
+
if (newChildren) cloned.children = newChildren;
|
|
2707
|
+
if (newAnimate) cloned.animate = newAnimate;
|
|
2708
|
+
return cloned;
|
|
2709
|
+
}
|
|
2710
|
+
var _elementIdCounter = 0;
|
|
2711
|
+
function generateElementId() {
|
|
2712
|
+
return "_px_el_" + ++_elementIdCounter;
|
|
2713
|
+
}
|
|
2714
|
+
function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
|
|
2715
|
+
const normalized = {};
|
|
2716
|
+
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
2717
|
+
if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
|
|
2718
|
+
continue;
|
|
2719
|
+
}
|
|
2720
|
+
const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
|
|
2721
|
+
if (normalizedKfs.length > 0) {
|
|
2722
|
+
const out = { keyframes: normalizedKfs };
|
|
2723
|
+
if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
|
|
2724
|
+
if (propAnim.loop !== void 0) out.loop = propAnim.loop;
|
|
2725
|
+
normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materializeMotionPathInPropAnim(out) : out;
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
return normalized;
|
|
2729
|
+
}
|
|
2730
|
+
function normalizeBindings(doc, engine = PxTimelineEngine.native) {
|
|
2731
|
+
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
2732
|
+
const defs = getDefinitions(doc);
|
|
2733
|
+
const duration = animatorConfig.duration || 1e3;
|
|
2734
|
+
const bindings = [];
|
|
2735
|
+
const processAnimation = (id, animDefs, staticTransform) => {
|
|
2736
|
+
if (animDefs.length === 0) return null;
|
|
2737
|
+
const merged = mergeStaticTransformIntoAnimDef(mergeAnimationDefinitions(animDefs), staticTransform);
|
|
2738
|
+
const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
|
|
2739
|
+
if (Object.keys(normalizedAnim).length === 0) return null;
|
|
2740
|
+
return {
|
|
2741
|
+
id,
|
|
2742
|
+
animate: normalizedAnim
|
|
2743
|
+
};
|
|
2744
|
+
};
|
|
2745
|
+
const docBindings = getBindings(doc);
|
|
2746
|
+
if (docBindings) {
|
|
2747
|
+
for (const binding of docBindings) {
|
|
2748
|
+
const id = binding.target.startsWith("#") ? binding.target.slice(1) : binding.target;
|
|
2749
|
+
const animDefs = binding.animateWith.map((name) => resolveAnimation(name, defs)).filter((d) => !!d);
|
|
2750
|
+
const normalized = processAnimation(id, animDefs);
|
|
2751
|
+
if (normalized) bindings.push(normalized);
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
const processNode = (node) => {
|
|
2755
|
+
const inlineAnim = node.animate;
|
|
2756
|
+
if (inlineAnim && Object.keys(inlineAnim).length > 0) {
|
|
2757
|
+
const nodeId = node.id || generateElementId();
|
|
2758
|
+
node.id = nodeId;
|
|
2759
|
+
const normalized = processAnimation(nodeId, resolveElementAnimation(inlineAnim, defs), node.transform);
|
|
2760
|
+
if (normalized) bindings.push(normalized);
|
|
2761
|
+
}
|
|
2762
|
+
if (node.children) {
|
|
2763
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
2764
|
+
processNode(node.children[i]);
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
};
|
|
2768
|
+
if (doc.children) {
|
|
2769
|
+
for (let i = 0; i < doc.children.length; i++) {
|
|
2770
|
+
processNode(doc.children[i]);
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
return bindings;
|
|
2774
|
+
}
|
|
2775
|
+
function getKeyframesPair(keyframes, progress) {
|
|
2776
|
+
var _a2, _b;
|
|
2777
|
+
const last = keyframes.length - 1;
|
|
2778
|
+
let prevKf = keyframes[0];
|
|
2779
|
+
let nextKf = keyframes[last > 0 ? 1 : 0];
|
|
2780
|
+
for (let j = 0; j < last; j++) {
|
|
2781
|
+
const aOff = (_a2 = keyframes[j].t) != null ? _a2 : 0;
|
|
2782
|
+
const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
|
|
2783
|
+
if (aOff <= progress && progress <= bOff) {
|
|
2784
|
+
prevKf = keyframes[j];
|
|
2785
|
+
nextKf = keyframes[j + 1];
|
|
2786
|
+
break;
|
|
2787
|
+
}
|
|
2788
|
+
if (progress > bOff && j === last - 1) {
|
|
2789
|
+
prevKf = keyframes[last > 0 ? last - 1 : 0];
|
|
2790
|
+
nextKf = keyframes[last];
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
return { prevKf, nextKf };
|
|
2794
|
+
}
|
|
2795
|
+
function calcPropertyValue(propName, propAnim, progress) {
|
|
2796
|
+
var _a2, _b, _c, _d, _e;
|
|
2797
|
+
const keyframes = propAnim.keyframes || [];
|
|
2798
|
+
if (keyframes.length === 0) return null;
|
|
2799
|
+
const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
|
|
2800
|
+
let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a2 = prevKf.t) != null ? _a2 : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
|
|
2801
|
+
localProgress = clamp(localProgress, 0, 1);
|
|
2802
|
+
const easing = keyframeEasing(prevKf);
|
|
2803
|
+
if (easing && Array.isArray(easing)) {
|
|
2804
|
+
try {
|
|
2805
|
+
localProgress = cubicBezier(easing)(localProgress);
|
|
2806
|
+
} catch (e) {
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
|
|
2810
|
+
let cssValue = null;
|
|
2811
|
+
const prevV = prevKf == null ? void 0 : prevKf.v;
|
|
2812
|
+
const nextV = nextKf == null ? void 0 : nextKf.v;
|
|
2813
|
+
if (cssAttrName === "d") {
|
|
2814
|
+
const prevPaths = (_c = prevV == null ? void 0 : prevV.paths) != null ? _c : Array.isArray(prevV) ? prevV : [];
|
|
2815
|
+
const nextPaths = (_d = nextV == null ? void 0 : nextV.paths) != null ? _d : Array.isArray(nextV) ? nextV : [];
|
|
2816
|
+
cssValue = interpolateBeziers(
|
|
2817
|
+
prevPaths,
|
|
2818
|
+
nextPaths,
|
|
2819
|
+
localProgress
|
|
2820
|
+
).map((bz) => bezierToSvgPath(bz)).join("");
|
|
2821
|
+
} else if (PX_COLOR_ATTR_NAMES.has(cssAttrName)) {
|
|
2822
|
+
cssValue = toRGBA(interpolateColor(
|
|
2823
|
+
prevV || [0, 0, 0, 1],
|
|
2824
|
+
nextV || [0, 0, 0, 1],
|
|
2825
|
+
localProgress
|
|
2826
|
+
));
|
|
2827
|
+
cssAttrName = propName;
|
|
2828
|
+
} else if (cssAttrName === "stroke-dasharray") {
|
|
2829
|
+
cssValue = interpolateVec(
|
|
2830
|
+
prevV || [],
|
|
2831
|
+
nextV || [],
|
|
2832
|
+
localProgress
|
|
2833
|
+
).join(" ");
|
|
2834
|
+
cssAttrName = propName;
|
|
2835
|
+
} else if (cssAttrName === "transform" && prevV !== null && typeof prevV === "object" && !Array.isArray(prevV)) {
|
|
2836
|
+
const partKeys = /* @__PURE__ */ new Set([
|
|
2837
|
+
...prevV ? Object.keys(prevV) : [],
|
|
2838
|
+
...nextV ? Object.keys(nextV) : []
|
|
2839
|
+
]);
|
|
2840
|
+
const partsResult = {};
|
|
2841
|
+
for (const partKey of partKeys) {
|
|
2842
|
+
const prevPart = prevV == null ? void 0 : prevV[partKey];
|
|
2843
|
+
const nextPart = nextV == null ? void 0 : nextV[partKey];
|
|
2844
|
+
if (partKey === "rotate" || partKey === "skew") {
|
|
2845
|
+
partsResult[partKey] = interpolateNum(+(prevPart != null ? prevPart : 0), +(nextPart != null ? nextPart : 0), localProgress);
|
|
2846
|
+
} else if (partKey === "translate" || partKey === "scale" || partKey === "origin") {
|
|
2847
|
+
const fallback = partKey === "scale" ? [1, 1] : [0, 0];
|
|
2848
|
+
const interp = interpolateVec(prevPart || fallback, nextPart || fallback, localProgress);
|
|
2849
|
+
partsResult[partKey] = interp;
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
if (propAnimIsMotionPath(propAnim)) {
|
|
2853
|
+
const prevTr = prevV.translate;
|
|
2854
|
+
const nextTr = nextV.translate;
|
|
2855
|
+
if (Array.isArray(prevTr) && Array.isArray(nextTr)) {
|
|
2856
|
+
const sample = evaluateMotionPathSegment(
|
|
2857
|
+
prevKf,
|
|
2858
|
+
nextKf,
|
|
2859
|
+
[+prevTr[0], +prevTr[1]],
|
|
2860
|
+
[+nextTr[0], +nextTr[1]],
|
|
2861
|
+
localProgress,
|
|
2862
|
+
!!propAnim.autoOrient
|
|
2863
|
+
);
|
|
2864
|
+
partsResult.translate = [sample.translate[0], sample.translate[1]];
|
|
2865
|
+
if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg + ((_e = partsResult.rotate) != null ? _e : 0);
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
cssValue = composeTransformParts(partsResult, { withUnits: false });
|
|
2869
|
+
cssAttrName = "transform";
|
|
2870
|
+
} else if (cssAttrName === "translate") {
|
|
2871
|
+
const v = interpolateVec(
|
|
2872
|
+
prevV || [0, 0],
|
|
2873
|
+
nextV || [0, 0],
|
|
2874
|
+
localProgress
|
|
2875
|
+
);
|
|
2876
|
+
cssValue = "translate(" + v.join(",") + ")";
|
|
2877
|
+
cssAttrName = "transform";
|
|
2878
|
+
} else if (cssAttrName === "rotate") {
|
|
2879
|
+
const v = interpolateNum(
|
|
2880
|
+
+(prevV || 0),
|
|
2881
|
+
+(nextV || 0),
|
|
2882
|
+
localProgress
|
|
2883
|
+
);
|
|
2884
|
+
cssValue = "rotate(" + v + ")";
|
|
2885
|
+
cssAttrName = "transform";
|
|
2886
|
+
} else if (cssAttrName === "scale") {
|
|
2887
|
+
const v = interpolateVec(
|
|
2888
|
+
prevV || [1, 1],
|
|
2889
|
+
nextV || [1, 1],
|
|
2890
|
+
localProgress
|
|
2891
|
+
);
|
|
2892
|
+
cssValue = "scale(" + v.join(",") + ")";
|
|
2893
|
+
cssAttrName = "transform";
|
|
2894
|
+
} else {
|
|
2895
|
+
const num2 = interpolateNum(
|
|
2896
|
+
+(prevV || 0),
|
|
2897
|
+
+(nextV || 0),
|
|
2898
|
+
localProgress
|
|
2899
|
+
);
|
|
2900
|
+
cssValue = num2;
|
|
2901
|
+
}
|
|
2902
|
+
if (PX_PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
|
|
2903
|
+
cssValue = cssValue * 100 + "%";
|
|
2904
|
+
}
|
|
2905
|
+
return { k: cssAttrName, v: cssValue === null ? "" : "" + cssValue };
|
|
2906
|
+
}
|
|
2907
|
+
function calcAnimationValues(animDef, progress) {
|
|
2908
|
+
const result = {};
|
|
2909
|
+
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
2910
|
+
const computed = calcPropertyValue(propName, propAnim, progress);
|
|
2911
|
+
if (computed) {
|
|
2912
|
+
result[computed.k] = computed.v;
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
return result;
|
|
2114
2916
|
}
|
|
2115
2917
|
|
|
2116
2918
|
// src/effects/PlayerEffectsUtil.visualModel.ts
|
|
@@ -2526,6 +3328,15 @@ function transformPathData(d, m, decimals = 2) {
|
|
|
2526
3328
|
}
|
|
2527
3329
|
|
|
2528
3330
|
// src/effects/shared/transformParts.ts
|
|
3331
|
+
function partsRecord(part, value, origin) {
|
|
3332
|
+
const rec = {};
|
|
3333
|
+
if (part === "translate" /* Translate */) rec.translate = value;
|
|
3334
|
+
else if (part === "rotate" /* Rotate */) rec.rotate = value;
|
|
3335
|
+
else if (part === "skew" /* Skew */) rec.skew = value;
|
|
3336
|
+
else rec.scale = value;
|
|
3337
|
+
if (origin && part !== "translate" /* Translate */) rec.origin = origin;
|
|
3338
|
+
return rec;
|
|
3339
|
+
}
|
|
2529
3340
|
function readAnimatable(raw) {
|
|
2530
3341
|
var _a2, _b;
|
|
2531
3342
|
if (raw === void 0) return { kind: "absent" /* Absent */ };
|
|
@@ -2544,6 +3355,24 @@ function readAnimatable(raw) {
|
|
|
2544
3355
|
}
|
|
2545
3356
|
return { kind: "static" /* Static */, value: raw };
|
|
2546
3357
|
}
|
|
3358
|
+
function writeAnimatableChannel(node, attrName, read, opts) {
|
|
3359
|
+
var _a2, _b, _c, _d;
|
|
3360
|
+
const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
|
|
3361
|
+
if (read.kind === "absent" /* Absent */) return;
|
|
3362
|
+
if (read.kind === "static" /* Static */) {
|
|
3363
|
+
node[attrName] = toOut(read.value);
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3366
|
+
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
3367
|
+
const animate = __spreadValues({}, prevAnimate || {});
|
|
3368
|
+
const block = { keyframes: read.keyframes };
|
|
3369
|
+
if (read.loop !== void 0) block.loop = read.loop;
|
|
3370
|
+
if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
|
|
3371
|
+
animate[attrName] = block;
|
|
3372
|
+
node.animate = animate;
|
|
3373
|
+
const baseline = (_d = (_b = read.base) != null ? _b : (_a2 = read.keyframes[0]) == null ? void 0 : _a2.value) != null ? _d : (_c = read.keyframes[0]) == null ? void 0 : _c.v;
|
|
3374
|
+
if (baseline !== void 0) node[attrName] = toOut(baseline);
|
|
3375
|
+
}
|
|
2547
3376
|
function normalizeKeyframe(kf) {
|
|
2548
3377
|
if (!kf || typeof kf !== "object") return kf;
|
|
2549
3378
|
const k = kf;
|
|
@@ -2558,6 +3387,22 @@ function normalizeKeyframe(kf) {
|
|
|
2558
3387
|
if (out.tangentIn === void 0 && k.ti !== void 0) out.tangentIn = k.ti;
|
|
2559
3388
|
return out;
|
|
2560
3389
|
}
|
|
3390
|
+
function readStaticOrigin(raw, ctx) {
|
|
3391
|
+
var _a2;
|
|
3392
|
+
const o = readAnimatable(raw);
|
|
3393
|
+
if (o.kind === "absent" /* Absent */) return void 0;
|
|
3394
|
+
if (o.kind === "static" /* Static */) return o.value;
|
|
3395
|
+
ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
|
|
3396
|
+
return (_a2 = o.keyframes[0]) == null ? void 0 : _a2.value;
|
|
3397
|
+
}
|
|
3398
|
+
function keyframeWith(kf, value) {
|
|
3399
|
+
const out = { value };
|
|
3400
|
+
if (kf.time !== void 0) out.time = kf.time;
|
|
3401
|
+
if (kf.easing !== void 0) out.easing = kf.easing;
|
|
3402
|
+
if (kf.tangentOut !== void 0) out.tangentOut = kf.tangentOut;
|
|
3403
|
+
if (kf.tangentIn !== void 0) out.tangentIn = kf.tangentIn;
|
|
3404
|
+
return out;
|
|
3405
|
+
}
|
|
2561
3406
|
|
|
2562
3407
|
// src/effects/text/textGlyphsEffect.ts
|
|
2563
3408
|
var DEFAULT_FONT_SIZE = 16;
|
|
@@ -3106,22 +3951,149 @@ function materializeGlyphText(node, opts) {
|
|
|
3106
3951
|
if (opts.alongPath) return materializeGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
|
|
3107
3952
|
return materializeGlyphTextHorizontal(node, opts);
|
|
3108
3953
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
if (read.kind === "static" /* Static */ && typeof read.value === "number") return { min: read.value, max: read.value };
|
|
3115
|
-
if (read.kind === "animated" /* Animated */ && read.keyframes.length) {
|
|
3116
|
-
const vals = read.keyframes.map((k) => Number(k.value) || 0);
|
|
3117
|
-
return { min: Math.min(...vals), max: Math.max(...vals) };
|
|
3954
|
+
function applyTextGlyphsEffect(node, fx, ctx) {
|
|
3955
|
+
if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
|
|
3956
|
+
if (!ctx.glyphs) {
|
|
3957
|
+
ctx.warnings.push("textGlyphs: no definitions.fonts \u2014 left as native <text>");
|
|
3958
|
+
return node;
|
|
3118
3959
|
}
|
|
3119
|
-
return {
|
|
3960
|
+
return materializeGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
|
|
3120
3961
|
}
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3962
|
+
function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
|
|
3963
|
+
if (!ctx.glyphs) {
|
|
3964
|
+
ctx.warnings.push("textGlyphs: no definitions.fonts");
|
|
3965
|
+
return null;
|
|
3966
|
+
}
|
|
3967
|
+
return materializeGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3970
|
+
// src/util/PxNodeCloneUtil.ts
|
|
3971
|
+
function deepClonePxNode(value) {
|
|
3972
|
+
if (value === null || typeof value !== "object") return value;
|
|
3973
|
+
if (Array.isArray(value)) return value.map(deepClonePxNode);
|
|
3974
|
+
const out = {};
|
|
3975
|
+
for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
|
|
3976
|
+
return out;
|
|
3977
|
+
}
|
|
3978
|
+
function regenerateIdsAndRewriteRefs(root, genId3) {
|
|
3979
|
+
const oldToNew = /* @__PURE__ */ new Map();
|
|
3980
|
+
const walkAssign = (n) => {
|
|
3981
|
+
var _a2;
|
|
3982
|
+
if (typeof n.id === "string") {
|
|
3983
|
+
const newId = genId3();
|
|
3984
|
+
oldToNew.set(n.id, newId);
|
|
3985
|
+
n.id = newId;
|
|
3986
|
+
}
|
|
3987
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
|
|
3988
|
+
};
|
|
3989
|
+
walkAssign(root);
|
|
3990
|
+
const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
|
|
3991
|
+
const newId = oldToNew.get(oldId);
|
|
3992
|
+
return newId ? "url(#" + newId + ")" : m;
|
|
3993
|
+
});
|
|
3994
|
+
const walkRewrite = (n) => {
|
|
3995
|
+
var _a2;
|
|
3996
|
+
if (typeof n.href === "string" && n.href.startsWith("#")) {
|
|
3997
|
+
const newId = oldToNew.get(n.href.slice(1));
|
|
3998
|
+
if (newId) n.href = "#" + newId;
|
|
3999
|
+
}
|
|
4000
|
+
for (const k of Object.keys(n)) {
|
|
4001
|
+
if (k === "children" || k === "effects" || k === "meta" || k === "animate" || k === "href" || k === "id") continue;
|
|
4002
|
+
const v = n[k];
|
|
4003
|
+
if (typeof v === "string" && v.indexOf("url(#") !== -1) {
|
|
4004
|
+
n[k] = rewriteUrl(v);
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
|
|
4008
|
+
};
|
|
4009
|
+
walkRewrite(root);
|
|
4010
|
+
return oldToNew;
|
|
4011
|
+
}
|
|
4012
|
+
function toFiniteNum(v) {
|
|
4013
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? parseFloat(v) : NaN;
|
|
4014
|
+
return Number.isFinite(n) ? n : 0;
|
|
4015
|
+
}
|
|
4016
|
+
function applyUseOffsetToG(gNode) {
|
|
4017
|
+
var _a2;
|
|
4018
|
+
const x = toFiniteNum(gNode.x);
|
|
4019
|
+
const y = toFiniteNum(gNode.y);
|
|
4020
|
+
delete gNode.x;
|
|
4021
|
+
delete gNode.y;
|
|
4022
|
+
if (!x && !y) return gNode;
|
|
4023
|
+
const offset = "translate(" + x + "," + y + ")";
|
|
4024
|
+
const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
|
|
4025
|
+
if (carriesTransform) {
|
|
4026
|
+
const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
|
|
4027
|
+
gNode.children = [inner];
|
|
4028
|
+
} else {
|
|
4029
|
+
gNode.transform = offset;
|
|
4030
|
+
}
|
|
4031
|
+
return gNode;
|
|
4032
|
+
}
|
|
4033
|
+
|
|
4034
|
+
// src/effects/shared/util.ts
|
|
4035
|
+
function genId(ctx, prefix) {
|
|
4036
|
+
return "_lw_" + prefix + "_" + ctx.nextId++;
|
|
4037
|
+
}
|
|
4038
|
+
function stripHash(href) {
|
|
4039
|
+
return typeof href === "string" ? href.replace(/^#/, "") : void 0;
|
|
4040
|
+
}
|
|
4041
|
+
function indexById(node, map) {
|
|
4042
|
+
var _a2;
|
|
4043
|
+
if (typeof node.id === "string") map.set(node.id, node);
|
|
4044
|
+
(_a2 = node.children) == null ? void 0 : _a2.forEach((child) => indexById(child, map));
|
|
4045
|
+
}
|
|
4046
|
+
function spliceDefs(root, defs) {
|
|
4047
|
+
if (!defs.length) return;
|
|
4048
|
+
const existing = root.children || (root.children = []);
|
|
4049
|
+
existing.unshift({ type: "defs", children: defs });
|
|
4050
|
+
}
|
|
4051
|
+
var clone = deepClonePxNode;
|
|
4052
|
+
function regenerateIdsInClone(root, ctx) {
|
|
4053
|
+
return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
|
|
4054
|
+
}
|
|
4055
|
+
|
|
4056
|
+
// src/effects/text/textPathEffect.ts
|
|
4057
|
+
var EXTEND_MARGIN_FRAC = 0.15;
|
|
4058
|
+
function numRange(v) {
|
|
4059
|
+
const read = readAnimatable(v);
|
|
4060
|
+
if (read.kind === "static" /* Static */ && typeof read.value === "number") return { min: read.value, max: read.value };
|
|
4061
|
+
if (read.kind === "animated" /* Animated */ && read.keyframes.length) {
|
|
4062
|
+
const vals = read.keyframes.map((k) => Number(k.value) || 0);
|
|
4063
|
+
return { min: Math.min(...vals), max: Math.max(...vals) };
|
|
4064
|
+
}
|
|
4065
|
+
return { min: 0, max: 0 };
|
|
4066
|
+
}
|
|
4067
|
+
function estimateTextAdvance(node) {
|
|
4068
|
+
let chars = 0, maxFont = 16;
|
|
4069
|
+
const walk = (el) => {
|
|
4070
|
+
var _a2;
|
|
4071
|
+
const fs = parseFloat(String((_a2 = el.fontSize) != null ? _a2 : "")) || 0;
|
|
4072
|
+
if (fs) maxFont = Math.max(maxFont, fs);
|
|
4073
|
+
const t = el.textContent;
|
|
4074
|
+
if (typeof t === "string") chars += t.length;
|
|
4075
|
+
if (el.children) for (const c of el.children) walk(c);
|
|
4076
|
+
};
|
|
4077
|
+
walk(node);
|
|
4078
|
+
return chars * maxFont;
|
|
4079
|
+
}
|
|
4080
|
+
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
4081
|
+
function shiftAnimatable(v, by) {
|
|
4082
|
+
if (!by || v === void 0 || v === null) return v;
|
|
4083
|
+
const read = readAnimatable(v);
|
|
4084
|
+
if (read.kind === "absent" /* Absent */) return v;
|
|
4085
|
+
if (read.kind === "static" /* Static */) return typeof v === "number" ? read.value + by : { value: read.value + by };
|
|
4086
|
+
const out = {
|
|
4087
|
+
keyframes: read.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by }))
|
|
4088
|
+
};
|
|
4089
|
+
if (read.loop !== void 0) out.loop = read.loop;
|
|
4090
|
+
if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
|
|
4091
|
+
if (read.base !== void 0) out.value = read.base + by;
|
|
4092
|
+
return out;
|
|
4093
|
+
}
|
|
4094
|
+
function extendedPathForBrowser(pathD, opts) {
|
|
4095
|
+
var _a2;
|
|
4096
|
+
if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
|
|
3125
4097
|
const sampler = createPathSampler(pathD);
|
|
3126
4098
|
if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
|
|
3127
4099
|
const L = sampler.totalLength;
|
|
@@ -3141,33 +4113,2083 @@ function extendedPathForBrowser(pathD, opts) {
|
|
|
3141
4113
|
const rest = pathD.replace(/^\s*[Mm]\s*-?[\d.]+[\s,]+-?[\d.]+/, "");
|
|
3142
4114
|
d = "M" + r3(sx) + "," + r3(sy) + "L" + r3(s.x) + "," + r3(s.y) + rest;
|
|
3143
4115
|
}
|
|
3144
|
-
if (endExt > 0) {
|
|
3145
|
-
const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
|
|
3146
|
-
d += "L" + r3(ex) + "," + r3(ey);
|
|
4116
|
+
if (endExt > 0) {
|
|
4117
|
+
const ex = e.x + Math.cos(e.angle) * endExt, ey = e.y + Math.sin(e.angle) * endExt;
|
|
4118
|
+
d += "L" + r3(ex) + "," + r3(ey);
|
|
4119
|
+
}
|
|
4120
|
+
return { d, startShift: startExt };
|
|
4121
|
+
}
|
|
4122
|
+
function applyTextPathEffect(node, fx, ctx) {
|
|
4123
|
+
var _a2;
|
|
4124
|
+
if (!fx || typeof fx.pathData !== "string" || !fx.pathData) return node;
|
|
4125
|
+
const pathId = genId(ctx, "tpath");
|
|
4126
|
+
const { d, startShift } = extendedPathForBrowser(fx.pathData, {
|
|
4127
|
+
pathOverflow: fx.pathOverflow,
|
|
4128
|
+
startOffset: fx.startOffset,
|
|
4129
|
+
textLength: fx.textLength,
|
|
4130
|
+
advance: estimateTextAdvance(node)
|
|
4131
|
+
});
|
|
4132
|
+
ctx.defs.push({ type: "path", id: pathId, d });
|
|
4133
|
+
const textPath = {
|
|
4134
|
+
type: "textPath",
|
|
4135
|
+
href: "#" + pathId,
|
|
4136
|
+
children: (_a2 = node.children) != null ? _a2 : []
|
|
4137
|
+
};
|
|
4138
|
+
if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
|
|
4139
|
+
if (fx.method !== void 0) textPath.method = fx.method;
|
|
4140
|
+
if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
|
|
4141
|
+
applyAnimatableNumber(textPath, "startOffset", shiftAnimatable(fx.startOffset, startShift));
|
|
4142
|
+
applyAnimatableNumber(textPath, "textLength", fx.textLength);
|
|
4143
|
+
node.children = [textPath];
|
|
4144
|
+
return node;
|
|
4145
|
+
}
|
|
4146
|
+
function applyAnimatableNumber(node, attrName, raw) {
|
|
4147
|
+
if (raw === void 0 || raw === null) return;
|
|
4148
|
+
writeAnimatableChannel(node, attrName, readAnimatable(raw), { asString: true });
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
// src/format/PxDocumentDiagnostic.ts
|
|
4152
|
+
var MAX_REPORTED = 6;
|
|
4153
|
+
function diagnoseDocument(doc) {
|
|
4154
|
+
try {
|
|
4155
|
+
return { problems: validateDocument(doc) };
|
|
4156
|
+
} catch (e) {
|
|
4157
|
+
return { problems: [] };
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
function reportDocumentDiagnostics(doc, where) {
|
|
4161
|
+
const { problems } = diagnoseDocument(doc);
|
|
4162
|
+
if (!problems.length) return;
|
|
4163
|
+
const shown = problems.slice(0, MAX_REPORTED);
|
|
4164
|
+
const more = problems.length - shown.length;
|
|
4165
|
+
console.warn(
|
|
4166
|
+
where + ": this document does not match the animation schema in " + problems.length + " place" + (problems.length === 1 ? "" : "s") + ".\n" + shown.map((p) => " - " + p).join("\n") + (more > 0 ? "\n \u2026 and " + more + " more" : "") + "\n\nIf you did not author these keys, the usual cause is a build that MANGLES PROPERTY NAMES. An animation document is data loaded at runtime, so renaming the property reads inside the player stops them matching the keys in the JSON, and the animation silently does nothing. Feed the published reserved-name list to your minifier \u2014 @pixodesk/svg-animator-web/mangle-reserved.json \u2014 see docs/library/minification.md."
|
|
4167
|
+
);
|
|
4168
|
+
}
|
|
4169
|
+
|
|
4170
|
+
// src/effects/transform/transformationEffect.ts
|
|
4171
|
+
function applyTransformByEffect(node, fx, ctx) {
|
|
4172
|
+
if (!fx) return node;
|
|
4173
|
+
delete node.transform;
|
|
4174
|
+
let n = node;
|
|
4175
|
+
n = wrapOrigin(
|
|
4176
|
+
n,
|
|
4177
|
+
fx.origin,
|
|
4178
|
+
/*invert=*/
|
|
4179
|
+
true
|
|
4180
|
+
);
|
|
4181
|
+
n = wrapTransformPart(n, "scale" /* Scale */, normalizeScale(fx.scale), ctx);
|
|
4182
|
+
n = wrapTransformPart(n, "skew" /* Skew */, fx.skew, ctx);
|
|
4183
|
+
n = wrapTransformPart(n, "rotate" /* Rotate */, fx.rotate, ctx);
|
|
4184
|
+
n = wrapOrigin(
|
|
4185
|
+
n,
|
|
4186
|
+
fx.origin,
|
|
4187
|
+
/*invert=*/
|
|
4188
|
+
false
|
|
4189
|
+
);
|
|
4190
|
+
if (translateHasAutoOrient(fx.translate)) {
|
|
4191
|
+
n = wrapOrigin(
|
|
4192
|
+
n,
|
|
4193
|
+
fx.origin,
|
|
4194
|
+
/*invert=*/
|
|
4195
|
+
true
|
|
4196
|
+
);
|
|
4197
|
+
n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
|
|
4198
|
+
n = wrapOrigin(
|
|
4199
|
+
n,
|
|
4200
|
+
fx.origin,
|
|
4201
|
+
/*invert=*/
|
|
4202
|
+
false
|
|
4203
|
+
);
|
|
4204
|
+
} else {
|
|
4205
|
+
n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
|
|
4206
|
+
}
|
|
4207
|
+
if (n !== node && node.id) {
|
|
4208
|
+
n.id = node.id;
|
|
4209
|
+
delete node.id;
|
|
4210
|
+
}
|
|
4211
|
+
return n;
|
|
4212
|
+
}
|
|
4213
|
+
function translateHasAutoOrient(translate) {
|
|
4214
|
+
if (!translate || typeof translate !== "object") return false;
|
|
4215
|
+
const obj = translate;
|
|
4216
|
+
if (obj.autoOrient) return true;
|
|
4217
|
+
return Array.isArray(obj.keyframes) && obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
|
|
4218
|
+
}
|
|
4219
|
+
function normalizeScale(raw) {
|
|
4220
|
+
return raw;
|
|
4221
|
+
}
|
|
4222
|
+
function wrapTransformPart(inner, part, raw, ctx) {
|
|
4223
|
+
if (raw === void 0) return inner;
|
|
4224
|
+
const v = readAnimatable(raw);
|
|
4225
|
+
if (v.kind === "static" /* Static */) {
|
|
4226
|
+
return { type: "g", transform: { value: partsRecord(part, v.value, void 0) }, children: [inner] };
|
|
4227
|
+
}
|
|
4228
|
+
if (v.kind === "animated" /* Animated */) {
|
|
4229
|
+
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
|
|
4230
|
+
if (v.autoOrient) animTr.autoOrient = true;
|
|
4231
|
+
if (v.loop !== void 0) animTr.loop = v.loop;
|
|
4232
|
+
return {
|
|
4233
|
+
type: "g",
|
|
4234
|
+
animate: { transform: animTr },
|
|
4235
|
+
children: [inner]
|
|
4236
|
+
};
|
|
4237
|
+
}
|
|
4238
|
+
return inner;
|
|
4239
|
+
}
|
|
4240
|
+
function wrapOrigin(inner, raw, invert) {
|
|
4241
|
+
if (raw === void 0) return inner;
|
|
4242
|
+
const v = readAnimatable(raw);
|
|
4243
|
+
const sign = (value) => invert ? [-value[0], -value[1]] : value;
|
|
4244
|
+
if (v.kind === "absent" /* Absent */) return inner;
|
|
4245
|
+
if (v.kind === "static" /* Static */) {
|
|
4246
|
+
if (v.value[0] === 0 && v.value[1] === 0) return inner;
|
|
4247
|
+
return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
|
|
4248
|
+
}
|
|
4249
|
+
if (v.kind === "animated" /* Animated */) {
|
|
4250
|
+
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) };
|
|
4251
|
+
if (v.loop !== void 0) animTr.loop = v.loop;
|
|
4252
|
+
return {
|
|
4253
|
+
type: "g",
|
|
4254
|
+
animate: { transform: animTr },
|
|
4255
|
+
children: [inner]
|
|
4256
|
+
};
|
|
4257
|
+
}
|
|
4258
|
+
return inner;
|
|
4259
|
+
}
|
|
4260
|
+
|
|
4261
|
+
// src/effects/reference/contentRefSplit.ts
|
|
4262
|
+
function identifyContentRefTargets(node, ctx, allocator) {
|
|
4263
|
+
var _a2, _b, _c;
|
|
4264
|
+
if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
|
|
4265
|
+
const sourceId = stripHash(node.effects.clone.source);
|
|
4266
|
+
if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
|
|
4267
|
+
ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
(_c = node.children) == null ? void 0 : _c.forEach((c) => identifyContentRefTargets(c, ctx, allocator));
|
|
4271
|
+
}
|
|
4272
|
+
function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
|
|
4273
|
+
const outerBody = liftBodyTranslate(node, transformBy);
|
|
4274
|
+
if (typeof node.id === "string") delete node.id;
|
|
4275
|
+
const { outer: outerTr, inner: innerTr } = splitTransformByEffect(transformBy);
|
|
4276
|
+
let innerNode = node;
|
|
4277
|
+
innerNode = applyTransformByEffect(innerNode, innerTr, ctx);
|
|
4278
|
+
const innerWrapper = { type: "g", id: innerId, children: [innerNode] };
|
|
4279
|
+
let outerWrapper = { type: "g", id: originalId, children: [innerWrapper] };
|
|
4280
|
+
if (outerBody.transform !== void 0) outerWrapper.transform = outerBody.transform;
|
|
4281
|
+
if (outerBody.animate !== void 0) outerWrapper.animate = outerBody.animate;
|
|
4282
|
+
if (outerTr) {
|
|
4283
|
+
delete outerWrapper.id;
|
|
4284
|
+
outerWrapper = applyTransformByEffect(outerWrapper, outerTr, ctx);
|
|
4285
|
+
outerWrapper.id = originalId;
|
|
4286
|
+
}
|
|
4287
|
+
return outerWrapper;
|
|
4288
|
+
}
|
|
4289
|
+
function liftBodyTranslate(node, transformBy) {
|
|
4290
|
+
var _a2, _b, _c;
|
|
4291
|
+
const out = {};
|
|
4292
|
+
let didLiftAnimate = false;
|
|
4293
|
+
const animTr = (_a2 = node.animate) == null ? void 0 : _a2.transform;
|
|
4294
|
+
if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
|
|
4295
|
+
const kfs = animTr.keyframes;
|
|
4296
|
+
const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
|
|
4297
|
+
if (hasTranslate) {
|
|
4298
|
+
const outerHasOrigin = needsOriginOnOuter(animTr);
|
|
4299
|
+
const outerKfs = kfs.map((kf) => {
|
|
4300
|
+
const v = kf.value || {};
|
|
4301
|
+
const newValue = {};
|
|
4302
|
+
if (v.translate !== void 0) newValue.translate = v.translate;
|
|
4303
|
+
if (outerHasOrigin && v.origin !== void 0) newValue.origin = v.origin;
|
|
4304
|
+
const outerKf = { value: newValue };
|
|
4305
|
+
if (kf.time !== void 0) outerKf.time = kf.time;
|
|
4306
|
+
if (kf.easing !== void 0) outerKf.easing = kf.easing;
|
|
4307
|
+
if (kf.tangentOut !== void 0) outerKf.tangentOut = kf.tangentOut;
|
|
4308
|
+
if (kf.tangentIn !== void 0) outerKf.tangentIn = kf.tangentIn;
|
|
4309
|
+
return outerKf;
|
|
4310
|
+
});
|
|
4311
|
+
const outerAnimTr = { keyframes: outerKfs };
|
|
4312
|
+
if (animTr.autoOrient) outerAnimTr.autoOrient = true;
|
|
4313
|
+
const srcLoop = animTr.loop;
|
|
4314
|
+
if (srcLoop !== void 0) outerAnimTr.loop = srcLoop;
|
|
4315
|
+
out.animate = { transform: outerAnimTr };
|
|
4316
|
+
const innerHasPivotedPart = kfs.some((kf) => {
|
|
4317
|
+
const v = kf.value || {};
|
|
4318
|
+
return v.rotate !== void 0 || v.scale !== void 0;
|
|
4319
|
+
});
|
|
4320
|
+
const innerKfs = kfs.map((kf) => {
|
|
4321
|
+
const v = kf.value || {};
|
|
4322
|
+
const newValue = {};
|
|
4323
|
+
if (v.rotate !== void 0) newValue.rotate = v.rotate;
|
|
4324
|
+
if (v.scale !== void 0) newValue.scale = v.scale;
|
|
4325
|
+
if (v.origin !== void 0 && (!outerHasOrigin || innerHasPivotedPart)) newValue.origin = v.origin;
|
|
4326
|
+
const innerKf = { value: newValue };
|
|
4327
|
+
if (kf.time !== void 0) innerKf.time = kf.time;
|
|
4328
|
+
if (kf.easing !== void 0) innerKf.easing = kf.easing;
|
|
4329
|
+
return innerKf;
|
|
4330
|
+
});
|
|
4331
|
+
const allInnerEmpty = innerKfs.every((kf) => Object.keys(kf.value).length === 0);
|
|
4332
|
+
if (allInnerEmpty) {
|
|
4333
|
+
delete node.animate.transform;
|
|
4334
|
+
if (node.animate && Object.keys(node.animate).length === 0) delete node.animate;
|
|
4335
|
+
} else {
|
|
4336
|
+
const innerAnimTr = { keyframes: innerKfs };
|
|
4337
|
+
if (srcLoop !== void 0) innerAnimTr.loop = srcLoop;
|
|
4338
|
+
node.animate.transform = innerAnimTr;
|
|
4339
|
+
}
|
|
4340
|
+
didLiftAnimate = true;
|
|
4341
|
+
}
|
|
4342
|
+
}
|
|
4343
|
+
const transformationHasTranslate = (transformBy == null ? void 0 : transformBy.translate) !== void 0;
|
|
4344
|
+
const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
|
|
4345
|
+
const liftedAnimateIsAutoOriented = didLiftAnimate && needsOriginOnOuter(((_b = node.animate) == null ? void 0 : _b.transform) || void 0) || didLiftAnimate && needsOriginOnOuter(((_c = out.animate) == null ? void 0 : _c.transform) || void 0);
|
|
4346
|
+
if (typeof node.transform === "string") {
|
|
4347
|
+
const split = splitTransformString(node.transform);
|
|
4348
|
+
if (stripBodyTranslateOnly) {
|
|
4349
|
+
if (split.translate !== void 0) {
|
|
4350
|
+
if (split.rest) node.transform = split.rest;
|
|
4351
|
+
else delete node.transform;
|
|
4352
|
+
} else if (isPureTranslateBody(node.transform)) {
|
|
4353
|
+
delete node.transform;
|
|
4354
|
+
} else if (liftedAnimateIsAutoOriented && isSingleMatrixBody(node.transform)) {
|
|
4355
|
+
delete node.transform;
|
|
4356
|
+
}
|
|
4357
|
+
} else if (split.translate) {
|
|
4358
|
+
out.transform = split.translate;
|
|
4359
|
+
if (split.rest) node.transform = split.rest;
|
|
4360
|
+
else delete node.transform;
|
|
4361
|
+
}
|
|
4362
|
+
} else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes) {
|
|
4363
|
+
const wrapped = node.transform.value;
|
|
4364
|
+
const isWrapped = !!(wrapped && typeof wrapped === "object");
|
|
4365
|
+
const value = isWrapped ? wrapped : node.transform;
|
|
4366
|
+
const rewrap = (rec) => isWrapped ? { value: rec } : rec;
|
|
4367
|
+
if (Array.isArray(value.translate)) {
|
|
4368
|
+
const rest = __spreadValues({}, value);
|
|
4369
|
+
delete rest.translate;
|
|
4370
|
+
const hasRest = Object.keys(rest).length > 0;
|
|
4371
|
+
if (stripBodyTranslateOnly) {
|
|
4372
|
+
if (hasRest) node.transform = rewrap(rest);
|
|
4373
|
+
else delete node.transform;
|
|
4374
|
+
} else {
|
|
4375
|
+
out.transform = rewrap({ translate: value.translate });
|
|
4376
|
+
if (hasRest) node.transform = rewrap(rest);
|
|
4377
|
+
else delete node.transform;
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
}
|
|
4381
|
+
return out;
|
|
4382
|
+
}
|
|
4383
|
+
function isSingleMatrixBody(s) {
|
|
4384
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
4385
|
+
let count = 0;
|
|
4386
|
+
let isMatrix = false;
|
|
4387
|
+
let m;
|
|
4388
|
+
while (m = re.exec(s)) {
|
|
4389
|
+
count++;
|
|
4390
|
+
if (m[1] === "matrix") isMatrix = true;
|
|
4391
|
+
}
|
|
4392
|
+
return count === 1 && isMatrix;
|
|
4393
|
+
}
|
|
4394
|
+
function isPureTranslateBody(s) {
|
|
4395
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
4396
|
+
const ops = [];
|
|
4397
|
+
let m;
|
|
4398
|
+
while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
|
|
4399
|
+
if (ops.length !== 1) return false;
|
|
4400
|
+
if (ops[0].name === "translate") return true;
|
|
4401
|
+
if (ops[0].name !== "matrix") return false;
|
|
4402
|
+
const args = /matrix\(([^)]*)\)/.exec(ops[0].full);
|
|
4403
|
+
if (!args) return false;
|
|
4404
|
+
const nums = args[1].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
4405
|
+
return nums.length >= 4 && nums[0] === 1 && nums[1] === 0 && nums[2] === 0 && nums[3] === 1;
|
|
4406
|
+
}
|
|
4407
|
+
function splitTransformString(s) {
|
|
4408
|
+
const ops = [];
|
|
4409
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
4410
|
+
let m;
|
|
4411
|
+
while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
|
|
4412
|
+
if (!ops.length) return { rest: s || void 0 };
|
|
4413
|
+
if (ops.every((o) => o.name === "translate")) {
|
|
4414
|
+
return { translate: ops.map((o) => o.full).join("") };
|
|
4415
|
+
}
|
|
4416
|
+
const leading = ops[0];
|
|
4417
|
+
const trailing = ops[ops.length - 1];
|
|
4418
|
+
if (trailing.name === "translate" && leading.name === "translate") {
|
|
4419
|
+
const trailingVec = parseTranslateArgs(trailing.full);
|
|
4420
|
+
const leadingVec = parseTranslateArgs(leading.full);
|
|
4421
|
+
const ox = -trailingVec[0];
|
|
4422
|
+
const oy = -trailingVec[1];
|
|
4423
|
+
const userTx = leadingVec[0] - ox;
|
|
4424
|
+
const userTy = leadingVec[1] - oy;
|
|
4425
|
+
if (userTx === 0 && userTy === 0) return { rest: s };
|
|
4426
|
+
const middleAndTrailing = "translate(" + ox + "," + oy + ")" + ops.slice(1).map((o) => o.full).join("");
|
|
4427
|
+
return { translate: "translate(" + userTx + "," + userTy + ")", rest: middleAndTrailing };
|
|
4428
|
+
}
|
|
4429
|
+
if (trailing.name === "translate") return { rest: s };
|
|
4430
|
+
const lifted = [];
|
|
4431
|
+
let i = 0;
|
|
4432
|
+
while (i < ops.length && ops[i].name === "translate") {
|
|
4433
|
+
lifted.push(ops[i].full);
|
|
4434
|
+
i++;
|
|
4435
|
+
}
|
|
4436
|
+
if (!lifted.length) return { rest: s };
|
|
4437
|
+
const rest = ops.slice(i).map((o) => o.full).join("");
|
|
4438
|
+
return {
|
|
4439
|
+
translate: lifted.join(""),
|
|
4440
|
+
rest: rest || void 0
|
|
4441
|
+
};
|
|
4442
|
+
}
|
|
4443
|
+
function parseTranslateArgs(translateOp) {
|
|
4444
|
+
const m = /translate\(([^)]*)\)/.exec(translateOp);
|
|
4445
|
+
if (!m) return [0, 0];
|
|
4446
|
+
const nums = m[1].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
4447
|
+
return [nums[0] || 0, nums[1] || 0];
|
|
4448
|
+
}
|
|
4449
|
+
function splitTransformByEffect(fx) {
|
|
4450
|
+
if (!fx) return {};
|
|
4451
|
+
const originOnOuter = needsOriginOnOuter(fx.translate);
|
|
4452
|
+
const innerHasPivotedPart = fx.rotate !== void 0 || fx.scale !== void 0;
|
|
4453
|
+
const outer = {};
|
|
4454
|
+
const inner = {};
|
|
4455
|
+
if (fx.translate !== void 0) outer.translate = fx.translate;
|
|
4456
|
+
if (originOnOuter && fx.origin !== void 0) outer.origin = fx.origin;
|
|
4457
|
+
if (fx.rotate !== void 0) inner.rotate = fx.rotate;
|
|
4458
|
+
if (fx.scale !== void 0) inner.scale = fx.scale;
|
|
4459
|
+
if (fx.skew !== void 0) inner.skew = fx.skew;
|
|
4460
|
+
if (fx.origin !== void 0 && (!originOnOuter || innerHasPivotedPart)) inner.origin = fx.origin;
|
|
4461
|
+
return {
|
|
4462
|
+
outer: Object.keys(outer).length ? outer : void 0,
|
|
4463
|
+
inner: Object.keys(inner).length ? inner : void 0
|
|
4464
|
+
};
|
|
4465
|
+
}
|
|
4466
|
+
function needsOriginOnOuter(translateAnim) {
|
|
4467
|
+
if (!translateAnim || typeof translateAnim !== "object") return false;
|
|
4468
|
+
const obj = translateAnim;
|
|
4469
|
+
if (obj.autoOrient) return true;
|
|
4470
|
+
if (Array.isArray(obj.keyframes)) {
|
|
4471
|
+
return obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
|
|
4472
|
+
}
|
|
4473
|
+
return false;
|
|
4474
|
+
}
|
|
4475
|
+
|
|
4476
|
+
// src/effects/paint/gradientEffect.ts
|
|
4477
|
+
function applyFillGradientEffect(node, fx, ctx) {
|
|
4478
|
+
return applyGradient(node, fx, ctx, "fill");
|
|
4479
|
+
}
|
|
4480
|
+
function applyStrokeGradientEffect(node, fx, ctx) {
|
|
4481
|
+
return applyGradient(node, fx, ctx, "stroke");
|
|
4482
|
+
}
|
|
4483
|
+
function applyGradient(node, fx, ctx, attr) {
|
|
4484
|
+
if (!fx) return node;
|
|
4485
|
+
const id = genId(ctx, "grad");
|
|
4486
|
+
const def = synthesiseGradientDef(fx, id, ctx);
|
|
4487
|
+
ctx.defs.push(def);
|
|
4488
|
+
node[attr] = "url(#" + id + ")";
|
|
4489
|
+
return node;
|
|
4490
|
+
}
|
|
4491
|
+
function synthesiseGradientDef(fx, id, ctx) {
|
|
4492
|
+
const out = {
|
|
4493
|
+
type: fx.type === PxGradientType.radial ? "radialGradient" : "linearGradient",
|
|
4494
|
+
id
|
|
4495
|
+
};
|
|
4496
|
+
if (fx.type === PxGradientType.linear) {
|
|
4497
|
+
applyGeomVec(out, "x1", "y1", fx.start);
|
|
4498
|
+
applyGeomVec(out, "x2", "y2", fx.end);
|
|
4499
|
+
} else {
|
|
4500
|
+
applyGeomVec(out, "cx", "cy", fx.center);
|
|
4501
|
+
applyGeomNumber(out, "r", fx.radius);
|
|
4502
|
+
applyGeomVec(out, "fx", "fy", fx.focal);
|
|
4503
|
+
}
|
|
4504
|
+
if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
|
|
4505
|
+
if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
|
|
4506
|
+
if (fx.gradientTransform) out.gradientTransform = fx.gradientTransform;
|
|
4507
|
+
out.children = buildStopChildren(fx.stops, ctx);
|
|
4508
|
+
return out;
|
|
4509
|
+
}
|
|
4510
|
+
function applyGeomVec(out, xAttr, yAttr, raw) {
|
|
4511
|
+
var _a2, _b, _c;
|
|
4512
|
+
const read = readAnimatable(raw);
|
|
4513
|
+
if (read.kind === "absent" /* Absent */) return;
|
|
4514
|
+
if (read.kind === "static" /* Static */) {
|
|
4515
|
+
out[xAttr] = String(read.value[0]);
|
|
4516
|
+
out[yAttr] = String(read.value[1]);
|
|
4517
|
+
return;
|
|
4518
|
+
}
|
|
4519
|
+
const axisChannel = (idx) => {
|
|
4520
|
+
const block = {
|
|
4521
|
+
keyframes: read.keyframes.map((kf) => {
|
|
4522
|
+
const axisKf = { time: kf.time, value: Array.isArray(kf.value) ? kf.value[idx] : void 0 };
|
|
4523
|
+
if (kf.easing !== void 0) axisKf.easing = kf.easing;
|
|
4524
|
+
return axisKf;
|
|
4525
|
+
})
|
|
4526
|
+
};
|
|
4527
|
+
if (read.loop !== void 0) block.loop = read.loop;
|
|
4528
|
+
return block;
|
|
4529
|
+
};
|
|
4530
|
+
const animate = (_a2 = out.animate) != null ? _a2 : {};
|
|
4531
|
+
animate[xAttr] = axisChannel(0);
|
|
4532
|
+
animate[yAttr] = axisChannel(1);
|
|
4533
|
+
out.animate = animate;
|
|
4534
|
+
const baseline = (_c = read.base) != null ? _c : (_b = read.keyframes[0]) == null ? void 0 : _b.value;
|
|
4535
|
+
if (Array.isArray(baseline)) {
|
|
4536
|
+
out[xAttr] = String(baseline[0]);
|
|
4537
|
+
out[yAttr] = String(baseline[1]);
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4540
|
+
function applyGeomNumber(out, attrName, raw) {
|
|
4541
|
+
const read = readAnimatable(raw);
|
|
4542
|
+
if (read.kind === "absent" /* Absent */) return;
|
|
4543
|
+
writeAnimatableChannel(out, attrName, read, { asString: true });
|
|
4544
|
+
}
|
|
4545
|
+
function buildStopChildren(stops, ctx) {
|
|
4546
|
+
var _a2, _b;
|
|
4547
|
+
if (!stops) return [];
|
|
4548
|
+
const read = readAnimatable(stops);
|
|
4549
|
+
if (read.kind === "absent" /* Absent */) return [];
|
|
4550
|
+
if (read.kind === "static" /* Static */) return Array.isArray(read.value) ? read.value.map(staticStopNode) : [];
|
|
4551
|
+
const kfs = read.keyframes;
|
|
4552
|
+
if (!kfs.length) return [];
|
|
4553
|
+
const loopFromSource = read.loop;
|
|
4554
|
+
let stopCount = 0;
|
|
4555
|
+
for (const kf of kfs) {
|
|
4556
|
+
const v = keyframeValue(kf);
|
|
4557
|
+
if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
|
|
4558
|
+
}
|
|
4559
|
+
if (!stopCount) return [];
|
|
4560
|
+
const firstKfValue = keyframeValue(kfs[0]);
|
|
4561
|
+
const baselineStops = [];
|
|
4562
|
+
for (let i = 0; i < stopCount; i++) {
|
|
4563
|
+
const s = (_b = (_a2 = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _a2 : prevDefinedStop(kfs, 0, i)) != null ? _b : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
|
|
4564
|
+
baselineStops.push({ offset: s.offset, color: s.color });
|
|
4565
|
+
}
|
|
4566
|
+
return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
|
|
4567
|
+
}
|
|
4568
|
+
function staticStopNode(s) {
|
|
4569
|
+
return {
|
|
4570
|
+
type: "stop",
|
|
4571
|
+
offset: formatOffset(s.offset),
|
|
4572
|
+
stopColor: s.color
|
|
4573
|
+
};
|
|
4574
|
+
}
|
|
4575
|
+
function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
|
|
4576
|
+
var _a2;
|
|
4577
|
+
const colorKfs = [];
|
|
4578
|
+
const offsetKfs = [];
|
|
4579
|
+
let offsetVaries = false;
|
|
4580
|
+
for (const kf of kfs) {
|
|
4581
|
+
const t = keyframeTime(kf);
|
|
4582
|
+
const arr = keyframeValue(kf);
|
|
4583
|
+
const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
|
|
4584
|
+
if (!sliced) continue;
|
|
4585
|
+
const easing = keyframeEasing(kf);
|
|
4586
|
+
const colorOut = { time: t, value: sliced.color };
|
|
4587
|
+
if (easing !== void 0) colorOut.easing = easing;
|
|
4588
|
+
colorKfs.push(colorOut);
|
|
4589
|
+
const offsetOut = { time: t, value: sliced.offset };
|
|
4590
|
+
if (easing !== void 0) offsetOut.easing = easing;
|
|
4591
|
+
offsetKfs.push(offsetOut);
|
|
4592
|
+
if (sliced.offset !== baseline.offset) offsetVaries = true;
|
|
4593
|
+
}
|
|
4594
|
+
const stop = {
|
|
4595
|
+
type: "stop",
|
|
4596
|
+
offset: formatOffset(baseline.offset),
|
|
4597
|
+
stopColor: baseline.color
|
|
4598
|
+
};
|
|
4599
|
+
const animate = {};
|
|
4600
|
+
if (colorKfs.length) {
|
|
4601
|
+
animate.stopColor = { keyframes: colorKfs };
|
|
4602
|
+
if (loop !== void 0) animate.stopColor.loop = loop;
|
|
4603
|
+
}
|
|
4604
|
+
if (offsetVaries && offsetKfs.length) {
|
|
4605
|
+
animate.offset = { keyframes: offsetKfs };
|
|
4606
|
+
if (loop !== void 0) animate.offset.loop = loop;
|
|
4607
|
+
}
|
|
4608
|
+
if (Object.keys(animate).length) stop.animate = animate;
|
|
4609
|
+
return stop;
|
|
4610
|
+
}
|
|
4611
|
+
function prevDefinedStop(kfs, fromIdx, stopIdx) {
|
|
4612
|
+
for (let i = fromIdx; i >= 0; i--) {
|
|
4613
|
+
const arr = keyframeValue(kfs[i]);
|
|
4614
|
+
if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
|
|
4615
|
+
}
|
|
4616
|
+
for (let i = fromIdx + 1; i < kfs.length; i++) {
|
|
4617
|
+
const arr = keyframeValue(kfs[i]);
|
|
4618
|
+
if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
|
|
4619
|
+
}
|
|
4620
|
+
return void 0;
|
|
4621
|
+
}
|
|
4622
|
+
function formatOffset(o) {
|
|
4623
|
+
const pct = Math.round(o * 1e3) / 10;
|
|
4624
|
+
return pct + "%";
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4627
|
+
// src/effects/clipping/clipPathEffect.ts
|
|
4628
|
+
function applyClipPathEffect(node, fx, ctx) {
|
|
4629
|
+
if (!(fx == null ? void 0 : fx.pathData)) return node;
|
|
4630
|
+
const clipId = genId(ctx, "clip");
|
|
4631
|
+
const pathChild = { type: "path" };
|
|
4632
|
+
const read = readAnimatable(fx.pathData);
|
|
4633
|
+
if (read.kind !== "absent" /* Absent */) {
|
|
4634
|
+
if (read.kind === "static" /* Static */) {
|
|
4635
|
+
pathChild.d = pathString(read.value);
|
|
4636
|
+
} else {
|
|
4637
|
+
writeAnimatableChannel(pathChild, "d", read);
|
|
4638
|
+
if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
|
|
4639
|
+
}
|
|
4640
|
+
}
|
|
4641
|
+
ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
|
|
4642
|
+
node.clipPath = "url(#" + clipId + ")";
|
|
4643
|
+
return node;
|
|
4644
|
+
}
|
|
4645
|
+
function pathString(v) {
|
|
4646
|
+
if (typeof v === "string") return v;
|
|
4647
|
+
if (v && typeof v === "object" && typeof v.pathData === "string") return v.pathData;
|
|
4648
|
+
return void 0;
|
|
4649
|
+
}
|
|
4650
|
+
|
|
4651
|
+
// src/effects/clipping/maskedByEffect.ts
|
|
4652
|
+
function applyMaskedByEffect(node, fx, transformBy, ctx) {
|
|
4653
|
+
if (!fx) return node;
|
|
4654
|
+
const sourceId = stripHash(fx.source);
|
|
4655
|
+
if (!sourceId) {
|
|
4656
|
+
ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
|
|
4657
|
+
return node;
|
|
4658
|
+
}
|
|
4659
|
+
const maskId = genId(ctx, "mask");
|
|
4660
|
+
let content = { type: "use", href: "#" + sourceId };
|
|
4661
|
+
if (transformBy) {
|
|
4662
|
+
content = wrapInverseTransform(content, transformBy, ctx);
|
|
4663
|
+
} else if (hasAnimateTransform(node)) {
|
|
4664
|
+
content = wrapInverseAnimatedBodyTransform(content, node, ctx);
|
|
4665
|
+
} else {
|
|
4666
|
+
const bodyStatic = readTransformationFromBody(node);
|
|
4667
|
+
if (bodyStatic) content = wrapInverseTransform(content, bodyStatic, ctx);
|
|
4668
|
+
}
|
|
4669
|
+
const includeTargetOwn = transformBy === void 0 && !nodeHasBodyTransform(node);
|
|
4670
|
+
content = wrapAncestorChainCompensation(content, node, sourceId, ctx, includeTargetOwn);
|
|
4671
|
+
const mask = { type: "mask", id: maskId, children: [content] };
|
|
4672
|
+
if (fx.maskType) mask.maskType = fx.maskType;
|
|
4673
|
+
if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
|
|
4674
|
+
if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
|
|
4675
|
+
if (fx.x !== void 0) mask.x = String(fx.x);
|
|
4676
|
+
if (fx.y !== void 0) mask.y = String(fx.y);
|
|
4677
|
+
if (fx.width !== void 0) mask.width = String(fx.width);
|
|
4678
|
+
if (fx.height !== void 0) mask.height = String(fx.height);
|
|
4679
|
+
ctx.defs.push(mask);
|
|
4680
|
+
node.mask = "url(#" + maskId + ")";
|
|
4681
|
+
return node;
|
|
4682
|
+
}
|
|
4683
|
+
function wrapInverseTransform(inner, fx, ctx) {
|
|
4684
|
+
if (!fx) return inner;
|
|
4685
|
+
const origin = readStaticOrigin(fx.origin, ctx);
|
|
4686
|
+
let n = inner;
|
|
4687
|
+
n = wrapInversePart(n, "translate" /* Translate */, fx.translate, void 0, ctx);
|
|
4688
|
+
n = wrapInversePart(n, "rotate" /* Rotate */, fx.rotate, origin, ctx);
|
|
4689
|
+
n = wrapInversePart(n, "scale" /* Scale */, fx.scale, origin, ctx);
|
|
4690
|
+
return n;
|
|
4691
|
+
}
|
|
4692
|
+
function wrapInversePart(inner, part, raw, origin, ctx) {
|
|
4693
|
+
if (raw === void 0) return inner;
|
|
4694
|
+
const normalizedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
|
|
4695
|
+
const v = readAnimatable(normalizedRaw);
|
|
4696
|
+
if (v.kind === "static" /* Static */) {
|
|
4697
|
+
return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
|
|
4698
|
+
}
|
|
4699
|
+
if (v.kind === "animated" /* Animated */) {
|
|
4700
|
+
const animTr = { keyframes: v.keyframes.map((kf) => {
|
|
4701
|
+
const out = keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin));
|
|
4702
|
+
return part === "translate" /* Translate */ ? __spreadValues(__spreadValues({}, out), negatedSpatialTangents(kf)) : out;
|
|
4703
|
+
}) };
|
|
4704
|
+
if (v.loop !== void 0) animTr.loop = v.loop;
|
|
4705
|
+
return {
|
|
4706
|
+
type: "g",
|
|
4707
|
+
animate: { transform: animTr },
|
|
4708
|
+
children: [inner]
|
|
4709
|
+
};
|
|
4710
|
+
}
|
|
4711
|
+
return inner;
|
|
4712
|
+
}
|
|
4713
|
+
function invertPartValue(part, value) {
|
|
4714
|
+
if (part === "translate" /* Translate */) return [-value[0], -value[1]];
|
|
4715
|
+
if (part === "rotate" /* Rotate */) return -value;
|
|
4716
|
+
return [1 / value[0], 1 / value[1]];
|
|
4717
|
+
}
|
|
4718
|
+
function negatedSpatialTangents(kf) {
|
|
4719
|
+
var _a2, _b;
|
|
4720
|
+
const out = {};
|
|
4721
|
+
const to = (_a2 = kf.tangentOut) != null ? _a2 : kf.to;
|
|
4722
|
+
const ti = (_b = kf.tangentIn) != null ? _b : kf.ti;
|
|
4723
|
+
if (Array.isArray(to)) out.tangentOut = [-to[0], -to[1]];
|
|
4724
|
+
if (Array.isArray(ti)) out.tangentIn = [-ti[0], -ti[1]];
|
|
4725
|
+
return out;
|
|
4726
|
+
}
|
|
4727
|
+
function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
|
|
4728
|
+
var _a2;
|
|
4729
|
+
const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
4730
|
+
const animTr = animate == null ? void 0 : animate.transform;
|
|
4731
|
+
const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
|
|
4732
|
+
if (!kfs || !kfs.length) return inner;
|
|
4733
|
+
const translateKfs = [];
|
|
4734
|
+
const rotateKfs = [];
|
|
4735
|
+
const scaleKfs = [];
|
|
4736
|
+
for (const kf of kfs) {
|
|
4737
|
+
const v = ((_a2 = kf.value) != null ? _a2 : kf.v) || {};
|
|
4738
|
+
const baseKf = keyframeWith(kf, void 0);
|
|
4739
|
+
if (Array.isArray(v.translate)) {
|
|
4740
|
+
translateKfs.push(__spreadProps(__spreadValues(__spreadValues({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
|
|
4741
|
+
}
|
|
4742
|
+
if (typeof v.rotate === "number") {
|
|
4743
|
+
const rec = { rotate: -v.rotate };
|
|
4744
|
+
if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
|
|
4745
|
+
rotateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
|
|
4746
|
+
}
|
|
4747
|
+
if (Array.isArray(v.scale)) {
|
|
4748
|
+
const rec = { scale: [1 / v.scale[0], 1 / v.scale[1]] };
|
|
4749
|
+
if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
|
|
4750
|
+
scaleKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
|
|
4751
|
+
}
|
|
4752
|
+
}
|
|
4753
|
+
const srcLoop = animTr == null ? void 0 : animTr.loop;
|
|
4754
|
+
const withLoop = (kfs2) => {
|
|
4755
|
+
const block = { keyframes: kfs2 };
|
|
4756
|
+
if (srcLoop !== void 0) block.loop = srcLoop;
|
|
4757
|
+
return block;
|
|
4758
|
+
};
|
|
4759
|
+
let n = inner;
|
|
4760
|
+
if (translateKfs.length) n = { type: "g", animate: { transform: withLoop(translateKfs) }, children: [n] };
|
|
4761
|
+
if (rotateKfs.length) n = { type: "g", animate: { transform: withLoop(rotateKfs) }, children: [n] };
|
|
4762
|
+
if (scaleKfs.length) n = { type: "g", animate: { transform: withLoop(scaleKfs) }, children: [n] };
|
|
4763
|
+
return n;
|
|
4764
|
+
}
|
|
4765
|
+
function nodeHasBodyTransform(node) {
|
|
4766
|
+
if (typeof node.transform === "string") return true;
|
|
4767
|
+
if (node.transform && typeof node.transform === "object") return true;
|
|
4768
|
+
return hasAnimateTransform(node);
|
|
4769
|
+
}
|
|
4770
|
+
function hasAnimateTransform(node) {
|
|
4771
|
+
const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
4772
|
+
return !!(animate && animate.transform);
|
|
4773
|
+
}
|
|
4774
|
+
function readTransformationFromBody(node) {
|
|
4775
|
+
if (typeof node.transform === "string") {
|
|
4776
|
+
const parts = parseTransformStringToParts(node.transform);
|
|
4777
|
+
if (!parts) return void 0;
|
|
4778
|
+
const out = {};
|
|
4779
|
+
if (parts.translate) out.translate = parts.translate;
|
|
4780
|
+
if (parts.rotate !== void 0) out.rotate = parts.rotate;
|
|
4781
|
+
if (parts.scale) out.scale = { value: parts.scale };
|
|
4782
|
+
if (parts.origin) out.origin = parts.origin;
|
|
4783
|
+
return Object.keys(out).length ? out : void 0;
|
|
4784
|
+
}
|
|
4785
|
+
if (node.transform && typeof node.transform === "object" && !node.transform.keyframes) {
|
|
4786
|
+
const wrapped = node.transform.value;
|
|
4787
|
+
const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
|
|
4788
|
+
if (value && typeof value === "object") {
|
|
4789
|
+
const out = {};
|
|
4790
|
+
if (Array.isArray(value.translate)) out.translate = value.translate;
|
|
4791
|
+
if (typeof value.rotate === "number") out.rotate = value.rotate;
|
|
4792
|
+
if (typeof value.skew === "number") out.skew = value.skew;
|
|
4793
|
+
if (Array.isArray(value.scale)) out.scale = { value: value.scale };
|
|
4794
|
+
if (Array.isArray(value.origin)) out.origin = value.origin;
|
|
4795
|
+
return Object.keys(out).length ? out : void 0;
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4798
|
+
return void 0;
|
|
4799
|
+
}
|
|
4800
|
+
function parseTransformStringToParts(s) {
|
|
4801
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
4802
|
+
const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
|
|
4803
|
+
let m;
|
|
4804
|
+
const ops = [];
|
|
4805
|
+
while ((m = re.exec(s)) !== null) {
|
|
4806
|
+
const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
|
|
4807
|
+
ops.push({ name: m[1], args });
|
|
4808
|
+
}
|
|
4809
|
+
if (!ops.length) return void 0;
|
|
4810
|
+
const last = ops[ops.length - 1];
|
|
4811
|
+
if (last.name === "translate") {
|
|
4812
|
+
for (let j = ops.length - 2; j >= 0; j--) {
|
|
4813
|
+
const cand = ops[j];
|
|
4814
|
+
if (cand.name !== "translate") continue;
|
|
4815
|
+
const ox = (_a2 = cand.args[0]) != null ? _a2 : 0;
|
|
4816
|
+
const oy = (_b = cand.args[1]) != null ? _b : 0;
|
|
4817
|
+
const lx = (_c = last.args[0]) != null ? _c : 0;
|
|
4818
|
+
const ly = (_d = last.args[1]) != null ? _d : 0;
|
|
4819
|
+
if (lx !== -ox || ly !== -oy) continue;
|
|
4820
|
+
const out2 = {};
|
|
4821
|
+
out2.origin = [ox, oy];
|
|
4822
|
+
for (let k = 0; k < j; k++) {
|
|
4823
|
+
if (ops[k].name === "translate") {
|
|
4824
|
+
const tx = (_e = ops[k].args[0]) != null ? _e : 0;
|
|
4825
|
+
const ty = (_f = ops[k].args[1]) != null ? _f : 0;
|
|
4826
|
+
out2.translate = out2.translate ? [out2.translate[0] + tx, out2.translate[1] + ty] : [tx, ty];
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
for (let k = j + 1; k < ops.length - 1; k++) {
|
|
4830
|
+
const op = ops[k];
|
|
4831
|
+
if (op.name === "rotate") out2.rotate = ((_g = out2.rotate) != null ? _g : 0) + ((_h = op.args[0]) != null ? _h : 0);
|
|
4832
|
+
else if (op.name === "scale") {
|
|
4833
|
+
const sx = (_i = op.args[0]) != null ? _i : 1;
|
|
4834
|
+
const sy = op.args.length > 1 ? op.args[1] : sx;
|
|
4835
|
+
out2.scale = out2.scale ? [out2.scale[0] * sx, out2.scale[1] * sy] : [sx, sy];
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
return out2;
|
|
4839
|
+
}
|
|
4840
|
+
}
|
|
4841
|
+
let translate;
|
|
4842
|
+
let rotate;
|
|
4843
|
+
let scale;
|
|
4844
|
+
for (const op of ops) {
|
|
4845
|
+
if (op.name === "translate") {
|
|
4846
|
+
const dx = (_j = op.args[0]) != null ? _j : 0;
|
|
4847
|
+
const dy = (_k = op.args[1]) != null ? _k : 0;
|
|
4848
|
+
translate = translate ? [translate[0] + dx, translate[1] + dy] : [dx, dy];
|
|
4849
|
+
} else if (op.name === "rotate") {
|
|
4850
|
+
rotate = (rotate != null ? rotate : 0) + ((_l = op.args[0]) != null ? _l : 0);
|
|
4851
|
+
} else if (op.name === "scale") {
|
|
4852
|
+
const sx = (_m = op.args[0]) != null ? _m : 1;
|
|
4853
|
+
const sy = op.args.length > 1 ? op.args[1] : sx;
|
|
4854
|
+
scale = scale ? [scale[0] * sx, scale[1] * sy] : [sx, sy];
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4857
|
+
const out = {};
|
|
4858
|
+
if (translate) out.translate = translate;
|
|
4859
|
+
if (rotate !== void 0) out.rotate = rotate;
|
|
4860
|
+
if (scale) out.scale = scale;
|
|
4861
|
+
return Object.keys(out).length ? out : void 0;
|
|
4862
|
+
}
|
|
4863
|
+
function wrapAncestorChainCompensation(inner, maskedNode, sourceId, ctx, includeTargetOwn) {
|
|
4864
|
+
const sourceNode = ctx.idMap.get(sourceId);
|
|
4865
|
+
const targetAncestors = ctx.maskAncestorChains.get(maskedNode) || [];
|
|
4866
|
+
const targetOwn = includeTargetOwn ? extractTranslateOnly(maskedNode, ctx) : void 0;
|
|
4867
|
+
const targetChain = targetOwn ? [...targetAncestors, targetOwn] : targetAncestors;
|
|
4868
|
+
const sourceChain = sourceNode && ctx.maskAncestorChains.get(sourceNode) || [];
|
|
4869
|
+
if (!targetChain.length && !sourceChain.length) return inner;
|
|
4870
|
+
const times = /* @__PURE__ */ new Set();
|
|
4871
|
+
for (const a of targetChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
|
|
4872
|
+
for (const a of sourceChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
|
|
4873
|
+
const animated = times.size > 0;
|
|
4874
|
+
if (!animated) {
|
|
4875
|
+
const tgt = sumStaticTranslate(targetChain);
|
|
4876
|
+
const src = sumStaticTranslate(sourceChain);
|
|
4877
|
+
const dx = src[0] - tgt[0];
|
|
4878
|
+
const dy = src[1] - tgt[1];
|
|
4879
|
+
if (dx === 0 && dy === 0) return inner;
|
|
4880
|
+
return { type: "g", transform: "translate(" + dx + "," + dy + ")", children: [inner] };
|
|
4881
|
+
}
|
|
4882
|
+
const sortedTimes = Array.from(times).sort((a, b) => a - b);
|
|
4883
|
+
const keyframes = sortedTimes.map((t) => {
|
|
4884
|
+
const tgt = sumTranslateAt(targetChain, t);
|
|
4885
|
+
const src = sumTranslateAt(sourceChain, t);
|
|
4886
|
+
return { time: t, value: { translate: [src[0] - tgt[0], src[1] - tgt[1]] } };
|
|
4887
|
+
});
|
|
4888
|
+
return { type: "g", animate: { transform: { keyframes } }, children: [inner] };
|
|
4889
|
+
}
|
|
4890
|
+
function sumStaticTranslate(chain) {
|
|
4891
|
+
let x = 0, y = 0;
|
|
4892
|
+
for (const a of chain) {
|
|
4893
|
+
if (a.translate) {
|
|
4894
|
+
x += a.translate[0];
|
|
4895
|
+
y += a.translate[1];
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
return [x, y];
|
|
4899
|
+
}
|
|
4900
|
+
function sumTranslateAt(chain, t) {
|
|
4901
|
+
let x = 0, y = 0;
|
|
4902
|
+
for (const a of chain) {
|
|
4903
|
+
if (a.translateKeyframes && a.translateKeyframes.length) {
|
|
4904
|
+
const v = interpKfs(a.translateKeyframes, t);
|
|
4905
|
+
x += v[0];
|
|
4906
|
+
y += v[1];
|
|
4907
|
+
} else if (a.translate) {
|
|
4908
|
+
x += a.translate[0];
|
|
4909
|
+
y += a.translate[1];
|
|
4910
|
+
}
|
|
4911
|
+
}
|
|
4912
|
+
return [x, y];
|
|
4913
|
+
}
|
|
4914
|
+
function interpKfs(kfs, t) {
|
|
4915
|
+
if (t <= kfs[0].time) return kfs[0].value;
|
|
4916
|
+
if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
|
|
4917
|
+
for (let i = 1; i < kfs.length; i++) {
|
|
4918
|
+
if (t <= kfs[i].time) {
|
|
4919
|
+
const prev = kfs[i - 1];
|
|
4920
|
+
const cur = kfs[i];
|
|
4921
|
+
const a = (t - prev.time) / (cur.time - prev.time);
|
|
4922
|
+
return [prev.value[0] + (cur.value[0] - prev.value[0]) * a, prev.value[1] + (cur.value[1] - prev.value[1]) * a];
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
return kfs[kfs.length - 1].value;
|
|
4926
|
+
}
|
|
4927
|
+
function collectMaskAncestorChains(root, ctx) {
|
|
4928
|
+
const interestingNodes = /* @__PURE__ */ new Set();
|
|
4929
|
+
const collectInterestingNodes = (n) => {
|
|
4930
|
+
var _a2, _b;
|
|
4931
|
+
const maskSourceId = stripHash((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
|
|
4932
|
+
if (typeof maskSourceId === "string") {
|
|
4933
|
+
interestingNodes.add(n);
|
|
4934
|
+
const sourceNode = ctx.idMap.get(maskSourceId);
|
|
4935
|
+
if (sourceNode) interestingNodes.add(sourceNode);
|
|
4936
|
+
}
|
|
4937
|
+
if (Array.isArray(n.children)) for (const ch of n.children) collectInterestingNodes(ch);
|
|
4938
|
+
};
|
|
4939
|
+
collectInterestingNodes(root);
|
|
4940
|
+
if (interestingNodes.size === 0) return;
|
|
4941
|
+
const walk = (node, chain) => {
|
|
4942
|
+
if (interestingNodes.has(node)) ctx.maskAncestorChains.set(node, chain);
|
|
4943
|
+
if (Array.isArray(node.children)) {
|
|
4944
|
+
const own = extractTranslateOnly(node, ctx);
|
|
4945
|
+
const next = own ? [...chain, own] : chain;
|
|
4946
|
+
for (const ch of node.children) walk(ch, next);
|
|
4947
|
+
}
|
|
4948
|
+
};
|
|
4949
|
+
walk(root, []);
|
|
4950
|
+
}
|
|
4951
|
+
function extractTranslateOnly(node, ctx) {
|
|
4952
|
+
var _a2, _b, _c;
|
|
4953
|
+
const tr = node.transform;
|
|
4954
|
+
const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
|
|
4955
|
+
if (tr === void 0 && !animateBlock) return void 0;
|
|
4956
|
+
const out = {};
|
|
4957
|
+
if (typeof tr === "string") {
|
|
4958
|
+
const parts = parseTranslateOnlyFromString(tr, ctx);
|
|
4959
|
+
if (parts) out.translate = parts;
|
|
4960
|
+
} else if (tr && typeof tr === "object" && !tr.keyframes) {
|
|
4961
|
+
const wrapped = tr.value;
|
|
4962
|
+
const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
|
|
4963
|
+
if (value && typeof value === "object" && Array.isArray(value.translate)) {
|
|
4964
|
+
out.translate = [value.translate[0] || 0, value.translate[1] || 0];
|
|
4965
|
+
}
|
|
4966
|
+
if (value && (value.rotate !== void 0 || value.scale !== void 0 || value.skew !== void 0)) {
|
|
4967
|
+
ctx.warnings.push("maskedBy ancestor: non-translate transform parts ignored (rotate/scale not yet supported)");
|
|
4968
|
+
}
|
|
4969
|
+
}
|
|
4970
|
+
if (animateBlock && Array.isArray(animateBlock.keyframes)) {
|
|
4971
|
+
const kfs = animateBlock.keyframes;
|
|
4972
|
+
const translateKfs = [];
|
|
4973
|
+
for (const kf of kfs) {
|
|
4974
|
+
const v = (_a2 = kf.value) != null ? _a2 : kf.v;
|
|
4975
|
+
const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
|
|
4976
|
+
if (v && typeof v === "object" && Array.isArray(v.translate)) {
|
|
4977
|
+
translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
|
|
4978
|
+
if (v.rotate !== void 0 || v.scale !== void 0 || v.skew !== void 0) {
|
|
4979
|
+
ctx.warnings.push("maskedBy ancestor: animated non-translate parts ignored");
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
if (translateKfs.length) out.translateKeyframes = translateKfs;
|
|
4984
|
+
}
|
|
4985
|
+
return out.translate || out.translateKeyframes ? out : void 0;
|
|
4986
|
+
}
|
|
4987
|
+
function parseTranslateOnlyFromString(s, ctx) {
|
|
4988
|
+
const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
|
|
4989
|
+
let m;
|
|
4990
|
+
let x = 0, y = 0;
|
|
4991
|
+
let seen = false;
|
|
4992
|
+
let droppedNonTranslate = false;
|
|
4993
|
+
while ((m = re.exec(s)) !== null) {
|
|
4994
|
+
const name = m[1];
|
|
4995
|
+
const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
|
|
4996
|
+
if (name === "translate") {
|
|
4997
|
+
x += args[0] || 0;
|
|
4998
|
+
y += args[1] || 0;
|
|
4999
|
+
seen = true;
|
|
5000
|
+
} else {
|
|
5001
|
+
droppedNonTranslate = true;
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
|
|
5005
|
+
return seen ? [x, y] : void 0;
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
// src/effects/reference/refEffect.ts
|
|
5009
|
+
function applyRefHref(node, clone2, ctx) {
|
|
5010
|
+
if (!clone2) return;
|
|
5011
|
+
const sourceId = stripHash(clone2.source);
|
|
5012
|
+
if (!sourceId) {
|
|
5013
|
+
if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
|
|
5014
|
+
return;
|
|
5015
|
+
}
|
|
5016
|
+
const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
|
|
5017
|
+
node.href = "#" + targetId;
|
|
5018
|
+
}
|
|
5019
|
+
function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
|
|
5020
|
+
applyRefHref(node, clone2, ctx);
|
|
5021
|
+
return applyTransformByEffect(node, transformBy, ctx);
|
|
5022
|
+
}
|
|
5023
|
+
|
|
5024
|
+
// src/effects/transform/repeaterEffect.ts
|
|
5025
|
+
function applyRepeaterEffect(node, fx, ctx) {
|
|
5026
|
+
var _a2, _b;
|
|
5027
|
+
if (!fx) return node;
|
|
5028
|
+
const copies = (_a2 = fx.copies) != null ? _a2 : 1;
|
|
5029
|
+
if (copies < 1) {
|
|
5030
|
+
ctx.errors.push("repeater.copies invalid: " + fx.copies);
|
|
5031
|
+
return node;
|
|
5032
|
+
}
|
|
5033
|
+
const sharedTransform = node.transform;
|
|
5034
|
+
const sharedAnimTransform = (_b = node.animate) == null ? void 0 : _b.transform;
|
|
5035
|
+
const base = clone(node);
|
|
5036
|
+
delete base.transform;
|
|
5037
|
+
if (base.animate) {
|
|
5038
|
+
delete base.animate.transform;
|
|
5039
|
+
if (Object.keys(base.animate).length === 0) delete base.animate;
|
|
5040
|
+
}
|
|
5041
|
+
delete base.id;
|
|
5042
|
+
const children = [base];
|
|
5043
|
+
for (let i = 1; i < copies; i++) {
|
|
5044
|
+
const baseClone = clone(base);
|
|
5045
|
+
const synthFx = synthesisePerCopyFx(fx, i);
|
|
5046
|
+
const wrapped = synthFx ? applyTransformByEffect(baseClone, synthFx, ctx) : baseClone;
|
|
5047
|
+
children.push(wrapped);
|
|
5048
|
+
}
|
|
5049
|
+
const wrapper = { type: "g", children };
|
|
5050
|
+
if (node.id) wrapper.id = node.id;
|
|
5051
|
+
if (sharedTransform !== void 0) wrapper.transform = sharedTransform;
|
|
5052
|
+
if (sharedAnimTransform !== void 0) wrapper.animate = { transform: sharedAnimTransform };
|
|
5053
|
+
return wrapper;
|
|
5054
|
+
}
|
|
5055
|
+
function synthesisePerCopyFx(fx, i) {
|
|
5056
|
+
const out = {};
|
|
5057
|
+
if (fx.translate !== void 0) {
|
|
5058
|
+
out.translate = mapAnimatable(fx.translate, (v) => [v[0] * i, v[1] * i]);
|
|
5059
|
+
}
|
|
5060
|
+
if (fx.rotate !== void 0) {
|
|
5061
|
+
out.rotate = mapAnimatable(fx.rotate, (v) => v * i);
|
|
5062
|
+
}
|
|
5063
|
+
if (fx.skew !== void 0) {
|
|
5064
|
+
out.skew = mapAnimatable(fx.skew, (v) => v * i);
|
|
5065
|
+
}
|
|
5066
|
+
if (fx.scale !== void 0) {
|
|
5067
|
+
out.scale = synthesiseScale(fx.scale, i);
|
|
5068
|
+
}
|
|
5069
|
+
if (fx.origin !== void 0) {
|
|
5070
|
+
out.origin = fx.origin;
|
|
5071
|
+
}
|
|
5072
|
+
return Object.keys(out).length ? out : void 0;
|
|
5073
|
+
}
|
|
5074
|
+
function mapAnimatable(raw, fn, wrapStatic = false) {
|
|
5075
|
+
const read = readAnimatable(raw);
|
|
5076
|
+
if (read.kind === "absent" /* Absent */) return raw;
|
|
5077
|
+
if (read.kind === "static" /* Static */) {
|
|
5078
|
+
const mapped = fn(read.value);
|
|
5079
|
+
const wasRawStatic = typeof raw === "number" || Array.isArray(raw);
|
|
5080
|
+
return wasRawStatic && !wrapStatic ? mapped : { value: mapped };
|
|
5081
|
+
}
|
|
5082
|
+
const out = {
|
|
5083
|
+
keyframes: read.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
|
|
5084
|
+
};
|
|
5085
|
+
if (read.loop !== void 0) out.loop = read.loop;
|
|
5086
|
+
if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
|
|
5087
|
+
if (read.base !== void 0) out.value = fn(read.base);
|
|
5088
|
+
return out;
|
|
5089
|
+
}
|
|
5090
|
+
function synthesiseScale(raw, i) {
|
|
5091
|
+
const scalePower = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
|
|
5092
|
+
return mapAnimatable(raw, scalePower, true);
|
|
5093
|
+
}
|
|
5094
|
+
|
|
5095
|
+
// src/effects/reference/retimeEffect.ts
|
|
5096
|
+
var RETIME_MATERIALIZATION_MODE_INLINE_G = false;
|
|
5097
|
+
function asRetime(r) {
|
|
5098
|
+
var _a2, _b;
|
|
5099
|
+
return { start: (_a2 = r.start) != null ? _a2 : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
|
|
5100
|
+
}
|
|
5101
|
+
var CROP_EDGE_MS = 1;
|
|
5102
|
+
function applyTimeCrop(useNode, crop, ctx) {
|
|
5103
|
+
const [start, end] = crop;
|
|
5104
|
+
if (!Number.isFinite(start) || !Number.isFinite(end)) {
|
|
5105
|
+
ctx.warnings.push("retime: timeCrop is not a pair of finite numbers \u2014 ignored");
|
|
5106
|
+
return;
|
|
5107
|
+
}
|
|
5108
|
+
const keyframes = end <= start ? [{ time: 0, value: 0 }] : [
|
|
5109
|
+
...start > 0 ? [{ time: Math.max(0, start - CROP_EDGE_MS), value: 0 }] : [],
|
|
5110
|
+
{ time: Math.max(0, start), value: 1 },
|
|
5111
|
+
{ time: end, value: 1 },
|
|
5112
|
+
{ time: end + CROP_EDGE_MS, value: 0 }
|
|
5113
|
+
];
|
|
5114
|
+
const inner = __spreadValues({}, useNode);
|
|
5115
|
+
for (const k of Object.keys(useNode)) delete useNode[k];
|
|
5116
|
+
useNode.type = "g";
|
|
5117
|
+
useNode.children = [inner];
|
|
5118
|
+
useNode.animate = { opacity: { keyframes } };
|
|
5119
|
+
}
|
|
5120
|
+
function concatRetime(child, parent) {
|
|
5121
|
+
return {
|
|
5122
|
+
start: parent.start + parent.stretch * child.start,
|
|
5123
|
+
stretch: parent.stretch * child.stretch
|
|
5124
|
+
};
|
|
5125
|
+
}
|
|
5126
|
+
function readCloneRetime(n) {
|
|
5127
|
+
var _a2, _b;
|
|
5128
|
+
return (_b = (_a2 = n.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.retime;
|
|
5129
|
+
}
|
|
5130
|
+
function clearCloneRetime(n) {
|
|
5131
|
+
var _a2;
|
|
5132
|
+
const clone2 = (_a2 = n.effects) == null ? void 0 : _a2.clone;
|
|
5133
|
+
if (!clone2) return;
|
|
5134
|
+
delete clone2.retime;
|
|
5135
|
+
if (Object.keys(clone2).length === 0) delete n.effects.clone;
|
|
5136
|
+
if (n.effects && Object.keys(n.effects).length === 0) delete n.effects;
|
|
5137
|
+
}
|
|
5138
|
+
function applyAllRetimeEffects(root, ctx) {
|
|
5139
|
+
ctx.idMap.clear();
|
|
5140
|
+
indexById(root, ctx.idMap);
|
|
5141
|
+
const sites = [];
|
|
5142
|
+
const collect = (n) => {
|
|
5143
|
+
var _a2;
|
|
5144
|
+
if (readCloneRetime(n)) sites.push(n);
|
|
5145
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach(collect);
|
|
5146
|
+
};
|
|
5147
|
+
collect(root);
|
|
5148
|
+
const reachCount = /* @__PURE__ */ new Map();
|
|
5149
|
+
for (const site of sites) {
|
|
5150
|
+
let count = 0;
|
|
5151
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5152
|
+
const walk = (n) => {
|
|
5153
|
+
var _a2;
|
|
5154
|
+
if (!n) return;
|
|
5155
|
+
if (n !== site && readCloneRetime(n)) count++;
|
|
5156
|
+
if (n.type === "use" && n.href) {
|
|
5157
|
+
const id = stripHash(n.href);
|
|
5158
|
+
if (id && !visited.has(id)) {
|
|
5159
|
+
visited.add(id);
|
|
5160
|
+
walk(ctx.idMap.get(id));
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
|
|
5164
|
+
};
|
|
5165
|
+
const rootId = stripHash(site.href);
|
|
5166
|
+
if (rootId) {
|
|
5167
|
+
visited.add(rootId);
|
|
5168
|
+
walk(ctx.idMap.get(rootId));
|
|
5169
|
+
}
|
|
5170
|
+
reachCount.set(site, count);
|
|
5171
|
+
}
|
|
5172
|
+
sites.sort((a, b) => {
|
|
5173
|
+
var _a2, _b;
|
|
5174
|
+
return ((_a2 = reachCount.get(b)) != null ? _a2 : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
|
|
5175
|
+
});
|
|
5176
|
+
for (const useNode of sites) {
|
|
5177
|
+
const retime = readCloneRetime(useNode);
|
|
5178
|
+
if (!retime) continue;
|
|
5179
|
+
const crop = retime.timeCrop;
|
|
5180
|
+
clearCloneRetime(useNode);
|
|
5181
|
+
materializeRetime(useNode, asRetime(retime), ctx);
|
|
5182
|
+
if (crop) applyTimeCrop(useNode, crop, ctx);
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
function materializeRetime(useNode, retime, ctx) {
|
|
5186
|
+
const targetId = stripHash(useNode.href);
|
|
5187
|
+
if (!targetId) {
|
|
5188
|
+
ctx.errors.push("retime: <use> has no href to follow");
|
|
5189
|
+
return;
|
|
5190
|
+
}
|
|
5191
|
+
const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
|
|
5192
|
+
if (!chainRootId) return;
|
|
5193
|
+
if (RETIME_MATERIALIZATION_MODE_INLINE_G) {
|
|
5194
|
+
const cloneNode = ctx.idMap.get(chainRootId);
|
|
5195
|
+
useNode.type = "g";
|
|
5196
|
+
delete useNode.href;
|
|
5197
|
+
useNode.children = [cloneNode];
|
|
5198
|
+
applyUseOffsetToG(useNode);
|
|
5199
|
+
ctx.defs = ctx.defs.filter((d) => d !== cloneNode);
|
|
5200
|
+
} else {
|
|
5201
|
+
useNode.href = "#" + chainRootId;
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
function buildChainClone(targetId, accum, ctx, chain) {
|
|
5205
|
+
if (chain.has(targetId)) {
|
|
5206
|
+
ctx.errors.push('retime: loop via "' + targetId + '"');
|
|
5207
|
+
return void 0;
|
|
5208
|
+
}
|
|
5209
|
+
const target = ctx.idMap.get(targetId);
|
|
5210
|
+
if (!target) {
|
|
5211
|
+
ctx.warnings.push('retime: target "' + targetId + '" not found');
|
|
5212
|
+
return void 0;
|
|
5213
|
+
}
|
|
5214
|
+
const cloneNode = clone(target);
|
|
5215
|
+
regenerateIdsInClone(cloneNode, ctx);
|
|
5216
|
+
if (target.type === "use") {
|
|
5217
|
+
remapKeyframeTimesOnly(cloneNode, accum.start, accum.stretch);
|
|
5218
|
+
} else {
|
|
5219
|
+
remapKeyframeTimes(cloneNode, accum.start, accum.stretch);
|
|
5220
|
+
}
|
|
5221
|
+
clearCloneRetime(cloneNode);
|
|
5222
|
+
if (target.type === "use" && target.href) {
|
|
5223
|
+
const subId = stripHash(target.href);
|
|
5224
|
+
if (subId) {
|
|
5225
|
+
const innerRetime = readCloneRetime(target);
|
|
5226
|
+
const subAccum = innerRetime ? concatRetime(asRetime(innerRetime), accum) : accum;
|
|
5227
|
+
const subChain = new Set(chain);
|
|
5228
|
+
subChain.add(targetId);
|
|
5229
|
+
const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
|
|
5230
|
+
if (subId2) cloneNode.href = "#" + subId2;
|
|
5231
|
+
}
|
|
5232
|
+
} else {
|
|
5233
|
+
materializeNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
|
|
5234
|
+
}
|
|
5235
|
+
ctx.defs.push(cloneNode);
|
|
5236
|
+
if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
|
|
5237
|
+
return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
|
|
5238
|
+
}
|
|
5239
|
+
function materializeNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
|
|
5240
|
+
const visit = (n) => {
|
|
5241
|
+
var _a2;
|
|
5242
|
+
const retime = readCloneRetime(n);
|
|
5243
|
+
if (n.type === "use" && retime && n.href) {
|
|
5244
|
+
const subId = stripHash(n.href);
|
|
5245
|
+
if (subId) {
|
|
5246
|
+
const subAccum = concatRetime(asRetime(retime), accum);
|
|
5247
|
+
const subChain = new Set(chain);
|
|
5248
|
+
subChain.add(parentTargetId);
|
|
5249
|
+
const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
|
|
5250
|
+
if (subId2) n.href = "#" + subId2;
|
|
5251
|
+
}
|
|
5252
|
+
clearCloneRetime(n);
|
|
5253
|
+
}
|
|
5254
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
|
|
5255
|
+
};
|
|
5256
|
+
visit(node);
|
|
5257
|
+
}
|
|
5258
|
+
function remapKeyframeTimes(node, start, stretch) {
|
|
5259
|
+
var _a2;
|
|
5260
|
+
remapKeyframeTimesOnly(node, start, stretch);
|
|
5261
|
+
(_a2 = node.children) == null ? void 0 : _a2.forEach((c) => remapKeyframeTimes(c, start, stretch));
|
|
5262
|
+
}
|
|
5263
|
+
function remapKeyframeTimesOnly(node, start, stretch) {
|
|
5264
|
+
const remap2 = (kfs) => {
|
|
5265
|
+
for (const kf of kfs) if (typeof kf.time === "number") kf.time = start + kf.time * stretch;
|
|
5266
|
+
};
|
|
5267
|
+
if (node.transform && typeof node.transform === "object" && Array.isArray(node.transform.keyframes)) {
|
|
5268
|
+
remap2(node.transform.keyframes);
|
|
5269
|
+
}
|
|
5270
|
+
if (node.animate && typeof node.animate === "object") {
|
|
5271
|
+
for (const prop of Object.keys(node.animate)) {
|
|
5272
|
+
const anim = node.animate[prop];
|
|
5273
|
+
if (anim && Array.isArray(anim.keyframes)) remap2(anim.keyframes);
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
}
|
|
5277
|
+
|
|
5278
|
+
// src/effects/stroke/strokeTrimEffect.ts
|
|
5279
|
+
function applyStrokeTrimEffect(node, strokeTrim, ctx) {
|
|
5280
|
+
if (!strokeTrim) return node;
|
|
5281
|
+
const combined = strokeTrim.subPaths === PxStrokeTrimSubPaths.combined;
|
|
5282
|
+
const leafEntries = [];
|
|
5283
|
+
const measure = (n) => {
|
|
5284
|
+
if (Array.isArray(n.children) && n.children.length > 0) {
|
|
5285
|
+
for (const ch of n.children) measure(ch);
|
|
5286
|
+
return;
|
|
5287
|
+
}
|
|
5288
|
+
const d = typeof n.d === "string" ? n.d : shapeToPathD(n);
|
|
5289
|
+
if (d === void 0) return;
|
|
5290
|
+
const subpaths = parseSvgPathToBezier(d);
|
|
5291
|
+
if (!subpaths.length) return;
|
|
5292
|
+
const entry = { leaf: n, subpaths: [] };
|
|
5293
|
+
for (const sp of subpaths) {
|
|
5294
|
+
const lengthPx = pxBezierPathLength(sp);
|
|
5295
|
+
entry.subpaths.push({ subpath: sp, lengthPx, startOffsetPx: 0 });
|
|
5296
|
+
}
|
|
5297
|
+
leafEntries.push(entry);
|
|
5298
|
+
};
|
|
5299
|
+
measure(node);
|
|
5300
|
+
if (!leafEntries.length) return node;
|
|
5301
|
+
let acc = 0;
|
|
5302
|
+
const iterOrder = combined ? [...leafEntries].reverse() : leafEntries;
|
|
5303
|
+
for (const entry of iterOrder) {
|
|
5304
|
+
for (const sp of entry.subpaths) {
|
|
5305
|
+
if (!combined) acc = 0;
|
|
5306
|
+
sp.startOffsetPx = acc;
|
|
5307
|
+
acc += sp.lengthPx;
|
|
5308
|
+
}
|
|
5309
|
+
}
|
|
5310
|
+
const chainLengthPx = acc;
|
|
5311
|
+
if (combined && chainLengthPx < 1e-3) return node;
|
|
5312
|
+
const offsetReadRaw = readAnimatable(strokeTrim.offset);
|
|
5313
|
+
const offsetRead = offsetReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: 0 } : offsetReadRaw;
|
|
5314
|
+
const rangeReadRaw = readRangeWithCrossings(strokeTrim.range);
|
|
5315
|
+
const rangeRead = rangeReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: [0, 1] } : rangeReadRaw;
|
|
5316
|
+
const offsetValues = readScalarValues(offsetRead);
|
|
5317
|
+
const minOffset = offsetValues.length ? Math.min(...offsetValues) : 0;
|
|
5318
|
+
const maxOffset = offsetValues.length ? Math.max(...offsetValues) : 0;
|
|
5319
|
+
const minMaxOffset = [minOffset, maxOffset];
|
|
5320
|
+
if (leafEntries.length === 1 && leafEntries[0].leaf === node && leafEntries[0].subpaths.length === 1) {
|
|
5321
|
+
const entry = leafEntries[0];
|
|
5322
|
+
const sp = entry.subpaths[0];
|
|
5323
|
+
const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
|
|
5324
|
+
if (pathLengthPx < 1e-3) return node;
|
|
5325
|
+
const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
|
|
5326
|
+
return collapseLeafWithTrim(entry.leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead);
|
|
5327
|
+
}
|
|
5328
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
5329
|
+
for (const entry of leafEntries) {
|
|
5330
|
+
const newChildren = [];
|
|
5331
|
+
for (const sp of entry.subpaths) {
|
|
5332
|
+
const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
|
|
5333
|
+
if (pathLengthPx < 1e-3) continue;
|
|
5334
|
+
const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
|
|
5335
|
+
newChildren.push(...buildSubpathNodes(entry.leaf, sp.subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx));
|
|
5336
|
+
}
|
|
5337
|
+
replacements.set(entry.leaf, wrapLeafAsGroup(entry.leaf, newChildren));
|
|
5338
|
+
}
|
|
5339
|
+
const swap = (n) => {
|
|
5340
|
+
const r = replacements.get(n);
|
|
5341
|
+
if (r) return r;
|
|
5342
|
+
if (Array.isArray(n.children) && n.children.length > 0) {
|
|
5343
|
+
return __spreadProps(__spreadValues({}, n), { children: n.children.map(swap) });
|
|
5344
|
+
}
|
|
5345
|
+
return n;
|
|
5346
|
+
};
|
|
5347
|
+
return swap(node);
|
|
5348
|
+
}
|
|
5349
|
+
function wrapLeafAsGroup(leaf, children) {
|
|
5350
|
+
const wrapper = __spreadProps(__spreadValues({}, leaf), { type: "g", children });
|
|
5351
|
+
delete wrapper.d;
|
|
5352
|
+
delete wrapper.strokeDasharray;
|
|
5353
|
+
delete wrapper.strokeDashoffset;
|
|
5354
|
+
delete wrapper.effects;
|
|
5355
|
+
return wrapper;
|
|
5356
|
+
}
|
|
5357
|
+
function buildSubpathNodes(leaf, subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx) {
|
|
5358
|
+
const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
|
|
5359
|
+
const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
|
|
5360
|
+
const dashOffsetAttr = computeAnimAttr(offsetRead, offsetToDashOffset);
|
|
5361
|
+
const dashArrayAttr = computeAnimAttr(rangeRead, rangeToDasharray);
|
|
5362
|
+
const strokeOpacityAttr = computeOpacityFromRange(rangeRead);
|
|
5363
|
+
const dStr = bezierToSvgPath(subpath);
|
|
5364
|
+
const base = makeBareSubpath(dStr);
|
|
5365
|
+
applyAttr(base, "strokeDasharray", dashArrayAttr);
|
|
5366
|
+
applyAttr(base, "strokeDashoffset", dashOffsetAttr);
|
|
5367
|
+
applyAttr(base, "strokeOpacity", strokeOpacityAttr);
|
|
5368
|
+
return [base];
|
|
5369
|
+
}
|
|
5370
|
+
function collapseLeafWithTrim(leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead) {
|
|
5371
|
+
const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
|
|
5372
|
+
const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
|
|
5373
|
+
const node = __spreadValues({}, leaf);
|
|
5374
|
+
delete node.effects;
|
|
5375
|
+
applyAttr(node, "strokeDasharray", computeAnimAttr(rangeRead, rangeToDasharray));
|
|
5376
|
+
applyAttr(node, "strokeDashoffset", computeAnimAttr(offsetRead, offsetToDashOffset));
|
|
5377
|
+
applyAttr(node, "strokeOpacity", computeOpacityFromRange(rangeRead));
|
|
5378
|
+
return node;
|
|
5379
|
+
}
|
|
5380
|
+
function makeBareSubpath(dStr) {
|
|
5381
|
+
return { type: "path", d: dStr };
|
|
5382
|
+
}
|
|
5383
|
+
var SMALL_PADDING_PX = 1;
|
|
5384
|
+
function makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset) {
|
|
5385
|
+
const [minIdx] = getOffsetIndexRange(minMaxOffset);
|
|
5386
|
+
return (offsetVal) => pathLengthPx * (-offsetVal - minIdx + startOffsetPct) + SMALL_PADDING_PX;
|
|
5387
|
+
}
|
|
5388
|
+
function makeRangeToDasharray(pathLengthPx, minMaxOffset) {
|
|
5389
|
+
const [minIdx, maxIdx] = getOffsetIndexRange(minMaxOffset);
|
|
5390
|
+
const repeats = maxIdx - minIdx + 1;
|
|
5391
|
+
return (rangeVal) => {
|
|
5392
|
+
const a = clamp(rangeVal[0], 0, 1);
|
|
5393
|
+
const b = clamp(rangeVal[1], 0, 1);
|
|
5394
|
+
const minR = Math.min(a, b);
|
|
5395
|
+
const maxR = Math.max(a, b);
|
|
5396
|
+
const out = [0];
|
|
5397
|
+
let gap = SMALL_PADDING_PX;
|
|
5398
|
+
for (let i = 0; i < repeats; i++) {
|
|
5399
|
+
out.push(gap + minR * pathLengthPx);
|
|
5400
|
+
out.push((maxR - minR) * pathLengthPx);
|
|
5401
|
+
gap = (1 - maxR) * pathLengthPx;
|
|
5402
|
+
}
|
|
5403
|
+
out.push(gap + SMALL_PADDING_PX);
|
|
5404
|
+
return out;
|
|
5405
|
+
};
|
|
5406
|
+
}
|
|
5407
|
+
function getOffsetIndexRange(minMaxOffset) {
|
|
5408
|
+
return [
|
|
5409
|
+
Math.floor(Math.min(-minMaxOffset[0], -minMaxOffset[1])),
|
|
5410
|
+
Math.ceil(Math.max(-minMaxOffset[0], -minMaxOffset[1]))
|
|
5411
|
+
];
|
|
5412
|
+
}
|
|
5413
|
+
function readScalarValues(r) {
|
|
5414
|
+
if (r.kind === "absent" /* Absent */) return [];
|
|
5415
|
+
if (r.kind === "static" /* Static */) return [r.value];
|
|
5416
|
+
const out = [];
|
|
5417
|
+
for (const kf of r.keyframes) {
|
|
5418
|
+
const v = keyframeValue(kf);
|
|
5419
|
+
if (typeof v === "number") out.push(v);
|
|
5420
|
+
}
|
|
5421
|
+
return out;
|
|
5422
|
+
}
|
|
5423
|
+
function computeAnimAttr(read, map) {
|
|
5424
|
+
if (read.kind === "absent" /* Absent */) return void 0;
|
|
5425
|
+
if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
|
|
5426
|
+
return {
|
|
5427
|
+
kind: "animated" /* Animated */,
|
|
5428
|
+
keyframes: read.keyframes.map((kf) => ({
|
|
5429
|
+
time: keyframeTime(kf),
|
|
5430
|
+
value: map(keyframeValue(kf)),
|
|
5431
|
+
easing: keyframeEasing(kf)
|
|
5432
|
+
})),
|
|
5433
|
+
loop: read.loop
|
|
5434
|
+
};
|
|
5435
|
+
}
|
|
5436
|
+
function applyAttr(node, attrName, attr) {
|
|
5437
|
+
if (!attr) return;
|
|
5438
|
+
writeAnimatableChannel(node, attrName, attr);
|
|
5439
|
+
}
|
|
5440
|
+
var OPACITY_STEP_MS = 10;
|
|
5441
|
+
function computeOpacityFromRange(rangeRead) {
|
|
5442
|
+
const hide = (v) => v[0] === v[1];
|
|
5443
|
+
if (rangeRead.kind === "absent" /* Absent */) return void 0;
|
|
5444
|
+
if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
|
|
5445
|
+
const kfs = rangeRead.keyframes;
|
|
5446
|
+
let anyHide = false;
|
|
5447
|
+
let allHide = true;
|
|
5448
|
+
for (const kf of kfs) {
|
|
5449
|
+
if (hide(keyframeValue(kf))) anyHide = true;
|
|
5450
|
+
else allHide = false;
|
|
5451
|
+
}
|
|
5452
|
+
if (!anyHide) return void 0;
|
|
5453
|
+
if (allHide) return { kind: "static" /* Static */, value: 0 };
|
|
5454
|
+
const out = [];
|
|
5455
|
+
for (let i = 0; i < kfs.length; i++) {
|
|
5456
|
+
const kf = kfs[i];
|
|
5457
|
+
const prevKf = i > 0 ? kfs[i - 1] : void 0;
|
|
5458
|
+
const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
|
|
5459
|
+
const t = keyframeTime(kf);
|
|
5460
|
+
const thisHide = hide(keyframeValue(kf));
|
|
5461
|
+
const prevHide = prevKf ? thisHide && hide(keyframeValue(prevKf)) : thisHide;
|
|
5462
|
+
const nextHide = nextKf ? thisHide && hide(keyframeValue(nextKf)) : thisHide;
|
|
5463
|
+
if (prevHide && !nextHide) {
|
|
5464
|
+
out.push({ time: t, value: 0 });
|
|
5465
|
+
out.push({ time: t + OPACITY_STEP_MS, value: 1 });
|
|
5466
|
+
} else if (!prevHide && nextHide) {
|
|
5467
|
+
out.push({ time: t - OPACITY_STEP_MS, value: 1 });
|
|
5468
|
+
out.push({ time: t, value: 0 });
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
if (out.length <= 1) return void 0;
|
|
5472
|
+
return { kind: "animated" /* Animated */, keyframes: out };
|
|
5473
|
+
}
|
|
5474
|
+
function readRangeWithCrossings(raw) {
|
|
5475
|
+
const r = readAnimatable(raw);
|
|
5476
|
+
if (r.kind !== "animated" /* Animated */) return r;
|
|
5477
|
+
const kfs = r.keyframes.map((kf) => ({
|
|
5478
|
+
time: keyframeTime(kf),
|
|
5479
|
+
value: keyframeValue(kf),
|
|
5480
|
+
easing: keyframeEasing(kf)
|
|
5481
|
+
}));
|
|
5482
|
+
const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
|
|
5483
|
+
if (!hasReverse) {
|
|
5484
|
+
return {
|
|
5485
|
+
kind: "animated" /* Animated */,
|
|
5486
|
+
keyframes: kfs.map((kf) => ({ time: kf.time, value: kf.value, easing: kf.easing }))
|
|
5487
|
+
};
|
|
5488
|
+
}
|
|
5489
|
+
const crossingTimes = [];
|
|
5490
|
+
for (let i = 1; i < kfs.length; i++) {
|
|
5491
|
+
const prev = kfs[i - 1];
|
|
5492
|
+
const cur = kfs[i];
|
|
5493
|
+
const dPrev = prev.value[1] - prev.value[0];
|
|
5494
|
+
const dCur = cur.value[1] - cur.value[0];
|
|
5495
|
+
if (dPrev * dCur < 0) {
|
|
5496
|
+
const t = bisectionForRangeCrossing(prev, cur);
|
|
5497
|
+
if (t !== null && t > prev.time && t < cur.time) {
|
|
5498
|
+
crossingTimes.push(Math.round(t));
|
|
5499
|
+
}
|
|
5500
|
+
}
|
|
5501
|
+
}
|
|
5502
|
+
const uniqueTs = Array.from(new Set(crossingTimes)).sort((a, b) => a - b);
|
|
5503
|
+
const out = [];
|
|
5504
|
+
let j = 0;
|
|
5505
|
+
for (const kf of kfs) {
|
|
5506
|
+
while (j < uniqueTs.length && uniqueTs[j] < kf.time) {
|
|
5507
|
+
const t = uniqueTs[j++];
|
|
5508
|
+
const v2 = interpolateRangeAt(kfs, t);
|
|
5509
|
+
const m = (v2[0] + v2[1]) / 2;
|
|
5510
|
+
out.push({ time: t, value: [m, m] });
|
|
5511
|
+
}
|
|
5512
|
+
const v = kf.value[0] > kf.value[1] ? [kf.value[1], kf.value[0]] : kf.value;
|
|
5513
|
+
out.push({ time: kf.time, value: v, easing: kf.easing });
|
|
5514
|
+
}
|
|
5515
|
+
while (j < uniqueTs.length) {
|
|
5516
|
+
const t = uniqueTs[j++];
|
|
5517
|
+
const v = interpolateRangeAt(kfs, t);
|
|
5518
|
+
const m = (v[0] + v[1]) / 2;
|
|
5519
|
+
out.push({ time: t, value: [m, m] });
|
|
5520
|
+
}
|
|
5521
|
+
return { kind: "animated" /* Animated */, keyframes: out };
|
|
5522
|
+
}
|
|
5523
|
+
function bisectionForRangeCrossing(prev, cur) {
|
|
5524
|
+
const f = (t) => {
|
|
5525
|
+
const a = (t - prev.time) / (cur.time - prev.time);
|
|
5526
|
+
const v0 = prev.value[0] + (cur.value[0] - prev.value[0]) * a;
|
|
5527
|
+
const v1 = prev.value[1] + (cur.value[1] - prev.value[1]) * a;
|
|
5528
|
+
return v1 - v0;
|
|
5529
|
+
};
|
|
5530
|
+
let lo = prev.time, hi = cur.time;
|
|
5531
|
+
let fLo = f(lo);
|
|
5532
|
+
if (fLo === 0) return lo;
|
|
5533
|
+
const fHi = f(hi);
|
|
5534
|
+
if (fHi === 0) return hi;
|
|
5535
|
+
if (fLo * fHi > 0) return null;
|
|
5536
|
+
for (let i = 0; i < 100; i++) {
|
|
5537
|
+
const mid = (lo + hi) / 2;
|
|
5538
|
+
const fMid = f(mid);
|
|
5539
|
+
if (fMid === 0 || Math.abs(hi - lo) < 1e-4) return mid;
|
|
5540
|
+
if (fLo * fMid < 0) {
|
|
5541
|
+
hi = mid;
|
|
5542
|
+
} else {
|
|
5543
|
+
lo = mid;
|
|
5544
|
+
fLo = fMid;
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
return (lo + hi) / 2;
|
|
5548
|
+
}
|
|
5549
|
+
function interpolateRangeAt(kfs, t) {
|
|
5550
|
+
if (t <= kfs[0].time) return kfs[0].value;
|
|
5551
|
+
if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
|
|
5552
|
+
for (let i = 1; i < kfs.length; i++) {
|
|
5553
|
+
if (t <= kfs[i].time) {
|
|
5554
|
+
const prev = kfs[i - 1];
|
|
5555
|
+
const cur = kfs[i];
|
|
5556
|
+
const a = (t - prev.time) / (cur.time - prev.time);
|
|
5557
|
+
return [
|
|
5558
|
+
prev.value[0] + (cur.value[0] - prev.value[0]) * a,
|
|
5559
|
+
prev.value[1] + (cur.value[1] - prev.value[1]) * a
|
|
5560
|
+
];
|
|
5561
|
+
}
|
|
5562
|
+
}
|
|
5563
|
+
return kfs[kfs.length - 1].value;
|
|
5564
|
+
}
|
|
5565
|
+
function pxBezierPathLength(path) {
|
|
5566
|
+
const v = path.v;
|
|
5567
|
+
if (!v || v.length < 2) return 0;
|
|
5568
|
+
let total = 0;
|
|
5569
|
+
for (let i = 0; i < v.length - 1; i++) {
|
|
5570
|
+
total += segmentLength(path, i, i + 1);
|
|
5571
|
+
}
|
|
5572
|
+
if (path.c && v.length > 1) {
|
|
5573
|
+
total += segmentLength(path, v.length - 1, 0);
|
|
5574
|
+
}
|
|
5575
|
+
return total;
|
|
5576
|
+
}
|
|
5577
|
+
function segmentLength(path, from, to) {
|
|
5578
|
+
var _a2, _b, _c, _d;
|
|
5579
|
+
const v = path.v;
|
|
5580
|
+
const p0 = v[from];
|
|
5581
|
+
const p3 = v[to];
|
|
5582
|
+
const p1 = (_b = (_a2 = path.o) == null ? void 0 : _a2[from]) != null ? _b : p0;
|
|
5583
|
+
const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
|
|
5584
|
+
const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
|
|
5585
|
+
return lut.ds[lut.ds.length - 1];
|
|
5586
|
+
}
|
|
5587
|
+
var ARC_KAPPA = 0.5522847498307936;
|
|
5588
|
+
function shapeToPathD(node) {
|
|
5589
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
5590
|
+
if (node.type === "rect") {
|
|
5591
|
+
const x = Number((_a2 = node.x) != null ? _a2 : 0), y = Number((_b = node.y) != null ? _b : 0);
|
|
5592
|
+
const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
|
|
5593
|
+
return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
|
|
5594
|
+
}
|
|
5595
|
+
if (node.type === "ellipse" || node.type === "circle") {
|
|
5596
|
+
const cx = Number((_e = node.cx) != null ? _e : 0), cy = Number((_f = node.cy) != null ? _f : 0);
|
|
5597
|
+
const rx = node.type === "circle" ? Number((_g = node.r) != null ? _g : 0) : Number((_h = node.rx) != null ? _h : 0);
|
|
5598
|
+
const ry = node.type === "circle" ? Number((_i = node.r) != null ? _i : 0) : Number((_j = node.ry) != null ? _j : 0);
|
|
5599
|
+
if (!(rx > 0) || !(ry > 0)) return void 0;
|
|
5600
|
+
const kx = rx * ARC_KAPPA, ky = ry * ARC_KAPPA;
|
|
5601
|
+
const c = (x1, y1, x2, y2, x, y) => "C" + x1 + "," + y1 + " " + x2 + "," + y2 + " " + x + "," + y;
|
|
5602
|
+
return "M" + (cx + rx) + "," + cy + c(cx + rx, cy + ky, cx + kx, cy + ry, cx, cy + ry) + c(cx - kx, cy + ry, cx - rx, cy + ky, cx - rx, cy) + c(cx - rx, cy - ky, cx - kx, cy - ry, cx, cy - ry) + c(cx + kx, cy - ry, cx + rx, cy - ky, cx + rx, cy) + "z";
|
|
5603
|
+
}
|
|
5604
|
+
return void 0;
|
|
5605
|
+
}
|
|
5606
|
+
|
|
5607
|
+
// src/effects/PlayerEffectsUtil.ts
|
|
5608
|
+
function materializeNodeEffects(root) {
|
|
5609
|
+
var _a2, _b;
|
|
5610
|
+
const ctx = {
|
|
5611
|
+
defs: [],
|
|
5612
|
+
warnings: [],
|
|
5613
|
+
errors: [],
|
|
5614
|
+
idMap: /* @__PURE__ */ new Map(),
|
|
5615
|
+
nextId: 0,
|
|
5616
|
+
contentRefInnerIds: /* @__PURE__ */ new Map(),
|
|
5617
|
+
maskAncestorChains: /* @__PURE__ */ new Map(),
|
|
5618
|
+
// Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
|
|
5619
|
+
// waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
|
|
5620
|
+
engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
|
|
5621
|
+
glyphs: (_b = getDefinitions(root)) == null ? void 0 : _b.fonts
|
|
5622
|
+
};
|
|
5623
|
+
const working = clone(root);
|
|
5624
|
+
indexById(working, ctx.idMap);
|
|
5625
|
+
identifyContentRefTargets(working, ctx, () => genId(ctx, "inner"));
|
|
5626
|
+
collectMaskAncestorChains(working, ctx);
|
|
5627
|
+
const afterPass1 = applyPlayerEffects_exceptRetime(working, ctx);
|
|
5628
|
+
const out = applyPlayerEffects_retime(afterPass1, ctx);
|
|
5629
|
+
spliceDefs(out, ctx.defs);
|
|
5630
|
+
return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
|
|
5631
|
+
}
|
|
5632
|
+
function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
5633
|
+
if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
|
|
5634
|
+
const fx = node.effects;
|
|
5635
|
+
const originalId = typeof node.id === "string" ? node.id : void 0;
|
|
5636
|
+
const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
|
|
5637
|
+
if (!fx && !innerIdForContentRef) return node;
|
|
5638
|
+
const { transformBy, repeater, maskedBy, clipPath, strokeTrim, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
|
|
5639
|
+
if (fx) delete node.effects;
|
|
5640
|
+
let n = node;
|
|
5641
|
+
let consumedByGlyphs = false;
|
|
5642
|
+
if (text == null ? void 0 : text.useGlyphs) {
|
|
5643
|
+
if (textPath) {
|
|
5644
|
+
const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
|
|
5645
|
+
const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
|
|
5646
|
+
if (glyphed) {
|
|
5647
|
+
n = glyphed;
|
|
5648
|
+
consumedByGlyphs = true;
|
|
5649
|
+
}
|
|
5650
|
+
} else {
|
|
5651
|
+
n = applyTextGlyphsEffect(n, text, ctx);
|
|
5652
|
+
consumedByGlyphs = true;
|
|
5653
|
+
}
|
|
5654
|
+
}
|
|
5655
|
+
if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
|
|
5656
|
+
n = applyFillGradientEffect(n, fillGradient, ctx);
|
|
5657
|
+
n = applyStrokeGradientEffect(n, strokeGradient, ctx);
|
|
5658
|
+
n = applyStrokeTrimEffect(n, strokeTrim, ctx);
|
|
5659
|
+
n = applyRepeaterEffect(n, repeater, ctx);
|
|
5660
|
+
n = applyMaskedByEffect(n, maskedBy, transformBy, ctx);
|
|
5661
|
+
n = applyClipPathEffect(n, clipPath, ctx);
|
|
5662
|
+
if (innerIdForContentRef) {
|
|
5663
|
+
applyRefHref(n, cloneFx, ctx);
|
|
5664
|
+
n = splitForContentRef(n, transformBy, originalId, innerIdForContentRef, ctx);
|
|
5665
|
+
} else {
|
|
5666
|
+
n = applyRefAndTransformationEffect(n, cloneFx, transformBy, ctx);
|
|
5667
|
+
}
|
|
5668
|
+
if (cloneFx == null ? void 0 : cloneFx.retime) node.effects = { clone: { retime: cloneFx.retime } };
|
|
5669
|
+
if (originalId) ctx.idMap.set(originalId, n);
|
|
5670
|
+
return n;
|
|
5671
|
+
}
|
|
5672
|
+
function applyPlayerEffects_retime(node, ctx) {
|
|
5673
|
+
applyAllRetimeEffects(node, ctx);
|
|
5674
|
+
return node;
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5677
|
+
// src/materialize/PxOffsetPathMaterializer.ts
|
|
5678
|
+
function cubicAt(p0, c1, c2, p1, t) {
|
|
5679
|
+
const u = 1 - t;
|
|
5680
|
+
const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
|
|
5681
|
+
return [
|
|
5682
|
+
a * p0[0] + b * c1[0] + c * c2[0] + d * p1[0],
|
|
5683
|
+
a * p0[1] + b * c1[1] + c * c2[1] + d * p1[1]
|
|
5684
|
+
];
|
|
5685
|
+
}
|
|
5686
|
+
function cubicLength(p0, c1, c2, p1, steps = 64) {
|
|
5687
|
+
let len = 0;
|
|
5688
|
+
let prev = p0;
|
|
5689
|
+
for (let i = 1; i <= steps; i++) {
|
|
5690
|
+
const pt = cubicAt(p0, c1, c2, p1, i / steps);
|
|
5691
|
+
len += Math.hypot(pt[0] - prev[0], pt[1] - prev[1]);
|
|
5692
|
+
prev = pt;
|
|
5693
|
+
}
|
|
5694
|
+
return len;
|
|
5695
|
+
}
|
|
5696
|
+
var fmt2 = (n) => {
|
|
5697
|
+
const r = Math.round(n * 1e4) / 1e4;
|
|
5698
|
+
return Object.is(r, -0) ? "0" : String(r);
|
|
5699
|
+
};
|
|
5700
|
+
function buildOffsetPath(propAnim) {
|
|
5701
|
+
var _a2, _b, _c;
|
|
5702
|
+
if (propAnim.alongPathMode !== "offsetPath") return void 0;
|
|
5703
|
+
const kfs = propAnim.keyframes;
|
|
5704
|
+
if (!kfs || kfs.length < 2) return void 0;
|
|
5705
|
+
const first = keyframeValue(kfs[0]);
|
|
5706
|
+
const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
|
|
5707
|
+
const points = [];
|
|
5708
|
+
let keyframesCarryRotate = false;
|
|
5709
|
+
for (const kf of kfs) {
|
|
5710
|
+
const v = keyframeValue(kf);
|
|
5711
|
+
const tr = v == null ? void 0 : v.translate;
|
|
5712
|
+
if (!tr || tr.length < 2) return void 0;
|
|
5713
|
+
const parts = Object.keys(v);
|
|
5714
|
+
if (parts.some((p) => p !== TRANSFORM_PART.translate && p !== TRANSFORM_PART.origin && p !== TRANSFORM_PART.rotate)) return void 0;
|
|
5715
|
+
if ((v == null ? void 0 : v.rotate) !== void 0) {
|
|
5716
|
+
if (v.rotate !== 0) return void 0;
|
|
5717
|
+
keyframesCarryRotate = true;
|
|
5718
|
+
}
|
|
5719
|
+
const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
|
|
5720
|
+
if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
|
|
5721
|
+
points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
|
|
5722
|
+
}
|
|
5723
|
+
if (!kfs.some((kf) => keyframeTangentIn(kf) || keyframeTangentOut(kf))) return void 0;
|
|
5724
|
+
let d = "M" + fmt2(points[0][0]) + "," + fmt2(points[0][1]);
|
|
5725
|
+
const segLens = [];
|
|
5726
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
5727
|
+
const p0 = points[i], p1 = points[i + 1];
|
|
5728
|
+
const to = (_b = keyframeTangentOut(kfs[i])) != null ? _b : [0, 0];
|
|
5729
|
+
const ti = (_c = keyframeTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
|
|
5730
|
+
const c1 = [p0[0] + to[0], p0[1] + to[1]];
|
|
5731
|
+
const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
|
|
5732
|
+
d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
|
|
5733
|
+
segLens.push(cubicLength(p0, c1, c2, p1));
|
|
5734
|
+
}
|
|
5735
|
+
const total = segLens.reduce((a, b) => a + b, 0);
|
|
5736
|
+
if (!(total > 0)) return void 0;
|
|
5737
|
+
const distanceKfs = [];
|
|
5738
|
+
let cum = 0;
|
|
5739
|
+
for (let i = 0; i < kfs.length; i++) {
|
|
5740
|
+
if (i > 0) cum += segLens[i - 1];
|
|
5741
|
+
const out = { t: keyframeTime(kfs[i]), v: cum / total };
|
|
5742
|
+
const e = keyframeEasing(kfs[i]);
|
|
5743
|
+
if (e !== void 0) out.e = e;
|
|
5744
|
+
distanceKfs.push(out);
|
|
5745
|
+
}
|
|
5746
|
+
return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor, keyframesCarryRotate };
|
|
5747
|
+
}
|
|
5748
|
+
function materializeOffsetPathsInTree(root) {
|
|
5749
|
+
const walk = (node) => {
|
|
5750
|
+
var _a2;
|
|
5751
|
+
let out = node;
|
|
5752
|
+
const anim = node.animate;
|
|
5753
|
+
const transform = anim == null ? void 0 : anim["transform"];
|
|
5754
|
+
if (transform) {
|
|
5755
|
+
const built = buildOffsetPath(transform);
|
|
5756
|
+
if (built) {
|
|
5757
|
+
const newAnimate = __spreadValues({}, anim);
|
|
5758
|
+
delete newAnimate[TRANSFORM_ATTR];
|
|
5759
|
+
const distance = { keyframes: built.distanceKfs };
|
|
5760
|
+
if (transform.loop !== void 0) distance.loop = transform.loop;
|
|
5761
|
+
newAnimate[OFFSET_DISTANCE_ATTR] = distance;
|
|
5762
|
+
const staticTr = node.transform;
|
|
5763
|
+
let newTransform = staticTr;
|
|
5764
|
+
if (staticTr && typeof staticTr === "object") {
|
|
5765
|
+
const t = __spreadValues({}, staticTr);
|
|
5766
|
+
delete t[TRANSFORM_PART.translate];
|
|
5767
|
+
delete t[TRANSFORM_PART.origin];
|
|
5768
|
+
if (built.keyframesCarryRotate) delete t[TRANSFORM_PART.rotate];
|
|
5769
|
+
newTransform = Object.keys(t).length ? t : void 0;
|
|
5770
|
+
}
|
|
5771
|
+
out = __spreadProps(__spreadValues({}, node), {
|
|
5772
|
+
animate: newAnimate,
|
|
5773
|
+
style: __spreadProps(__spreadValues({}, node.style), {
|
|
5774
|
+
offsetPath: "path('" + built.pathStr + "')",
|
|
5775
|
+
offsetAnchor: fmt2(built.anchor[0]) + "px " + fmt2(built.anchor[1]) + "px",
|
|
5776
|
+
offsetRotate: built.autoOrient ? "auto" : "0deg",
|
|
5777
|
+
offsetDistance: "0%"
|
|
5778
|
+
})
|
|
5779
|
+
});
|
|
5780
|
+
if (newTransform !== void 0) out.transform = newTransform;
|
|
5781
|
+
else delete out.transform;
|
|
5782
|
+
}
|
|
5783
|
+
}
|
|
5784
|
+
if ((_a2 = out.children) == null ? void 0 : _a2.length) {
|
|
5785
|
+
const children = out.children.map(walk);
|
|
5786
|
+
if (children.some((c, i) => c !== out.children[i])) out = __spreadProps(__spreadValues({}, out), { children });
|
|
5787
|
+
}
|
|
5788
|
+
return out;
|
|
5789
|
+
};
|
|
5790
|
+
return walk(root);
|
|
5791
|
+
}
|
|
5792
|
+
|
|
5793
|
+
// src/materialize/PxAnimatorUseMaterializer.ts
|
|
5794
|
+
function materializeAnimatedUseInstances(root) {
|
|
5795
|
+
var _a2;
|
|
5796
|
+
const idMap = buildIdMap2(root);
|
|
5797
|
+
const animatedIds = computeAnimatedSubtreeIds(root, idMap);
|
|
5798
|
+
if (animatedIds.size === 0) return root;
|
|
5799
|
+
let idCounter = 0;
|
|
5800
|
+
const genId3 = () => "_lw_use_mat_" + ++idCounter;
|
|
5801
|
+
const rootViewport = readRootViewport(root);
|
|
5802
|
+
const defsCollector = [];
|
|
5803
|
+
const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
5804
|
+
if (defsCollector.length === 0) return walked;
|
|
5805
|
+
const defsNode = { type: "defs", children: defsCollector };
|
|
5806
|
+
const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
|
|
5807
|
+
return __spreadProps(__spreadValues({}, walked), { children: newChildren });
|
|
5808
|
+
}
|
|
5809
|
+
function readRootViewport(root) {
|
|
5810
|
+
const vb = parseViewBox(root.viewBox);
|
|
5811
|
+
if (vb) return [vb[2], vb[3]];
|
|
5812
|
+
const w = numericAttr(root.width);
|
|
5813
|
+
const h = numericAttr(root.height);
|
|
5814
|
+
if (w !== void 0 && h !== void 0) return [w, h];
|
|
5815
|
+
return [1, 1];
|
|
5816
|
+
}
|
|
5817
|
+
function numericAttr(v) {
|
|
5818
|
+
if (typeof v === "number") return v;
|
|
5819
|
+
if (typeof v === "string") {
|
|
5820
|
+
const n = parseFloat(v);
|
|
5821
|
+
return Number.isFinite(n) ? n : void 0;
|
|
5822
|
+
}
|
|
5823
|
+
return void 0;
|
|
5824
|
+
}
|
|
5825
|
+
function buildIdMap2(root) {
|
|
5826
|
+
const map = /* @__PURE__ */ new Map();
|
|
5827
|
+
const visit = (n) => {
|
|
5828
|
+
var _a2;
|
|
5829
|
+
if (typeof n.id === "string") map.set(n.id, n);
|
|
5830
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
|
|
5831
|
+
};
|
|
5832
|
+
visit(root);
|
|
5833
|
+
return map;
|
|
5834
|
+
}
|
|
5835
|
+
function computeAnimatedSubtreeIds(root, idMap) {
|
|
5836
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
5837
|
+
const result = /* @__PURE__ */ new Set();
|
|
5838
|
+
const hasAnim = (n, visiting) => {
|
|
5839
|
+
const cached = cache.get(n);
|
|
5840
|
+
if (cached !== void 0) return cached;
|
|
5841
|
+
if (visiting.has(n)) return false;
|
|
5842
|
+
visiting.add(n);
|
|
5843
|
+
let r = false;
|
|
5844
|
+
if (n.animate && typeof n.animate === "object" && !Array.isArray(n.animate)) {
|
|
5845
|
+
for (const _ in n.animate) {
|
|
5846
|
+
r = true;
|
|
5847
|
+
break;
|
|
5848
|
+
}
|
|
5849
|
+
}
|
|
5850
|
+
if (!r && n.children) {
|
|
5851
|
+
for (const ch of n.children) {
|
|
5852
|
+
if (hasAnim(ch, visiting)) {
|
|
5853
|
+
r = true;
|
|
5854
|
+
break;
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
if (!r && n.type === "use" && typeof n.href === "string") {
|
|
5859
|
+
const targetId = stripHash2(n.href);
|
|
5860
|
+
const target = targetId ? idMap.get(targetId) : void 0;
|
|
5861
|
+
if (target) r = hasAnim(target, visiting);
|
|
5862
|
+
}
|
|
5863
|
+
visiting.delete(n);
|
|
5864
|
+
cache.set(n, r);
|
|
5865
|
+
return r;
|
|
5866
|
+
};
|
|
5867
|
+
for (const [id, node] of idMap) {
|
|
5868
|
+
if (hasAnim(node, /* @__PURE__ */ new Set())) result.add(id);
|
|
5869
|
+
}
|
|
5870
|
+
return result;
|
|
5871
|
+
}
|
|
5872
|
+
function stripHash2(href) {
|
|
5873
|
+
if (typeof href !== "string") return void 0;
|
|
5874
|
+
return href.startsWith("#") ? href.slice(1) : href;
|
|
5875
|
+
}
|
|
5876
|
+
function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
|
|
5877
|
+
var _a2, _b, _c, _d;
|
|
5878
|
+
const clone2 = deepClonePxNode(target);
|
|
5879
|
+
regenerateIdsAndRewriteRefs(clone2, genId3);
|
|
5880
|
+
const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
|
|
5881
|
+
const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
|
|
5882
|
+
const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
|
|
5883
|
+
const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
|
|
5884
|
+
const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
5885
|
+
const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materializedClone] });
|
|
5886
|
+
delete newNode.href;
|
|
5887
|
+
delete newNode.width;
|
|
5888
|
+
delete newNode.height;
|
|
5889
|
+
return applyUseOffsetToG(newNode);
|
|
5890
|
+
}
|
|
5891
|
+
function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
|
|
5892
|
+
const viewBox = parseViewBox(symbolNode.viewBox);
|
|
5893
|
+
const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
|
|
5894
|
+
delete g.viewBox;
|
|
5895
|
+
delete g.preserveAspectRatio;
|
|
5896
|
+
delete g.width;
|
|
5897
|
+
delete g.height;
|
|
5898
|
+
if (!viewBox) return g;
|
|
5899
|
+
const [vbX, vbY, vbW, vbH] = viewBox;
|
|
5900
|
+
const scale = vbW > 0 && vbH > 0 ? Math.min(useW / vbW, useH / vbH) : 1;
|
|
5901
|
+
const xOff = (useW - vbW * scale) / 2;
|
|
5902
|
+
const yOff = (useH - vbH * scale) / 2;
|
|
5903
|
+
const parts = [];
|
|
5904
|
+
if (xOff !== 0 || yOff !== 0) parts.push("translate(" + xOff + "," + yOff + ")");
|
|
5905
|
+
if (scale !== 1) parts.push("scale(" + scale + ")");
|
|
5906
|
+
if (vbX !== 0 || vbY !== 0) parts.push("translate(" + -vbX + "," + -vbY + ")");
|
|
5907
|
+
if (parts.length) g.transform = parts.join("");
|
|
5908
|
+
const clipId = genId3();
|
|
5909
|
+
defsCollector.push({
|
|
5910
|
+
type: "clipPath",
|
|
5911
|
+
id: clipId,
|
|
5912
|
+
children: [{ type: "rect", x: vbX, y: vbY, width: vbW, height: vbH }]
|
|
5913
|
+
});
|
|
5914
|
+
g.clipPath = "url(#" + clipId + ")";
|
|
5915
|
+
return g;
|
|
5916
|
+
}
|
|
5917
|
+
function parseViewBox(v) {
|
|
5918
|
+
if (typeof v !== "string") return void 0;
|
|
5919
|
+
const parts = v.trim().split(/[\s,]+/).map(Number);
|
|
5920
|
+
if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
|
|
5921
|
+
return [parts[0], parts[1], parts[2], parts[3]];
|
|
5922
|
+
}
|
|
5923
|
+
function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
|
|
5924
|
+
if (node.type === "use" && typeof node.href === "string") {
|
|
5925
|
+
const targetId = stripHash2(node.href);
|
|
5926
|
+
if (targetId && animatedIds.has(targetId)) {
|
|
5927
|
+
const target = idMap.get(targetId);
|
|
5928
|
+
if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
5929
|
+
}
|
|
3147
5930
|
}
|
|
3148
|
-
|
|
5931
|
+
if (!node.children) return node;
|
|
5932
|
+
let changed = false;
|
|
5933
|
+
const newChildren = node.children.map((ch) => {
|
|
5934
|
+
const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
|
|
5935
|
+
if (m !== ch) changed = true;
|
|
5936
|
+
return m;
|
|
5937
|
+
});
|
|
5938
|
+
return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
|
|
3149
5939
|
}
|
|
3150
5940
|
|
|
3151
|
-
// src/
|
|
3152
|
-
var
|
|
3153
|
-
function
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
5941
|
+
// src/util/PxIdUtil.ts
|
|
5942
|
+
var _idCounter = 0;
|
|
5943
|
+
function generateUniqueId() {
|
|
5944
|
+
const timestamp = Date.now().toString(36);
|
|
5945
|
+
const counter = (++_idCounter).toString(36);
|
|
5946
|
+
const random = Math.random().toString(36).substring(2, 6);
|
|
5947
|
+
return "_px_" + timestamp + counter + random;
|
|
5948
|
+
}
|
|
5949
|
+
function deepClone(value) {
|
|
5950
|
+
if (value === null || typeof value !== "object") return value;
|
|
5951
|
+
if (Array.isArray(value)) return value.map((item) => deepClone(item));
|
|
5952
|
+
const obj = value;
|
|
5953
|
+
const cloned = {};
|
|
5954
|
+
for (const key of Object.keys(obj)) {
|
|
5955
|
+
cloned[key] = deepClone(obj[key]);
|
|
3158
5956
|
}
|
|
5957
|
+
return cloned;
|
|
3159
5958
|
}
|
|
3160
|
-
function
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
const
|
|
3164
|
-
const
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
5959
|
+
function generateNewIds(doc) {
|
|
5960
|
+
var _a2;
|
|
5961
|
+
const cloned = deepClone(doc);
|
|
5962
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
5963
|
+
const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
|
|
5964
|
+
const urlRefAttrs = /* @__PURE__ */ new Set([
|
|
5965
|
+
"fill",
|
|
5966
|
+
"stroke",
|
|
5967
|
+
"clip-path",
|
|
5968
|
+
"clipPath",
|
|
5969
|
+
"mask",
|
|
5970
|
+
"marker",
|
|
5971
|
+
"marker-start",
|
|
5972
|
+
"marker-mid",
|
|
5973
|
+
"marker-end",
|
|
5974
|
+
"filter",
|
|
5975
|
+
"flood-color",
|
|
5976
|
+
"lighting-color"
|
|
5977
|
+
]);
|
|
5978
|
+
const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
|
|
5979
|
+
const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
|
|
5980
|
+
function collectIds(node) {
|
|
5981
|
+
if (!node || typeof node !== "object") return;
|
|
5982
|
+
if (node.id && typeof node.id === "string") {
|
|
5983
|
+
const oldId = node.id;
|
|
5984
|
+
const newId = generateUniqueId();
|
|
5985
|
+
idMap.set(oldId, newId);
|
|
5986
|
+
node.id = newId;
|
|
5987
|
+
} else if (node.animate) {
|
|
5988
|
+
node.id = generateUniqueId();
|
|
5989
|
+
}
|
|
5990
|
+
if (Array.isArray(node.children)) {
|
|
5991
|
+
for (const child of node.children) {
|
|
5992
|
+
collectIds(child);
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
function updateRefs(node, parentKey) {
|
|
5997
|
+
if (!node || typeof node !== "object") return;
|
|
5998
|
+
for (const [key, value] of Object.entries(node)) {
|
|
5999
|
+
if (key === "children") {
|
|
6000
|
+
if (Array.isArray(value)) {
|
|
6001
|
+
for (const child of value) {
|
|
6002
|
+
updateRefs(child);
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
6005
|
+
continue;
|
|
6006
|
+
}
|
|
6007
|
+
if (typeof value === "string") {
|
|
6008
|
+
if (hashRefAttrs.has(key) && value.startsWith("#")) {
|
|
6009
|
+
const oldId = value.slice(1);
|
|
6010
|
+
const newId = idMap.get(oldId);
|
|
6011
|
+
if (newId) {
|
|
6012
|
+
node[key] = "#" + newId;
|
|
6013
|
+
}
|
|
6014
|
+
} else if (urlRefAttrs.has(key)) {
|
|
6015
|
+
node[key] = replaceUrlRefs(value, idMap);
|
|
6016
|
+
} else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
|
|
6017
|
+
const hasHash = value.startsWith("#");
|
|
6018
|
+
const newId = idMap.get(hasHash ? value.slice(1) : value);
|
|
6019
|
+
if (newId) {
|
|
6020
|
+
node[key] = hasHash ? "#" + newId : newId;
|
|
6021
|
+
}
|
|
6022
|
+
} else if (value.includes("url(#")) {
|
|
6023
|
+
node[key] = replaceUrlRefs(value, idMap);
|
|
6024
|
+
}
|
|
6025
|
+
} else if (key === "style" && typeof value === "object" && value !== null) {
|
|
6026
|
+
for (const [styleProp, styleValue] of Object.entries(value)) {
|
|
6027
|
+
if (typeof styleValue === "string") {
|
|
6028
|
+
value[styleProp] = replaceUrlRefs(styleValue, idMap);
|
|
6029
|
+
}
|
|
6030
|
+
}
|
|
6031
|
+
} else if (typeof value === "object" && value !== null) {
|
|
6032
|
+
updateRefs(value, key);
|
|
6033
|
+
}
|
|
6034
|
+
}
|
|
6035
|
+
}
|
|
6036
|
+
collectIds(cloned);
|
|
6037
|
+
updateRefs(cloned);
|
|
6038
|
+
const docBindings = (_a2 = cloned.animator) == null ? void 0 : _a2.bindings;
|
|
6039
|
+
if (Array.isArray(docBindings)) {
|
|
6040
|
+
const updatedBindings = docBindings.map((binding) => {
|
|
6041
|
+
var _a3;
|
|
6042
|
+
const hashed = binding.target.startsWith("#");
|
|
6043
|
+
const id = hashed ? binding.target.slice(1) : binding.target;
|
|
6044
|
+
const newId = (_a3 = idMap.get(id)) != null ? _a3 : id;
|
|
6045
|
+
return __spreadProps(__spreadValues({}, binding), { target: hashed ? "#" + newId : newId });
|
|
6046
|
+
});
|
|
6047
|
+
cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { bindings: updatedBindings });
|
|
6048
|
+
}
|
|
6049
|
+
return cloned;
|
|
6050
|
+
}
|
|
6051
|
+
function replaceUrlRefs(value, idMap) {
|
|
6052
|
+
return value.replace(/url\(#([^)]+)\)/g, (match, oldId) => {
|
|
6053
|
+
const newId = idMap.get(oldId);
|
|
6054
|
+
return newId ? "url(#" + newId + ")" : match;
|
|
6055
|
+
});
|
|
6056
|
+
}
|
|
6057
|
+
|
|
6058
|
+
// src/materialize/PxRestPose.ts
|
|
6059
|
+
var TRANSFORM_CHANNEL = "transform";
|
|
6060
|
+
var REVERSED_DIRECTIONS = /* @__PURE__ */ new Set(["reverse", "alternate-reverse"]);
|
|
6061
|
+
var SCRATCH_ID_PREFIX = "__px_rest_";
|
|
6062
|
+
function materializeRestPosesInTree(root, engine) {
|
|
6063
|
+
var _a2;
|
|
6064
|
+
const out = deepClone(root);
|
|
6065
|
+
const config = getAnimatorConfig(out) || {};
|
|
6066
|
+
const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
|
|
6067
|
+
const firstFrameTime = REVERSED_DIRECTIONS.has(String(config.direction)) ? duration : 0;
|
|
6068
|
+
const nodes = animatedNodes(out);
|
|
6069
|
+
if (!nodes.size) return out;
|
|
6070
|
+
const before = bindingsOf(out, engine);
|
|
6071
|
+
const added = /* @__PURE__ */ new Map();
|
|
6072
|
+
for (const [key, animate] of before) {
|
|
6073
|
+
const node = nodes.get(key);
|
|
6074
|
+
if (!node) continue;
|
|
6075
|
+
for (const channel of Object.keys(animate)) {
|
|
6076
|
+
if (!mayCarryRestPose(node, channel)) continue;
|
|
6077
|
+
const value = firstFrameValue(animate, channel, firstFrameTime);
|
|
6078
|
+
if (value === void 0) continue;
|
|
6079
|
+
node[channel] = value;
|
|
6080
|
+
added.set(key, [...(_a2 = added.get(key)) != null ? _a2 : [], channel]);
|
|
6081
|
+
}
|
|
6082
|
+
}
|
|
6083
|
+
if (added.size) {
|
|
6084
|
+
const after = bindingsOf(out, engine);
|
|
6085
|
+
for (const [key, channels] of added) {
|
|
6086
|
+
if (JSON.stringify(after.get(key)) === JSON.stringify(before.get(key))) continue;
|
|
6087
|
+
const node = nodes.get(key);
|
|
6088
|
+
if (node) for (const channel of channels) delete node[channel];
|
|
6089
|
+
}
|
|
6090
|
+
}
|
|
6091
|
+
return out;
|
|
6092
|
+
}
|
|
6093
|
+
function mayCarryRestPose(node, channel) {
|
|
6094
|
+
if (node[channel] !== void 0) return false;
|
|
6095
|
+
if (PX_TRANSFORM_FN_NAMES.has(channel)) return false;
|
|
6096
|
+
if (channel === TRANSFORM_CHANNEL) {
|
|
6097
|
+
for (const part of PX_TRANSFORM_FN_NAMES) if (node[part] !== void 0) return false;
|
|
6098
|
+
}
|
|
6099
|
+
return true;
|
|
6100
|
+
}
|
|
6101
|
+
function firstFrameValue(animate, channel, timeMs) {
|
|
6102
|
+
const values = Object.values(calcAnimationValues({ [channel]: animate[channel] }, timeMs));
|
|
6103
|
+
return values.length === 1 && values[0] !== "" ? values[0] : void 0;
|
|
6104
|
+
}
|
|
6105
|
+
function bindingsOf(tree, engine) {
|
|
6106
|
+
const scratch = deepClone(tree);
|
|
6107
|
+
const keyById = /* @__PURE__ */ new Map();
|
|
6108
|
+
for (const [key, node] of animatedNodes(scratch)) {
|
|
6109
|
+
if (node.id === void 0) node.id = SCRATCH_ID_PREFIX + key;
|
|
6110
|
+
keyById.set(String(node.id), key);
|
|
6111
|
+
}
|
|
6112
|
+
const out = /* @__PURE__ */ new Map();
|
|
6113
|
+
for (const binding of normalizeBindings(scratch, engine)) {
|
|
6114
|
+
const key = keyById.get(binding.id);
|
|
6115
|
+
if (key !== void 0) out.set(key, binding.animate);
|
|
6116
|
+
}
|
|
6117
|
+
return out;
|
|
6118
|
+
}
|
|
6119
|
+
function animatedNodes(tree) {
|
|
6120
|
+
const out = /* @__PURE__ */ new Map();
|
|
6121
|
+
let counter = 0;
|
|
6122
|
+
const visit = (node) => {
|
|
6123
|
+
if (node.animate) out.set(String(counter++), node);
|
|
6124
|
+
if (node.children) for (const child of node.children) visit(child);
|
|
6125
|
+
};
|
|
6126
|
+
if (tree.children) for (const child of tree.children) visit(child);
|
|
6127
|
+
return out;
|
|
6128
|
+
}
|
|
6129
|
+
|
|
6130
|
+
// src/materialize/PxAnimatorMaterializeAll.ts
|
|
6131
|
+
function materializeAllInTree(doc, engine, options) {
|
|
6132
|
+
var _a2, _b;
|
|
6133
|
+
let root = materializeNodeEffects(doc).root;
|
|
6134
|
+
root = materializeOffsetPathsInTree(root);
|
|
6135
|
+
const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : PX_DEFAULT_DURATION_MS;
|
|
6136
|
+
root = materializeInternalLoopsInTree(root, duration);
|
|
6137
|
+
if (engine === PxTimelineEngine.native) {
|
|
6138
|
+
root = materializeMotionPathsInTree(root, options == null ? void 0 : options.motionPath);
|
|
6139
|
+
root = materializeAnimatedUseInstances(root);
|
|
6140
|
+
root = pruneUnreferencedDefs(root);
|
|
6141
|
+
}
|
|
6142
|
+
root = materializeRestPosesInTree(root, engine);
|
|
6143
|
+
return root;
|
|
6144
|
+
}
|
|
6145
|
+
function prepareDocumentForRender(doc) {
|
|
6146
|
+
var _a2;
|
|
6147
|
+
const engine = resolveTimelineEngine((_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.engine);
|
|
6148
|
+
return generateNewIds(materializeAllInTree(doc, engine));
|
|
6149
|
+
}
|
|
6150
|
+
function pruneUnreferencedDefs(root) {
|
|
6151
|
+
const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
|
|
6152
|
+
const walk = (n, fn) => {
|
|
6153
|
+
var _a2;
|
|
6154
|
+
fn(n);
|
|
6155
|
+
(_a2 = n.children) == null ? void 0 : _a2.forEach((c) => walk(c, fn));
|
|
6156
|
+
};
|
|
6157
|
+
let changed = true;
|
|
6158
|
+
while (changed) {
|
|
6159
|
+
changed = false;
|
|
6160
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
6161
|
+
walk(root, (n) => {
|
|
6162
|
+
if (n.type === "use" && typeof n.href === "string") referenced.add(stripHash3(n.href));
|
|
6163
|
+
});
|
|
6164
|
+
walk(root, (n) => {
|
|
6165
|
+
if (!n.children) return;
|
|
6166
|
+
let kept = n.children;
|
|
6167
|
+
if (n.type === "defs") {
|
|
6168
|
+
kept = kept.filter((c) => !((c.type === "g" || c.type === "symbol") && typeof c.id === "string" && !referenced.has(c.id)));
|
|
6169
|
+
}
|
|
6170
|
+
kept = kept.filter((c) => !(c.type === "defs" && (!c.children || c.children.length === 0)));
|
|
6171
|
+
if (kept.length !== n.children.length) {
|
|
6172
|
+
n.children = kept;
|
|
6173
|
+
changed = true;
|
|
6174
|
+
}
|
|
6175
|
+
});
|
|
6176
|
+
}
|
|
6177
|
+
return root;
|
|
3168
6178
|
}
|
|
3169
6179
|
|
|
3170
6180
|
// src/playback/PxDiagnostics.ts
|
|
6181
|
+
var PxDiagnosticKind = {
|
|
6182
|
+
/** The document is wrong — regenerate or repair the file. */
|
|
6183
|
+
document: "document",
|
|
6184
|
+
/** The page or app cannot provide what the document asks for — fix the mount. */
|
|
6185
|
+
host: "host",
|
|
6186
|
+
/** The platform cannot do it and the player degraded — usually nothing to fix. */
|
|
6187
|
+
platform: "platform",
|
|
6188
|
+
/** The call is wrong or self-contradictory — fix the options or props you passed. */
|
|
6189
|
+
usage: "usage",
|
|
6190
|
+
/** The player failed where it did not expect to — report it to us. */
|
|
6191
|
+
internal: "internal"
|
|
6192
|
+
};
|
|
3171
6193
|
var DOCS_URL = "https://github.com/pixodesk/pixodesk-svg-animator/blob/main/docs/diagnostics.md";
|
|
3172
6194
|
function codeLine(code) {
|
|
3173
6195
|
return "PX" + code + " " + DOCS_URL + "#px" + code;
|
|
@@ -3200,81 +6222,6 @@ function createDiagnostics(config, prefix) {
|
|
|
3200
6222
|
};
|
|
3201
6223
|
}
|
|
3202
6224
|
|
|
3203
|
-
// src/playback/PxScrollMath.ts
|
|
3204
|
-
function isScrollTimeline(config) {
|
|
3205
|
-
return (config == null ? void 0 : config.timelineSource) === "scroll";
|
|
3206
|
-
}
|
|
3207
|
-
function scrollTotalDurationMs(config) {
|
|
3208
|
-
const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : PX_DEFAULT_DURATION_MS;
|
|
3209
|
-
const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
|
|
3210
|
-
return duration * iterations;
|
|
3211
|
-
}
|
|
3212
|
-
function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
|
|
3213
|
-
const s = subjectSize, vp = scrollportSize;
|
|
3214
|
-
switch (phase) {
|
|
3215
|
-
case "cover":
|
|
3216
|
-
return [0, s + vp];
|
|
3217
|
-
case "entry":
|
|
3218
|
-
return [0, Math.min(s, vp)];
|
|
3219
|
-
case "contain":
|
|
3220
|
-
return [Math.min(s, vp), Math.max(s, vp)];
|
|
3221
|
-
case "exit":
|
|
3222
|
-
return [Math.max(s, vp), s + vp];
|
|
3223
|
-
case "entry-crossing":
|
|
3224
|
-
return [0, s];
|
|
3225
|
-
case "exit-crossing":
|
|
3226
|
-
return [vp, s + vp];
|
|
3227
|
-
}
|
|
3228
|
-
}
|
|
3229
|
-
var DEFAULT_PHASE = "cover";
|
|
3230
|
-
function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
|
|
3231
|
-
var _a2;
|
|
3232
|
-
const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
|
|
3233
|
-
const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
|
|
3234
|
-
return u0 + fraction * (u1 - u0);
|
|
3235
|
-
}
|
|
3236
|
-
function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
|
|
3237
|
-
const u = scrollportSize - subjectStart;
|
|
3238
|
-
const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
|
|
3239
|
-
const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
|
|
3240
|
-
if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
|
|
3241
|
-
return clamp((u - uStart) / (uEnd - uStart), 0, 1);
|
|
3242
|
-
}
|
|
3243
|
-
function scrollOffsetProgress(offset, maxOffset, range) {
|
|
3244
|
-
var _a2, _b;
|
|
3245
|
-
const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
|
|
3246
|
-
const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
|
|
3247
|
-
const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
|
|
3248
|
-
if (end <= start) return raw >= end ? 1 : 0;
|
|
3249
|
-
return clamp((raw - start) / (end - start), 0, 1);
|
|
3250
|
-
}
|
|
3251
|
-
function scrollResolveAxis(axis, writingMode) {
|
|
3252
|
-
const a = axis != null ? axis : "block";
|
|
3253
|
-
if (a === "x" || a === "y") return a;
|
|
3254
|
-
const vertical = !!writingMode && writingMode.startsWith("vertical");
|
|
3255
|
-
if (a === "inline") return vertical ? "y" : "x";
|
|
3256
|
-
return vertical ? "x" : "y";
|
|
3257
|
-
}
|
|
3258
|
-
|
|
3259
|
-
// src/util/PxIdUtil.ts
|
|
3260
|
-
var _idCounter = 0;
|
|
3261
|
-
function generateUniqueId() {
|
|
3262
|
-
const timestamp = Date.now().toString(36);
|
|
3263
|
-
const counter = (++_idCounter).toString(36);
|
|
3264
|
-
const random = Math.random().toString(36).substring(2, 6);
|
|
3265
|
-
return "_px_" + timestamp + counter + random;
|
|
3266
|
-
}
|
|
3267
|
-
function deepClone(value) {
|
|
3268
|
-
if (value === null || typeof value !== "object") return value;
|
|
3269
|
-
if (Array.isArray(value)) return value.map((item) => deepClone(item));
|
|
3270
|
-
const obj = value;
|
|
3271
|
-
const cloned = {};
|
|
3272
|
-
for (const key of Object.keys(obj)) {
|
|
3273
|
-
cloned[key] = deepClone(obj[key]);
|
|
3274
|
-
}
|
|
3275
|
-
return cloned;
|
|
3276
|
-
}
|
|
3277
|
-
|
|
3278
6225
|
// src/util/PxNodeProps.ts
|
|
3279
6226
|
var PX_DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
|
|
3280
6227
|
"script",
|
|
@@ -3338,6 +6285,135 @@ function sanitizeAttributeValue(name, value) {
|
|
|
3338
6285
|
}
|
|
3339
6286
|
return value;
|
|
3340
6287
|
}
|
|
6288
|
+
function toDomProps(props) {
|
|
6289
|
+
const propsCopy = {};
|
|
6290
|
+
for (const rawKey of Object.keys(props)) {
|
|
6291
|
+
const key = kebabToCamelCaseWord(rawKey);
|
|
6292
|
+
if (INTERNAL_ATTRS.has(key)) continue;
|
|
6293
|
+
if (key === "style") continue;
|
|
6294
|
+
let value = props[rawKey];
|
|
6295
|
+
if (PX_COLOR_ATTR_NAMES.has(key) && Array.isArray(value)) {
|
|
6296
|
+
propsCopy[key] = toRGBA(value);
|
|
6297
|
+
} else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
|
|
6298
|
+
const parts = value.value && typeof value.value === "object" ? value.value : value;
|
|
6299
|
+
propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
|
|
6300
|
+
} else if (PX_TRANSFORM_FN_NAMES.has(key)) {
|
|
6301
|
+
if (Array.isArray(value)) {
|
|
6302
|
+
if (key === "translate") value = value.map((v) => v + "px");
|
|
6303
|
+
value = value.join(",");
|
|
6304
|
+
}
|
|
6305
|
+
if (key === "rotate") value = value + "deg";
|
|
6306
|
+
propsCopy[TRANSFORM_ATTR] = key + "(" + value + ")";
|
|
6307
|
+
} else if (Array.isArray(value)) {
|
|
6308
|
+
propsCopy[key] = value.join(",");
|
|
6309
|
+
} else if (value !== void 0 && value !== null) {
|
|
6310
|
+
propsCopy[key] = String(value);
|
|
6311
|
+
}
|
|
6312
|
+
}
|
|
6313
|
+
return propsCopy;
|
|
6314
|
+
}
|
|
6315
|
+
|
|
6316
|
+
// src/render/PxRenderTree.ts
|
|
6317
|
+
var CLASS_NAME_KEY = "className";
|
|
6318
|
+
var CLASS_ATTR2 = "class";
|
|
6319
|
+
var DOM_TYPE_KEY = "domType";
|
|
6320
|
+
var TYPE_ATTR = "type";
|
|
6321
|
+
var DEFAULT_TAG = "g";
|
|
6322
|
+
function renderPxTree(node, factory, diag) {
|
|
6323
|
+
return node ? renderOne(node, factory, diag, true, 0) : null;
|
|
6324
|
+
}
|
|
6325
|
+
function renderOne(node, factory, diag, isRoot, index) {
|
|
6326
|
+
const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
|
|
6327
|
+
const tag = type || DEFAULT_TAG;
|
|
6328
|
+
if (PX_DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
|
|
6329
|
+
(diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, 1103 /* blockedTag */, tag);
|
|
6330
|
+
return null;
|
|
6331
|
+
}
|
|
6332
|
+
const domType = props[DOM_TYPE_KEY];
|
|
6333
|
+
if (domType !== void 0) delete props[DOM_TYPE_KEY];
|
|
6334
|
+
const attrs = {};
|
|
6335
|
+
let inlineStyle;
|
|
6336
|
+
const domProps = toDomProps(props);
|
|
6337
|
+
for (const propName of Object.keys(domProps)) {
|
|
6338
|
+
const sanitized = sanitizeAttributeValue(propName, domProps[propName]);
|
|
6339
|
+
if (sanitized === void 0) continue;
|
|
6340
|
+
if (PX_CSS_ONLY_STYLE_PROPS.has(propName)) {
|
|
6341
|
+
(inlineStyle != null ? inlineStyle : inlineStyle = {})[propName] = String(sanitized);
|
|
6342
|
+
continue;
|
|
6343
|
+
}
|
|
6344
|
+
attrs[propName === CLASS_NAME_KEY ? CLASS_ATTR2 : camelCaseToKebabWordIfNeeded(propName)] = sanitized;
|
|
6345
|
+
}
|
|
6346
|
+
if (domType !== void 0) attrs[TYPE_ATTR] = String(domType);
|
|
6347
|
+
if (style) {
|
|
6348
|
+
for (const styleProp of Object.keys(style)) (inlineStyle != null ? inlineStyle : inlineStyle = {})[styleProp] = String(style[styleProp]);
|
|
6349
|
+
}
|
|
6350
|
+
const rendered = [];
|
|
6351
|
+
if (children) {
|
|
6352
|
+
children.forEach((child, i) => {
|
|
6353
|
+
const el = renderOne(child, factory, diag, false, i);
|
|
6354
|
+
if (el !== null) rendered.push(el);
|
|
6355
|
+
});
|
|
6356
|
+
}
|
|
6357
|
+
const ownText = props[PX_TEXT_CONTENT_ATTR];
|
|
6358
|
+
const text = !rendered.length && typeof ownText === "string" && ownText ? ownText : void 0;
|
|
6359
|
+
return factory({ tag, attrs, style: inlineStyle, children: rendered, text, node, isRoot, index });
|
|
6360
|
+
}
|
|
6361
|
+
|
|
6362
|
+
// src/playback/PxScrollMath.ts
|
|
6363
|
+
function isScrollTimeline(config) {
|
|
6364
|
+
return (config == null ? void 0 : config.timelineSource) === "scroll";
|
|
6365
|
+
}
|
|
6366
|
+
function scrollTotalDurationMs(config) {
|
|
6367
|
+
const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : PX_DEFAULT_DURATION_MS;
|
|
6368
|
+
const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
|
|
6369
|
+
return duration * iterations;
|
|
6370
|
+
}
|
|
6371
|
+
function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
|
|
6372
|
+
const s = subjectSize, vp = scrollportSize;
|
|
6373
|
+
switch (phase) {
|
|
6374
|
+
case "cover":
|
|
6375
|
+
return [0, s + vp];
|
|
6376
|
+
case "entry":
|
|
6377
|
+
return [0, Math.min(s, vp)];
|
|
6378
|
+
case "contain":
|
|
6379
|
+
return [Math.min(s, vp), Math.max(s, vp)];
|
|
6380
|
+
case "exit":
|
|
6381
|
+
return [Math.max(s, vp), s + vp];
|
|
6382
|
+
case "entry-crossing":
|
|
6383
|
+
return [0, s];
|
|
6384
|
+
case "exit-crossing":
|
|
6385
|
+
return [vp, s + vp];
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6388
|
+
var DEFAULT_PHASE = "cover";
|
|
6389
|
+
function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
|
|
6390
|
+
var _a2;
|
|
6391
|
+
const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
|
|
6392
|
+
const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
|
|
6393
|
+
return u0 + fraction * (u1 - u0);
|
|
6394
|
+
}
|
|
6395
|
+
function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
|
|
6396
|
+
const u = scrollportSize - subjectStart;
|
|
6397
|
+
const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
|
|
6398
|
+
const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
|
|
6399
|
+
if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
|
|
6400
|
+
return clamp((u - uStart) / (uEnd - uStart), 0, 1);
|
|
6401
|
+
}
|
|
6402
|
+
function scrollOffsetProgress(offset, maxOffset, range) {
|
|
6403
|
+
var _a2, _b;
|
|
6404
|
+
const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
|
|
6405
|
+
const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
|
|
6406
|
+
const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
|
|
6407
|
+
if (end <= start) return raw >= end ? 1 : 0;
|
|
6408
|
+
return clamp((raw - start) / (end - start), 0, 1);
|
|
6409
|
+
}
|
|
6410
|
+
function scrollResolveAxis(axis, writingMode) {
|
|
6411
|
+
const a = axis != null ? axis : "block";
|
|
6412
|
+
if (a === "x" || a === "y") return a;
|
|
6413
|
+
const vertical = !!writingMode && writingMode.startsWith("vertical");
|
|
6414
|
+
if (a === "inline") return vertical ? "y" : "x";
|
|
6415
|
+
return vertical ? "x" : "y";
|
|
6416
|
+
}
|
|
3341
6417
|
|
|
3342
6418
|
// src/version/PxSchemaFieldUniverse.ts
|
|
3343
6419
|
function schemaFieldUniverse(root) {
|
|
@@ -3498,7 +6574,9 @@ function releaseLogProblems(releases, steps, declared, baseline) {
|
|
|
3498
6574
|
materializeMotionPathInPropAnim,
|
|
3499
6575
|
mergeStaticTransformIntoAnimDef,
|
|
3500
6576
|
planSchemaRelease,
|
|
6577
|
+
prepareDocumentForRender,
|
|
3501
6578
|
releaseLogProblems,
|
|
6579
|
+
renderPxTree,
|
|
3502
6580
|
reportDocumentDiagnostics,
|
|
3503
6581
|
reverseEasing,
|
|
3504
6582
|
sanitizeAttributeValue,
|