@hyperframes/parsers 0.7.17 → 0.7.19
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/gsapParser.d.ts +33 -1
- package/dist/gsapParser.js +82 -3
- package/dist/gsapParser.js.map +1 -1
- package/dist/gsapParserExports.js.map +1 -1
- package/dist/gsapWriterAcorn.d.ts +41 -1
- package/dist/gsapWriterAcorn.js +83 -9
- package/dist/gsapWriterAcorn.js.map +1 -1
- package/dist/index.js +11 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -24,9 +24,49 @@ declare function addAnimationToScript(script: string, animation: Omit<GsapAnimat
|
|
|
24
24
|
id: string;
|
|
25
25
|
};
|
|
26
26
|
declare function removeAnimationFromScript(script: string, animationId: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Enforce "exactly one position write per element". Position commits (drag, add
|
|
29
|
+
* keyframe, static hold) must never leave the same selector with two conflicting
|
|
30
|
+
* position representations (e.g. a degenerate `tl.to("#box",{duration:0,x,y})`
|
|
31
|
+
* AND a `gsap.set("#box",{x,y})`) — the later one silently overrides the earlier,
|
|
32
|
+
* so the element "can't move" / snaps / leaves residue on delete.
|
|
33
|
+
*
|
|
34
|
+
* Keeps `keepId` (the write the commit just edited); falls back to the LAST
|
|
35
|
+
* position write in source order (the runtime-effective one) if `keepId` is stale.
|
|
36
|
+
* Removes every OTHER pure-position write (`propertyGroup === "position"`, which
|
|
37
|
+
* covers tl.to/from/fromTo flat-or-keyframed, tl.set, and standalone gsap.set,
|
|
38
|
+
* including degenerate duration:0 tweens). Non-position writes for the same
|
|
39
|
+
* selector (rotation / opacity / size / mixed) are left untouched.
|
|
40
|
+
*/
|
|
41
|
+
declare function dedupePositionWritesInScript(script: string, selector: string, keepId?: string): string;
|
|
27
42
|
declare function updateKeyframeInScript(script: string, animationId: string, percentage: number, properties: Record<string, number | string>, ease?: string): string;
|
|
28
43
|
declare function addKeyframeToScript(script: string, animationId: string, percentage: number, properties: Record<string, number | string>, ease?: string, backfillDefaults?: Record<string, number | string>): string;
|
|
29
44
|
declare function removeKeyframeFromScript(script: string, animationId: string, percentage: number): string;
|
|
45
|
+
/**
|
|
46
|
+
* Retime a keyframe: move the keyframe at `fromPercentage` to `toPercentage`,
|
|
47
|
+
* PRESERVING its properties and per-keyframe ease (the Studio "Move to Playhead"
|
|
48
|
+
* gesture). Re-sorts keyframes by percentage. If a keyframe already exists at
|
|
49
|
+
* `toPercentage`, it is overwritten by the moved one (no duplicate). No-op when
|
|
50
|
+
* the animation/keyframe isn't found, the tween has no object-form keyframes, or
|
|
51
|
+
* the move resolves onto the same keyframe.
|
|
52
|
+
*/
|
|
53
|
+
declare function moveKeyframeInScript(script: string, animationId: string, fromPercentage: number, toPercentage: number): string;
|
|
54
|
+
/**
|
|
55
|
+
* Resize a keyframed tween's window (boundary drag-to-retime): set the tween's
|
|
56
|
+
* `position` (trailing position arg) + `duration`, and RE-KEY each existing
|
|
57
|
+
* keyframe to its new percentage via `pctRemap` (each `{ from, to }` matches an
|
|
58
|
+
* existing keyframe by its current tween-% and re-keys it to `to`).
|
|
59
|
+
*
|
|
60
|
+
* Unlike replace-with-keyframes (which rebuilds the keyframes object from a plain
|
|
61
|
+
* array and loses author intent), this re-keys the percentage KEY in place and
|
|
62
|
+
* leaves every value node, each keyframe's `_auto` + per-keyframe `ease`, the
|
|
63
|
+
* keyframes-object `easeEach`, and the OUTER tween `ease` byte-for-byte verbatim.
|
|
64
|
+
* No-op when the animation/keyframes can't be located.
|
|
65
|
+
*/
|
|
66
|
+
declare function resizeKeyframedTweenInScript(script: string, animationId: string, newPosition: number, newDuration: number, pctRemap: ReadonlyArray<{
|
|
67
|
+
from: number;
|
|
68
|
+
to: number;
|
|
69
|
+
}>): string;
|
|
30
70
|
declare function removePropertyFromAnimation(script: string, animationId: string, property: string, from?: boolean): string;
|
|
31
71
|
/**
|
|
32
72
|
* Remove all keyframes from a tween, collapsing to a flat tween with one
|
|
@@ -91,4 +131,4 @@ type UnrollElement = {
|
|
|
91
131
|
*/
|
|
92
132
|
declare function unrollDynamicAnimations(script: string, animationId: string, elements: UnrollElement[]): string;
|
|
93
133
|
|
|
94
|
-
export { type UnrollElement, addAnimationToScript, addAnimationWithKeyframesToScript, addKeyframeToScript, addLabelToScript, convertToKeyframesFromScript, materializeKeyframesFromScript, removeAllKeyframesFromScript, removeAnimationFromScript, removeArcPathFromScript, removeKeyframeFromScript, removeLabelFromScript, removePropertyFromAnimation, scalePositionsInScript, setArcPathInScript, shiftPositionsInScript, splitAnimationsInScript, splitIntoPropertyGroupsFromScript, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript };
|
|
134
|
+
export { type UnrollElement, addAnimationToScript, addAnimationWithKeyframesToScript, addKeyframeToScript, addLabelToScript, convertToKeyframesFromScript, dedupePositionWritesInScript, materializeKeyframesFromScript, moveKeyframeInScript, removeAllKeyframesFromScript, removeAnimationFromScript, removeArcPathFromScript, removeKeyframeFromScript, removeLabelFromScript, removePropertyFromAnimation, resizeKeyframedTweenInScript, scalePositionsInScript, setArcPathInScript, shiftPositionsInScript, splitAnimationsInScript, splitIntoPropertyGroupsFromScript, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript };
|
package/dist/gsapWriterAcorn.js
CHANGED
|
@@ -1223,19 +1223,37 @@ function addAnimationToScript(script, animation) {
|
|
|
1223
1223
|
const newId = reParsed?.located[reParsed.located.length - 1]?.id ?? "";
|
|
1224
1224
|
return { script: result, id: newId };
|
|
1225
1225
|
}
|
|
1226
|
+
function removeCallFromMagicString(ms, call, script) {
|
|
1227
|
+
const N = call.node;
|
|
1228
|
+
const exprStmt = findEnclosingExpressionStatement(call.ancestors);
|
|
1229
|
+
if (N.callee?.object?.type !== "CallExpression" && exprStmt?.expression === N) {
|
|
1230
|
+
const end = exprStmt.end < script.length && script[exprStmt.end] === "\n" ? exprStmt.end + 1 : exprStmt.end;
|
|
1231
|
+
ms.remove(exprStmt.start, end);
|
|
1232
|
+
} else {
|
|
1233
|
+
ms.remove(N.callee.object.end, N.end);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1226
1236
|
function removeAnimationFromScript(script, animationId) {
|
|
1227
1237
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
1228
1238
|
if (!parsed) return script;
|
|
1229
1239
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
1230
1240
|
if (!target) return script;
|
|
1231
1241
|
const ms = new MagicString(script);
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1242
|
+
removeCallFromMagicString(ms, target.call, script);
|
|
1243
|
+
return ms.toString();
|
|
1244
|
+
}
|
|
1245
|
+
function dedupePositionWritesInScript(script, selector, keepId) {
|
|
1246
|
+
const parsed = parseGsapScriptAcornForWrite(script);
|
|
1247
|
+
if (!parsed) return script;
|
|
1248
|
+
const posWrites = parsed.located.filter(
|
|
1249
|
+
(l) => l.animation.targetSelector === selector && l.animation.propertyGroup === "position"
|
|
1250
|
+
);
|
|
1251
|
+
if (posWrites.length <= 1) return script;
|
|
1252
|
+
const keeper = posWrites.find((l) => l.id === keepId) ?? posWrites[posWrites.length - 1];
|
|
1253
|
+
const ms = new MagicString(script);
|
|
1254
|
+
for (const l of posWrites) {
|
|
1255
|
+
if (l === keeper) continue;
|
|
1256
|
+
removeCallFromMagicString(ms, l.call, script);
|
|
1239
1257
|
}
|
|
1240
1258
|
return ms.toString();
|
|
1241
1259
|
}
|
|
@@ -1322,6 +1340,7 @@ function convertFlatTweenToKeyframes(script, target) {
|
|
|
1322
1340
|
}
|
|
1323
1341
|
var PERCENTAGE_KEY_RE2 = /^(\d+(?:\.\d+)?)%$/;
|
|
1324
1342
|
var PCT_TOLERANCE = 2;
|
|
1343
|
+
var MOVE_NOOP_EPSILON_PCT = 0.05;
|
|
1325
1344
|
function percentageFromKey(key) {
|
|
1326
1345
|
const m = PERCENTAGE_KEY_RE2.exec(key);
|
|
1327
1346
|
return m ? Number.parseFloat(m[1] ?? "0") : Number.NaN;
|
|
@@ -1631,6 +1650,50 @@ function removeKeyframeFromScript(script, animationId, percentage) {
|
|
|
1631
1650
|
removeProp(ms, match.prop, allProps);
|
|
1632
1651
|
return ms.toString();
|
|
1633
1652
|
}
|
|
1653
|
+
function moveKeyframeInScript(script, animationId, fromPercentage, toPercentage) {
|
|
1654
|
+
const located = locateWithKeyframes(script, animationId);
|
|
1655
|
+
if (!located) return script;
|
|
1656
|
+
const { kfNode } = located;
|
|
1657
|
+
const match = findKfPropByPct(kfNode, fromPercentage);
|
|
1658
|
+
if (!match) return script;
|
|
1659
|
+
if (Math.abs(fromPercentage - toPercentage) < MOVE_NOOP_EPSILON_PCT) return script;
|
|
1660
|
+
const dest = findKfPropByPct(kfNode, toPercentage);
|
|
1661
|
+
const collision = dest && dest.prop !== match.prop ? dest : null;
|
|
1662
|
+
const entries = [];
|
|
1663
|
+
for (const prop of percentagePropsOf(kfNode)) {
|
|
1664
|
+
if (prop === match.prop) continue;
|
|
1665
|
+
if (collision && prop === collision.prop) continue;
|
|
1666
|
+
const pct = percentageFromKey(propKeyName2(prop) ?? "");
|
|
1667
|
+
if (Number.isNaN(pct)) continue;
|
|
1668
|
+
entries.push({ pct, record: valueNodeToRecord(prop.value, script) });
|
|
1669
|
+
}
|
|
1670
|
+
entries.push({ pct: toPercentage, record: valueNodeToRecord(match.prop.value, script) });
|
|
1671
|
+
entries.sort((a, b) => a.pct - b.pct);
|
|
1672
|
+
const body = entries.map((e) => `${JSON.stringify(`${e.pct}%`)}: ${recordToCode(e.record)}`).join(", ");
|
|
1673
|
+
const ms = new MagicString(script);
|
|
1674
|
+
ms.overwrite(kfNode.start, kfNode.end, `{ ${body} }`);
|
|
1675
|
+
return ms.toString();
|
|
1676
|
+
}
|
|
1677
|
+
function resizeKeyframedTweenInScript(script, animationId, newPosition, newDuration, pctRemap) {
|
|
1678
|
+
const located = locateWithKeyframes(script, animationId);
|
|
1679
|
+
if (!located) return script;
|
|
1680
|
+
const { target, kfNode } = located;
|
|
1681
|
+
const edits = [];
|
|
1682
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1683
|
+
for (const { from, to } of pctRemap) {
|
|
1684
|
+
const match = findKfPropByPct(kfNode, from);
|
|
1685
|
+
if (!match || seen.has(match.prop.key)) continue;
|
|
1686
|
+
seen.add(match.prop.key);
|
|
1687
|
+
edits.push({ keyNode: match.prop.key, to });
|
|
1688
|
+
}
|
|
1689
|
+
const ms = new MagicString(script);
|
|
1690
|
+
for (const { keyNode, to } of edits) {
|
|
1691
|
+
ms.overwrite(keyNode.start, keyNode.end, JSON.stringify(`${to}%`));
|
|
1692
|
+
}
|
|
1693
|
+
overwritePosition(ms, target.call, newPosition);
|
|
1694
|
+
upsertProp(ms, target.call.varsArg, "duration", newDuration);
|
|
1695
|
+
return ms.toString();
|
|
1696
|
+
}
|
|
1634
1697
|
function removePropertyFromAnimation(script, animationId, property, from = false) {
|
|
1635
1698
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
1636
1699
|
if (!parsed) return script;
|
|
@@ -1662,6 +1725,14 @@ function removeAllKeyframesFromScript(script, animationId) {
|
|
|
1662
1725
|
target.call,
|
|
1663
1726
|
buildVarsObjectCode(buildCollapsedFlatVars(target.animation, collapse))
|
|
1664
1727
|
);
|
|
1728
|
+
if (target.animation.propertyGroup === "position") {
|
|
1729
|
+
for (const l of parsed.located) {
|
|
1730
|
+
if (l === target) continue;
|
|
1731
|
+
if (l.animation.targetSelector === target.animation.targetSelector && l.animation.propertyGroup === "position") {
|
|
1732
|
+
removeCallFromMagicString(ms, l.call, script);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1665
1736
|
return ms.toString();
|
|
1666
1737
|
}
|
|
1667
1738
|
function buildCollapsedFlatVars(animation, collapse) {
|
|
@@ -1669,11 +1740,11 @@ function buildCollapsedFlatVars(animation, collapse) {
|
|
|
1669
1740
|
for (const [k, v] of Object.entries(collapse.properties)) {
|
|
1670
1741
|
if (k !== "ease") flat[k] = v;
|
|
1671
1742
|
}
|
|
1672
|
-
if (animation.duration !== void 0) flat.duration = animation.duration;
|
|
1673
|
-
if (animation.ease) flat.ease = animation.ease;
|
|
1674
1743
|
for (const [k, v] of Object.entries(animation.extras ?? {})) {
|
|
1675
1744
|
if (typeof v === "number" || typeof v === "string") flat[k] = v;
|
|
1676
1745
|
}
|
|
1746
|
+
flat.duration = 0;
|
|
1747
|
+
flat.immediateRender = true;
|
|
1677
1748
|
return flat;
|
|
1678
1749
|
}
|
|
1679
1750
|
function buildKeyframesVarsCode(animation, fromProps, toProps, varsNode, source, setDuration) {
|
|
@@ -2393,13 +2464,16 @@ export {
|
|
|
2393
2464
|
addKeyframeToScript,
|
|
2394
2465
|
addLabelToScript,
|
|
2395
2466
|
convertToKeyframesFromScript,
|
|
2467
|
+
dedupePositionWritesInScript,
|
|
2396
2468
|
materializeKeyframesFromScript,
|
|
2469
|
+
moveKeyframeInScript,
|
|
2397
2470
|
removeAllKeyframesFromScript,
|
|
2398
2471
|
removeAnimationFromScript,
|
|
2399
2472
|
removeArcPathFromScript,
|
|
2400
2473
|
removeKeyframeFromScript,
|
|
2401
2474
|
removeLabelFromScript,
|
|
2402
2475
|
removePropertyFromAnimation,
|
|
2476
|
+
resizeKeyframedTweenInScript,
|
|
2403
2477
|
scalePositionsInScript,
|
|
2404
2478
|
setArcPathInScript,
|
|
2405
2479
|
shiftPositionsInScript,
|