mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 23:00:03 +00:00
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:
@@ -7,6 +7,7 @@ interface CompositionsTabProps {
|
||||
onSelect: (comp: string) => void;
|
||||
onRenderComposition?: (comp: string) => void;
|
||||
isRendering?: boolean;
|
||||
lintFindingsByFile?: Map<string, { count: number; messages: string[] }>;
|
||||
}
|
||||
|
||||
const DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
|
||||
@@ -111,6 +112,7 @@ function CompCard({
|
||||
onSelect,
|
||||
onRender,
|
||||
isRendering,
|
||||
lintInfo,
|
||||
}: {
|
||||
projectId: string;
|
||||
comp: string;
|
||||
@@ -118,6 +120,7 @@ function CompCard({
|
||||
onSelect: () => void;
|
||||
onRender?: () => void;
|
||||
isRendering?: boolean;
|
||||
lintInfo?: { count: number; messages: string[] };
|
||||
}) {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const [stageSize, setStageSize] = useState(DEFAULT_PREVIEW_STAGE);
|
||||
@@ -215,8 +218,16 @@ function CompCard({
|
||||
tabIndex={-1}
|
||||
/>
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<span className="text-[11px] font-medium text-neutral-300 truncate block">{name}</span>
|
||||
<div
|
||||
className="min-w-0 flex-1"
|
||||
title={lintInfo && lintInfo.count > 0 ? lintInfo.messages.join("\n") : undefined}
|
||||
>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-[11px] font-medium text-neutral-300 truncate">{name}</span>
|
||||
{lintInfo && lintInfo.count > 0 && (
|
||||
<span className="flex-shrink-0 w-2 h-2 rounded-full bg-amber-400" />
|
||||
)}
|
||||
</div>
|
||||
<span className="text-[9px] text-neutral-600 truncate block">{comp}</span>
|
||||
</div>
|
||||
{onRender && (
|
||||
@@ -262,6 +273,7 @@ export const CompositionsTab = memo(function CompositionsTab({
|
||||
onSelect,
|
||||
onRenderComposition,
|
||||
isRendering,
|
||||
lintFindingsByFile,
|
||||
}: CompositionsTabProps) {
|
||||
if (compositions.length === 0) {
|
||||
return (
|
||||
@@ -282,6 +294,7 @@ export const CompositionsTab = memo(function CompositionsTab({
|
||||
onSelect={() => onSelect(comp)}
|
||||
onRender={onRenderComposition ? () => onRenderComposition(comp) : undefined}
|
||||
isRendering={isRendering}
|
||||
lintInfo={lintFindingsByFile?.get(comp)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -54,6 +54,8 @@ interface LeftSidebarProps {
|
||||
isRendering?: boolean;
|
||||
onLint?: () => void;
|
||||
linting?: boolean;
|
||||
lintFindingCount?: number;
|
||||
lintFindingsByFile?: Map<string, { count: number; messages: string[] }>;
|
||||
onToggleCollapse?: () => void;
|
||||
onAddBlock?: (blockName: string) => void;
|
||||
onPreviewBlock?: (preview: BlockPreviewInfo | null) => void;
|
||||
@@ -84,6 +86,8 @@ export const LeftSidebar = memo(
|
||||
isRendering,
|
||||
onLint,
|
||||
linting,
|
||||
lintFindingCount,
|
||||
lintFindingsByFile,
|
||||
onToggleCollapse,
|
||||
onAddBlock,
|
||||
onPreviewBlock,
|
||||
@@ -216,6 +220,7 @@ export const LeftSidebar = memo(
|
||||
onSelect={onSelectComposition}
|
||||
onRenderComposition={onRenderComposition}
|
||||
isRendering={isRendering}
|
||||
lintFindingsByFile={lintFindingsByFile}
|
||||
/>
|
||||
)}
|
||||
{tab === "assets" && (
|
||||
@@ -242,6 +247,7 @@ export const LeftSidebar = memo(
|
||||
onDuplicateFile={onDuplicateFile}
|
||||
onMoveFile={onMoveFile}
|
||||
onImportFiles={onImportFiles}
|
||||
lintFindingsByFile={lintFindingsByFile}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -279,6 +285,11 @@ export const LeftSidebar = memo(
|
||||
<path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11" />
|
||||
</svg>
|
||||
{linting ? "Linting…" : "Lint"}
|
||||
{!linting && lintFindingCount != null && lintFindingCount > 0 && (
|
||||
<span className="ml-1 min-w-[16px] rounded-full bg-amber-500/20 px-1 text-[9px] font-bold text-amber-400">
|
||||
{lintFindingCount}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user