feat(studio): bulk-edit easing for merged keyframes

This commit is contained in:
Miguel Angel Simon Sierra
2026-07-29 03:39:51 +02:00
parent 7482c22d82
commit 10d45def05
22 changed files with 687 additions and 65 deletions
@@ -686,12 +686,12 @@ describe("TimelineClipDiamonds", () => {
return { host, root };
};
it("hides the inline ease button on a colliding merged segment", () => {
// The 50->100 segment ends on a keyframe shared by two animations, so one
// button cannot honestly stand for the several curves that meet there. Only
// the unambiguous 0->50 segment keeps its button.
it("shows the inline ease button on a colliding merged segment (bulk edit)", () => {
// Both segments (0->50, 50->100) render their ease button; the 50->100
// segment ends on a keyframe shared by two animations and the button now
// bulk-edits both rather than being hidden.
const { host, root } = renderSegmentLane(true);
expect(host.querySelectorAll("[data-keyframe-ease-segment]").length).toBe(1);
expect(host.querySelectorAll("[data-keyframe-ease-segment]").length).toBe(2);
act(() => root.unmount());
});
@@ -90,13 +90,13 @@ export function TimelineDiamondConnectors({
/**
* The ease control targets one segment, so it needs the keyframe's own
* animationId/tweenPercentage. On a merged inline row it is hidden where two
* source animations collide at this percentage (one button cannot honestly
* stand for several curves) or the keyframe has no source animation id
* (runtime-scanned) so there is no tween to target.
* animationId. A merged keyframe now shows one too: the editor edits every
* colliding tween together, so one button standing for several curves is
* honest. Only a keyframe with no source animation id (runtime-scanned) is left
* out, because there is no tween to target.
*/
function showsEaseControl(kf: TimelineDiamondKeyframe): boolean {
return (kf.collidingAnimationTargets?.length ?? 0) <= 1 && kf.animationId !== undefined;
return kf.animationId !== undefined;
}
/**