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 {}