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