"use client"; import { useState, useRef, useEffect } from "react"; import { ChevronDown, Search } from "lucide-react"; import clsx from "clsx"; import styles from "@/styles/AgentSelector.module.css"; interface AgentSelectorProps { agents: string[]; selectedAgent: string; onSelect: (agent: string) => void; placeholder?: string; } export function AgentSelector({ agents, selectedAgent, onSelect, placeholder = "Select an agent..." }: AgentSelectorProps) { const [isOpen, setIsOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(""); const [highlightedIndex, setHighlightedIndex] = useState(0); const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 }); const dropdownRef = useRef(null); const triggerRef = useRef(null); const searchRef = useRef(null); const filteredAgents = agents.filter(agent => agent.toLowerCase().includes(searchTerm.toLowerCase()) ); useEffect(() => { function handleClickOutside(event: MouseEvent) { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setIsOpen(false); setSearchTerm(""); } } if (isOpen) { document.addEventListener("mousedown", handleClickOutside); } return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [isOpen]); useEffect(() => { if (isOpen && searchRef.current) { searchRef.current.focus(); } }, [isOpen]); useEffect(() => { setHighlightedIndex(0); }, [searchTerm]); const handleKeyDown = (e: React.KeyboardEvent) => { if (!isOpen) { if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") { e.preventDefault(); updateDropdownPosition(); setIsOpen(true); } return; } switch (e.key) { case "ArrowDown": e.preventDefault(); setHighlightedIndex(prev => prev < filteredAgents.length - 1 ? prev + 1 : 0 ); break; case "ArrowUp": e.preventDefault(); setHighlightedIndex(prev => prev > 0 ? prev - 1 : filteredAgents.length - 1 ); break; case "Enter": e.preventDefault(); if (filteredAgents[highlightedIndex]) { onSelect(filteredAgents[highlightedIndex]); setIsOpen(false); setSearchTerm(""); } break; case "Escape": e.preventDefault(); setIsOpen(false); setSearchTerm(""); break; } }; const handleSelect = (agent: string) => { onSelect(agent); setIsOpen(false); setSearchTerm(""); }; const updateDropdownPosition = () => { if (triggerRef.current) { const rect = triggerRef.current.getBoundingClientRect(); setDropdownPosition({ top: rect.bottom + 2, left: rect.left, width: rect.width }); } }; const handleOpen = () => { updateDropdownPosition(); setIsOpen(!isOpen); }; return (
{isOpen && (
setSearchTerm(e.target.value)} onKeyDown={handleKeyDown} />
    {filteredAgents.length === 0 ? (
  • No agents found
  • ) : ( filteredAgents.map((agent, index) => (
  • handleSelect(agent)} role="option" aria-selected={agent === selectedAgent} > {agent}
  • )) )}
)}
); }