import { type ReactNode } from "react"; import { RotateCcw } from "lucide-react"; // ±10s skip glyph: an outline circular arrow with a "10" in the centre — the YouTube/Plex-native // muscle-memory shape. Deliberately distinct from the episode-level SkipBack/SkipForward (double // triangles) and from Restart's plain RotateCcw. The arrowhead is an L-corner at the arc's open end, // the same construction lucide uses for RotateCcw/RotateCw, so it sits consistently in the bar. export function Skip10({ dir }: { dir: "back" | "forward" }) { const back = dir === "back"; return ( ); } // --- settings-panel building blocks ------------------------------------------------------------ export function PanelHead({ children }: { children: ReactNode }) { return (
{children}
); } export function Slider({ label, value, min, max, step, suffix, onChange, onReset, }: { label: string; value: number; min: number; max: number; step: number; suffix?: string; onChange: (v: number) => void; onReset?: () => void; }) { return (
{label} {Number.isInteger(value) ? value : value.toFixed(1)} {suffix ?? ""} {onReset && ( )}
onChange(Number(e.target.value))} className="w-full accent-accent" />
); } export function Toggle({ label, checked, onChange, }: { label: string; checked: boolean; onChange: (v: boolean) => void; }) { return ( ); } // A control button with a tooltip that opens ABOVE it (so it never clips off the bottom of the // viewport, unlike a native title tooltip on the bottom control bar). export function Ctrl({ label, onClick, disabled, align = "center", children, }: { label: string; onClick: () => void; disabled?: boolean; // Tooltip horizontal anchor: "start"/"end" for edge buttons so it doesn't clip off the viewport. align?: "start" | "center" | "end"; children: ReactNode; }) { const pos = align === "start" ? "left-0" : align === "end" ? "right-0" : "left-1/2 -translate-x-1/2"; return (
{label}
); }