chore(ui): client-side renders all default field labels, descriptions, and errors

This commit is contained in:
Jacob Fletcher
2024-03-20 15:01:46 -04:00
parent 9f690c1f5d
commit b3d28bac6a
48 changed files with 512 additions and 322 deletions

View File

@@ -1,6 +1,6 @@
'use client' 'use client'
import { ReactSelect } from '@payloadcms/ui/elements/ReactSelect' import { ReactSelect } from '@payloadcms/ui/elements/ReactSelect'
import { Label } from '@payloadcms/ui/forms/Label' import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useTranslation } from '@payloadcms/ui/providers/Translation' import { useTranslation } from '@payloadcms/ui/providers/Translation'
import React from 'react' import React from 'react'
@@ -20,7 +20,7 @@ export const Settings: React.FC<{
<div className={[baseClass, className].filter(Boolean).join(' ')}> <div className={[baseClass, className].filter(Boolean).join(' ')}>
<h3>{t('general:payloadSettings')}</h3> <h3>{t('general:payloadSettings')}</h3>
<div className={`${baseClass}__language`}> <div className={`${baseClass}__language`}>
<Label htmlFor="language-select" label={t('general:language')} /> <FieldLabel htmlFor="language-select" label={t('general:language')} />
<ReactSelect <ReactSelect
inputId="language-select" inputId="language-select"
onChange={async ({ value }) => { onChange={async ({ value }) => {

View File

@@ -3,8 +3,8 @@ import type { PayloadRequest } from 'payload/types'
import { CopyToClipboard } from '@payloadcms/ui/elements/CopyToClipboard' import { CopyToClipboard } from '@payloadcms/ui/elements/CopyToClipboard'
import { GenerateConfirmation } from '@payloadcms/ui/elements/GenerateConfirmation' import { GenerateConfirmation } from '@payloadcms/ui/elements/GenerateConfirmation'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useFormFields } from '@payloadcms/ui/forms/Form' import { useFormFields } from '@payloadcms/ui/forms/Form'
import { Label } from '@payloadcms/ui/forms/Label'
import { useField } from '@payloadcms/ui/forms/useField' import { useField } from '@payloadcms/ui/forms/useField'
import { useConfig } from '@payloadcms/ui/providers/Config' import { useConfig } from '@payloadcms/ui/providers/Config'
import { useTranslation } from '@payloadcms/ui/providers/Translation' import { useTranslation } from '@payloadcms/ui/providers/Translation'
@@ -89,7 +89,7 @@ export const APIKey: React.FC<{ readOnly?: boolean }> = ({ readOnly }) => {
return ( return (
<React.Fragment> <React.Fragment>
<div className={[fieldBaseClass, 'api-key', 'read-only'].filter(Boolean).join(' ')}> <div className={[fieldBaseClass, 'api-key', 'read-only'].filter(Boolean).join(' ')}>
<Label htmlFor={path} label={APIKeyLabel} /> <FieldLabel htmlFor={path} label={APIKeyLabel} />
<input <input
className={highlightedField ? 'highlight' : undefined} className={highlightedField ? 'highlight' : undefined}
disabled disabled

View File

@@ -145,7 +145,6 @@ export const DefaultEditView: React.FC = () => {
entitySlug, entitySlug,
user, user,
collectionSlug, collectionSlug,
userSlug,
getVersions, getVersions,
getDocPermissions, getDocPermissions,
isEditing, isEditing,

View File

@@ -97,7 +97,7 @@ export const VersionsViewClient: React.FC<{
)} )}
{versionCount > 0 && ( {versionCount > 0 && (
<React.Fragment> <React.Fragment>
<Table columns={columns} data={data?.docs} /> <Table columns={columns} data={data?.docs} fieldMap={componentMap?.fieldMap} />
<div className={`${baseClass}__page-controls`}> <div className={`${baseClass}__page-controls`}>
<Pagination <Pagination
hasNextPage={data.hasNextPage} hasNextPage={data.hasNextPage}

View File

@@ -4,6 +4,7 @@ import type { FormFieldBase } from '@payloadcms/ui/fields/shared'
import type { FieldType, Options } from '@payloadcms/ui/forms/useField' import type { FieldType, Options } from '@payloadcms/ui/forms/useField'
import { TextareaInput } from '@payloadcms/ui/fields/Textarea' import { TextareaInput } from '@payloadcms/ui/fields/Textarea'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider' import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider'
import { useAllFormFields } from '@payloadcms/ui/forms/Form' import { useAllFormFields } from '@payloadcms/ui/forms/Form'
import { useField } from '@payloadcms/ui/forms/useField' import { useField } from '@payloadcms/ui/forms/useField'
@@ -26,7 +27,7 @@ type MetaDescriptionProps = FormFieldBase & {
} }
export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => { export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
const { Label, hasGenerateDescriptionFn, path, required } = props const { CustomLabel, hasGenerateDescriptionFn, labelProps, path, required } = props
const { path: pathFromContext } = useFieldProps() const { path: pathFromContext } = useFieldProps()
const { t } = useTranslation() const { t } = useTranslation()
@@ -75,8 +76,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
}} }}
> >
<div className="plugin-seo__field"> <div className="plugin-seo__field">
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{required && ( {required && (
<span <span
style={{ style={{
@@ -131,7 +131,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
}} }}
> >
<TextareaInput <TextareaInput
Error={errorMessage} // TODO: Fix CustomError={errorMessage}
onChange={setValue} onChange={setValue}
path={pathFromContext} path={pathFromContext}
required={required} required={required}

View File

@@ -4,6 +4,7 @@ import type { UploadInputProps } from '@payloadcms/ui/fields/Upload'
import type { FieldType, Options } from '@payloadcms/ui/forms/useField' import type { FieldType, Options } from '@payloadcms/ui/forms/useField'
import { UploadInput } from '@payloadcms/ui/fields/Upload' import { UploadInput } from '@payloadcms/ui/fields/Upload'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useAllFormFields } from '@payloadcms/ui/forms/Form' import { useAllFormFields } from '@payloadcms/ui/forms/Form'
import { useField } from '@payloadcms/ui/forms/useField' import { useField } from '@payloadcms/ui/forms/useField'
import { useConfig } from '@payloadcms/ui/providers/Config' import { useConfig } from '@payloadcms/ui/providers/Config'
@@ -22,7 +23,7 @@ type MetaImageProps = UploadInputProps & {
} }
export const MetaImage: React.FC<MetaImageProps> = (props) => { export const MetaImage: React.FC<MetaImageProps> = (props) => {
const { Label, hasGenerateImageFn, relationTo, required } = props || {} const { CustomLabel, hasGenerateImageFn, labelProps, relationTo, required } = props || {}
const field: FieldType<string> = useField(props as Options) const field: FieldType<string> = useField(props as Options)
@@ -76,8 +77,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
}} }}
> >
<div className="plugin-seo__field"> <div className="plugin-seo__field">
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{required && ( {required && (
<span <span
style={{ style={{
@@ -88,7 +88,6 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
* *
</span> </span>
)} )}
{hasGenerateImageFn && ( {hasGenerateImageFn && (
<React.Fragment> <React.Fragment>
&nbsp; &mdash; &nbsp; &nbsp; &mdash; &nbsp;
@@ -127,7 +126,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
}} }}
> >
<UploadInput <UploadInput
Error={errorMessage} // TODO: Fix CustomError={errorMessage}
api={api} api={api}
collection={collection} collection={collection}
filterOptions={{}} filterOptions={{}}

View File

@@ -5,6 +5,7 @@ import type { Options } from '@payloadcms/ui/forms/useField'
import type { FieldType } from '@payloadcms/ui/forms/useField' import type { FieldType } from '@payloadcms/ui/forms/useField'
import { TextInput } from '@payloadcms/ui/fields/Text' import { TextInput } from '@payloadcms/ui/fields/Text'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider' import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider'
import { useAllFormFields } from '@payloadcms/ui/forms/Form' import { useAllFormFields } from '@payloadcms/ui/forms/Form'
import { useField } from '@payloadcms/ui/forms/useField' import { useField } from '@payloadcms/ui/forms/useField'
@@ -27,7 +28,7 @@ type MetaTitleProps = FormFieldBase & {
} }
export const MetaTitle: React.FC<MetaTitleProps> = (props) => { export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
const { Label, hasGenerateTitleFn, path, required } = props || {} const { CustomLabel, hasGenerateTitleFn, labelProps, path, required } = props || {}
const { path: pathFromContext } = useFieldProps() const { path: pathFromContext } = useFieldProps()
const { t } = useTranslation() const { t } = useTranslation()
@@ -76,8 +77,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
}} }}
> >
<div className="plugin-seo__field"> <div className="plugin-seo__field">
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{required && ( {required && (
<span <span
style={{ style={{
@@ -88,7 +88,6 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
* *
</span> </span>
)} )}
{hasGenerateTitleFn && ( {hasGenerateTitleFn && (
<React.Fragment> <React.Fragment>
&nbsp; &mdash; &nbsp; &nbsp; &mdash; &nbsp;
@@ -133,7 +132,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
}} }}
> >
<TextInput <TextInput
Error={errorMessage} // TODO: fix errormessage CustomError={errorMessage}
onChange={setValue} onChange={setValue}
path={pathFromContext} path={pathFromContext}
required={required} required={required}

View File

@@ -2,6 +2,9 @@
import type { FormFieldBase } from '@payloadcms/ui/fields/shared' import type { FormFieldBase } from '@payloadcms/ui/fields/shared'
import type { SerializedEditorState } from 'lexical' import type { SerializedEditorState } from 'lexical'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useField } from '@payloadcms/ui/forms/useField' import { useField } from '@payloadcms/ui/forms/useField'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { ErrorBoundary } from 'react-error-boundary' import { ErrorBoundary } from 'react-error-boundary'
@@ -23,11 +26,14 @@ export const RichText: React.FC<
> = (props) => { > = (props) => {
const { const {
name, name,
Description, CustomDescription,
Error, CustomError,
Label, CustomLabel,
className, className,
descriptionProps,
editorConfig, editorConfig,
errorProps,
labelProps,
path: pathFromProps, path: pathFromProps,
readOnly, readOnly,
required, required,
@@ -75,8 +81,8 @@ export const RichText: React.FC<
}} }}
> >
<div className={`${baseClass}__wrap`}> <div className={`${baseClass}__wrap`}>
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<ErrorBoundary fallbackRender={fallbackRender} onReset={() => {}}> <ErrorBoundary fallbackRender={fallbackRender} onReset={() => {}}>
<LexicalProvider <LexicalProvider
editorConfig={editorConfig} editorConfig={editorConfig}
@@ -99,7 +105,11 @@ export const RichText: React.FC<
value={value} value={value}
/> />
</ErrorBoundary> </ErrorBoundary>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
</div> </div>
) )

View File

@@ -6,6 +6,9 @@ import type { HistoryEditor } from 'slate-history'
import type { ReactEditor } from 'slate-react' import type { ReactEditor } from 'slate-react'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { useField } from '@payloadcms/ui/forms/useField' import { useField } from '@payloadcms/ui/forms/useField'
import { withCondition } from '@payloadcms/ui/forms/withCondition' import { withCondition } from '@payloadcms/ui/forms/withCondition'
import { useEditDepth } from '@payloadcms/ui/providers/EditDepth' import { useEditDepth } from '@payloadcms/ui/providers/EditDepth'
@@ -55,11 +58,14 @@ const RichTextField: React.FC<
> = (props) => { > = (props) => {
const { const {
name, name,
Description, CustomDescription,
Error, CustomError,
Label, CustomLabel,
className, className,
descriptionProps,
elements, elements,
errorProps,
labelProps,
leaves, leaves,
path: pathFromProps, path: pathFromProps,
placeholder, placeholder,
@@ -299,8 +305,8 @@ const RichTextField: React.FC<
}} }}
> >
<div className={`${baseClass}__wrap`}> <div className={`${baseClass}__wrap`}>
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<Slate <Slate
editor={editor} editor={editor}
key={JSON.stringify({ initialValue, path })} // makes sure slate is completely re-rendered when initialValue changes, bypassing the slate-internal value memoization. That way, external changes to the form will update the editor key={JSON.stringify({ initialValue, path })} // makes sure slate is completely re-rendered when initialValue changes, bypassing the slate-internal value memoization. That way, external changes to the form will update the editor
@@ -430,7 +436,11 @@ const RichTextField: React.FC<
</div> </div>
</div> </div>
</Slate> </Slate>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
</div> </div>
) )

View File

@@ -4,9 +4,9 @@ import React, { Fragment, useState } from 'react'
import type { FieldMap, MappedField } from '../../providers/ComponentMap/buildComponentMap/types.js' import type { FieldMap, MappedField } from '../../providers/ComponentMap/buildComponentMap/types.js'
import { FieldLabel } from '../../forms/FieldLabel/index.js'
import { useForm } from '../../forms/Form/context.js' import { useForm } from '../../forms/Form/context.js'
import { createNestedClientFieldPath } from '../../forms/Form/createNestedFieldPath.js' import { createNestedClientFieldPath } from '../../forms/Form/createNestedFieldPath.js'
import { Label } from '../../forms/Label/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
import { ReactSelect } from '../ReactSelect/index.js' import { ReactSelect } from '../ReactSelect/index.js'
import './index.scss' import './index.scss'
@@ -23,7 +23,18 @@ const combineLabel = (prefix: JSX.Element, field: MappedField): JSX.Element => {
<Fragment> <Fragment>
<span style={{ display: 'inline-block' }}>{prefix}</span> <span style={{ display: 'inline-block' }}>{prefix}</span>
{prefix ? <Fragment>{' > '}</Fragment> : ''} {prefix ? <Fragment>{' > '}</Fragment> : ''}
<span style={{ display: 'inline-block' }}>{field.fieldComponentProps.Label}</span> <span style={{ display: 'inline-block' }}>
{'CustomLabel' in field.fieldComponentProps &&
field.fieldComponentProps.CustomLabel !== undefined ? (
field.fieldComponentProps.CustomLabel
) : (
<FieldLabel
{...(('labelProps' in field.fieldComponentProps &&
field.fieldComponentProps.labelProps) ||
{})}
/>
)}
</span>
</Fragment> </Fragment>
) )
} }
@@ -45,7 +56,7 @@ const reduceFields = (
(field.disableBulkEdit || (field.disableBulkEdit ||
field.unique || field.unique ||
field.isHidden || field.isHidden ||
field.fieldComponentProps?.readOnly) ('readOnly' in field.fieldComponentProps && field.fieldComponentProps.readOnly))
) { ) {
return fieldsToUse return fieldsToUse
} }
@@ -128,7 +139,7 @@ export const FieldSelect: React.FC<FieldSelectProps> = ({ fieldMap, setSelected
return ( return (
<div className={baseClass}> <div className={baseClass}>
<Label label={t('fields:selectFieldsToEdit')} /> <FieldLabel label={t('fields:selectFieldsToEdit')} />
<ReactSelect isMulti onChange={handleChange} options={options} /> <ReactSelect isMulti onChange={handleChange} options={options} />
</div> </div>
) )

View File

@@ -9,7 +9,7 @@ import React, { useCallback, useEffect, useReducer, useState } from 'react'
import type { ListPreferences } from '../TableColumns/index.js' import type { ListPreferences } from '../TableColumns/index.js'
import type { ListDrawerProps } from './types.js' import type { ListDrawerProps } from './types.js'
import { Label } from '../../forms/Label/index.js' import { FieldLabel } from '../../forms/FieldLabel/index.js'
import usePayloadAPI from '../../hooks/usePayloadAPI.js' import usePayloadAPI from '../../hooks/usePayloadAPI.js'
import { useUseTitleField } from '../../hooks/useUseAsTitle.js' import { useUseTitleField } from '../../hooks/useUseAsTitle.js'
import { X } from '../../icons/X/index.js' import { X } from '../../icons/X/index.js'
@@ -264,7 +264,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
)} )}
{moreThanOneAvailableCollection && ( {moreThanOneAvailableCollection && (
<div className={`${baseClass}__select-collection-wrap`}> <div className={`${baseClass}__select-collection-wrap`}>
<Label label={t('upload:selectCollectionToBrowse')} /> <FieldLabel label={t('upload:selectCollectionToBrowse')} />
<ReactSelect <ReactSelect
className={`${baseClass}__select-collection`} className={`${baseClass}__select-collection`}
onChange={setSelectedOption} // this is only changing the options which is not rerunning my effect onChange={setSelectedOption} // this is only changing the options which is not rerunning my effect

View File

@@ -1,11 +1,11 @@
'use client' 'use client'
import type { FormState, SanitizedCollectionConfig } from 'payload/types' import type { FormState, SanitizedCollectionConfig } from 'payload/types'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { isImage } from 'payload/utilities' import { isImage } from 'payload/utilities'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
import { fieldBaseClass } from '../../fields/shared/index.js' import { fieldBaseClass } from '../../fields/shared/index.js'
import { Error } from '../../forms/Error/index.js'
import { useFormSubmitted } from '../../forms/Form/context.js' import { useFormSubmitted } from '../../forms/Form/context.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { useDocumentInfo } from '../../providers/DocumentInfo/index.js' import { useDocumentInfo } from '../../providers/DocumentInfo/index.js'
@@ -135,7 +135,7 @@ export const Upload: React.FC<UploadProps> = (props) => {
return ( return (
<div className={[fieldBaseClass, baseClass].filter(Boolean).join(' ')}> <div className={[fieldBaseClass, baseClass].filter(Boolean).join(' ')}>
<Error message={errorMessage} showError={showError} /> <FieldError message={errorMessage} showError={showError} />
{doc.filename && !replacingFile && ( {doc.filename && !replacingFile && (
<FileDetails <FileDetails
canEdit={showCrop || showFocalPoint} canEdit={showCrop || showFocalPoint}

View File

@@ -4,6 +4,9 @@ import type { FieldBase } from 'payload/types'
import type { ArrayField as ArrayFieldType } from 'payload/types' import type { ArrayField as ArrayFieldType } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js' import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js'
@@ -15,7 +18,6 @@ import { DraggableSortableItem } from '../../elements/DraggableSortable/Draggabl
import { DraggableSortable } from '../../elements/DraggableSortable/index.js' import { DraggableSortable } from '../../elements/DraggableSortable/index.js'
import { ErrorPill } from '../../elements/ErrorPill/index.js' import { ErrorPill } from '../../elements/ErrorPill/index.js'
import { useForm, useFormSubmitted } from '../../forms/Form/context.js' import { useForm, useFormSubmitted } from '../../forms/Form/context.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { NullifyLocaleField } from '../../forms/NullifyField/index.js' import { NullifyLocaleField } from '../../forms/NullifyField/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { useConfig } from '../../providers/Config/index.js' import { useConfig } from '../../providers/Config/index.js'
@@ -46,15 +48,17 @@ export type ArrayFieldProps = FormFieldBase & {
export const ArrayField: React.FC<ArrayFieldProps> = (props) => { export const ArrayField: React.FC<ArrayFieldProps> = (props) => {
const { const {
name, name,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
RowLabel, RowLabel,
className, className,
descriptionProps,
errorProps,
fieldMap, fieldMap,
forceRender = false, forceRender = false,
indexPath, indexPath,
label, labelProps,
localized, localized,
maxRows, maxRows,
minRows, minRows,
@@ -65,8 +69,6 @@ export const ArrayField: React.FC<ArrayFieldProps> = (props) => {
validate, validate,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { setDocFieldPreferences } = useDocumentInfo() const { setDocFieldPreferences } = useDocumentInfo()
const { addFieldRow, dispatchFields, setModified } = useForm() const { addFieldRow, dispatchFields, setModified } = useForm()
const submitted = useFormSubmitted() const submitted = useFormSubmitted()
@@ -194,11 +196,17 @@ export const ArrayField: React.FC<ArrayFieldProps> = (props) => {
.join(' ')} .join(' ')}
id={`field-${path.replace(/\./g, '__')}`} id={`field-${path.replace(/\./g, '__')}`}
> >
{showError && <div className={`${baseClass}__error-wrap`}>{Error}</div>} {showError && (
<div className={`${baseClass}__error-wrap`}>
{CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
</div>
)}
<header className={`${baseClass}__header`}> <header className={`${baseClass}__header`}>
<div className={`${baseClass}__header-wrap`}> <div className={`${baseClass}__header-wrap`}>
<div className={`${baseClass}__header-content`}> <div className={`${baseClass}__header-content`}>
<h3 className={`${baseClass}__title`}>{Label}</h3> <h3 className={`${baseClass}__title`}>
{CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
</h3>
{fieldHasErrors && fieldErrorCount > 0 && ( {fieldHasErrors && fieldErrorCount > 0 && (
<ErrorPill count={fieldErrorCount} i18n={i18n} withMessage /> <ErrorPill count={fieldErrorCount} i18n={i18n} withMessage />
)} )}
@@ -226,7 +234,11 @@ export const ArrayField: React.FC<ArrayFieldProps> = (props) => {
</ul> </ul>
)} )}
</div> </div>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</header> </header>
<NullifyLocaleField fieldValue={value} localized={localized} path={path} /> <NullifyLocaleField fieldValue={value} localized={localized} path={path} />
{(rows.length > 0 || (!valid && (showRequired || showMinRows))) && ( {(rows.length > 0 || (!valid && (showRequired || showMinRows))) && (

View File

@@ -10,7 +10,6 @@ import { DrawerToggler } from '../../elements/Drawer/index.js'
import { useDrawerSlug } from '../../elements/Drawer/useDrawerSlug.js' import { useDrawerSlug } from '../../elements/Drawer/useDrawerSlug.js'
import { ErrorPill } from '../../elements/ErrorPill/index.js' import { ErrorPill } from '../../elements/ErrorPill/index.js'
import { useForm, useFormSubmitted } from '../../forms/Form/context.js' import { useForm, useFormSubmitted } from '../../forms/Form/context.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { NullifyLocaleField } from '../../forms/NullifyField/index.js' import { NullifyLocaleField } from '../../forms/NullifyField/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { useConfig } from '../../providers/Config/index.js' import { useConfig } from '../../providers/Config/index.js'
@@ -28,6 +27,10 @@ const baseClass = 'blocks-field'
import type { FieldPermissions } from 'payload/auth' import type { FieldPermissions } from 'payload/auth'
import type { BlockField, FieldBase } from 'payload/types' import type { BlockField, FieldBase } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import type { import type {
FieldMap, FieldMap,
ReducedBlock, ReducedBlock,
@@ -54,14 +57,16 @@ export const BlocksField: React.FC<BlocksFieldProps> = (props) => {
const { const {
name, name,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
blocks, blocks,
className, className,
descriptionProps,
errorProps,
forceRender = false, forceRender = false,
indexPath, indexPath,
label, labelProps,
labels: labelsFromProps, labels: labelsFromProps,
localized, localized,
maxRows, maxRows,
@@ -72,8 +77,6 @@ export const BlocksField: React.FC<BlocksFieldProps> = (props) => {
validate, validate,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { setDocFieldPreferences } = useDocumentInfo() const { setDocFieldPreferences } = useDocumentInfo()
const { addFieldRow, dispatchFields, setModified } = useForm() const { addFieldRow, dispatchFields, setModified } = useForm()
const { code: locale } = useLocale() const { code: locale } = useLocale()
@@ -207,11 +210,17 @@ export const BlocksField: React.FC<BlocksFieldProps> = (props) => {
.join(' ')} .join(' ')}
id={`field-${path.replace(/\./g, '__')}`} id={`field-${path.replace(/\./g, '__')}`}
> >
{showError && <div className={`${baseClass}__error-wrap`}>{Error}</div>} {showError && (
<div className={`${baseClass}__error-wrap`}>
{CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
</div>
)}
<header className={`${baseClass}__header`}> <header className={`${baseClass}__header`}>
<div className={`${baseClass}__header-wrap`}> <div className={`${baseClass}__header-wrap`}>
<div className={`${baseClass}__heading-with-error`}> <div className={`${baseClass}__heading-with-error`}>
<h3>{Label}</h3> <h3>
{CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
</h3>
{fieldHasErrors && fieldErrorCount > 0 && ( {fieldHasErrors && fieldErrorCount > 0 && (
<ErrorPill count={fieldErrorCount} i18n={i18n} withMessage /> <ErrorPill count={fieldErrorCount} i18n={i18n} withMessage />
)} )}
@@ -239,7 +248,11 @@ export const BlocksField: React.FC<BlocksFieldProps> = (props) => {
</ul> </ul>
)} )}
</div> </div>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</header> </header>
<NullifyLocaleField fieldValue={value} localized={localized} path={path} /> <NullifyLocaleField fieldValue={value} localized={localized} path={path} />
{(rows.length > 0 || (!valid && (showRequired || showMinRows))) && ( {(rows.length > 0 || (!valid && (showRequired || showMinRows))) && (

View File

@@ -1,4 +1,7 @@
'use client' 'use client'
import type { LabelProps } from 'packages/payload/src/admin/types.js'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React from 'react' import React from 'react'
import { Check } from '../../icons/Check/index.js' import { Check } from '../../icons/Check/index.js'
@@ -7,11 +10,12 @@ import { Line } from '../../icons/Line/index.js'
type Props = { type Props = {
AfterInput?: React.ReactNode AfterInput?: React.ReactNode
BeforeInput?: React.ReactNode BeforeInput?: React.ReactNode
Label?: React.ReactNode CustomLabel?: React.ReactNode
checked?: boolean checked?: boolean
className?: string className?: string
id?: string id?: string
inputRef?: React.RefObject<HTMLInputElement> inputRef?: React.RefObject<HTMLInputElement>
labelProps?: LabelProps
name?: string name?: string
onToggle: (event: React.ChangeEvent<HTMLInputElement>) => void onToggle: (event: React.ChangeEvent<HTMLInputElement>) => void
partialChecked?: boolean partialChecked?: boolean
@@ -26,10 +30,11 @@ export const CheckboxInput: React.FC<Props> = ({
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Label, CustomLabel,
checked, checked,
className, className,
inputRef, inputRef,
labelProps,
onToggle, onToggle,
partialChecked, partialChecked,
readOnly, readOnly,
@@ -69,7 +74,7 @@ export const CheckboxInput: React.FC<Props> = ({
</span> </span>
{AfterInput} {AfterInput}
</div> </div>
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
</div> </div>
) )
} }

View File

@@ -1,12 +1,13 @@
'use client' 'use client'
import type { ClientValidate } from 'payload/types' import type { ClientValidate } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import type { CheckboxFieldProps } from './types.js' import type { CheckboxFieldProps } from './types.js'
import { useForm } from '../../forms/Form/context.js' import { useForm } from '../../forms/Form/context.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { generateFieldID } from '../../utilities/generateFieldID.js' import { generateFieldID } from '../../utilities/generateFieldID.js'
@@ -24,13 +25,15 @@ const CheckboxField: React.FC<CheckboxFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
checked: checkedFromProps, checked: checkedFromProps,
className, className,
descriptionProps,
disableFormData, disableFormData,
label, errorProps,
labelProps,
onChange: onChangeFromProps, onChange: onChangeFromProps,
partialChecked, partialChecked,
path: pathFromProps, path: pathFromProps,
@@ -43,8 +46,6 @@ const CheckboxField: React.FC<CheckboxFieldProps> = (props) => {
const { uuid } = useForm() const { uuid } = useForm()
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const memoizedValidate: ClientValidate = useCallback( const memoizedValidate: ClientValidate = useCallback(
(value, options) => { (value, options) => {
if (typeof validate === 'function') { if (typeof validate === 'function') {
@@ -88,21 +89,28 @@ const CheckboxField: React.FC<CheckboxFieldProps> = (props) => {
width, width,
}} }}
> >
<div className={`${baseClass}__error-wrap`}>{Error}</div> <div className={`${baseClass}__error-wrap`}>
{CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
</div>
<CheckboxInput <CheckboxInput
AfterInput={AfterInput} AfterInput={AfterInput}
BeforeInput={BeforeInput} BeforeInput={BeforeInput}
Label={Label} CustomLabel={CustomLabel}
checked={checked} checked={checked}
id={fieldID} id={fieldID}
inputRef={null} inputRef={null}
labelProps={labelProps}
name={path} name={path}
onToggle={onToggle} onToggle={onToggle}
partialChecked={partialChecked} partialChecked={partialChecked}
readOnly={readOnly} readOnly={readOnly}
required={required} required={required}
/> />
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -2,12 +2,14 @@
'use client' 'use client'
import type { CodeField as CodeFieldType, FieldBase } from 'payload/types' import type { CodeField as CodeFieldType, FieldBase } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
import { CodeEditor } from '../../elements/CodeEditor/index.js' import { CodeEditor } from '../../elements/CodeEditor/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
@@ -34,12 +36,14 @@ const CodeField: React.FC<CodeFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
editorOptions = {}, editorOptions = {},
label, errorProps,
labelProps,
language = 'javascript', language = 'javascript',
path: pathFromProps, path: pathFromProps,
readOnly, readOnly,
@@ -49,8 +53,6 @@ const CodeField: React.FC<CodeFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const memoizedValidate = useCallback( const memoizedValidate = useCallback(
(value, options) => { (value, options) => {
if (typeof validate === 'function') { if (typeof validate === 'function') {
@@ -81,8 +83,8 @@ const CodeField: React.FC<CodeFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div> <div>
{BeforeInput} {BeforeInput}
<CodeEditor <CodeEditor
@@ -94,7 +96,7 @@ const CodeField: React.FC<CodeFieldProps> = (props) => {
/> />
{AfterInput} {AfterInput}
</div> </div>
{Description} {CustomDescription ? CustomDescription : <FieldDescription {...(descriptionProps || {})} />}
</div> </div>
) )
} }

View File

@@ -7,7 +7,6 @@ import React, { Fragment, useCallback, useEffect, useState } from 'react'
import { Collapsible as CollapsibleElement } from '../../elements/Collapsible/index.js' import { Collapsible as CollapsibleElement } from '../../elements/Collapsible/index.js'
import { ErrorPill } from '../../elements/ErrorPill/index.js' import { ErrorPill } from '../../elements/ErrorPill/index.js'
import { useFieldProps } from '../../forms/FieldPropsProvider/index.js' import { useFieldProps } from '../../forms/FieldPropsProvider/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { RenderFields } from '../../forms/RenderFields/index.js' import { RenderFields } from '../../forms/RenderFields/index.js'
import { WatchChildErrors } from '../../forms/WatchChildErrors/index.js' import { WatchChildErrors } from '../../forms/WatchChildErrors/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
@@ -22,6 +21,9 @@ const baseClass = 'collapsible-field'
import type { FieldPermissions } from 'payload/auth' import type { FieldPermissions } from 'payload/auth'
import type { FieldBase } from 'payload/types' import type { FieldBase } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js' import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
@@ -36,18 +38,16 @@ export type CollapsibleFieldProps = FormFieldBase & {
const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => { const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
const { const {
Description, CustomDescription,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
fieldMap, fieldMap,
initCollapsed = false, initCollapsed = false,
label, labelProps,
path: pathFromProps, path: pathFromProps,
required,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { path: pathFromContext, readOnly, schemaPath, siblingPermissions } = useFieldProps() const { path: pathFromContext, readOnly, schemaPath, siblingPermissions } = useFieldProps()
const path = pathFromProps || pathFromContext const path = pathFromProps || pathFromContext
@@ -126,7 +126,7 @@ const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
collapsibleStyle={fieldHasErrors ? 'error' : 'default'} collapsibleStyle={fieldHasErrors ? 'error' : 'default'}
header={ header={
<div className={`${baseClass}__row-label-wrap`}> <div className={`${baseClass}__row-label-wrap`}>
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />} {fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
</div> </div>
} }
@@ -143,7 +143,11 @@ const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
schemaPath={schemaPath} schemaPath={schemaPath}
/> />
</CollapsibleElement> </CollapsibleElement>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
</Fragment> </Fragment>
) )

View File

@@ -3,9 +3,9 @@ import type { FormField } from 'payload/types'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { Error } from '../../forms/Error/index.js' import { FieldError } from '../../forms/FieldError/index.js'
import { FieldLabel } from '../../forms/FieldLabel/index.js'
import { useFormFields } from '../../forms/Form/context.js' import { useFormFields } from '../../forms/Form/context.js'
import { Label } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
@@ -50,8 +50,8 @@ export const ConfirmPassword: React.FC<ConfirmPasswordFieldProps> = (props) => {
.filter(Boolean) .filter(Boolean)
.join(' ')} .join(' ')}
> >
<Error path={path} /> <FieldError path={path} />
<Label <FieldLabel
htmlFor="field-confirm-password" htmlFor="field-confirm-password"
label={t('authentication:confirmPassword')} label={t('authentication:confirmPassword')}
required required

View File

@@ -6,7 +6,7 @@ import { getTranslation } from '@payloadcms/translations'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { DatePickerField } from '../../elements/DatePicker/index.js' import { DatePickerField } from '../../elements/DatePicker/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js' import { FieldLabel } from '../../forms/FieldLabel/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
@@ -16,6 +16,9 @@ const baseClass = 'date-time-field'
import type { DateField, FieldBase } from 'payload/types' import type { DateField, FieldBase } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
@@ -34,12 +37,14 @@ const DateTimeField: React.FC<DateFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
date: datePickerProps, date: datePickerProps,
label, descriptionProps,
errorProps,
labelProps,
path: pathFromProps, path: pathFromProps,
placeholder, placeholder,
readOnly, readOnly,
@@ -49,8 +54,6 @@ const DateTimeField: React.FC<DateFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n } = useTranslation() const { i18n } = useTranslation()
const memoizedValidate: ClientValidate = useCallback( const memoizedValidate: ClientValidate = useCallback(
@@ -83,8 +86,10 @@ const DateTimeField: React.FC<DateFieldProps> = (props) => {
width, width,
}} }}
> >
<div className={`${baseClass}__error-wrap`}>{Error}</div> <div className={`${baseClass}__error-wrap`}>
{Label} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
</div>
{CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div className={`${baseClass}__input-wrapper`} id={`field-${path.replace(/\./g, '__')}`}> <div className={`${baseClass}__input-wrapper`} id={`field-${path.replace(/\./g, '__')}`}>
{BeforeInput} {BeforeInput}
<DatePickerField <DatePickerField
@@ -98,7 +103,11 @@ const DateTimeField: React.FC<DateFieldProps> = (props) => {
/> />
{AfterInput} {AfterInput}
</div> </div>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -3,11 +3,13 @@ import type { ClientValidate } from 'payload/types'
import type { EmailField as EmailFieldType, FieldBase } from 'payload/types' import type { EmailField as EmailFieldType, FieldBase } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
@@ -28,12 +30,14 @@ const EmailField: React.FC<EmailFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
autoComplete, autoComplete,
className, className,
label, descriptionProps,
errorProps,
labelProps,
path: pathFromProps, path: pathFromProps,
placeholder, placeholder,
readOnly, readOnly,
@@ -43,8 +47,6 @@ const EmailField: React.FC<EmailFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n } = useTranslation() const { i18n } = useTranslation()
const memoizedValidate: ClientValidate = useCallback( const memoizedValidate: ClientValidate = useCallback(
@@ -71,8 +73,8 @@ const EmailField: React.FC<EmailFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div> <div>
{BeforeInput} {BeforeInput}
<input <input
@@ -87,7 +89,11 @@ const EmailField: React.FC<EmailFieldProps> = (props) => {
/> />
{AfterInput} {AfterInput}
</div> </div>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -2,6 +2,8 @@
import type { FieldPermissions } from 'payload/auth' import type { FieldPermissions } from 'payload/auth'
import type { FieldBase } from 'payload/types' import type { FieldBase } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { Fragment } from 'react' import React, { Fragment } from 'react'
import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js' import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js'
@@ -10,7 +12,6 @@ import type { FormFieldBase } from '../shared/index.js'
import { useCollapsible } from '../../elements/Collapsible/provider.js' import { useCollapsible } from '../../elements/Collapsible/provider.js'
import { ErrorPill } from '../../elements/ErrorPill/index.js' import { ErrorPill } from '../../elements/ErrorPill/index.js'
import { useFieldProps } from '../../forms/FieldPropsProvider/index.js' import { useFieldProps } from '../../forms/FieldPropsProvider/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { RenderFields } from '../../forms/RenderFields/index.js' import { RenderFields } from '../../forms/RenderFields/index.js'
import { WatchChildErrors } from '../../forms/WatchChildErrors/index.js' import { WatchChildErrors } from '../../forms/WatchChildErrors/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
@@ -36,19 +37,17 @@ export type GroupFieldProps = FormFieldBase & {
const GroupField: React.FC<GroupFieldProps> = (props) => { const GroupField: React.FC<GroupFieldProps> = (props) => {
const { const {
Description, CustomDescription,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
fieldMap, fieldMap,
hideGutter, hideGutter,
label, labelProps,
required,
style, style,
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { path, permissions, readOnly, schemaPath } = useFieldProps() const { path, permissions, readOnly, schemaPath } = useFieldProps()
const { i18n } = useTranslation() const { i18n } = useTranslation()
const isWithinCollapsible = useCollapsible() const isWithinCollapsible = useCollapsible()
@@ -87,10 +86,14 @@ const GroupField: React.FC<GroupFieldProps> = (props) => {
<GroupProvider> <GroupProvider>
<div className={`${baseClass}__wrap`}> <div className={`${baseClass}__wrap`}>
<div className={`${baseClass}__header`}> <div className={`${baseClass}__header`}>
{(Label || Description) && ( {(CustomLabel || CustomDescription) && (
<header> <header>
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</header> </header>
)} )}
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />} {fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}

View File

@@ -1,10 +1,12 @@
'use client' 'use client'
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import type { FormFieldBase } from '../index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
export type HiddenInputFieldProps = { export type HiddenInputFieldProps = FormFieldBase & {
disableModifyingForm?: false disableModifyingForm?: false
name: string name: string
path?: string path?: string

View File

@@ -4,7 +4,7 @@ import type { ClientValidate } from 'payload/types'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
import { CodeEditor } from '../../elements/CodeEditor/index.js' import { CodeEditor } from '../../elements/CodeEditor/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js' import { FieldLabel } from '../../forms/FieldLabel/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
@@ -14,6 +14,9 @@ const baseClass = 'json-field'
import type { FieldBase, JSONField as JSONFieldType } from 'payload/types' import type { FieldBase, JSONField as JSONFieldType } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
export type JSONFieldProps = FormFieldBase & { export type JSONFieldProps = FormFieldBase & {
@@ -29,12 +32,14 @@ const JSONFieldComponent: React.FC<JSONFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
editorOptions, editorOptions,
label, errorProps,
labelProps,
path: pathFromProps, path: pathFromProps,
readOnly, readOnly,
required, required,
@@ -43,8 +48,6 @@ const JSONFieldComponent: React.FC<JSONFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const [stringValue, setStringValue] = useState<string>() const [stringValue, setStringValue] = useState<string>()
const [jsonError, setJsonError] = useState<string>() const [jsonError, setJsonError] = useState<string>()
const [hasLoadedValue, setHasLoadedValue] = useState(false) const [hasLoadedValue, setHasLoadedValue] = useState(false)
@@ -108,8 +111,8 @@ const JSONFieldComponent: React.FC<JSONFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div> <div>
{BeforeInput} {BeforeInput}
<CodeEditor <CodeEditor
@@ -121,7 +124,11 @@ const JSONFieldComponent: React.FC<JSONFieldProps> = (props) => {
/> />
{AfterInput} {AfterInput}
</div> </div>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -3,6 +3,9 @@
import type { FieldBase, NumberField as NumberFieldType } from 'payload/types' import type { FieldBase, NumberField as NumberFieldType } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { isNumber } from 'payload/utilities' import { isNumber } from 'payload/utilities'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
@@ -10,7 +13,6 @@ import type { Option } from '../../elements/ReactSelect/types.js'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
import { ReactSelect } from '../../elements/ReactSelect/index.js' import { ReactSelect } from '../../elements/ReactSelect/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
@@ -36,12 +38,14 @@ const NumberFieldComponent: React.FC<NumberFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
errorProps,
hasMany = false, hasMany = false,
label, labelProps,
max = Infinity, max = Infinity,
maxRows = Infinity, maxRows = Infinity,
min = -Infinity, min = -Infinity,
@@ -56,8 +60,6 @@ const NumberFieldComponent: React.FC<NumberFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n, t } = useTranslation() const { i18n, t } = useTranslation()
const memoizedValidate = useCallback( const memoizedValidate = useCallback(
@@ -149,8 +151,8 @@ const NumberFieldComponent: React.FC<NumberFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{Label} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{hasMany ? ( {hasMany ? (
<ReactSelect <ReactSelect
className={`field-${path.replace(/\./g, '__')}`} className={`field-${path.replace(/\./g, '__')}`}
@@ -201,7 +203,11 @@ const NumberFieldComponent: React.FC<NumberFieldProps> = (props) => {
{AfterInput} {AfterInput}
</div> </div>
)} )}
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -1,11 +1,12 @@
'use client' 'use client'
import type { ClientValidate, Description, Validate } from 'payload/types' import type { ClientValidate, Description, Validate } from 'payload/types'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
@@ -28,12 +29,13 @@ export type PasswordFieldProps = FormFieldBase & {
export const PasswordField: React.FC<PasswordFieldProps> = (props) => { export const PasswordField: React.FC<PasswordFieldProps> = (props) => {
const { const {
name, name,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
autoComplete, autoComplete,
className, className,
disabled, disabled,
label, errorProps,
labelProps,
path: pathFromProps, path: pathFromProps,
required, required,
style, style,
@@ -41,8 +43,6 @@ export const PasswordField: React.FC<PasswordFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const memoizedValidate: ClientValidate = useCallback( const memoizedValidate: ClientValidate = useCallback(
(value, options) => { (value, options) => {
if (typeof validate === 'function') { if (typeof validate === 'function') {
@@ -67,8 +67,8 @@ export const PasswordField: React.FC<PasswordFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<input <input
autoComplete={autoComplete} autoComplete={autoComplete}
disabled={formProcessing || disabled} disabled={formProcessing || disabled}

View File

@@ -5,7 +5,6 @@ import type { ClientValidate, FieldBase } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
@@ -14,6 +13,10 @@ import './index.scss'
const baseClass = 'point' const baseClass = 'point'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
export type PointFieldProps = FormFieldBase & { export type PointFieldProps = FormFieldBase & {
@@ -30,11 +33,13 @@ const PointField: React.FC<PointFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
label, descriptionProps,
errorProps,
labelProps,
path: pathFromProps, path: pathFromProps,
placeholder, placeholder,
readOnly, readOnly,
@@ -45,8 +50,6 @@ const PointField: React.FC<PointFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n } = useTranslation() const { i18n } = useTranslation()
const memoizedValidate: ClientValidate = useCallback( const memoizedValidate: ClientValidate = useCallback(
@@ -97,10 +100,10 @@ const PointField: React.FC<PointFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
<ul className={`${baseClass}__wrap`}> <ul className={`${baseClass}__wrap`}>
<li> <li>
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div className="input-wrapper"> <div className="input-wrapper">
{BeforeInput} {BeforeInput}
<input <input
@@ -117,7 +120,7 @@ const PointField: React.FC<PointFieldProps> = (props) => {
</div> </div>
</li> </li>
<li> <li>
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div className="input-wrapper"> <div className="input-wrapper">
{BeforeInput} {BeforeInput}
<input <input
@@ -134,7 +137,11 @@ const PointField: React.FC<PointFieldProps> = (props) => {
</div> </div>
</li> </li>
</ul> </ul>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -6,8 +6,8 @@ import type { FieldBase, Option } from 'payload/types'
import { optionIsObject } from 'payload/types' import { optionIsObject } from 'payload/types'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { FieldLabel } from '../../forms/FieldLabel/index.js'
import { useForm } from '../../forms/Form/context.js' import { useForm } from '../../forms/Form/context.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
@@ -16,6 +16,9 @@ import './index.scss'
const baseClass = 'radio-group' const baseClass = 'radio-group'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
export type RadioFieldProps = FormFieldBase & { export type RadioFieldProps = FormFieldBase & {
@@ -34,11 +37,13 @@ export type OnChange<T = string> = (value: T) => void
const RadioGroupField: React.FC<RadioFieldProps> = (props) => { const RadioGroupField: React.FC<RadioFieldProps> = (props) => {
const { const {
name, name,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
label, descriptionProps,
errorProps,
labelProps,
layout = 'horizontal', layout = 'horizontal',
onChange: onChangeFromProps, onChange: onChangeFromProps,
options = [], options = [],
@@ -53,8 +58,6 @@ const RadioGroupField: React.FC<RadioFieldProps> = (props) => {
const { uuid } = useForm() const { uuid } = useForm()
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const memoizedValidate = useCallback( const memoizedValidate = useCallback(
(value, validationOptions) => { (value, validationOptions) => {
if (typeof validate === 'function') if (typeof validate === 'function')
@@ -92,8 +95,10 @@ const RadioGroupField: React.FC<RadioFieldProps> = (props) => {
width, width,
}} }}
> >
<div className={`${baseClass}__error-wrap`}>{Error}</div> <div className={`${baseClass}__error-wrap`}>
{Label} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
</div>
{CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<ul className={`${baseClass}--group`} id={`field-${path.replace(/\./g, '__')}`}> <ul className={`${baseClass}--group`} id={`field-${path.replace(/\./g, '__')}`}>
{options.map((option) => { {options.map((option) => {
let optionValue = '' let optionValue = ''
@@ -130,7 +135,11 @@ const RadioGroupField: React.FC<RadioFieldProps> = (props) => {
) )
})} })}
</ul> </ul>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -2,6 +2,9 @@
import type { PaginatedDocs } from 'payload/database' import type { PaginatedDocs } from 'payload/database'
import type { Where } from 'payload/types' import type { Where } from 'payload/types'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import { wordBoundariesRegex } from 'payload/utilities' import { wordBoundariesRegex } from 'payload/utilities'
import qs from 'qs' import qs from 'qs'
import React, { useCallback, useEffect, useReducer, useRef, useState } from 'react' import React, { useCallback, useEffect, useReducer, useRef, useState } from 'react'
@@ -36,13 +39,16 @@ export { RelationshipFieldProps }
const RelationshipField: React.FC<RelationshipFieldProps> = (props) => { const RelationshipField: React.FC<RelationshipFieldProps> = (props) => {
const { const {
name, name,
Description, CustomDescription,
Error, CustomError,
Label, CustomLabel,
allowCreate = true, allowCreate = true,
className, className,
descriptionProps,
errorProps,
hasMany, hasMany,
isSortable = true, isSortable = true,
labelProps,
path: pathFromProps, path: pathFromProps,
readOnly, readOnly,
relationTo, relationTo,
@@ -434,8 +440,8 @@ const RelationshipField: React.FC<RelationshipFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{!errorLoading && ( {!errorLoading && (
<div className={`${baseClass}__wrap`}> <div className={`${baseClass}__wrap`}>
<ReactSelect <ReactSelect
@@ -527,7 +533,11 @@ const RelationshipField: React.FC<RelationshipFieldProps> = (props) => {
</div> </div>
)} )}
{errorLoading && <div className={`${baseClass}__error-loading`}>{errorLoading}</div>} {errorLoading && <div className={`${baseClass}__error-loading`}>{errorLoading}</div>}
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -3,12 +3,14 @@
import type { ClientValidate, FieldBase, Option, OptionObject } from 'payload/types' import type { ClientValidate, FieldBase, Option, OptionObject } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { useCallback, useState } from 'react' import React, { useCallback, useState } from 'react'
import type { FormFieldBase } from '../shared/index.js' import type { FormFieldBase } from '../shared/index.js'
import { ReactSelect } from '../../elements/ReactSelect/index.js' import { ReactSelect } from '../../elements/ReactSelect/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
@@ -45,14 +47,16 @@ export const SelectField: React.FC<SelectFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
errorProps,
hasMany = false, hasMany = false,
isClearable = true, isClearable = true,
isSortable = true, isSortable = true,
label, labelProps,
onChange: onChangeFromProps, onChange: onChangeFromProps,
options: optionsFromProps = [], options: optionsFromProps = [],
path: pathFromProps, path: pathFromProps,
@@ -63,8 +67,6 @@ export const SelectField: React.FC<SelectFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n } = useTranslation() const { i18n } = useTranslation()
const [options] = useState(formatOptions(optionsFromProps)) const [options] = useState(formatOptions(optionsFromProps))
@@ -143,8 +145,8 @@ export const SelectField: React.FC<SelectFieldProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
<div> <div>
{BeforeInput} {BeforeInput}
<ReactSelect <ReactSelect
@@ -162,7 +164,11 @@ export const SelectField: React.FC<SelectFieldProps> = (props) => {
/> />
{AfterInput} {AfterInput}
</div> </div>
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -3,6 +3,7 @@ import type { FieldPermissions } from 'payload/auth'
import type { DocumentPreferences } from 'payload/types' import type { DocumentPreferences } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { toKebabCase } from 'payload/utilities' import { toKebabCase } from 'payload/utilities'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
@@ -39,8 +40,9 @@ export type TabsFieldProps = FormFieldBase & {
const TabsField: React.FC<TabsFieldProps> = (props) => { const TabsField: React.FC<TabsFieldProps> = (props) => {
const { const {
name, name,
Description, CustomDescription,
className, className,
descriptionProps,
forceRender = false, forceRender = false,
indexPath, indexPath,
path: pathFromProps, path: pathFromProps,
@@ -143,7 +145,11 @@ const TabsField: React.FC<TabsFieldProps> = (props) => {
.filter(Boolean) .filter(Boolean)
.join(' ')} .join(' ')}
> >
{Description} {CustomDescription ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
<RenderFields <RenderFields
fieldMap={activeTabConfig.fieldMap} fieldMap={activeTabConfig.fieldMap}
forceRender={forceRender} forceRender={forceRender}

View File

@@ -1,5 +1,8 @@
'use client' 'use client'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React from 'react' import React from 'react'
import type { TextInputProps } from './types.js' import type { TextInputProps } from './types.js'
@@ -13,12 +16,15 @@ export const TextInput: React.FC<TextInputProps> = (props) => {
const { const {
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label, CustomLabel,
className, className,
descriptionProps,
errorProps,
hasMany, hasMany,
inputRef, inputRef,
labelProps,
maxRows, maxRows,
onChange, onChange,
onKeyDown, onKeyDown,
@@ -52,8 +58,8 @@ export const TextInput: React.FC<TextInputProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{hasMany ? ( {hasMany ? (
<ReactSelect <ReactSelect
className={`field-${path.replace(/\./g, '__')}`} className={`field-${path.replace(/\./g, '__')}`}
@@ -97,7 +103,11 @@ export const TextInput: React.FC<TextInputProps> = (props) => {
{AfterInput} {AfterInput}
</div> </div>
)} )}
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -7,7 +7,6 @@ import React, { useCallback, useEffect, useState } from 'react'
import type { Option } from '../../elements/ReactSelect/types.js' import type { Option } from '../../elements/ReactSelect/types.js'
import type { TextFieldProps, TextInputProps } from './types.js' import type { TextFieldProps, TextInputProps } from './types.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { useConfig } from '../../providers/Config/index.js' import { useConfig } from '../../providers/Config/index.js'
@@ -23,13 +22,15 @@ const TextField: React.FC<TextFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
errorProps,
hasMany, hasMany,
inputRef, inputRef,
label, labelProps,
localized, localized,
maxLength, maxLength,
maxRows, maxRows,
@@ -44,8 +45,6 @@ const TextField: React.FC<TextFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const locale = useLocale() const locale = useLocale()
const { localization: localizationConfig } = useConfig() const { localization: localizationConfig } = useConfig()
@@ -115,12 +114,15 @@ const TextField: React.FC<TextFieldProps> = (props) => {
<TextInput <TextInput
AfterInput={AfterInput} AfterInput={AfterInput}
BeforeInput={BeforeInput} BeforeInput={BeforeInput}
Description={Description} CustomDescription={CustomDescription}
Error={Error} CustomError={CustomError}
Label={Label} CustomLabel={CustomLabel}
className={className} className={className}
descriptionProps={descriptionProps}
errorProps={errorProps}
hasMany={hasMany} hasMany={hasMany}
inputRef={inputRef} inputRef={inputRef}
labelProps={labelProps}
maxRows={maxRows} maxRows={maxRows}
minRows={minRows} minRows={minRows}
onChange={ onChange={

View File

@@ -1,5 +1,8 @@
'use client' 'use client'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React from 'react' import React from 'react'
import type { TextAreaInputProps } from './types.js' import type { TextAreaInputProps } from './types.js'
@@ -12,10 +15,13 @@ export const TextareaInput: React.FC<TextAreaInputProps> = (props) => {
const { const {
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label, CustomLabel,
className, className,
descriptionProps,
errorProps,
labelProps,
onChange, onChange,
path, path,
placeholder, placeholder,
@@ -46,8 +52,8 @@ export const TextareaInput: React.FC<TextAreaInputProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{BeforeInput} {BeforeInput}
<label className="textarea-outer" htmlFor={`field-${path.replace(/\./g, '__')}`}> <label className="textarea-outer" htmlFor={`field-${path.replace(/\./g, '__')}`}>
<div className="textarea-inner"> <div className="textarea-inner">
@@ -66,7 +72,11 @@ export const TextareaInput: React.FC<TextAreaInputProps> = (props) => {
</div> </div>
</label> </label>
{AfterInput} {AfterInput}
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</div> </div>
) )
} }

View File

@@ -7,7 +7,6 @@ import React, { useCallback } from 'react'
import type { TextAreaInputProps, TextareaFieldProps } from './types.js' import type { TextAreaInputProps, TextareaFieldProps } from './types.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { withCondition } from '../../forms/withCondition/index.js' import { withCondition } from '../../forms/withCondition/index.js'
import { useConfig } from '../../providers/Config/index.js' import { useConfig } from '../../providers/Config/index.js'
@@ -23,11 +22,13 @@ const TextareaField: React.FC<TextareaFieldProps> = (props) => {
name, name,
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
label, descriptionProps,
errorProps,
labelProps,
locale, locale,
localized, localized,
maxLength, maxLength,
@@ -42,8 +43,6 @@ const TextareaField: React.FC<TextareaFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n } = useTranslation() const { i18n } = useTranslation()
const { localization } = useConfig() const { localization } = useConfig()
@@ -72,10 +71,13 @@ const TextareaField: React.FC<TextareaFieldProps> = (props) => {
<TextareaInput <TextareaInput
AfterInput={AfterInput} AfterInput={AfterInput}
BeforeInput={BeforeInput} BeforeInput={BeforeInput}
Description={Description} CustomDescription={CustomDescription}
Error={Error} CustomError={CustomError}
Label={Label} CustomLabel={CustomLabel}
className={className} className={className}
descriptionProps={descriptionProps}
errorProps={errorProps}
labelProps={labelProps}
onChange={(e) => { onChange={(e) => {
setValue(e.target.value) setValue(e.target.value)
}} }}

View File

@@ -3,6 +3,9 @@
import type { ClientCollectionConfig, FilterOptionsResult, UploadField } from 'payload/types' import type { ClientCollectionConfig, FilterOptionsResult, UploadField } from 'payload/types'
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
import { FieldError } from '@payloadcms/ui/forms/FieldError'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
import type { DocumentDrawerProps } from '../../elements/DocumentDrawer/types.js' import type { DocumentDrawerProps } from '../../elements/DocumentDrawer/types.js'
@@ -13,7 +16,6 @@ import { Button } from '../../elements/Button/index.js'
import { useDocumentDrawer } from '../../elements/DocumentDrawer/index.js' import { useDocumentDrawer } from '../../elements/DocumentDrawer/index.js'
import { FileDetails } from '../../elements/FileDetails/index.js' import { FileDetails } from '../../elements/FileDetails/index.js'
import { useListDrawer } from '../../elements/ListDrawer/index.js' import { useListDrawer } from '../../elements/ListDrawer/index.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
import { fieldBaseClass } from '../shared/index.js' import { fieldBaseClass } from '../shared/index.js'
import './index.scss' import './index.scss'
@@ -33,14 +35,17 @@ export type UploadInputProps = Omit<UploadFieldProps, 'filterOptions'> & {
export const UploadInput: React.FC<UploadInputProps> = (props) => { export const UploadInput: React.FC<UploadInputProps> = (props) => {
const { const {
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
api = '/api', api = '/api',
className, className,
collection, collection,
descriptionProps,
errorProps,
filterOptions, filterOptions,
label, label,
labelProps,
onChange, onChange,
readOnly, readOnly,
relationTo, relationTo,
@@ -52,8 +57,6 @@ export const UploadInput: React.FC<UploadInputProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { i18n, t } = useTranslation() const { i18n, t } = useTranslation()
const [file, setFile] = useState(undefined) const [file, setFile] = useState(undefined)
@@ -130,8 +133,8 @@ export const UploadInput: React.FC<UploadInputProps> = (props) => {
width, width,
}} }}
> >
{Error} {CustomError !== undefined ? CustomError : <FieldError {...(errorProps || {})} />}
{Label} {CustomLabel !== undefined ? CustomLabel : <FieldLabel {...(labelProps || {})} />}
{collection?.upload && ( {collection?.upload && (
<React.Fragment> <React.Fragment>
{file && !missingFile && ( {file && !missingFile && (
@@ -166,7 +169,11 @@ export const UploadInput: React.FC<UploadInputProps> = (props) => {
</div> </div>
</div> </div>
)} )}
{Description} {CustomDescription !== undefined ? (
CustomDescription
) : (
<FieldDescription {...(descriptionProps || {})} />
)}
</React.Fragment> </React.Fragment>
)} )}
{!readOnly && <DocumentDrawer onSave={onSave} />} {!readOnly && <DocumentDrawer onSave={onSave} />}

View File

@@ -4,7 +4,6 @@ import React, { useCallback } from 'react'
import type { UploadInputProps } from './Input.js' import type { UploadInputProps } from './Input.js'
import type { UploadFieldProps } from './types.js' import type { UploadFieldProps } from './types.js'
import { Label as LabelComp } from '../../forms/Label/index.js'
import { useField } from '../../forms/useField/index.js' import { useField } from '../../forms/useField/index.js'
import { useConfig } from '../../providers/Config/index.js' import { useConfig } from '../../providers/Config/index.js'
import { UploadInput } from './Input.js' import { UploadInput } from './Input.js'
@@ -15,11 +14,14 @@ export type { UploadInputProps }
export const Upload: React.FC<UploadFieldProps> = (props) => { export const Upload: React.FC<UploadFieldProps> = (props) => {
const { const {
Description, CustomDescription,
Error, CustomError,
Label: LabelFromProps, CustomLabel,
className, className,
descriptionProps,
errorProps,
label, label,
labelProps,
path: pathFromProps, path: pathFromProps,
readOnly, readOnly,
relationTo, relationTo,
@@ -29,8 +31,6 @@ export const Upload: React.FC<UploadFieldProps> = (props) => {
width, width,
} = props } = props
const Label = LabelFromProps || <LabelComp label={label} required={required} />
const { const {
collections, collections,
routes: { api }, routes: { api },
@@ -64,13 +64,16 @@ export const Upload: React.FC<UploadFieldProps> = (props) => {
if (collection.upload) { if (collection.upload) {
return ( return (
<UploadInput <UploadInput
Description={Description} CustomDescription={CustomDescription}
Error={Error} CustomError={CustomError}
Label={Label} CustomLabel={CustomLabel}
api={api} api={api}
className={className} className={className}
collection={collection} collection={collection}
descriptionProps={descriptionProps}
errorProps={errorProps}
filterOptions={filterOptions} filterOptions={filterOptions}
labelProps={labelProps}
onChange={onChange} onChange={onChange}
path={path} path={path}
readOnly={readOnly} readOnly={readOnly}

View File

@@ -1,18 +1,23 @@
import type { User } from 'payload/auth' import type { User } from 'payload/auth'
import type { Locale, SanitizedLocalizationConfig } from 'payload/config' import type { Locale, SanitizedLocalizationConfig } from 'payload/config'
import type { DocumentPreferences, Validate } from 'payload/types' import type { DocumentPreferences, ErrorProps, LabelProps, Validate } from 'payload/types'
import type { FieldDescriptionProps } from '../../forms/FieldDescription/types.js'
export const fieldBaseClass = 'field-type' export const fieldBaseClass = 'field-type'
export type FormFieldBase = { export type FormFieldBase = {
AfterInput?: React.ReactNode AfterInput?: React.ReactNode
BeforeInput?: React.ReactNode BeforeInput?: React.ReactNode
Description?: React.ReactNode CustomDescription?: React.ReactNode
Error?: React.ReactNode CustomError?: React.ReactNode
Label?: React.ReactNode CustomLabel?: React.ReactNode
className?: string className?: string
descriptionProps?: FieldDescriptionProps
disabled?: boolean disabled?: boolean
docPreferences?: DocumentPreferences docPreferences?: DocumentPreferences
errorProps?: ErrorProps
labelProps?: LabelProps
locale?: Locale locale?: Locale
localized?: boolean localized?: boolean
path?: string path?: string

View File

@@ -2,17 +2,17 @@
import { getTranslation } from '@payloadcms/translations' import { getTranslation } from '@payloadcms/translations'
import React from 'react' import React from 'react'
import type { Props } from './types.js' import type { FieldDescriptionProps } from './types.js'
import { useTranslation } from '../../providers/Translation/index.js' import { useTranslation } from '../../providers/Translation/index.js'
import { useFieldProps } from '../FieldPropsProvider/index.js' import { useFieldProps } from '../FieldPropsProvider/index.js'
import './index.scss' import './index.scss'
export { Props as FieldDescriptionProps } export { FieldDescriptionProps }
const baseClass = 'field-description' const baseClass = 'field-description'
export const FieldDescription: React.FC<Props> = (props) => { export const FieldDescription: React.FC<FieldDescriptionProps> = (props) => {
const { className, description, marginPlacement } = props const { className, description, marginPlacement } = props
const { path } = useFieldProps() const { path } = useFieldProps()

View File

@@ -1,4 +1,4 @@
export type Props = { export type FieldDescriptionProps = {
className?: string className?: string
description?: Record<string, string> | string description?: Record<string, string> | string
marginPlacement?: 'bottom' | 'top' marginPlacement?: 'bottom' | 'top'

View File

@@ -11,7 +11,7 @@ import './index.scss'
const baseClass = 'field-error' const baseClass = 'field-error'
export const Error: React.FC<ErrorProps> = (props) => { export const FieldError: React.FC<ErrorProps> = (props) => {
const { const {
alignCaret = 'right', alignCaret = 'right',
message: messageFromProps, message: messageFromProps,

View File

@@ -10,7 +10,7 @@ import { useFieldProps } from '../FieldPropsProvider/index.js'
import { useForm } from '../Form/context.js' import { useForm } from '../Form/context.js'
import './index.scss' import './index.scss'
export const Label: React.FC<LabelProps> = (props) => { export const FieldLabel: React.FC<LabelProps> = (props) => {
const { htmlFor: htmlForFromProps, label: labelFromProps, required = false } = props const { htmlFor: htmlForFromProps, label: labelFromProps, required = false } = props
const { uuid } = useForm() const { uuid } = useForm()
const { path } = useFieldProps() const { path } = useFieldProps()

View File

@@ -30,6 +30,7 @@ export const buildComponentMap = (args: {
} }
const editViewFromConfig = collectionConfig?.admin?.components?.views?.Edit const editViewFromConfig = collectionConfig?.admin?.components?.views?.Edit
const listViewFromConfig = collectionConfig?.admin?.components?.views?.List const listViewFromConfig = collectionConfig?.admin?.components?.views?.List
const CustomEditView = const CustomEditView =
@@ -52,6 +53,7 @@ export const buildComponentMap = (args: {
: undefined : undefined
const Edit = (CustomEditView as React.FC<EditViewProps>) || DefaultEditView const Edit = (CustomEditView as React.FC<EditViewProps>) || DefaultEditView
const List = CustomListView || DefaultListView const List = CustomListView || DefaultListView
const beforeList = collectionConfig?.admin?.components?.BeforeList const beforeList = collectionConfig?.admin?.components?.BeforeList

View File

@@ -1,3 +1,4 @@
import type { FieldDescriptionProps } from '@payloadcms/ui/forms/FieldDescription'
import type { CellProps, Field, FieldWithPath, LabelProps, SanitizedConfig } from 'payload/types' import type { CellProps, Field, FieldWithPath, LabelProps, SanitizedConfig } from 'payload/types'
import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/types' import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/types'
@@ -25,7 +26,6 @@ import type { TextFieldProps } from '../../../fields/Text/types.js'
import type { TextareaFieldProps } from '../../../fields/Textarea/types.js' import type { TextareaFieldProps } from '../../../fields/Textarea/types.js'
import type { UploadFieldProps } from '../../../fields/Upload/types.js' import type { UploadFieldProps } from '../../../fields/Upload/types.js'
import type { FormFieldBase } from '../../../fields/shared/index.js' import type { FormFieldBase } from '../../../fields/shared/index.js'
import type { Props as FieldDescription } from '../../../forms/FieldDescription/types.js'
import type { import type {
FieldComponentProps, FieldComponentProps,
FieldMap, FieldMap,
@@ -34,11 +34,7 @@ import type {
ReducedBlock, ReducedBlock,
} from './types.js' } from './types.js'
import { RenderCustomComponent } from '../../../elements/RenderCustomComponent/index.js'
import { HiddenInput } from '../../../fields/HiddenInput/index.js' import { HiddenInput } from '../../../fields/HiddenInput/index.js'
import { Error as DefaultError } from '../../../forms/Error/index.js'
import { FieldDescription as DefaultDescription } from '../../../forms/FieldDescription/index.js'
import { Label as DefaultLabel } from '../../../forms/Label/index.js'
export const mapFields = (args: { export const mapFields = (args: {
config: SanitizedConfig config: SanitizedConfig
@@ -89,7 +85,7 @@ export const mapFields = (args: {
required: 'required' in field ? field.required : undefined, required: 'required' in field ? field.required : undefined,
} }
const descriptionProps: FieldDescription = { const descriptionProps: FieldDescriptionProps = {
description: description:
field.admin && field.admin &&
'description' in field.admin && 'description' in field.admin &&
@@ -111,75 +107,83 @@ export const mapFields = (args: {
readOnly: readOnlyOverride, readOnly: readOnlyOverride,
}) })
const AfterInput = 'admin' in field && const AfterInput =
'components' in field.admin && ('admin' in field &&
'afterInput' in field.admin.components && 'components' in field.admin &&
Array.isArray(field.admin?.components?.afterInput) && ( 'afterInput' in field.admin.components &&
<Fragment> Array.isArray(field.admin?.components?.afterInput) && (
{field.admin.components.afterInput.map((Component, i) => ( <Fragment>
<Component key={i} /> {field.admin.components.afterInput.map((Component, i) => (
))} <Component key={i} />
</Fragment> ))}
) </Fragment>
)) ||
null
const BeforeInput = 'admin' in field && const BeforeInput =
field.admin?.components && ('admin' in field &&
'beforeInput' in field.admin.components && field.admin?.components &&
Array.isArray(field.admin.components.beforeInput) && ( 'beforeInput' in field.admin.components &&
<Fragment> Array.isArray(field.admin.components.beforeInput) && (
{field.admin.components.beforeInput.map((Component, i) => ( <Fragment>
<Component key={i} /> {field.admin.components.beforeInput.map((Component, i) => (
))} <Component key={i} />
</Fragment> ))}
) </Fragment>
)) ||
null
const Description = ( const CustomDescriptionComponent =
<RenderCustomComponent (field.admin &&
CustomComponent={ 'description' in field.admin &&
field.admin && field.admin.description &&
'description' in field.admin && typeof field.admin.description === 'function' &&
field.admin.description && (field.admin.description as React.FC<any>)) ||
typeof field.admin.description === 'function' && undefined
(field.admin.description as React.FC<any>)
}
DefaultComponent={DefaultDescription}
componentProps={descriptionProps}
/>
)
const Error = ( const CustomDescription =
<RenderCustomComponent CustomDescriptionComponent !== undefined ? (
CustomComponent={ <CustomDescriptionComponent {...(descriptionProps || {})} />
'admin' in field && ) : undefined
field.admin.components &&
'Error' in field.admin.components &&
field.admin?.components?.Error
}
DefaultComponent={DefaultError}
componentProps={{ path }}
/>
)
const Label = ( const CustomErrorComponent =
<RenderCustomComponent ('admin' in field &&
CustomComponent={ field.admin?.components &&
'admin' in field && 'Error' in field.admin.components &&
field.admin?.components && field.admin?.components?.Error) ||
'Label' in field.admin.components && undefined
field.admin?.components?.Label
} const errorProps = {
DefaultComponent={DefaultLabel} path,
componentProps={labelProps} }
/>
) const CustomError =
CustomErrorComponent !== undefined ? (
<CustomErrorComponent {...(errorProps || {})} />
) : undefined
const CustomLabelComponent =
('admin' in field &&
field.admin?.components &&
'Label' in field.admin.components &&
field.admin?.components?.Label) ||
undefined
const CustomLabel =
CustomLabelComponent !== undefined ? (
<CustomLabelComponent {...(labelProps || {})} />
) : undefined
const baseFieldProps: FormFieldBase = { const baseFieldProps: FormFieldBase = {
AfterInput, AfterInput,
BeforeInput, BeforeInput,
Description, CustomDescription,
Error, CustomError,
Label, CustomLabel,
descriptionProps,
disabled: 'admin' in field && 'disabled' in field.admin ? field.admin?.disabled : false, disabled: 'admin' in field && 'disabled' in field.admin ? field.admin?.disabled : false,
errorProps,
labelProps,
path, path,
required: 'required' in field ? field.required : undefined, required: 'required' in field ? field.required : undefined,
} }
@@ -324,7 +328,7 @@ export const mapFields = (args: {
const collapsibleField: Omit<CollapsibleFieldProps, 'indexPath' | 'permissions'> = { const collapsibleField: Omit<CollapsibleFieldProps, 'indexPath' | 'permissions'> = {
...baseFieldProps, ...baseFieldProps,
Label: CollapsibleLabel, CustomLabel: CollapsibleLabel,
className: field.admin?.className, className: field.admin?.className,
disabled: field.admin?.disabled, disabled: field.admin?.disabled,
fieldMap: nestedFieldMap, fieldMap: nestedFieldMap,

View File

@@ -1,3 +1,4 @@
import type { HiddenInputFieldProps } from '@payloadcms/ui/fields/HiddenInput'
import type { FieldTypes } from 'payload/config' import type { FieldTypes } from 'payload/config'
import type { import type {
BlockField, BlockField,
@@ -50,6 +51,7 @@ export type FieldComponentProps =
| DateFieldProps | DateFieldProps
| EmailFieldProps | EmailFieldProps
| GroupFieldProps | GroupFieldProps
| HiddenInputFieldProps
| JSONFieldProps | JSONFieldProps
| NumberFieldProps | NumberFieldProps
| PointFieldProps | PointFieldProps