@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
|
@@ -22,11 +22,17 @@ type PositionWrite = Pick<GsapAnimation, "propertyGroup" | "properties" | "fromP
|
|
|
22
22
|
declare function isXYPositionWrite(a: PositionWrite): boolean;
|
|
23
23
|
declare function classifyPropertyGroup(prop: string): PropertyGroupName;
|
|
24
24
|
declare function classifyTweenPropertyGroup(properties: Record<string, unknown>): PropertyGroupName | undefined;
|
|
25
|
+
interface HoldScope {
|
|
26
|
+
touched: (animation: GsapAnimation) => boolean;
|
|
27
|
+
held: (selector: string) => ReadonlyMap<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
/** The tweens an edit touched (not in `previous`; none without it), and what the script's holds already pin. */
|
|
30
|
+
declare function holdScope(before: readonly GsapAnimation[], previous: readonly GsapAnimation[] | null): HoldScope;
|
|
25
31
|
/**
|
|
26
|
-
* What a Studio hold pins from t=0
|
|
27
|
-
*
|
|
32
|
+
* What a Studio hold pins from t=0: a keyframed tween's 0% position props before a later start, and the position and
|
|
33
|
+
* size of a lone key (GSAP renders none) only where this edit made it or a hold already pins it, minus earlier tweens.
|
|
28
34
|
*/
|
|
29
|
-
declare function
|
|
35
|
+
declare function keyframeHoldForAnimation(animation: GsapAnimation, animations: readonly GsapAnimation[], scope: HoldScope): Record<string, number> | null;
|
|
30
36
|
declare const SUPPORTED_EASES: string[];
|
|
31
37
|
|
|
32
38
|
/**
|
|
@@ -216,4 +222,4 @@ declare function gsapAnimationsToKeyframes(animations: GsapAnimation[], elementS
|
|
|
216
222
|
skipBaseSet?: boolean;
|
|
217
223
|
}): Keyframe[];
|
|
218
224
|
|
|
219
|
-
export { type ArcPathConfig as A, BUILTIN_VAR_KEYS as B, DROPPED_VAR_KEYS as D, EXTRAS_KEYS as E, type
|
|
225
|
+
export { type ArcPathConfig as A, BUILTIN_VAR_KEYS as B, keyframeHoldForAnimation as C, DROPPED_VAR_KEYS as D, EXTRAS_KEYS as E, type GsapAnimation as G, type HoldScope as H, type KeyframeEditability as K, type MotionPathShape as M, type ParsedGsap as P, SUPPORTED_EASES as S, type ArcPathSegment as a, type GsapKeyframeFormat as b, type GsapKeyframesData as c, type GsapMethod as d, type GsapPercentageKeyframe as e, PROPERTY_GROUPS as f, type PropertyGroupName as g, SUPPORTED_PROPS as h, classifyPropertyGroup as i, classifyTweenPropertyGroup as j, getAnimationsForElementId as k, gsapAnimationsToKeyframes as l, keyframesToGsapAnimations as m, type GsapProvenance as n, type GsapProvenanceKind as o, buildArcPath as p, editabilityForProvenance 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, holdScope as x, isTweenConfigKey as y, isXYPositionWrite as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as GsapAnimation, A as ArcPathConfig, r as SplitAnimationsOptions, t as SplitAnimationsResult, a as ArcPathSegment } from './gsapSerialize-WJrRO8uT.js';
|
|
2
2
|
import './types-Ejqndkej.js';
|
|
3
3
|
|
|
4
4
|
type TweenTarget = Pick<GsapAnimation, "targetSelector" | "hasPartialSelector">;
|
|
@@ -179,7 +179,10 @@ declare function addMotionPathToScript(script: string, targetSelector: string, p
|
|
|
179
179
|
};
|
|
180
180
|
declare function removeArcPathFromScript(script: string, animationId: string): string;
|
|
181
181
|
/** Acorn-native, byte-preserving hold synchronization used after mutations. */
|
|
182
|
-
declare function syncPositionHoldsBeforeKeyframes(script: string): string;
|
|
182
|
+
declare function syncPositionHoldsBeforeKeyframes(script: string, previous?: string): string;
|
|
183
|
+
/** GSAP 3.15 stretches a keyframe tween that stops short of 100% on its first render, unlike once played:
|
|
184
|
+
* each tween this mutation wrote or edited ends on its last key instead. Tweens it left alone keep their tail. */
|
|
185
|
+
declare function trimTrailingKeyframeSpans(previous: string, script: string): string;
|
|
183
186
|
declare function splitAnimationsInScript(script: string, opts: SplitAnimationsOptions): SplitAnimationsResult;
|
|
184
187
|
type UnrollElement = {
|
|
185
188
|
selector: string;
|
|
@@ -197,4 +200,4 @@ type UnrollElement = {
|
|
|
197
200
|
*/
|
|
198
201
|
declare function unrollDynamicAnimations(script: string, animationId: string, elements: UnrollElement[]): string;
|
|
199
202
|
|
|
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 };
|
|
203
|
+
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, trimTrailingKeyframeSpans, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript, updateMotionPathPointInScript };
|
package/dist/gsapWriterAcorn.js
CHANGED
|
@@ -57,23 +57,43 @@ function knownStart(animation) {
|
|
|
57
57
|
if (animation.resolvedStart !== void 0) return animation.resolvedStart;
|
|
58
58
|
return typeof animation.position === "number" ? animation.position : void 0;
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
var tweenSignature = (a) => JSON.stringify([a.targetSelector, a.method, a.position, a.duration, a.properties, a.keyframes]);
|
|
61
|
+
function holdScope(before, previous) {
|
|
62
|
+
const kept = new Set(previous?.map(tweenSignature));
|
|
63
|
+
const held = /* @__PURE__ */ new Map();
|
|
64
|
+
for (const a of before.filter((b) => b.method === "set" && b.properties?.data === "hf-hold")) {
|
|
65
|
+
const props = held.get(a.targetSelector) ?? /* @__PURE__ */ new Map();
|
|
66
|
+
for (const [property, value] of Object.entries(a.properties)) props.set(property, value);
|
|
67
|
+
held.set(a.targetSelector, props);
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
touched: (a) => previous !== null && !kept.has(tweenSignature(a)),
|
|
71
|
+
held: (selector) => held.get(selector) ?? /* @__PURE__ */ new Map()
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function keyframeHoldForAnimation(animation, animations, scope) {
|
|
61
75
|
if (!animation.keyframes) return null;
|
|
62
|
-
const start = knownStart(animation)
|
|
63
|
-
|
|
76
|
+
const start = knownStart(animation);
|
|
77
|
+
const lone = animation.keyframes.keyframes.length === 1;
|
|
78
|
+
if (start === void 0 || !(start > 1e-3) && !lone) return null;
|
|
64
79
|
const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
|
|
65
80
|
if (!atStart) return null;
|
|
66
81
|
const earlier = animations.filter((other) => {
|
|
67
82
|
const otherStart = knownStart(other);
|
|
68
83
|
return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
|
|
69
84
|
});
|
|
70
|
-
const
|
|
85
|
+
const touched = scope.touched(animation);
|
|
86
|
+
const pinned = scope.held(animation.targetSelector);
|
|
87
|
+
const kept = (property, value) => touched ? pinned.has(property) : pinned.get(property) === value;
|
|
88
|
+
const pins = (group, property, value) => group === "position" && start > 1e-3 || (group === "position" || group === "size") && (lone && touched || kept(property, value));
|
|
89
|
+
const hold = {};
|
|
71
90
|
for (const [property, value] of Object.entries(atStart.properties)) {
|
|
72
|
-
if (classifyPropertyGroup(property)
|
|
91
|
+
if (!pins(classifyPropertyGroup(property), property, value) || typeof value !== "number")
|
|
92
|
+
continue;
|
|
73
93
|
if (earlier.some((other) => writesProperty(other, property))) continue;
|
|
74
|
-
|
|
94
|
+
hold[property] = value;
|
|
75
95
|
}
|
|
76
|
-
return Object.keys(
|
|
96
|
+
return Object.keys(hold).length > 0 ? hold : null;
|
|
77
97
|
}
|
|
78
98
|
|
|
79
99
|
// src/gsapSerialize.ts
|
|
@@ -118,6 +138,10 @@ function buildArcPath(coords, curviness, autoRotate, isCubic) {
|
|
|
118
138
|
}
|
|
119
139
|
return { arcPath: { enabled: true, autoRotate, segments }, waypoints };
|
|
120
140
|
}
|
|
141
|
+
function plainPercentKey(percentage) {
|
|
142
|
+
const text = Math.abs(percentage) < 1e-6 ? percentage.toFixed(20).replace(/\.?0+$/, "") : String(percentage);
|
|
143
|
+
return `${text}%`;
|
|
144
|
+
}
|
|
121
145
|
var CSS_IDENTITY = {
|
|
122
146
|
opacity: 1,
|
|
123
147
|
autoAlpha: 1,
|
|
@@ -1067,9 +1091,6 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
|
|
|
1067
1091
|
properties[key] = val;
|
|
1068
1092
|
}
|
|
1069
1093
|
}
|
|
1070
|
-
if (keyframesData && typeof vars.easeEach === "string") {
|
|
1071
|
-
keyframesData.easeEach = vars.easeEach;
|
|
1072
|
-
}
|
|
1073
1094
|
if (motionPathResult) {
|
|
1074
1095
|
const { waypoints } = motionPathResult;
|
|
1075
1096
|
if (!keyframesData) {
|
|
@@ -2135,7 +2156,7 @@ function convertArrayKeyframesToObject(script, target) {
|
|
|
2135
2156
|
if (!timing) return script;
|
|
2136
2157
|
const entries = els.map((el, i) => {
|
|
2137
2158
|
const { duration: _duration, ...record } = records[i];
|
|
2138
|
-
return `${JSON.stringify(
|
|
2159
|
+
return `${JSON.stringify(plainPercentKey(timing.percentages[i]))}: ${recordToCode(record)}`;
|
|
2139
2160
|
});
|
|
2140
2161
|
const ms = new MagicString(script);
|
|
2141
2162
|
ms.overwrite(
|
|
@@ -2197,7 +2218,13 @@ function addKeyframeToScript(script, animationId, percentage, properties, ease,
|
|
|
2197
2218
|
ms.overwrite(existing.prop.value.start, existing.prop.value.end, recordToCode(targetRecord));
|
|
2198
2219
|
}
|
|
2199
2220
|
} else {
|
|
2200
|
-
insertNewKeyframe(
|
|
2221
|
+
insertNewKeyframe(
|
|
2222
|
+
ms,
|
|
2223
|
+
kfNode,
|
|
2224
|
+
percentage,
|
|
2225
|
+
plainPercentKey(percentage),
|
|
2226
|
+
recordToCode(targetRecord)
|
|
2227
|
+
);
|
|
2201
2228
|
}
|
|
2202
2229
|
for (const [prop, rec] of [...endpointOverwrites, ...backfillOverwrites]) {
|
|
2203
2230
|
ms.overwrite(prop.value.start, prop.value.end, recordToCode(rec));
|
|
@@ -2296,7 +2323,12 @@ function moveKeyframeInScript(script, animationId, fromPercentage, toPercentage)
|
|
|
2296
2323
|
}
|
|
2297
2324
|
entries.push({ pct: toPercentage, record: valueNodeToRecord(match.prop.value, src) });
|
|
2298
2325
|
entries.sort((a, b) => a.pct - b.pct);
|
|
2299
|
-
const
|
|
2326
|
+
const pctProps = new Set(percentagePropsOf(kfNode));
|
|
2327
|
+
const kept = (kfNode.properties ?? []).filter((p) => !pctProps.has(p)).map((p) => src.slice(p.start, p.end));
|
|
2328
|
+
const body = [
|
|
2329
|
+
...entries.map((e) => `${JSON.stringify(plainPercentKey(e.pct))}: ${recordToCode(e.record)}`),
|
|
2330
|
+
...kept
|
|
2331
|
+
].join(", ");
|
|
2300
2332
|
const ms = new MagicString(src);
|
|
2301
2333
|
ms.overwrite(kfNode.start, kfNode.end, `{ ${body} }`);
|
|
2302
2334
|
return ms.toString();
|
|
@@ -2315,7 +2347,7 @@ function resizeKeyframedTweenInScript(script, animationId, newPosition, newDurat
|
|
|
2315
2347
|
}
|
|
2316
2348
|
const ms = new MagicString(src);
|
|
2317
2349
|
for (const { keyNode, to } of edits) {
|
|
2318
|
-
ms.overwrite(keyNode.start, keyNode.end, JSON.stringify(
|
|
2350
|
+
ms.overwrite(keyNode.start, keyNode.end, JSON.stringify(plainPercentKey(to)));
|
|
2319
2351
|
}
|
|
2320
2352
|
overwritePosition(ms, target.call, newPosition);
|
|
2321
2353
|
upsertProp(ms, target.call.varsArg, "duration", newDuration);
|
|
@@ -2433,7 +2465,7 @@ function buildKeyframeObjectCode(keyframes, easeEach) {
|
|
|
2433
2465
|
const props = Object.entries(kf.properties).map(([k, v]) => `${safeKey(k)}: ${valueToCode(v)}`);
|
|
2434
2466
|
if (kf.ease) props.push(`ease: ${valueToCode(kf.ease)}`);
|
|
2435
2467
|
if (kf.auto) props.push(`_auto: 1`);
|
|
2436
|
-
return `${JSON.stringify(
|
|
2468
|
+
return `${JSON.stringify(plainPercentKey(kf.percentage))}: { ${props.join(", ")} }`;
|
|
2437
2469
|
});
|
|
2438
2470
|
if (easeEach) entries.push(`easeEach: ${valueToCode(easeEach)}`);
|
|
2439
2471
|
return `{ ${entries.join(", ")} }`;
|
|
@@ -2587,7 +2619,8 @@ function addGroupAnimToScript(script, anim, propSet) {
|
|
|
2587
2619
|
pos,
|
|
2588
2620
|
anim.duration ?? 0.5,
|
|
2589
2621
|
groupKeyframes,
|
|
2590
|
-
anim.keyframes.
|
|
2622
|
+
anim.keyframes.ease ?? anim.ease,
|
|
2623
|
+
anim.keyframes.easeEach
|
|
2591
2624
|
);
|
|
2592
2625
|
}
|
|
2593
2626
|
const groupProperties = filterGroupProperties(anim.properties, propSet);
|
|
@@ -2906,15 +2939,20 @@ function removeStudioHoldSets(script, parsed) {
|
|
|
2906
2939
|
for (const hold of staleHolds) removeCallFromMagicString(ms, hold.call, script);
|
|
2907
2940
|
return ms.toString();
|
|
2908
2941
|
}
|
|
2909
|
-
function syncPositionHoldsBeforeKeyframes(script) {
|
|
2942
|
+
function syncPositionHoldsBeforeKeyframes(script, previous) {
|
|
2910
2943
|
const parsed = parseGsapScriptAcornForWrite(script);
|
|
2911
2944
|
if (!parsed) return script;
|
|
2945
|
+
const tweensOf = (text) => parseGsapScriptAcornForWrite(text)?.located.map((entry) => entry.animation) ?? null;
|
|
2946
|
+
const scope = holdScope(
|
|
2947
|
+
parsed.located.map((entry) => entry.animation),
|
|
2948
|
+
previous === void 0 ? null : tweensOf(previous)
|
|
2949
|
+
);
|
|
2912
2950
|
let result = removeStudioHoldSets(script, parsed);
|
|
2913
2951
|
const current = parseGsapScriptAcornForWrite(result);
|
|
2914
2952
|
if (!current) return result;
|
|
2915
2953
|
const animations = current.located.map((entry) => entry.animation);
|
|
2916
2954
|
for (const animation of animations) {
|
|
2917
|
-
const position =
|
|
2955
|
+
const position = keyframeHoldForAnimation(animation, animations, scope);
|
|
2918
2956
|
if (!position) continue;
|
|
2919
2957
|
result = insertInheritedStateSetInScript(result, animation.targetSelector, 0, {
|
|
2920
2958
|
...position,
|
|
@@ -2923,6 +2961,62 @@ function syncPositionHoldsBeforeKeyframes(script) {
|
|
|
2923
2961
|
}
|
|
2924
2962
|
return result;
|
|
2925
2963
|
}
|
|
2964
|
+
var roundPct = (pct) => Math.round(pct * 1e3) / 1e3;
|
|
2965
|
+
var LINEAR_RUN = /* @__PURE__ */ new Set(["none", "linear"]);
|
|
2966
|
+
var PLACED_BY_TIMELINE = /\.(?:add|addLabel|addPause|call|repeat|yoyo|duration|timeScale)\s*\(|\b(?:repeat|yoyo)\s*:/;
|
|
2967
|
+
function linearPercentageKeys(animation) {
|
|
2968
|
+
const data = animation.keyframes;
|
|
2969
|
+
if (data?.format !== "percentage" || data.fromMotionPath || animation.arcPath) return null;
|
|
2970
|
+
if (animation.durationUnresolved || !LINEAR_RUN.has(animation.ease || "none")) return null;
|
|
2971
|
+
return data.keyframes;
|
|
2972
|
+
}
|
|
2973
|
+
var loops = (animation) => Boolean(animation.extras?.repeat || animation.extras?.yoyo);
|
|
2974
|
+
function trimmableKeyframes(animation) {
|
|
2975
|
+
const keyframes = loops(animation) ? null : linearPercentageKeys(animation);
|
|
2976
|
+
const { duration, position } = animation;
|
|
2977
|
+
if (!keyframes || typeof position !== "number" || typeof duration !== "number") return null;
|
|
2978
|
+
return duration > 0 ? { keyframes, duration, position } : null;
|
|
2979
|
+
}
|
|
2980
|
+
function trailingSpanTrim(animation) {
|
|
2981
|
+
const tween = trimmableKeyframes(animation);
|
|
2982
|
+
if (!tween) return null;
|
|
2983
|
+
const last = Math.max(...tween.keyframes.map((keyframe) => keyframe.percentage));
|
|
2984
|
+
if (tween.keyframes.length < 2 || !(last > 0) || last >= 99.999) return null;
|
|
2985
|
+
return {
|
|
2986
|
+
position: tween.position,
|
|
2987
|
+
duration: Math.round(tween.duration * last * 10) / 1e3,
|
|
2988
|
+
pctRemap: tween.keyframes.map(({ percentage: from }) => ({
|
|
2989
|
+
from,
|
|
2990
|
+
to: roundPct(from / last * 100)
|
|
2991
|
+
}))
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
function trimTrailingKeyframeSpans(previous, script) {
|
|
2995
|
+
if (script === previous) return script;
|
|
2996
|
+
const located = parseGsapScriptAcornForWrite(script)?.located ?? [];
|
|
2997
|
+
const placedAfter = ({ animation: a }) => !a.global && (a.implicitPosition || typeof a.position !== "number");
|
|
2998
|
+
if (PLACED_BY_TIMELINE.test(script) || located.some(placedAfter)) return script;
|
|
2999
|
+
const trims = located.flatMap((entry) => {
|
|
3000
|
+
const trim = trailingSpanTrim(entry.animation);
|
|
3001
|
+
return trim ? [{ entry, trim }] : [];
|
|
3002
|
+
});
|
|
3003
|
+
if (!trims.length) return script;
|
|
3004
|
+
const source = (text, { call }) => `${call.method}${text.slice(call.node.arguments[0]?.start, call.node.end)}`;
|
|
3005
|
+
const previousTweens = parseGsapScriptAcornForWrite(previous)?.located ?? [];
|
|
3006
|
+
const untouched = new Set(previousTweens.map((entry) => source(previous, entry)));
|
|
3007
|
+
let result = script;
|
|
3008
|
+
for (const { entry, trim } of trims) {
|
|
3009
|
+
if (untouched.has(source(script, entry))) continue;
|
|
3010
|
+
result = resizeKeyframedTweenInScript(
|
|
3011
|
+
result,
|
|
3012
|
+
entry.id,
|
|
3013
|
+
trim.position,
|
|
3014
|
+
trim.duration,
|
|
3015
|
+
trim.pctRemap
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
return result;
|
|
3019
|
+
}
|
|
2926
3020
|
function computeForwardBaselines(matching, splitTime) {
|
|
2927
3021
|
const before = [];
|
|
2928
3022
|
const acc = {};
|
|
@@ -3244,6 +3338,7 @@ export {
|
|
|
3244
3338
|
splitAnimationsInScript,
|
|
3245
3339
|
splitIntoPropertyGroupsFromScript,
|
|
3246
3340
|
syncPositionHoldsBeforeKeyframes,
|
|
3341
|
+
trimTrailingKeyframeSpans,
|
|
3247
3342
|
unrollDynamicAnimations,
|
|
3248
3343
|
updateAnimationInScript,
|
|
3249
3344
|
updateArcSegmentInScript,
|