Fixes issues where access control was not properly affecting the read-only setting on fields.
128 lines
4.1 KiB
TypeScript
128 lines
4.1 KiB
TypeScript
'use client'
|
|
|
|
import { getTranslation } from '@payloadcms/translations'
|
|
import React, { Fragment } from 'react'
|
|
|
|
import type { FieldMap } from '../../providers/ComponentMap/buildComponentMap/types.js'
|
|
import type { FormFieldBase } from '../shared/index.js'
|
|
|
|
import { useCollapsible } from '../../elements/Collapsible/provider.js'
|
|
import { ErrorPill } from '../../elements/ErrorPill/index.js'
|
|
import { useFieldProps } from '../../forms/FieldPropsProvider/index.js'
|
|
import {
|
|
useFormInitializing,
|
|
useFormProcessing,
|
|
useFormSubmitted,
|
|
} from '../../forms/Form/context.js'
|
|
import { RenderFields } from '../../forms/RenderFields/index.js'
|
|
import { useField } from '../../forms/useField/index.js'
|
|
import { withCondition } from '../../forms/withCondition/index.js'
|
|
import { useTranslation } from '../../providers/Translation/index.js'
|
|
import { FieldDescription } from '../FieldDescription/index.js'
|
|
import { useRow } from '../Row/provider.js'
|
|
import { useTabs } from '../Tabs/provider.js'
|
|
import { fieldBaseClass } from '../shared/index.js'
|
|
import './index.scss'
|
|
import { GroupProvider, useGroup } from './provider.js'
|
|
|
|
const baseClass = 'group-field'
|
|
|
|
export type GroupFieldProps = FormFieldBase & {
|
|
fieldMap: FieldMap
|
|
forceRender?: boolean
|
|
hideGutter?: boolean
|
|
name?: string
|
|
width?: string
|
|
}
|
|
|
|
const GroupField: React.FC<GroupFieldProps> = (props) => {
|
|
const {
|
|
CustomDescription,
|
|
CustomLabel,
|
|
className,
|
|
descriptionProps,
|
|
fieldMap,
|
|
hideGutter,
|
|
label,
|
|
readOnly: readOnlyFromProps,
|
|
style,
|
|
width,
|
|
} = props
|
|
|
|
const { path, permissions, readOnly: readOnlyFromContext, schemaPath } = useFieldProps()
|
|
const { i18n } = useTranslation()
|
|
const { isWithinCollapsible } = useCollapsible()
|
|
const isWithinGroup = useGroup()
|
|
const isWithinRow = useRow()
|
|
const isWithinTab = useTabs()
|
|
const { errorPaths } = useField({ path })
|
|
const formInitializing = useFormInitializing()
|
|
const formProcessing = useFormProcessing()
|
|
const submitted = useFormSubmitted()
|
|
const errorCount = errorPaths.length
|
|
const fieldHasErrors = submitted && errorCount > 0
|
|
const disabled = readOnlyFromProps || readOnlyFromContext || formProcessing || formInitializing
|
|
|
|
const isTopLevel = !(isWithinCollapsible || isWithinGroup || isWithinRow)
|
|
|
|
return (
|
|
<Fragment>
|
|
<div
|
|
className={[
|
|
fieldBaseClass,
|
|
baseClass,
|
|
isTopLevel && `${baseClass}--top-level`,
|
|
isWithinCollapsible && `${baseClass}--within-collapsible`,
|
|
isWithinGroup && `${baseClass}--within-group`,
|
|
isWithinRow && `${baseClass}--within-row`,
|
|
isWithinTab && `${baseClass}--within-tab`,
|
|
!hideGutter && isWithinGroup && `${baseClass}--gutter`,
|
|
fieldHasErrors && `${baseClass}--has-error`,
|
|
className,
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
id={`field-${path?.replace(/\./g, '__')}`}
|
|
style={{
|
|
...style,
|
|
width,
|
|
}}
|
|
>
|
|
<GroupProvider>
|
|
<div className={`${baseClass}__wrap`}>
|
|
<div className={`${baseClass}__header`}>
|
|
{(CustomLabel || CustomDescription || label) && (
|
|
<header>
|
|
{CustomLabel !== undefined ? (
|
|
CustomLabel
|
|
) : label ? (
|
|
<h3 className={`${baseClass}__title`}>{getTranslation(label, i18n)}</h3>
|
|
) : null}
|
|
{CustomDescription !== undefined ? (
|
|
CustomDescription
|
|
) : (
|
|
<FieldDescription {...(descriptionProps || {})} />
|
|
)}
|
|
</header>
|
|
)}
|
|
{fieldHasErrors && <ErrorPill count={errorCount} i18n={i18n} withMessage />}
|
|
</div>
|
|
<RenderFields
|
|
fieldMap={fieldMap}
|
|
margins="small"
|
|
path={path}
|
|
permissions={permissions?.fields}
|
|
readOnly={disabled}
|
|
schemaPath={schemaPath}
|
|
/>
|
|
</div>
|
|
</GroupProvider>
|
|
</div>
|
|
</Fragment>
|
|
)
|
|
}
|
|
|
|
export { GroupProvider, useGroup }
|
|
|
|
export const Group = withCondition(GroupField)
|