diff --git a/packages/ui/src/fields/Checkbox/Input.tsx b/packages/ui/src/fields/Checkbox/Input.tsx index 57349501c..47885049f 100644 --- a/packages/ui/src/fields/Checkbox/Input.tsx +++ b/packages/ui/src/fields/Checkbox/Input.tsx @@ -7,7 +7,7 @@ import { FieldLabel } from '../../forms/FieldLabel/index.js' import { Check } from '../../icons/Check/index.js' import { Line } from '../../icons/Line/index.js' -type Props = { +export type CheckboxInputProps = { AfterInput?: React.ReactNode BeforeInput?: React.ReactNode CustomLabel?: React.ReactNode @@ -26,7 +26,7 @@ type Props = { export const inputBaseClass = 'checkbox-input' -export const CheckboxInput: React.FC = ({ +export const CheckboxInput: React.FC = ({ id, name, AfterInput, diff --git a/packages/ui/src/fields/Checkbox/index.tsx b/packages/ui/src/fields/Checkbox/index.tsx index 22af3fe83..f8f6bc511 100644 --- a/packages/ui/src/fields/Checkbox/index.tsx +++ b/packages/ui/src/fields/Checkbox/index.tsx @@ -3,6 +3,7 @@ import type { ClientValidate } from 'payload/types' import React, { useCallback } from 'react' +import type { CheckboxInputProps } from './Input.js' import type { CheckboxFieldProps } from './types.js' import { FieldDescription } from '../../forms/FieldDescription/index.js' @@ -19,7 +20,7 @@ import './index.scss' const baseClass = 'checkbox' -export { CheckboxFieldProps, CheckboxInput } +export { CheckboxFieldProps, CheckboxInput, type CheckboxInputProps } const CheckboxField: React.FC = (props) => { const { diff --git a/packages/ui/src/fields/Select/Input.tsx b/packages/ui/src/fields/Select/Input.tsx new file mode 100644 index 000000000..ee5a66c29 --- /dev/null +++ b/packages/ui/src/fields/Select/Input.tsx @@ -0,0 +1,131 @@ +'use client' +import type { OptionObject } from 'payload/types' + +import { getTranslation } from '@payloadcms/translations' +import React from 'react' + +import type { SelectFieldProps } from './index.js' + +import { ReactSelect } from '../../elements/ReactSelect/index.js' +import { FieldDescription } from '../../forms/FieldDescription/index.js' +import { FieldError } from '../../forms/FieldError/index.js' +import { FieldLabel } from '../../forms/FieldLabel/index.js' +import { useTranslation } from '../../providers/Translation/index.js' +import { fieldBaseClass } from '../shared/index.js' +import './index.scss' + +export type SelectInputProps = Omit< + SelectFieldProps, + | 'custom' + | 'disabled' + | 'docPreferences' + | 'locale' + | 'localized' + | 'options' + | 'rtl' + | 'type' + | 'user' + | 'validate' + | 'value' +> & { + options?: OptionObject[] + showError?: boolean + value?: string | string[] +} + +export const SelectInput: React.FC = (props) => { + const { + AfterInput, + BeforeInput, + CustomDescription, + CustomError, + CustomLabel, + className, + descriptionProps, + errorProps, + hasMany = false, + isClearable = true, + isSortable = true, + label, + labelProps, + onChange, + options, + path, + readOnly, + required, + showError, + style, + value, + width, + } = props + + const { i18n } = useTranslation() + + let valueToRender + + if (hasMany && Array.isArray(value)) { + valueToRender = value.map((val) => { + const matchingOption = options.find((option) => option.value === val) + return { + label: matchingOption ? getTranslation(matchingOption.label, i18n) : val, + value: matchingOption?.value ?? val, + } + }) + } else if (value) { + const matchingOption = options.find((option) => option.value === value) + valueToRender = { + label: matchingOption ? getTranslation(matchingOption.label, i18n) : value, + value: matchingOption?.value ?? value, + } + } + + return ( +
+ + +
+ + {BeforeInput} + ({ + ...option, + label: getTranslation(option.label, i18n), + }))} + showError={showError} + value={valueToRender as OptionObject} + /> + {AfterInput} +
+ {CustomDescription !== undefined ? ( + CustomDescription + ) : ( + + )} +
+ ) +} diff --git a/packages/ui/src/fields/Select/index.tsx b/packages/ui/src/fields/Select/index.tsx index 2d21cfa55..a1fa9ce97 100644 --- a/packages/ui/src/fields/Select/index.tsx +++ b/packages/ui/src/fields/Select/index.tsx @@ -2,21 +2,15 @@ 'use client' import type { ClientValidate, Option, OptionObject } from 'payload/types' -import { getTranslation } from '@payloadcms/translations' import React, { useCallback, useState } from 'react' import type { FormFieldBase } from '../shared/index.js' +import type { SelectInputProps } from './Input.js' -import { ReactSelect } from '../../elements/ReactSelect/index.js' -import { FieldDescription } from '../../forms/FieldDescription/index.js' -import { FieldError } from '../../forms/FieldError/index.js' -import { FieldLabel } from '../../forms/FieldLabel/index.js' import { useFieldProps } from '../../forms/FieldPropsProvider/index.js' import { useField } from '../../forms/useField/index.js' import { withCondition } from '../../forms/withCondition/index.js' -import { useTranslation } from '../../providers/Translation/index.js' -import { fieldBaseClass } from '../shared/index.js' -import './index.scss' +import { SelectInput } from './Input.js' export type SelectFieldProps = FormFieldBase & { hasMany?: boolean @@ -68,8 +62,6 @@ const SelectField: React.FC = (props) => { width, } = props - const { i18n } = useTranslation() - const [options] = useState(formatOptions(optionsFromProps)) const memoizedValidate: ClientValidate = useCallback( @@ -88,24 +80,6 @@ const SelectField: React.FC = (props) => { validate: memoizedValidate, }) - let valueToRender - - if (hasMany && Array.isArray(value)) { - valueToRender = value.map((val) => { - const matchingOption = options.find((option) => option.value === val) - return { - label: matchingOption ? getTranslation(matchingOption.label, i18n) : val, - value: matchingOption?.value ?? val, - } - }) - } else if (value) { - const matchingOption = options.find((option) => option.value === value) - valueToRender = { - label: matchingOption ? getTranslation(matchingOption.label, i18n) : value, - value: matchingOption?.value ?? value, - } - } - const onChange = useCallback( (selectedOption) => { if (!readOnly) { @@ -133,54 +107,34 @@ const SelectField: React.FC = (props) => { ) return ( -
- - -
- - {BeforeInput} - ({ - ...option, - label: getTranslation(option.label, i18n), - }))} - showError={showError} - value={valueToRender as OptionObject} - /> - {AfterInput} -
- {CustomDescription !== undefined ? ( - CustomDescription - ) : ( - - )} -
+ ) } export const Select = withCondition(SelectField) + +export { SelectInput, type SelectInputProps }