feat(ui): provides payload as prop to all custom server components (#5775)
This commit is contained in:
@@ -12,6 +12,7 @@ import { createClientConfig } from 'payload/config'
|
||||
import React from 'react'
|
||||
import 'react-toastify/dist/ReactToastify.css'
|
||||
|
||||
import { getPayloadHMR } from '../../utilities/getPayloadHMR.js'
|
||||
import { getRequestLanguage } from '../../utilities/getRequestLanguage.js'
|
||||
import { DefaultEditView } from '../../views/Edit/Default/index.js'
|
||||
import { DefaultListView } from '../../views/List/Default/index.js'
|
||||
@@ -39,6 +40,7 @@ export const RootLayout = async ({
|
||||
headers,
|
||||
})
|
||||
|
||||
const payload = await getPayloadHMR({ config })
|
||||
const i18n = await initI18n({ config: config.i18n, context: 'client', language: languageCode })
|
||||
const clientConfig = await createClientConfig({ config, t: i18n.t })
|
||||
|
||||
@@ -76,6 +78,7 @@ export const RootLayout = async ({
|
||||
children,
|
||||
config,
|
||||
i18n,
|
||||
payload,
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { Field } from 'payload/types'
|
||||
import type { Field, WithServerSideProps as WithServerSidePropsType } from 'payload/types'
|
||||
import type { AdminViewProps } from 'payload/types'
|
||||
|
||||
import { Form } from '@payloadcms/ui/forms/Form'
|
||||
import { FormSubmit } from '@payloadcms/ui/forms/Submit'
|
||||
import { buildStateFromSchema } from '@payloadcms/ui/forms/buildStateFromSchema'
|
||||
import { WithServerSideProps as WithServerSidePropsGeneric } from '@payloadcms/ui/providers/ComponentMap'
|
||||
import { mapFields } from '@payloadcms/ui/utilities/buildComponentMap'
|
||||
import React from 'react'
|
||||
|
||||
@@ -17,6 +18,7 @@ export const CreateFirstUserView: React.FC<AdminViewProps> = async ({ initPageRe
|
||||
req,
|
||||
req: {
|
||||
i18n,
|
||||
payload,
|
||||
payload: {
|
||||
config,
|
||||
config: {
|
||||
@@ -49,7 +51,12 @@ export const CreateFirstUserView: React.FC<AdminViewProps> = async ({ initPageRe
|
||||
},
|
||||
]
|
||||
|
||||
const WithServerSideProps: WithServerSidePropsType = ({ Component, ...rest }) => {
|
||||
return <WithServerSidePropsGeneric Component={Component} payload={payload} {...rest} />
|
||||
}
|
||||
|
||||
const createFirstUserFieldMap = mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: fields,
|
||||
i18n,
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { JSONSchema4 } from 'json-schema'
|
||||
import type { SanitizedConfig } from '../config/types.js'
|
||||
import type { Field, RichTextField, Validate } from '../fields/config/types.js'
|
||||
import type { PayloadRequest, RequestContext } from '../types/index.js'
|
||||
import type { WithServerSideProps } from './elements/WithServerSideProps.js'
|
||||
|
||||
export type RichTextFieldProps<
|
||||
Value extends object,
|
||||
@@ -28,6 +29,7 @@ type RichTextAdapterBase<
|
||||
siblingDoc: Record<string, unknown>
|
||||
}) => Promise<void> | null
|
||||
generateComponentMap: (args: {
|
||||
WithServerSideProps: WithServerSideProps
|
||||
config: SanitizedConfig
|
||||
i18n: I18n
|
||||
schemaPath: string
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export type CustomPreviewButton = React.ComponentType
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type CustomPreviewButton = CustomComponent
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export type CustomPublishButton = React.ComponentType
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type CustomPublishButton = CustomComponent
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export type CustomSaveButton = React.ComponentType
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type CustomSaveButton = CustomComponent
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export type CustomSaveDraftButton = React.ComponentType
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type CustomSaveDraftButton = CustomComponent
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export type WithServerSideProps = (args: {
|
||||
[key: string]: any
|
||||
Component: React.ComponentType<any>
|
||||
}) => React.ReactNode
|
||||
@@ -1,10 +1,11 @@
|
||||
import type React from 'react'
|
||||
|
||||
import type { LabelFunction } from '../../config/types.js'
|
||||
import type { CustomComponent, LabelFunction } from '../../config/types.js'
|
||||
import type { Payload } from '../../index.js'
|
||||
|
||||
export type DescriptionFunction = LabelFunction
|
||||
|
||||
export type DescriptionComponent = React.ComponentType<FieldDescriptionProps>
|
||||
export type DescriptionComponent = CustomComponent<FieldDescriptionProps>
|
||||
|
||||
export type Description =
|
||||
| DescriptionComponent
|
||||
@@ -17,4 +18,5 @@ export type FieldDescriptionProps = {
|
||||
className?: string
|
||||
description?: Record<string, string> | string
|
||||
marginPlacement?: 'bottom' | 'top'
|
||||
payload?: Payload
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export type RowLabelComponent = React.ComponentType
|
||||
import type { CustomComponent } from '../../config/types.js'
|
||||
|
||||
export type RowLabelComponent = CustomComponent
|
||||
|
||||
export type RowLabel = Record<string, string> | RowLabelComponent | string
|
||||
|
||||
@@ -13,6 +13,7 @@ export type {
|
||||
DocumentTabConfig,
|
||||
DocumentTabProps,
|
||||
} from './elements/Tab.js'
|
||||
export type { WithServerSideProps } from './elements/WithServerSideProps.js'
|
||||
export type { ErrorProps } from './forms/Error.js'
|
||||
export type {
|
||||
Description,
|
||||
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
import type { Auth, ClientUser, IncomingAuthType } from '../../auth/types.js'
|
||||
import type {
|
||||
Access,
|
||||
CustomComponent,
|
||||
EditConfig,
|
||||
Endpoint,
|
||||
EntityDescription,
|
||||
@@ -201,10 +202,10 @@ export type CollectionAdminOptions = {
|
||||
* Custom admin components
|
||||
*/
|
||||
components?: {
|
||||
AfterList?: React.ComponentType<any>[]
|
||||
AfterListTable?: React.ComponentType<any>[]
|
||||
BeforeList?: React.ComponentType<any>[]
|
||||
BeforeListTable?: React.ComponentType<any>[]
|
||||
AfterList?: CustomComponent[]
|
||||
AfterListTable?: CustomComponent[]
|
||||
BeforeList?: CustomComponent[]
|
||||
BeforeListTable?: CustomComponent[]
|
||||
/**
|
||||
* Components within the edit view
|
||||
*/
|
||||
@@ -239,7 +240,7 @@ export type CollectionAdminOptions = {
|
||||
List?:
|
||||
| {
|
||||
Component?: React.ComponentType<any>
|
||||
actions?: React.ComponentType<any>[]
|
||||
actions?: CustomComponent[]
|
||||
}
|
||||
| React.ComponentType<any>
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ export type EditViewConfig =
|
||||
path: string
|
||||
}
|
||||
| {
|
||||
actions?: React.ComponentType<any>[]
|
||||
actions?: CustomComponent[]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,6 +291,14 @@ export type EditViewConfig =
|
||||
*/
|
||||
export type EditView = EditViewComponent | EditViewConfig
|
||||
|
||||
export type ServerProps = {
|
||||
payload: Payload
|
||||
}
|
||||
|
||||
export const serverProps: (keyof ServerProps)[] = ['payload']
|
||||
|
||||
export type CustomComponent<T extends any = any> = React.ComponentType<T & ServerProps>
|
||||
|
||||
export type Locale = {
|
||||
/**
|
||||
* value of supported locale
|
||||
@@ -420,46 +428,46 @@ export type Config = {
|
||||
/**
|
||||
* Replace the navigation with a custom component
|
||||
*/
|
||||
Nav?: React.ComponentType<any>
|
||||
Nav?: CustomComponent
|
||||
/**
|
||||
* Add custom components to the top right of the Admin Panel
|
||||
*/
|
||||
actions?: React.ComponentType<any>[]
|
||||
actions?: CustomComponent[]
|
||||
/**
|
||||
* Add custom components after the collection overview
|
||||
*/
|
||||
afterDashboard?: React.ComponentType<any>[]
|
||||
afterDashboard?: CustomComponent[]
|
||||
/**
|
||||
* Add custom components after the email/password field
|
||||
*/
|
||||
afterLogin?: React.ComponentType<any>[]
|
||||
afterLogin?: CustomComponent[]
|
||||
/**
|
||||
* Add custom components after the navigation links
|
||||
*/
|
||||
afterNavLinks?: React.ComponentType<any>[]
|
||||
afterNavLinks?: CustomComponent[]
|
||||
/**
|
||||
* Add custom components before the collection overview
|
||||
*/
|
||||
beforeDashboard?: React.ComponentType<any>[]
|
||||
beforeDashboard?: CustomComponent[]
|
||||
/**
|
||||
* Add custom components before the email/password field
|
||||
*/
|
||||
beforeLogin?: React.ComponentType<any>[]
|
||||
beforeLogin?: CustomComponent[]
|
||||
/**
|
||||
* Add custom components before the navigation links
|
||||
*/
|
||||
beforeNavLinks?: React.ComponentType<any>[]
|
||||
beforeNavLinks?: CustomComponent[]
|
||||
/** Replace graphical components */
|
||||
graphics?: {
|
||||
/** Replace the icon in the navigation */
|
||||
Icon?: React.ComponentType<any>
|
||||
Icon?: CustomComponent
|
||||
/** Replace the logo on the login page */
|
||||
Logo?: React.ComponentType<any>
|
||||
Logo?: CustomComponent
|
||||
}
|
||||
/** Replace logout related components */
|
||||
logout?: {
|
||||
/** Replace the logout button */
|
||||
Button?: React.ComponentType<any>
|
||||
Button?: CustomComponent
|
||||
}
|
||||
/**
|
||||
* Wrap the admin dashboard in custom context providers
|
||||
@@ -716,7 +724,7 @@ export type EditConfig =
|
||||
)
|
||||
| EditViewComponent
|
||||
|
||||
export type EntityDescriptionComponent = React.ComponentType<any>
|
||||
export type EntityDescriptionComponent = CustomComponent
|
||||
|
||||
export type EntityDescriptionFunction = () => string
|
||||
|
||||
|
||||
@@ -34,7 +34,12 @@ export { isEntityHidden } from '../utilities/isEntityHidden.js'
|
||||
export { isNumber } from '../utilities/isNumber.js'
|
||||
export { isPlainObject } from '../utilities/isPlainObject.js'
|
||||
|
||||
export { isPlainFunction, isReactComponent } from '../utilities/isReactComponent.js'
|
||||
export {
|
||||
isPlainFunction,
|
||||
isReactClientComponent,
|
||||
isReactComponent,
|
||||
isReactServerComponent,
|
||||
} from '../utilities/isReactComponent.js'
|
||||
export { isValidID } from '../utilities/isValidID.js'
|
||||
export { default as isolateObjectProperty } from '../utilities/isolateObjectProperty.js'
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import type {
|
||||
} from '../../admin/types.js'
|
||||
import type { User } from '../../auth/index.js'
|
||||
import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'
|
||||
import type { LabelFunction } from '../../config/types.js'
|
||||
import type { CustomComponent, LabelFunction } from '../../config/types.js'
|
||||
import type { DBIdentifierName } from '../../database/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../../globals/config/types.js'
|
||||
import type { Operation, PayloadRequest, RequestContext, Where } from '../../types/index.js'
|
||||
@@ -115,8 +115,8 @@ export type FilterOptions<T = any> =
|
||||
type Admin = {
|
||||
className?: string
|
||||
components?: {
|
||||
Cell?: React.ComponentType<any>
|
||||
Field?: React.ComponentType<any>
|
||||
Cell?: CustomComponent
|
||||
Field?: CustomComponent
|
||||
Filter?: React.ComponentType<any>
|
||||
}
|
||||
/**
|
||||
@@ -208,10 +208,10 @@ export type NumberField = FieldBase & {
|
||||
/** Set this property to a string that will be used for browser autocomplete. */
|
||||
autoComplete?: string
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
afterInput?: React.ComponentType<any>[]
|
||||
beforeInput?: React.ComponentType<any>[]
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
/** Set this property to define a placeholder string for the field. */
|
||||
placeholder?: Record<string, string> | string
|
||||
@@ -246,10 +246,10 @@ export type TextField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
autoComplete?: string
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
afterInput?: React.ComponentType<any>[]
|
||||
beforeInput?: React.ComponentType<any>[]
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
placeholder?: Record<string, string> | string
|
||||
rtl?: boolean
|
||||
@@ -280,10 +280,10 @@ export type EmailField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
autoComplete?: string
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
afterInput?: React.ComponentType<any>[]
|
||||
beforeInput?: React.ComponentType<any>[]
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
placeholder?: Record<string, string> | string
|
||||
}
|
||||
@@ -293,10 +293,10 @@ export type EmailField = FieldBase & {
|
||||
export type TextareaField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
afterInput?: React.ComponentType<any>[]
|
||||
beforeInput?: React.ComponentType<any>[]
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
placeholder?: Record<string, string> | string
|
||||
rows?: number
|
||||
@@ -310,10 +310,10 @@ export type TextareaField = FieldBase & {
|
||||
export type CheckboxField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
afterInput?: React.ComponentType<any>[]
|
||||
beforeInput?: React.ComponentType<any>[]
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
}
|
||||
type: 'checkbox'
|
||||
@@ -322,10 +322,10 @@ export type CheckboxField = FieldBase & {
|
||||
export type DateField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
afterInput?: React.ComponentType<any>[]
|
||||
beforeInput?: React.ComponentType<any>[]
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
afterInput?: CustomComponent[]
|
||||
beforeInput?: CustomComponent[]
|
||||
}
|
||||
date?: ConditionalDateProps
|
||||
placeholder?: Record<string, string> | string
|
||||
@@ -416,8 +416,8 @@ export type TabAsField = Tab & {
|
||||
export type UIField = {
|
||||
admin: {
|
||||
components?: {
|
||||
Cell?: React.ComponentType<any>
|
||||
Field: React.ComponentType<any>
|
||||
Cell?: CustomComponent
|
||||
Field: CustomComponent
|
||||
Filter?: React.ComponentType<any>
|
||||
}
|
||||
condition?: Condition
|
||||
@@ -435,8 +435,8 @@ export type UIField = {
|
||||
export type UploadField = FieldBase & {
|
||||
admin?: {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
}
|
||||
filterOptions?: FilterOptions
|
||||
@@ -447,8 +447,8 @@ export type UploadField = FieldBase & {
|
||||
|
||||
type CodeAdmin = Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
editorOptions?: EditorProps['options']
|
||||
language?: string
|
||||
@@ -463,8 +463,8 @@ export type CodeField = Omit<FieldBase, 'admin'> & {
|
||||
|
||||
type JSONAdmin = Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
editorOptions?: EditorProps['options']
|
||||
}
|
||||
@@ -477,8 +477,8 @@ export type JSONField = Omit<FieldBase, 'admin'> & {
|
||||
export type SelectField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
isClearable?: boolean
|
||||
isSortable?: boolean
|
||||
@@ -533,8 +533,8 @@ type SharedRelationshipProperties = FieldBase & {
|
||||
type RelationshipAdmin = Admin & {
|
||||
allowCreate?: boolean
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
isSortable?: boolean
|
||||
}
|
||||
@@ -574,8 +574,8 @@ export type RichTextField<
|
||||
> = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
}
|
||||
editor?: RichTextAdapter<Value, AdapterProps, AdapterProps>
|
||||
@@ -618,8 +618,8 @@ export type ArrayField = FieldBase & {
|
||||
export type RadioField = FieldBase & {
|
||||
admin?: Admin & {
|
||||
components?: {
|
||||
Error?: React.ComponentType<ErrorProps>
|
||||
Label?: React.ComponentType<LabelProps>
|
||||
Error?: CustomComponent<ErrorProps>
|
||||
Label?: CustomComponent<LabelProps>
|
||||
}
|
||||
layout?: 'horizontal' | 'vertical'
|
||||
}
|
||||
|
||||
@@ -4,14 +4,23 @@ import { isValidElement } from 'react'
|
||||
|
||||
import { isPlainObject } from './isPlainObject.js'
|
||||
|
||||
export function isReactServerComponent<T extends any>(
|
||||
component: React.ComponentType | any,
|
||||
): component is T {
|
||||
return typeof component === 'function' && isValidElement(component)
|
||||
}
|
||||
|
||||
export function isReactClientComponent<T extends any>(
|
||||
component: React.ComponentType | any,
|
||||
): component is T {
|
||||
// Do this to test for client components (`use client` directive) bc they import as empty objects
|
||||
return typeof component === 'object' && !isPlainObject(component)
|
||||
}
|
||||
|
||||
export function isReactComponent<T extends any>(
|
||||
component: React.ComponentType | any,
|
||||
): component is T {
|
||||
return (
|
||||
(typeof component === 'function' && isValidElement(component)) ||
|
||||
// Do this to test for client components (`use client` directive) bc they import as empty objects
|
||||
(typeof component === 'object' && !isPlainObject(component))
|
||||
)
|
||||
return isReactServerComponent(component) || isReactClientComponent(component)
|
||||
}
|
||||
|
||||
export function isPlainFunction<T extends Function>(fn: any): fn is T {
|
||||
|
||||
@@ -13,7 +13,7 @@ export const getGenerateComponentMap =
|
||||
(args: {
|
||||
resolvedFeatureMap: ResolvedServerFeatureMap
|
||||
}): RichTextAdapter['generateComponentMap'] =>
|
||||
({ config, i18n, schemaPath }) => {
|
||||
({ WithServerSideProps, config, i18n, schemaPath }) => {
|
||||
const validRelationships = config.collections.map((c) => c.slug) || []
|
||||
|
||||
const componentMap = new Map()
|
||||
@@ -50,7 +50,8 @@ export const getGenerateComponentMap =
|
||||
if (Component) {
|
||||
componentMap.set(
|
||||
`feature.${featureKey}.components.${componentKey}`,
|
||||
<Component
|
||||
<WithServerSideProps
|
||||
Component={Component}
|
||||
componentKey={componentKey}
|
||||
featureKey={resolvedFeature.key}
|
||||
key={`${resolvedFeature.key}-${componentKey}`}
|
||||
@@ -86,6 +87,7 @@ export const getGenerateComponentMap =
|
||||
})
|
||||
|
||||
const mappedFields = mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
disableAddingID: true,
|
||||
fieldSchema: sanitizedFields,
|
||||
|
||||
@@ -14,7 +14,7 @@ import { defaultLeaves as leafTypes } from './field/leaves/index.js'
|
||||
|
||||
export const getGenerateComponentMap =
|
||||
(args: AdapterArguments): RichTextAdapter['generateComponentMap'] =>
|
||||
({ config, i18n }) => {
|
||||
({ WithServerSideProps, config, i18n }) => {
|
||||
const componentMap = new Map()
|
||||
|
||||
const validRelationships = config.collections.map((c) => c.slug) || []
|
||||
@@ -73,6 +73,7 @@ export const getGenerateComponentMap =
|
||||
})
|
||||
|
||||
const mappedFields = mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: linkFields,
|
||||
i18n,
|
||||
@@ -104,6 +105,7 @@ export const getGenerateComponentMap =
|
||||
})
|
||||
|
||||
const mappedFields = mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: uploadFields,
|
||||
i18n,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { serverProps } from 'payload/config'
|
||||
import { deepMerge } from 'payload/utilities'
|
||||
import React from 'react'
|
||||
|
||||
@@ -21,14 +22,23 @@ import React from 'react'
|
||||
*/
|
||||
export function withMergedProps<ToMergeIntoProps, CompleteReturnProps>({
|
||||
Component,
|
||||
sanitizeServerOnlyProps = true,
|
||||
toMergeIntoProps,
|
||||
}: {
|
||||
Component: React.FC<CompleteReturnProps>
|
||||
sanitizeServerOnlyProps?: boolean
|
||||
toMergeIntoProps: ToMergeIntoProps
|
||||
}): React.FC<CompleteReturnProps> {
|
||||
// A wrapper around the args.Component to inject the args.toMergeArgs as props, which are merged with the passed props
|
||||
const MergedPropsComponent: React.FC<CompleteReturnProps> = (passedProps) => {
|
||||
const mergedProps = deepMerge(passedProps, toMergeIntoProps)
|
||||
|
||||
if (sanitizeServerOnlyProps) {
|
||||
serverProps.forEach((prop) => {
|
||||
delete (mergedProps)[prop]
|
||||
})
|
||||
}
|
||||
|
||||
return <Component {...mergedProps} />
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { withCondition } from '../../forms/withCondition/index.js'
|
||||
export type HiddenInputFieldProps = FormFieldBase & {
|
||||
disableModifyingForm?: false
|
||||
forceUsePathFromProps?: boolean
|
||||
name: string
|
||||
name?: string
|
||||
path?: string
|
||||
value?: unknown
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { WithServerSideProps as WithServerSidePropsType } from 'payload/types'
|
||||
|
||||
import { isReactServerComponent } from 'payload/utilities'
|
||||
import React from 'react'
|
||||
|
||||
export const WithServerSideProps: WithServerSidePropsType = ({ Component, payload, ...rest }) => {
|
||||
if (Component) {
|
||||
const WithServerSideProps: React.FC<any> = (passedProps) => {
|
||||
const propsWithPayload = {
|
||||
...passedProps,
|
||||
...(isReactServerComponent(Component) ? { payload } : {}),
|
||||
}
|
||||
|
||||
return <Component {...propsWithPayload} />
|
||||
}
|
||||
|
||||
return <WithServerSideProps {...rest} />
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from 'payload/types'
|
||||
import type {
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedGlobalConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import type { ActionMap } from './types.js'
|
||||
|
||||
export const mapActions = (args: {
|
||||
WithServerSideProps: WithServerSidePropsType
|
||||
collectionConfig?: SanitizedCollectionConfig
|
||||
globalConfig?: SanitizedGlobalConfig
|
||||
}): ActionMap => {
|
||||
const { collectionConfig, globalConfig } = args
|
||||
const { WithServerSideProps, collectionConfig, globalConfig } = args
|
||||
|
||||
const editViews = (collectionConfig || globalConfig)?.admin?.components?.views?.Edit
|
||||
|
||||
@@ -28,7 +33,7 @@ export const mapActions = (args: {
|
||||
view.actions.forEach((action) => {
|
||||
const Action = action
|
||||
if (typeof Action === 'function') {
|
||||
result.Edit[key] = [...(result[key] || []), <Action />]
|
||||
result.Edit[key] = [...(result[key] || []), <WithServerSideProps Component={Action} />]
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -40,7 +45,7 @@ export const mapActions = (args: {
|
||||
const Action = action
|
||||
if (typeof Action === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
result.List = [...result.List, <Action />]
|
||||
result.List = [...result.List, <WithServerSideProps Component={Action} />]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
EntityDescriptionFunction,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import { ViewDescription } from '@payloadcms/ui/elements/ViewDescription'
|
||||
@@ -21,6 +22,7 @@ import { mapFields } from './fields.js'
|
||||
export const mapCollections = ({
|
||||
DefaultEditView,
|
||||
DefaultListView,
|
||||
WithServerSideProps,
|
||||
collections,
|
||||
config,
|
||||
i18n,
|
||||
@@ -28,6 +30,7 @@ export const mapCollections = ({
|
||||
}: {
|
||||
DefaultEditView: React.FC<EditViewProps>
|
||||
DefaultListView: React.FC<AdminViewProps>
|
||||
WithServerSideProps: WithServerSidePropsType
|
||||
collections: SanitizedCollectionConfig[]
|
||||
config: SanitizedConfig
|
||||
i18n: I18n
|
||||
@@ -71,44 +74,60 @@ export const mapCollections = ({
|
||||
|
||||
const List = CustomListView || DefaultListView
|
||||
|
||||
const beforeList = collectionConfig?.admin?.components?.BeforeList
|
||||
|
||||
const beforeListTable = collectionConfig?.admin?.components?.BeforeListTable
|
||||
|
||||
const afterList = collectionConfig?.admin?.components?.AfterList
|
||||
|
||||
const afterListTable = collectionConfig?.admin?.components?.AfterListTable
|
||||
|
||||
const SaveButtonComponent = collectionConfig?.admin?.components?.edit?.SaveButton
|
||||
const SaveButton = SaveButtonComponent ? <SaveButtonComponent /> : undefined
|
||||
|
||||
const SaveButton = SaveButtonComponent ? (
|
||||
<WithServerSideProps Component={SaveButtonComponent} />
|
||||
) : undefined
|
||||
|
||||
const SaveDraftButtonComponent = collectionConfig?.admin?.components?.edit?.SaveDraftButton
|
||||
const SaveDraftButton = SaveDraftButtonComponent ? <SaveDraftButtonComponent /> : undefined
|
||||
|
||||
const SaveDraftButton = SaveDraftButtonComponent ? (
|
||||
<WithServerSideProps Component={SaveDraftButtonComponent} />
|
||||
) : undefined
|
||||
|
||||
const PreviewButtonComponent = collectionConfig?.admin?.components?.edit?.PreviewButton
|
||||
const PreviewButton = PreviewButtonComponent ? <PreviewButtonComponent /> : undefined
|
||||
|
||||
const PreviewButton = PreviewButtonComponent ? (
|
||||
<WithServerSideProps Component={PreviewButtonComponent} />
|
||||
) : undefined
|
||||
|
||||
const PublishButtonComponent = collectionConfig?.admin?.components?.edit?.PublishButton
|
||||
const PublishButton = PublishButtonComponent ? <PublishButtonComponent /> : undefined
|
||||
|
||||
const PublishButton = PublishButtonComponent ? (
|
||||
<WithServerSideProps Component={PublishButtonComponent} />
|
||||
) : undefined
|
||||
|
||||
const beforeList = collectionConfig?.admin?.components?.BeforeList
|
||||
|
||||
const BeforeList =
|
||||
(beforeList && Array.isArray(beforeList) && beforeList?.map((Component) => <Component />)) ||
|
||||
(beforeList &&
|
||||
Array.isArray(beforeList) &&
|
||||
beforeList?.map((Component) => <WithServerSideProps Component={Component} />)) ||
|
||||
null
|
||||
|
||||
const beforeListTable = collectionConfig?.admin?.components?.BeforeListTable
|
||||
|
||||
const BeforeListTable =
|
||||
(beforeListTable &&
|
||||
Array.isArray(beforeListTable) &&
|
||||
beforeListTable?.map((Component) => <Component />)) ||
|
||||
beforeListTable?.map((Component) => <WithServerSideProps Component={Component} />)) ||
|
||||
null
|
||||
|
||||
const afterList = collectionConfig?.admin?.components?.AfterList
|
||||
|
||||
const AfterList =
|
||||
(afterList && Array.isArray(afterList) && afterList?.map((Component) => <Component />)) ||
|
||||
(afterList &&
|
||||
Array.isArray(afterList) &&
|
||||
afterList?.map((Component) => <WithServerSideProps Component={Component} />)) ||
|
||||
null
|
||||
|
||||
const afterListTable = collectionConfig?.admin?.components?.AfterListTable
|
||||
|
||||
const AfterListTable =
|
||||
(afterListTable &&
|
||||
Array.isArray(afterListTable) &&
|
||||
afterListTable?.map((Component) => <Component />)) ||
|
||||
afterListTable?.map((Component) => <WithServerSideProps Component={Component} />)) ||
|
||||
null
|
||||
|
||||
const descriptionProps: ViewDescriptionProps = {
|
||||
@@ -134,7 +153,7 @@ export const mapCollections = ({
|
||||
|
||||
const Description =
|
||||
DescriptionComponent !== undefined ? (
|
||||
<DescriptionComponent {...(descriptionProps || {})} />
|
||||
<WithServerSideProps Component={DescriptionComponent} {...(descriptionProps || {})} />
|
||||
) : undefined
|
||||
|
||||
const componentMap: CollectionComponentMap = {
|
||||
@@ -150,9 +169,11 @@ export const mapCollections = ({
|
||||
SaveButton,
|
||||
SaveDraftButton,
|
||||
actionsMap: mapActions({
|
||||
WithServerSideProps,
|
||||
collectionConfig,
|
||||
}),
|
||||
fieldMap: mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: fields,
|
||||
i18n,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type { CustomComponent } from 'packages/payload/src/config/types.js'
|
||||
import type {
|
||||
CellComponentProps,
|
||||
DescriptionComponent,
|
||||
@@ -11,11 +12,17 @@ import type {
|
||||
Option,
|
||||
RowLabelComponent,
|
||||
SanitizedConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import { FieldDescription } from '@payloadcms/ui/forms/FieldDescription'
|
||||
import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/types'
|
||||
import { isPlainFunction, isReactComponent } from 'payload/utilities'
|
||||
import {
|
||||
isPlainFunction,
|
||||
isReactClientComponent,
|
||||
isReactComponent,
|
||||
isReactServerComponent,
|
||||
} from 'payload/utilities'
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
import type { ArrayFieldProps } from '../../../fields/Array/index.js'
|
||||
@@ -50,6 +57,7 @@ import type {
|
||||
import { HiddenInput } from '../../../fields/HiddenInput/index.js'
|
||||
|
||||
export const mapFields = (args: {
|
||||
WithServerSideProps: WithServerSidePropsType
|
||||
config: SanitizedConfig
|
||||
/**
|
||||
* If mapFields is used outside of collections, you might not want it to add an id field
|
||||
@@ -62,6 +70,7 @@ export const mapFields = (args: {
|
||||
readOnly?: boolean
|
||||
}): FieldMap => {
|
||||
const {
|
||||
WithServerSideProps,
|
||||
config,
|
||||
disableAddingID,
|
||||
fieldSchema,
|
||||
@@ -74,8 +83,7 @@ export const mapFields = (args: {
|
||||
|
||||
const result: FieldMap = fieldSchema.reduce((acc, field): FieldMap => {
|
||||
const fieldIsPresentational = fieldIsPresentationalOnly(field)
|
||||
let CustomFieldComponent: React.ComponentType<FieldComponentProps> =
|
||||
field.admin?.components?.Field
|
||||
let CustomFieldComponent: CustomComponent<FieldComponentProps> = field.admin?.components?.Field
|
||||
|
||||
const CustomCellComponent = field.admin?.components?.Cell
|
||||
|
||||
@@ -102,7 +110,7 @@ export const mapFields = (args: {
|
||||
Array.isArray(field.admin?.components?.afterInput) && (
|
||||
<Fragment>
|
||||
{field.admin.components.afterInput.map((Component, i) => (
|
||||
<Component key={i} />
|
||||
<WithServerSideProps Component={Component} key={i} />
|
||||
))}
|
||||
</Fragment>
|
||||
)) ||
|
||||
@@ -115,7 +123,7 @@ export const mapFields = (args: {
|
||||
Array.isArray(field.admin.components.beforeInput) && (
|
||||
<Fragment>
|
||||
{field.admin.components.beforeInput.map((Component, i) => (
|
||||
<Component key={i} />
|
||||
<WithServerSideProps Component={Component} key={i} />
|
||||
))}
|
||||
</Fragment>
|
||||
)) ||
|
||||
@@ -133,12 +141,12 @@ export const mapFields = (args: {
|
||||
('admin' in field &&
|
||||
field.admin?.components &&
|
||||
'Label' in field.admin.components &&
|
||||
field.admin?.components?.Label) ||
|
||||
field.admin.components?.Label) ||
|
||||
undefined
|
||||
|
||||
const CustomLabel =
|
||||
CustomLabelComponent !== undefined ? (
|
||||
<CustomLabelComponent {...(labelProps || {})} />
|
||||
<WithServerSideProps Component={CustomLabelComponent} {...(labelProps || {})} />
|
||||
) : undefined
|
||||
|
||||
const descriptionProps: FieldDescriptionProps = {
|
||||
@@ -164,7 +172,10 @@ export const mapFields = (args: {
|
||||
|
||||
const CustomDescription =
|
||||
CustomDescriptionComponent !== undefined ? (
|
||||
<CustomDescriptionComponent {...(descriptionProps || {})} />
|
||||
<WithServerSideProps
|
||||
Component={CustomDescriptionComponent}
|
||||
{...(descriptionProps || {})}
|
||||
/>
|
||||
) : undefined
|
||||
|
||||
const errorProps = {
|
||||
@@ -180,7 +191,7 @@ export const mapFields = (args: {
|
||||
|
||||
const CustomError =
|
||||
CustomErrorComponent !== undefined ? (
|
||||
<CustomErrorComponent {...(errorProps || {})} />
|
||||
<WithServerSideProps Component={CustomErrorComponent} {...(errorProps || {})} />
|
||||
) : undefined
|
||||
|
||||
const baseFieldProps: FormFieldBase = {
|
||||
@@ -239,7 +250,7 @@ export const mapFields = (args: {
|
||||
isReactComponent<RowLabelComponent>(field.admin.components.RowLabel)
|
||||
) {
|
||||
const CustomRowLabelComponent = field.admin.components.RowLabel
|
||||
CustomRowLabel = <CustomRowLabelComponent />
|
||||
CustomRowLabel = <WithServerSideProps Component={CustomRowLabelComponent} />
|
||||
}
|
||||
|
||||
const arrayFieldProps: Omit<ArrayFieldProps, 'indexPath' | 'permissions'> = {
|
||||
@@ -249,6 +260,7 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
fieldMap: mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: field.fields,
|
||||
filter,
|
||||
@@ -272,6 +284,7 @@ export const mapFields = (args: {
|
||||
case 'blocks': {
|
||||
const blocks = field.blocks.map((block) => {
|
||||
const blockFieldMap = mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: block.fields,
|
||||
filter,
|
||||
@@ -355,7 +368,9 @@ export const mapFields = (args: {
|
||||
|
||||
if (isReactComponent(field.label) || isPlainFunction(field.label)) {
|
||||
const CustomCollapsibleLabelComponent = field.label as RowLabelComponent
|
||||
CustomCollapsibleLabel = <CustomCollapsibleLabelComponent />
|
||||
CustomCollapsibleLabel = (
|
||||
<WithServerSideProps Component={CustomCollapsibleLabelComponent} />
|
||||
)
|
||||
}
|
||||
|
||||
const collapsibleField: Omit<CollapsibleFieldProps, 'indexPath' | 'permissions'> = {
|
||||
@@ -364,6 +379,7 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
fieldMap: mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
disableAddingID: true,
|
||||
fieldSchema: field.fields,
|
||||
@@ -426,6 +442,7 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
fieldMap: mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
disableAddingID: true,
|
||||
fieldSchema: field.fields,
|
||||
@@ -553,7 +570,12 @@ export const mapFields = (args: {
|
||||
const RichTextCellComponent = field.editor.CellComponent
|
||||
|
||||
if (typeof field.editor.generateComponentMap === 'function') {
|
||||
const result = field.editor.generateComponentMap({ config, i18n, schemaPath: path })
|
||||
const result = field.editor.generateComponentMap({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
i18n,
|
||||
schemaPath: path,
|
||||
})
|
||||
richTextField.richTextComponentMap = result
|
||||
cellComponentProps.richTextComponentMap = result
|
||||
}
|
||||
@@ -563,7 +585,9 @@ export const mapFields = (args: {
|
||||
}
|
||||
|
||||
if (RichTextCellComponent) {
|
||||
cellComponentProps.CellComponentOverride = <RichTextCellComponent />
|
||||
cellComponentProps.CellComponentOverride = (
|
||||
<WithServerSideProps Component={RichTextCellComponent} />
|
||||
)
|
||||
}
|
||||
|
||||
fieldComponentProps = richTextField
|
||||
@@ -576,6 +600,7 @@ export const mapFields = (args: {
|
||||
className: field.admin?.className,
|
||||
disabled: field.admin?.disabled,
|
||||
fieldMap: mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
disableAddingID: true,
|
||||
fieldSchema: field.fields,
|
||||
@@ -597,6 +622,7 @@ export const mapFields = (args: {
|
||||
// `tabs` fields require a field map of each of its tab's nested fields
|
||||
const tabs = field.tabs.map((tab) => {
|
||||
const tabFieldMap = mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
disableAddingID: true,
|
||||
fieldSchema: tab.fields,
|
||||
@@ -722,10 +748,10 @@ export const mapFields = (args: {
|
||||
name: 'name' in field ? field.name : undefined,
|
||||
type: field.type,
|
||||
CustomCell: CustomCellComponent ? (
|
||||
<CustomCellComponent {...cellComponentProps} />
|
||||
<WithServerSideProps Component={CustomCellComponent} {...cellComponentProps} />
|
||||
) : undefined,
|
||||
CustomField: CustomFieldComponent ? (
|
||||
<CustomFieldComponent {...fieldComponentProps} />
|
||||
<WithServerSideProps Component={CustomFieldComponent} {...fieldComponentProps} />
|
||||
) : undefined,
|
||||
cellComponentProps,
|
||||
disableBulkEdit:
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
EntityDescriptionFunction,
|
||||
SanitizedConfig,
|
||||
SanitizedGlobalConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import { ViewDescription, type ViewDescriptionProps } from '@payloadcms/ui/elements/ViewDescription'
|
||||
@@ -18,12 +19,14 @@ import { mapFields } from './fields.js'
|
||||
|
||||
export const mapGlobals = ({
|
||||
DefaultEditView,
|
||||
WithServerSideProps,
|
||||
config,
|
||||
globals,
|
||||
i18n,
|
||||
readOnly: readOnlyOverride,
|
||||
}: {
|
||||
DefaultEditView: React.FC<EditViewProps>
|
||||
WithServerSideProps: WithServerSidePropsType
|
||||
config: SanitizedConfig
|
||||
globals: SanitizedGlobalConfig[]
|
||||
i18n: I18n
|
||||
@@ -37,16 +40,28 @@ export const mapGlobals = ({
|
||||
const editViewFromConfig = globalConfig?.admin?.components?.views?.Edit
|
||||
|
||||
const SaveButton = globalConfig?.admin?.components?.elements?.SaveButton
|
||||
const SaveButtonComponent = SaveButton ? <SaveButton /> : undefined
|
||||
|
||||
const SaveButtonComponent = SaveButton ? (
|
||||
<WithServerSideProps Component={SaveButton} />
|
||||
) : undefined
|
||||
|
||||
const SaveDraftButton = globalConfig?.admin?.components?.elements?.SaveDraftButton
|
||||
const SaveDraftButtonComponent = SaveDraftButton ? <SaveDraftButton /> : undefined
|
||||
|
||||
const SaveDraftButtonComponent = SaveDraftButton ? (
|
||||
<WithServerSideProps Component={SaveDraftButton} />
|
||||
) : undefined
|
||||
|
||||
const PreviewButton = globalConfig?.admin?.components?.elements?.PreviewButton
|
||||
const PreviewButtonComponent = PreviewButton ? <PreviewButton /> : undefined
|
||||
|
||||
const PreviewButtonComponent = PreviewButton ? (
|
||||
<WithServerSideProps Component={PreviewButton} />
|
||||
) : undefined
|
||||
|
||||
const PublishButton = globalConfig?.admin?.components?.elements?.PublishButton
|
||||
const PublishButtonComponent = PublishButton ? <PublishButton /> : undefined
|
||||
|
||||
const PublishButtonComponent = PublishButton ? (
|
||||
<WithServerSideProps Component={PublishButton} />
|
||||
) : undefined
|
||||
|
||||
const CustomEditView =
|
||||
typeof editViewFromConfig === 'function'
|
||||
@@ -84,7 +99,7 @@ export const mapGlobals = ({
|
||||
|
||||
const Description =
|
||||
DescriptionComponent !== undefined ? (
|
||||
<DescriptionComponent {...(descriptionProps || {})} />
|
||||
<WithServerSideProps Component={DescriptionComponent} {...(descriptionProps || {})} />
|
||||
) : undefined
|
||||
|
||||
const componentMap: GlobalComponentMap = {
|
||||
@@ -95,9 +110,11 @@ export const mapGlobals = ({
|
||||
SaveButton: SaveButtonComponent,
|
||||
SaveDraftButton: SaveDraftButtonComponent,
|
||||
actionsMap: mapActions({
|
||||
WithServerSideProps,
|
||||
globalConfig,
|
||||
}),
|
||||
fieldMap: mapFields({
|
||||
WithServerSideProps,
|
||||
config,
|
||||
fieldSchema: fields,
|
||||
i18n,
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type { AdminViewProps, EditViewProps, SanitizedConfig } from 'payload/types'
|
||||
import type {
|
||||
AdminViewProps,
|
||||
EditViewProps,
|
||||
Payload,
|
||||
SanitizedConfig,
|
||||
WithServerSideProps as WithServerSidePropsType,
|
||||
} from 'payload/types'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import type { ComponentMap } from './types.js'
|
||||
|
||||
import { WithServerSideProps as WithServerSidePropsGeneric } from './WithServerSideProps.js'
|
||||
import { mapCollections } from './collections.js'
|
||||
import { mapGlobals } from './globals.js'
|
||||
|
||||
@@ -14,16 +21,22 @@ export const buildComponentMap = (args: {
|
||||
children: React.ReactNode
|
||||
config: SanitizedConfig
|
||||
i18n: I18n
|
||||
payload: Payload
|
||||
readOnly?: boolean
|
||||
}): {
|
||||
componentMap: ComponentMap
|
||||
wrappedChildren: React.ReactNode
|
||||
} => {
|
||||
const { DefaultEditView, DefaultListView, children, config, i18n, readOnly } = args
|
||||
const { DefaultEditView, DefaultListView, children, config, i18n, payload, readOnly } = args
|
||||
|
||||
const WithServerSideProps: WithServerSidePropsType = ({ Component, ...rest }) => {
|
||||
return <WithServerSidePropsGeneric Component={Component} payload={payload} {...rest} />
|
||||
}
|
||||
|
||||
const collections = mapCollections({
|
||||
DefaultEditView,
|
||||
DefaultListView,
|
||||
WithServerSideProps,
|
||||
collections: config.collections,
|
||||
config,
|
||||
i18n,
|
||||
@@ -32,6 +45,7 @@ export const buildComponentMap = (args: {
|
||||
|
||||
const globals = mapGlobals({
|
||||
DefaultEditView,
|
||||
WithServerSideProps,
|
||||
config,
|
||||
globals: config.globals,
|
||||
i18n,
|
||||
@@ -52,17 +66,21 @@ export const buildComponentMap = (args: {
|
||||
|
||||
const LogoutButtonComponent = config.admin?.components?.logout?.Button
|
||||
|
||||
const LogoutButton = LogoutButtonComponent ? <LogoutButtonComponent /> : null
|
||||
const LogoutButton = LogoutButtonComponent ? (
|
||||
<WithServerSideProps Component={LogoutButtonComponent} />
|
||||
) : null
|
||||
|
||||
const IconComponent = config.admin?.components?.graphics?.Icon
|
||||
|
||||
const Icon = IconComponent ? <IconComponent /> : null
|
||||
const Icon = IconComponent ? <WithServerSideProps Component={IconComponent} /> : null
|
||||
|
||||
return {
|
||||
componentMap: {
|
||||
Icon,
|
||||
LogoutButton,
|
||||
actions: config.admin?.components?.actions?.map((Component) => <Component />),
|
||||
actions: config.admin?.components?.actions?.map((Component) => (
|
||||
<WithServerSideProps Component={Component} />
|
||||
)),
|
||||
collections,
|
||||
globals,
|
||||
},
|
||||
|
||||
@@ -17,6 +17,8 @@ export type IComponentMapContext = {
|
||||
}) => MappedField | undefined
|
||||
}
|
||||
|
||||
export { WithServerSideProps } from './buildComponentMap/WithServerSideProps.js'
|
||||
|
||||
const ComponentMapContext = createContext<IComponentMapContext>({} as IComponentMapContext)
|
||||
|
||||
export const ComponentMapProvider: React.FC<{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
const baseClass = 'admin-button'
|
||||
|
||||
export const AdminButton: React.FC = () => {
|
||||
export const AdminButton: SanitizedConfig['admin']['components']['actions'][0] = () => {
|
||||
return (
|
||||
<div
|
||||
className={baseClass}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'after-dashboard'
|
||||
|
||||
export const AfterDashboard: React.FC = () => {
|
||||
export const AfterDashboard: SanitizedConfig['admin']['components']['afterDashboard'][0] = () => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<h4>Test Config</h4>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
|
||||
import { useConfig } from '@payloadcms/ui/providers/Config'
|
||||
import LinkImport from 'next/link.js'
|
||||
const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
|
||||
@@ -8,7 +10,7 @@ import React from 'react'
|
||||
|
||||
const baseClass = 'after-nav-links'
|
||||
|
||||
export const AfterNavLinks: React.FC = () => {
|
||||
export const AfterNavLinks: SanitizedConfig['admin']['components']['afterNavLinks'][0] = () => {
|
||||
const {
|
||||
routes: { admin: adminRoute },
|
||||
} = useConfig()
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import type { SanitizedConfig } from 'payload/types'
|
||||
|
||||
import { useTranslation } from '@payloadcms/ui/providers/Translation'
|
||||
import React from 'react'
|
||||
|
||||
export const BeforeLogin: React.FC = () => {
|
||||
export const BeforeLogin: SanitizedConfig['admin']['components']['beforeLogin'][0] = () => {
|
||||
const translation = useTranslation()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>{translation.t('general:welcome')}</h3>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { CustomComponent } from 'payload/config'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
const baseClass = 'collection-api-button'
|
||||
|
||||
export const CollectionAPIButton: React.FC = () => {
|
||||
export const CollectionAPIButton: CustomComponent = () => {
|
||||
return (
|
||||
<div
|
||||
className={baseClass}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { CustomComponent } from 'payload/config'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
const baseClass = 'collection-edit-button'
|
||||
|
||||
export const CollectionEditButton: React.FC = () => {
|
||||
export const CollectionEditButton: CustomComponent = () => {
|
||||
return (
|
||||
<div
|
||||
className={baseClass}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { CustomComponent } from 'payload/config'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
const baseClass = 'collection-list-button'
|
||||
|
||||
export const CollectionListButton: React.FC = () => {
|
||||
export const CollectionListButton: CustomComponent = () => {
|
||||
return (
|
||||
<div
|
||||
className={baseClass}
|
||||
|
||||
@@ -161,4 +161,4 @@
|
||||
".next/types/**/*.ts",
|
||||
"scripts/**/*.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user