21 lines
2.4 KiB
TypeScript
21 lines
2.4 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { CheckIcon, ChevronsUpDownIcon } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
import { cn } from "@/lib/utils";
|
|
import { rarityGradientClass } from "@/lib/catalog-rarity";
|
|
import type { CatalogItem } from "@/lib/translator/types";
|
|
|
|
export function CatalogCombobox({ items, value, onChange, placeholder }: { items: CatalogItem[]; value: string; onChange: (item: CatalogItem) => void; placeholder: string }) {
|
|
const [open, setOpen] = useState(false);
|
|
const selected = items.find((item) => item.id === value);
|
|
return <Popover open={open} onOpenChange={setOpen}>
|
|
<PopoverTrigger render={<Button variant="outline" className="w-full justify-between normal-case tracking-normal" />}>{selected ? <Avatar size="sm" className={rarityGradientClass(selected.rarity)}><AvatarImage src={selected.imageUrl || undefined} alt="" /><AvatarFallback>{selected.name.slice(0, 1)}</AvatarFallback></Avatar> : null}<span className="min-w-0 flex-1 truncate text-left">{selected?.name ?? placeholder}</span>{selected?.rarity ? <span className="shrink-0 text-muted-foreground tabular-nums">{selected.rarity}★</span> : null}<ChevronsUpDownIcon data-icon="inline-end" /></PopoverTrigger>
|
|
<PopoverContent className="w-(--anchor-width) p-0" align="start"><Command><CommandInput placeholder={`Search ${placeholder.toLowerCase()}...`} /><CommandList><CommandEmpty>No matching item.</CommandEmpty><CommandGroup>{items.map((item) => <CommandItem key={item.id} value={`${item.name} ${item.key}`} disabled={!item.supported} onSelect={() => { onChange(item); setOpen(false); }}><CheckIcon className={cn(item.id === value ? "opacity-100" : "opacity-0")} /><Avatar size="sm" className={rarityGradientClass(item.rarity)}><AvatarImage src={item.imageUrl || undefined} alt="" /><AvatarFallback>{item.name.slice(0, 1)}</AvatarFallback></Avatar><span className="min-w-0 flex-1 truncate">{item.name}</span>{item.rarity ? <span className="ml-auto shrink-0 text-muted-foreground tabular-nums">{item.rarity}★</span> : null}</CommandItem>)}</CommandGroup></CommandList></Command></PopoverContent>
|
|
</Popover>;
|
|
}
|