import type { HTMLAttributes } from "react"; import type { ChoicesProps } from "ra-core"; import { useChoices, useFieldValue, useTranslate } from "ra-core"; import type { FieldProps } from "@/lib/field.type"; import { genericMemo } from "@/lib/genericMemo"; /** * Displays a value from an enumeration by mapping it to a human-readable label. * * Supports custom optionText and optionValue properties, and automatic translation of choice labels. * To be used with RecordField or DataTable.Col components, or anywhere a RecordContext is available. * * @see {@link https://marmelab.com/shadcn-admin-kit/docs/selectfield/ SelectField documentation} * * @example * import { List, DataTable, SelectField } from '@/components/admin'; * * const choices = [{ id: 'M', name: 'Male' }, { id: 'F', name: 'Female' }]; * * const UserList = () => ( * * * * * * * * * ); * * The current choice is translated by default, so you can use translation identifiers as choices: * @example * const choices = [ * { id: 'M', name: 'myroot.gender.male' }, * { id: 'F', name: 'myroot.gender.female' }, * ]; * * However, in some cases (e.g. inside a ``), you may not want * the choice to be translated. In that case, set the `translateChoice` prop to false. * @example * * * **Tip**: sets `translateChoice` to false by default. */ const SelectFieldImpl = < // eslint-disable-next-line @typescript-eslint/no-explicit-any RecordType extends Record = Record, >( props: SelectFieldProps, ) => { const { className, empty, choices, defaultValue, source, record, optionValue = "id", optionText = "name", translateChoice = true, ...rest } = props; const value = useFieldValue({ defaultValue, source, record }); const { getChoiceText, getChoiceValue } = useChoices({ optionText, optionValue, translateChoice, }); const translate = useTranslate(); const choice = choices ? // eslint-disable-next-line @typescript-eslint/no-explicit-any choices.find((choice: any) => getChoiceValue(choice) === value) : null; if (!choice) { if (!empty) { return null; } return ( {typeof empty === "string" ? translate(empty, { _: empty }) : empty} ); } const choiceText = getChoiceText(choice); return ( {choiceText} ); }; SelectFieldImpl.displayName = "SelectFieldImpl"; export const SelectField = genericMemo(SelectFieldImpl); export interface SelectFieldProps< // eslint-disable-next-line @typescript-eslint/no-explicit-any RecordType extends Record = Record, > extends Omit< ChoicesProps, "disableValue" | "createValue" | "createHintValue" >, FieldProps, HTMLAttributes {}