refactor(studio): extract shared timeline components and deduplicate code (#1329)

Extract shared utilities to reduce duplication across timeline components:

- PlayheadIndicator: shared playhead rendering (was duplicated in
  TimelineCanvas and TimelineEditorNotice)
- useContextMenuDismiss: outside-click/Escape dismiss pattern (was
  duplicated in ClipContextMenu and KeyframeDiamondContextMenu)
- TimelineCallbacks: shared callback interfaces for drop and edit
  operations (was duplicated in NLELayout and Timeline props)
- useTimelineZoom: consolidated zoom store selectors
- timelineElementSplit: shared canSplitElement, buildPatchTarget, and
  readFileContent utilities
- gsapParser.test-helpers: shared test utilities for parser specs
This commit is contained in:
Miguel Ángel
2026-06-10 23:45:03 -04:00
committed by GitHub
parent 06426b5014
commit ab08260201
12 changed files with 373 additions and 157 deletions
@@ -1,25 +1,13 @@
// fallow-ignore-file clone-families
import { useCallback, useState, type RefObject } from "react";
import { TIMELINE_ASSET_MIME, TIMELINE_BLOCK_MIME } from "../../utils/timelineAssetDrop";
import { TRACK_H, resolveTimelineAssetDrop } from "./timelineLayout";
import type { TimelineDropCallbacks } from "./timelineCallbacks";
interface UseTimelineAssetDropOptions {
interface UseTimelineAssetDropOptions extends TimelineDropCallbacks {
scrollRef: RefObject<HTMLDivElement | null>;
ppsRef: RefObject<number>;
durationRef: RefObject<number>;
trackOrderRef: RefObject<number[]>;
onFileDrop?: (
files: File[],
placement?: { start: number; track: number },
) => Promise<void> | void;
onAssetDrop?: (
assetPath: string,
placement: { start: number; track: number },
) => Promise<void> | void;
onBlockDrop?: (
blockName: string,
placement: { start: number; track: number },
) => Promise<void> | void;
}
export function useTimelineAssetDrop({