Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
1 line
10 KiB
Plaintext
1 line
10 KiB
Plaintext
{"version":3,"sources":["../../src/utilities/flattenTopLevelFields.ts"],"sourcesContent":["import type { I18nClient } from '@payloadcms/translations'\n\nimport { getTranslation } from '@payloadcms/translations'\n\nimport type { ClientTab } from '../admin/fields/Tabs.js'\nimport type { ClientField } from '../fields/config/client.js'\nimport type {\n Field,\n FieldAffectingData,\n FieldAffectingDataClient,\n FieldPresentationalOnly,\n FieldPresentationalOnlyClient,\n Tab,\n} from '../fields/config/types.js'\n\nimport {\n fieldAffectsData,\n fieldHasSubFields,\n fieldIsPresentationalOnly,\n tabHasName,\n} from '../fields/config/types.js'\n\ntype FlattenedField<TField> = TField extends ClientField\n ? { accessor?: string; labelWithPrefix?: string } & (\n | FieldAffectingDataClient\n | FieldPresentationalOnlyClient\n )\n : { accessor?: string; labelWithPrefix?: string } & (FieldAffectingData | FieldPresentationalOnly)\n\ntype TabType<TField> = TField extends ClientField ? ClientTab : Tab\n\n/**\n * Options to control how fields are flattened.\n */\ntype FlattenFieldsOptions = {\n /**\n * i18n context used for translating `label` values via `getTranslation`.\n */\n i18n?: I18nClient\n /**\n * If true, presentational-only fields (like UI fields) will be included\n * in the output. Otherwise, they will be skipped.\n * Default: false.\n */\n keepPresentationalFields?: boolean\n /**\n * A label prefix to prepend to translated labels when building `labelWithPrefix`.\n * Used recursively when flattening nested fields.\n */\n labelPrefix?: string\n /**\n * If true, nested fields inside `group` & `tabs` fields will be lifted to the top level\n * and given contextual `accessor` and `labelWithPrefix` values.\n * Default: false.\n */\n moveSubFieldsToTop?: boolean\n /**\n * A path prefix to prepend to field names when building the `accessor`.\n * Used recursively when flattening nested fields.\n */\n pathPrefix?: string\n}\n\n/**\n * Flattens a collection's fields into a single array of fields, optionally\n * extracting nested fields in group fields.\n *\n * @param fields - Array of fields to flatten\n * @param options - Options to control the flattening behavior\n */\nexport function flattenTopLevelFields<TField extends ClientField | Field>(\n fields: TField[] = [],\n options?: boolean | FlattenFieldsOptions,\n): FlattenedField<TField>[] {\n const normalizedOptions: FlattenFieldsOptions =\n typeof options === 'boolean' ? { keepPresentationalFields: options } : (options ?? {})\n\n const {\n i18n,\n keepPresentationalFields,\n labelPrefix,\n moveSubFieldsToTop = false,\n pathPrefix,\n } = normalizedOptions\n\n return fields.reduce<FlattenedField<TField>[]>((acc, field) => {\n // If a group field has subfields and has a name, otherwise we catch it below along with collapsible and row fields\n if (field.type === 'group' && 'fields' in field) {\n if (moveSubFieldsToTop) {\n const isNamedGroup = 'name' in field && typeof field.name === 'string' && !!field.name\n const groupName = 'name' in field ? field.name : undefined\n\n const translatedLabel =\n 'label' in field && field.label && i18n\n ? getTranslation(field.label as string, i18n)\n : undefined\n\n const labelWithPrefix = labelPrefix\n ? `${labelPrefix} > ${translatedLabel ?? groupName}`\n : (translatedLabel ?? groupName)\n\n const nameWithPrefix =\n 'name' in field && field.name\n ? pathPrefix\n ? `${pathPrefix}.${field.name}`\n : field.name\n : pathPrefix\n\n acc.push(\n // Need to include the top-level group field when hoisting its subfields,\n // so that `buildColumnState` can detect and render a column if the group\n // has a custom admin Cell component defined in its configuration.\n // See: packages/ui/src/providers/TableColumns/buildColumnState/index.tsx\n field as FlattenedField<TField>,\n ...flattenTopLevelFields(field.fields as TField[], {\n i18n,\n keepPresentationalFields,\n labelPrefix: isNamedGroup ? labelWithPrefix : labelPrefix,\n moveSubFieldsToTop,\n pathPrefix: isNamedGroup ? nameWithPrefix : pathPrefix,\n }),\n )\n } else {\n if (fieldAffectsData(field)) {\n // Hoisting diabled - keep as top level field\n acc.push(field as FlattenedField<TField>)\n } else {\n acc.push(...flattenTopLevelFields(field.fields as TField[], options))\n }\n }\n } else if (field.type === 'tabs' && 'tabs' in field) {\n return [\n ...acc,\n ...field.tabs.reduce<FlattenedField<TField>[]>((tabFields, tab) => {\n if (tabHasName(tab)) {\n if (moveSubFieldsToTop) {\n const translatedLabel =\n 'label' in tab && tab.label && i18n ? getTranslation(tab.label, i18n) : undefined\n\n const labelWithPrefixForTab = labelPrefix\n ? `${labelPrefix} > ${translatedLabel ?? tab.name}`\n : (translatedLabel ?? tab.name)\n\n const pathPrefixForTab = tab.name\n ? pathPrefix\n ? `${pathPrefix}.${tab.name}`\n : tab.name\n : pathPrefix\n\n return [\n ...tabFields,\n ...flattenTopLevelFields(tab.fields as TField[], {\n i18n,\n keepPresentationalFields,\n labelPrefix: labelWithPrefixForTab,\n moveSubFieldsToTop,\n pathPrefix: pathPrefixForTab,\n }),\n ]\n } else {\n // Named tab, hoisting disabled: keep as top-level field\n return [\n ...tabFields,\n {\n ...tab,\n type: 'tab',\n } as unknown as FlattenedField<TField>,\n ]\n }\n } else {\n // Unnamed tab: always hoist its fields\n return [...tabFields, ...flattenTopLevelFields<TField>(tab.fields as TField[], options)]\n }\n }, []),\n ]\n } else if (fieldHasSubFields(field) && ['collapsible', 'row'].includes(field.type)) {\n // Recurse into row and collapsible\n acc.push(...flattenTopLevelFields(field.fields as TField[], options))\n } else if (\n fieldAffectsData(field) ||\n (keepPresentationalFields && fieldIsPresentationalOnly(field))\n ) {\n // Ignore nested `id` fields when inside nested structure\n if (field.name === 'id' && labelPrefix !== undefined) {\n return acc\n }\n\n const translatedLabel =\n 'label' in field && field.label && i18n ? getTranslation(field.label, i18n) : undefined\n\n const name = 'name' in field ? field.name : undefined\n\n const isHoistingFromGroup = pathPrefix !== undefined || labelPrefix !== undefined\n\n acc.push({\n ...(field as FlattenedField<TField>),\n ...(moveSubFieldsToTop &&\n isHoistingFromGroup && {\n accessor: pathPrefix && name ? `${pathPrefix}.${name}` : (name ?? ''),\n labelWithPrefix: labelPrefix\n ? `${labelPrefix} > ${translatedLabel ?? name}`\n : (translatedLabel ?? name),\n }),\n })\n }\n\n return acc\n }, [])\n}\n"],"names":["getTranslation","fieldAffectsData","fieldHasSubFields","fieldIsPresentationalOnly","tabHasName","flattenTopLevelFields","fields","options","normalizedOptions","keepPresentationalFields","i18n","labelPrefix","moveSubFieldsToTop","pathPrefix","reduce","acc","field","type","isNamedGroup","name","groupName","undefined","translatedLabel","label","labelWithPrefix","nameWithPrefix","push","tabs","tabFields","tab","labelWithPrefixForTab","pathPrefixForTab","includes","isHoistingFromGroup","accessor"],"mappings":"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"} |