import { CheckIcon, ChevronsUpDownIcon } from "lucide-react"; import { useEffect, useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { cn } from "@/lib/utils"; export type ModelOption = { value: string; label: string; default?: boolean; provider?: string; }; export type GroupedModelOption = { group: string; options: ModelOption[]; icon?: React.ReactNode; }; export function ModelSelector({ options, groupedOptions, value = "", onValueChange, icon, placeholder = "Select model...", searchPlaceholder = "Search model...", noOptionsPlaceholder = "No models available", custom = false, hasError = false, defaultOpen = false, }: { options?: ModelOption[]; groupedOptions?: GroupedModelOption[]; value: string; icon?: React.ReactNode; placeholder?: string; searchPlaceholder?: string; noOptionsPlaceholder?: string; custom?: boolean; onValueChange: (value: string, provider?: string) => void; hasError?: boolean; defaultOpen?: boolean; }) { const [open, setOpen] = useState(defaultOpen); const [searchValue, setSearchValue] = useState(""); // Flatten grouped options or use regular options const allOptions = groupedOptions?.flatMap((group) => group.options) || options || []; // Find the group icon for the selected value const selectedOptionGroup = groupedOptions?.find((group) => group.options.some((opt) => opt.value === value), ); const selectedIcon = selectedOptionGroup?.icon || icon; useEffect(() => { if ( value && value !== "" && !allOptions.find((option) => option.value === value) && !custom ) { onValueChange(""); } }, [allOptions, value, custom, onValueChange]); // Update open state when defaultOpen changes useEffect(() => { if (defaultOpen) { setOpen(true); } }, [defaultOpen]); return ( e.preventDefault()} > e.stopPropagation()} > {noOptionsPlaceholder} {groupedOptions ? ( groupedOptions.map((group) => ( {group.icon && (
{group.icon}
)} {group.group} } > {group.options.length === 0 ? ( No models available ) : ( group.options.map((option) => ( { if (currentValue !== value) { onValueChange(currentValue, option.provider); } setOpen(false); }} >
{option.label}
)) )}
)) ) : ( {allOptions.map((option) => ( { if (currentValue !== value) { onValueChange(currentValue, option.provider); } setOpen(false); }} >
{option.label}
))} {custom && searchValue && !allOptions.find( (option) => option.value === searchValue, ) && ( { if (currentValue !== value) { onValueChange(currentValue); } setOpen(false); }} >
{searchValue} Custom
)}
)}
); }