import { useEffect, useMemo, useRef, useState } from "react" import { CaretDownIcon, FolderIcon } from "@phosphor-icons/react" import { cn } from "@/lib/utils" type RepoOption = { full_name: string } interface RepoSelectorProps { repos?: Array selectedRepo?: string | null onRepoChange: (repo: string | null) => void placeholder?: string emptySelectionLabel?: string searchPlaceholder?: string noMatchesLabel?: string className?: string triggerClassName?: string dropdownClassName?: string disabled?: boolean } export function RepoSelector({ repos, selectedRepo = null, onRepoChange, placeholder = "Select repository", emptySelectionLabel = "No repository", searchPlaceholder = "Search repositories…", noMatchesLabel = "No matches", className, triggerClassName, dropdownClassName, disabled = false, }: RepoSelectorProps) { const [open, setOpen] = useState(false) const [query, setQuery] = useState("") const dropdownRef = useRef(null) const filteredRepos = useMemo(() => { const all = repos ?? [] const q = query.trim().toLowerCase() if (!q) return all return all.filter((repo) => repo.full_name.toLowerCase().includes(q)) }, [repos, query]) useEffect(() => { function handleClickOutside(e: MouseEvent) { const target = e.target as Node if (dropdownRef.current && !dropdownRef.current.contains(target)) { setOpen(false) } } document.addEventListener("mousedown", handleClickOutside) return () => document.removeEventListener("mousedown", handleClickOutside) }, []) return (
{open && (
setQuery(e.target.value)} placeholder={searchPlaceholder} className="w-full border-b border-border bg-transparent px-2 py-1.5 text-foreground outline-none placeholder:text-muted-foreground" />
{filteredRepos.length === 0 ? (
{noMatchesLabel}
) : ( filteredRepos.map((repo) => { const selected = repo.full_name === selectedRepo return ( ) }) )}
)}
) }