diff --git a/docs/fields/overview.mdx b/docs/fields/overview.mdx index be4ffe223..6d5a05ea4 100644 --- a/docs/fields/overview.mdx +++ b/docs/fields/overview.mdx @@ -95,7 +95,8 @@ Here are the available Presentational Fields: - [Collapsible](../fields/collapsible) - nests fields within a collapsible component - [Row](../fields/row) - aligns fields horizontally -- [Tabs (Unnamed)](../fields/tabs) - nests fields within a tabbed layout +- [Tabs (Unnamed)](../fields/tabs) - nests fields within a tabbed layout. It is not presentational if the tab has a name. +- [Group (Unnamed)](../fields/group) - nests fields within a keyed object It is not presentational if the group has a name. - [UI](../fields/ui) - blank field for custom UI components ### Virtual Fields diff --git a/packages/payload/src/fields/config/types.ts b/packages/payload/src/fields/config/types.ts index 14f1fc7fa..bece73a76 100644 --- a/packages/payload/src/fields/config/types.ts +++ b/packages/payload/src/fields/config/types.ts @@ -753,7 +753,7 @@ export type NamedGroupField = { export type UnnamedGroupField = { interfaceName?: never localized?: never -} & Omit +} & Omit export type GroupField = NamedGroupField | UnnamedGroupField @@ -777,7 +777,7 @@ export type RowField = { admin?: Omit fields: Field[] type: 'row' -} & Omit +} & Omit export type RowFieldClient = { admin?: Omit @@ -816,7 +816,7 @@ export type CollapsibleField = { label: Required } ) & - Omit + Omit export type CollapsibleFieldClient = { admin?: { @@ -863,7 +863,7 @@ export type UnnamedTab = { | LabelFunction | string localized?: never -} & Omit +} & Omit export type Tab = NamedTab | UnnamedTab export type TabsField = { diff --git a/packages/payload/src/fields/hooks/afterChange/promise.ts b/packages/payload/src/fields/hooks/afterChange/promise.ts index ecbc93087..5f256f042 100644 --- a/packages/payload/src/fields/hooks/afterChange/promise.ts +++ b/packages/payload/src/fields/hooks/afterChange/promise.ts @@ -73,7 +73,7 @@ export const promise = async ({ if (fieldAffectsData(field)) { // Execute hooks - if (field.hooks?.afterChange) { + if ('hooks' in field && field.hooks?.afterChange) { for (const hook of field.hooks.afterChange) { const hookedValue = await hook({ blockData, @@ -88,16 +88,16 @@ export const promise = async ({ path: pathSegments, previousDoc, previousSiblingDoc, - previousValue: previousDoc?.[field.name!], + previousValue: previousDoc?.[field.name], req, schemaPath: schemaPathSegments, siblingData, siblingFields: siblingFields!, - value: siblingDoc?.[field.name!], + value: siblingDoc?.[field.name], }) if (hookedValue !== undefined) { - siblingDoc[field.name!] = hookedValue + siblingDoc[field.name] = hookedValue } } } diff --git a/packages/payload/src/fields/hooks/afterRead/promise.ts b/packages/payload/src/fields/hooks/afterRead/promise.ts index bad55561c..04957f233 100644 --- a/packages/payload/src/fields/hooks/afterRead/promise.ts +++ b/packages/payload/src/fields/hooks/afterRead/promise.ts @@ -238,15 +238,15 @@ export const promise = async ({ if (fieldAffectsDataResult) { // Execute hooks - if (triggerHooks && field.hooks?.afterRead) { + if (triggerHooks && 'hooks' in field && field.hooks?.afterRead) { for (const hook of field.hooks.afterRead) { const shouldRunHookOnAllLocales = fieldShouldBeLocalized({ field, parentIsLocalized: parentIsLocalized! }) && (locale === 'all' || !flattenLocales) && - typeof siblingDoc[field.name!] === 'object' + typeof siblingDoc[field.name] === 'object' if (shouldRunHookOnAllLocales) { - const localesAndValues = Object.entries(siblingDoc[field.name!]) + const localesAndValues = Object.entries(siblingDoc[field.name]) await Promise.all( localesAndValues.map(async ([localeKey, value]) => { const hookedValue = await hook({ @@ -274,7 +274,7 @@ export const promise = async ({ }) if (hookedValue !== undefined) { - siblingDoc[field.name!][localeKey] = hookedValue + siblingDoc[field.name][localeKey] = hookedValue } }), ) @@ -300,11 +300,11 @@ export const promise = async ({ showHiddenFields, siblingData: siblingDoc, siblingFields: siblingFields!, - value: siblingDoc[field.name!], + value: siblingDoc[field.name], }) if (hookedValue !== undefined) { - siblingDoc[field.name!] = hookedValue + siblingDoc[field.name] = hookedValue } } } diff --git a/packages/payload/src/fields/hooks/beforeChange/promise.ts b/packages/payload/src/fields/hooks/beforeChange/promise.ts index 1441d1b37..027cddf1c 100644 --- a/packages/payload/src/fields/hooks/beforeChange/promise.ts +++ b/packages/payload/src/fields/hooks/beforeChange/promise.ts @@ -129,7 +129,7 @@ export const promise = async ({ } // Execute hooks - if (field.hooks?.beforeChange) { + if ('hooks' in field && field.hooks?.beforeChange) { for (const hook of field.hooks.beforeChange) { const hookedValue = await hook({ blockData, @@ -143,17 +143,17 @@ export const promise = async ({ originalDoc: doc, path: pathSegments, previousSiblingDoc: siblingDoc, - previousValue: siblingDoc[field.name!], + previousValue: siblingDoc[field.name], req, schemaPath: schemaPathSegments, siblingData, siblingDocWithLocales, siblingFields: siblingFields!, - value: siblingData[field.name!], + value: siblingData[field.name], }) if (hookedValue !== undefined) { - siblingData[field.name!] = hookedValue + siblingData[field.name] = hookedValue } } } diff --git a/packages/payload/src/fields/hooks/beforeDuplicate/promise.ts b/packages/payload/src/fields/hooks/beforeDuplicate/promise.ts index 337f2f82a..2e8cfb469 100644 --- a/packages/payload/src/fields/hooks/beforeDuplicate/promise.ts +++ b/packages/payload/src/fields/hooks/beforeDuplicate/promise.ts @@ -65,7 +65,7 @@ export const promise = async ({ // Run field beforeDuplicate hooks. // These hooks are responsible for resetting the `id` field values of array and block rows. See `baseIDField`. - if (Array.isArray(field.hooks?.beforeDuplicate)) { + if (Array.isArray('hooks' in field && field.hooks?.beforeDuplicate)) { if (fieldIsLocalized) { const localeData: JsonObject = {} @@ -90,8 +90,10 @@ export const promise = async ({ } let hookResult - for (const hook of field.hooks.beforeDuplicate) { - hookResult = await hook(beforeDuplicateArgs) + if ('hooks' in field && field.hooks?.beforeDuplicate) { + for (const hook of field.hooks.beforeDuplicate) { + hookResult = await hook(beforeDuplicateArgs) + } } if (typeof hookResult !== 'undefined') { @@ -121,8 +123,10 @@ export const promise = async ({ } let hookResult - for (const hook of field.hooks.beforeDuplicate) { - hookResult = await hook(beforeDuplicateArgs) + if ('hooks' in field && field.hooks?.beforeDuplicate) { + for (const hook of field.hooks.beforeDuplicate) { + hookResult = await hook(beforeDuplicateArgs) + } } if (typeof hookResult !== 'undefined') { diff --git a/packages/payload/src/fields/hooks/beforeValidate/promise.ts b/packages/payload/src/fields/hooks/beforeValidate/promise.ts index 5ef47e008..a433273ab 100644 --- a/packages/payload/src/fields/hooks/beforeValidate/promise.ts +++ b/packages/payload/src/fields/hooks/beforeValidate/promise.ts @@ -284,7 +284,7 @@ export const promise = async ({ } // Execute hooks - if (field.hooks?.beforeValidate) { + if ('hooks' in field && field.hooks?.beforeValidate) { for (const hook of field.hooks.beforeValidate) { const hookedValue = await hook({ blockData, @@ -299,19 +299,19 @@ export const promise = async ({ overrideAccess, path: pathSegments, previousSiblingDoc: siblingDoc, - previousValue: siblingDoc[field.name!], + previousValue: siblingDoc[field.name], req, schemaPath: schemaPathSegments, siblingData, siblingFields: siblingFields!, value: - typeof siblingData[field.name!] === 'undefined' + typeof siblingData[field.name] === 'undefined' ? fallbackResult.value - : siblingData[field.name!], + : siblingData[field.name], }) if (hookedValue !== undefined) { - siblingData[field.name!] = hookedValue + siblingData[field.name] = hookedValue } } } diff --git a/packages/payload/src/fields/setDefaultBeforeDuplicate.ts b/packages/payload/src/fields/setDefaultBeforeDuplicate.ts index 449035412..feab7812c 100644 --- a/packages/payload/src/fields/setDefaultBeforeDuplicate.ts +++ b/packages/payload/src/fields/setDefaultBeforeDuplicate.ts @@ -13,6 +13,7 @@ export const setDefaultBeforeDuplicate = ( ) => { if ( (('required' in field && field.required) || field.unique) && + 'hooks' in field && (!field.hooks?.beforeDuplicate || (Array.isArray(field.hooks.beforeDuplicate) && field.hooks.beforeDuplicate.length === 0)) ) { diff --git a/packages/plugin-cloud-storage/src/fields/getFields.ts b/packages/plugin-cloud-storage/src/fields/getFields.ts index acfe138ed..8ca75323c 100644 --- a/packages/plugin-cloud-storage/src/fields/getFields.ts +++ b/packages/plugin-cloud-storage/src/fields/getFields.ts @@ -119,7 +119,10 @@ export const getFields = ({ generateFileURL, size, }), - ...(existingSizeURLField?.hooks?.afterRead || []), + ...((typeof existingSizeURLField === 'object' && + 'hooks' in existingSizeURLField && + existingSizeURLField?.hooks?.afterRead) || + []), ], }, },