import { Eye, EyeSlash } from "@phosphor-icons/react"; import type { GsapAnimation } from "@hyperframes/core/gsap-parser"; import { Music } from "../../icons/SystemIcons"; import type { TimelineElement } from "../store/playerStore"; import type { TimelineEditCallbacks } from "./timelineCallbacks"; import { getTimelinePropertyLanes } from "./TimelinePropertyLanes"; import { clipTimingStart } from "../../hooks/gsapShared"; import { LayerDisclosureRow } from "./LayerDisclosureRow"; import { TrackClipCount } from "./TrackClipCount"; import { LABEL_COL_W, LANE_H, getTimelineLaneTop } from "./timelineLayout"; import type { TimelineTheme } from "./timelineTheme"; import { resolveLaneHeaderState, type KeyframeNavigationState, type TimelinePropertyLane, } from "./trackHeaderLaneState"; import { valueReadout } from "./trackHeaderLaneValues"; import { trackDisplaySuffix } from "./timelineTrackDisplay"; import { timelineLogicalRowCellId, timelinePropertyRowId } from "./timelineNavigationIdentity"; interface TimelineTrackHeaderProps { /** The track's real key: a FRACTIONAL z-order sort value. Routes callbacks; * never shown or announced. */ trackNumber: number; /** The track's 1-based position in the rendered order: the only number safe * to put in a label. Announcing `trackNumber` read out "track * 0.16666666666666666". Null when the key has no row, which drops the number * from the label rather than inventing one (see trackDisplayNumber). */ trackDisplayNumber: number | null; trackLabel: string; /** Id of the canvas-side lanes element the disclosure caret expands. Minted by * TimelineLanes, which is the one place that sees both subtrees. */ lanesId: string; contentOrigin: number; /** The track's active keyframe clip (selected, else primary) — the one whose * disclosure + property rows this header shows, whether expanded or not. */ keyframeClip: TimelineElement | null; /** Clips on this track, so the header can say how many the row holds. */ clipCount: number; isExpanded: boolean; animations: readonly GsapAnimation[]; currentTime: number; isTrackHidden: boolean; isAudioTrack: boolean; rovingTargetId?: string | null; theme: TimelineTheme; onToggleClipExpanded: () => void; onToggleTrackHidden: TimelineEditCallbacks["onToggleTrackHidden"]; onTogglePropertyGroupKeyframe?: TimelineEditCallbacks["onTogglePropertyGroupKeyframe"]; onSeek?: (time: number) => void; } function VisibilityButton({ hidden, trackNumber, trackDisplayNumber, visible, onToggle, }: { hidden: boolean; trackNumber: number; trackDisplayNumber: number | null; visible: boolean; onToggle: TimelineEditCallbacks["onToggleTrackHidden"]; }) { if (!visible) return