@hyperframes/parsers 0.7.70 → 0.7.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/colorGradingContract.d.ts +17 -0
- package/dist/colorGradingContract.js +269 -0
- package/dist/colorGradingContract.js.map +1 -0
- package/dist/gsapConstants.js +4 -0
- package/dist/gsapConstants.js.map +1 -1
- package/dist/gsapParser.d.ts +3 -4
- package/dist/gsapParser.js +201 -86
- package/dist/gsapParser.js.map +1 -1
- package/dist/gsapParserAcorn.js +41 -29
- package/dist/gsapParserAcorn.js.map +1 -1
- package/dist/gsapParserExports.js +45 -29
- package/dist/gsapParserExports.js.map +1 -1
- package/dist/gsapWriterAcorn.d.ts +3 -4
- package/dist/gsapWriterAcorn.js +167 -69
- package/dist/gsapWriterAcorn.js.map +1 -1
- package/dist/index.js +45 -29
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
|
@@ -45,10 +45,9 @@ declare function removeKeyframeFromScript(script: string, animationId: string, p
|
|
|
45
45
|
/**
|
|
46
46
|
* Retime a keyframe: move the keyframe at `fromPercentage` to `toPercentage`,
|
|
47
47
|
* PRESERVING its properties and per-keyframe ease (the Studio "Move to Playhead"
|
|
48
|
-
* gesture). Re-sorts keyframes by percentage.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* the move resolves onto the same keyframe.
|
|
48
|
+
* gesture). Re-sorts keyframes by percentage. No-op when the animation/keyframe
|
|
49
|
+
* isn't found, the tween has no object-form keyframes, the move resolves onto the
|
|
50
|
+
* same keyframe, or the destination is occupied.
|
|
52
51
|
*/
|
|
53
52
|
declare function moveKeyframeInScript(script: string, animationId: string, fromPercentage: number, toPercentage: number): string;
|
|
54
53
|
/**
|
package/dist/gsapWriterAcorn.js
CHANGED
|
@@ -29,6 +29,23 @@ function classifyTweenPropertyGroup(properties) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// src/gsapSerialize.ts
|
|
32
|
+
function mergePercentageKeyframes(keyframes) {
|
|
33
|
+
const byPercentage = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const keyframe of keyframes) {
|
|
35
|
+
const existing = byPercentage.get(keyframe.percentage);
|
|
36
|
+
if (!existing) {
|
|
37
|
+
byPercentage.set(keyframe.percentage, {
|
|
38
|
+
...keyframe,
|
|
39
|
+
properties: { ...keyframe.properties }
|
|
40
|
+
});
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
existing.properties = { ...existing.properties, ...keyframe.properties };
|
|
44
|
+
if (keyframe.ease !== void 0) existing.ease = keyframe.ease;
|
|
45
|
+
if (keyframe.auto !== void 0) existing.auto = keyframe.auto;
|
|
46
|
+
}
|
|
47
|
+
return [...byPercentage.values()].sort((a, b) => a.percentage - b.percentage);
|
|
48
|
+
}
|
|
32
49
|
function buildArcPath(coords, curviness, autoRotate, isCubic) {
|
|
33
50
|
const first = coords[0];
|
|
34
51
|
if (coords.length < 2 || !first) return void 0;
|
|
@@ -159,6 +176,61 @@ function readProvenance(node) {
|
|
|
159
176
|
return node?.__hfProvenance;
|
|
160
177
|
}
|
|
161
178
|
|
|
179
|
+
// src/gsapObjectArrayTiming.ts
|
|
180
|
+
var roundPercentage = (percentage) => Math.round(percentage * 10) / 10;
|
|
181
|
+
var OBJECT_ARRAY_PERCENTAGE_TOLERANCE = 2;
|
|
182
|
+
function getObjectArrayKeyframeTiming(durations) {
|
|
183
|
+
const hasAuthoredDuration = durations.some((duration) => duration !== void 0);
|
|
184
|
+
if (hasAuthoredDuration) {
|
|
185
|
+
if (!durations.every(
|
|
186
|
+
(duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
|
|
187
|
+
)) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
const totalDuration = durations.reduce((sum, duration) => sum + duration, 0);
|
|
191
|
+
let cumulative = 0;
|
|
192
|
+
return {
|
|
193
|
+
percentages: durations.map((duration) => {
|
|
194
|
+
cumulative += duration;
|
|
195
|
+
return roundPercentage(cumulative / totalDuration * 100);
|
|
196
|
+
}),
|
|
197
|
+
totalDuration
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const lastIndex = durations.length - 1;
|
|
201
|
+
return {
|
|
202
|
+
percentages: durations.map(
|
|
203
|
+
(_, index) => lastIndex > 0 ? roundPercentage(index / lastIndex * 100) : 0
|
|
204
|
+
)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function getCompatibleObjectArrayKeyframeTiming(durations, outerDuration) {
|
|
208
|
+
const timing = getObjectArrayKeyframeTiming(durations);
|
|
209
|
+
if (!timing) return null;
|
|
210
|
+
if (timing.totalDuration === void 0 || outerDuration === void 0) return timing;
|
|
211
|
+
if (typeof outerDuration === "number" && Math.abs(outerDuration - timing.totalDuration) <= Number.EPSILON) {
|
|
212
|
+
return timing;
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
function findObjectArrayKeyframeIndex(durations, percentage, options) {
|
|
217
|
+
if (!Number.isFinite(percentage) || percentage < 0 || percentage > 100) return null;
|
|
218
|
+
const timing = getObjectArrayKeyframeTiming(durations);
|
|
219
|
+
if (!timing) return null;
|
|
220
|
+
const { percentages } = timing;
|
|
221
|
+
let match = null;
|
|
222
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
223
|
+
for (let index = 0; index < percentages.length; index++) {
|
|
224
|
+
const distance = Math.abs(percentages[index] - percentage);
|
|
225
|
+
if (distance < bestDistance) {
|
|
226
|
+
match = index;
|
|
227
|
+
bestDistance = distance;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const tolerance = options?.tolerance ?? OBJECT_ARRAY_PERCENTAGE_TOLERANCE;
|
|
231
|
+
return bestDistance <= tolerance || options?.fallbackToNearest ? match : null;
|
|
232
|
+
}
|
|
233
|
+
|
|
162
234
|
// src/gsapParserAcorn.ts
|
|
163
235
|
var GSAP_METHODS = /* @__PURE__ */ new Set(["set", "to", "from", "fromTo"]);
|
|
164
236
|
var QUERY_METHODS = /* @__PURE__ */ new Set(["querySelector", "querySelectorAll"]);
|
|
@@ -729,6 +801,8 @@ function parsePercentageKeyframes(node, scope, source) {
|
|
|
729
801
|
for (const [k, v] of Object.entries(record)) {
|
|
730
802
|
if (k === "ease" && typeof v === "string") {
|
|
731
803
|
kfEase = v;
|
|
804
|
+
} else if (k === "duration") {
|
|
805
|
+
continue;
|
|
732
806
|
} else if (typeof v === "number" || typeof v === "string") {
|
|
733
807
|
properties[k] = v;
|
|
734
808
|
}
|
|
@@ -753,13 +827,13 @@ function computeKeyframesTotalDuration(varsNode, scope, source) {
|
|
|
753
827
|
(p) => (p.key?.name ?? p.key?.value) === "keyframes"
|
|
754
828
|
)?.value;
|
|
755
829
|
if (!kfNode || kfNode.type !== "ArrayExpression") return void 0;
|
|
756
|
-
|
|
830
|
+
const durations = [];
|
|
757
831
|
for (const el of kfNode.elements ?? []) {
|
|
758
832
|
if (!el || el.type !== "ObjectExpression") continue;
|
|
759
833
|
const r = objectExpressionToRecord(el, scope, source);
|
|
760
|
-
|
|
834
|
+
durations.push(r.duration);
|
|
761
835
|
}
|
|
762
|
-
return
|
|
836
|
+
return getObjectArrayKeyframeTiming(durations)?.totalDuration;
|
|
763
837
|
}
|
|
764
838
|
function parseObjectArrayKeyframes(node, scope, source) {
|
|
765
839
|
const elements = node.elements ?? [];
|
|
@@ -771,7 +845,7 @@ function parseObjectArrayKeyframes(node, scope, source) {
|
|
|
771
845
|
let duration;
|
|
772
846
|
let ease;
|
|
773
847
|
for (const [k, v] of Object.entries(record)) {
|
|
774
|
-
if (k === "duration"
|
|
848
|
+
if (k === "duration") {
|
|
775
849
|
duration = v;
|
|
776
850
|
} else if (k === "ease" && typeof v === "string") {
|
|
777
851
|
ease = v;
|
|
@@ -781,31 +855,13 @@ function parseObjectArrayKeyframes(node, scope, source) {
|
|
|
781
855
|
}
|
|
782
856
|
raw.push({ properties, duration, ease });
|
|
783
857
|
}
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
keyframes.push({
|
|
792
|
-
percentage,
|
|
793
|
-
properties: entry.properties,
|
|
794
|
-
...entry.ease ? { ease: entry.ease } : {}
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
} else {
|
|
798
|
-
for (let i = 0; i < raw.length; i++) {
|
|
799
|
-
const entry = raw[i];
|
|
800
|
-
if (!entry) continue;
|
|
801
|
-
const percentage = raw.length > 1 ? Math.round(i / (raw.length - 1) * 100) : 0;
|
|
802
|
-
keyframes.push({
|
|
803
|
-
percentage,
|
|
804
|
-
properties: entry.properties,
|
|
805
|
-
...entry.ease ? { ease: entry.ease } : {}
|
|
806
|
-
});
|
|
807
|
-
}
|
|
808
|
-
}
|
|
858
|
+
const timing = getObjectArrayKeyframeTiming(raw.map((entry) => entry.duration));
|
|
859
|
+
if (!timing) return void 0;
|
|
860
|
+
const keyframes = raw.map((entry, index) => ({
|
|
861
|
+
percentage: timing.percentages[index],
|
|
862
|
+
properties: entry.properties,
|
|
863
|
+
...entry.ease ? { ease: entry.ease } : {}
|
|
864
|
+
}));
|
|
809
865
|
return { format: "object-array", keyframes };
|
|
810
866
|
}
|
|
811
867
|
function parseSimpleArrayKeyframes(node, scope) {
|
|
@@ -1698,43 +1754,85 @@ function findKfPropByPct(kfNode, percentage) {
|
|
|
1698
1754
|
}
|
|
1699
1755
|
return best;
|
|
1700
1756
|
}
|
|
1757
|
+
function updateMotionPathPosition(script, target, percentage, properties) {
|
|
1758
|
+
const waypoints = extractArcWaypoints(target.animation);
|
|
1759
|
+
if (waypoints.length < 2) return void 0;
|
|
1760
|
+
const pointIndex = Math.max(
|
|
1761
|
+
0,
|
|
1762
|
+
Math.min(waypoints.length - 1, Math.round(percentage / 100 * (waypoints.length - 1)))
|
|
1763
|
+
);
|
|
1764
|
+
const current = waypoints[pointIndex];
|
|
1765
|
+
if (!current) return void 0;
|
|
1766
|
+
const x = properties.x ?? current.x;
|
|
1767
|
+
const y = properties.y ?? current.y;
|
|
1768
|
+
if (typeof x !== "number" || typeof y !== "number") return void 0;
|
|
1769
|
+
return updateMotionPathPointInScript(script, target.id, pointIndex, { x, y });
|
|
1770
|
+
}
|
|
1771
|
+
function updateTweenEase(script, animationId, ease) {
|
|
1772
|
+
const reparsed = parseGsapScriptAcornForWrite(script);
|
|
1773
|
+
const target = reparsed?.located.find((entry) => entry.id === animationId);
|
|
1774
|
+
if (!target) return void 0;
|
|
1775
|
+
const ms = new MagicString(script);
|
|
1776
|
+
upsertProp(ms, target.call.varsArg, "ease", ease);
|
|
1777
|
+
return ms.toString();
|
|
1778
|
+
}
|
|
1779
|
+
function updateMotionPathKeyframe(script, target, percentage, properties, ease) {
|
|
1780
|
+
if (!target.animation.arcPath?.enabled || !findPropertyNode2(target.call.varsArg, "motionPath")) {
|
|
1781
|
+
return void 0;
|
|
1782
|
+
}
|
|
1783
|
+
const propertyKeys = Object.keys(properties);
|
|
1784
|
+
if (propertyKeys.some((key) => key !== "x" && key !== "y")) return void 0;
|
|
1785
|
+
const next = propertyKeys.length === 0 ? script : updateMotionPathPosition(script, target, percentage, properties);
|
|
1786
|
+
if (next === void 0 || ease === void 0) return next;
|
|
1787
|
+
return updateTweenEase(next, target.id, ease);
|
|
1788
|
+
}
|
|
1789
|
+
function updateObjectKeyframe(script, prop, properties, ease) {
|
|
1790
|
+
const ms = new MagicString(script);
|
|
1791
|
+
if (prop.value?.type === "ObjectExpression") {
|
|
1792
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
1793
|
+
upsertProp(ms, prop.value, key, value);
|
|
1794
|
+
}
|
|
1795
|
+
if (ease !== void 0) upsertProp(ms, prop.value, "ease", ease);
|
|
1796
|
+
} else {
|
|
1797
|
+
const record = { ...properties };
|
|
1798
|
+
if (ease) record.ease = ease;
|
|
1799
|
+
ms.overwrite(prop.value.start, prop.value.end, recordToCode(record));
|
|
1800
|
+
}
|
|
1801
|
+
return ms.toString();
|
|
1802
|
+
}
|
|
1701
1803
|
function updateKeyframeInScript(script, animationId, percentage, properties, ease) {
|
|
1702
1804
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
1703
1805
|
if (!parsed) return script;
|
|
1704
1806
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
1705
1807
|
if (!target) return script;
|
|
1706
1808
|
const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
|
|
1707
|
-
if (!kfPropNode)
|
|
1809
|
+
if (!kfPropNode) {
|
|
1810
|
+
return updateMotionPathKeyframe(script, target, percentage, properties, ease) ?? script;
|
|
1811
|
+
}
|
|
1708
1812
|
if (kfPropNode.value?.type === "ArrayExpression") {
|
|
1709
1813
|
return updateArrayKeyframeByPct(script, kfPropNode.value, percentage, properties, ease);
|
|
1710
1814
|
}
|
|
1711
1815
|
if (kfPropNode.value?.type !== "ObjectExpression") return script;
|
|
1712
1816
|
const match = findKfPropByPct(kfPropNode.value, percentage);
|
|
1713
1817
|
if (!match) return script;
|
|
1714
|
-
|
|
1715
|
-
if (match.prop.value?.type === "ObjectExpression") {
|
|
1716
|
-
for (const [k, v] of Object.entries(properties)) {
|
|
1717
|
-
upsertProp(ms, match.prop.value, k, v);
|
|
1718
|
-
}
|
|
1719
|
-
if (ease !== void 0) upsertProp(ms, match.prop.value, "ease", ease);
|
|
1720
|
-
} else {
|
|
1721
|
-
const record = { ...properties };
|
|
1722
|
-
if (ease) record.ease = ease;
|
|
1723
|
-
ms.overwrite(match.prop.value.start, match.prop.value.end, recordToCode(record));
|
|
1724
|
-
}
|
|
1725
|
-
return ms.toString();
|
|
1818
|
+
return updateObjectKeyframe(script, match.prop, properties, ease);
|
|
1726
1819
|
}
|
|
1727
1820
|
function updateArrayKeyframeByPct(script, arrayNode, percentage, properties, ease) {
|
|
1728
1821
|
const elements = (arrayNode.elements ?? []).filter(
|
|
1729
1822
|
(el2) => !!el2 && el2.type === "ObjectExpression"
|
|
1730
1823
|
);
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
const idx =
|
|
1734
|
-
|
|
1824
|
+
if (elements.length === 0) return script;
|
|
1825
|
+
const records = elements.map((element) => valueNodeToRecord(element, script));
|
|
1826
|
+
const idx = findObjectArrayKeyframeIndex(
|
|
1827
|
+
records.map((record) => record.duration),
|
|
1828
|
+
percentage,
|
|
1829
|
+
{ fallbackToNearest: true }
|
|
1830
|
+
);
|
|
1831
|
+
if (idx === null) return script;
|
|
1832
|
+
const el = elements[idx];
|
|
1735
1833
|
if (!el) return script;
|
|
1736
1834
|
const merged = {
|
|
1737
|
-
...
|
|
1835
|
+
...records[idx],
|
|
1738
1836
|
...properties
|
|
1739
1837
|
};
|
|
1740
1838
|
if (ease) merged.ease = ease;
|
|
@@ -1785,14 +1883,23 @@ function convertArrayKeyframesToObject(script, target) {
|
|
|
1785
1883
|
const els = (kfPropNode.value.elements ?? []).filter(
|
|
1786
1884
|
(el) => !!el && el.type === "ObjectExpression"
|
|
1787
1885
|
);
|
|
1788
|
-
|
|
1789
|
-
|
|
1886
|
+
if (els.length === 0) return script;
|
|
1887
|
+
const records = els.map((element) => valueNodeToRecord(element, script));
|
|
1888
|
+
const outerDuration = valueNodeToRecord(target.call.varsArg, script).duration;
|
|
1889
|
+
const timing = getCompatibleObjectArrayKeyframeTiming(
|
|
1890
|
+
records.map((record) => record.duration),
|
|
1891
|
+
outerDuration
|
|
1892
|
+
);
|
|
1893
|
+
if (!timing) return script;
|
|
1790
1894
|
const entries = els.map((el, i) => {
|
|
1791
|
-
const
|
|
1792
|
-
return `${JSON.stringify(`${
|
|
1895
|
+
const { duration: _duration, ...record } = records[i];
|
|
1896
|
+
return `${JSON.stringify(`${timing.percentages[i]}%`)}: ${recordToCode(record)}`;
|
|
1793
1897
|
});
|
|
1794
1898
|
const ms = new MagicString(script);
|
|
1795
1899
|
ms.overwrite(kfPropNode.value.start, kfPropNode.value.end, `{ ${entries.join(", ")} }`);
|
|
1900
|
+
if (timing.totalDuration !== void 0 && findPropertyNode2(target.call.varsArg, "duration") === void 0) {
|
|
1901
|
+
upsertProp(ms, target.call.varsArg, "duration", timing.totalDuration);
|
|
1902
|
+
}
|
|
1796
1903
|
return ms.toString();
|
|
1797
1904
|
}
|
|
1798
1905
|
function ensureKeyframesNode(script, animationId) {
|
|
@@ -1877,25 +1984,17 @@ function collapseKeyframesToFlat(ms, varsNode, source, remainingRecord) {
|
|
|
1877
1984
|
}
|
|
1878
1985
|
ms.overwrite(varsNode.start, varsNode.end, `{ ${entries.join(", ")} }`);
|
|
1879
1986
|
}
|
|
1880
|
-
function arrayKeyframePct(i, n) {
|
|
1881
|
-
return n > 1 ? i / (n - 1) * 100 : 0;
|
|
1882
|
-
}
|
|
1883
1987
|
function removeArrayKeyframe(ms, varsArg, arrNode, script, percentage) {
|
|
1884
1988
|
const elements = (arrNode.elements ?? []).filter(
|
|
1885
1989
|
(e) => !!e && e.type === "ObjectExpression"
|
|
1886
1990
|
);
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
matchIdx = i;
|
|
1895
|
-
bestDist = dist;
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
if (matchIdx === -1) return false;
|
|
1991
|
+
if (elements.length === 0) return false;
|
|
1992
|
+
const records = elements.map((element) => valueNodeToRecord(element, script));
|
|
1993
|
+
const matchIdx = findObjectArrayKeyframeIndex(
|
|
1994
|
+
records.map((record) => record.duration),
|
|
1995
|
+
percentage
|
|
1996
|
+
);
|
|
1997
|
+
if (matchIdx === null) return false;
|
|
1899
1998
|
const remaining = elements.filter((_, i) => i !== matchIdx);
|
|
1900
1999
|
if (remaining.length < 2) {
|
|
1901
2000
|
const sole = remaining[0];
|
|
@@ -1941,11 +2040,10 @@ function moveKeyframeInScript(script, animationId, fromPercentage, toPercentage)
|
|
|
1941
2040
|
if (!match) return src;
|
|
1942
2041
|
if (Math.abs(fromPercentage - toPercentage) < MOVE_NOOP_EPSILON_PCT) return src;
|
|
1943
2042
|
const dest = findKfPropByPct(kfNode, toPercentage);
|
|
1944
|
-
|
|
2043
|
+
if (dest && dest.prop !== match.prop) return script;
|
|
1945
2044
|
const entries = [];
|
|
1946
2045
|
for (const prop of percentagePropsOf(kfNode)) {
|
|
1947
2046
|
if (prop === match.prop) continue;
|
|
1948
|
-
if (collision && prop === collision.prop) continue;
|
|
1949
2047
|
const pct = percentageFromKey(propKeyName2(prop) ?? "");
|
|
1950
2048
|
if (Number.isNaN(pct)) continue;
|
|
1951
2049
|
entries.push({ pct, record: valueNodeToRecord(prop.value, src) });
|
|
@@ -2085,7 +2183,7 @@ function convertToKeyframesFromScript(script, animationId, resolvedFromValues, s
|
|
|
2085
2183
|
return ms.toString();
|
|
2086
2184
|
}
|
|
2087
2185
|
function buildKeyframeObjectCode(keyframes, easeEach) {
|
|
2088
|
-
const entries = keyframes.map((kf) => {
|
|
2186
|
+
const entries = mergePercentageKeyframes(keyframes).map((kf) => {
|
|
2089
2187
|
const props = Object.entries(kf.properties).map(([k, v]) => `${safeKey(k)}: ${valueToCode(v)}`);
|
|
2090
2188
|
if (kf.ease) props.push(`ease: ${JSON.stringify(kf.ease)}`);
|
|
2091
2189
|
if (kf.auto) props.push(`_auto: 1`);
|