@hyperframes/parsers 0.8.133 → 0.8.135
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/gsapConstants.d.ts +1 -1
- package/dist/gsapConstants.js +29 -8
- package/dist/gsapConstants.js.map +1 -1
- package/dist/gsapParser.d.ts +3 -15
- package/dist/gsapParser.js +61 -23
- package/dist/gsapParser.js.map +1 -1
- package/dist/gsapParserAcorn.d.ts +9 -3
- package/dist/gsapParserAcorn.js +35 -9
- package/dist/gsapParserAcorn.js.map +1 -1
- package/dist/gsapParserExports.d.ts +1 -1
- package/dist/gsapParserExports.js +0 -3
- package/dist/gsapParserExports.js.map +1 -1
- package/dist/{gsapSerialize-CfSXM_Ez.d.ts → gsapSerialize-WJrRO8uT.d.ts} +10 -4
- package/dist/gsapWriterAcorn.d.ts +6 -3
- package/dist/gsapWriterAcorn.js +113 -18
- package/dist/gsapWriterAcorn.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/gsapConstants.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { B as BUILTIN_VAR_KEYS, D as DROPPED_VAR_KEYS, E as EXTRAS_KEYS, u as GSAP_DEFAULT_DURATION,
|
|
1
|
+
export { B as BUILTIN_VAR_KEYS, D as DROPPED_VAR_KEYS, E as EXTRAS_KEYS, u as GSAP_DEFAULT_DURATION, H as HoldScope, f as PROPERTY_GROUPS, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, x as holdScope, y as isTweenConfigKey, z as isXYPositionWrite, C as keyframeHoldForAnimation } from './gsapSerialize-WJrRO8uT.js';
|
|
2
2
|
import './types-Ejqndkej.js';
|
package/dist/gsapConstants.js
CHANGED
|
@@ -94,23 +94,43 @@ function knownStart(animation) {
|
|
|
94
94
|
if (animation.resolvedStart !== void 0) return animation.resolvedStart;
|
|
95
95
|
return typeof animation.position === "number" ? animation.position : void 0;
|
|
96
96
|
}
|
|
97
|
-
|
|
97
|
+
var tweenSignature = (a) => JSON.stringify([a.targetSelector, a.method, a.position, a.duration, a.properties, a.keyframes]);
|
|
98
|
+
function holdScope(before, previous) {
|
|
99
|
+
const kept = new Set(previous?.map(tweenSignature));
|
|
100
|
+
const held = /* @__PURE__ */ new Map();
|
|
101
|
+
for (const a of before.filter((b) => b.method === "set" && b.properties?.data === "hf-hold")) {
|
|
102
|
+
const props = held.get(a.targetSelector) ?? /* @__PURE__ */ new Map();
|
|
103
|
+
for (const [property, value] of Object.entries(a.properties)) props.set(property, value);
|
|
104
|
+
held.set(a.targetSelector, props);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
touched: (a) => previous !== null && !kept.has(tweenSignature(a)),
|
|
108
|
+
held: (selector) => held.get(selector) ?? /* @__PURE__ */ new Map()
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function keyframeHoldForAnimation(animation, animations, scope) {
|
|
98
112
|
if (!animation.keyframes) return null;
|
|
99
|
-
const start = knownStart(animation)
|
|
100
|
-
|
|
113
|
+
const start = knownStart(animation);
|
|
114
|
+
const lone = animation.keyframes.keyframes.length === 1;
|
|
115
|
+
if (start === void 0 || !(start > 1e-3) && !lone) return null;
|
|
101
116
|
const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
|
|
102
117
|
if (!atStart) return null;
|
|
103
118
|
const earlier = animations.filter((other) => {
|
|
104
119
|
const otherStart = knownStart(other);
|
|
105
120
|
return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
|
|
106
121
|
});
|
|
107
|
-
const
|
|
122
|
+
const touched = scope.touched(animation);
|
|
123
|
+
const pinned = scope.held(animation.targetSelector);
|
|
124
|
+
const kept = (property, value) => touched ? pinned.has(property) : pinned.get(property) === value;
|
|
125
|
+
const pins = (group, property, value) => group === "position" && start > 1e-3 || (group === "position" || group === "size") && (lone && touched || kept(property, value));
|
|
126
|
+
const hold = {};
|
|
108
127
|
for (const [property, value] of Object.entries(atStart.properties)) {
|
|
109
|
-
if (classifyPropertyGroup(property)
|
|
128
|
+
if (!pins(classifyPropertyGroup(property), property, value) || typeof value !== "number")
|
|
129
|
+
continue;
|
|
110
130
|
if (earlier.some((other) => writesProperty(other, property))) continue;
|
|
111
|
-
|
|
131
|
+
hold[property] = value;
|
|
112
132
|
}
|
|
113
|
-
return Object.keys(
|
|
133
|
+
return Object.keys(hold).length > 0 ? hold : null;
|
|
114
134
|
}
|
|
115
135
|
var SUPPORTED_EASES = [
|
|
116
136
|
"none",
|
|
@@ -159,8 +179,9 @@ export {
|
|
|
159
179
|
SUPPORTED_PROPS,
|
|
160
180
|
classifyPropertyGroup,
|
|
161
181
|
classifyTweenPropertyGroup,
|
|
182
|
+
holdScope,
|
|
162
183
|
isTweenConfigKey,
|
|
163
184
|
isXYPositionWrite,
|
|
164
|
-
|
|
185
|
+
keyframeHoldForAnimation
|
|
165
186
|
};
|
|
166
187
|
//# sourceMappingURL=gsapConstants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/gsapConstants.ts"],"sourcesContent":["/**\n * GSAP property and ease constants.\n *\n * Extracted into a standalone module so browser code can import them\n * without pulling in gsapParser (which depends on recast / @babel/parser).\n */\n\nimport type { GsapAnimation } from \"./gsapSerialize.js\";\n\nexport const GSAP_DEFAULT_DURATION = 0.5;\n\nexport const SUPPORTED_PROPS = [\n // 2D Transforms\n \"x\",\n \"y\",\n \"scale\",\n \"scaleX\",\n \"scaleY\",\n \"rotation\",\n \"skewX\",\n \"skewY\",\n // 3D Transforms\n \"z\",\n \"rotationX\",\n \"rotationY\",\n \"rotationZ\",\n \"perspective\",\n \"transformPerspective\",\n \"transformOrigin\",\n // Visibility\n \"opacity\",\n \"visibility\",\n \"autoAlpha\",\n // Dimensions\n \"width\",\n \"height\",\n // Colors\n \"color\",\n \"backgroundColor\",\n \"borderColor\",\n // Box model\n \"borderRadius\",\n // Typography\n \"fontSize\",\n \"letterSpacing\",\n // Filter & Clipping\n \"filter\",\n \"clipPath\",\n // DOM content (number counters, text roll-ups)\n \"innerText\",\n];\n\n/** Keys stored on dedicated GsapAnimation fields (not in properties/extras). */\nexport const BUILTIN_VAR_KEYS: ReadonlySet<string> = new Set([\"duration\", \"ease\", \"delay\"]);\nexport const DROPPED_VAR_KEYS: ReadonlySet<string> = new Set([\n \"onComplete\",\n \"onStart\",\n \"onUpdate\",\n \"onRepeat\",\n]);\n/** Keys that go in `extras`: non-editable GSAP config that must survive round-trips. */\nexport const EXTRAS_KEYS: ReadonlySet<string> = new Set([\n \"stagger\",\n \"yoyo\",\n \"repeat\",\n \"repeatDelay\",\n \"snap\",\n \"overwrite\",\n \"immediateRender\",\n]);\n\nexport function isTweenConfigKey(key: string): boolean {\n return BUILTIN_VAR_KEYS.has(key) || DROPPED_VAR_KEYS.has(key) || EXTRAS_KEYS.has(key);\n}\n\n// ── Property Groups ─────────────────────────────────────────────────────────\n// Each group maps to an independent GSAP tween so editing one property\n// (e.g. drag → x/y) never contaminates another (e.g. scale, rotation).\n\nexport type PropertyGroupName = \"position\" | \"scale\" | \"size\" | \"rotation\" | \"visual\" | \"other\";\n\nexport const PROPERTY_GROUPS: Record<PropertyGroupName, ReadonlySet<string>> = {\n position: new Set([\"x\", \"y\", \"xPercent\", \"yPercent\"]),\n scale: new Set([\"scale\", \"scaleX\", \"scaleY\"]),\n size: new Set([\"width\", \"height\"]),\n rotation: new Set([\"rotation\", \"skewX\", \"skewY\"]),\n visual: new Set([\"opacity\", \"autoAlpha\"]),\n other: new Set<string>(),\n};\n\nconst PROP_TO_GROUP = new Map<string, PropertyGroupName>();\nfor (const [group, props] of Object.entries(PROPERTY_GROUPS) as [\n PropertyGroupName,\n ReadonlySet<string>,\n][]) {\n for (const p of props) PROP_TO_GROUP.set(p, group);\n}\n\ntype PositionWrite = Pick<\n GsapAnimation,\n \"propertyGroup\" | \"properties\" | \"fromProperties\" | \"keyframes\"\n>;\n\nfunction writesProperty(animation: PositionWrite, property: string): boolean {\n return (\n property in animation.properties ||\n (!!animation.fromProperties && property in animation.fromProperties) ||\n !!animation.keyframes?.keyframes.some((k) => property in k.properties)\n );\n}\n\n/** A position write that sets x or y. An xPercent/yPercent centring set never duplicates one. */\nexport function isXYPositionWrite(a: PositionWrite): boolean {\n return a.propertyGroup === \"position\" && (writesProperty(a, \"x\") || writesProperty(a, \"y\"));\n}\n\nexport function classifyPropertyGroup(prop: string): PropertyGroupName {\n return PROP_TO_GROUP.get(prop) ?? \"other\";\n}\n\nexport function classifyTweenPropertyGroup(\n properties: Record<string, unknown>,\n): PropertyGroupName | undefined {\n const groups = new Set<PropertyGroupName>();\n for (const key of Object.keys(properties)) {\n // transformOrigin is a modifier; `_auto` is Studio's internal endpoint marker;\n // `data` is GSAP-reserved (carries the Studio hold-set tag). None is an animated\n // property, so none should affect the group.\n if (key === \"transformOrigin\" || key === \"_auto\" || key === \"data\") continue;\n const g = classifyPropertyGroup(key);\n groups.add(g);\n }\n if (groups.size === 1) return groups.values().next().value;\n return undefined;\n}\n\nfunction knownStart(animation: GsapAnimation): number | undefined {\n if (animation.resolvedStart !== undefined) return animation.resolvedStart;\n return typeof animation.position === \"number\" ? animation.position : undefined;\n}\n\n/**\n * What a Studio hold pins from t=0 before a later keyframed tween: its 0% keyframe's position props,\n * minus those an earlier timeline tween on the target writes (a global `gsap.set` is a base value).\n */\nexport function positionHoldForAnimation(\n animation: GsapAnimation,\n animations: readonly GsapAnimation[],\n): Record<string, number> | null {\n if (!animation.keyframes) return null;\n const start = knownStart(animation) ?? 0;\n if (!(start > 0.001)) return null;\n const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);\n if (!atStart) return null;\n // A tween whose start the parser could not resolve (a label, say) is not known to come first.\n const earlier = animations.filter((other) => {\n const otherStart = knownStart(other);\n return (\n other !== animation &&\n !other.global &&\n other.targetSelector === animation.targetSelector &&\n otherStart !== undefined &&\n otherStart < start - 0.001\n );\n });\n const position: Record<string, number> = {};\n for (const [property, value] of Object.entries(atStart.properties)) {\n if (classifyPropertyGroup(property) !== \"position\" || typeof value !== \"number\") continue;\n if (earlier.some((other) => writesProperty(other, property))) continue;\n position[property] = value;\n }\n return Object.keys(position).length > 0 ? position : null;\n}\n\nexport const SUPPORTED_EASES = [\n \"none\",\n \"power1.in\",\n \"power1.out\",\n \"power1.inOut\",\n \"power2.in\",\n \"power2.out\",\n \"power2.inOut\",\n \"power3.in\",\n \"power3.out\",\n \"power3.inOut\",\n \"power4.in\",\n \"power4.out\",\n \"power4.inOut\",\n \"back.in\",\n \"back.out\",\n \"back.inOut\",\n \"elastic.in\",\n \"elastic.out\",\n \"elastic.inOut\",\n \"bounce.in\",\n \"bounce.out\",\n \"bounce.inOut\",\n \"circ.inOut\",\n \"expo.in\",\n \"expo.out\",\n \"expo.inOut\",\n \"elastic.out(1,0.3)\",\n \"elastic.inOut(1,0.3)\",\n \"spring-gentle\",\n \"spring-bouncy\",\n \"spring-stiff\",\n \"spring-wobbly\",\n \"spring-heavy\",\n \"hold\",\n \"steps(1)\",\n];\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/gsapConstants.ts"],"sourcesContent":["/**\n * GSAP property and ease constants.\n *\n * Extracted into a standalone module so browser code can import them\n * without pulling in gsapParser (which depends on recast / @babel/parser).\n */\n\nimport type { GsapAnimation } from \"./gsapSerialize.js\";\n\nexport const GSAP_DEFAULT_DURATION = 0.5;\n\nexport const SUPPORTED_PROPS = [\n // 2D Transforms\n \"x\",\n \"y\",\n \"scale\",\n \"scaleX\",\n \"scaleY\",\n \"rotation\",\n \"skewX\",\n \"skewY\",\n // 3D Transforms\n \"z\",\n \"rotationX\",\n \"rotationY\",\n \"rotationZ\",\n \"perspective\",\n \"transformPerspective\",\n \"transformOrigin\",\n // Visibility\n \"opacity\",\n \"visibility\",\n \"autoAlpha\",\n // Dimensions\n \"width\",\n \"height\",\n // Colors\n \"color\",\n \"backgroundColor\",\n \"borderColor\",\n // Box model\n \"borderRadius\",\n // Typography\n \"fontSize\",\n \"letterSpacing\",\n // Filter & Clipping\n \"filter\",\n \"clipPath\",\n // DOM content (number counters, text roll-ups)\n \"innerText\",\n];\n\n/** Keys stored on dedicated GsapAnimation fields (not in properties/extras). */\nexport const BUILTIN_VAR_KEYS: ReadonlySet<string> = new Set([\"duration\", \"ease\", \"delay\"]);\nexport const DROPPED_VAR_KEYS: ReadonlySet<string> = new Set([\n \"onComplete\",\n \"onStart\",\n \"onUpdate\",\n \"onRepeat\",\n]);\n/** Keys that go in `extras`: non-editable GSAP config that must survive round-trips. */\nexport const EXTRAS_KEYS: ReadonlySet<string> = new Set([\n \"stagger\",\n \"yoyo\",\n \"repeat\",\n \"repeatDelay\",\n \"snap\",\n \"overwrite\",\n \"immediateRender\",\n]);\n\nexport function isTweenConfigKey(key: string): boolean {\n return BUILTIN_VAR_KEYS.has(key) || DROPPED_VAR_KEYS.has(key) || EXTRAS_KEYS.has(key);\n}\n\n// ── Property Groups ─────────────────────────────────────────────────────────\n// Each group maps to an independent GSAP tween so editing one property\n// (e.g. drag → x/y) never contaminates another (e.g. scale, rotation).\n\nexport type PropertyGroupName = \"position\" | \"scale\" | \"size\" | \"rotation\" | \"visual\" | \"other\";\n\nexport const PROPERTY_GROUPS: Record<PropertyGroupName, ReadonlySet<string>> = {\n position: new Set([\"x\", \"y\", \"xPercent\", \"yPercent\"]),\n scale: new Set([\"scale\", \"scaleX\", \"scaleY\"]),\n size: new Set([\"width\", \"height\"]),\n rotation: new Set([\"rotation\", \"skewX\", \"skewY\"]),\n visual: new Set([\"opacity\", \"autoAlpha\"]),\n other: new Set<string>(),\n};\n\nconst PROP_TO_GROUP = new Map<string, PropertyGroupName>();\nfor (const [group, props] of Object.entries(PROPERTY_GROUPS) as [\n PropertyGroupName,\n ReadonlySet<string>,\n][]) {\n for (const p of props) PROP_TO_GROUP.set(p, group);\n}\n\ntype PositionWrite = Pick<\n GsapAnimation,\n \"propertyGroup\" | \"properties\" | \"fromProperties\" | \"keyframes\"\n>;\n\nfunction writesProperty(animation: PositionWrite, property: string): boolean {\n return (\n property in animation.properties ||\n (!!animation.fromProperties && property in animation.fromProperties) ||\n !!animation.keyframes?.keyframes.some((k) => property in k.properties)\n );\n}\n\n/** A position write that sets x or y. An xPercent/yPercent centring set never duplicates one. */\nexport function isXYPositionWrite(a: PositionWrite): boolean {\n return a.propertyGroup === \"position\" && (writesProperty(a, \"x\") || writesProperty(a, \"y\"));\n}\n\nexport function classifyPropertyGroup(prop: string): PropertyGroupName {\n return PROP_TO_GROUP.get(prop) ?? \"other\";\n}\n\nexport function classifyTweenPropertyGroup(\n properties: Record<string, unknown>,\n): PropertyGroupName | undefined {\n const groups = new Set<PropertyGroupName>();\n for (const key of Object.keys(properties)) {\n // transformOrigin is a modifier; `_auto` is Studio's internal endpoint marker;\n // `data` is GSAP-reserved (carries the Studio hold-set tag). None is an animated\n // property, so none should affect the group.\n if (key === \"transformOrigin\" || key === \"_auto\" || key === \"data\") continue;\n const g = classifyPropertyGroup(key);\n groups.add(g);\n }\n if (groups.size === 1) return groups.values().next().value;\n return undefined;\n}\n\nfunction knownStart(animation: GsapAnimation): number | undefined {\n if (animation.resolvedStart !== undefined) return animation.resolvedStart;\n return typeof animation.position === \"number\" ? animation.position : undefined;\n}\n\nexport interface HoldScope {\n touched: (animation: GsapAnimation) => boolean;\n held: (selector: string) => ReadonlyMap<string, unknown>;\n}\n\nconst tweenSignature = (a: GsapAnimation) =>\n JSON.stringify([a.targetSelector, a.method, a.position, a.duration, a.properties, a.keyframes]);\n\n/** The tweens an edit touched (not in `previous`; none without it), and what the script's holds already pin. */\nexport function holdScope(\n before: readonly GsapAnimation[],\n previous: readonly GsapAnimation[] | null,\n): HoldScope {\n const kept = new Set(previous?.map(tweenSignature));\n const held = new Map<string, Map<string, unknown>>();\n for (const a of before.filter((b) => b.method === \"set\" && b.properties?.data === \"hf-hold\")) {\n const props = held.get(a.targetSelector) ?? new Map<string, unknown>();\n for (const [property, value] of Object.entries(a.properties)) props.set(property, value);\n held.set(a.targetSelector, props);\n }\n return {\n touched: (a) => previous !== null && !kept.has(tweenSignature(a)),\n held: (selector) => held.get(selector) ?? new Map(),\n };\n}\n\n/**\n * What a Studio hold pins from t=0: a keyframed tween's 0% position props before a later start, and the position and\n * size of a lone key (GSAP renders none) only where this edit made it or a hold already pins it, minus earlier tweens.\n */\nexport function keyframeHoldForAnimation(\n animation: GsapAnimation,\n animations: readonly GsapAnimation[],\n scope: HoldScope,\n): Record<string, number> | null {\n if (!animation.keyframes) return null;\n const start = knownStart(animation);\n const lone = animation.keyframes.keyframes.length === 1;\n if (start === undefined || (!(start > 0.001) && !lone)) return null;\n const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);\n if (!atStart) return null;\n // A tween whose start the parser could not resolve (a label, say) is not known to come first.\n const earlier = animations.filter((other) => {\n const otherStart = knownStart(other);\n return (\n other !== animation &&\n !other.global &&\n other.targetSelector === animation.targetSelector &&\n otherStart !== undefined &&\n otherStart < start - 0.001\n );\n });\n const touched = scope.touched(animation);\n const pinned = scope.held(animation.targetSelector);\n // An untouched tween keeps only the hold it made: one with its own first value.\n const kept = (property: string, value: unknown) =>\n touched ? pinned.has(property) : pinned.get(property) === value;\n const pins = (group: PropertyGroupName, property: string, value: unknown) =>\n (group === \"position\" && start > 0.001) ||\n ((group === \"position\" || group === \"size\") && ((lone && touched) || kept(property, value)));\n const hold: Record<string, number> = {};\n for (const [property, value] of Object.entries(atStart.properties)) {\n if (!pins(classifyPropertyGroup(property), property, value) || typeof value !== \"number\")\n continue;\n if (earlier.some((other) => writesProperty(other, property))) continue;\n hold[property] = value;\n }\n return Object.keys(hold).length > 0 ? hold : null;\n}\n\nexport const SUPPORTED_EASES = [\n \"none\",\n \"power1.in\",\n \"power1.out\",\n \"power1.inOut\",\n \"power2.in\",\n \"power2.out\",\n \"power2.inOut\",\n \"power3.in\",\n \"power3.out\",\n \"power3.inOut\",\n \"power4.in\",\n \"power4.out\",\n \"power4.inOut\",\n \"back.in\",\n \"back.out\",\n \"back.inOut\",\n \"elastic.in\",\n \"elastic.out\",\n \"elastic.inOut\",\n \"bounce.in\",\n \"bounce.out\",\n \"bounce.inOut\",\n \"circ.inOut\",\n \"expo.in\",\n \"expo.out\",\n \"expo.inOut\",\n \"elastic.out(1,0.3)\",\n \"elastic.inOut(1,0.3)\",\n \"spring-gentle\",\n \"spring-bouncy\",\n \"spring-stiff\",\n \"spring-wobbly\",\n \"spring-heavy\",\n \"hold\",\n \"steps(1)\",\n];\n"],"mappings":";AASO,IAAM,wBAAwB;AAE9B,IAAM,kBAAkB;AAAA;AAAA,EAE7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;AAGO,IAAM,mBAAwC,oBAAI,IAAI,CAAC,YAAY,QAAQ,OAAO,CAAC;AACnF,IAAM,mBAAwC,oBAAI,IAAI;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,cAAmC,oBAAI,IAAI;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,iBAAiB,KAAsB;AACrD,SAAO,iBAAiB,IAAI,GAAG,KAAK,iBAAiB,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG;AACtF;AAQO,IAAM,kBAAkE;AAAA,EAC7E,UAAU,oBAAI,IAAI,CAAC,KAAK,KAAK,YAAY,UAAU,CAAC;AAAA,EACpD,OAAO,oBAAI,IAAI,CAAC,SAAS,UAAU,QAAQ,CAAC;AAAA,EAC5C,MAAM,oBAAI,IAAI,CAAC,SAAS,QAAQ,CAAC;AAAA,EACjC,UAAU,oBAAI,IAAI,CAAC,YAAY,SAAS,OAAO,CAAC;AAAA,EAChD,QAAQ,oBAAI,IAAI,CAAC,WAAW,WAAW,CAAC;AAAA,EACxC,OAAO,oBAAI,IAAY;AACzB;AAEA,IAAM,gBAAgB,oBAAI,IAA+B;AACzD,WAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,eAAe,GAGtD;AACH,aAAW,KAAK,MAAO,eAAc,IAAI,GAAG,KAAK;AACnD;AAOA,SAAS,eAAe,WAA0B,UAA2B;AAC3E,SACE,YAAY,UAAU,cACrB,CAAC,CAAC,UAAU,kBAAkB,YAAY,UAAU,kBACrD,CAAC,CAAC,UAAU,WAAW,UAAU,KAAK,CAAC,MAAM,YAAY,EAAE,UAAU;AAEzE;AAGO,SAAS,kBAAkB,GAA2B;AAC3D,SAAO,EAAE,kBAAkB,eAAe,eAAe,GAAG,GAAG,KAAK,eAAe,GAAG,GAAG;AAC3F;AAEO,SAAS,sBAAsB,MAAiC;AACrE,SAAO,cAAc,IAAI,IAAI,KAAK;AACpC;AAEO,SAAS,2BACd,YAC+B;AAC/B,QAAM,SAAS,oBAAI,IAAuB;AAC1C,aAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AAIzC,QAAI,QAAQ,qBAAqB,QAAQ,WAAW,QAAQ,OAAQ;AACpE,UAAM,IAAI,sBAAsB,GAAG;AACnC,WAAO,IAAI,CAAC;AAAA,EACd;AACA,MAAI,OAAO,SAAS,EAAG,QAAO,OAAO,OAAO,EAAE,KAAK,EAAE;AACrD,SAAO;AACT;AAEA,SAAS,WAAW,WAA8C;AAChE,MAAI,UAAU,kBAAkB,OAAW,QAAO,UAAU;AAC5D,SAAO,OAAO,UAAU,aAAa,WAAW,UAAU,WAAW;AACvE;AAOA,IAAM,iBAAiB,CAAC,MACtB,KAAK,UAAU,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC;AAGzF,SAAS,UACd,QACA,UACW;AACX,QAAM,OAAO,IAAI,IAAI,UAAU,IAAI,cAAc,CAAC;AAClD,QAAM,OAAO,oBAAI,IAAkC;AACnD,aAAW,KAAK,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE,YAAY,SAAS,SAAS,GAAG;AAC5F,UAAM,QAAQ,KAAK,IAAI,EAAE,cAAc,KAAK,oBAAI,IAAqB;AACrE,eAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,EAAE,UAAU,EAAG,OAAM,IAAI,UAAU,KAAK;AACvF,SAAK,IAAI,EAAE,gBAAgB,KAAK;AAAA,EAClC;AACA,SAAO;AAAA,IACL,SAAS,CAAC,MAAM,aAAa,QAAQ,CAAC,KAAK,IAAI,eAAe,CAAC,CAAC;AAAA,IAChE,MAAM,CAAC,aAAa,KAAK,IAAI,QAAQ,KAAK,oBAAI,IAAI;AAAA,EACpD;AACF;AAMO,SAAS,yBACd,WACA,YACA,OAC+B;AAC/B,MAAI,CAAC,UAAU,UAAW,QAAO;AACjC,QAAM,QAAQ,WAAW,SAAS;AAClC,QAAM,OAAO,UAAU,UAAU,UAAU,WAAW;AACtD,MAAI,UAAU,UAAc,EAAE,QAAQ,SAAU,CAAC,KAAO,QAAO;AAC/D,QAAM,UAAU,UAAU,UAAU,UAAU,KAAK,CAAC,aAAa,SAAS,eAAe,CAAC;AAC1F,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,UAAU,WAAW,OAAO,CAAC,UAAU;AAC3C,UAAM,aAAa,WAAW,KAAK;AACnC,WACE,UAAU,aACV,CAAC,MAAM,UACP,MAAM,mBAAmB,UAAU,kBACnC,eAAe,UACf,aAAa,QAAQ;AAAA,EAEzB,CAAC;AACD,QAAM,UAAU,MAAM,QAAQ,SAAS;AACvC,QAAM,SAAS,MAAM,KAAK,UAAU,cAAc;AAElD,QAAM,OAAO,CAAC,UAAkB,UAC9B,UAAU,OAAO,IAAI,QAAQ,IAAI,OAAO,IAAI,QAAQ,MAAM;AAC5D,QAAM,OAAO,CAAC,OAA0B,UAAkB,UACvD,UAAU,cAAc,QAAQ,SAC/B,UAAU,cAAc,UAAU,YAAa,QAAQ,WAAY,KAAK,UAAU,KAAK;AAC3F,QAAM,OAA+B,CAAC;AACtC,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,QAAQ,UAAU,GAAG;AAClE,QAAI,CAAC,KAAK,sBAAsB,QAAQ,GAAG,UAAU,KAAK,KAAK,OAAO,UAAU;AAC9E;AACF,QAAI,QAAQ,KAAK,CAAC,UAAU,eAAe,OAAO,QAAQ,CAAC,EAAG;AAC9D,SAAK,QAAQ,IAAI;AAAA,EACnB;AACA,SAAO,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAC/C;AAEO,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
package/dist/gsapParser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { G as GsapAnimation, P as ParsedGsap, A as ArcPathConfig, a as ArcPathSegment } from './gsapSerialize-WJrRO8uT.js';
|
|
2
|
+
export { b as GsapKeyframeFormat, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, f as PROPERTY_GROUPS, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-WJrRO8uT.js';
|
|
3
3
|
export { SPRING_PRESETS, SpringPreset, generateSpringEaseData } from './springEase.js';
|
|
4
4
|
import './types-Ejqndkej.js';
|
|
5
5
|
|
|
@@ -36,19 +36,7 @@ declare function dedupePositionWritesInScript(script: string, selector: string,
|
|
|
36
36
|
/** True for a `tl.set(...)` this module emitted to hold a keyframe before its tween.
|
|
37
37
|
* The Studio filters these out so they never appear as user keyframes/diamonds. */
|
|
38
38
|
declare function isStudioHoldSet(anim: GsapAnimation): boolean;
|
|
39
|
-
|
|
40
|
-
* Keep a `tl.set(selector, {x,y}, 0)` "hold" in front of every position-keyframed
|
|
41
|
-
* tween that starts after t=0, so the element holds its first keyframe's position
|
|
42
|
-
* BEFORE the tween plays instead of snapping to its CSS base (the universal NLE
|
|
43
|
-
* "hold before first keyframe" behavior). The set is tagged with `data: "hf-hold"`
|
|
44
|
-
* so this pass owns it: every call wipes the prior holds and recomputes from the
|
|
45
|
-
* current keyframes, keeping them in sync as keyframes are added/moved/deleted.
|
|
46
|
-
*
|
|
47
|
-
* Idempotent. Only position props (x/y/xPercent/yPercent) are held — opacity/scale
|
|
48
|
-
* keep their authored pre-tween behavior. A tween already starting at 0 needs no
|
|
49
|
-
* hold (no gap before it).
|
|
50
|
-
*/
|
|
51
|
-
declare function syncPositionHoldsBeforeKeyframes(script: string): string;
|
|
39
|
+
declare function syncPositionHoldsBeforeKeyframes(script: string, previous?: string): string;
|
|
52
40
|
interface SplitAnimationsOptions {
|
|
53
41
|
originalId: string;
|
|
54
42
|
newId: string;
|
package/dist/gsapParser.js
CHANGED
|
@@ -98,23 +98,43 @@ function knownStart(animation) {
|
|
|
98
98
|
if (animation.resolvedStart !== void 0) return animation.resolvedStart;
|
|
99
99
|
return typeof animation.position === "number" ? animation.position : void 0;
|
|
100
100
|
}
|
|
101
|
-
|
|
101
|
+
var tweenSignature = (a) => JSON.stringify([a.targetSelector, a.method, a.position, a.duration, a.properties, a.keyframes]);
|
|
102
|
+
function holdScope(before, previous) {
|
|
103
|
+
const kept = new Set(previous?.map(tweenSignature));
|
|
104
|
+
const held = /* @__PURE__ */ new Map();
|
|
105
|
+
for (const a of before.filter((b) => b.method === "set" && b.properties?.data === "hf-hold")) {
|
|
106
|
+
const props = held.get(a.targetSelector) ?? /* @__PURE__ */ new Map();
|
|
107
|
+
for (const [property, value] of Object.entries(a.properties)) props.set(property, value);
|
|
108
|
+
held.set(a.targetSelector, props);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
touched: (a) => previous !== null && !kept.has(tweenSignature(a)),
|
|
112
|
+
held: (selector) => held.get(selector) ?? /* @__PURE__ */ new Map()
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function keyframeHoldForAnimation(animation, animations, scope) {
|
|
102
116
|
if (!animation.keyframes) return null;
|
|
103
|
-
const start = knownStart(animation)
|
|
104
|
-
|
|
117
|
+
const start = knownStart(animation);
|
|
118
|
+
const lone = animation.keyframes.keyframes.length === 1;
|
|
119
|
+
if (start === void 0 || !(start > 1e-3) && !lone) return null;
|
|
105
120
|
const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
|
|
106
121
|
if (!atStart) return null;
|
|
107
122
|
const earlier = animations.filter((other) => {
|
|
108
123
|
const otherStart = knownStart(other);
|
|
109
124
|
return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
|
|
110
125
|
});
|
|
111
|
-
const
|
|
126
|
+
const touched = scope.touched(animation);
|
|
127
|
+
const pinned = scope.held(animation.targetSelector);
|
|
128
|
+
const kept = (property, value) => touched ? pinned.has(property) : pinned.get(property) === value;
|
|
129
|
+
const pins = (group, property, value) => group === "position" && start > 1e-3 || (group === "position" || group === "size") && (lone && touched || kept(property, value));
|
|
130
|
+
const hold = {};
|
|
112
131
|
for (const [property, value] of Object.entries(atStart.properties)) {
|
|
113
|
-
if (classifyPropertyGroup(property)
|
|
132
|
+
if (!pins(classifyPropertyGroup(property), property, value) || typeof value !== "number")
|
|
133
|
+
continue;
|
|
114
134
|
if (earlier.some((other) => writesProperty(other, property))) continue;
|
|
115
|
-
|
|
135
|
+
hold[property] = value;
|
|
116
136
|
}
|
|
117
|
-
return Object.keys(
|
|
137
|
+
return Object.keys(hold).length > 0 ? hold : null;
|
|
118
138
|
}
|
|
119
139
|
var SUPPORTED_EASES = [
|
|
120
140
|
"none",
|
|
@@ -246,6 +266,10 @@ function serializeValue(value) {
|
|
|
246
266
|
if (typeof value === "string") return JSON.stringify(value);
|
|
247
267
|
return String(value);
|
|
248
268
|
}
|
|
269
|
+
function plainPercentKey(percentage) {
|
|
270
|
+
const text = Math.abs(percentage) < 1e-6 ? percentage.toFixed(20).replace(/\.?0+$/, "") : String(percentage);
|
|
271
|
+
return `${text}%`;
|
|
272
|
+
}
|
|
249
273
|
function safeJsKey(key) {
|
|
250
274
|
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
|
|
251
275
|
}
|
|
@@ -1210,9 +1234,6 @@ function tweenCallToAnimation(call, scope) {
|
|
|
1210
1234
|
properties[key] = val;
|
|
1211
1235
|
}
|
|
1212
1236
|
}
|
|
1213
|
-
if (keyframesData && typeof vars.easeEach === "string") {
|
|
1214
|
-
keyframesData.easeEach = vars.easeEach;
|
|
1215
|
-
}
|
|
1216
1237
|
if (motionPathResult) {
|
|
1217
1238
|
const { waypoints } = motionPathResult;
|
|
1218
1239
|
if (!keyframesData) {
|
|
@@ -1768,7 +1789,14 @@ var STUDIO_HOLD_MARKER = "hf-hold";
|
|
|
1768
1789
|
function isStudioHoldSet(anim) {
|
|
1769
1790
|
return anim.method === "set" && anim.properties?.data === STUDIO_HOLD_MARKER;
|
|
1770
1791
|
}
|
|
1771
|
-
function
|
|
1792
|
+
function animationsOf(script) {
|
|
1793
|
+
try {
|
|
1794
|
+
return parseGsapScript(script).animations;
|
|
1795
|
+
} catch {
|
|
1796
|
+
return null;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
function syncPositionHoldsBeforeKeyframes(script, previous) {
|
|
1772
1800
|
let parsed;
|
|
1773
1801
|
try {
|
|
1774
1802
|
parsed = parseGsapScript(script);
|
|
@@ -1784,8 +1812,12 @@ function syncPositionHoldsBeforeKeyframes(script) {
|
|
|
1784
1812
|
} catch {
|
|
1785
1813
|
return result;
|
|
1786
1814
|
}
|
|
1815
|
+
const scope = holdScope(
|
|
1816
|
+
parsed.animations,
|
|
1817
|
+
previous === void 0 ? null : animationsOf(previous)
|
|
1818
|
+
);
|
|
1787
1819
|
for (const anim of reparsed.animations) {
|
|
1788
|
-
const posProps =
|
|
1820
|
+
const posProps = keyframeHoldForAnimation(anim, reparsed.animations, scope);
|
|
1789
1821
|
if (!posProps) continue;
|
|
1790
1822
|
result = insertInheritedStateSet(result, anim.targetSelector, 0, {
|
|
1791
1823
|
...posProps,
|
|
@@ -1903,7 +1935,7 @@ function buildKeyframeObjectCode(keyframes, options) {
|
|
|
1903
1935
|
const props = keyframePropsToCode(kf);
|
|
1904
1936
|
if (kf.ease) props.push(`ease: ${JSON.stringify(kf.ease)}`);
|
|
1905
1937
|
if (kf.auto) props.push(`_auto: 1`);
|
|
1906
|
-
return `${JSON.stringify(
|
|
1938
|
+
return `${JSON.stringify(plainPercentKey(kf.percentage))}: { ${props.join(", ")} }`;
|
|
1907
1939
|
});
|
|
1908
1940
|
if (options?.easeEach) entries.push(`easeEach: ${JSON.stringify(options.easeEach)}`);
|
|
1909
1941
|
return `{ ${entries.join(", ")} }`;
|
|
@@ -2019,7 +2051,7 @@ function convertArrayKeyframesToObjectNode(varsArg, scope) {
|
|
|
2019
2051
|
el.properties = (el.properties ?? []).filter(
|
|
2020
2052
|
(property) => !isObjectProperty(property) || propKeyName(property) !== "duration"
|
|
2021
2053
|
);
|
|
2022
|
-
return `${JSON.stringify(
|
|
2054
|
+
return `${JSON.stringify(plainPercentKey(timing.percentages[i]))}: ${recast.print(el).code}`;
|
|
2023
2055
|
});
|
|
2024
2056
|
prop.value = parseExpr(`{ ${entries.join(", ")}, easeEach: "none" }`);
|
|
2025
2057
|
return prop.value;
|
|
@@ -2044,7 +2076,7 @@ function locateKeyframeCtx(script, animationId, percentage) {
|
|
|
2044
2076
|
if (!loc) return null;
|
|
2045
2077
|
const kfNode = findKeyframesObjectNode(loc.target.call.varsArg);
|
|
2046
2078
|
if (!kfNode) return null;
|
|
2047
|
-
return { loc, kfNode, pctKey:
|
|
2079
|
+
return { loc, kfNode, pctKey: plainPercentKey(percentage) };
|
|
2048
2080
|
}
|
|
2049
2081
|
function addKeyframeToScript(script, animationId, percentage, properties, ease, backfillDefaults) {
|
|
2050
2082
|
let loc = locateAnimationWithFallback(script, animationId);
|
|
@@ -2060,7 +2092,7 @@ function addKeyframeToScript(script, animationId, percentage, properties, ease,
|
|
|
2060
2092
|
kfNode = findKeyframesObjectNode(loc.target.call.varsArg);
|
|
2061
2093
|
if (!kfNode) return script;
|
|
2062
2094
|
}
|
|
2063
|
-
const pctKey =
|
|
2095
|
+
const pctKey = plainPercentKey(percentage);
|
|
2064
2096
|
const newValueNode = buildKeyframeValueNode(properties, ease);
|
|
2065
2097
|
const existing = findKeyframePropByPct(kfNode, percentage);
|
|
2066
2098
|
if (existing) {
|
|
@@ -2188,11 +2220,16 @@ function moveKeyframeInScript(script, animationId, fromPercentage, toPercentage)
|
|
|
2188
2220
|
}
|
|
2189
2221
|
entries.push({ pct: toPercentage, value: movedValue });
|
|
2190
2222
|
entries.sort((a, b) => a.pct - b.pct);
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2223
|
+
const pctProps = new Set(filterPercentageProps(kfNode));
|
|
2224
|
+
const kept = (kfNode.properties ?? []).filter((p) => !pctProps.has(p));
|
|
2225
|
+
kfNode.properties = [
|
|
2226
|
+
...entries.map((e) => {
|
|
2227
|
+
const p = parseExpr(`{ ${JSON.stringify(plainPercentKey(e.pct))}: {} }`).properties[0];
|
|
2228
|
+
p.value = e.value;
|
|
2229
|
+
return p;
|
|
2230
|
+
}),
|
|
2231
|
+
...kept
|
|
2232
|
+
];
|
|
2196
2233
|
return recast.print(loc.parsed.ast).code;
|
|
2197
2234
|
}
|
|
2198
2235
|
function resizeKeyframedTweenInScript(script, animationId, newPosition, newDuration, pctRemap) {
|
|
@@ -2205,7 +2242,7 @@ function resizeKeyframedTweenInScript(script, animationId, newPosition, newDurat
|
|
|
2205
2242
|
const match = findKeyframePropByPct(kfNode, from);
|
|
2206
2243
|
if (!match || seen.has(match.prop)) continue;
|
|
2207
2244
|
seen.add(match.prop);
|
|
2208
|
-
match.prop.key = parseExpr(`{ ${JSON.stringify(
|
|
2245
|
+
match.prop.key = parseExpr(`{ ${JSON.stringify(plainPercentKey(to))}: 0 }`).properties[0].key;
|
|
2209
2246
|
}
|
|
2210
2247
|
applyUpdatesToCall(loc.target.call, {
|
|
2211
2248
|
position: newPosition,
|
|
@@ -2715,7 +2752,8 @@ function splitIntoPropertyGroups(script, animationId) {
|
|
|
2715
2752
|
typeof anim.position === "number" ? anim.position : 0,
|
|
2716
2753
|
anim.duration ?? 0.5,
|
|
2717
2754
|
groupKeyframes,
|
|
2718
|
-
anim.keyframes.
|
|
2755
|
+
anim.keyframes.ease ?? anim.ease,
|
|
2756
|
+
anim.keyframes.easeEach
|
|
2719
2757
|
);
|
|
2720
2758
|
result = addResult.script;
|
|
2721
2759
|
} else {
|