Merge branch 'alpha' of github.com:payloadcms/payload into alpha
This commit is contained in:
@@ -87,7 +87,7 @@ export const Account: React.FC<AdminViewProps> = async ({ initPageResult, search
|
||||
req,
|
||||
})
|
||||
|
||||
const serverSideProps: ServerSideEditViewProps = {
|
||||
const viewComponentProps: ServerSideEditViewProps = {
|
||||
initPageResult,
|
||||
routeSegments: [],
|
||||
searchParams,
|
||||
@@ -133,7 +133,7 @@ export const Account: React.FC<AdminViewProps> = async ({ initPageResult, search
|
||||
typeof CustomAccountComponent === 'function' ? CustomAccountComponent : undefined
|
||||
}
|
||||
DefaultComponent={EditView}
|
||||
componentProps={serverSideProps}
|
||||
componentProps={viewComponentProps}
|
||||
/>
|
||||
</FormQueryParamsProvider>
|
||||
</DocumentInfoProvider>
|
||||
|
||||
@@ -41,7 +41,7 @@ export const Dashboard: React.FC<AdminViewProps> = ({
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
const componentProps: DashboardProps = {
|
||||
const viewComponentProps: DashboardProps = {
|
||||
Link,
|
||||
config,
|
||||
permissions,
|
||||
@@ -57,7 +57,7 @@ export const Dashboard: React.FC<AdminViewProps> = ({
|
||||
typeof CustomDashboardComponent === 'function' ? CustomDashboardComponent : undefined
|
||||
}
|
||||
DefaultComponent={DefaultDashboard}
|
||||
componentProps={componentProps}
|
||||
componentProps={viewComponentProps}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
@@ -214,7 +214,7 @@ export const Document: React.FC<AdminViewProps> = async ({
|
||||
req,
|
||||
})
|
||||
|
||||
const serverSideProps: ServerSideEditViewProps = {
|
||||
const viewComponentProps: ServerSideEditViewProps = {
|
||||
initPageResult,
|
||||
routeSegments: segments,
|
||||
searchParams,
|
||||
@@ -263,7 +263,7 @@ export const Document: React.FC<AdminViewProps> = async ({
|
||||
<RenderCustomComponent
|
||||
CustomComponent={ViewOverride || CustomView}
|
||||
DefaultComponent={DefaultView}
|
||||
componentProps={serverSideProps}
|
||||
componentProps={viewComponentProps}
|
||||
/>
|
||||
</FormQueryParamsProvider>
|
||||
</EditDepthProvider>
|
||||
|
||||
@@ -85,7 +85,7 @@ export const ListView: React.FC<AdminViewProps> = async ({ initPageResult, searc
|
||||
user,
|
||||
})
|
||||
|
||||
const componentProps: DefaultListViewProps = {
|
||||
const viewComponentProps: DefaultListViewProps = {
|
||||
collectionSlug,
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export const ListView: React.FC<AdminViewProps> = async ({ initPageResult, searc
|
||||
<RenderCustomComponent
|
||||
CustomComponent={CustomListView}
|
||||
DefaultComponent={DefaultListView}
|
||||
componentProps={componentProps}
|
||||
componentProps={viewComponentProps}
|
||||
/>
|
||||
</TableColumnsProvider>
|
||||
</ListInfoProvider>
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import type { FieldMap, StepNavItem } from '@payloadcms/ui'
|
||||
import type {
|
||||
FieldAffectingData,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedGlobalConfig,
|
||||
} from 'payload/types'
|
||||
import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from 'payload/types'
|
||||
import type React from 'react'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
@@ -53,8 +49,8 @@ export const SetStepNav: React.FC<{
|
||||
const titleField = fieldMap.find((f) => {
|
||||
const { isFieldAffectingData } = f
|
||||
const fieldName = 'name' in f ? f.name : undefined
|
||||
return isFieldAffectingData && fieldName === useAsTitle
|
||||
}) as FieldAffectingData
|
||||
return Boolean(isFieldAffectingData && fieldName === useAsTitle)
|
||||
})
|
||||
|
||||
if (titleField && mostRecentDoc[useAsTitle]) {
|
||||
if (titleField.localized) {
|
||||
|
||||
@@ -28,10 +28,10 @@ const Iterable: React.FC<Props> = ({
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
{'label' in field && field.label && (
|
||||
{'label' in field.fieldComponentProps && field.fieldComponentProps.label && (
|
||||
<Label>
|
||||
{locale && <span className={`${baseClass}__locale-label`}>{locale}</span>}
|
||||
{getTranslation(field.label, i18n)}
|
||||
{getTranslation(field.fieldComponentProps.label, i18n)}
|
||||
</Label>
|
||||
)}
|
||||
{maxRows > 0 && (
|
||||
@@ -42,7 +42,8 @@ const Iterable: React.FC<Props> = ({
|
||||
|
||||
let fieldMap: MappedField[] = []
|
||||
|
||||
if (field.type === 'array' && 'fieldMap' in field) fieldMap = field.fieldMap
|
||||
if (field.type === 'array' && 'fieldMap' in field.fieldComponentProps)
|
||||
fieldMap = field.fieldComponentProps.fieldMap
|
||||
|
||||
if (field.type === 'blocks') {
|
||||
fieldMap = [
|
||||
@@ -54,20 +55,26 @@ const Iterable: React.FC<Props> = ({
|
||||
]
|
||||
|
||||
if (versionRow?.blockType === comparisonRow?.blockType) {
|
||||
const matchedBlock = ('blocks' in field &&
|
||||
field.blocks?.find((block) => block.slug === versionRow?.blockType)) || {
|
||||
const matchedBlock = ('blocks' in field.fieldComponentProps &&
|
||||
field.fieldComponentProps.blocks?.find(
|
||||
(block) => block.slug === versionRow?.blockType,
|
||||
)) || {
|
||||
fieldMap: [],
|
||||
}
|
||||
|
||||
fieldMap = [...fieldMap, ...matchedBlock.fieldMap]
|
||||
} else {
|
||||
const matchedVersionBlock = ('blocks' in field &&
|
||||
field.blocks?.find((block) => block.slug === versionRow?.blockType)) || {
|
||||
const matchedVersionBlock = ('blocks' in field.fieldComponentProps &&
|
||||
field.fieldComponentProps.blocks?.find(
|
||||
(block) => block.slug === versionRow?.blockType,
|
||||
)) || {
|
||||
fieldMap: [],
|
||||
}
|
||||
|
||||
const matchedComparisonBlock = ('blocks' in field &&
|
||||
field.blocks?.find((block) => block.slug === comparisonRow?.blockType)) || {
|
||||
const matchedComparisonBlock = ('blocks' in field.fieldComponentProps &&
|
||||
field.fieldComponentProps.blocks?.find(
|
||||
(block) => block.slug === comparisonRow?.blockType,
|
||||
)) || {
|
||||
fieldMap: [],
|
||||
}
|
||||
|
||||
@@ -102,8 +109,8 @@ const Iterable: React.FC<Props> = ({
|
||||
<div className={`${baseClass}__no-rows`}>
|
||||
{i18n.t('version:noRowsFound', {
|
||||
label:
|
||||
'labels' in field && field.labels?.plural
|
||||
? getTranslation(field.labels?.plural, i18n)
|
||||
'labels' in field.fieldComponentProps && field.fieldComponentProps.labels?.plural
|
||||
? getTranslation(field.fieldComponentProps.labels.plural, i18n)
|
||||
: i18n.t('general:rows'),
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -23,10 +23,10 @@ const Nested: React.FC<Props> = ({
|
||||
}) => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
{'label' in field && field.label && (
|
||||
{'label' in field.fieldComponentProps && field.fieldComponentProps.label && (
|
||||
<Label>
|
||||
{locale && <span className={`${baseClass}__locale-label`}>{locale}</span>}
|
||||
{getTranslation(field.label, i18n)}
|
||||
{getTranslation(field.fieldComponentProps.label, i18n)}
|
||||
</Label>
|
||||
)}
|
||||
<div
|
||||
|
||||
@@ -30,7 +30,8 @@ const generateLabelFromValue = (
|
||||
let relatedDoc: RelationshipValue
|
||||
let valueToReturn = '' as any
|
||||
|
||||
const relationTo = 'relationTo' in field ? field.relationTo : undefined
|
||||
const relationTo =
|
||||
'relationTo' in field.fieldComponentProps ? field.fieldComponentProps.relationTo : undefined
|
||||
|
||||
if (value === null || typeof value === 'undefined') {
|
||||
return String(value)
|
||||
@@ -96,7 +97,10 @@ const Relationship: React.FC<Props> = ({ comparison, field, i18n, locale, versio
|
||||
comparisonToRender = generateLabelFromValue(collections, field, locale, comparison)
|
||||
}
|
||||
|
||||
const label = 'label' in field && typeof field.label !== 'boolean' ? field?.label : ''
|
||||
const label =
|
||||
'label' in field.fieldComponentProps && typeof field.fieldComponentProps.label !== 'boolean'
|
||||
? field.fieldComponentProps.label
|
||||
: ''
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { I18n } from '@payloadcms/translations'
|
||||
import type { SelectFieldProps } from 'packages/ui/src/forms/fields/Select/types.js'
|
||||
import type { MappedFieldBase } from 'packages/ui/src/utilities/buildComponentMap/types.js'
|
||||
import type { MappedField } from 'packages/ui/src/utilities/buildComponentMap/types.js'
|
||||
import type { OptionObject, SelectField } from 'payload/types'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
@@ -48,7 +48,7 @@ const getTranslatedOptions = (
|
||||
|
||||
const Select: React.FC<
|
||||
Omit<Props, 'field'> & {
|
||||
field: MappedFieldBase & SelectFieldProps
|
||||
field: MappedField & SelectFieldProps
|
||||
}
|
||||
> = ({ comparison, diffMethod, field, i18n, locale, version }) => {
|
||||
let placeholder = ''
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TabsFieldProps } from 'packages/ui/src/forms/fields/Tabs/types.js'
|
||||
import type { MappedFieldBase } from 'packages/ui/src/utilities/buildComponentMap/types.js'
|
||||
import type { MappedField } from 'packages/ui/src/utilities/buildComponentMap/types.js'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
@@ -12,7 +12,7 @@ const baseClass = 'tabs-diff'
|
||||
|
||||
const Tabs: React.FC<
|
||||
Omit<Props, 'field'> & {
|
||||
field: MappedFieldBase & TabsFieldProps
|
||||
field: MappedField & TabsFieldProps
|
||||
}
|
||||
> = ({ comparison, diffComponents, field, i18n, locale, locales, permissions, version }) => {
|
||||
return (
|
||||
|
||||
@@ -35,7 +35,8 @@ const Text: React.FC<Props> = ({
|
||||
<div className={baseClass}>
|
||||
<Label>
|
||||
{locale && <span className={`${baseClass}__locale-label`}>{locale}</span>}
|
||||
{'label' in field && getTranslation(field?.label || '', i18n)}
|
||||
{'label' in field.fieldComponentProps &&
|
||||
getTranslation(field.fieldComponentProps.label || '', i18n)}
|
||||
</Label>
|
||||
<DiffViewer
|
||||
comparisonToRender={comparisonToRender}
|
||||
|
||||
@@ -32,19 +32,20 @@ const RenderFieldsToDiff: React.FC<Props> = ({
|
||||
|
||||
if (Component) {
|
||||
if (field.isFieldAffectingData && 'name' in field) {
|
||||
const fieldName = field.name
|
||||
const valueIsObject = field.type === 'code' || field.type === 'json'
|
||||
|
||||
const versionValue = valueIsObject
|
||||
? JSON.stringify(version?.[field.name])
|
||||
: version?.[field.name]
|
||||
? JSON.stringify(version?.[fieldName])
|
||||
: version?.[fieldName]
|
||||
|
||||
const comparisonValue = valueIsObject
|
||||
? JSON.stringify(comparison?.[field.name])
|
||||
: comparison?.[field.name]
|
||||
? JSON.stringify(comparison?.[fieldName])
|
||||
: comparison?.[fieldName]
|
||||
|
||||
const hasPermission = fieldPermissions?.[field.name]?.read?.permission
|
||||
const hasPermission = fieldPermissions?.[fieldName]?.read?.permission
|
||||
|
||||
const subFieldPermissions = fieldPermissions?.[field.name]?.fields
|
||||
const subFieldPermissions = fieldPermissions?.[fieldName]?.fields
|
||||
|
||||
if (hasPermission === false) return null
|
||||
|
||||
@@ -53,7 +54,10 @@ const RenderFieldsToDiff: React.FC<Props> = ({
|
||||
diffComponents,
|
||||
diffMethod,
|
||||
field,
|
||||
fieldMap: 'fieldMap' in field ? field.fieldMap : fieldMap,
|
||||
fieldMap:
|
||||
'fieldMap' in field.fieldComponentProps
|
||||
? field.fieldComponentProps?.fieldMap
|
||||
: fieldMap,
|
||||
fieldPermissions: subFieldPermissions,
|
||||
i18n,
|
||||
isRichText,
|
||||
@@ -93,7 +97,7 @@ const RenderFieldsToDiff: React.FC<Props> = ({
|
||||
)
|
||||
}
|
||||
|
||||
if (field.type === 'tabs' && 'fieldMap' in field) {
|
||||
if (field.type === 'tabs' && 'fieldMap' in field.fieldComponentProps) {
|
||||
const Tabs = diffComponents.tabs
|
||||
|
||||
return (
|
||||
@@ -101,7 +105,7 @@ const RenderFieldsToDiff: React.FC<Props> = ({
|
||||
comparison={comparison}
|
||||
diffComponents={diffComponents}
|
||||
field={field}
|
||||
fieldMap={field.fieldMap}
|
||||
fieldMap={field.fieldComponentProps.fieldMap}
|
||||
i18n={i18n}
|
||||
key={i}
|
||||
locales={locales}
|
||||
@@ -111,14 +115,14 @@ const RenderFieldsToDiff: React.FC<Props> = ({
|
||||
}
|
||||
|
||||
// At this point, we are dealing with a `row`, etc
|
||||
if ('fieldMap' in field) {
|
||||
if ('fieldMap' in field.fieldComponentProps) {
|
||||
return (
|
||||
<Nested
|
||||
comparison={comparison}
|
||||
diffComponents={diffComponents}
|
||||
disableGutter
|
||||
field={field}
|
||||
fieldMap={field.fieldMap}
|
||||
fieldMap={field.fieldComponentProps.fieldMap}
|
||||
i18n={i18n}
|
||||
key={i}
|
||||
locales={locales}
|
||||
|
||||
@@ -3,5 +3,5 @@ import type React from 'react'
|
||||
export type Props = {
|
||||
CustomComponent?: Promise<React.ComponentType<any>> | React.ComponentType<any>
|
||||
DefaultComponent: Promise<React.ComponentType<any>> | React.ComponentType<any>
|
||||
componentProps?: Record<string, unknown>
|
||||
fieldComponentProps?: Record<string, unknown>
|
||||
}
|
||||
|
||||
@@ -59,10 +59,12 @@ export const buildColumns = (args: {
|
||||
|
||||
const isFirstActiveColumn = activeColumnsIndices[0] === index
|
||||
|
||||
const name = 'name' in field ? field.name : undefined
|
||||
|
||||
if (field) {
|
||||
const column: Column = {
|
||||
name: 'name' in field ? field.name : undefined,
|
||||
accessor: 'name' in field ? field.name : undefined,
|
||||
name,
|
||||
accessor: name,
|
||||
active,
|
||||
cellProps: {
|
||||
...cellProps?.[index],
|
||||
@@ -72,7 +74,7 @@ export const buildColumns = (args: {
|
||||
Cell: field.Cell,
|
||||
Heading: field.Heading,
|
||||
},
|
||||
label: 'label' in field ? field.label : undefined,
|
||||
label: 'label' in field.fieldComponentProps ? field.fieldComponentProps.label : undefined,
|
||||
}
|
||||
|
||||
acc.push(column)
|
||||
|
||||
@@ -55,7 +55,7 @@ export { type TextAreaInputProps, TextareaInput } from '../forms/fields/Textarea
|
||||
export { default as Textarea } from '../forms/fields/Textarea/index.js'
|
||||
export { UploadInput, type UploadInputProps } from '../forms/fields/Upload/Input.js'
|
||||
export { default as UploadField } from '../forms/fields/Upload/index.js'
|
||||
export { fieldTypes } from '../forms/fields/index.js'
|
||||
export { fieldComponents } from '../forms/fields/index.js'
|
||||
export { fieldBaseClass } from '../forms/fields/shared.js'
|
||||
export { useField } from '../forms/useField/index.js'
|
||||
export type { FieldType, Options } from '../forms/useField/types.js'
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
'use client'
|
||||
|
||||
import type { FieldTypes } from 'payload/config.js'
|
||||
import type { FieldPermissions } from 'payload/types'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import type { FieldComponentProps, MappedField } from '../../utilities/buildComponentMap/types.js'
|
||||
|
||||
import { HiddenInput } from '../../index.js'
|
||||
import { useFieldComponents } from '../../providers/FieldComponentsProvider/index.js'
|
||||
import { useOperation } from '../../providers/OperationProvider/index.js'
|
||||
import { FieldPropsProvider, useFieldProps } from '../FieldPropsProvider/index.js'
|
||||
|
||||
type Props = {
|
||||
Field: React.ReactNode
|
||||
CustomField: MappedField['CustomField']
|
||||
disabled: boolean
|
||||
fieldComponentProps?: FieldComponentProps
|
||||
isHidden?: boolean
|
||||
name?: string
|
||||
path: string
|
||||
permissions?: FieldPermissions
|
||||
@@ -18,12 +25,16 @@ type Props = {
|
||||
siblingPermissions: {
|
||||
[fieldName: string]: FieldPermissions
|
||||
}
|
||||
type: keyof FieldTypes
|
||||
}
|
||||
|
||||
export const RenderField: React.FC<Props> = ({
|
||||
name,
|
||||
Field,
|
||||
type,
|
||||
CustomField,
|
||||
disabled,
|
||||
fieldComponentProps,
|
||||
isHidden,
|
||||
path: pathFromProps,
|
||||
permissions,
|
||||
readOnly: readOnlyFromProps,
|
||||
@@ -32,6 +43,7 @@ export const RenderField: React.FC<Props> = ({
|
||||
}) => {
|
||||
const operation = useOperation()
|
||||
const { readOnly: readOnlyFromContext } = useFieldProps()
|
||||
const fieldComponents = useFieldComponents()
|
||||
|
||||
const path = `${pathFromProps ? `${pathFromProps}.` : ''}${name ? `${name}` : ''}`
|
||||
const schemaPath = `${schemaPathFromProps ? `${schemaPathFromProps}` : ''}${name ? `.${name}` : ''}`
|
||||
@@ -53,6 +65,12 @@ export const RenderField: React.FC<Props> = ({
|
||||
readOnly = true
|
||||
}
|
||||
|
||||
const DefaultField = isHidden ? HiddenInput : fieldComponents[type]
|
||||
|
||||
if (!CustomField && !DefaultField) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<FieldPropsProvider
|
||||
path={path}
|
||||
@@ -61,7 +79,7 @@ export const RenderField: React.FC<Props> = ({
|
||||
schemaPath={schemaPath}
|
||||
siblingPermissions={siblingPermissions}
|
||||
>
|
||||
{Field}
|
||||
{CustomField || <DefaultField {...fieldComponentProps} />}
|
||||
</FieldPropsProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ export const RenderFields: React.FC<Props> = (props) => {
|
||||
}, [shouldRender, hasRendered])
|
||||
|
||||
if (!fieldMap || (Array.isArray(fieldMap) && fieldMap.length === 0)) {
|
||||
console.error('No fieldMap provided when calling RenderFields')
|
||||
console.error('No fieldMap provided when calling RenderFields') // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
if (!i18n) {
|
||||
console.error('Need to implement i18n when calling RenderFields')
|
||||
console.error('Need to implement i18n when calling RenderFields') // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
if (fieldMap) {
|
||||
@@ -54,14 +54,23 @@ export const RenderFields: React.FC<Props> = (props) => {
|
||||
>
|
||||
{hasRendered &&
|
||||
fieldMap?.map((f, fieldIndex) => {
|
||||
const { Field, disabled, readOnly } = f
|
||||
const {
|
||||
type,
|
||||
CustomField,
|
||||
disabled,
|
||||
fieldComponentProps,
|
||||
fieldComponentProps: { readOnly },
|
||||
isHidden,
|
||||
} = f
|
||||
|
||||
const name = 'name' in f ? f.name : undefined
|
||||
|
||||
return (
|
||||
<RenderField
|
||||
Field={Field}
|
||||
CustomField={CustomField}
|
||||
disabled={disabled}
|
||||
fieldComponentProps={fieldComponentProps}
|
||||
isHidden={isHidden}
|
||||
key={fieldIndex}
|
||||
name={name}
|
||||
path={path}
|
||||
@@ -69,6 +78,7 @@ export const RenderFields: React.FC<Props> = (props) => {
|
||||
readOnly={readOnly}
|
||||
schemaPath={schemaPath}
|
||||
siblingPermissions={permissions}
|
||||
type={type}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -2,18 +2,20 @@ import type { FieldMap } from '../../utilities/buildComponentMap/types.js'
|
||||
|
||||
export const buildPathSegments = (parentPath: string, fieldMap: FieldMap): string[] => {
|
||||
const pathNames = fieldMap.reduce((acc, subField) => {
|
||||
if ('fieldMap' in subField) {
|
||||
if (subField.fieldMap && subField.isFieldAffectingData) {
|
||||
if ('fieldMap' in subField.fieldComponentProps) {
|
||||
const fieldMap = subField.fieldComponentProps.fieldMap
|
||||
|
||||
if (fieldMap && subField.isFieldAffectingData) {
|
||||
// group, block, array
|
||||
const name = 'name' in subField ? subField.name : 'unnamed'
|
||||
acc.push(parentPath ? `${parentPath}.${name}.` : `${name}.`)
|
||||
} else if (subField.fieldMap) {
|
||||
} else if (fieldMap) {
|
||||
// rows, collapsibles, unnamed-tab
|
||||
acc.push(...buildPathSegments(parentPath, subField.fieldMap))
|
||||
acc.push(...buildPathSegments(parentPath, fieldMap))
|
||||
} else if (subField.type === 'tabs') {
|
||||
// tabs
|
||||
'tabs' in subField &&
|
||||
subField.tabs?.forEach((tab) => {
|
||||
'tabs' in subField.fieldComponentProps &&
|
||||
subField.fieldComponentProps?.tabs?.forEach((tab) => {
|
||||
let tabPath = parentPath
|
||||
if ('name' in tab) {
|
||||
tabPath = parentPath ? `${parentPath}.${tab.name}` : tab.name
|
||||
|
||||
@@ -27,7 +27,9 @@ const Code: React.FC<CodeFieldProps> = (props) => {
|
||||
Error,
|
||||
Label: LabelFromProps,
|
||||
className,
|
||||
editorOptions = {},
|
||||
label,
|
||||
language = 'javascript',
|
||||
path: pathFromProps,
|
||||
readOnly,
|
||||
required,
|
||||
@@ -38,9 +40,6 @@ const Code: React.FC<CodeFieldProps> = (props) => {
|
||||
|
||||
const Label = LabelFromProps || <LabelComp label={label} required={required} />
|
||||
|
||||
const editorOptions = 'editorOptions' in props ? props.editorOptions : {}
|
||||
const language = 'language' in props ? props.language : 'javascript'
|
||||
|
||||
const memoizedValidate = useCallback(
|
||||
(value, options) => {
|
||||
if (typeof validate === 'function') {
|
||||
|
||||
@@ -27,6 +27,7 @@ const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
|
||||
Label: LabelFromProps,
|
||||
className,
|
||||
fieldMap,
|
||||
initCollapsed = false,
|
||||
label,
|
||||
path: pathFromProps,
|
||||
required,
|
||||
@@ -38,7 +39,6 @@ const CollapsibleField: React.FC<CollapsibleFieldProps> = (props) => {
|
||||
const path = pathFromProps || pathFromContext
|
||||
|
||||
const { i18n } = useTranslation()
|
||||
const initCollapsed = 'initCollapsed' in props ? props.initCollapsed : false
|
||||
const { getPreference, setPreference } = usePreferences()
|
||||
const { preferencesKey } = useDocumentInfo()
|
||||
const [collapsedOnMount, setCollapsedOnMount] = useState<boolean>()
|
||||
|
||||
@@ -44,6 +44,11 @@ const Relationship: React.FC<RelationshipFieldProps> = (props) => {
|
||||
style,
|
||||
validate,
|
||||
width,
|
||||
relationTo,
|
||||
hasMany,
|
||||
sortOptions,
|
||||
isSortable = true,
|
||||
allowCreate = true,
|
||||
} = props
|
||||
|
||||
const config = useConfig()
|
||||
@@ -54,12 +59,6 @@ const Relationship: React.FC<RelationshipFieldProps> = (props) => {
|
||||
serverURL,
|
||||
} = config
|
||||
|
||||
const relationTo = 'relationTo' in props ? props?.relationTo : undefined
|
||||
const hasMany = 'hasMany' in props ? props?.hasMany : undefined
|
||||
const sortOptions = 'sortOptions' in props ? props?.sortOptions : undefined
|
||||
const isSortable = 'isSortable' in props ? props?.isSortable : true
|
||||
const allowCreate = 'allowCreate' in props ? props?.allowCreate : true
|
||||
|
||||
const { i18n, t } = useTranslation()
|
||||
const { permissions } = useAuth()
|
||||
const { code: locale } = useLocale()
|
||||
|
||||
@@ -44,15 +44,14 @@ export const Select: React.FC<SelectFieldProps> = (props) => {
|
||||
style,
|
||||
validate,
|
||||
width,
|
||||
options: optionsFromProps = [],
|
||||
hasMany = false,
|
||||
isClearable = true,
|
||||
isSortable = true,
|
||||
} = props
|
||||
|
||||
const Label = LabelFromProps || <LabelComp label={label} required={required} />
|
||||
|
||||
const optionsFromProps = 'options' in props ? props.options : []
|
||||
const hasMany = 'hasMany' in props ? props.hasMany : false
|
||||
const isClearable = 'isClearable' in props ? props.isClearable : true
|
||||
const isSortable = 'isSortable' in props ? props.isSortable : true
|
||||
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
const [options] = useState(formatOptions(optionsFromProps))
|
||||
|
||||
@@ -37,12 +37,11 @@ const Textarea: React.FC<TextareaFieldProps> = (props) => {
|
||||
style,
|
||||
validate,
|
||||
width,
|
||||
rows,
|
||||
} = props
|
||||
|
||||
const Label = LabelFromProps || <LabelComp label={label} required={required} />
|
||||
|
||||
const rows = 'rows' in props ? props.rows : undefined
|
||||
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
const { localization } = useConfig()
|
||||
|
||||
@@ -25,7 +25,7 @@ import textarea from './Textarea/index.js'
|
||||
import ui from './UI/index.js'
|
||||
import upload from './Upload/index.js'
|
||||
|
||||
export const fieldTypes: FieldTypes = {
|
||||
export const fieldComponents: FieldTypes = {
|
||||
array,
|
||||
blocks,
|
||||
checkbox,
|
||||
|
||||
21
packages/ui/src/providers/FieldComponentsProvider/index.tsx
Normal file
21
packages/ui/src/providers/FieldComponentsProvider/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
'use client'
|
||||
import React, { createContext, useContext } from 'react'
|
||||
|
||||
import { fieldComponents } from '../../forms/fields/index.js'
|
||||
import { FieldTypes } from 'payload/config.js'
|
||||
|
||||
export type IFieldComponentsContext = FieldTypes
|
||||
|
||||
const FieldComponentsContext = createContext<IFieldComponentsContext>(fieldComponents)
|
||||
|
||||
export const FieldComponentsProvider: React.FC<{
|
||||
children: React.ReactNode
|
||||
}> = ({ children }) => {
|
||||
return (
|
||||
<FieldComponentsContext.Provider value={fieldComponents}>
|
||||
{children}
|
||||
</FieldComponentsContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useFieldComponents = (): IFieldComponentsContext => useContext(FieldComponentsContext)
|
||||
@@ -27,6 +27,7 @@ import { RouteCache } from '../RouteCache/index.js'
|
||||
import { SearchParamsProvider } from '../SearchParams/index.js'
|
||||
import { ThemeProvider } from '../Theme/index.js'
|
||||
import { TranslationProvider } from '../Translation/index.js'
|
||||
import { FieldComponentsProvider } from '../FieldComponentsProvider/index.js'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
@@ -59,50 +60,52 @@ export const RootProvider: React.FC<Props> = ({
|
||||
<RouteCache>
|
||||
<ConfigProvider config={config}>
|
||||
<ComponentMapProvider componentMap={componentMap}>
|
||||
<ClientFunctionProvider>
|
||||
<TranslationProvider
|
||||
fallbackLang={fallbackLang}
|
||||
lang={lang}
|
||||
languageOptions={languageOptions}
|
||||
translations={translations}
|
||||
>
|
||||
<WindowInfoProvider
|
||||
breakpoints={{
|
||||
l: '(max-width: 1440px)',
|
||||
m: '(max-width: 1024px)',
|
||||
s: '(max-width: 768px)',
|
||||
xs: '(max-width: 400px)',
|
||||
}}
|
||||
<FieldComponentsProvider>
|
||||
<ClientFunctionProvider>
|
||||
<TranslationProvider
|
||||
fallbackLang={fallbackLang}
|
||||
lang={lang}
|
||||
languageOptions={languageOptions}
|
||||
translations={translations}
|
||||
>
|
||||
<ScrollInfoProvider>
|
||||
<SearchParamsProvider>
|
||||
<ModalProvider classPrefix="payload" transTime={0} zIndex="var(--z-modal)">
|
||||
<AuthProvider>
|
||||
<PreferencesProvider>
|
||||
<ThemeProvider>
|
||||
<ParamsProvider>
|
||||
<LocaleProvider>
|
||||
<StepNavProvider>
|
||||
<LoadingOverlayProvider>
|
||||
<DocumentEventsProvider>
|
||||
<ActionsProvider>
|
||||
<NavProvider>{children}</NavProvider>
|
||||
</ActionsProvider>
|
||||
</DocumentEventsProvider>
|
||||
</LoadingOverlayProvider>
|
||||
</StepNavProvider>
|
||||
</LocaleProvider>
|
||||
</ParamsProvider>
|
||||
</ThemeProvider>
|
||||
</PreferencesProvider>
|
||||
<ModalContainer />
|
||||
</AuthProvider>
|
||||
</ModalProvider>
|
||||
</SearchParamsProvider>
|
||||
</ScrollInfoProvider>
|
||||
</WindowInfoProvider>
|
||||
</TranslationProvider>
|
||||
</ClientFunctionProvider>
|
||||
<WindowInfoProvider
|
||||
breakpoints={{
|
||||
l: '(max-width: 1440px)',
|
||||
m: '(max-width: 1024px)',
|
||||
s: '(max-width: 768px)',
|
||||
xs: '(max-width: 400px)',
|
||||
}}
|
||||
>
|
||||
<ScrollInfoProvider>
|
||||
<SearchParamsProvider>
|
||||
<ModalProvider classPrefix="payload" transTime={0} zIndex="var(--z-modal)">
|
||||
<AuthProvider>
|
||||
<PreferencesProvider>
|
||||
<ThemeProvider>
|
||||
<ParamsProvider>
|
||||
<LocaleProvider>
|
||||
<StepNavProvider>
|
||||
<LoadingOverlayProvider>
|
||||
<DocumentEventsProvider>
|
||||
<ActionsProvider>
|
||||
<NavProvider>{children}</NavProvider>
|
||||
</ActionsProvider>
|
||||
</DocumentEventsProvider>
|
||||
</LoadingOverlayProvider>
|
||||
</StepNavProvider>
|
||||
</LocaleProvider>
|
||||
</ParamsProvider>
|
||||
</ThemeProvider>
|
||||
</PreferencesProvider>
|
||||
<ModalContainer />
|
||||
</AuthProvider>
|
||||
</ModalProvider>
|
||||
</SearchParamsProvider>
|
||||
</ScrollInfoProvider>
|
||||
</WindowInfoProvider>
|
||||
</TranslationProvider>
|
||||
</ClientFunctionProvider>
|
||||
</FieldComponentsProvider>
|
||||
</ComponentMapProvider>
|
||||
</ConfigProvider>
|
||||
</RouteCache>
|
||||
|
||||
@@ -37,8 +37,7 @@ import { SortColumn } from '../../elements/SortColumn/index.js'
|
||||
import DefaultError from '../../forms/Error/index.js'
|
||||
import DefaultDescription from '../../forms/FieldDescription/index.js'
|
||||
import DefaultLabel from '../../forms/Label/index.js'
|
||||
import HiddenInput from '../../forms/fields/HiddenInput/index.js'
|
||||
import { fieldTypes } from '../../forms/fields/index.js'
|
||||
import { HiddenInput } from '../../index.js'
|
||||
|
||||
export const mapFields = (args: {
|
||||
DefaultCell?: React.FC<any>
|
||||
@@ -64,13 +63,17 @@ export const mapFields = (args: {
|
||||
|
||||
const result: FieldMap = fieldSchema.reduce((acc, field): FieldMap => {
|
||||
const fieldIsPresentational = fieldIsPresentationalOnly(field)
|
||||
let FieldComponent = field.admin?.components?.Field || fieldTypes[field.type]
|
||||
let CellComponent = field.admin?.components?.Cell
|
||||
let CustomFieldComponent: React.ComponentType<FieldComponentProps>
|
||||
const CustomCellComponent = field.admin?.components?.Cell
|
||||
|
||||
const isHidden = field?.admin && 'hidden' in field.admin && field.admin.hidden
|
||||
|
||||
if (fieldIsPresentational || (!field?.hidden && field?.admin?.disabled !== true)) {
|
||||
if ((filter && typeof filter === 'function' && filter(field)) || !filter) {
|
||||
if (field.admin && 'hidden' in field.admin && field?.admin?.hidden) {
|
||||
FieldComponent = fieldTypes.hidden
|
||||
if (isHidden) {
|
||||
if (CustomFieldComponent) {
|
||||
CustomFieldComponent = HiddenInput
|
||||
}
|
||||
}
|
||||
|
||||
const isFieldAffectingData = fieldAffectsData(field)
|
||||
@@ -480,11 +483,11 @@ export const mapFields = (args: {
|
||||
}
|
||||
|
||||
if (RichTextFieldComponent) {
|
||||
FieldComponent = RichTextFieldComponent
|
||||
CustomFieldComponent = RichTextFieldComponent
|
||||
}
|
||||
|
||||
if (RichTextCellComponent) {
|
||||
CellComponent = RichTextCellComponent
|
||||
cellComponentProps.CellComponentOverride = <RichTextCellComponent />
|
||||
}
|
||||
|
||||
break
|
||||
@@ -622,11 +625,9 @@ export const mapFields = (args: {
|
||||
}
|
||||
}
|
||||
|
||||
const Field = <FieldComponent {...fieldComponentProps} />
|
||||
|
||||
const Cell = (
|
||||
<RenderCustomComponent
|
||||
CustomComponent={CellComponent}
|
||||
CustomComponent={CustomCellComponent}
|
||||
DefaultComponent={DefaultCell}
|
||||
componentProps={cellComponentProps}
|
||||
/>
|
||||
@@ -651,21 +652,23 @@ export const mapFields = (args: {
|
||||
)
|
||||
|
||||
const reducedField: MappedField = {
|
||||
...fieldComponentProps,
|
||||
name: 'name' in field ? field.name : undefined,
|
||||
type: field.type,
|
||||
Cell,
|
||||
Field,
|
||||
CustomField: CustomFieldComponent ? (
|
||||
<CustomFieldComponent {...fieldComponentProps} />
|
||||
) : null,
|
||||
Heading,
|
||||
fieldComponentProps,
|
||||
fieldIsPresentational,
|
||||
isFieldAffectingData,
|
||||
isHidden,
|
||||
isSidebar:
|
||||
'admin' in field && 'position' in field.admin && field.admin.position === 'sidebar',
|
||||
localized: 'localized' in field ? field.localized : false,
|
||||
}
|
||||
|
||||
if (FieldComponent) {
|
||||
acc.push(reducedField)
|
||||
}
|
||||
acc.push(reducedField)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,14 +680,16 @@ export const mapFields = (args: {
|
||||
|
||||
if (!disableAddingID && !hasID) {
|
||||
result.push({
|
||||
name: 'id',
|
||||
type: 'text',
|
||||
Cell: DefaultCell ? <DefaultCell name="id" /> : null,
|
||||
Field: <HiddenInput name="id" />,
|
||||
Heading: <SortColumn label="ID" name="id" />,
|
||||
fieldComponentProps: {
|
||||
name: 'id',
|
||||
label: 'ID',
|
||||
},
|
||||
fieldIsPresentational: false,
|
||||
isFieldAffectingData: true,
|
||||
// label: 'ID',
|
||||
isHidden: true,
|
||||
localized: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import type { FieldTypes } from 'payload/config.js'
|
||||
import type {
|
||||
BlockField,
|
||||
FieldBase,
|
||||
Labels,
|
||||
Option,
|
||||
RelationshipField,
|
||||
RichTextField,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedGlobalConfig,
|
||||
TabsField,
|
||||
@@ -28,7 +24,6 @@ import type { TabsFieldProps } from '../../forms/fields/Tabs/types.js'
|
||||
import type { TextFieldProps } from '../../forms/fields/Text/types.js'
|
||||
import type { TextareaFieldProps } from '../../forms/fields/Textarea/types.js'
|
||||
import type { UploadFieldProps } from '../../forms/fields/Upload/types.js'
|
||||
import type { fieldTypes } from '../../forms/fields/index.js'
|
||||
|
||||
export type MappedTab = {
|
||||
fieldMap?: FieldMap
|
||||
@@ -64,20 +59,21 @@ export type FieldComponentProps =
|
||||
| TextareaFieldProps
|
||||
| UploadFieldProps
|
||||
|
||||
export type MappedFieldBase = {
|
||||
export type MappedField = {
|
||||
Cell: React.ReactNode
|
||||
Field: React.ReactNode
|
||||
CustomField?: React.ReactNode
|
||||
Heading: React.ReactNode
|
||||
disabled?: boolean
|
||||
fieldComponentProps: FieldComponentProps
|
||||
fieldIsPresentational: boolean
|
||||
isFieldAffectingData: boolean
|
||||
isHidden?: boolean
|
||||
isSidebar?: boolean
|
||||
localized: boolean
|
||||
type: keyof typeof fieldTypes
|
||||
name?: string
|
||||
type: keyof FieldTypes
|
||||
}
|
||||
|
||||
export type MappedField = FieldComponentProps & MappedFieldBase
|
||||
|
||||
export type FieldMap = MappedField[]
|
||||
|
||||
export type ActionMap = {
|
||||
|
||||
@@ -18,24 +18,24 @@ export const PostsCollection: CollectionConfig = {
|
||||
type: 'row',
|
||||
fields: [],
|
||||
},
|
||||
// {
|
||||
// name: 'richText',
|
||||
// type: 'richText',
|
||||
// },
|
||||
{
|
||||
name: 'richText',
|
||||
type: 'richText',
|
||||
},
|
||||
{
|
||||
name: 'relationship',
|
||||
type: 'relationship',
|
||||
filterOptions: ({ id }) => {
|
||||
return {
|
||||
where: [
|
||||
{
|
||||
id: {
|
||||
not_equals: id,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
// filterOptions: ({ id }) => {
|
||||
// return {
|
||||
// where: [
|
||||
// {
|
||||
// id: {
|
||||
// not_equals: id,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
// },
|
||||
relationTo: ['posts'],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -171,4 +171,4 @@
|
||||
"app/**/*.tsx",
|
||||
"scripts/**/*.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user