cde7be9f2a
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
import type { components } from "../api/schema";
|
|
import { labelText } from "../lib/labels";
|
|
import {
|
|
ComboboxRoot,
|
|
ComboboxInputGroup,
|
|
ComboboxInput,
|
|
ComboboxClear,
|
|
ComboboxTrigger,
|
|
ComboboxPopup,
|
|
ComboboxList,
|
|
ComboboxItem,
|
|
ComboboxItemIndicator,
|
|
ComboboxEmpty,
|
|
} from "@/components/ui/combobox";
|
|
|
|
type LabelView = components["schemas"]["LabelView"];
|
|
|
|
export type Option = { id: string; labels: LabelView[] };
|
|
|
|
export function OptionsCombobox({
|
|
id,
|
|
value,
|
|
onChange,
|
|
options,
|
|
lang,
|
|
placeholder,
|
|
}: {
|
|
id: string;
|
|
value: string;
|
|
onChange: (v: string) => void;
|
|
options: Option[];
|
|
lang: string;
|
|
placeholder: string;
|
|
}) {
|
|
const selected = options.find((o) => o.id === value) ?? null;
|
|
|
|
return (
|
|
<ComboboxRoot<Option | null>
|
|
items={options}
|
|
value={selected}
|
|
onValueChange={(option) => onChange(option?.id ?? "")}
|
|
itemToStringLabel={(option) => (option ? labelText(option.labels, lang) : "")}
|
|
isItemEqualToValue={(a, b) => a?.id === b?.id}
|
|
>
|
|
<ComboboxInputGroup>
|
|
<ComboboxInput id={id} placeholder={placeholder} />
|
|
<ComboboxClear aria-label="Clear" />
|
|
<ComboboxTrigger aria-label="Open" />
|
|
</ComboboxInputGroup>
|
|
|
|
<ComboboxPopup>
|
|
<ComboboxEmpty>No matches.</ComboboxEmpty>
|
|
<ComboboxList>
|
|
{(option: Option) => (
|
|
<ComboboxItem key={option.id} value={option}>
|
|
<ComboboxItemIndicator className="text-primary">✓</ComboboxItemIndicator>
|
|
{labelText(option.labels, lang)}
|
|
</ComboboxItem>
|
|
)}
|
|
</ComboboxList>
|
|
</ComboboxPopup>
|
|
</ComboboxRoot>
|
|
);
|
|
}
|