@hyperframes/parsers 0.8.126 → 0.8.128
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/composition.d.ts +1 -1
- package/dist/composition.js.map +1 -1
- package/dist/gsapConstants.d.ts +1 -1
- package/dist/gsapConstants.js +28 -5
- package/dist/gsapConstants.js.map +1 -1
- package/dist/gsapParser.d.ts +2 -2
- package/dist/gsapParser.js +83 -53
- package/dist/gsapParser.js.map +1 -1
- package/dist/gsapParserAcorn.d.ts +2 -2
- package/dist/gsapParserAcorn.js +50 -40
- package/dist/gsapParserAcorn.js.map +1 -1
- package/dist/gsapParserExports.d.ts +15 -1
- package/dist/gsapParserExports.js +52 -40
- package/dist/gsapParserExports.js.map +1 -1
- package/dist/{gsapSerialize-CVwsMItk.d.ts → gsapSerialize-CfSXM_Ez.d.ts} +10 -2
- package/dist/gsapWriterAcorn.d.ts +23 -3
- package/dist/gsapWriterAcorn.js +169 -116
- package/dist/gsapWriterAcorn.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +53 -41
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -7,7 +7,14 @@ import { K as Keyframe, V as ValidationResult } from './types-Ejqndkej.js';
|
|
|
7
7
|
* without pulling in gsapParser (which depends on recast / @babel/parser).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
declare const GSAP_DEFAULT_DURATION = 0.5;
|
|
10
11
|
declare const SUPPORTED_PROPS: string[];
|
|
12
|
+
/** Keys stored on dedicated GsapAnimation fields (not in properties/extras). */
|
|
13
|
+
declare const BUILTIN_VAR_KEYS: ReadonlySet<string>;
|
|
14
|
+
declare const DROPPED_VAR_KEYS: ReadonlySet<string>;
|
|
15
|
+
/** Keys that go in `extras`: non-editable GSAP config that must survive round-trips. */
|
|
16
|
+
declare const EXTRAS_KEYS: ReadonlySet<string>;
|
|
17
|
+
declare function isTweenConfigKey(key: string): boolean;
|
|
11
18
|
type PropertyGroupName = "position" | "scale" | "size" | "rotation" | "visual" | "other";
|
|
12
19
|
declare const PROPERTY_GROUPS: Record<PropertyGroupName, ReadonlySet<string>>;
|
|
13
20
|
type PositionWrite = Pick<GsapAnimation, "propertyGroup" | "properties" | "fromProperties" | "keyframes">;
|
|
@@ -16,7 +23,7 @@ declare function isXYPositionWrite(a: PositionWrite): boolean;
|
|
|
16
23
|
declare function classifyPropertyGroup(prop: string): PropertyGroupName;
|
|
17
24
|
declare function classifyTweenPropertyGroup(properties: Record<string, unknown>): PropertyGroupName | undefined;
|
|
18
25
|
/**
|
|
19
|
-
* What a Studio hold pins from t=0 before a later keyframed tween: its
|
|
26
|
+
* What a Studio hold pins from t=0 before a later keyframed tween: its 0% keyframe's position props,
|
|
20
27
|
* minus those an earlier timeline tween on the target writes (a global `gsap.set` is a base value).
|
|
21
28
|
*/
|
|
22
29
|
declare function positionHoldForAnimation(animation: GsapAnimation, animations: readonly GsapAnimation[]): Record<string, number> | null;
|
|
@@ -123,6 +130,7 @@ interface GsapKeyframesData<K extends GsapPercentageKeyframe = GsapPercentageKey
|
|
|
123
130
|
keyframes: K[];
|
|
124
131
|
ease?: string;
|
|
125
132
|
easeEach?: string;
|
|
133
|
+
fromMotionPath?: true;
|
|
126
134
|
}
|
|
127
135
|
interface ArcPathSegment {
|
|
128
136
|
curviness: number;
|
|
@@ -208,4 +216,4 @@ declare function gsapAnimationsToKeyframes(animations: GsapAnimation[], elementS
|
|
|
208
216
|
skipBaseSet?: boolean;
|
|
209
217
|
}): Keyframe[];
|
|
210
218
|
|
|
211
|
-
export { type ArcPathConfig as A, type
|
|
219
|
+
export { type ArcPathConfig as A, BUILTIN_VAR_KEYS as B, DROPPED_VAR_KEYS as D, EXTRAS_KEYS as E, type GsapMethod as G, type KeyframeEditability as K, type MotionPathShape as M, type ParsedGsap as P, SUPPORTED_EASES as S, type GsapAnimation as a, type ArcPathSegment as b, type GsapProvenance as c, type GsapProvenanceKind as d, buildArcPath as e, editabilityForProvenance as f, type GsapKeyframeFormat as g, type GsapKeyframesData as h, type GsapPercentageKeyframe as i, PROPERTY_GROUPS as j, type PropertyGroupName as k, SUPPORTED_PROPS as l, classifyPropertyGroup as m, classifyTweenPropertyGroup as n, getAnimationsForElementId as o, gsapAnimationsToKeyframes as p, keyframesToGsapAnimations as q, type SplitAnimationsOptions as r, serializeGsapAnimations as s, type SplitAnimationsResult as t, GSAP_DEFAULT_DURATION as u, validateCompositionGsap as v, type SourcedGsapPercentageKeyframe as w, isTweenConfigKey as x, isXYPositionWrite as y, positionHoldForAnimation as z };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as GsapAnimation, A as ArcPathConfig, r as SplitAnimationsOptions, t as SplitAnimationsResult, b as ArcPathSegment } from './gsapSerialize-CfSXM_Ez.js';
|
|
2
2
|
import './types-Ejqndkej.js';
|
|
3
3
|
|
|
4
4
|
type TweenTarget = Pick<GsapAnimation, "targetSelector" | "hasPartialSelector">;
|
|
5
5
|
type TweenTime = Pick<GsapAnimation, "position" | "implicitPosition">;
|
|
6
|
-
declare function clipTweenMatcher(clipSelectors: string | readonly string[], root?: ParentNode): (tween: TweenTarget) => boolean;
|
|
6
|
+
declare function clipTweenMatcher(clipSelectors: string | readonly string[], root?: ParentNode, queries?: Map<string, Element[]>): (tween: TweenTarget) => boolean;
|
|
7
7
|
/** Where a GSAP script's clips live: linkedom keeps a `<template>`'s children under it, out of document queries. */
|
|
8
8
|
declare function clipQueryRoot(script: Element): ParentNode;
|
|
9
9
|
/** A written position; an implicit one follows the tween before it and must stay unwritten. */
|
|
@@ -21,6 +21,26 @@ declare function updateAnimationInScript(script: string, animationId: string, up
|
|
|
21
21
|
* (used by timeline clip-move to keep GSAP positions in sync with the clip start).
|
|
22
22
|
*/
|
|
23
23
|
declare function shiftPositionsInScript(script: string, targetSelector: string, delta: number, root?: ParentNode): string;
|
|
24
|
+
type ClipTweenRetime = {
|
|
25
|
+
kind: "shift";
|
|
26
|
+
targetSelector: string;
|
|
27
|
+
delta: number;
|
|
28
|
+
} | {
|
|
29
|
+
kind: "scale";
|
|
30
|
+
targetSelector: string;
|
|
31
|
+
oldStart: number;
|
|
32
|
+
oldDuration: number;
|
|
33
|
+
newStart: number;
|
|
34
|
+
newDuration: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Applies `retimes` in order with one parse: the bytes equal running shift/scalePositionsInScript once
|
|
38
|
+
* per retime. `changed[i]` says whether retime i moved a value.
|
|
39
|
+
*/
|
|
40
|
+
declare function retimeClipTweensInScript(script: string, retimes: readonly ClipTweenRetime[], root?: ParentNode): {
|
|
41
|
+
script: string;
|
|
42
|
+
changed: boolean[];
|
|
43
|
+
};
|
|
24
44
|
/** Copies each tween on `fromSelector` for `toSelector`, `delta` seconds later, in its own argument text. Exact or
|
|
25
45
|
* absent: only a tween at a number, written straight in the timeline's own block, is copied. */
|
|
26
46
|
declare function copyAnimationsInScript(script: string, fromSelector: string, toSelector: string, delta: number): string;
|
|
@@ -177,4 +197,4 @@ type UnrollElement = {
|
|
|
177
197
|
*/
|
|
178
198
|
declare function unrollDynamicAnimations(script: string, animationId: string, elements: UnrollElement[]): string;
|
|
179
199
|
|
|
180
|
-
export { type UnrollElement, addAnimationToScript, addAnimationWithKeyframesToScript, addKeyframeToScript, addLabelToScript, addMotionPathPointInScript, addMotionPathToScript, clipQueryRoot, clipTweenMatcher, convertToKeyframesFromScript, copyAnimationsInScript, dedupePositionWritesInScript, hasExplicitTime, materializeKeyframesFromScript, moveKeyframeInScript, removeAllKeyframesFromScript, removeAnimationFromScript, removeArcPathFromScript, removeKeyframeFromScript, removeLabelFromScript, removeMotionPathPointInScript, removePropertyFromAnimation, replaceTweenWithKeyframesInScript, resizeKeyframedTweenInScript, scalePositionsInScript, setArcPathInScript, shiftPositionsInScript, splitAnimationsInScript, splitIntoPropertyGroupsFromScript, syncPositionHoldsBeforeKeyframes, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript, updateMotionPathPointInScript };
|
|
200
|
+
export { type ClipTweenRetime, type UnrollElement, addAnimationToScript, addAnimationWithKeyframesToScript, addKeyframeToScript, addLabelToScript, addMotionPathPointInScript, addMotionPathToScript, clipQueryRoot, clipTweenMatcher, convertToKeyframesFromScript, copyAnimationsInScript, dedupePositionWritesInScript, hasExplicitTime, materializeKeyframesFromScript, moveKeyframeInScript, removeAllKeyframesFromScript, removeAnimationFromScript, removeArcPathFromScript, removeKeyframeFromScript, removeLabelFromScript, removeMotionPathPointInScript, removePropertyFromAnimation, replaceTweenWithKeyframesInScript, resizeKeyframedTweenInScript, retimeClipTweensInScript, scalePositionsInScript, setArcPathInScript, shiftPositionsInScript, splitAnimationsInScript, splitIntoPropertyGroupsFromScript, syncPositionHoldsBeforeKeyframes, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript, updateMotionPathPointInScript };
|
package/dist/gsapWriterAcorn.js
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
import MagicString from "magic-string";
|
|
3
3
|
|
|
4
4
|
// src/gsapConstants.ts
|
|
5
|
+
var GSAP_DEFAULT_DURATION = 0.5;
|
|
6
|
+
var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
|
|
7
|
+
var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set([
|
|
8
|
+
"onComplete",
|
|
9
|
+
"onStart",
|
|
10
|
+
"onUpdate",
|
|
11
|
+
"onRepeat"
|
|
12
|
+
]);
|
|
13
|
+
var EXTRAS_KEYS = /* @__PURE__ */ new Set([
|
|
14
|
+
"stagger",
|
|
15
|
+
"yoyo",
|
|
16
|
+
"repeat",
|
|
17
|
+
"repeatDelay",
|
|
18
|
+
"snap",
|
|
19
|
+
"overwrite",
|
|
20
|
+
"immediateRender"
|
|
21
|
+
]);
|
|
22
|
+
function isTweenConfigKey(key) {
|
|
23
|
+
return BUILTIN_VAR_KEYS.has(key) || DROPPED_VAR_KEYS.has(key) || EXTRAS_KEYS.has(key);
|
|
24
|
+
}
|
|
5
25
|
var PROPERTY_GROUPS = {
|
|
6
26
|
position: /* @__PURE__ */ new Set(["x", "y", "xPercent", "yPercent"]),
|
|
7
27
|
scale: /* @__PURE__ */ new Set(["scale", "scaleX", "scaleY"]),
|
|
@@ -41,16 +61,14 @@ function positionHoldForAnimation(animation, animations) {
|
|
|
41
61
|
if (!animation.keyframes) return null;
|
|
42
62
|
const start = knownStart(animation) ?? 0;
|
|
43
63
|
if (!(start > 1e-3)) return null;
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
)[0];
|
|
47
|
-
if (!first) return null;
|
|
64
|
+
const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
|
|
65
|
+
if (!atStart) return null;
|
|
48
66
|
const earlier = animations.filter((other) => {
|
|
49
67
|
const otherStart = knownStart(other);
|
|
50
68
|
return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
|
|
51
69
|
});
|
|
52
70
|
const position = {};
|
|
53
|
-
for (const [property, value] of Object.entries(
|
|
71
|
+
for (const [property, value] of Object.entries(atStart.properties)) {
|
|
54
72
|
if (classifyPropertyGroup(property) !== "position" || typeof value !== "number") continue;
|
|
55
73
|
if (earlier.some((other) => writesProperty(other, property))) continue;
|
|
56
74
|
position[property] = value;
|
|
@@ -59,6 +77,9 @@ function positionHoldForAnimation(animation, animations) {
|
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
// src/gsapSerialize.ts
|
|
80
|
+
function authorsKeyframes(anim) {
|
|
81
|
+
return anim.keyframes !== void 0 || anim.hasUnresolvedKeyframes === true;
|
|
82
|
+
}
|
|
62
83
|
function mergePercentageKeyframes(keyframes) {
|
|
63
84
|
const byPercentage = /* @__PURE__ */ new Map();
|
|
64
85
|
for (const keyframe of keyframes) {
|
|
@@ -210,34 +231,27 @@ function readProvenance(node) {
|
|
|
210
231
|
var roundPercentage = (percentage) => Math.round(percentage * 10) / 10;
|
|
211
232
|
var OBJECT_ARRAY_PERCENTAGE_TOLERANCE = 2;
|
|
212
233
|
function getObjectArrayKeyframeTiming(durations) {
|
|
213
|
-
const
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return null;
|
|
219
|
-
}
|
|
220
|
-
const totalDuration = durations.reduce((sum, duration) => sum + duration, 0);
|
|
221
|
-
let cumulative = 0;
|
|
222
|
-
return {
|
|
223
|
-
percentages: durations.map((duration) => {
|
|
224
|
-
cumulative += duration;
|
|
225
|
-
return roundPercentage(cumulative / totalDuration * 100);
|
|
226
|
-
}),
|
|
227
|
-
totalDuration
|
|
228
|
-
};
|
|
234
|
+
const steps = durations.map((duration) => duration ?? GSAP_DEFAULT_DURATION);
|
|
235
|
+
if (!steps.every(
|
|
236
|
+
(duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
|
|
237
|
+
)) {
|
|
238
|
+
return null;
|
|
229
239
|
}
|
|
230
|
-
const
|
|
240
|
+
const totalDuration = steps.reduce((sum, duration) => sum + duration, 0);
|
|
241
|
+
let cumulative = 0;
|
|
231
242
|
return {
|
|
232
|
-
percentages:
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
percentages: steps.map((duration) => {
|
|
244
|
+
cumulative += duration;
|
|
245
|
+
return roundPercentage(cumulative / totalDuration * 100);
|
|
246
|
+
}),
|
|
247
|
+
totalDuration
|
|
235
248
|
};
|
|
236
249
|
}
|
|
237
250
|
function getCompatibleObjectArrayKeyframeTiming(durations, outerDuration) {
|
|
238
251
|
const timing = getObjectArrayKeyframeTiming(durations);
|
|
239
252
|
if (!timing) return null;
|
|
240
|
-
|
|
253
|
+
const stepsAuthorDuration = durations.some((duration) => duration !== void 0);
|
|
254
|
+
if (!stepsAuthorDuration || outerDuration === void 0) return timing;
|
|
241
255
|
if (typeof outerDuration === "number" && Math.abs(outerDuration - timing.totalDuration) <= Number.EPSILON) {
|
|
242
256
|
return timing;
|
|
243
257
|
}
|
|
@@ -755,17 +769,6 @@ function findTimelineVar(ast, scope) {
|
|
|
755
769
|
});
|
|
756
770
|
return { timelineVar, ref, timelineCount, defaults };
|
|
757
771
|
}
|
|
758
|
-
var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
|
|
759
|
-
var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set(["onComplete", "onStart", "onUpdate", "onRepeat"]);
|
|
760
|
-
var EXTRAS_KEYS = /* @__PURE__ */ new Set([
|
|
761
|
-
"stagger",
|
|
762
|
-
"yoyo",
|
|
763
|
-
"repeat",
|
|
764
|
-
"repeatDelay",
|
|
765
|
-
"snap",
|
|
766
|
-
"overwrite",
|
|
767
|
-
"immediateRender"
|
|
768
|
-
]);
|
|
769
772
|
function isTimelineRootedCall(callNode, ref) {
|
|
770
773
|
let obj = callNode.callee?.object;
|
|
771
774
|
while (obj?.type === "CallExpression") {
|
|
@@ -844,6 +847,7 @@ function parsePercentageKeyframes(node, scope, source) {
|
|
|
844
847
|
if (typeof key !== "string") continue;
|
|
845
848
|
const pctMatch = PERCENTAGE_KEY_RE.exec(key);
|
|
846
849
|
if (pctMatch) {
|
|
850
|
+
if (!isPlainStep(prop.value)) return void 0;
|
|
847
851
|
const percentage = Number.parseFloat(pctMatch[1] ?? "0");
|
|
848
852
|
const record = objectExpressionToRecord(prop.value, scope, source);
|
|
849
853
|
const properties = {};
|
|
@@ -862,6 +866,8 @@ function parsePercentageKeyframes(node, scope, source) {
|
|
|
862
866
|
ease = tryResolveStringProp(prop.value, scope, source) ?? ease;
|
|
863
867
|
} else if (key === "easeEach") {
|
|
864
868
|
easeEach = tryResolveStringProp(prop.value, scope, source) ?? easeEach;
|
|
869
|
+
} else {
|
|
870
|
+
return void 0;
|
|
865
871
|
}
|
|
866
872
|
}
|
|
867
873
|
keyframes.sort((a, b) => a.percentage - b.percentage);
|
|
@@ -885,11 +891,19 @@ function computeKeyframesTotalDuration(varsNode, scope, source) {
|
|
|
885
891
|
}
|
|
886
892
|
return getObjectArrayKeyframeTiming(durations)?.totalDuration;
|
|
887
893
|
}
|
|
894
|
+
function staticKeyName(prop) {
|
|
895
|
+
if (prop.type !== "ObjectProperty" && prop.type !== "Property") return void 0;
|
|
896
|
+
if (prop.method || prop.kind && prop.kind !== "init") return void 0;
|
|
897
|
+
const key = prop.computed ? prop.key?.type === "Literal" && prop.key.value : prop.key?.name ?? prop.key?.value;
|
|
898
|
+
return typeof key === "string" ? key : void 0;
|
|
899
|
+
}
|
|
900
|
+
var isPlainObject = (node) => node?.type === "ObjectExpression" && (node.properties ?? []).every((p) => staticKeyName(p) !== void 0);
|
|
901
|
+
var isPlainStep = (node) => node?.type === "Literal" || isPlainObject(node);
|
|
888
902
|
function parseObjectArrayKeyframes(node, scope, source) {
|
|
889
903
|
const elements = node.elements ?? [];
|
|
890
904
|
const raw = [];
|
|
891
905
|
for (const el of elements) {
|
|
892
|
-
if (!el
|
|
906
|
+
if (!isPlainObject(el)) return void 0;
|
|
893
907
|
const record = objectExpressionToRecord(el, scope, source);
|
|
894
908
|
const properties = {};
|
|
895
909
|
let duration;
|
|
@@ -901,6 +915,8 @@ function parseObjectArrayKeyframes(node, scope, source) {
|
|
|
901
915
|
ease = v;
|
|
902
916
|
} else if (typeof v === "number" || typeof v === "string") {
|
|
903
917
|
properties[k] = v;
|
|
918
|
+
} else {
|
|
919
|
+
return void 0;
|
|
904
920
|
}
|
|
905
921
|
}
|
|
906
922
|
raw.push({ properties, duration, ease });
|
|
@@ -926,9 +942,8 @@ function parseSimpleArrayKeyframes(node, scope) {
|
|
|
926
942
|
const values = [];
|
|
927
943
|
for (const el of prop.value.elements ?? []) {
|
|
928
944
|
const val = resolveNode(el, scope);
|
|
929
|
-
if (typeof val
|
|
930
|
-
|
|
931
|
-
}
|
|
945
|
+
if (typeof val !== "number" && typeof val !== "string") return void 0;
|
|
946
|
+
values.push(val);
|
|
932
947
|
}
|
|
933
948
|
if (values.length > 0) arrayProps.set(key, values);
|
|
934
949
|
} else if (key === "ease") {
|
|
@@ -961,6 +976,7 @@ function parseKeyframesNode(node, scope, source) {
|
|
|
961
976
|
}
|
|
962
977
|
if (node.type !== "ObjectExpression") return void 0;
|
|
963
978
|
const props = node.properties ?? [];
|
|
979
|
+
if (!props.every((p) => staticKeyName(p) !== void 0)) return void 0;
|
|
964
980
|
let hasPercentageKey = false;
|
|
965
981
|
let hasArrayValue = false;
|
|
966
982
|
for (const prop of props) {
|
|
@@ -1061,7 +1077,7 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
|
|
|
1061
1077
|
percentage: waypoints.length > 1 ? Math.round(i / (waypoints.length - 1) * 100) : 0,
|
|
1062
1078
|
properties: { x: wp.x, y: wp.y }
|
|
1063
1079
|
}));
|
|
1064
|
-
keyframesData = { format: "percentage", keyframes: kf };
|
|
1080
|
+
keyframesData = { format: "percentage", keyframes: kf, fromMotionPath: true };
|
|
1065
1081
|
} else {
|
|
1066
1082
|
const kfs = keyframesData.keyframes;
|
|
1067
1083
|
if (kfs.length === waypoints.length) {
|
|
@@ -1091,10 +1107,10 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
|
|
|
1091
1107
|
const position = typeof posVal === "number" ? posVal : typeof posVal === "string" ? posVal : hasPositionArg ? `__raw:${source.slice(call.positionArg.start, call.positionArg.end)}` : 0;
|
|
1092
1108
|
let duration = typeof vars.duration === "number" ? vars.duration : void 0;
|
|
1093
1109
|
const ease = typeof vars.ease === "string" ? vars.ease : void 0;
|
|
1094
|
-
|
|
1110
|
+
const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
|
|
1111
|
+
if (duration === void 0 && keyframesData && !durationUnresolved) {
|
|
1095
1112
|
duration = computeKeyframesTotalDuration(call.varsArg, scope, source);
|
|
1096
1113
|
}
|
|
1097
|
-
const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
|
|
1098
1114
|
let selector = call.selector;
|
|
1099
1115
|
let targetIdentity;
|
|
1100
1116
|
if (selector === "__unresolved__") {
|
|
@@ -1148,7 +1164,6 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
|
|
|
1148
1164
|
if (provenance) anim.provenance = provenance;
|
|
1149
1165
|
return anim;
|
|
1150
1166
|
}
|
|
1151
|
-
var GSAP_DEFAULT_DURATION = 0.5;
|
|
1152
1167
|
function resolvePositionString(pos, cursor, prevStart) {
|
|
1153
1168
|
const trimmed = pos.trim();
|
|
1154
1169
|
if (trimmed === "") return cursor;
|
|
@@ -1181,7 +1196,7 @@ function applyTimelineDefaults(anims, defaults) {
|
|
|
1181
1196
|
if (defaults.duration !== void 0) anim.duration = defaults.duration;
|
|
1182
1197
|
else if (defaults.durationUnresolved) anim.durationUnresolved = true;
|
|
1183
1198
|
}
|
|
1184
|
-
if (anim.ease === void 0 && defaults.ease !== void 0 && !anim.keyframes) {
|
|
1199
|
+
if (anim.ease === void 0 && defaults.ease !== void 0 && (!anim.keyframes || anim.keyframes.fromMotionPath)) {
|
|
1185
1200
|
anim.ease = defaults.ease;
|
|
1186
1201
|
}
|
|
1187
1202
|
}
|
|
@@ -1350,14 +1365,25 @@ function parseGsapScriptAcornForWrite(script) {
|
|
|
1350
1365
|
import * as acornWalk2 from "acorn-walk";
|
|
1351
1366
|
|
|
1352
1367
|
// src/clipTweens.ts
|
|
1353
|
-
function clipTweenMatcher(clipSelectors, root) {
|
|
1368
|
+
function clipTweenMatcher(clipSelectors, root, queries = /* @__PURE__ */ new Map()) {
|
|
1354
1369
|
const own = typeof clipSelectors === "string" ? [clipSelectors] : clipSelectors;
|
|
1355
|
-
|
|
1370
|
+
if (!root)
|
|
1371
|
+
return ({ targetSelector, hasPartialSelector }) => !hasPartialSelector && own.includes(targetSelector);
|
|
1372
|
+
const queryAll = (selector) => {
|
|
1373
|
+
if (ID_SELECTOR.test(selector)) {
|
|
1374
|
+
if (!queries.has(ALL_IDS)) indexIds(root, queries);
|
|
1375
|
+
return queries.get(selector) ?? [];
|
|
1376
|
+
}
|
|
1377
|
+
let found = queries.get(selector);
|
|
1378
|
+
if (!found) queries.set(selector, found = queryRoot(root, selector));
|
|
1379
|
+
return found;
|
|
1380
|
+
};
|
|
1381
|
+
const clips = own.flatMap((selector) => queryAll(selector));
|
|
1356
1382
|
return ({ targetSelector, hasPartialSelector }) => {
|
|
1357
1383
|
if (hasPartialSelector) return false;
|
|
1358
1384
|
if (own.includes(targetSelector)) return true;
|
|
1359
|
-
if (
|
|
1360
|
-
const targets = queryAll(
|
|
1385
|
+
if (clips.length === 0) return false;
|
|
1386
|
+
const targets = queryAll(targetSelector);
|
|
1361
1387
|
return targets.length > 0 && targets.every((target) => {
|
|
1362
1388
|
const owner = target.closest("[data-start]");
|
|
1363
1389
|
return clips.includes(target) || owner !== null && clips.includes(owner);
|
|
@@ -1370,7 +1396,20 @@ function clipQueryRoot(script) {
|
|
|
1370
1396
|
function hasExplicitTime(animation) {
|
|
1371
1397
|
return typeof animation.position === "number" && !animation.implicitPosition;
|
|
1372
1398
|
}
|
|
1373
|
-
|
|
1399
|
+
var ID_SELECTOR = /^#-?[A-Za-z_][\w-]*$/;
|
|
1400
|
+
var ALL_IDS = "[id]";
|
|
1401
|
+
function indexIds(root, queries) {
|
|
1402
|
+
const all = queryRoot(root, ALL_IDS);
|
|
1403
|
+
queries.set(ALL_IDS, all);
|
|
1404
|
+
for (const el of all) {
|
|
1405
|
+
const key = `#${el.id}`;
|
|
1406
|
+
if (!ID_SELECTOR.test(key)) continue;
|
|
1407
|
+
const list = queries.get(key);
|
|
1408
|
+
if (list) list.push(el);
|
|
1409
|
+
else queries.set(key, [el]);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
function queryRoot(root, selector) {
|
|
1374
1413
|
try {
|
|
1375
1414
|
return Array.from(root.querySelectorAll(selector));
|
|
1376
1415
|
} catch {
|
|
@@ -1486,24 +1525,8 @@ function upsertProp(ms, objNode, key, value) {
|
|
|
1486
1525
|
ms.appendLeft(objNode.end - 1, `${sep}${safeKey(key)}: ${valueToCode(value)}`);
|
|
1487
1526
|
}
|
|
1488
1527
|
}
|
|
1489
|
-
var NON_EDITABLE_PROP_KEYS = /* @__PURE__ */ new Set([
|
|
1490
|
-
"duration",
|
|
1491
|
-
"ease",
|
|
1492
|
-
"delay",
|
|
1493
|
-
"onComplete",
|
|
1494
|
-
"onStart",
|
|
1495
|
-
"onUpdate",
|
|
1496
|
-
"onRepeat",
|
|
1497
|
-
"stagger",
|
|
1498
|
-
"yoyo",
|
|
1499
|
-
"repeat",
|
|
1500
|
-
"repeatDelay",
|
|
1501
|
-
"snap",
|
|
1502
|
-
"overwrite",
|
|
1503
|
-
"immediateRender"
|
|
1504
|
-
]);
|
|
1505
1528
|
function isEditableVarKey(key) {
|
|
1506
|
-
return !
|
|
1529
|
+
return !isTweenConfigKey(key);
|
|
1507
1530
|
}
|
|
1508
1531
|
function preservedEntries(objNode, source, drop, overrides) {
|
|
1509
1532
|
const entries = [];
|
|
@@ -1562,7 +1585,7 @@ function updateAnimationInScript(script, animationId, updates) {
|
|
|
1562
1585
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
1563
1586
|
if (!parsed) return script;
|
|
1564
1587
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
1565
|
-
if (!target) return script;
|
|
1588
|
+
if (!target || updates.properties && target.animation.hasUnresolvedKeyframes) return script;
|
|
1566
1589
|
const ms = new MagicString(script);
|
|
1567
1590
|
const { call } = target;
|
|
1568
1591
|
if (updates.properties) {
|
|
@@ -1626,17 +1649,54 @@ function overwritePosition(ms, call, position) {
|
|
|
1626
1649
|
}
|
|
1627
1650
|
}
|
|
1628
1651
|
function shiftPositionsInScript(script, targetSelector, delta, root) {
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1652
|
+
return retimeClipTweensInScript(script, [{ kind: "shift", targetSelector, delta }], root).script;
|
|
1653
|
+
}
|
|
1654
|
+
var isLiveRetime = (r) => r.kind === "shift" || r.oldDuration > 0 && r.newDuration > 0;
|
|
1655
|
+
function applyRetime(animation, retime) {
|
|
1656
|
+
if (retime.kind === "shift") {
|
|
1657
|
+
if (!hasExplicitTime(animation)) return { position: false, duration: false };
|
|
1658
|
+
animation.position = shiftedPosition(animation.position, retime.delta);
|
|
1659
|
+
return { position: true, duration: false };
|
|
1660
|
+
}
|
|
1661
|
+
const touched = { position: false, duration: false };
|
|
1662
|
+
if (!isLiveRetime(retime) || typeof animation.position !== "number") return touched;
|
|
1663
|
+
const ratio = retime.newDuration / retime.oldDuration;
|
|
1664
|
+
if (hasExplicitTime(animation)) {
|
|
1665
|
+
const scaled = retime.newStart + (animation.position - retime.oldStart) * ratio;
|
|
1666
|
+
animation.position = Math.max(0, Math.round(scaled * 1e3) / 1e3);
|
|
1667
|
+
touched.position = true;
|
|
1668
|
+
}
|
|
1669
|
+
if (typeof animation.duration === "number" && animation.duration > 0) {
|
|
1670
|
+
animation.duration = Math.max(1e-3, Math.round(animation.duration * ratio * 1e3) / 1e3);
|
|
1671
|
+
touched.duration = true;
|
|
1672
|
+
}
|
|
1673
|
+
return touched;
|
|
1674
|
+
}
|
|
1675
|
+
function retimeClipTweensInScript(script, retimes, root) {
|
|
1676
|
+
const changed = retimes.map(() => false);
|
|
1677
|
+
const parsed = retimes.some(isLiveRetime) ? parseGsapScriptAcornForWrite(script) : null;
|
|
1678
|
+
if (!parsed) return { script, changed };
|
|
1679
|
+
const queries = /* @__PURE__ */ new Map();
|
|
1680
|
+
const matchers = retimes.map((r) => clipTweenMatcher(r.targetSelector, root, queries));
|
|
1632
1681
|
const ms = new MagicString(script);
|
|
1633
|
-
let
|
|
1682
|
+
let wrote = false;
|
|
1634
1683
|
for (const entry of parsed.located) {
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1684
|
+
const animation = { ...entry.animation };
|
|
1685
|
+
let position = false;
|
|
1686
|
+
let duration = false;
|
|
1687
|
+
retimes.forEach((retime, i) => {
|
|
1688
|
+
if (!matchers[i](animation)) return;
|
|
1689
|
+
const before = [animation.position, animation.duration];
|
|
1690
|
+
const touched = applyRetime(animation, retime);
|
|
1691
|
+
position ||= touched.position;
|
|
1692
|
+
duration ||= touched.duration;
|
|
1693
|
+
if (before[0] !== animation.position || before[1] !== animation.duration) changed[i] = true;
|
|
1694
|
+
});
|
|
1695
|
+
if (position) overwritePosition(ms, entry.call, animation.position);
|
|
1696
|
+
if (duration) upsertProp(ms, entry.call.varsArg, "duration", animation.duration);
|
|
1697
|
+
wrote ||= position || duration;
|
|
1638
1698
|
}
|
|
1639
|
-
return
|
|
1699
|
+
return { script: wrote ? ms.toString() : script, changed };
|
|
1640
1700
|
}
|
|
1641
1701
|
function copyAnimationsInScript(script, fromSelector, toSelector, delta) {
|
|
1642
1702
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
@@ -1708,29 +1768,11 @@ function isLoopOrForEach(node) {
|
|
|
1708
1768
|
return isLoopNode(node) || isForEachStatement(node) || node?.type === "DoWhileStatement";
|
|
1709
1769
|
}
|
|
1710
1770
|
function scalePositionsInScript(script, targetSelector, oldStart, oldDuration, newStart, newDuration, root) {
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
const ms = new MagicString(script);
|
|
1717
|
-
let changed = false;
|
|
1718
|
-
for (const entry of parsed.located) {
|
|
1719
|
-
if (!carries(entry.animation) || typeof entry.animation.position !== "number") continue;
|
|
1720
|
-
if (hasExplicitTime(entry.animation)) {
|
|
1721
|
-
const newPos = Math.max(
|
|
1722
|
-
0,
|
|
1723
|
-
Math.round((newStart + (entry.animation.position - oldStart) * ratio) * 1e3) / 1e3
|
|
1724
|
-
);
|
|
1725
|
-
overwritePosition(ms, entry.call, newPos);
|
|
1726
|
-
}
|
|
1727
|
-
if (typeof entry.animation.duration === "number" && entry.animation.duration > 0) {
|
|
1728
|
-
const newDur = Math.max(1e-3, Math.round(entry.animation.duration * ratio * 1e3) / 1e3);
|
|
1729
|
-
upsertProp(ms, entry.call.varsArg, "duration", newDur);
|
|
1730
|
-
}
|
|
1731
|
-
changed = true;
|
|
1732
|
-
}
|
|
1733
|
-
return changed ? ms.toString() : script;
|
|
1771
|
+
return retimeClipTweensInScript(
|
|
1772
|
+
script,
|
|
1773
|
+
[{ kind: "scale", targetSelector, oldStart, oldDuration, newStart, newDuration }],
|
|
1774
|
+
root
|
|
1775
|
+
).script;
|
|
1734
1776
|
}
|
|
1735
1777
|
function addAnimationToScript(script, animation) {
|
|
1736
1778
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
@@ -2004,7 +2046,7 @@ function updateKeyframeInScript(script, animationId, percentage, properties, eas
|
|
|
2004
2046
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
2005
2047
|
if (!parsed) return script;
|
|
2006
2048
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
2007
|
-
if (!target) return script;
|
|
2049
|
+
if (!target || target.animation.hasUnresolvedKeyframes) return script;
|
|
2008
2050
|
const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
|
|
2009
2051
|
if (!kfPropNode) {
|
|
2010
2052
|
return updateMotionPathKeyframe(script, target, percentage, properties, ease) ?? script;
|
|
@@ -2072,7 +2114,7 @@ function locateWithKeyframes(script, animationId) {
|
|
|
2072
2114
|
if (!parsed) return null;
|
|
2073
2115
|
const convertedId = animationId.replace(/-from-|-fromTo-/, "-to-");
|
|
2074
2116
|
const target = parsed.located.find((l) => l.id === animationId) ?? parsed.located.find((l) => l.id === convertedId);
|
|
2075
|
-
if (!target) return null;
|
|
2117
|
+
if (!target || target.animation.hasUnresolvedKeyframes) return null;
|
|
2076
2118
|
const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
|
|
2077
2119
|
if (!kfPropNode || kfPropNode.value?.type !== "ObjectExpression") return null;
|
|
2078
2120
|
return { script, parsed, target, kfNode: kfPropNode.value };
|
|
@@ -2096,8 +2138,12 @@ function convertArrayKeyframesToObject(script, target) {
|
|
|
2096
2138
|
return `${JSON.stringify(`${timing.percentages[i]}%`)}: ${recordToCode(record)}`;
|
|
2097
2139
|
});
|
|
2098
2140
|
const ms = new MagicString(script);
|
|
2099
|
-
ms.overwrite(
|
|
2100
|
-
|
|
2141
|
+
ms.overwrite(
|
|
2142
|
+
kfPropNode.value.start,
|
|
2143
|
+
kfPropNode.value.end,
|
|
2144
|
+
`{ ${entries.join(", ")}, easeEach: "none" }`
|
|
2145
|
+
);
|
|
2146
|
+
if (findPropertyNode2(target.call.varsArg, "duration") === void 0) {
|
|
2101
2147
|
upsertProp(ms, target.call.varsArg, "duration", timing.totalDuration);
|
|
2102
2148
|
}
|
|
2103
2149
|
return ms.toString();
|
|
@@ -2107,7 +2153,7 @@ function ensureKeyframesNode(script, animationId) {
|
|
|
2107
2153
|
if (direct) return direct;
|
|
2108
2154
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
2109
2155
|
const target = parsed?.located.find((l) => l.id === animationId);
|
|
2110
|
-
if (!target) return null;
|
|
2156
|
+
if (!target || target.animation.hasUnresolvedKeyframes) return null;
|
|
2111
2157
|
const kfProp = findPropertyNode2(target.call.varsArg, "keyframes");
|
|
2112
2158
|
if (kfProp?.value?.type === "ArrayExpression") {
|
|
2113
2159
|
const normalized = convertArrayKeyframesToObject(script, target);
|
|
@@ -2209,7 +2255,7 @@ function removeKeyframeFromScript(script, animationId, percentage) {
|
|
|
2209
2255
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
2210
2256
|
if (!parsed) return script;
|
|
2211
2257
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
2212
|
-
if (!target) return script;
|
|
2258
|
+
if (!target || target.animation.hasUnresolvedKeyframes) return script;
|
|
2213
2259
|
const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
|
|
2214
2260
|
if (!kfPropNode) return script;
|
|
2215
2261
|
if (kfPropNode.value?.type === "ArrayExpression") {
|
|
@@ -2348,7 +2394,7 @@ function convertToKeyframesFromScript(script, animationId, resolvedFromValues, s
|
|
|
2348
2394
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
2349
2395
|
if (!target) return script;
|
|
2350
2396
|
const { animation, call } = target;
|
|
2351
|
-
if (animation
|
|
2397
|
+
if (authorsKeyframes(animation)) return script;
|
|
2352
2398
|
const isSet = call.method === "set";
|
|
2353
2399
|
const { fromProps, toProps } = resolveConversionProps(animation, resolvedFromValues);
|
|
2354
2400
|
const ms = new MagicString(script);
|
|
@@ -2564,6 +2610,7 @@ function splitIntoPropertyGroupsFromScript(script, animationId) {
|
|
|
2564
2610
|
const target = parsed.located.find((l) => l.id === animationId);
|
|
2565
2611
|
if (!target) return { script, ids: [animationId] };
|
|
2566
2612
|
const { animation } = target;
|
|
2613
|
+
if (animation.hasUnresolvedKeyframes) return { script, ids: [animationId] };
|
|
2567
2614
|
const allPropKeys = collectPropertyKeys(animation);
|
|
2568
2615
|
const groupProps = partitionPropertyGroups(allPropKeys);
|
|
2569
2616
|
if (groupProps.size <= 1) return { script, ids: [animationId] };
|
|
@@ -2884,8 +2931,8 @@ function computeForwardBaselines(matching, splitTime) {
|
|
|
2884
2931
|
const pos = typeof anim.position === "number" ? anim.position : 0;
|
|
2885
2932
|
const dur = anim.duration ?? 0;
|
|
2886
2933
|
const animEnd = pos + dur;
|
|
2887
|
-
if (anim
|
|
2888
|
-
const kfs = anim.keyframes
|
|
2934
|
+
if (authorsKeyframes(anim)) {
|
|
2935
|
+
const kfs = anim.keyframes?.keyframes ?? [];
|
|
2889
2936
|
if (pos >= splitTime) {
|
|
2890
2937
|
} else if (animEnd > splitTime) {
|
|
2891
2938
|
for (const kf of kfs) {
|
|
@@ -2946,17 +2993,22 @@ function buildSpanningSplit(result, anim, pos, dur, fromSource, ctx) {
|
|
|
2946
2993
|
extras: anim.extras
|
|
2947
2994
|
}).script;
|
|
2948
2995
|
}
|
|
2996
|
+
function applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors) {
|
|
2997
|
+
if (pos >= ctx.splitTime)
|
|
2998
|
+
return updateAnimationSelectorInScript(result, anim.id, ctx.newSelector);
|
|
2999
|
+
if (animEnd > ctx.splitTime) {
|
|
3000
|
+
skippedSelectors.push(`${ctx.originalSelector} (keyframes spanning split)`);
|
|
3001
|
+
} else if (anim.hasUnresolvedKeyframes) {
|
|
3002
|
+
skippedSelectors.push(`${ctx.originalSelector} (unreadable keyframes before split)`);
|
|
3003
|
+
}
|
|
3004
|
+
return result;
|
|
3005
|
+
}
|
|
2949
3006
|
function applyTweenSplit(result, anim, baselineBefore, ctx, skippedSelectors) {
|
|
2950
3007
|
const pos = typeof anim.position === "number" ? anim.position : 0;
|
|
2951
3008
|
const dur = anim.duration ?? 0;
|
|
2952
3009
|
const animEnd = pos + dur;
|
|
2953
|
-
if (anim
|
|
2954
|
-
|
|
2955
|
-
return updateAnimationSelectorInScript(result, anim.id, ctx.newSelector);
|
|
2956
|
-
if (animEnd > ctx.splitTime) {
|
|
2957
|
-
skippedSelectors.push(`${ctx.originalSelector} (keyframes spanning split)`);
|
|
2958
|
-
}
|
|
2959
|
-
return result;
|
|
3010
|
+
if (authorsKeyframes(anim)) {
|
|
3011
|
+
return applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors);
|
|
2960
3012
|
}
|
|
2961
3013
|
if (animEnd <= ctx.splitTime) return result;
|
|
2962
3014
|
if (pos >= ctx.splitTime)
|
|
@@ -3185,6 +3237,7 @@ export {
|
|
|
3185
3237
|
removePropertyFromAnimation,
|
|
3186
3238
|
replaceTweenWithKeyframesInScript,
|
|
3187
3239
|
resizeKeyframedTweenInScript,
|
|
3240
|
+
retimeClipTweensInScript,
|
|
3188
3241
|
scalePositionsInScript,
|
|
3189
3242
|
setArcPathInScript,
|
|
3190
3243
|
shiftPositionsInScript,
|