fix(studio): don't crash resizing an element whose keyframes were removed

commitWholePropertyOffset reduced the tween's keyframe list to find the
"nearest" stop without an initial value. When a to()/from() tween had been
collapsed to a zero-duration immediateRender hold (what removeAllKeyframes
leaves behind), synthesizeFlatTweenKeyframes correctly treats it as a
static hold and returns null, leaving an empty keyframe list — so the
reduce threw "Reduce of empty array with no initial value". Reachable by
resizing such an element with auto-keyframe recording off.

With no keyframe shape to preserve, persist the flat value directly via an
update-properties mutation instead.
This commit is contained in:
Miguel Angel Simon Sierra
2026-07-01 21:55:31 -07:00
parent 70606f840d
commit dff3634ea8
2 changed files with 38 additions and 3 deletions
@@ -43,9 +43,18 @@ export async function commitWholePropertyOffset(
typeof props[key] === "number" ? (props[key] as number) : (PROPERTY_DEFAULTS[key] ?? 0);
const kfs =
effectiveAnim.keyframes?.keyframes ??
synthesizeFlatTweenKeyframes(effectiveAnim)?.keyframes ??
[];
effectiveAnim.keyframes?.keyframes ?? synthesizeFlatTweenKeyframes(effectiveAnim)?.keyframes;
if (!kfs || kfs.length === 0) {
// A `to()`/`from()` collapsed to a zero-duration immediateRender hold (what
// removeAllKeyframesFromScript leaves behind) has no shape to preserve —
// just persist the flat value instead of replacing with an empty keyframe list.
await callbacks.commitMutation(
selection,
{ type: "update-properties", animationId: effectiveAnim.id, properties: newValues },
{ label, softReload: true },
);
return;
}
const nearest = kfs.reduce((best, kf) =>
Math.abs(kf.percentage - currentPct) < Math.abs(best.percentage - currentPct) ? kf : best,
);