fix(studio): keep gsapAnimations in sync with the keyframe cache

An ungrouped tween (mixed property groups classify to propertyGroup
undefined) fed keyframeCache but was skipped by every gsapAnimations
writer, so the collapsed row drew diamonds the expanded lanes had no
source animation to render. Drop the property-group gate at all three
writers; lane consumers already filter by group.

Also route the same-percentage merge in updateKeyframeCacheFromParsed
through deduplicateKeyframes so the easeAmbiguous rule has one owner.
This commit is contained in:
Miguel Angel Simon Sierra
2026-07-25 22:48:00 +02:00
parent e4d7bde64f
commit e34e529720
3 changed files with 41 additions and 32 deletions
@@ -329,9 +329,9 @@ export function useGsapAnimationsForElement(
// fallow-ignore-next-line complexity
useEffect(() => {
if (!elementId) return;
// No property-group filter: ungrouped tweens are recorded here as well.
const sourceAnimations = animations.filter(
(animation) =>
animation.propertyGroup && (animation.keyframes || synthesizeFlatTweenKeyframes(animation)),
(animation) => animation.keyframes || synthesizeFlatTweenKeyframes(animation),
);
if (sourceAnimations.length > 0)
writeGsapAnimationsForElement(sourceFile, elementId, sourceAnimations);
@@ -493,10 +493,10 @@ export function usePopulateKeyframeCacheForFile(
// group / descendant selectors, not just `#id`).
for (const id of resolveSelectorElementIds(anim.targetSelector, doc)) {
// kfData is already resolved (real keyframes OR a synthesized flat
// tween), so a grouped flat tween joins the store like a keyframed one.
if (anim.propertyGroup) {
sourceByElement.set(id, [...(sourceByElement.get(id) ?? []), anim]);
}
// tween), so a flat tween joins the store like a keyframed one. No
// property-group filter: this map must cover every tween the cache
// below records, or expanded lanes have nothing to render.
sourceByElement.set(id, [...(sourceByElement.get(id) ?? []), anim]);
const { elStart, elDuration } = resolveClipTimingBasis(id, sf, elements, domClipChildren);
const clipKeyframes = kfData.keyframes.map((kf) => {
const absTime = toAbsoluteTime(tweenPos, tweenDur, kf.percentage);