feat!: fix non-functional custom RSC component handling, separate label and description props, fix non-functional label function handling (#6264)
Breaking Changes: - Globals config: `admin.description` no longer accepts a custom component. You will have to move it to `admin.components.elements.Description` - Collections config: `admin.description` no longer accepts a custom component. You will have to move it to `admin.components.edit.Description` - All Fields: `field.admin.description` no longer accepts a custom component. You will have to move it to `field.admin.components.Description` - Collapsible Field: `field.label` no longer accepts a custom component. You will have to move it to `field.admin.components.RowLabel` - Array Field: `field.admin.components.RowLabel` no longer accepts strings or records - If you are using our exported field components in your own app, their `labelProps` property has been stripped down and no longer contains the `label` and `required` prop. Those can now only be configured at the top-level
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { AdminViewProps } from 'payload/types'
|
||||
|
||||
import { WithServerSideProps } from '@payloadcms/ui/elements/WithServerSideProps'
|
||||
import { Logo } from '@payloadcms/ui/graphics/Logo'
|
||||
import { redirect } from 'next/navigation.js'
|
||||
import React, { Fragment } from 'react'
|
||||
@@ -16,6 +17,7 @@ export const LoginView: React.FC<AdminViewProps> = ({ initPageResult, searchPara
|
||||
|
||||
const {
|
||||
payload: { config },
|
||||
payload,
|
||||
user,
|
||||
} = req
|
||||
|
||||
@@ -25,6 +27,18 @@ export const LoginView: React.FC<AdminViewProps> = ({ initPageResult, searchPara
|
||||
routes: { admin },
|
||||
} = config
|
||||
|
||||
const BeforeLogins = Array.isArray(beforeLogin)
|
||||
? beforeLogin.map((Component, i) => (
|
||||
<WithServerSideProps Component={Component} key={i} payload={payload} />
|
||||
))
|
||||
: null
|
||||
|
||||
const AfterLogins = Array.isArray(afterLogin)
|
||||
? afterLogin.map((Component, i) => (
|
||||
<WithServerSideProps Component={Component} key={i} payload={payload} />
|
||||
))
|
||||
: null
|
||||
|
||||
if (user) {
|
||||
redirect(admin)
|
||||
}
|
||||
@@ -36,9 +50,9 @@ export const LoginView: React.FC<AdminViewProps> = ({ initPageResult, searchPara
|
||||
<div className={`${loginBaseClass}__brand`}>
|
||||
<Logo config={config} />
|
||||
</div>
|
||||
{Array.isArray(beforeLogin) && beforeLogin.map((Component, i) => <Component key={i} />)}
|
||||
{Array.isArray(BeforeLogins) && BeforeLogins.map((Component) => Component)}
|
||||
{!collectionConfig?.auth?.disableLocalStrategy && <LoginForm searchParams={searchParams} />}
|
||||
{Array.isArray(afterLogin) && afterLogin.map((Component, i) => <Component key={i} />)}
|
||||
{Array.isArray(AfterLogins) && AfterLogins.map((Component) => Component)}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,11 +7,7 @@ export type DescriptionFunction = LabelFunction
|
||||
|
||||
export type DescriptionComponent = CustomComponent<FieldDescriptionProps>
|
||||
|
||||
export type Description =
|
||||
| DescriptionComponent
|
||||
| DescriptionFunction
|
||||
| Record<string, string>
|
||||
| string
|
||||
export type Description = DescriptionFunction | Record<string, string> | string
|
||||
|
||||
export type FieldDescriptionProps = {
|
||||
CustomDescription?: React.ReactNode
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { LabelFunction } from '../../config/types.js'
|
||||
|
||||
export type LabelProps = {
|
||||
CustomLabel?: React.ReactNode
|
||||
as?: 'label' | 'span'
|
||||
htmlFor?: string
|
||||
label?: LabelFunction | Record<string, string> | false | string
|
||||
label?: Record<string, string> | string
|
||||
required?: boolean
|
||||
unstyled?: boolean
|
||||
}
|
||||
|
||||
export type SanitizedLabelProps = Omit<LabelProps, 'label' | 'required'>
|
||||
|
||||
@@ -2,4 +2,4 @@ import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type RowLabelComponent = CustomComponent
|
||||
|
||||
export type RowLabel = Record<string, string> | RowLabelComponent | string
|
||||
export type RowLabel = Record<string, string> | string
|
||||
|
||||
@@ -22,7 +22,7 @@ export type {
|
||||
FieldDescriptionProps,
|
||||
} from './forms/FieldDescription.js'
|
||||
export type { Data, FilterOptionsResult, FormField, FormState, Row } from './forms/Form.js'
|
||||
export type { LabelProps } from './forms/Label.js'
|
||||
export type { LabelProps, SanitizedLabelProps } from './forms/Label.js'
|
||||
export type { RowLabel, RowLabelComponent } from './forms/RowLabel.js'
|
||||
|
||||
export type {
|
||||
|
||||
@@ -30,6 +30,7 @@ const collectionSchema = joi.object().keys({
|
||||
BeforeList: joi.array().items(componentSchema),
|
||||
BeforeListTable: joi.array().items(componentSchema),
|
||||
edit: joi.object({
|
||||
Description: componentSchema,
|
||||
PreviewButton: componentSchema,
|
||||
PublishButton: componentSchema,
|
||||
SaveButton: componentSchema,
|
||||
@@ -59,7 +60,9 @@ const collectionSchema = joi.object().keys({
|
||||
}),
|
||||
custom: joi.object().pattern(joi.string(), joi.any()),
|
||||
defaultColumns: joi.array().items(joi.string()),
|
||||
description: joi.alternatives().try(joi.string(), componentSchema),
|
||||
description: joi
|
||||
.alternatives()
|
||||
.try(joi.func(), joi.object().pattern(joi.string(), [joi.string()]), joi.string()),
|
||||
enableRichTextLink: joi.boolean(),
|
||||
enableRichTextRelationship: joi.boolean(),
|
||||
group: joi.alternatives().try(joi.string(), joi.object().pattern(joi.string(), [joi.string()])),
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
EditConfig,
|
||||
Endpoint,
|
||||
EntityDescription,
|
||||
EntityDescriptionComponent,
|
||||
GeneratePreviewURL,
|
||||
LabelFunction,
|
||||
LivePreviewConfig,
|
||||
@@ -212,6 +213,8 @@ export type CollectionAdminOptions = {
|
||||
* Components within the edit view
|
||||
*/
|
||||
edit?: {
|
||||
Description?: EntityDescriptionComponent
|
||||
|
||||
/**
|
||||
* Replaces the "Preview" button
|
||||
*/
|
||||
|
||||
@@ -694,12 +694,8 @@ export type EditConfig =
|
||||
|
||||
export type EntityDescriptionComponent = CustomComponent
|
||||
|
||||
export type EntityDescriptionFunction = () => string
|
||||
export type EntityDescriptionFunction = ({ t }: { t: TFunction }) => string
|
||||
|
||||
export type EntityDescription =
|
||||
| EntityDescriptionComponent
|
||||
| EntityDescriptionFunction
|
||||
| Record<string, string>
|
||||
| string
|
||||
export type EntityDescription = EntityDescriptionFunction | Record<string, string> | string
|
||||
|
||||
export type { EmailAdapter, SendEmailOptions }
|
||||
|
||||
@@ -42,10 +42,9 @@ export { isNumber } from '../utilities/isNumber.js'
|
||||
|
||||
export { isPlainObject } from '../utilities/isPlainObject.js'
|
||||
export {
|
||||
isPlainFunction,
|
||||
isReactClientComponent,
|
||||
isReactComponent,
|
||||
isReactServerComponent,
|
||||
isReactComponentOrFunction,
|
||||
isReactServerComponentOrFunction,
|
||||
} from '../utilities/isReactComponent.js'
|
||||
export { isValidID } from '../utilities/isValidID.js'
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ export const sanitizeFields = async ({
|
||||
field.name &&
|
||||
typeof field.label !== 'object' &&
|
||||
typeof field.label !== 'string' &&
|
||||
typeof field.label !== 'function' &&
|
||||
field.label !== false
|
||||
) {
|
||||
field.label = toWords(field.name)
|
||||
|
||||
@@ -6,6 +6,7 @@ export const baseAdminComponentFields = joi
|
||||
.object()
|
||||
.keys({
|
||||
Cell: componentSchema,
|
||||
Description: componentSchema,
|
||||
Field: componentSchema,
|
||||
Filter: componentSchema,
|
||||
})
|
||||
@@ -18,7 +19,7 @@ export const baseAdminFields = joi.object().keys({
|
||||
custom: joi.object().pattern(joi.string(), joi.any()),
|
||||
description: joi
|
||||
.alternatives()
|
||||
.try(joi.string(), joi.object().pattern(joi.string(), [joi.string()]), componentSchema),
|
||||
.try(joi.string(), joi.object().pattern(joi.string(), [joi.string()]), joi.function()),
|
||||
disableBulkEdit: joi.boolean().default(false),
|
||||
disabled: joi.boolean().default(false),
|
||||
hidden: joi.boolean().default(false),
|
||||
@@ -269,9 +270,27 @@ export const row = baseField.keys({
|
||||
|
||||
export const collapsible = baseField.keys({
|
||||
type: joi.string().valid('collapsible').required(),
|
||||
admin: baseAdminFields.default(),
|
||||
admin: baseAdminFields
|
||||
.keys({
|
||||
components: baseAdminComponentFields
|
||||
.keys({
|
||||
RowLabel: componentSchema.optional(),
|
||||
})
|
||||
.default({}),
|
||||
})
|
||||
.default({}),
|
||||
fields: joi.array().items(joi.link('#field')),
|
||||
label: joi.alternatives().try(joi.string(), componentSchema),
|
||||
label: joi.alternatives().conditional('admin.components.RowLabel', {
|
||||
is: joi.exist(),
|
||||
otherwise: joi
|
||||
.alternatives()
|
||||
.try(joi.string(), joi.object().pattern(joi.string(), [joi.string()]), joi.function())
|
||||
.required(),
|
||||
then: joi
|
||||
.alternatives()
|
||||
.try(joi.string(), joi.object().pattern(joi.string(), [joi.string()]), joi.function())
|
||||
.optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
const tab = baseField.keys({
|
||||
|
||||
@@ -11,9 +11,11 @@ import type { RichTextAdapter, RichTextAdapterProvider } from '../../admin/RichT
|
||||
import type {
|
||||
ConditionalDateProps,
|
||||
Description,
|
||||
DescriptionComponent,
|
||||
ErrorProps,
|
||||
LabelProps,
|
||||
RowLabel,
|
||||
RowLabelComponent,
|
||||
} from '../../admin/types.js'
|
||||
import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'
|
||||
import type { CustomComponent, LabelFunction } from '../../config/types.js'
|
||||
@@ -117,6 +119,7 @@ type Admin = {
|
||||
className?: string
|
||||
components?: {
|
||||
Cell?: CustomComponent
|
||||
Description?: DescriptionComponent
|
||||
Field?: CustomComponent
|
||||
Filter?: React.ComponentType<any>
|
||||
}
|
||||
@@ -361,13 +364,25 @@ export type RowField = Omit<FieldBase, 'admin' | 'label' | 'name'> & {
|
||||
}
|
||||
|
||||
export type CollapsibleField = Omit<FieldBase, 'label' | 'name'> & {
|
||||
admin?: Admin & {
|
||||
initCollapsed?: boolean
|
||||
}
|
||||
fields: Field[]
|
||||
label: RowLabel
|
||||
type: 'collapsible'
|
||||
}
|
||||
} & (
|
||||
| {
|
||||
admin: Admin & {
|
||||
components: {
|
||||
RowLabel: RowLabelComponent
|
||||
} & Admin['components']
|
||||
initCollapsed?: boolean
|
||||
}
|
||||
label?: Required<FieldBase['label']>
|
||||
}
|
||||
| {
|
||||
admin?: Admin & {
|
||||
initCollapsed?: boolean
|
||||
}
|
||||
label: Required<FieldBase['label']>
|
||||
}
|
||||
)
|
||||
|
||||
export type TabsAdmin = Omit<Admin, 'description'>
|
||||
|
||||
@@ -610,7 +625,7 @@ export type RichTextField<
|
||||
export type ArrayField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
RowLabel?: RowLabel
|
||||
RowLabel?: RowLabelComponent
|
||||
} & Admin['components']
|
||||
initCollapsed?: boolean
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ const globalSchema = joi
|
||||
admin: joi.object({
|
||||
components: joi.object({
|
||||
elements: joi.object({
|
||||
Description: componentSchema,
|
||||
PreviewButton: componentSchema,
|
||||
PublishButton: componentSchema,
|
||||
SaveButton: componentSchema,
|
||||
@@ -40,7 +41,9 @@ const globalSchema = joi
|
||||
}),
|
||||
}),
|
||||
custom: joi.object().pattern(joi.string(), joi.any()),
|
||||
description: joi.alternatives().try(joi.string(), componentSchema),
|
||||
description: joi
|
||||
.alternatives()
|
||||
.try(joi.func(), joi.object().pattern(joi.string(), [joi.string()]), joi.string()),
|
||||
group: joi
|
||||
.alternatives()
|
||||
.try(joi.string(), joi.object().pattern(joi.string(), [joi.string()])),
|
||||
|
||||
@@ -7,12 +7,12 @@ import type {
|
||||
CustomSaveButton,
|
||||
CustomSaveDraftButton,
|
||||
} from '../../admin/types.js'
|
||||
import type { User } from '../../auth/types.js'
|
||||
import type {
|
||||
Access,
|
||||
EditConfig,
|
||||
Endpoint,
|
||||
EntityDescription,
|
||||
EntityDescriptionComponent,
|
||||
GeneratePreviewURL,
|
||||
LivePreviewConfig,
|
||||
} from '../../config/types.js'
|
||||
@@ -77,6 +77,7 @@ export type GlobalAdminOptions = {
|
||||
*/
|
||||
components?: {
|
||||
elements?: {
|
||||
Description?: EntityDescriptionComponent
|
||||
/**
|
||||
* Replaces the "Preview" button
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import type React from 'react'
|
||||
|
||||
import { isValidElement } from 'react'
|
||||
|
||||
import { isPlainObject } from './isPlainObject.js'
|
||||
|
||||
export function isReactServerComponent<T extends any>(
|
||||
export function isReactServerComponentOrFunction<T extends any>(
|
||||
component: React.ComponentType | any,
|
||||
): component is T {
|
||||
return typeof component === 'function' && isValidElement(component)
|
||||
const isClassComponent =
|
||||
typeof component === 'function' &&
|
||||
component.prototype &&
|
||||
typeof component.prototype.render === 'function'
|
||||
|
||||
const isFunctionalComponent =
|
||||
typeof component === 'function' && (!component.prototype || !component.prototype.render)
|
||||
|
||||
return isClassComponent || isFunctionalComponent
|
||||
}
|
||||
|
||||
export function isReactClientComponent<T extends any>(
|
||||
@@ -17,12 +23,8 @@ export function isReactClientComponent<T extends any>(
|
||||
return typeof component === 'object' && !isPlainObject(component)
|
||||
}
|
||||
|
||||
export function isReactComponent<T extends any>(
|
||||
export function isReactComponentOrFunction<T extends any>(
|
||||
component: React.ComponentType | any,
|
||||
): component is T {
|
||||
return isReactServerComponent(component) || isReactClientComponent(component)
|
||||
}
|
||||
|
||||
export function isPlainFunction<T extends Function>(fn: any): fn is T {
|
||||
return typeof fn === 'function' && !isReactComponent(fn)
|
||||
return isReactServerComponentOrFunction(component) || isReactClientComponent(component)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { TextField } from 'payload/types'
|
||||
import type { TextFieldProps } from '@payloadcms/ui/fields/Text'
|
||||
|
||||
import { Select } from '@payloadcms/ui/fields/Select'
|
||||
import { useForm } from '@payloadcms/ui/forms/Form'
|
||||
@@ -8,7 +8,7 @@ import React, { useEffect, useState } from 'react'
|
||||
|
||||
import type { SelectFieldOption } from '../../types.js'
|
||||
|
||||
export const DynamicFieldSelector: React.FC<TextField> = (props) => {
|
||||
export const DynamicFieldSelector: React.FC<TextFieldProps> = (props) => {
|
||||
const { fields, getDataByPath } = useForm()
|
||||
|
||||
const [options, setOptions] = useState<SelectFieldOption[]>([])
|
||||
|
||||
@@ -6,7 +6,6 @@ import type { Data } from 'payload/types'
|
||||
import { Text } from '@payloadcms/ui/fields/Text'
|
||||
import { useWatchForm } from '@payloadcms/ui/forms/Form'
|
||||
import { useLocale } from '@payloadcms/ui/providers/Locale'
|
||||
import { useTranslation } from '@payloadcms/ui/providers/Translation'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
type FieldWithID = {
|
||||
@@ -20,7 +19,6 @@ export const DynamicPriceSelector: React.FC<TextFieldProps> = (props) => {
|
||||
const { fields, getData, getDataByPath } = useWatchForm()
|
||||
|
||||
const locale = useLocale()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [isNumberField, setIsNumberField] = useState<boolean>()
|
||||
const [valueType, setValueType] = useState<'static' | 'valueOfField'>()
|
||||
@@ -54,12 +52,8 @@ export const DynamicPriceSelector: React.FC<TextFieldProps> = (props) => {
|
||||
|
||||
const localeCode = typeof locale === 'object' && 'code' in locale ? locale.code : locale
|
||||
|
||||
const localLabels =
|
||||
typeof label === 'function'
|
||||
? label({ t })
|
||||
: typeof label === 'object'
|
||||
? label
|
||||
: { [localeCode]: label }
|
||||
const localLabels = typeof label === 'object' ? label : { [localeCode]: label }
|
||||
|
||||
const labelValue = localLabels[localeCode] || localLabels['en'] || ''
|
||||
|
||||
if (valueType === 'valueOfField' && !isNumberField) {
|
||||
|
||||
@@ -27,7 +27,7 @@ type MetaDescriptionProps = FormFieldBase & {
|
||||
}
|
||||
|
||||
export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
||||
const { CustomLabel, hasGenerateDescriptionFn, labelProps, path, required } = props
|
||||
const { CustomLabel, hasGenerateDescriptionFn, label, labelProps, path, required } = props
|
||||
const { path: pathFromContext } = useFieldProps()
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -76,7 +76,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
||||
}}
|
||||
>
|
||||
<div className="plugin-seo__field">
|
||||
<FieldLabel CustomLabel={CustomLabel} {...(labelProps || {})} />
|
||||
<FieldLabel CustomLabel={CustomLabel} label={label} {...(labelProps || {})} />
|
||||
{hasGenerateDescriptionFn && (
|
||||
<React.Fragment>
|
||||
—
|
||||
|
||||
@@ -23,7 +23,7 @@ type MetaImageProps = UploadInputProps & {
|
||||
}
|
||||
|
||||
export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
||||
const { CustomLabel, hasGenerateImageFn, labelProps, relationTo, required } = props || {}
|
||||
const { CustomLabel, hasGenerateImageFn, label, labelProps, relationTo, required } = props || {}
|
||||
|
||||
const field: FieldType<string> = useField(props as Options)
|
||||
|
||||
@@ -77,7 +77,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
||||
}}
|
||||
>
|
||||
<div className="plugin-seo__field">
|
||||
<FieldLabel CustomLabel={CustomLabel} {...(labelProps || {})} />
|
||||
<FieldLabel CustomLabel={CustomLabel} label={label} {...(labelProps || {})} />
|
||||
{hasGenerateImageFn && (
|
||||
<React.Fragment>
|
||||
—
|
||||
|
||||
@@ -28,7 +28,7 @@ type MetaTitleProps = FormFieldBase & {
|
||||
}
|
||||
|
||||
export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
||||
const { CustomLabel, hasGenerateTitleFn, labelProps, path, required } = props || {}
|
||||
const { CustomLabel, hasGenerateTitleFn, label, labelProps, path, required } = props || {}
|
||||
const { path: pathFromContext } = useFieldProps()
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -77,7 +77,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
||||
}}
|
||||
>
|
||||
<div className="plugin-seo__field">
|
||||
<FieldLabel CustomLabel={CustomLabel} {...(labelProps || {})} />
|
||||
<FieldLabel CustomLabel={CustomLabel} label={label} {...(labelProps || {})} />
|
||||
{hasGenerateTitleFn && (
|
||||
<React.Fragment>
|
||||
—
|
||||
|
||||
@@ -43,7 +43,7 @@ export const seoPlugin =
|
||||
type: 'text',
|
||||
admin: {
|
||||
components: {
|
||||
Field: (props) => (
|
||||
Field: ({ payload: _payload, ...props }) => (
|
||||
<MetaTitle
|
||||
{...props}
|
||||
hasGenerateTitleFn={typeof pluginConfig?.generateTitle === 'function'}
|
||||
@@ -59,7 +59,7 @@ export const seoPlugin =
|
||||
type: 'textarea',
|
||||
admin: {
|
||||
components: {
|
||||
Field: (props) => (
|
||||
Field: ({ payload: _payload, ...props }) => (
|
||||
<MetaDescription
|
||||
{...props}
|
||||
hasGenerateDescriptionFn={
|
||||
@@ -80,7 +80,7 @@ export const seoPlugin =
|
||||
type: 'upload',
|
||||
admin: {
|
||||
components: {
|
||||
Field: (props) => (
|
||||
Field: ({ payload: _payload, ...props }) => (
|
||||
<MetaImage
|
||||
{...props}
|
||||
hasGenerateImageFn={typeof pluginConfig?.generateImage === 'function'}
|
||||
@@ -103,7 +103,7 @@ export const seoPlugin =
|
||||
type: 'ui',
|
||||
admin: {
|
||||
components: {
|
||||
Field: (props) => (
|
||||
Field: ({ payload: _payload, ...props }) => (
|
||||
<Preview
|
||||
{...props}
|
||||
hasGenerateURLFn={typeof pluginConfig?.generateURL === 'function'}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use client'
|
||||
import type { FormFieldBase } from '@payloadcms/ui/fields/shared'
|
||||
import type { SerializedEditorState } from 'lexical'
|
||||
import type { FieldBase } from 'payload/types'
|
||||
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
import { FieldError } from '@payloadcms/ui/forms/FieldError'
|
||||
@@ -22,7 +21,6 @@ const baseClass = 'rich-text-lexical'
|
||||
const _RichText: React.FC<
|
||||
FormFieldBase & {
|
||||
editorConfig: SanitizedClientEditorConfig // With rendered features n stuff
|
||||
label?: FieldBase['label']
|
||||
name: string
|
||||
richTextComponentMap: Map<string, React.ReactNode>
|
||||
width?: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { FormFieldBase } from '@payloadcms/ui/fields/shared'
|
||||
import type { ClientValidate, FieldBase } from 'payload/types'
|
||||
import type { ClientValidate } from 'payload/types'
|
||||
import type { BaseEditor, BaseOperation } from 'slate'
|
||||
import type { HistoryEditor } from 'slate-history'
|
||||
import type { ReactEditor } from 'slate-react'
|
||||
@@ -50,7 +50,6 @@ declare module 'slate' {
|
||||
const RichTextField: React.FC<
|
||||
FormFieldBase & {
|
||||
elements: EnabledFeatures['elements']
|
||||
label?: FieldBase['label']
|
||||
leaves: EnabledFeatures['leaves']
|
||||
name: string
|
||||
placeholder?: string
|
||||
|
||||
@@ -74,8 +74,13 @@ export const clientTranslationKeys = [
|
||||
'fields:blockType',
|
||||
'fields:chooseBetweenCustomTextOrDocument',
|
||||
'fields:customURL',
|
||||
'fields:chooseDocumentToLink',
|
||||
'fields:openInNewTab',
|
||||
'fields:enterURL',
|
||||
'fields:internalLink',
|
||||
'fields:chooseFromExisting',
|
||||
'fields:linkType',
|
||||
'fields:textToDisplay',
|
||||
'fields:collapseAll',
|
||||
'fields:editLink',
|
||||
'fields:editRelationship',
|
||||
@@ -120,6 +125,7 @@ export const clientTranslationKeys = [
|
||||
'general:copy',
|
||||
'general:create',
|
||||
'general:created',
|
||||
'general:createdAt',
|
||||
'general:createNew',
|
||||
'general:createNewLabel',
|
||||
'general:creating',
|
||||
@@ -239,6 +245,8 @@ export const clientTranslationKeys = [
|
||||
'upload:setFocalPoint',
|
||||
'upload:sizesFor',
|
||||
'upload:width',
|
||||
'upload:fileName',
|
||||
'upload:fileSize',
|
||||
|
||||
'validation:emailAddress',
|
||||
'validation:fieldHasNo',
|
||||
|
||||
@@ -34,8 +34,11 @@ const combineLabel = ({
|
||||
? field.fieldComponentProps.CustomLabel
|
||||
: null
|
||||
const DefaultLabelToRender =
|
||||
field && 'labelProps' in field.fieldComponentProps && field.fieldComponentProps.labelProps ? (
|
||||
<FieldLabel {...field.fieldComponentProps.labelProps} />
|
||||
field && 'label' in field.fieldComponentProps && field.fieldComponentProps.label ? (
|
||||
<FieldLabel
|
||||
label={field.fieldComponentProps.label}
|
||||
{...(field.fieldComponentProps.labelProps || {})}
|
||||
/>
|
||||
) : null
|
||||
|
||||
const LabelToRender = CustomLabelToRender || DefaultLabelToRender || customLabel
|
||||
|
||||
@@ -103,7 +103,8 @@ export const buildColumnState = (args: Args): Column[] => {
|
||||
const Label = (
|
||||
<FieldLabel
|
||||
CustomLabel={CustomLabelToRender}
|
||||
{...field.fieldComponentProps?.labelProps}
|
||||
label={field.fieldComponentProps?.label}
|
||||
{...(field.fieldComponentProps?.labelProps || {})}
|
||||
unstyled
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import type { WithServerSideProps as WithServerSidePropsType } from 'payload/types'
|
||||
|
||||
import { isReactServerComponent } from 'payload/utilities'
|
||||
import { isReactServerComponentOrFunction } from 'payload/utilities'
|
||||
import React from 'react'
|
||||
|
||||
export const WithServerSideProps: WithServerSidePropsType = ({ Component, payload, ...rest }) => {
|
||||
if (Component) {
|
||||
const WithServerSideProps: React.FC<any> = (passedProps) => {
|
||||
const WithServerSideProps: React.FC = (passedProps) => {
|
||||
const propsWithPayload = {
|
||||
...passedProps,
|
||||
...(isReactServerComponent(Component) ? { payload } : {}),
|
||||
...(isReactServerComponentOrFunction(Component) ? { payload } : {}),
|
||||
}
|
||||
|
||||
return <Component {...propsWithPayload} />
|
||||
@@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
import type { FieldPermissions } from 'payload/auth'
|
||||
import type { FieldBase } from 'payload/types'
|
||||
import type { ArrayField as ArrayFieldType } from 'payload/types'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
@@ -38,7 +37,6 @@ export type ArrayFieldProps = FormFieldBase & {
|
||||
fieldMap: FieldMap
|
||||
forceRender?: boolean
|
||||
isSortable?: boolean
|
||||
label?: FieldBase['label']
|
||||
labels?: ArrayFieldType['labels']
|
||||
maxRows?: ArrayFieldType['maxRows']
|
||||
minRows?: ArrayFieldType['minRows']
|
||||
@@ -93,9 +91,9 @@ export const _ArrayField: React.FC<ArrayFieldProps> = (props) => {
|
||||
})()
|
||||
|
||||
// Handle labeling for Arrays, Global Arrays, and Blocks
|
||||
const getLabels = (p: ArrayFieldProps) => {
|
||||
const getLabels = (p: ArrayFieldProps): ArrayFieldType['labels'] => {
|
||||
if ('labels' in p && p?.labels) return p.labels
|
||||
if ('label' in p && p?.label) return { plural: undefined, singular: p.label }
|
||||
if ('label' in p && p?.label) return { plural: undefined, singular: p?.label }
|
||||
return { plural: t('general:rows'), singular: t('general:row') }
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ export type BlocksFieldProps = FormFieldBase & {
|
||||
blocks?: ReducedBlock[]
|
||||
forceRender?: boolean
|
||||
isSortable?: boolean
|
||||
label?: FieldBase['label']
|
||||
labels?: BlockField['labels']
|
||||
maxRows?: number
|
||||
minRows?: number
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { FieldBase, LabelProps } from 'payload/types'
|
||||
import type { LabelProps, SanitizedLabelProps } from 'payload/types'
|
||||
|
||||
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'
|
||||
import React from 'react'
|
||||
@@ -15,8 +15,8 @@ type Props = {
|
||||
className?: string
|
||||
id?: string
|
||||
inputRef?: React.RefObject<HTMLInputElement>
|
||||
label?: FieldBase['label']
|
||||
labelProps?: LabelProps
|
||||
label?: LabelProps['label']
|
||||
labelProps?: SanitizedLabelProps
|
||||
name?: string
|
||||
onToggle: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
partialChecked?: boolean
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import type { FieldBase } from 'payload/types'
|
||||
|
||||
import type { FormFieldBase } from '../shared/index.js'
|
||||
|
||||
export type CheckboxFieldProps = FormFieldBase & {
|
||||
checked?: boolean
|
||||
disableFormData?: boolean
|
||||
id?: string
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
onChange?: (val: boolean) => void
|
||||
partialChecked?: boolean
|
||||
|
||||
@@ -18,7 +18,6 @@ import './index.scss'
|
||||
|
||||
export type CodeFieldProps = FormFieldBase & {
|
||||
editorOptions?: CodeFieldType['admin']['editorOptions']
|
||||
label?: FieldBase['label']
|
||||
language?: CodeFieldType['admin']['language']
|
||||
name?: string
|
||||
path?: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { DocumentPreferences, FieldBase } from 'payload/types'
|
||||
import type { DocumentPreferences } from 'payload/types'
|
||||
|
||||
import React, { Fragment, useCallback, useEffect, useState } from 'react'
|
||||
|
||||
@@ -28,7 +28,6 @@ import type { FormFieldBase } from '../shared/index.js'
|
||||
export type CollapsibleFieldProps = FormFieldBase & {
|
||||
fieldMap: FieldMap
|
||||
initCollapsed?: boolean
|
||||
label?: FieldBase['label']
|
||||
permissions: FieldPermissions
|
||||
width?: string
|
||||
}
|
||||
@@ -41,7 +40,7 @@ const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
|
||||
descriptionProps,
|
||||
fieldMap,
|
||||
initCollapsed = false,
|
||||
labelProps,
|
||||
label,
|
||||
path: pathFromProps,
|
||||
readOnly: readOnlyFromProps,
|
||||
} = props
|
||||
@@ -139,12 +138,7 @@ const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
|
||||
collapsibleStyle={fieldHasErrors ? 'error' : 'default'}
|
||||
header={
|
||||
<div className={`${baseClass}__row-label-wrap`}>
|
||||
<RowLabel
|
||||
RowLabelComponent={CustomLabel}
|
||||
i18n={i18n}
|
||||
path={path}
|
||||
rowLabel={labelProps.label}
|
||||
/>
|
||||
<RowLabel RowLabelComponent={CustomLabel} i18n={i18n} path={path} rowLabel={label} />
|
||||
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'date-time-field'
|
||||
|
||||
import type { DateField, FieldBase } from 'payload/types'
|
||||
import type { DateField } from 'payload/types'
|
||||
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
import { FieldError } from '@payloadcms/ui/forms/FieldError'
|
||||
@@ -26,7 +26,6 @@ import { withCondition } from '../../forms/withCondition/index.js'
|
||||
|
||||
export type DateFieldProps = FormFieldBase & {
|
||||
date?: DateField['admin']['date']
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
path?: string
|
||||
placeholder?: DateField['admin']['placeholder'] | string
|
||||
|
||||
@@ -19,7 +19,6 @@ import './index.scss'
|
||||
|
||||
export type EmailFieldProps = FormFieldBase & {
|
||||
autoComplete?: string
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
path?: string
|
||||
placeholder?: EmailFieldType['admin']['placeholder']
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
import type { FieldPermissions } from 'payload/auth'
|
||||
import type { FieldBase } from 'payload/types'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
@@ -29,7 +28,6 @@ export type GroupFieldProps = FormFieldBase & {
|
||||
fieldMap: FieldMap
|
||||
forceRender?: boolean
|
||||
hideGutter?: boolean
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
permissions: FieldPermissions
|
||||
width?: string
|
||||
@@ -43,7 +41,7 @@ const GroupField: React.FC<GroupFieldProps> = (props) => {
|
||||
descriptionProps,
|
||||
fieldMap,
|
||||
hideGutter,
|
||||
labelProps,
|
||||
label,
|
||||
readOnly: readOnlyFromProps,
|
||||
style,
|
||||
width,
|
||||
@@ -89,14 +87,12 @@ const GroupField: React.FC<GroupFieldProps> = (props) => {
|
||||
<GroupProvider>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
<div className={`${baseClass}__header`}>
|
||||
{(CustomLabel || CustomDescription || labelProps?.label) && (
|
||||
{(CustomLabel || CustomDescription || label) && (
|
||||
<header>
|
||||
{CustomLabel !== undefined ? (
|
||||
CustomLabel
|
||||
) : labelProps?.label ? (
|
||||
<h3 className={`${baseClass}__title`}>
|
||||
{getTranslation(labelProps.label, i18n)}
|
||||
</h3>
|
||||
) : label ? (
|
||||
<h3 className={`${baseClass}__title`}>{getTranslation(label, i18n)}</h3>
|
||||
) : null}
|
||||
{CustomDescription !== undefined ? (
|
||||
CustomDescription
|
||||
|
||||
@@ -12,7 +12,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'json-field'
|
||||
|
||||
import type { FieldBase, JSONField as JSONFieldType } from 'payload/types'
|
||||
import type { JSONField as JSONFieldType } from 'payload/types'
|
||||
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
import { FieldError } from '@payloadcms/ui/forms/FieldError'
|
||||
@@ -23,7 +23,6 @@ import type { FormFieldBase } from '../shared/index.js'
|
||||
export type JSONFieldProps = FormFieldBase & {
|
||||
editorOptions?: JSONFieldType['admin']['editorOptions']
|
||||
jsonSchema?: Record<string, unknown>
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
path?: string
|
||||
width?: string
|
||||
|
||||
@@ -22,7 +22,6 @@ import './index.scss'
|
||||
|
||||
export type NumberFieldProps = FormFieldBase & {
|
||||
hasMany?: boolean
|
||||
label?: FieldBase['label']
|
||||
max?: number
|
||||
maxRows?: number
|
||||
min?: number
|
||||
|
||||
@@ -17,7 +17,6 @@ export type PasswordFieldProps = FormFieldBase & {
|
||||
className?: string
|
||||
description?: Description
|
||||
disabled?: boolean
|
||||
label?: string
|
||||
name: string
|
||||
path?: string
|
||||
required?: boolean
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
'use client'
|
||||
import type { ClientValidate, FieldBase } from 'payload/types'
|
||||
import type { ClientValidate } from 'payload/types'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import React, { useCallback } from 'react'
|
||||
@@ -21,7 +21,6 @@ import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider'
|
||||
import type { FormFieldBase } from '../shared/index.js'
|
||||
|
||||
export type PointFieldProps = FormFieldBase & {
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
path?: string
|
||||
placeholder?: string
|
||||
@@ -40,6 +39,7 @@ const PointField: React.FC<PointFieldProps> = (props) => {
|
||||
className,
|
||||
descriptionProps,
|
||||
errorProps,
|
||||
label,
|
||||
labelProps,
|
||||
path: pathFromProps,
|
||||
placeholder,
|
||||
@@ -90,7 +90,7 @@ const PointField: React.FC<PointFieldProps> = (props) => {
|
||||
|
||||
const getCoordinateFieldLabel = (type: 'latitude' | 'longitude') => {
|
||||
const suffix = type === 'longitude' ? t('fields:longitude') : t('fields:latitude')
|
||||
const fieldLabel = labelProps && labelProps.label ? getTranslation(labelProps.label, i18n) : ''
|
||||
const fieldLabel = label ? getTranslation(label, i18n) : ''
|
||||
|
||||
return {
|
||||
...labelProps,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import type { FieldBase, Option } from 'payload/types'
|
||||
import type { Option } from 'payload/types'
|
||||
|
||||
import { optionIsObject } from 'payload/types'
|
||||
import React, { useCallback } from 'react'
|
||||
@@ -23,7 +23,6 @@ import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider'
|
||||
import type { FormFieldBase } from '../shared/index.js'
|
||||
|
||||
export type RadioFieldProps = FormFieldBase & {
|
||||
label?: FieldBase['label']
|
||||
layout?: 'horizontal' | 'vertical'
|
||||
name?: string
|
||||
onChange?: OnChange
|
||||
|
||||
@@ -8,7 +8,6 @@ export type RelationshipFieldProps = FormFieldBase & {
|
||||
allowCreate?: RelationshipField['admin']['allowCreate']
|
||||
hasMany?: boolean
|
||||
isSortable?: boolean
|
||||
label?: FieldBase['label']
|
||||
name: string
|
||||
relationTo?: RelationshipField['relationTo']
|
||||
sortOptions?: RelationshipField['admin']['sortOptions']
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import type { FieldBase } from 'payload/types'
|
||||
import type React from 'react'
|
||||
|
||||
import type { MappedField } from '../../providers/ComponentMap/buildComponentMap/types.js'
|
||||
import type { FormFieldBase } from '../shared/index.js'
|
||||
|
||||
export type RichTextFieldProps = FormFieldBase & {
|
||||
label?: FieldBase['label']
|
||||
name: string
|
||||
richTextComponentMap?: Map<string, MappedField[] | React.ReactNode>
|
||||
width?: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
'use client'
|
||||
import type { ClientValidate, FieldBase, Option, OptionObject } from 'payload/types'
|
||||
import type { ClientValidate, Option, OptionObject } from 'payload/types'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
@@ -22,7 +22,6 @@ export type SelectFieldProps = FormFieldBase & {
|
||||
hasMany?: boolean
|
||||
isClearable?: boolean
|
||||
isSortable?: boolean
|
||||
label?: FieldBase['label']
|
||||
name?: string
|
||||
onChange?: (e: string) => void
|
||||
options?: Option[]
|
||||
|
||||
@@ -31,6 +31,7 @@ const TextField: React.FC<TextFieldProps> = (props) => {
|
||||
errorProps,
|
||||
hasMany,
|
||||
inputRef,
|
||||
label,
|
||||
labelProps,
|
||||
localized,
|
||||
maxLength,
|
||||
@@ -127,6 +128,7 @@ const TextField: React.FC<TextFieldProps> = (props) => {
|
||||
errorProps={errorProps}
|
||||
hasMany={hasMany}
|
||||
inputRef={inputRef}
|
||||
label={label}
|
||||
labelProps={labelProps}
|
||||
maxRows={maxRows}
|
||||
minRows={minRows}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { FieldBase, TextField } from 'payload/types'
|
||||
import type { TextField } from 'payload/types'
|
||||
import type { ChangeEvent } from 'react'
|
||||
|
||||
import type { Option } from '../../elements/ReactSelect/types.js'
|
||||
@@ -7,7 +7,6 @@ import type { FormFieldBase } from '../shared/index.js'
|
||||
export type TextFieldProps = FormFieldBase & {
|
||||
hasMany?: boolean
|
||||
inputRef?: React.MutableRefObject<HTMLInputElement>
|
||||
label?: FieldBase['label']
|
||||
maxLength?: number
|
||||
maxRows?: number
|
||||
minLength?: number
|
||||
|
||||
@@ -29,6 +29,7 @@ const TextareaField: React.FC<TextareaFieldProps> = (props) => {
|
||||
className,
|
||||
descriptionProps,
|
||||
errorProps,
|
||||
label,
|
||||
labelProps,
|
||||
locale,
|
||||
localized,
|
||||
@@ -82,6 +83,7 @@ const TextareaField: React.FC<TextareaFieldProps> = (props) => {
|
||||
className={className}
|
||||
descriptionProps={descriptionProps}
|
||||
errorProps={errorProps}
|
||||
label={label}
|
||||
labelProps={labelProps}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { FieldBase, TextareaField as TextareaFieldType } from 'payload/types'
|
||||
import type { TextareaField as TextareaFieldType } from 'payload/types'
|
||||
|
||||
import { type ChangeEvent } from 'react'
|
||||
|
||||
import type { FormFieldBase } from '../shared/index.js'
|
||||
|
||||
export type TextareaFieldProps = FormFieldBase & {
|
||||
label?: FieldBase['label']
|
||||
maxLength?: number
|
||||
minLength?: number
|
||||
name?: string
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { FormFieldBase } from '../shared/index.js'
|
||||
|
||||
export type UploadFieldProps = FormFieldBase & {
|
||||
filterOptions?: UploadField['filterOptions']
|
||||
label?: UploadField['label']
|
||||
name?: string
|
||||
path?: string
|
||||
relationTo?: UploadField['relationTo']
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
ErrorProps,
|
||||
FieldDescriptionProps,
|
||||
LabelProps,
|
||||
SanitizedLabelProps,
|
||||
Validate,
|
||||
} from 'payload/types'
|
||||
|
||||
@@ -22,7 +23,8 @@ export type FormFieldBase = {
|
||||
disabled?: boolean
|
||||
docPreferences?: DocumentPreferences
|
||||
errorProps?: ErrorProps
|
||||
labelProps?: LabelProps
|
||||
label?: LabelProps['label']
|
||||
labelProps?: SanitizedLabelProps
|
||||
locale?: Locale
|
||||
localized?: boolean
|
||||
path?: string
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type { LabelProps, RowLabel, RowLabelComponent } from 'payload/types'
|
||||
|
||||
import React from 'react'
|
||||
import type { LabelProps } from 'payload/types'
|
||||
import type React from 'react'
|
||||
|
||||
export type Props = {
|
||||
RowLabelComponent?: React.ReactNode
|
||||
@@ -11,7 +10,3 @@ export type Props = {
|
||||
rowLabel?: LabelProps['label']
|
||||
rowNumber?: number
|
||||
}
|
||||
|
||||
export function isComponent(label: RowLabel): label is RowLabelComponent {
|
||||
return React.isValidElement(label)
|
||||
}
|
||||
|
||||
@@ -24,15 +24,3 @@ export const Account = () => {
|
||||
if (Avatar) return <Avatar active={isOnAccountPage} />
|
||||
return <DefaultAccountIcon active={isOnAccountPage} />
|
||||
}
|
||||
|
||||
function isClassComponent(component) {
|
||||
return typeof component === 'function' && !!component.prototype.isReactComponent
|
||||
}
|
||||
|
||||
function isFunctionComponent(component) {
|
||||
return typeof component === 'function' && String(component).includes('return React.createElement')
|
||||
}
|
||||
|
||||
function isReactComponent(component) {
|
||||
return isClassComponent(component) || isFunctionComponent(component)
|
||||
}
|
||||
|
||||
@@ -3,15 +3,12 @@ import type { ViewDescriptionProps } from '@payloadcms/ui/elements/ViewDescripti
|
||||
import type {
|
||||
AdminViewProps,
|
||||
EditViewProps,
|
||||
EntityDescriptionComponent,
|
||||
EntityDescriptionFunction,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import { ViewDescription } from '@payloadcms/ui/elements/ViewDescription'
|
||||
import { isPlainFunction, isReactComponent } from 'payload/utilities'
|
||||
import React from 'react'
|
||||
|
||||
import type { CollectionComponentMap } from './types.js'
|
||||
@@ -19,15 +16,7 @@ import type { CollectionComponentMap } from './types.js'
|
||||
import { mapActions } from './actions.js'
|
||||
import { mapFields } from './fields.js'
|
||||
|
||||
export const mapCollections = ({
|
||||
DefaultEditView,
|
||||
DefaultListView,
|
||||
WithServerSideProps,
|
||||
collections,
|
||||
config,
|
||||
i18n,
|
||||
readOnly: readOnlyOverride,
|
||||
}: {
|
||||
export const mapCollections = (args: {
|
||||
DefaultEditView: React.FC<EditViewProps>
|
||||
DefaultListView: React.FC<AdminViewProps>
|
||||
WithServerSideProps: WithServerSidePropsType
|
||||
@@ -37,8 +26,19 @@ export const mapCollections = ({
|
||||
readOnly?: boolean
|
||||
}): {
|
||||
[key: SanitizedCollectionConfig['slug']]: CollectionComponentMap
|
||||
} =>
|
||||
collections.reduce((acc, collectionConfig) => {
|
||||
} => {
|
||||
const {
|
||||
DefaultEditView,
|
||||
DefaultListView,
|
||||
WithServerSideProps,
|
||||
collections,
|
||||
config,
|
||||
i18n,
|
||||
i18n: { t },
|
||||
readOnly: readOnlyOverride,
|
||||
} = args
|
||||
|
||||
return collections.reduce((acc, collectionConfig) => {
|
||||
const { slug, fields } = collectionConfig
|
||||
|
||||
const internalCollections = ['payload-preferences', 'payload-migrations']
|
||||
@@ -130,26 +130,25 @@ export const mapCollections = ({
|
||||
afterListTable?.map((Component) => <WithServerSideProps Component={Component} />)) ||
|
||||
null
|
||||
|
||||
let description = undefined
|
||||
if (collectionConfig.admin && 'description' in collectionConfig.admin) {
|
||||
if (
|
||||
typeof collectionConfig.admin?.description === 'string' ||
|
||||
typeof collectionConfig.admin?.description === 'object'
|
||||
) {
|
||||
description = collectionConfig.admin.description
|
||||
} else if (typeof collectionConfig.admin?.description === 'function') {
|
||||
description = collectionConfig.admin?.description({ t })
|
||||
}
|
||||
}
|
||||
|
||||
const descriptionProps: ViewDescriptionProps = {
|
||||
description:
|
||||
(collectionConfig.admin &&
|
||||
'description' in collectionConfig.admin &&
|
||||
(((typeof collectionConfig.admin?.description === 'string' ||
|
||||
typeof collectionConfig.admin?.description === 'object') &&
|
||||
collectionConfig.admin.description) ||
|
||||
(typeof collectionConfig.admin?.description === 'function' &&
|
||||
isPlainFunction<EntityDescriptionFunction>(collectionConfig.admin?.description) &&
|
||||
collectionConfig.admin?.description()))) ||
|
||||
undefined,
|
||||
description,
|
||||
}
|
||||
|
||||
const DescriptionComponent =
|
||||
(collectionConfig.admin &&
|
||||
'description' in collectionConfig.admin &&
|
||||
((isReactComponent<EntityDescriptionComponent>(collectionConfig.admin.description) &&
|
||||
collectionConfig.admin.description) ||
|
||||
(collectionConfig.admin.description && ViewDescription))) ||
|
||||
undefined
|
||||
collectionConfig.admin?.components?.edit?.Description ||
|
||||
(description ? ViewDescription : undefined)
|
||||
|
||||
const Description =
|
||||
DescriptionComponent !== undefined ? (
|
||||
@@ -187,3 +186,4 @@ export const mapCollections = ({
|
||||
[slug]: componentMap,
|
||||
}
|
||||
}, {})
|
||||
}
|
||||
|
||||
@@ -2,27 +2,17 @@ import type { I18n } from '@payloadcms/translations'
|
||||
import type { CustomComponent } from 'payload/config'
|
||||
import type {
|
||||
CellComponentProps,
|
||||
DescriptionComponent,
|
||||
DescriptionFunction,
|
||||
Field,
|
||||
FieldBase,
|
||||
FieldDescriptionProps,
|
||||
FieldWithPath,
|
||||
LabelProps,
|
||||
Option,
|
||||
RowLabelComponent,
|
||||
SanitizedConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/types'
|
||||
import {
|
||||
isPlainFunction,
|
||||
isReactClientComponent,
|
||||
isReactComponent,
|
||||
isReactServerComponent,
|
||||
} from 'payload/utilities'
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
import type { ArrayFieldProps } from '../../../fields/Array/index.js'
|
||||
@@ -129,11 +119,17 @@ export const mapFields = (args: {
|
||||
)) ||
|
||||
null
|
||||
|
||||
let label = undefined
|
||||
if ('label' in field) {
|
||||
if (typeof field.label === 'string' || typeof field.label === 'object') {
|
||||
label = field.label
|
||||
} else if (typeof field.label === 'function') {
|
||||
label = field.label({ t })
|
||||
}
|
||||
}
|
||||
|
||||
const labelProps: LabelProps = {
|
||||
label:
|
||||
'label' in field && !isPlainFunction(field.label) && !isReactComponent(field.label)
|
||||
? field.label
|
||||
: undefined,
|
||||
label,
|
||||
required: 'required' in field ? field.required : undefined,
|
||||
}
|
||||
|
||||
@@ -144,31 +140,38 @@ export const mapFields = (args: {
|
||||
field.admin.components?.Label) ||
|
||||
undefined
|
||||
|
||||
// If we return undefined here (so if no CUSTOM label component is set), the field client component is responsible for falling back to the default label
|
||||
const CustomLabel =
|
||||
CustomLabelComponent !== undefined ? (
|
||||
<WithServerSideProps Component={CustomLabelComponent} {...(labelProps || {})} />
|
||||
) : undefined
|
||||
|
||||
const descriptionProps: FieldDescriptionProps = {
|
||||
description:
|
||||
(field.admin &&
|
||||
'description' in field.admin &&
|
||||
(((typeof field.admin?.description === 'string' ||
|
||||
typeof field.admin?.description === 'object') &&
|
||||
field.admin.description) ||
|
||||
(typeof field.admin?.description === 'function' &&
|
||||
isPlainFunction<DescriptionFunction>(field.admin?.description) &&
|
||||
field.admin?.description({ t })))) ||
|
||||
undefined,
|
||||
let description = undefined
|
||||
if (field.admin && 'description' in field.admin) {
|
||||
if (
|
||||
typeof field.admin?.description === 'string' ||
|
||||
typeof field.admin?.description === 'object'
|
||||
) {
|
||||
description = field.admin.description
|
||||
} else if (typeof field.admin?.description === 'function') {
|
||||
description = field.admin?.description({ t })
|
||||
}
|
||||
}
|
||||
|
||||
const CustomDescriptionComponent =
|
||||
(field.admin &&
|
||||
'description' in field.admin &&
|
||||
((isReactComponent<DescriptionComponent>(field.admin.description) &&
|
||||
field.admin.description) ||
|
||||
(field.admin.description && FieldDescription))) ||
|
||||
undefined
|
||||
const descriptionProps: FieldDescriptionProps = {
|
||||
description,
|
||||
}
|
||||
|
||||
let CustomDescriptionComponent = undefined
|
||||
if (
|
||||
field.admin?.components &&
|
||||
'Description' in field.admin.components &&
|
||||
field.admin.components?.Description
|
||||
) {
|
||||
CustomDescriptionComponent = field.admin.components.Description
|
||||
} else if (description) {
|
||||
CustomDescriptionComponent = FieldDescription
|
||||
}
|
||||
|
||||
const CustomDescription =
|
||||
CustomDescriptionComponent !== undefined ? (
|
||||
@@ -194,6 +197,7 @@ export const mapFields = (args: {
|
||||
<WithServerSideProps Component={CustomErrorComponent} {...(errorProps || {})} />
|
||||
) : undefined
|
||||
|
||||
// These fields are shared across all field types even if they are not used in the default field, as the custom field component can use them
|
||||
const baseFieldProps: FormFieldBase = {
|
||||
AfterInput,
|
||||
BeforeInput,
|
||||
@@ -204,7 +208,7 @@ export const mapFields = (args: {
|
||||
descriptionProps,
|
||||
disabled: 'admin' in field && 'disabled' in field.admin ? field.admin?.disabled : false,
|
||||
errorProps,
|
||||
labelProps,
|
||||
label: labelProps?.label,
|
||||
path,
|
||||
required: 'required' in field ? field.required : undefined,
|
||||
}
|
||||
@@ -217,7 +221,7 @@ export const mapFields = (args: {
|
||||
fieldOptions = field.options.map((option) => {
|
||||
if (typeof option === 'object' && typeof option.label === 'function') {
|
||||
return {
|
||||
label: option.label({ t: i18n.t }),
|
||||
label: option.label({ t }),
|
||||
value: option.value,
|
||||
}
|
||||
}
|
||||
@@ -230,10 +234,7 @@ export const mapFields = (args: {
|
||||
name: 'name' in field ? field.name : undefined,
|
||||
fieldType: field.type,
|
||||
isFieldAffectingData,
|
||||
label:
|
||||
'label' in field && field.label && typeof field.label !== 'function'
|
||||
? field.label
|
||||
: undefined,
|
||||
label: labelProps?.label || undefined,
|
||||
labels: 'labels' in field ? field.labels : undefined,
|
||||
options: 'options' in field ? fieldOptions : undefined,
|
||||
relationTo: 'relationTo' in field ? field.relationTo : undefined,
|
||||
@@ -247,11 +248,12 @@ export const mapFields = (args: {
|
||||
'admin' in field &&
|
||||
field.admin.components &&
|
||||
'RowLabel' in field.admin.components &&
|
||||
field.admin.components.RowLabel &&
|
||||
isReactComponent<RowLabelComponent>(field.admin.components.RowLabel)
|
||||
field.admin.components.RowLabel
|
||||
) {
|
||||
const CustomRowLabelComponent = field.admin.components.RowLabel
|
||||
CustomRowLabel = <WithServerSideProps Component={CustomRowLabelComponent} />
|
||||
CustomRowLabel = (
|
||||
<WithServerSideProps Component={CustomRowLabelComponent} {...(labelProps || {})} />
|
||||
)
|
||||
}
|
||||
|
||||
const arrayFieldProps: Omit<ArrayFieldProps, 'indexPath' | 'permissions'> = {
|
||||
@@ -270,7 +272,6 @@ export const mapFields = (args: {
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
isSortable: field.admin?.isSortable,
|
||||
label: field?.label,
|
||||
labels: field.labels,
|
||||
maxRows: field.maxRows,
|
||||
minRows: field.minRows,
|
||||
@@ -314,7 +315,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
isSortable: field.admin?.isSortable,
|
||||
label: field?.label,
|
||||
labels: field.labels,
|
||||
maxRows: field.maxRows,
|
||||
minRows: field.minRows,
|
||||
@@ -339,7 +339,6 @@ export const mapFields = (args: {
|
||||
name: field.name,
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
style: field.admin?.style,
|
||||
@@ -356,7 +355,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
editorOptions: field.admin?.editorOptions,
|
||||
label: field.label,
|
||||
language: field.admin?.language,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
@@ -369,11 +367,17 @@ export const mapFields = (args: {
|
||||
}
|
||||
case 'collapsible': {
|
||||
let CustomCollapsibleLabel: React.ReactNode
|
||||
|
||||
if (isReactComponent(field.label) || isPlainFunction(field.label)) {
|
||||
const CustomCollapsibleLabelComponent = field.label as RowLabelComponent
|
||||
if (
|
||||
field?.admin?.components &&
|
||||
'RowLabel' in field.admin.components &&
|
||||
field?.admin?.components?.RowLabel
|
||||
) {
|
||||
const CustomCollapsibleLabelComponent = field.admin.components.RowLabel
|
||||
CustomCollapsibleLabel = (
|
||||
<WithServerSideProps Component={CustomCollapsibleLabelComponent} />
|
||||
<WithServerSideProps
|
||||
Component={CustomCollapsibleLabelComponent}
|
||||
{...(labelProps || {})}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -393,7 +397,6 @@ export const mapFields = (args: {
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
initCollapsed: field.admin?.initCollapsed,
|
||||
label: !CustomCollapsibleLabel ? (field.label as FieldBase['label']) : undefined,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
style: field.admin?.style,
|
||||
@@ -410,7 +413,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
date: field.admin?.date,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
placeholder: field.admin?.placeholder,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
@@ -428,7 +430,6 @@ export const mapFields = (args: {
|
||||
name: field.name,
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
placeholder: field.admin?.placeholder,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
@@ -455,7 +456,6 @@ export const mapFields = (args: {
|
||||
parentPath: path,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
style: field.admin?.style,
|
||||
width: field.admin?.width,
|
||||
@@ -472,7 +472,6 @@ export const mapFields = (args: {
|
||||
disabled: field.admin?.disabled,
|
||||
editorOptions: field.admin?.editorOptions,
|
||||
jsonSchema: field.jsonSchema,
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
style: field.admin?.style,
|
||||
@@ -489,7 +488,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
hasMany: field.hasMany,
|
||||
label: field.label,
|
||||
max: field.max,
|
||||
maxRows: field.maxRows,
|
||||
min: field.min,
|
||||
@@ -509,7 +507,6 @@ export const mapFields = (args: {
|
||||
name: field.name,
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
style: field.admin?.style,
|
||||
@@ -527,7 +524,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
hasMany: field.hasMany,
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
relationTo: field.relationTo,
|
||||
required: field.required,
|
||||
@@ -546,7 +542,6 @@ export const mapFields = (args: {
|
||||
name: field.name,
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
options: fieldOptions,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
@@ -564,7 +559,6 @@ export const mapFields = (args: {
|
||||
name: field.name,
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
style: field.admin?.style,
|
||||
@@ -671,7 +665,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
hasMany: field.hasMany,
|
||||
label: field.label,
|
||||
maxLength: field.maxLength,
|
||||
minLength: field.minLength,
|
||||
placeholder: field.admin?.placeholder,
|
||||
@@ -690,7 +683,6 @@ export const mapFields = (args: {
|
||||
name: field.name,
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
label: field.label,
|
||||
maxLength: field.maxLength,
|
||||
minLength: field.minLength,
|
||||
placeholder: field.admin?.placeholder,
|
||||
@@ -715,7 +707,6 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
filterOptions: field.filterOptions,
|
||||
label: field.label,
|
||||
readOnly: field.admin?.readOnly,
|
||||
relationTo: field.relationTo,
|
||||
required: field.required,
|
||||
@@ -735,7 +726,6 @@ export const mapFields = (args: {
|
||||
disabled: field.admin?.disabled,
|
||||
hasMany: field.hasMany,
|
||||
isClearable: field.admin?.isClearable,
|
||||
label: field.label,
|
||||
options: fieldOptions,
|
||||
readOnly: field.admin?.readOnly,
|
||||
required: field.required,
|
||||
@@ -798,9 +788,6 @@ export const mapFields = (args: {
|
||||
fieldComponentProps: {
|
||||
name: 'id',
|
||||
label: 'ID',
|
||||
labelProps: {
|
||||
label: 'ID',
|
||||
},
|
||||
},
|
||||
fieldIsPresentational: false,
|
||||
isFieldAffectingData: true,
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type {
|
||||
EditViewProps,
|
||||
EntityDescriptionComponent,
|
||||
EntityDescriptionFunction,
|
||||
SanitizedConfig,
|
||||
SanitizedGlobalConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import { ViewDescription, type ViewDescriptionProps } from '@payloadcms/ui/elements/ViewDescription'
|
||||
import { isPlainFunction, isReactComponent } from 'payload/utilities'
|
||||
import React from 'react'
|
||||
|
||||
import type { GlobalComponentMap } from './types.js'
|
||||
@@ -17,14 +14,7 @@ import type { GlobalComponentMap } from './types.js'
|
||||
import { mapActions } from './actions.js'
|
||||
import { mapFields } from './fields.js'
|
||||
|
||||
export const mapGlobals = ({
|
||||
DefaultEditView,
|
||||
WithServerSideProps,
|
||||
config,
|
||||
globals,
|
||||
i18n,
|
||||
readOnly: readOnlyOverride,
|
||||
}: {
|
||||
export const mapGlobals = (args: {
|
||||
DefaultEditView: React.FC<EditViewProps>
|
||||
WithServerSideProps: WithServerSidePropsType
|
||||
config: SanitizedConfig
|
||||
@@ -33,8 +23,18 @@ export const mapGlobals = ({
|
||||
readOnly?: boolean
|
||||
}): {
|
||||
[key: SanitizedGlobalConfig['slug']]: GlobalComponentMap
|
||||
} =>
|
||||
globals.reduce((acc, globalConfig) => {
|
||||
} => {
|
||||
const {
|
||||
DefaultEditView,
|
||||
WithServerSideProps,
|
||||
config,
|
||||
globals,
|
||||
i18n,
|
||||
i18n: { t },
|
||||
readOnly: readOnlyOverride,
|
||||
} = args
|
||||
|
||||
return globals.reduce((acc, globalConfig) => {
|
||||
const { slug, fields } = globalConfig
|
||||
|
||||
const editViewFromConfig = globalConfig?.admin?.components?.views?.Edit
|
||||
@@ -76,26 +76,24 @@ export const mapGlobals = ({
|
||||
|
||||
const Edit = (CustomEditView as React.FC<EditViewProps>) || DefaultEditView
|
||||
|
||||
const descriptionProps: ViewDescriptionProps = {
|
||||
description:
|
||||
(globalConfig.admin &&
|
||||
'description' in globalConfig.admin &&
|
||||
(((typeof globalConfig.admin?.description === 'string' ||
|
||||
typeof globalConfig.admin?.description === 'object') &&
|
||||
globalConfig.admin.description) ||
|
||||
(typeof globalConfig.admin?.description === 'function' &&
|
||||
isPlainFunction<EntityDescriptionFunction>(globalConfig.admin?.description) &&
|
||||
globalConfig.admin?.description()))) ||
|
||||
undefined,
|
||||
let description = undefined
|
||||
if (globalConfig.admin && 'description' in globalConfig.admin) {
|
||||
if (
|
||||
typeof globalConfig.admin?.description === 'string' ||
|
||||
typeof globalConfig.admin?.description === 'object'
|
||||
) {
|
||||
description = globalConfig.admin.description
|
||||
} else if (typeof globalConfig.admin?.description === 'function') {
|
||||
description = globalConfig.admin?.description({ t })
|
||||
}
|
||||
}
|
||||
|
||||
const descriptionProps: ViewDescriptionProps = {
|
||||
description,
|
||||
}
|
||||
const DescriptionComponent =
|
||||
(globalConfig.admin &&
|
||||
'description' in globalConfig.admin &&
|
||||
((isReactComponent<EntityDescriptionComponent>(globalConfig.admin.description) &&
|
||||
globalConfig.admin.description) ||
|
||||
(globalConfig.admin.description && ViewDescription))) ||
|
||||
undefined
|
||||
globalConfig.admin?.components?.elements?.Description ||
|
||||
(description ? ViewDescription : undefined)
|
||||
|
||||
const Description =
|
||||
DescriptionComponent !== undefined ? (
|
||||
@@ -128,3 +126,4 @@ export const mapGlobals = ({
|
||||
[slug]: componentMap,
|
||||
}
|
||||
}, {})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import React from 'react'
|
||||
|
||||
import type { ComponentMap } from './types.js'
|
||||
|
||||
import { WithServerSideProps as WithServerSidePropsGeneric } from './WithServerSideProps.js'
|
||||
import { WithServerSideProps as WithServerSidePropsGeneric } from '../../../elements/WithServerSideProps/index.js'
|
||||
import { mapCollections } from './collections.js'
|
||||
import { mapGlobals } from './globals.js'
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@ export type IComponentMapContext = {
|
||||
}) => MappedField | undefined
|
||||
}
|
||||
|
||||
export { WithServerSideProps } from './buildComponentMap/WithServerSideProps.js'
|
||||
|
||||
const ComponentMapContext = createContext<IComponentMapContext>({} as IComponentMapContext)
|
||||
|
||||
export const ComponentMapProvider: React.FC<{
|
||||
|
||||
@@ -119,7 +119,9 @@ export const Posts: CollectionConfig = {
|
||||
name: 'descriptionAsComponent',
|
||||
type: 'text',
|
||||
admin: {
|
||||
description: FieldDescriptionComponent,
|
||||
components: {
|
||||
Description: FieldDescriptionComponent,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -78,16 +78,18 @@ const CollapsibleFields: CollectionConfig = {
|
||||
],
|
||||
},
|
||||
{
|
||||
label: () =>
|
||||
getCustomLabel({
|
||||
path: 'functionTitleField',
|
||||
fallback: 'Custom Collapsible Label',
|
||||
style: {},
|
||||
}),
|
||||
type: 'collapsible',
|
||||
admin: {
|
||||
description: 'Collapsible label rendered from a function.',
|
||||
initCollapsed: true,
|
||||
components: {
|
||||
RowLabel: () =>
|
||||
getCustomLabel({
|
||||
path: 'functionTitleField',
|
||||
fallback: 'Custom Collapsible Label',
|
||||
style: {},
|
||||
}),
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
@@ -97,10 +99,12 @@ const CollapsibleFields: CollectionConfig = {
|
||||
],
|
||||
},
|
||||
{
|
||||
label: () => getCustomLabel({ path: 'componentTitleField', style: {} }),
|
||||
type: 'collapsible',
|
||||
admin: {
|
||||
description: 'Collapsible label rendered as a react component.',
|
||||
components: {
|
||||
RowLabel: () => getCustomLabel({ path: 'componentTitleField', style: {} }),
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
@@ -109,8 +113,12 @@ const CollapsibleFields: CollectionConfig = {
|
||||
},
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: () =>
|
||||
getCustomLabel({ path: 'nestedTitle', fallback: 'Nested Collapsible', style: {} }),
|
||||
admin: {
|
||||
components: {
|
||||
RowLabel: () =>
|
||||
getCustomLabel({ path: 'nestedTitle', fallback: 'Nested Collapsible', style: {} }),
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
@@ -125,7 +133,11 @@ const CollapsibleFields: CollectionConfig = {
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
label: NestedCustomLabel,
|
||||
admin: {
|
||||
components: {
|
||||
RowLabel: NestedCustomLabel,
|
||||
},
|
||||
},
|
||||
type: 'collapsible',
|
||||
fields: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user