import clsx from "clsx"; import { ChevronsUpDown, Search, X } from "lucide-react"; import type * as React from "react"; import { Autocomplete, Button, Input, type Key, ListBox, ListBoxItem, Popover, SearchField, Select, type SelectProps, SelectValue, } from "react-aria-components"; import { useTranslation } from "react-i18next"; import { SendouBottomTexts } from "~/components/elements/BottomTexts"; import { SendouLabel } from "~/components/elements/Label"; import searchSelectStyles from "./SearchSelect.module.css"; import selectStyles from "./Select.module.css"; import type { EntitySearch } from "./useEntitySearch"; const PLACEHOLDER_TEXTS = { teamSearch: { placeholder: "common:forms.teamSearch.placeholder", noResults: "common:forms.teamSearch.noResults", }, tournamentSearch: { placeholder: "common:forms.tournamentSearch.placeholder", noResults: "common:forms.tournamentSearch.noResults", }, userSearch: { placeholder: "common:forms.userSearch.placeholder", noResults: "common:forms.userSearch.noResults", }, } as const; interface SearchSelectProps< TItem extends { id: number; name: string }, T extends object, > extends Omit, "children" | "onChange"> { name?: string; label?: string; bottomText?: string; errorText?: string; ariaLabel: string; inputTestId: string; inputClassName?: string; i18nKey: keyof typeof PLACEHOLDER_TEXTS; search: EntitySearch; buttonRef?: React.Ref; renderItem: (item: TItem) => React.ReactElement; } /** * Presentational autocomplete select shared by the entity search components * (e.g. `UserSearch`, `TeamSearch`, `TournamentSearch`). Wire up data fetching * with `useEntitySearch` and pass its result as `search`. */ export function SearchSelect< TItem extends { id: number; name: string }, T extends object, >({ name, label, bottomText, errorText, ariaLabel, inputTestId, inputClassName, i18nKey, search, buttonRef, renderItem, ...rest }: SearchSelectProps) { return ( {(item) => typeof item.id === "string" ? ( ) : ( renderItem(item as TItem) ) } ); } function PlaceholderItem({ id, i18nKey, }: { id: "PLACEHOLDER" | "NO_RESULTS"; i18nKey: keyof typeof PLACEHOLDER_TEXTS; }) { const { t } = useTranslation(["common"]); // for some reason the `renderEmptyState` on ListBox is not working // so doing this as a workaround return ( {id === "PLACEHOLDER" ? t(PLACEHOLDER_TEXTS[i18nKey].placeholder) : t(PLACEHOLDER_TEXTS[i18nKey].noResults)} ); }