fix(studio): selectedGsapAnimations empty after gesture recording (#1646)

- include target in useGsapAnimationsForElement fetch key so a selection
  change triggers a re-fetch even at the same cache version
- add gsapCacheVersion to useDomEditPreviewSync deps so the selection
  re-syncs after every soft reload
- trim manualEditsDom.ts to 600 LOC (filesize compliance)

Fixes #1645
This commit is contained in:
Miguel Ángel
2026-06-22 14:06:53 -04:00
committed by GitHub
parent 4be81b4fb4
commit 82a5298058
5 changed files with 10 additions and 13 deletions
@@ -254,7 +254,7 @@ export const MotionPathOverlay = memo(function MotionPathOverlay({
ref: MotionNodeRef, ref: MotionNodeRef,
) => { ) => {
if (!interactive) return; if (!interactive) return;
if (e.button !== 0) return; // primary button only — right-click is the context menu if (e.button !== 0) return;
e.stopPropagation(); e.stopPropagation();
(e.target as Element).setPointerCapture(e.pointerId); (e.target as Element).setPointerCapture(e.pointerId);
dragRef.current = { dragRef.current = {
@@ -536,7 +536,6 @@ export function applyStudioRotationDraft(element: HTMLElement, rotation: { angle
} }
/* ── Seek reapply (position + motion) ────────────────────────────── */ /* ── Seek reapply (position + motion) ────────────────────────────── */
function queryStudioElements(doc: Document, attr: string): HTMLElement[] { function queryStudioElements(doc: Document, attr: string): HTMLElement[] {
const ctor = doc.defaultView?.HTMLElement; const ctor = doc.defaultView?.HTMLElement;
if (!ctor) return []; if (!ctor) return [];
@@ -584,7 +583,6 @@ function reapplyBoxSizes(doc: Document): void {
} }
} }
} }
function reapplyRotations(doc: Document): void { function reapplyRotations(doc: Document): void {
for (const el of queryStudioElements(doc, STUDIO_ROTATION_ATTR)) { for (const el of queryStudioElements(doc, STUDIO_ROTATION_ATTR)) {
const angle = Number.parseFloat(el.style.getPropertyValue(STUDIO_ROTATION_PROP)); const angle = Number.parseFloat(el.style.getPropertyValue(STUDIO_ROTATION_PROP));
@@ -28,6 +28,7 @@ interface UseDomEditPreviewSyncParams {
>; >;
openSourceForSelection?: (sourceFile: string, target: PatchTarget) => void; openSourceForSelection?: (sourceFile: string, target: PatchTarget) => void;
getSidebarTab?: () => SidebarTab; getSidebarTab?: () => SidebarTab;
gsapCacheVersion?: number;
} }
export function useDomEditPreviewSync({ export function useDomEditPreviewSync({
@@ -43,6 +44,7 @@ export function useDomEditPreviewSync({
applyStudioManualEditsToPreviewRef, applyStudioManualEditsToPreviewRef,
openSourceForSelection, openSourceForSelection,
getSidebarTab, getSidebarTab,
gsapCacheVersion,
}: UseDomEditPreviewSyncParams): void { }: UseDomEditPreviewSyncParams): void {
// Sync selection from preview document on load / refresh // Sync selection from preview document on load / refresh
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
@@ -102,6 +104,7 @@ export function useDomEditPreviewSync({
refreshPreviewDocumentVersion, refreshPreviewDocumentVersion,
syncPreviewHistoryHotkey, syncPreviewHistoryHotkey,
applyStudioManualEditsToPreviewRef, applyStudioManualEditsToPreviewRef,
gsapCacheVersion,
]); ]);
// Auto-reveal source when an element is selected while the Code tab is active. // Auto-reveal source when an element is selected while the Code tab is active.
@@ -242,6 +242,7 @@ export function useDomEditWiring({
applyStudioManualEditsToPreviewRef, applyStudioManualEditsToPreviewRef,
openSourceForSelection, openSourceForSelection,
getSidebarTab, getSidebarTab,
gsapCacheVersion,
}); });
return { return {
+5 -10
View File
@@ -137,7 +137,8 @@ export function useGsapAnimationsForElement(
const retryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); const retryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => { useEffect(() => {
const fetchKey = `${projectId}:${sourceFile}:${version}`; const targetKey = target?.id ?? target?.selector ?? "";
const fetchKey = `${projectId}:${sourceFile}:${version}:${targetKey}`;
if (fetchKey === lastFetchKeyRef.current) return; if (fetchKey === lastFetchKeyRef.current) return;
lastFetchKeyRef.current = fetchKey; lastFetchKeyRef.current = fetchKey;
@@ -366,9 +367,7 @@ export function usePopulateKeyframeCacheForFile(
const sf = sourceFile; const sf = sourceFile;
fetchParsedAnimations(projectId, sf).then((parsed) => { fetchParsedAnimations(projectId, sf).then((parsed) => {
if (!parsed) { if (!parsed) return;
return;
}
const { setKeyframeCache } = usePlayerStore.getState(); const { setKeyframeCache } = usePlayerStore.getState();
clearKeyframeCacheForFile(sf); clearKeyframeCacheForFile(sf);
const { elements } = usePlayerStore.getState(); const { elements } = usePlayerStore.getState();
@@ -376,13 +375,9 @@ export function usePopulateKeyframeCacheForFile(
for (const anim of parsed.animations) { for (const anim of parsed.animations) {
const id = extractIdFromSelector(anim.targetSelector); const id = extractIdFromSelector(anim.targetSelector);
if (!id) continue; if (!id) continue;
if (anim.hasUnresolvedKeyframes) { if (anim.hasUnresolvedKeyframes) continue;
continue;
}
const kfData = anim.keyframes ?? synthesizeFlatTweenKeyframes(anim); const kfData = anim.keyframes ?? synthesizeFlatTweenKeyframes(anim);
if (!kfData) { if (!kfData) continue;
continue;
}
const tweenPos = const tweenPos =
anim.resolvedStart ?? (typeof anim.position === "number" ? anim.position : 0); anim.resolvedStart ?? (typeof anim.position === "number" ? anim.position : 0);
const tweenDur = anim.duration ?? 1; const tweenDur = anim.duration ?? 1;