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
@@ -18,12 +18,16 @@ import {
parseNumericOrString,
BOOLEAN_PROPS,
} from "./AnimationCardParts";
import type { AnimationKeyframeTarget } from "../../hooks/gsapTweenSynth";
interface AnimationCardProps extends GsapAnimationEditCallbacks {
animation: GsapAnimation;
defaultExpanded: boolean;
flat?: boolean;
focusedSegment?: { tweenPercentage: number } | null;
focusedSegment?: {
tweenPercentage: number;
collidingAnimationTargets?: AnimationKeyframeTarget[];
} | null;
onFocusSegmentConsumed?: () => void;
}
@@ -47,6 +51,7 @@ export const AnimationCard = memo(function AnimationCard({
onSetArcPath,
onUpdateArcSegment,
onUpdateKeyframeEase,
onUpdateSegmentEase,
onSetAllKeyframeEases,
onUnroll,
}: AnimationCardProps) {
@@ -54,6 +59,9 @@ export const AnimationCard = memo(function AnimationCard({
const [addingProp, setAddingProp] = useState(false);
const [addingFromProp, setAddingFromProp] = useState(false);
const [expandedKfPct, setExpandedKfPct] = useState<number | null>(null);
const [focusedCollidingAnimationTargets, setFocusedCollidingAnimationTargets] = useState<
AnimationKeyframeTarget[] | undefined
>();
const cardRef = useRef<HTMLDivElement>(null);
const pendingAutoScrollRef = useRef(false);
@@ -62,6 +70,7 @@ export const AnimationCard = memo(function AnimationCard({
setExpanded(true);
pendingAutoScrollRef.current = true;
setExpandedKfPct(focusedSegment.tweenPercentage);
setFocusedCollidingAnimationTargets(focusedSegment.collidingAnimationTargets);
onFocusSegmentConsumed?.();
}, [focusedSegment, onFocusSegmentConsumed]);
@@ -288,9 +297,21 @@ export const AnimationCard = memo(function AnimationCard({
keyframes={animation.keyframes.keyframes}
globalEase={animation.keyframes.easeEach ?? animation.ease ?? "none"}
expandedPct={expandedKfPct}
onToggle={setExpandedKfPct}
collidingAnimationTargets={focusedCollidingAnimationTargets}
onToggle={(pct) => {
setExpandedKfPct(pct);
setFocusedCollidingAnimationTargets(undefined);
}}
onEaseCommit={(pct, ease) => {
onUpdateKeyframeEase(animation.id, pct, ease);
if (
focusedCollidingAnimationTargets &&
focusedCollidingAnimationTargets.length > 1 &&
onUpdateSegmentEase
) {
onUpdateSegmentEase(focusedCollidingAnimationTargets, ease);
} else {
onUpdateKeyframeEase(animation.id, pct, ease);
}
trackStudioSegmentEaseEdit({ action: "commit", ease });
}}
onApplyAll={