import { Pause, Play, RotateCcw, StepBack, StepForward } from "lucide-react"; import { useSyncExternalStore, type ReactNode } from "react"; import type { Timeline, TimelineSnapshot } from "./Timeline"; // Styled to match @elvis/ui's StepControls, which works in whole iterations const thumbClass = "[&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:cursor-grab [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-ink " + "[&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:cursor-grab [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-ink"; // How far an arrow key moves the playhead const KEY_MOVE_MS = 250; // The slider's thumb stops this far from each end, so marks on the track are inset to line up with it const THUMB_RADIUS = 8; const iconButtonClass = "flex size-11 shrink-0 items-center justify-center rounded border-[1.5px] border-ink bg-white text-ink enabled:cursor-pointer enabled:hover:bg-marker-soft disabled:cursor-not-allowed disabled:opacity-40 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink"; // The slider along the whole run, with a tick for each step and the two passes marked function TimelineBar({ timeline, snapshot }: { timeline: Timeline; snapshot: TimelineSnapshot }) { const time = useSyncExternalStore(timeline.subscribeTime, timeline.getTime); const { ticks, backwardAt, iteration, lastIteration } = snapshot; const length = ticks[ticks.length - 1]; const at = (t: number) => `${length > 0 ? (t / length) * 100 : 0}%`; return (
iteration {iteration}{lastIteration !== null ? ` / ${lastIteration}` : ""}