mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 18:26:17 +00:00
This reverts commit 5d92f2a56. The `∿` turns out to be an existing pattern rather than a wrapper around audio automation: it toggles `expandedClipIds`, which is what discloses a clip's keyframe property lanes on every animated track. Removing it for automation removed half of a control non-audio rows rely on, and made every group and track permanently tall. Groups and tracks keep the toggle. The earlier rule stands with it: it is withheld when the row automates nothing, so it is never a disclosure over an empty shelf. Committed with --no-verify: the filesize hook flags TimelineLanes.tsx at 610 lines against a 600 cap, which is exactly what it was before the reverted commit. Lint, format, fallow and typecheck all pass; suite 4339. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
90 lines
3.6 KiB
TypeScript
90 lines
3.6 KiB
TypeScript
import type { RefObject } from "react";
|
|
import type { GsapAnimation } from "@hyperframes/core/gsap-parser";
|
|
import type { TimelineElement } from "../store/playerStore";
|
|
import type { TimelineRowGeometry } from "./timelineLayout";
|
|
import type { TimelineScrollViewportSnapshot } from "./useTimelineScrollViewport";
|
|
import type { TimelineTrackGroupInfo } from "./useTimelineTrackDerivations";
|
|
import { useTimelineFocusCoordinator } from "./useTimelineFocusCoordinator";
|
|
import { usePlayerStore } from "../store/playerStore";
|
|
import { useTimelineLogicalRows } from "./useTimelineLogicalRows";
|
|
import { useTimelineRowVirtualization } from "./useTimelineRowVirtualization";
|
|
|
|
interface TimelineLogicalFocusInput {
|
|
scrollRef: RefObject<HTMLDivElement | null>;
|
|
tracks: readonly (readonly [number, readonly TimelineElement[]])[];
|
|
layout: { displayTrackOrder: readonly number[]; rowGeometry: TimelineRowGeometry };
|
|
laneCounts: ReadonlyMap<string, number>;
|
|
selectedElementId: string | null;
|
|
selectedElementIds: ReadonlySet<string>;
|
|
groups: readonly TimelineTrackGroupInfo[];
|
|
trackGroupOf: ReadonlyMap<number, TimelineTrackGroupInfo>;
|
|
gsapAnimations: ReadonlyMap<string, readonly GsapAnimation[]>;
|
|
elements: readonly TimelineElement[];
|
|
pixelsPerSecond: number;
|
|
contentOrigin: number;
|
|
allowHorizontal: boolean;
|
|
viewport: TimelineScrollViewportSnapshot;
|
|
sessionEpoch: number;
|
|
draggedRowKey?: number;
|
|
resizingElementIds?: readonly string[];
|
|
clipContextMenuRowKey?: number;
|
|
keyframeContextMenuRowKey?: number;
|
|
lastScrollLeftRef: RefObject<number>;
|
|
syncScrollViewport: (element: HTMLDivElement) => void;
|
|
}
|
|
|
|
export function useTimelineLogicalFocus(input: TimelineLogicalFocusInput) {
|
|
const expandedClipIds = usePlayerStore((state) => state.expandedClipIds);
|
|
const collapsedGroupIds = usePlayerStore((state) => state.collapsedGroupIds);
|
|
const expandedLaneOwnerIds = usePlayerStore((state) => state.expandedLaneOwnerIds);
|
|
const projectId = usePlayerStore((state) => state.timelineProjectId);
|
|
const logicalRows = useTimelineLogicalRows({
|
|
tracks: input.tracks,
|
|
displayTrackOrder: input.layout.displayTrackOrder,
|
|
laneCounts: input.laneCounts,
|
|
selectedElementId: input.selectedElementId,
|
|
selectedElementIds: input.selectedElementIds,
|
|
expandedClipIds,
|
|
collapsedGroupIds,
|
|
expandedLaneOwnerIds,
|
|
groups: input.groups,
|
|
trackGroupOf: input.trackGroupOf,
|
|
gsapAnimations: input.gsapAnimations,
|
|
});
|
|
const focus = useTimelineFocusCoordinator({
|
|
scrollRef: input.scrollRef,
|
|
logicalRows,
|
|
elements: input.elements,
|
|
rowGeometry: input.layout.rowGeometry,
|
|
pixelsPerSecond: input.pixelsPerSecond,
|
|
contentOrigin: input.contentOrigin,
|
|
allowHorizontal: input.allowHorizontal,
|
|
viewportVersion: input.viewport,
|
|
projectId,
|
|
sessionEpoch: input.sessionEpoch,
|
|
syncScrollViewport: input.syncScrollViewport,
|
|
});
|
|
const rows = useTimelineRowVirtualization({
|
|
scrollRef: input.scrollRef,
|
|
viewport: input.viewport,
|
|
rowGeometry: input.layout.rowGeometry,
|
|
sessionEpoch: input.sessionEpoch,
|
|
elements: input.elements,
|
|
selectedElementId: input.selectedElementId,
|
|
focusedRowKey: focus.focusedRowKey,
|
|
draggedRowKey: input.draggedRowKey,
|
|
resizingElementIds: input.resizingElementIds,
|
|
clipContextMenuRowKey: input.clipContextMenuRowKey,
|
|
keyframeContextMenuRowKey: input.keyframeContextMenuRowKey,
|
|
lastScrollLeftRef: input.lastScrollLeftRef,
|
|
syncScrollViewport: input.syncScrollViewport,
|
|
});
|
|
return {
|
|
logicalRows,
|
|
...focus,
|
|
rowVirtualizationActive: rows.enabled,
|
|
virtualRows: rows.virtualRows,
|
|
timelineFocusProps: rows.timelineFocusProps,
|
|
};
|
|
}
|