"use client"; import { useEffect, useRef, useState } from "react"; import { ChevronDown } from "lucide-react"; import { cn } from "@/lib/utils"; export interface VariantOption { /** Stable identifier (typically the absolute partIdx). */ id: number; /** Short label shown in the chip and menu, e.g. `original`, `fixed`, `1080p`. */ label: string; /** Full filename, shown muted in the menu for disambiguation. */ filename: string; } /** * Compact dropdown that picks between alternate encodes of one part. * Renders nothing when there's only one option — caller can still * mount it unconditionally. */ export function VariantPicker({ options, selectedId, onChange, }: { options: VariantOption[]; selectedId: number; onChange: (id: number) => void; }) { const [open, setOpen] = useState(false); const ref = useRef(null); useEffect(() => { if (!open) return; const onDocDown = (e: MouseEvent) => { if (!ref.current) return; if (!ref.current.contains(e.target as Node)) setOpen(false); }; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") setOpen(false); }; document.addEventListener("mousedown", onDocDown); document.addEventListener("keydown", onKey); return () => { document.removeEventListener("mousedown", onDocDown); document.removeEventListener("keydown", onKey); }; }, [open]); if (options.length <= 1) return null; const selected = options.find((o) => o.id === selectedId) ?? options[0]!; return (
{open && (
{options.map((o) => ( ))}
)}
); }