fix(studio): keyframe bug fixes — gate delete hooks, fix value corruption, gesture recording (#1314)

- Gate stripStudioEditsFromTarget/bakeVisibilityOnDelete behind a
  stripStudioEdits flag on the delete mutation type so they only fire on
  user-initiated deletes, not on internal delete-then-recreate drags.

- Add bakeVisibilityOnDelete to the remove-all-keyframes handler so
  elements with CSS opacity:0 stay visible after collapsing keyframes.

- Fix integer rounding in readAllAnimatedProperties: use 3-decimal
  precision for visual properties (opacity, scale, rotation) instead of
  Math.round which corrupted mid-fade values to 0.

- Guard VISUAL_BASELINE against cross-tween contamination by querying
  __timelines for properties animated by other tweens on the same element.

- Harden bakeVisibilityOnDelete: reverse-scan keyframes for the last one
  containing opacity, guard against relative values (+=/-=/*=), and add
  Number.isFinite check.

- Fix falsy-zero doubling in drag commit: replace || fallback with
  Number.isFinite so a base GSAP position of 0 is correctly preserved.

- Fix gesture recording sign inversion: remove pointerElementOffset
  subtraction from dx/dy formula and instead apply it once to basePosition
  so the element center tracks the pointer.

- Fix TypeScript build errors in gsapSoftReload.ts (6 double-casts).

- Strip all diagnostic logs from production code.
This commit is contained in:
Miguel Ángel
2026-06-10 18:53:06 -04:00
committed by GitHub
parent 3a72aa528d
commit f0b499b582
38 changed files with 1641 additions and 821 deletions
@@ -142,53 +142,54 @@ export const RenderQueueItem = memo(function RenderQueueItem({
)}
</div>
{/* Actions */}
{hovered && (
<div className="flex items-center gap-1 flex-shrink-0">
{isComplete && (
<button
onClick={handleDownload}
className="p-1 rounded text-panel-text-4 hover:text-panel-accent transition-colors"
title="Download"
>
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
</button>
)}
<button
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
className="p-1 rounded text-panel-text-4 hover:text-red-400 transition-colors"
title="Remove"
{/* Actions — always visible to prevent layout shifts */}
<div className="flex items-center gap-1 flex-shrink-0">
<button
onClick={isComplete ? handleDownload : undefined}
className={`p-1 rounded transition-colors ${
isComplete
? "text-panel-text-5 hover:text-panel-accent"
: "text-panel-text-5/30 pointer-events-none"
}`}
title={isComplete ? "Download" : "Rendering..."}
disabled={!isComplete}
>
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
>
<path d="M18 6L6 18M6 6l12 12" />
</svg>
</button>
</div>
)}
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" y1="15" x2="12" y2="3" />
</svg>
</button>
<button
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
className="p-1 rounded text-panel-text-5 hover:text-red-400 transition-colors"
title="Remove"
>
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
>
<path d="M18 6L6 18M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
);