♻️ create custom autocomplete tag input

This commit is contained in:
Fred KISSIE
2026-04-25 04:10:54 +02:00
parent c746e1bc8d
commit cb3fa028c3
4 changed files with 330 additions and 172 deletions

View File

@@ -5,8 +5,10 @@ import { useMemo, useState } from "react";
import { useDebounce } from "use-debounce";
import { useTranslations } from "next-intl";
import { MultiSelectTags } from "./multi-select/multi-select-tags";
import { TagInput, type TagInputProps } from "./tags/tag-input";
import {
SuggestionsTagInput,
type SuggestionsTagInputProps
} from "./tags/suggestions-tag-input";
export type SelectedMachine = Pick<
ListClientsResponse["clients"][number],
@@ -18,19 +20,14 @@ export type MachineSelectorProps = {
selectedMachines?: SelectedMachine[];
onSelectMachines: (machine: SelectedMachine[]) => void;
} & Omit<
TagInputProps,
| "activeTagIndex"
| "setActiveTagIndex"
| "placeholder"
| "size"
SuggestionsTagInputProps,
| "tags"
| "setTags"
| "value"
| "suggestedOptions"
| "searchQuery"
| "onSearchQueryChange"
| "suggestedOptions"
| "enableAutocomplete"
| "autocompleteOptions"
| "activeTagIndex"
| "setActiveTagIndex"
>;
export function MachinesSelector({
@@ -48,7 +45,7 @@ export function MachinesSelector({
orgQueries.machineClients({ orgId, perPage: 3, query: debouncedValue })
);
// always include the selected machines in the list of machines shown (if the user isn't searching)
// always include the selected machines in the list (if the user isn't searching)
const machinesShown = useMemo(() => {
const allMachines: Array<SelectedMachine> = [...machines];
if (debouncedValue.trim().length === 0) {
@@ -60,117 +57,45 @@ export function MachinesSelector({
}
}
}
return allMachines;
}, [machines, selectedMachines, debouncedValue]);
// const selectedMachinesIds = new Set(
// selectedMachines.map((m) => m.clientId)
// );
const [activeTagIndex, setActiveTagIndex] = useState<number | null>(null);
return (
<>
<TagInput
{...props}
activeTagIndex={activeTagIndex}
setActiveTagIndex={setActiveTagIndex}
placeholder={t("accessClientSelect")}
size="sm"
tags={selectedMachines.map((mc) => ({
id: mc.clientId.toString(),
text: mc.name
}))}
setTags={(newTags) => {
const tags =
typeof newTags === "function"
? newTags(
selectedMachines.map((mc) => ({
id: mc.clientId.toString(),
text: mc.name
}))
)
: newTags;
onSelectMachines(
tags.map((tag) => ({
clientId: Number(tag.id),
name: tag.text
}))
);
}}
searchQuery={machineSearchQuery}
onSearchQueryChange={setMachineSearchQuery}
suggestedOptions={machinesShown.map((mc) => ({
id: mc.clientId.toString(),
text: mc.name
}))}
allowDuplicates={false}
restrictTagsToAutocompleteOptions
sortTags
/>
</>
// <MultiSelectTags
// emptyPlaceholder={t("machineNotFound")}
// searchPlaceholder={t("machineSearch")}
// value={selectedMachines.map((m) => ({
// ...m,
// text: m.name,
// id: m.clientId.toString()
// }))}
// onChange={(values) => {
// onSelectMachines(values);
// }}
// options={machinesShown.map((m) => ({
// ...m,
// id: m.clientId.toString(),
// text: m.name
// }))}
// onSearch={setMachineSearchQuery}
// searchQuery={machineSearchQuery}
// />
// <Command shouldFilter={false}>
// <CommandInput
// placeholder={t("machineSearch")}
// value={machineSearchQuery}
// onValueChange={setMachineSearchQuery}
// />
// <CommandList>
// <CommandEmpty>{t("machineNotFound")}</CommandEmpty>
// <CommandGroup>
// {machinesShown.map((m) => (
// <CommandItem
// value={`${m.name}:${m.clientId}`}
// key={m.clientId}
// onSelect={() => {
// let newMachineClients = [];
// if (selectedMachinesIds.has(m.clientId)) {
// newMachineClients = selectedMachines.filter(
// (mc) => mc.clientId !== m.clientId
// );
// } else {
// newMachineClients = [
// ...selectedMachines,
// m
// ];
// }
// onSelectMachines(newMachineClients);
// }}
// >
// <CheckIcon
// className={cn(
// "mr-2 h-4 w-4",
// selectedMachinesIds.has(m.clientId)
// ? "opacity-100"
// : "opacity-0"
// )}
// />
// {`${m.name}`}
// </CommandItem>
// ))}
// </CommandGroup>
// </CommandList>
// </Command>
<SuggestionsTagInput
{...props}
activeTagIndex={activeTagIndex}
setActiveTagIndex={setActiveTagIndex}
placeholder={t("accessClientSelect")}
tags={selectedMachines.map((mc) => ({
id: mc.clientId.toString(),
text: mc.name
}))}
setTags={(newTags) => {
const tags =
typeof newTags === "function"
? newTags(
selectedMachines.map((mc) => ({
id: mc.clientId.toString(),
text: mc.name
}))
)
: newTags;
onSelectMachines(
tags.map((tag) => ({
clientId: Number(tag.id),
name: tag.text
}))
);
}}
searchQuery={machineSearchQuery}
onSearchQueryChange={setMachineSearchQuery}
suggestedOptions={machinesShown.map((mc) => ({
id: mc.clientId.toString(),
text: mc.name
}))}
allowDuplicates={false}
/>
);
}