"use client"; import * as React from "react"; import { useState } from "react"; import { ChevronsUpDown } from "lucide-react"; import { cn } from "./utils"; import { Button } from "./button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "./command"; import { Popover, PopoverContent, PopoverTrigger } from "./popover"; export type SearchableSelectOption = { value: string; label: string; }; export function SearchableSelect({ value, onValueChange, options, placeholder = "Select…", searchPlaceholder = "Search…", emptyText = "No matching results.", disabled, className, }: { /** 空字符串表示未选择 */ value: string; onValueChange: (next: string) => void; options: SearchableSelectOption[]; placeholder?: string; searchPlaceholder?: string; emptyText?: string; disabled?: boolean; className?: string; }) { const [open, setOpen] = useState(false); const hit = value ? options.find((o) => o.value === value) : undefined; const selectedLabel = value ? hit?.label ?? value : null; return ( {emptyText} {options.map((opt) => ( { onValueChange(opt.value); setOpen(false); }} className={cn( "cursor-pointer rounded-md px-2 py-2 transition-colors", "hover:bg-gray-100 hover:text-gray-900", "data-[selected=true]:bg-gray-100", value === opt.value && "bg-blue-50 text-gray-900 font-medium data-[selected=true]:bg-blue-100", )} > {opt.label} ))} {value ? (
) : null}
); }