@strapi/content-manager 5.61.0 → 5.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/components/ConfigurationForm/Fields.js +1 -1
- package/dist/admin/components/ConfigurationForm/Fields.js.map +1 -1
- package/dist/admin/components/ConfigurationForm/Fields.mjs +3 -3
- package/dist/admin/components/ConfigurationForm/Fields.mjs.map +1 -1
- package/dist/admin/features/I18nSharedFieldsLock.js +54 -0
- package/dist/admin/features/I18nSharedFieldsLock.js.map +1 -0
- package/dist/admin/features/I18nSharedFieldsLock.mjs +31 -0
- package/dist/admin/features/I18nSharedFieldsLock.mjs.map +1 -0
- package/dist/admin/history/components/VersionInputRenderer.js +7 -2
- package/dist/admin/history/components/VersionInputRenderer.js.map +1 -1
- package/dist/admin/history/components/VersionInputRenderer.mjs +7 -3
- package/dist/admin/history/components/VersionInputRenderer.mjs.map +1 -1
- package/dist/admin/hooks/useContentManagerInitData.js +27 -8
- package/dist/admin/hooks/useContentManagerInitData.js.map +1 -1
- package/dist/admin/hooks/useContentManagerInitData.mjs +29 -10
- package/dist/admin/hooks/useContentManagerInitData.mjs.map +1 -1
- package/dist/admin/hooks/useDocument.js +11 -13
- package/dist/admin/hooks/useDocument.js.map +1 -1
- package/dist/admin/hooks/useDocument.mjs +11 -13
- package/dist/admin/hooks/useDocument.mjs.map +1 -1
- package/dist/admin/hooks/useI18nFieldLock.js +169 -0
- package/dist/admin/hooks/useI18nFieldLock.js.map +1 -0
- package/dist/admin/hooks/useI18nFieldLock.mjs +140 -0
- package/dist/admin/hooks/useI18nFieldLock.mjs.map +1 -0
- package/dist/admin/hooks/usePersistentQueryParams.js +16 -3
- package/dist/admin/hooks/usePersistentQueryParams.js.map +1 -1
- package/dist/admin/hooks/usePersistentQueryParams.mjs +16 -3
- package/dist/admin/hooks/usePersistentQueryParams.mjs.map +1 -1
- package/dist/admin/index.js +5 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +2 -0
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/modules/app.js +8 -1
- package/dist/admin/modules/app.js.map +1 -1
- package/dist/admin/modules/app.mjs +8 -2
- package/dist/admin/modules/app.mjs.map +1 -1
- package/dist/admin/pages/EditView/EditViewPage.js +129 -127
- package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
- package/dist/admin/pages/EditView/EditViewPage.mjs +129 -127
- package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/DocumentActions.js +11 -4
- package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
- package/dist/admin/pages/EditView/components/DocumentActions.mjs +12 -5
- package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.js +31 -21
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.mjs +32 -22
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/AddComponentMenu.js +98 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/AddComponentMenu.js.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/AddComponentMenu.mjs +96 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/AddComponentMenu.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/ComponentCopyModal.js +1103 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/ComponentCopyModal.js.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/ComponentCopyModal.mjs +1077 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/ComponentCopyModal.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/CopiedComponents.js +211 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/CopiedComponents.js.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/CopiedComponents.mjs +183 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/CopiedComponents.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/Initializer.js +84 -41
- package/dist/admin/pages/EditView/components/FormInputs/Component/Initializer.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Initializer.mjs +86 -43
- package/dist/admin/pages/EditView/components/FormInputs/Component/Initializer.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js +86 -20
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.mjs +89 -23
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js +5 -2
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.mjs +5 -2
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js +142 -22
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs +143 -23
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/utils/componentCopy.js +402 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/utils/componentCopy.js.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/utils/componentCopy.mjs +389 -0
- package/dist/admin/pages/EditView/components/FormInputs/Component/utils/componentCopy.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js +84 -33
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs +85 -34
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.js +5 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.mjs +5 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +17 -4
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +18 -5
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js +54 -6
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs +54 -6
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +11 -9
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +12 -10
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +9 -4
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +9 -4
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.js +66 -63
- package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.mjs +66 -63
- package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/InputRenderer.js +7 -1
- package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
- package/dist/admin/pages/EditView/components/InputRenderer.mjs +7 -1
- package/dist/admin/pages/EditView/components/InputRenderer.mjs.map +1 -1
- package/dist/admin/pages/EditView/utils/data.js +14 -9
- package/dist/admin/pages/EditView/utils/data.js.map +1 -1
- package/dist/admin/pages/EditView/utils/data.mjs +14 -9
- package/dist/admin/pages/EditView/utils/data.mjs.map +1 -1
- package/dist/admin/pages/EditView/utils/forms.js +34 -0
- package/dist/admin/pages/EditView/utils/forms.js.map +1 -1
- package/dist/admin/pages/EditView/utils/forms.mjs +34 -1
- package/dist/admin/pages/EditView/utils/forms.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/DraggableCard.js +2 -1
- package/dist/admin/pages/ListConfiguration/components/DraggableCard.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/DraggableCard.mjs +2 -1
- package/dist/admin/pages/ListConfiguration/components/DraggableCard.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/EditFieldForm.js +7 -6
- package/dist/admin/pages/ListConfiguration/components/EditFieldForm.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/EditFieldForm.mjs +7 -6
- package/dist/admin/pages/ListConfiguration/components/EditFieldForm.mjs.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.js +11 -2
- package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.mjs +13 -4
- package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.js +15 -5
- package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.mjs +16 -7
- package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
- package/dist/admin/preview/components/InputPopover.js +18 -8
- package/dist/admin/preview/components/InputPopover.js.map +1 -1
- package/dist/admin/preview/components/InputPopover.mjs +19 -9
- package/dist/admin/preview/components/InputPopover.mjs.map +1 -1
- package/dist/admin/preview/pages/Preview.js +5 -16
- package/dist/admin/preview/pages/Preview.js.map +1 -1
- package/dist/admin/preview/pages/Preview.mjs +5 -16
- package/dist/admin/preview/pages/Preview.mjs.map +1 -1
- package/dist/admin/preview/utils/fieldUtils.js +2 -0
- package/dist/admin/preview/utils/fieldUtils.js.map +1 -1
- package/dist/admin/preview/utils/fieldUtils.mjs +2 -1
- package/dist/admin/preview/utils/fieldUtils.mjs.map +1 -1
- package/dist/admin/services/api.js +2 -1
- package/dist/admin/services/api.js.map +1 -1
- package/dist/admin/services/api.mjs +2 -1
- package/dist/admin/services/api.mjs.map +1 -1
- package/dist/admin/services/documents.js +21 -1
- package/dist/admin/services/documents.js.map +1 -1
- package/dist/admin/services/documents.mjs +21 -2
- package/dist/admin/services/documents.mjs.map +1 -1
- package/dist/admin/services/relations.js +47 -1
- package/dist/admin/services/relations.js.map +1 -1
- package/dist/admin/services/relations.mjs +47 -2
- package/dist/admin/services/relations.mjs.map +1 -1
- package/dist/admin/src/exports.d.ts +2 -0
- package/dist/admin/src/features/I18nSharedFieldsLock.d.ts +22 -0
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +7 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useI18nFieldLock.d.ts +61 -0
- package/dist/admin/src/modules/app.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/AddComponentMenu.d.ts +15 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/ComponentCopyModal.d.ts +58 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/CopiedComponents.d.ts +41 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Initializer.d.ts +7 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/NonRepeatable.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Repeatable.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/utils/componentCopy.d.ts +115 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +6 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.d.ts +2 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +5 -1
- package/dist/admin/src/pages/EditView/utils/forms.d.ts +13 -2
- package/dist/admin/src/pages/ListView/components/Filters.d.ts +12 -3
- package/dist/admin/src/preview/services/preview.d.ts +1 -1
- package/dist/admin/src/preview/utils/fieldUtils.d.ts +1 -0
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +25 -21
- package/dist/admin/src/services/homepage.d.ts +1 -1
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +5 -3
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/translations/en.json.js +41 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +41 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/controllers/relations.js +4 -2
- package/dist/server/controllers/relations.js.map +1 -1
- package/dist/server/controllers/relations.mjs +4 -2
- package/dist/server/controllers/relations.mjs.map +1 -1
- package/dist/server/controllers/utils/metadata.js +3 -1
- package/dist/server/controllers/utils/metadata.js.map +1 -1
- package/dist/server/controllers/utils/metadata.mjs +3 -1
- package/dist/server/controllers/utils/metadata.mjs.map +1 -1
- package/dist/server/history/services/utils.js +3 -1
- package/dist/server/history/services/utils.js.map +1 -1
- package/dist/server/history/services/utils.mjs +3 -1
- package/dist/server/history/services/utils.mjs.map +1 -1
- package/dist/server/homepage/services/homepage-query-utils.js +14 -0
- package/dist/server/homepage/services/homepage-query-utils.js.map +1 -1
- package/dist/server/homepage/services/homepage-query-utils.mjs +14 -1
- package/dist/server/homepage/services/homepage-query-utils.mjs.map +1 -1
- package/dist/server/homepage/services/homepage.js +1 -1
- package/dist/server/homepage/services/homepage.js.map +1 -1
- package/dist/server/homepage/services/homepage.mjs +2 -2
- package/dist/server/homepage/services/homepage.mjs.map +1 -1
- package/dist/server/mcp/sanitizers/shape-relations.js +1 -3
- package/dist/server/mcp/sanitizers/shape-relations.js.map +1 -1
- package/dist/server/mcp/sanitizers/shape-relations.mjs +1 -3
- package/dist/server/mcp/sanitizers/shape-relations.mjs.map +1 -1
- package/dist/server/mcp/schemas/output-schemas.js +2 -1
- package/dist/server/mcp/schemas/output-schemas.js.map +1 -1
- package/dist/server/mcp/schemas/output-schemas.mjs +2 -1
- package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -1
- package/dist/server/services/document-manager.js +3 -2
- package/dist/server/services/document-manager.js.map +1 -1
- package/dist/server/services/document-manager.mjs +3 -2
- package/dist/server/services/document-manager.mjs.map +1 -1
- package/dist/server/services/document-metadata.js +92 -4
- package/dist/server/services/document-metadata.js.map +1 -1
- package/dist/server/services/document-metadata.mjs +92 -4
- package/dist/server/services/document-metadata.mjs.map +1 -1
- package/dist/server/services/permission-checker.js +20 -8
- package/dist/server/services/permission-checker.js.map +1 -1
- package/dist/server/services/permission-checker.mjs +20 -8
- package/dist/server/services/permission-checker.mjs.map +1 -1
- package/dist/server/services/uid.js +2 -1
- package/dist/server/services/uid.js.map +1 -1
- package/dist/server/services/uid.mjs +2 -1
- package/dist/server/services/uid.mjs.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +1 -0
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/homepage/services/homepage-query-utils.d.ts +6 -0
- package/dist/server/src/homepage/services/homepage-query-utils.d.ts.map +1 -1
- package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +21 -7
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/mcp/sanitizers/shape-relations.d.ts.map +1 -1
- package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +5 -1
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +21 -7
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts +6 -5
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/uid.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +7 -0
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/single-types.d.ts +4 -0
- package/dist/shared/contracts/single-types.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentCopyModal.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/ComponentCopyModal.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useAPIErrorHandler, useForm, useNotification } from '@strapi/admin/strapi-admin';\nimport {\n Badge,\n Box,\n Button,\n Checkbox,\n Flex,\n Loader,\n Modal,\n Radio,\n Searchbar,\n Typography,\n} from '@strapi/design-system';\nimport { Duplicate, WarningCircle } from '@strapi/icons';\nimport toPath from 'lodash/toPath';\nimport { type IntlFormatters, useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { COLLECTION_TYPES } from '../../../../../constants/collections';\nimport { useDebounce } from '../../../../../hooks/useDebounce';\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { useDocumentLayout } from '../../../../../hooks/useDocumentLayout';\nimport {\n useLazyGetAllDocumentsQuery,\n useLazyGetDocumentQuery,\n} from '../../../../../services/documents';\nimport { useLazyGetAllRelationsQuery } from '../../../../../services/relations';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { CellValue } from '../../../../ListView/components/TableCells/CellValue';\nimport { type AnyData } from '../../../utils/data';\n\nimport {\n cloneComponentData,\n connectRelations,\n getComponentInstances,\n getComponentPreview,\n getRelationsToCopy,\n type ComponentCopyMode,\n type ComponentInstance,\n type ComponentPreviewField,\n} from './utils/componentCopy';\n\nimport type { Document } from '../../../../../hooks/useDocument';\n\n/* -------------------------------------------------------------------------------------------------\n * ComponentCopyModal\n * -----------------------------------------------------------------------------------------------*/\n\ntype ComponentCopySelection = 'single' | 'multiple';\n\ninterface ComponentCopyModalProps {\n componentUid: string;\n /**\n * The label of the field the copies land in, as it's displayed in the form.\n */\n fieldLabel: string;\n /**\n * How many components the field can still take. The selection can't exceed it.\n */\n maxSelection?: number;\n mode: ComponentCopyMode;\n onClose: () => void;\n /**\n * Inserts the copies in the field. Returns `false` when the field turns them down, e.g. because\n * it already holds its maximum number of components. The field then reports it to the user itself.\n */\n onInsert: (components: AnyData[]) => boolean;\n /**\n * Whether the field already holds content the copy is going to replace. Only applies to a\n * `single` selection.\n */\n replacesContent?: boolean;\n /**\n * A field holding one component takes a single copy, a repeatable component or a dynamic zone\n * take several at once.\n */\n selection: ComponentCopySelection;\n sourceFieldName: string;\n}\n\nconst ENTRIES_PAGE_SIZE = '10';\n\nconst getDocumentTitle = (\n document: Document,\n mainField: string,\n fallback: string,\n untitled: string\n) => {\n if (mainField !== 'id') {\n const value = document?.[mainField];\n\n if (value !== undefined && value !== null && String(value).trim().length > 0) {\n return String(value);\n }\n }\n\n return fallback || untitled;\n};\n\ninterface EntryRow {\n documentId: string;\n title: string;\n isCurrent: boolean;\n disabled: boolean;\n meta?: string;\n}\n\n/**\n * The entry picked in the list. Kept apart from the list: searching can filter the entry out of\n * the list while its components are still previewed.\n */\ninterface SelectedEntry {\n documentId: string;\n title: string;\n isCurrent: boolean;\n}\n\ninterface GetEntryMetaArgs {\n /**\n * How many components of the wanted kind the entry holds, `undefined` when it isn't known yet.\n */\n count: number | undefined;\n fieldLabel: string;\n /**\n * The label of the only component of the entry, when it holds a single one.\n */\n firstInstanceLabel?: string;\n formatMessage: IntlFormatters['formatMessage'];\n isCurrent: boolean;\n isFormModified: boolean;\n selection: ComponentCopySelection;\n}\n\n/**\n * The line of text shown under the title of an entry in the list.\n */\nconst getEntryMeta = ({\n count,\n fieldLabel,\n firstInstanceLabel,\n formatMessage,\n isCurrent,\n isFormModified,\n selection,\n}: GetEntryMetaArgs): string | undefined => {\n if (isCurrent && isFormModified) {\n return formatMessage({\n id: getTranslation('components.ComponentCopyModal.entries.unsaved'),\n defaultMessage: 'Save your changes to copy from this entry',\n });\n }\n\n if (count === undefined) {\n return undefined;\n }\n\n if (count === 0) {\n return isCurrent && selection === 'single'\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.entries.noneOther'),\n defaultMessage: 'No other {label} in this entry',\n },\n { label: fieldLabel }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.entries.none'),\n defaultMessage: 'No {label} yet',\n },\n { label: fieldLabel }\n );\n }\n\n if (isCurrent) {\n return formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.entries.count.saved'),\n defaultMessage: '{count, plural, one {# item} other {# items}} · last saved version',\n },\n { count }\n );\n }\n\n if (selection === 'single' && count === 1 && firstInstanceLabel) {\n return firstInstanceLabel;\n }\n\n return formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.entries.count'),\n defaultMessage: '{count, plural, one {# item} other {# items}}',\n },\n { count }\n );\n};\n\n/**\n * The modal is mounted while it's open and unmounted when it's closed.\n */\nconst ComponentCopyModal = ({\n componentUid,\n fieldLabel,\n maxSelection = Infinity,\n mode,\n onClose,\n onInsert,\n replacesContent = false,\n selection,\n sourceFieldName,\n}: ComponentCopyModalProps) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);\n const { currentDocument, currentDocumentMeta } = useDocumentContext('ComponentCopyModal');\n const {\n edit: { components: componentLayouts, settings },\n } = useDocumentLayout(currentDocumentMeta.model);\n const targetValues = useForm('ComponentCopyModal', (state) => state.values);\n const isFormModified = useForm('ComponentCopyModal', (state) => state.modified);\n\n const [search, setSearch] = React.useState('');\n const debouncedSearch = useDebounce(search, 300);\n const searchRef = React.useRef<HTMLInputElement>(null);\n const [selectedEntry, setSelectedEntry] = React.useState<SelectedEntry | null>(null);\n const [sourceDocument, setSourceDocument] = React.useState<Document | null>(null);\n const [selectedPaths, setSelectedPaths] = React.useState<string[]>([]);\n const [isCopying, setIsCopying] = React.useState(false);\n // Read while rendering: once mounted, the modal holds the focus\n const [returnFocusTarget] = React.useState(getReturnFocusTarget);\n\n /**\n * Loading an entry and copying components are asynchronous, the modal can be closed in the\n * meantime and the user can pick another entry while one loads.\n */\n const isMountedRef = React.useRef(true);\n const selectedDocumentIdRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n isMountedRef.current = true;\n\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n const [\n getDocuments,\n {\n data: documentsData,\n error: documentsError,\n isFetching: isFetchingDocuments,\n isUninitialized: isDocumentsQueryUninitialized,\n },\n ] = useLazyGetAllDocumentsQuery();\n const [getDocument, { isFetching: isFetchingDocument }] = useLazyGetDocumentQuery();\n const [getAllRelations] = useLazyGetAllRelationsQuery();\n\n const { components } = currentDocument;\n const componentDisplayName = components[componentUid]?.info?.displayName ?? componentUid;\n const currentDocumentId = currentDocumentMeta.documentId;\n /**\n * The last saved version of the entry being edited: what the API holds for it.\n */\n const savedDocument = currentDocument.document;\n /**\n * The list of entries only loads the first level of components: for a field nested in another\n * component, how many components an entry holds is only known once the entry is loaded.\n */\n const isNestedField = toPath(sourceFieldName).length > 1;\n\n React.useEffect(() => {\n if (currentDocumentMeta.collectionType !== COLLECTION_TYPES) {\n return;\n }\n\n void getDocuments({\n model: currentDocumentMeta.model,\n params: {\n ...currentDocumentMeta.params,\n _q: debouncedSearch || undefined,\n page: '1',\n pageSize: ENTRIES_PAGE_SIZE,\n sort: 'updatedAt:DESC',\n },\n });\n }, [\n currentDocumentMeta.collectionType,\n currentDocumentMeta.model,\n currentDocumentMeta.params,\n debouncedSearch,\n getDocuments,\n ]);\n\n React.useEffect(() => {\n if (documentsError) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(documentsError),\n });\n }\n }, [documentsError, formatAPIError, toggleNotification]);\n\n const findInstances = React.useCallback(\n (document: Document) =>\n getComponentInstances({\n componentUid,\n components,\n getMainField: (uid) => componentLayouts[uid]?.settings?.mainField,\n mode,\n schema: currentDocument.schema,\n sourceDocument: document,\n sourceFieldName,\n targetValues,\n }),\n [\n componentLayouts,\n componentUid,\n components,\n currentDocument.schema,\n mode,\n sourceFieldName,\n targetValues,\n ]\n );\n\n /**\n * In a field holding one component, the saved version of that very component is not something\n * to copy: the field already holds it.\n */\n const filterOwnInstance = React.useCallback(\n (instances: ComponentInstance[]) =>\n selection === 'single'\n ? instances.filter((instance) => instance.sourcePath !== sourceFieldName)\n : instances,\n [selection, sourceFieldName]\n );\n\n const currentEntryInstances = React.useMemo(\n () => (savedDocument ? filterOwnInstance(findInstances(savedDocument)) : []),\n [filterOwnInstance, findInstances, savedDocument]\n );\n\n const untitled = formatMessage({\n id: 'content-manager.containers.untitled',\n defaultMessage: 'Untitled',\n });\n const getTitle = (document: Document) =>\n getDocumentTitle(document, settings.mainField, document.documentId, untitled);\n\n const currentEntryTitle = savedDocument ? getTitle(savedDocument) : '';\n const normalizedSearch = debouncedSearch.trim().toLowerCase();\n // A locale that isn't saved yet has a document id but nothing stored (no `id`)\n const showCurrentEntry =\n !!savedDocument?.id &&\n !!currentDocumentId &&\n (!normalizedSearch || currentEntryTitle.toLowerCase().includes(normalizedSearch));\n\n const currentEntryRow: EntryRow | null = showCurrentEntry\n ? {\n documentId: currentDocumentId,\n title: currentEntryTitle,\n isCurrent: true,\n disabled: isFormModified || currentEntryInstances.length === 0,\n meta: getEntryMeta({\n count: currentEntryInstances.length,\n fieldLabel,\n formatMessage,\n isCurrent: true,\n isFormModified,\n selection,\n }),\n }\n : null;\n\n const entryRows: EntryRow[] = [\n ...(currentEntryRow ? [currentEntryRow] : []),\n ...(documentsData?.results ?? [])\n .filter((document) => document.documentId !== currentDocumentId)\n .map((document): EntryRow => {\n const instances = isNestedField ? undefined : findInstances(document);\n\n return {\n documentId: document.documentId,\n title: getTitle(document),\n isCurrent: false,\n disabled: instances?.length === 0,\n meta: getEntryMeta({\n count: instances?.length,\n fieldLabel,\n firstInstanceLabel: instances?.[0]?.label,\n formatMessage,\n isCurrent: false,\n isFormModified,\n selection,\n }),\n };\n }),\n ];\n\n /**\n * Loads the entry components are copied from.\n */\n const handleSelectEntry = async (row: EntryRow) => {\n // Picking the entry that's already selected keeps the components ticked in it.\n if (selectedDocumentIdRef.current === row.documentId) {\n return;\n }\n\n selectedDocumentIdRef.current = row.documentId;\n setSelectedEntry({ documentId: row.documentId, title: row.title, isCurrent: row.isCurrent });\n setSelectedPaths([]);\n\n if (row.isCurrent) {\n setSourceDocument(savedDocument ?? null);\n\n return;\n }\n\n setSourceDocument(null);\n\n const result = await getDocument({\n collectionType: currentDocumentMeta.collectionType,\n documentId: row.documentId,\n model: currentDocumentMeta.model,\n params: currentDocumentMeta.params,\n });\n\n // Another entry was picked in the meantime, or the modal was closed.\n if (!isMountedRef.current || selectedDocumentIdRef.current !== row.documentId) {\n return;\n }\n\n if (result.error) {\n toggleNotification({\n type: 'danger',\n message: formatAPIError(result.error),\n });\n selectedDocumentIdRef.current = null;\n setSelectedEntry(null);\n\n return;\n }\n\n // Without its data the entry can't be previewed: unselect it, so it can be picked again.\n if (!result.data?.data) {\n selectedDocumentIdRef.current = null;\n setSelectedEntry(null);\n\n return;\n }\n\n setSourceDocument(result.data.data);\n };\n\n const isCurrentEntrySelected = selectedEntry?.isCurrent ?? false;\n const instances = React.useMemo(() => {\n if (isCurrentEntrySelected) {\n return currentEntryInstances;\n }\n\n return sourceDocument ? findInstances(sourceDocument) : [];\n }, [currentEntryInstances, findInstances, isCurrentEntrySelected, sourceDocument]);\n\n // An entry holding a single component is selected right away: there's nothing else to pick.\n React.useEffect(() => {\n if (instances.length === 1) {\n const [{ sourcePath }] = instances;\n\n setSelectedPaths((paths) =>\n paths.length === 1 && paths[0] === sourcePath ? paths : [sourcePath]\n );\n }\n }, [instances]);\n\n const selectedInstances = instances.filter((instance) =>\n selectedPaths.includes(instance.sourcePath)\n );\n const areAllSelected = instances.length > 0 && selectedInstances.length === instances.length;\n const isSelectionTooLarge = selectedInstances.length > maxSelection;\n\n const mainField = componentLayouts[componentUid]?.settings?.mainField;\n const previewFields = React.useMemo(\n () =>\n componentLayouts[componentUid]?.layout\n .flat()\n .filter((field) => field.name !== mainField)\n .map((field) => ({ name: field.name, label: field.label })),\n [componentLayouts, componentUid, mainField]\n );\n\n /**\n * The copy is a snapshot of the component, its relations are connected to the same entries.\n * A relation that can't be loaded is left empty rather than failing the whole copy.\n */\n const copyInstance = async (instance: ComponentInstance) => {\n const relations = getRelationsToCopy(instance.source, componentUid, components);\n\n const loadedRelations = await Promise.allSettled(\n relations.map(({ model, id, targetField }) =>\n getAllRelations({ model, id, targetField, params: currentDocumentMeta.params }).unwrap()\n )\n );\n\n const data = loadedRelations.reduce(\n (acc, result, index) =>\n result.status === 'fulfilled'\n ? connectRelations(acc, relations[index].path, result.value)\n : acc,\n cloneComponentData(instance.source, componentUid, components)\n );\n\n return {\n data: mode === 'dynamiczone' ? { ...data, __component: componentUid } : data,\n hasMissingRelations: loadedRelations.some((result) => result.status === 'rejected'),\n };\n };\n\n /**\n * The current entry gets its own messages: \"this entry\" can't be injected in place of an\n * entry title without breaking the sentence in other languages.\n */\n const getSuccessMessage = (count: number) => {\n const entry = selectedEntry?.title ?? '';\n\n if (selection === 'single' && replacesContent) {\n return isCurrentEntrySelected\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.replaced.currentEntry'),\n defaultMessage: '{label} replaced with content from this entry',\n },\n { label: fieldLabel }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.replaced'),\n defaultMessage: '{label} replaced with content from {entry}',\n },\n { label: fieldLabel, entry }\n );\n }\n\n if (selection === 'single') {\n return isCurrentEntrySelected\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.single.currentEntry'),\n defaultMessage: '{label} copied from this entry',\n },\n { label: fieldLabel }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.single'),\n defaultMessage: '{label} copied from {entry}',\n },\n { label: fieldLabel, entry }\n );\n }\n\n if (mode === 'dynamiczone') {\n return isCurrentEntrySelected\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.components.currentEntry'),\n defaultMessage:\n '{count, plural, one {# {component} component} other {# {component} components}} copied from this entry',\n },\n { count, component: componentDisplayName }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.components'),\n defaultMessage:\n '{count, plural, one {# {component} component} other {# {component} components}} copied from {entry}',\n },\n { count, component: componentDisplayName, entry }\n );\n }\n\n return isCurrentEntrySelected\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.entries.currentEntry'),\n defaultMessage:\n '{count, plural, one {# entry} other {# entries}} copied from this entry',\n },\n { count }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.success.entries'),\n defaultMessage: '{count, plural, one {# entry} other {# entries}} copied from {entry}',\n },\n { count, entry }\n );\n };\n\n const handleConfirm = async () => {\n if (selectedInstances.length === 0 || isSelectionTooLarge) {\n return;\n }\n\n setIsCopying(true);\n\n const copies = await Promise.all(selectedInstances.map(copyInstance));\n\n if (!isMountedRef.current) {\n return;\n }\n\n // The field tells the user why it turns the copies down, e.g. it's full.\n if (!onInsert(copies.map(({ data }) => data))) {\n onClose();\n\n return;\n }\n\n onClose();\n toggleNotification(\n copies.some(({ hasMissingRelations }) => hasMissingRelations)\n ? {\n type: 'warning',\n message: formatMessage({\n id: getTranslation('components.ComponentCopyModal.relations-warning'),\n defaultMessage: 'Content copied, but some of its relations could not be loaded.',\n }),\n }\n : {\n type: 'success',\n message: getSuccessMessage(copies.length),\n }\n );\n };\n\n const title =\n selection === 'single'\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.title.single'),\n defaultMessage: 'Copy an existing {label}',\n },\n { label: fieldLabel }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.title.multiple'),\n defaultMessage: 'Copy existing {label}',\n },\n { label: fieldLabel }\n );\n\n const getConfirmLabel = () => {\n if (selection === 'single' && replacesContent) {\n return formatMessage({\n id: getTranslation('components.ComponentCopyModal.confirm.replace'),\n defaultMessage: 'Replace content',\n });\n }\n\n if (selectedInstances.length > 1) {\n return formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.confirm.multiple'),\n defaultMessage: 'Use content from {count} items',\n },\n { count: selectedInstances.length }\n );\n }\n\n return formatMessage({\n id: getTranslation('components.ComponentCopyModal.confirm'),\n defaultMessage: 'Use content',\n });\n };\n\n const renderFooterNote = () => {\n if (isSelectionTooLarge) {\n return (\n <FooterWarning>\n {formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.footer.tooMany'),\n defaultMessage:\n 'You can add {remaining, plural, one {# more item} other {# more items}} to {label}. Unselect {excess, plural, one {# item} other {# items}}.',\n },\n {\n label: fieldLabel,\n remaining: maxSelection,\n excess: selectedInstances.length - maxSelection,\n }\n )}\n </FooterWarning>\n );\n }\n\n if (selection === 'single' && replacesContent) {\n return (\n <FooterWarning>\n {formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.footer.replace'),\n defaultMessage: 'This will replace the current content of {label}.',\n },\n { label: fieldLabel }\n )}\n </FooterWarning>\n );\n }\n\n return (\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('components.ComponentCopyModal.footer.note'),\n defaultMessage: 'The content is copied: editing it here won’t change the original entry.',\n })}\n </Typography>\n );\n };\n\n const isLoadingEntries = isFetchingDocuments || isDocumentsQueryUninitialized;\n const isLoadingSource = selectedEntry !== null && !selectedEntry.isCurrent && !sourceDocument;\n const loadingLabel = formatMessage({\n id: getTranslation('components.ComponentCopyModal.loading'),\n defaultMessage: 'Loading',\n });\n\n const renderInstanceSummary = (instance: ComponentInstance, titleId: string) => (\n <InstanceSummary\n instance={instance}\n preview={getComponentPreview(instance.source, componentUid, components, previewFields)}\n titleId={titleId}\n />\n );\n\n const renderPreview = () => {\n if (selectedEntry === null) {\n return (\n <Flex\n direction=\"column\"\n alignItems=\"center\"\n justifyContent=\"center\"\n gap={2}\n padding={6}\n grow={1}\n >\n <Flex color=\"neutral400\">\n <Duplicate width=\"2.4rem\" height=\"2.4rem\" />\n </Flex>\n <Typography variant=\"omega\" textColor=\"neutral600\" textAlign=\"center\">\n {selection === 'single'\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.preview.empty.single'),\n defaultMessage: 'Pick an entry to preview its {label}.',\n },\n { label: fieldLabel }\n )\n : formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.preview.empty'),\n defaultMessage: 'Pick an entry to see its {label}.',\n },\n { label: fieldLabel }\n )}\n </Typography>\n </Flex>\n );\n }\n\n if (isLoadingSource) {\n return (\n <Flex justifyContent=\"center\" alignItems=\"center\" grow={1} padding={6}>\n <Loader small>{loadingLabel}</Loader>\n </Flex>\n );\n }\n\n return (\n <>\n <PreviewHeader\n justifyContent=\"space-between\"\n alignItems=\"center\"\n gap={4}\n paddingTop={4}\n paddingBottom={4}\n paddingLeft={5}\n paddingRight={5}\n >\n <Typography fontWeight=\"bold\" textColor=\"neutral800\" ellipsis>\n {formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.preview.title'),\n defaultMessage: '{entry} · {label}',\n },\n { entry: selectedEntry.title, label: fieldLabel }\n )}\n </Typography>\n {selection === 'multiple' && instances.length > 1 && (\n <Checkbox\n checked={areAllSelected}\n onCheckedChange={(checked) =>\n setSelectedPaths(\n checked === true ? instances.map((instance) => instance.sourcePath) : []\n )\n }\n >\n {formatMessage({\n id: getTranslation('components.ComponentCopyModal.selectAll'),\n defaultMessage: 'Select all',\n })}\n </Checkbox>\n )}\n </PreviewHeader>\n <Scrollable direction=\"column\" alignItems=\"stretch\" gap={3} padding={5}>\n <InstancePicker\n fieldLabel={fieldLabel}\n instances={instances}\n onSelectedPathsChange={setSelectedPaths}\n renderSummary={renderInstanceSummary}\n selectedPaths={selectedPaths}\n selection={selection}\n />\n </Scrollable>\n </>\n );\n };\n\n return (\n <Modal.Root open onOpenChange={(isOpen) => !isOpen && onClose()}>\n <ModalContent\n onCloseAutoFocus={(event) => {\n // The modal has no trigger of its own to give the focus back to\n if (returnFocusTarget?.isConnected) {\n event.preventDefault();\n returnFocusTarget.focus();\n }\n }}\n onEscapeKeyDown={(event) => {\n // Escape in a filled search only clears it, which the searchbar does itself\n if (search !== '' && event.target === searchRef.current) {\n event.preventDefault();\n }\n }}\n >\n <Modal.Header>\n <Modal.Title>{title}</Modal.Title>\n </Modal.Header>\n <Panes>\n <EntriesPane\n appliedSearch={debouncedSearch}\n isLoading={isLoadingEntries}\n // Picking a second entry while one loads would start a race between the two.\n isSelectionLocked={isFetchingDocument || isCopying}\n onSearchChange={setSearch}\n onSelect={handleSelectEntry}\n rows={entryRows}\n search={search}\n searchRef={searchRef}\n selectedDocumentId={selectedEntry?.documentId ?? null}\n />\n <PreviewPane direction=\"column\" alignItems=\"stretch\">\n {renderPreview()}\n </PreviewPane>\n </Panes>\n <ModalFooter gap={4}>\n {renderFooterNote()}\n <Flex gap={2} shrink={0}>\n <Modal.Close>\n <Button variant=\"tertiary\">\n {formatMessage({\n id: 'app.components.Button.cancel',\n defaultMessage: 'Cancel',\n })}\n </Button>\n </Modal.Close>\n <Button\n onClick={handleConfirm}\n disabled={selectedInstances.length === 0 || isSelectionTooLarge}\n loading={isCopying}\n >\n {getConfirmLabel()}\n </Button>\n </Flex>\n </ModalFooter>\n </ModalContent>\n </Modal.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * getReturnFocusTarget\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @description The element to focus once the modal is closed: the button that opened it, or when\n * it was opened from a menu item, the button of the menu (the menu is gone by then).\n */\nconst getReturnFocusTarget = (): HTMLElement | null => {\n const active = document.activeElement;\n\n if (!(active instanceof HTMLElement) || active === document.body) {\n return null;\n }\n\n const menu = active.closest<HTMLElement>('[role=\"menu\"]');\n\n if (!menu) {\n return active;\n }\n\n return menu.id\n ? document.querySelector<HTMLElement>(`[aria-controls=\"${CSS.escape(menu.id)}\"]`)\n : null;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * EntriesPane\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EntriesPaneProps {\n /**\n * The search the list reflects: the typed search, debounced.\n */\n appliedSearch: string;\n isLoading: boolean;\n /**\n * Whether picking an entry is temporarily refused, e.g. while one loads.\n */\n isSelectionLocked: boolean;\n onSearchChange: (search: string) => void;\n onSelect: (row: EntryRow) => void;\n rows: EntryRow[];\n search: string;\n searchRef: React.RefObject<HTMLInputElement>;\n selectedDocumentId: string | null;\n}\n\n/**\n * The left pane of the modal: the search and the list of entries to copy from.\n */\nconst EntriesPane = ({\n appliedSearch,\n isLoading,\n isSelectionLocked,\n onSearchChange,\n onSelect,\n rows,\n search,\n searchRef,\n selectedDocumentId,\n}: EntriesPaneProps) => {\n const { formatMessage } = useIntl();\n const normalizedSearch = appliedSearch.trim();\n const searchLabel = formatMessage({\n id: getTranslation('components.ComponentCopyModal.search'),\n defaultMessage: 'Search all entries',\n });\n\n const renderRows = () => {\n if (isLoading) {\n return (\n <Flex justifyContent=\"center\" padding={4}>\n <Loader small>\n {formatMessage({\n id: getTranslation('components.ComponentCopyModal.loading'),\n defaultMessage: 'Loading',\n })}\n </Loader>\n </Flex>\n );\n }\n\n if (rows.length === 0) {\n return (\n <Box padding={2}>\n <Typography variant=\"omega\" textColor=\"neutral600\">\n {normalizedSearch\n ? formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.entries.noMatch'),\n defaultMessage: 'No entry matches “{search}”',\n },\n { search: normalizedSearch }\n )\n : formatMessage({\n id: getTranslation('components.ComponentCopyModal.noEntries'),\n defaultMessage: 'No entries found',\n })}\n </Typography>\n </Box>\n );\n }\n\n // While locked, the entries aren't `disabled`: the picked one keeps the focus while it loads.\n return rows.map((row) => (\n <EntryButton\n key={row.documentId}\n type=\"button\"\n aria-pressed={row.documentId === selectedDocumentId}\n aria-disabled={isSelectionLocked || undefined}\n disabled={row.disabled}\n onClick={() => {\n if (!isSelectionLocked) {\n onSelect(row);\n }\n }}\n >\n <Flex gap={2} alignItems=\"center\" wrap=\"wrap\">\n <Typography fontWeight=\"bold\" textColor=\"inherit\">\n {row.title}\n </Typography>\n {row.isCurrent && (\n <Badge size=\"S\" active>\n {formatMessage({\n id: getTranslation('components.ComponentCopyModal.entries.current'),\n defaultMessage: 'This entry',\n })}\n </Badge>\n )}\n </Flex>\n {row.meta && (\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {row.meta}\n </Typography>\n )}\n </EntryButton>\n ));\n };\n\n return (\n <EntriesPaneRoot direction=\"column\" alignItems=\"stretch\">\n <Box paddingTop={4} paddingBottom={2} paddingLeft={4} paddingRight={4}>\n <Searchbar\n ref={searchRef}\n name=\"component-copy-search\"\n value={search}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) =>\n onSearchChange(event.target.value)\n }\n onClear={() => onSearchChange('')}\n clearLabel={formatMessage({\n id: 'clearLabel',\n defaultMessage: 'Clear',\n })}\n placeholder={searchLabel}\n size=\"S\"\n >\n {searchLabel}\n </Searchbar>\n </Box>\n {!normalizedSearch && (\n <Box paddingLeft={4} paddingRight={4} paddingBottom={1}>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('components.ComponentCopyModal.entries.title'),\n defaultMessage: 'Recently updated entries',\n })}\n </Typography>\n </Box>\n )}\n <Scrollable direction=\"column\" alignItems=\"stretch\" gap={1} padding={2}>\n {renderRows()}\n </Scrollable>\n </EntriesPaneRoot>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * InstancePicker\n * -----------------------------------------------------------------------------------------------*/\n\ninterface InstancePickerProps {\n fieldLabel: string;\n instances: ComponentInstance[];\n onSelectedPathsChange: (paths: string[]) => void;\n renderSummary: (instance: ComponentInstance, titleId: string) => React.ReactNode;\n selectedPaths: string[];\n selection: ComponentCopySelection;\n}\n\n/**\n * The components of the picked entry: a read-only card when there's one to take, radios when one\n * of several is taken, checkboxes when several can be taken.\n */\nconst InstancePicker = ({\n fieldLabel,\n instances,\n onSelectedPathsChange,\n renderSummary,\n selectedPaths,\n selection,\n}: InstancePickerProps) => {\n const { formatMessage } = useIntl();\n const radioTitleId = React.useId();\n\n if (instances.length === 0) {\n return (\n <Typography variant=\"omega\" textColor=\"neutral600\">\n {formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.preview.noComponents'),\n defaultMessage: 'No {label} in this entry',\n },\n { label: fieldLabel }\n )}\n </Typography>\n );\n }\n\n if (selection === 'single' && instances.length === 1) {\n return (\n <InstanceCard $selected>{renderSummary(instances[0], `${radioTitleId}-0`)}</InstanceCard>\n );\n }\n\n if (selection === 'single') {\n return (\n <Radio.Group\n value={selectedPaths[0] ?? ''}\n onValueChange={(value: string) => onSelectedPathsChange([value])}\n >\n {instances.map((instance, index) => {\n const titleId = `${radioTitleId}-${index}`;\n\n return (\n <InstanceCard\n key={instance.sourcePath}\n $selected={selectedPaths.includes(instance.sourcePath)}\n >\n <Radio.Item value={instance.sourcePath} aria-labelledby={titleId}>\n {renderSummary(instance, titleId)}\n </Radio.Item>\n </InstanceCard>\n );\n })}\n </Radio.Group>\n );\n }\n\n const togglePath = (sourcePath: string, checked: boolean) => {\n onSelectedPathsChange(\n checked\n ? [...selectedPaths.filter((path) => path !== sourcePath), sourcePath]\n : selectedPaths.filter((path) => path !== sourcePath)\n );\n };\n\n return (\n <>\n {instances.map((instance) => (\n <SelectableInstanceCard\n key={instance.sourcePath}\n checked={selectedPaths.includes(instance.sourcePath)}\n onCheckedChange={(checked) => togglePath(instance.sourcePath, checked)}\n renderSummary={(titleId) => renderSummary(instance, titleId)}\n />\n ))}\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * InstanceSummary\n * -----------------------------------------------------------------------------------------------*/\n\ninterface InstanceSummaryProps {\n instance: ComponentInstance;\n preview: ComponentPreviewField[];\n /**\n * The id given to the title, for the control picking the component to be named after it.\n */\n titleId: string;\n}\n\nconst InstanceSummary = ({ instance, preview, titleId }: InstanceSummaryProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex tag=\"span\" direction=\"column\" alignItems=\"stretch\" gap={2} grow={1} minWidth={0}>\n <Flex tag=\"span\" gap={2} alignItems=\"baseline\" wrap=\"wrap\">\n <Typography tag=\"span\" id={titleId} fontWeight=\"bold\" textColor=\"neutral800\">\n {instance.label}\n </Typography>\n {instance.parentLabel && (\n <Typography tag=\"span\" variant=\"pi\" textColor=\"neutral600\">\n {formatMessage(\n {\n id: getTranslation('components.ComponentCopyModal.instance.nested'),\n defaultMessage: 'In {parent}',\n },\n { parent: instance.parentLabel }\n )}\n </Typography>\n )}\n </Flex>\n {preview.length > 0 && (\n <PreviewGrid tag=\"span\">\n {preview.map((field) => (\n <Flex tag=\"span\" key={field.name} direction=\"column\" alignItems=\"stretch\" minWidth={0}>\n <Typography tag=\"span\" variant=\"sigma\" textColor=\"neutral600\">\n {field.label}\n </Typography>\n <Typography tag=\"span\" variant=\"omega\" textColor=\"neutral800\" ellipsis>\n <CellValue type={field.type} value={field.value} />\n </Typography>\n </Flex>\n ))}\n </PreviewGrid>\n )}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * SelectableInstanceCard\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SelectableInstanceCardProps {\n checked: boolean;\n onCheckedChange: (checked: boolean) => void;\n renderSummary: (titleId: string) => React.ReactNode;\n}\n\n/**\n * The whole card toggles its checkbox. The checkbox is named after the title of the component\n * only, not after the whole preview.\n */\nconst SelectableInstanceCard = ({\n checked,\n onCheckedChange,\n renderSummary,\n}: SelectableInstanceCardProps) => {\n const id = React.useId();\n const titleId = `${id}-title`;\n\n return (\n <InstanceCard tag=\"label\" htmlFor={id} $selected={checked} $interactive>\n <Flex tag=\"span\" gap={3} alignItems=\"flex-start\">\n <Checkbox\n id={id}\n aria-labelledby={titleId}\n checked={checked}\n onCheckedChange={(value) => onCheckedChange(value === true)}\n />\n {renderSummary(titleId)}\n </Flex>\n </InstanceCard>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Styles\n * -----------------------------------------------------------------------------------------------*/\n\nconst FooterWarning = ({ children }: { children: React.ReactNode }) => (\n <Flex gap={2} alignItems=\"center\" color=\"warning600\">\n <WarningCircle width=\"1.6rem\" height=\"1.6rem\" aria-hidden />\n <Typography variant=\"pi\" textColor=\"warning600\">\n {children}\n </Typography>\n </Flex>\n);\n\nconst ModalContent = styled(Modal.Content)`\n width: 92rem;\n max-width: calc(100% - ${({ theme }) => theme.spaces[8]});\n height: 60rem;\n`;\n\nconst ModalFooter = styled(Modal.Footer)`\n flex: 0 0 auto;\n`;\n\nconst Panes = styled.div`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n\n ${({ theme }) => theme.breakpoints.medium} {\n flex-direction: row;\n }\n`;\n\nconst EntriesPaneRoot = styled(Flex)`\n flex: 0 0 auto;\n max-height: 40%;\n min-height: 0;\n border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};\n\n ${({ theme }) => theme.breakpoints.medium} {\n width: 30rem;\n max-height: none;\n border-bottom: 0;\n border-right: 1px solid ${({ theme }) => theme.colors.neutral150};\n }\n`;\n\nconst PreviewPane = styled(Flex)`\n flex: 1;\n min-width: 0;\n min-height: 0;\n`;\n\nconst Scrollable = styled(Flex)`\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n`;\n\nconst PreviewHeader = styled(Flex)`\n border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\nconst EntryButton = styled.button`\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: ${({ theme }) => theme.spaces[1]};\n width: 100%;\n border: 1px solid transparent;\n border-radius: ${({ theme }) => theme.borderRadius};\n background: transparent;\n color: ${({ theme }) => theme.colors.neutral800};\n padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[3]};\n text-align: left;\n cursor: pointer;\n\n &:not(:disabled):not([aria-disabled='true']):hover {\n background: ${({ theme }) => theme.colors.neutral100};\n }\n\n &:not(:disabled):focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n\n &[aria-pressed='true'] {\n border-color: ${({ theme }) => theme.colors.primary200};\n background: ${({ theme }) => theme.colors.primary100};\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n cursor: not-allowed;\n color: ${({ theme }) => theme.colors.neutral500};\n }\n`;\n\nconst InstanceCard = styled(Box)<{ $selected?: boolean; $interactive?: boolean }>`\n display: block;\n border: 1px solid\n ${({ theme, $selected }) => ($selected ? theme.colors.primary600 : theme.colors.neutral200)};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme, $selected }) =>\n $selected ? theme.colors.primary100 : theme.colors.neutral100};\n padding: ${({ theme }) => theme.spaces[4]};\n cursor: ${({ $interactive }) => ($interactive ? 'pointer' : 'default')};\n\n @media (prefers-reduced-motion: no-preference) {\n transition:\n border-color 120ms ${({ theme }) => theme.motion.easings.easeOutQuad},\n background-color 120ms ${({ theme }) => theme.motion.easings.easeOutQuad};\n }\n\n &:hover {\n border-color: ${({ theme, $interactive, $selected }) =>\n $interactive && !$selected ? theme.colors.primary200 : undefined};\n }\n`;\n\nconst PreviewGrid = styled(Box)`\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));\n gap: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[4]};\n`;\n\nexport { ComponentCopyModal, getEntryMeta };\nexport type { ComponentCopyModalProps, ComponentCopySelection };\n"],"names":["ENTRIES_PAGE_SIZE","getDocumentTitle","document","mainField","fallback","untitled","value","undefined","String","trim","length","getEntryMeta","count","fieldLabel","firstInstanceLabel","formatMessage","isCurrent","isFormModified","selection","id","getTranslation","defaultMessage","label","ComponentCopyModal","componentUid","maxSelection","Infinity","mode","onClose","onInsert","replacesContent","sourceFieldName","useIntl","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","currentDocument","currentDocumentMeta","useDocumentContext","edit","components","componentLayouts","settings","useDocumentLayout","model","targetValues","useForm","state","values","modified","search","setSearch","React","useState","debouncedSearch","useDebounce","searchRef","useRef","selectedEntry","setSelectedEntry","sourceDocument","setSourceDocument","selectedPaths","setSelectedPaths","isCopying","setIsCopying","returnFocusTarget","getReturnFocusTarget","isMountedRef","selectedDocumentIdRef","useEffect","current","getDocuments","data","documentsData","error","documentsError","isFetching","isFetchingDocuments","isUninitialized","isDocumentsQueryUninitialized","useLazyGetAllDocumentsQuery","getDocument","isFetchingDocument","useLazyGetDocumentQuery","getAllRelations","useLazyGetAllRelationsQuery","componentDisplayName","info","displayName","currentDocumentId","documentId","savedDocument","isNestedField","toPath","collectionType","COLLECTION_TYPES","params","_q","page","pageSize","sort","type","message","findInstances","useCallback","getComponentInstances","getMainField","uid","schema","filterOwnInstance","instances","filter","instance","sourcePath","currentEntryInstances","useMemo","getTitle","currentEntryTitle","normalizedSearch","toLowerCase","showCurrentEntry","includes","currentEntryRow","title","disabled","meta","entryRows","results","map","handleSelectEntry","row","result","isCurrentEntrySelected","paths","selectedInstances","areAllSelected","isSelectionTooLarge","previewFields","layout","flat","field","name","copyInstance","relations","getRelationsToCopy","source","loadedRelations","Promise","allSettled","targetField","unwrap","reduce","acc","index","status","connectRelations","path","cloneComponentData","__component","hasMissingRelations","some","getSuccessMessage","entry","component","handleConfirm","copies","all","getConfirmLabel","renderFooterNote","_jsx","FooterWarning","remaining","excess","Typography","variant","textColor","isLoadingEntries","isLoadingSource","loadingLabel","renderInstanceSummary","titleId","InstanceSummary","preview","getComponentPreview","renderPreview","_jsxs","Flex","direction","alignItems","justifyContent","gap","padding","grow","color","Duplicate","width","height","textAlign","Loader","small","_Fragment","PreviewHeader","paddingTop","paddingBottom","paddingLeft","paddingRight","fontWeight","ellipsis","Checkbox","checked","onCheckedChange","Scrollable","InstancePicker","onSelectedPathsChange","renderSummary","Modal","Root","open","onOpenChange","isOpen","ModalContent","onCloseAutoFocus","event","isConnected","preventDefault","focus","onEscapeKeyDown","target","Header","Title","Panes","EntriesPane","appliedSearch","isLoading","isSelectionLocked","onSearchChange","onSelect","rows","selectedDocumentId","PreviewPane","ModalFooter","shrink","Close","Button","onClick","loading","active","activeElement","HTMLElement","body","menu","closest","querySelector","CSS","escape","searchLabel","renderRows","Box","EntryButton","aria-pressed","aria-disabled","wrap","Badge","size","EntriesPaneRoot","Searchbar","ref","onChange","onClear","clearLabel","placeholder","radioTitleId","useId","InstanceCard","$selected","Radio","Group","onValueChange","Item","aria-labelledby","togglePath","SelectableInstanceCard","tag","minWidth","parentLabel","parent","PreviewGrid","CellValue","htmlFor","$interactive","children","WarningCircle","aria-hidden","styled","Content","theme","spaces","Footer","div","breakpoints","medium","colors","neutral150","button","borderRadius","neutral800","neutral100","primary600","primary200","primary100","neutral500","neutral200","motion","easings","easeOutQuad"],"mappings":"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"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
6
|
+
var fractionalIndexing = require('fractional-indexing');
|
|
7
|
+
var toPath = require('lodash/toPath');
|
|
8
|
+
var objects = require('../../../../../utils/objects.js');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
function _interopNamespace(e) {
|
|
13
|
+
if (e && e.__esModule) return e;
|
|
14
|
+
var n = Object.create(null);
|
|
15
|
+
if (e) {
|
|
16
|
+
Object.keys(e).forEach(function (k) {
|
|
17
|
+
if (k !== 'default') {
|
|
18
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
19
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return e[k]; }
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
n.default = e;
|
|
27
|
+
return Object.freeze(n);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
31
|
+
var toPath__default = /*#__PURE__*/_interopDefault(toPath);
|
|
32
|
+
|
|
33
|
+
/* -------------------------------------------------------------------------------------------------
|
|
34
|
+
* Key paths
|
|
35
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
36
|
+
* A component is identified by the temp keys of the rows leading to it, not by their indexes:
|
|
37
|
+
* `blocks.[a1].dishes.[a0]`. Rows keep their key when they're reordered, so the identity survives
|
|
38
|
+
* a move, and it's gone with the row when the row is deleted.
|
|
39
|
+
*/ const KEY_SEGMENT = /^\[(.+)\]$/;
|
|
40
|
+
const getTempKey = (row)=>objects.isObject(row) && typeof row.__temp_key__ === 'string' ? row.__temp_key__ : undefined;
|
|
41
|
+
/**
|
|
42
|
+
* @description Turns the name of a field into its key path: `blocks.1.dishes` becomes
|
|
43
|
+
* `blocks.[a1].dishes`, `a1` being the temp key of the second block.
|
|
44
|
+
*/ const getFieldKeyPath = (values, name)=>{
|
|
45
|
+
const segments = toPath__default.default(name);
|
|
46
|
+
return segments.map((segment, position)=>{
|
|
47
|
+
if (!objects.isInteger(segment)) {
|
|
48
|
+
return segment;
|
|
49
|
+
}
|
|
50
|
+
const key = getTempKey(objects.getIn(values, segments.slice(0, position + 1)));
|
|
51
|
+
return `[${key ?? segment}]`;
|
|
52
|
+
}).join('.');
|
|
53
|
+
};
|
|
54
|
+
const getComponentKeyPath = (fieldKeyPath, tempKey)=>`${fieldKeyPath}.[${tempKey}]`;
|
|
55
|
+
/**
|
|
56
|
+
* @description Returns the component at the given key path, if the form still holds it.
|
|
57
|
+
*/ const getComponentAt = (values, keyPath)=>{
|
|
58
|
+
let current = values;
|
|
59
|
+
for (const segment of keyPath.split('.')){
|
|
60
|
+
const keyMatch = KEY_SEGMENT.exec(segment);
|
|
61
|
+
if (keyMatch) {
|
|
62
|
+
current = Array.isArray(current) ? current.find((row)=>getTempKey(row) === keyMatch[1]) : undefined;
|
|
63
|
+
} else {
|
|
64
|
+
current = objects.isObject(current) ? current[segment] : undefined;
|
|
65
|
+
}
|
|
66
|
+
if (current === undefined || current === null) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return current;
|
|
71
|
+
};
|
|
72
|
+
/* -------------------------------------------------------------------------------------------------
|
|
73
|
+
* Copy marker
|
|
74
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
75
|
+
* Set on the components put in the form by a copy. Key paths aren't enough to recognise them:
|
|
76
|
+
* "Fill in from another locale" replaces the values with rows that reuse the same temp keys
|
|
77
|
+
* (`a0`, `a1`…), so a copy's key path can point to a component that wasn't copied. Editing a field
|
|
78
|
+
* clones the objects on its path with `lodash/clone`, which keeps symbol keys, while values that
|
|
79
|
+
* replace the component don't carry the marker. Symbol keys aren't serialised, so the marker never
|
|
80
|
+
* reaches the API.
|
|
81
|
+
*/ const COPIED = Symbol('copied');
|
|
82
|
+
const withCopyMarker = (item)=>({
|
|
83
|
+
...item,
|
|
84
|
+
[COPIED]: true
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* @description Tells whether the form still holds, at the given key path, the component that was
|
|
88
|
+
* copied there.
|
|
89
|
+
*/ const hasCopyAt = (values, keyPath)=>{
|
|
90
|
+
const component = getComponentAt(values, keyPath);
|
|
91
|
+
return objects.isObject(component) && component[COPIED] === true;
|
|
92
|
+
};
|
|
93
|
+
const [CopiedComponentsContextProvider, useCopiedComponentsContext] = strapiAdmin.createContext('CopiedComponents');
|
|
94
|
+
/**
|
|
95
|
+
* Remembers which components of the form were copied from another entry, so that they can be
|
|
96
|
+
* flagged until the entry is saved. The state lives above the fields: a field nested in a block
|
|
97
|
+
* is unmounted when the block collapses and would lose it otherwise. Must be rendered in a `Form`.
|
|
98
|
+
*/ const CopiedComponentsProvider = ({ children })=>{
|
|
99
|
+
const [copiedPaths, setCopiedPaths] = React__namespace.useState([]);
|
|
100
|
+
const values = strapiAdmin.useForm('CopiedComponentsProvider', (state)=>state.values);
|
|
101
|
+
const isFormModified = strapiAdmin.useForm('CopiedComponentsProvider', (state)=>state.modified);
|
|
102
|
+
// Saving the entry, or undoing every change, clears the flags.
|
|
103
|
+
React__namespace.useEffect(()=>{
|
|
104
|
+
if (!isFormModified) {
|
|
105
|
+
setCopiedPaths((paths)=>paths.length > 0 ? [] : paths);
|
|
106
|
+
}
|
|
107
|
+
}, [
|
|
108
|
+
isFormModified
|
|
109
|
+
]);
|
|
110
|
+
// A copied component that's removed or replaced (e.g. by "Fill in from another locale") drops its
|
|
111
|
+
// flag, so that a component put at the same key path can't inherit it.
|
|
112
|
+
React__namespace.useEffect(()=>{
|
|
113
|
+
setCopiedPaths((paths)=>{
|
|
114
|
+
const kept = paths.filter((path)=>hasCopyAt(values, path));
|
|
115
|
+
return kept.length === paths.length ? paths : kept;
|
|
116
|
+
});
|
|
117
|
+
}, [
|
|
118
|
+
values
|
|
119
|
+
]);
|
|
120
|
+
const markCopied = React__namespace.useCallback((keyPaths)=>{
|
|
121
|
+
setCopiedPaths((paths)=>{
|
|
122
|
+
const added = keyPaths.filter((keyPath)=>!paths.includes(keyPath));
|
|
123
|
+
return added.length > 0 ? [
|
|
124
|
+
...paths,
|
|
125
|
+
...added
|
|
126
|
+
] : paths;
|
|
127
|
+
});
|
|
128
|
+
}, []);
|
|
129
|
+
return /*#__PURE__*/ jsxRuntime.jsx(CopiedComponentsContextProvider, {
|
|
130
|
+
copiedPaths: copiedPaths,
|
|
131
|
+
markCopied: markCopied,
|
|
132
|
+
children: children
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
/* -------------------------------------------------------------------------------------------------
|
|
136
|
+
* useCopiedComponents
|
|
137
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
138
|
+
* @description Inserts copied components in a repeatable component or a dynamic zone field and
|
|
139
|
+
* tells which of its rows are copies. Without a `CopiedComponentsProvider` the copies are still
|
|
140
|
+
* inserted, they're just not flagged.
|
|
141
|
+
*/ const useCopiedComponents = (name)=>{
|
|
142
|
+
const copiedPaths = useCopiedComponentsContext('useCopiedComponents', (state)=>state.copiedPaths, false);
|
|
143
|
+
const markCopied = useCopiedComponentsContext('useCopiedComponents', (state)=>state.markCopied, false);
|
|
144
|
+
const { value, onChange } = strapiAdmin.useField(name);
|
|
145
|
+
const fieldKeyPath = strapiAdmin.useForm('useCopiedComponents', (state)=>getFieldKeyPath(state.values, name));
|
|
146
|
+
const isCopied = React__namespace.useCallback((tempKey)=>copiedPaths?.includes(getComponentKeyPath(fieldKeyPath, tempKey)) ?? false, [
|
|
147
|
+
copiedPaths,
|
|
148
|
+
fieldKeyPath
|
|
149
|
+
]);
|
|
150
|
+
/**
|
|
151
|
+
* The rows are added with their keys already set, so the copies are flagged by key rather than
|
|
152
|
+
* recognised among the rows that appear next.
|
|
153
|
+
*/ const insertCopies = React__namespace.useCallback((items)=>{
|
|
154
|
+
const rows = Array.isArray(value) ? value : [];
|
|
155
|
+
const lastKey = rows.map(getTempKey).filter((key)=>key !== undefined && key !== '').sort().pop() ?? null;
|
|
156
|
+
const keys = fractionalIndexing.generateNKeysBetween(lastKey, null, items.length);
|
|
157
|
+
onChange(name, [
|
|
158
|
+
...rows,
|
|
159
|
+
...items.map((item, index)=>withCopyMarker({
|
|
160
|
+
...item,
|
|
161
|
+
__temp_key__: keys[index]
|
|
162
|
+
}))
|
|
163
|
+
]);
|
|
164
|
+
markCopied?.(keys.map((key)=>getComponentKeyPath(fieldKeyPath, key)));
|
|
165
|
+
}, [
|
|
166
|
+
fieldKeyPath,
|
|
167
|
+
markCopied,
|
|
168
|
+
name,
|
|
169
|
+
onChange,
|
|
170
|
+
value
|
|
171
|
+
]);
|
|
172
|
+
return {
|
|
173
|
+
isCopied,
|
|
174
|
+
insertCopies
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
/* -------------------------------------------------------------------------------------------------
|
|
178
|
+
* useCopiedComponent
|
|
179
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
180
|
+
* @description Puts a copied component in a non-repeatable component field and tells whether the
|
|
181
|
+
* field holds a copy. The flag is set on the field itself: resetting the field drops it, so a
|
|
182
|
+
* component added afterwards isn't flagged. Without a `CopiedComponentsProvider` the copy is still
|
|
183
|
+
* put in place, it's just not flagged.
|
|
184
|
+
*/ const useCopiedComponent = (name)=>{
|
|
185
|
+
const copiedPaths = useCopiedComponentsContext('useCopiedComponent', (state)=>state.copiedPaths, false);
|
|
186
|
+
const markCopied = useCopiedComponentsContext('useCopiedComponent', (state)=>state.markCopied, false);
|
|
187
|
+
const { onChange } = strapiAdmin.useField(name);
|
|
188
|
+
const fieldKeyPath = strapiAdmin.useForm('useCopiedComponent', (state)=>getFieldKeyPath(state.values, name));
|
|
189
|
+
const isCopied = copiedPaths?.includes(fieldKeyPath) ?? false;
|
|
190
|
+
const insertCopy = React__namespace.useCallback((item)=>{
|
|
191
|
+
onChange(name, withCopyMarker(item));
|
|
192
|
+
markCopied?.([
|
|
193
|
+
fieldKeyPath
|
|
194
|
+
]);
|
|
195
|
+
}, [
|
|
196
|
+
fieldKeyPath,
|
|
197
|
+
markCopied,
|
|
198
|
+
name,
|
|
199
|
+
onChange
|
|
200
|
+
]);
|
|
201
|
+
return {
|
|
202
|
+
isCopied,
|
|
203
|
+
insertCopy
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
exports.CopiedComponentsProvider = CopiedComponentsProvider;
|
|
208
|
+
exports.getFieldKeyPath = getFieldKeyPath;
|
|
209
|
+
exports.useCopiedComponent = useCopiedComponent;
|
|
210
|
+
exports.useCopiedComponents = useCopiedComponents;
|
|
211
|
+
//# sourceMappingURL=CopiedComponents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopiedComponents.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/CopiedComponents.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { createContext, useField, useForm } from '@strapi/admin/strapi-admin';\nimport { generateNKeysBetween } from 'fractional-indexing';\nimport toPath from 'lodash/toPath';\n\nimport { getIn, isInteger, isObject } from '../../../../../utils/objects';\n\nimport type { AnyData } from '../../../utils/data';\n\n/* -------------------------------------------------------------------------------------------------\n * Key paths\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * A component is identified by the temp keys of the rows leading to it, not by their indexes:\n * `blocks.[a1].dishes.[a0]`. Rows keep their key when they're reordered, so the identity survives\n * a move, and it's gone with the row when the row is deleted.\n */\nconst KEY_SEGMENT = /^\\[(.+)\\]$/;\n\nconst getTempKey = (row: unknown): string | undefined =>\n isObject(row) && typeof row.__temp_key__ === 'string' ? row.__temp_key__ : undefined;\n\n/**\n * @description Turns the name of a field into its key path: `blocks.1.dishes` becomes\n * `blocks.[a1].dishes`, `a1` being the temp key of the second block.\n */\nconst getFieldKeyPath = (values: unknown, name: string): string => {\n const segments = toPath(name);\n\n return segments\n .map((segment, position) => {\n if (!isInteger(segment)) {\n return segment;\n }\n\n const key = getTempKey(getIn(values, segments.slice(0, position + 1)));\n\n return `[${key ?? segment}]`;\n })\n .join('.');\n};\n\nconst getComponentKeyPath = (fieldKeyPath: string, tempKey: string) =>\n `${fieldKeyPath}.[${tempKey}]`;\n\n/**\n * @description Returns the component at the given key path, if the form still holds it.\n */\nconst getComponentAt = (values: unknown, keyPath: string): unknown => {\n let current: unknown = values;\n\n for (const segment of keyPath.split('.')) {\n const keyMatch = KEY_SEGMENT.exec(segment);\n\n if (keyMatch) {\n current = Array.isArray(current)\n ? current.find((row) => getTempKey(row) === keyMatch[1])\n : undefined;\n } else {\n current = isObject(current) ? current[segment] : undefined;\n }\n\n if (current === undefined || current === null) {\n return undefined;\n }\n }\n\n return current;\n};\n\n/**\n * @description Tells whether the form still holds the component at the given key path.\n */\nconst hasComponentAt = (values: unknown, keyPath: string): boolean =>\n getComponentAt(values, keyPath) !== undefined;\n\n/* -------------------------------------------------------------------------------------------------\n * Copy marker\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * Set on the components put in the form by a copy. Key paths aren't enough to recognise them:\n * \"Fill in from another locale\" replaces the values with rows that reuse the same temp keys\n * (`a0`, `a1`…), so a copy's key path can point to a component that wasn't copied. Editing a field\n * clones the objects on its path with `lodash/clone`, which keeps symbol keys, while values that\n * replace the component don't carry the marker. Symbol keys aren't serialised, so the marker never\n * reaches the API.\n */\nconst COPIED = Symbol('copied');\n\nconst withCopyMarker = (item: AnyData): AnyData => ({ ...item, [COPIED]: true });\n\n/**\n * @description Tells whether the form still holds, at the given key path, the component that was\n * copied there.\n */\nconst hasCopyAt = (values: unknown, keyPath: string): boolean => {\n const component = getComponentAt(values, keyPath);\n\n return isObject(component) && (component as Record<symbol, unknown>)[COPIED] === true;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * CopiedComponentsProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CopiedComponentsContextValue {\n /**\n * The key paths of the components copied from another entry since the form was last saved.\n */\n copiedPaths: string[];\n markCopied: (keyPaths: string[]) => void;\n}\n\nconst [CopiedComponentsContextProvider, useCopiedComponentsContext] =\n createContext<CopiedComponentsContextValue>('CopiedComponents');\n\ninterface CopiedComponentsProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Remembers which components of the form were copied from another entry, so that they can be\n * flagged until the entry is saved. The state lives above the fields: a field nested in a block\n * is unmounted when the block collapses and would lose it otherwise. Must be rendered in a `Form`.\n */\nconst CopiedComponentsProvider = ({ children }: CopiedComponentsProviderProps) => {\n const [copiedPaths, setCopiedPaths] = React.useState<string[]>([]);\n const values = useForm('CopiedComponentsProvider', (state) => state.values);\n const isFormModified = useForm('CopiedComponentsProvider', (state) => state.modified);\n\n // Saving the entry, or undoing every change, clears the flags.\n React.useEffect(() => {\n if (!isFormModified) {\n setCopiedPaths((paths) => (paths.length > 0 ? [] : paths));\n }\n }, [isFormModified]);\n\n // A copied component that's removed or replaced (e.g. by \"Fill in from another locale\") drops its\n // flag, so that a component put at the same key path can't inherit it.\n React.useEffect(() => {\n setCopiedPaths((paths) => {\n const kept = paths.filter((path) => hasCopyAt(values, path));\n\n return kept.length === paths.length ? paths : kept;\n });\n }, [values]);\n\n const markCopied = React.useCallback((keyPaths: string[]) => {\n setCopiedPaths((paths) => {\n const added = keyPaths.filter((keyPath) => !paths.includes(keyPath));\n\n return added.length > 0 ? [...paths, ...added] : paths;\n });\n }, []);\n\n return (\n <CopiedComponentsContextProvider copiedPaths={copiedPaths} markCopied={markCopied}>\n {children}\n </CopiedComponentsContextProvider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useCopiedComponents\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @description Inserts copied components in a repeatable component or a dynamic zone field and\n * tells which of its rows are copies. Without a `CopiedComponentsProvider` the copies are still\n * inserted, they're just not flagged.\n */\nconst useCopiedComponents = (name: string) => {\n const copiedPaths = useCopiedComponentsContext(\n 'useCopiedComponents',\n (state) => state.copiedPaths,\n false\n );\n const markCopied = useCopiedComponentsContext(\n 'useCopiedComponents',\n (state) => state.markCopied,\n false\n );\n const { value, onChange } = useField<AnyData[] | null>(name);\n const fieldKeyPath = useForm('useCopiedComponents', (state) =>\n getFieldKeyPath(state.values, name)\n );\n\n const isCopied = React.useCallback(\n (tempKey: string) => copiedPaths?.includes(getComponentKeyPath(fieldKeyPath, tempKey)) ?? false,\n [copiedPaths, fieldKeyPath]\n );\n\n /**\n * The rows are added with their keys already set, so the copies are flagged by key rather than\n * recognised among the rows that appear next.\n */\n const insertCopies = React.useCallback(\n (items: AnyData[]) => {\n const rows = Array.isArray(value) ? value : [];\n const lastKey =\n rows\n .map(getTempKey)\n .filter((key): key is string => key !== undefined && key !== '')\n .sort()\n .pop() ?? null;\n const keys = generateNKeysBetween(lastKey, null, items.length);\n\n onChange(name, [\n ...rows,\n ...items.map((item, index) => withCopyMarker({ ...item, __temp_key__: keys[index] })),\n ]);\n markCopied?.(keys.map((key) => getComponentKeyPath(fieldKeyPath, key)));\n },\n [fieldKeyPath, markCopied, name, onChange, value]\n );\n\n return { isCopied, insertCopies };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * useCopiedComponent\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * @description Puts a copied component in a non-repeatable component field and tells whether the\n * field holds a copy. The flag is set on the field itself: resetting the field drops it, so a\n * component added afterwards isn't flagged. Without a `CopiedComponentsProvider` the copy is still\n * put in place, it's just not flagged.\n */\nconst useCopiedComponent = (name: string) => {\n const copiedPaths = useCopiedComponentsContext(\n 'useCopiedComponent',\n (state) => state.copiedPaths,\n false\n );\n const markCopied = useCopiedComponentsContext(\n 'useCopiedComponent',\n (state) => state.markCopied,\n false\n );\n const { onChange } = useField<AnyData | null>(name);\n const fieldKeyPath = useForm('useCopiedComponent', (state) =>\n getFieldKeyPath(state.values, name)\n );\n\n const isCopied = copiedPaths?.includes(fieldKeyPath) ?? false;\n\n const insertCopy = React.useCallback(\n (item: AnyData) => {\n onChange(name, withCopyMarker(item));\n markCopied?.([fieldKeyPath]);\n },\n [fieldKeyPath, markCopied, name, onChange]\n );\n\n return { isCopied, insertCopy };\n};\n\nexport {\n CopiedComponentsProvider,\n useCopiedComponents,\n useCopiedComponent,\n getFieldKeyPath,\n hasComponentAt,\n};\nexport type { CopiedComponentsProviderProps };\n"],"names":["KEY_SEGMENT","getTempKey","row","isObject","__temp_key__","undefined","getFieldKeyPath","values","name","segments","toPath","map","segment","position","isInteger","key","getIn","slice","join","getComponentKeyPath","fieldKeyPath","tempKey","getComponentAt","keyPath","current","split","keyMatch","exec","Array","isArray","find","COPIED","Symbol","withCopyMarker","item","hasCopyAt","component","CopiedComponentsContextProvider","useCopiedComponentsContext","createContext","CopiedComponentsProvider","children","copiedPaths","setCopiedPaths","React","useState","useForm","state","isFormModified","modified","useEffect","paths","length","kept","filter","path","markCopied","useCallback","keyPaths","added","includes","_jsx","useCopiedComponents","value","onChange","useField","isCopied","insertCopies","items","rows","lastKey","sort","pop","keys","generateNKeysBetween","index","useCopiedComponent","insertCopy"],"mappings":"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"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { createContext, useField, useForm } from '@strapi/admin/strapi-admin';
|
|
4
|
+
import { generateNKeysBetween } from 'fractional-indexing';
|
|
5
|
+
import toPath from 'lodash/toPath';
|
|
6
|
+
import { isInteger, getIn, isObject } from '../../../../../utils/objects.mjs';
|
|
7
|
+
|
|
8
|
+
/* -------------------------------------------------------------------------------------------------
|
|
9
|
+
* Key paths
|
|
10
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
11
|
+
* A component is identified by the temp keys of the rows leading to it, not by their indexes:
|
|
12
|
+
* `blocks.[a1].dishes.[a0]`. Rows keep their key when they're reordered, so the identity survives
|
|
13
|
+
* a move, and it's gone with the row when the row is deleted.
|
|
14
|
+
*/ const KEY_SEGMENT = /^\[(.+)\]$/;
|
|
15
|
+
const getTempKey = (row)=>isObject(row) && typeof row.__temp_key__ === 'string' ? row.__temp_key__ : undefined;
|
|
16
|
+
/**
|
|
17
|
+
* @description Turns the name of a field into its key path: `blocks.1.dishes` becomes
|
|
18
|
+
* `blocks.[a1].dishes`, `a1` being the temp key of the second block.
|
|
19
|
+
*/ const getFieldKeyPath = (values, name)=>{
|
|
20
|
+
const segments = toPath(name);
|
|
21
|
+
return segments.map((segment, position)=>{
|
|
22
|
+
if (!isInteger(segment)) {
|
|
23
|
+
return segment;
|
|
24
|
+
}
|
|
25
|
+
const key = getTempKey(getIn(values, segments.slice(0, position + 1)));
|
|
26
|
+
return `[${key ?? segment}]`;
|
|
27
|
+
}).join('.');
|
|
28
|
+
};
|
|
29
|
+
const getComponentKeyPath = (fieldKeyPath, tempKey)=>`${fieldKeyPath}.[${tempKey}]`;
|
|
30
|
+
/**
|
|
31
|
+
* @description Returns the component at the given key path, if the form still holds it.
|
|
32
|
+
*/ const getComponentAt = (values, keyPath)=>{
|
|
33
|
+
let current = values;
|
|
34
|
+
for (const segment of keyPath.split('.')){
|
|
35
|
+
const keyMatch = KEY_SEGMENT.exec(segment);
|
|
36
|
+
if (keyMatch) {
|
|
37
|
+
current = Array.isArray(current) ? current.find((row)=>getTempKey(row) === keyMatch[1]) : undefined;
|
|
38
|
+
} else {
|
|
39
|
+
current = isObject(current) ? current[segment] : undefined;
|
|
40
|
+
}
|
|
41
|
+
if (current === undefined || current === null) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return current;
|
|
46
|
+
};
|
|
47
|
+
/* -------------------------------------------------------------------------------------------------
|
|
48
|
+
* Copy marker
|
|
49
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
50
|
+
* Set on the components put in the form by a copy. Key paths aren't enough to recognise them:
|
|
51
|
+
* "Fill in from another locale" replaces the values with rows that reuse the same temp keys
|
|
52
|
+
* (`a0`, `a1`…), so a copy's key path can point to a component that wasn't copied. Editing a field
|
|
53
|
+
* clones the objects on its path with `lodash/clone`, which keeps symbol keys, while values that
|
|
54
|
+
* replace the component don't carry the marker. Symbol keys aren't serialised, so the marker never
|
|
55
|
+
* reaches the API.
|
|
56
|
+
*/ const COPIED = Symbol('copied');
|
|
57
|
+
const withCopyMarker = (item)=>({
|
|
58
|
+
...item,
|
|
59
|
+
[COPIED]: true
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* @description Tells whether the form still holds, at the given key path, the component that was
|
|
63
|
+
* copied there.
|
|
64
|
+
*/ const hasCopyAt = (values, keyPath)=>{
|
|
65
|
+
const component = getComponentAt(values, keyPath);
|
|
66
|
+
return isObject(component) && component[COPIED] === true;
|
|
67
|
+
};
|
|
68
|
+
const [CopiedComponentsContextProvider, useCopiedComponentsContext] = createContext('CopiedComponents');
|
|
69
|
+
/**
|
|
70
|
+
* Remembers which components of the form were copied from another entry, so that they can be
|
|
71
|
+
* flagged until the entry is saved. The state lives above the fields: a field nested in a block
|
|
72
|
+
* is unmounted when the block collapses and would lose it otherwise. Must be rendered in a `Form`.
|
|
73
|
+
*/ const CopiedComponentsProvider = ({ children })=>{
|
|
74
|
+
const [copiedPaths, setCopiedPaths] = React.useState([]);
|
|
75
|
+
const values = useForm('CopiedComponentsProvider', (state)=>state.values);
|
|
76
|
+
const isFormModified = useForm('CopiedComponentsProvider', (state)=>state.modified);
|
|
77
|
+
// Saving the entry, or undoing every change, clears the flags.
|
|
78
|
+
React.useEffect(()=>{
|
|
79
|
+
if (!isFormModified) {
|
|
80
|
+
setCopiedPaths((paths)=>paths.length > 0 ? [] : paths);
|
|
81
|
+
}
|
|
82
|
+
}, [
|
|
83
|
+
isFormModified
|
|
84
|
+
]);
|
|
85
|
+
// A copied component that's removed or replaced (e.g. by "Fill in from another locale") drops its
|
|
86
|
+
// flag, so that a component put at the same key path can't inherit it.
|
|
87
|
+
React.useEffect(()=>{
|
|
88
|
+
setCopiedPaths((paths)=>{
|
|
89
|
+
const kept = paths.filter((path)=>hasCopyAt(values, path));
|
|
90
|
+
return kept.length === paths.length ? paths : kept;
|
|
91
|
+
});
|
|
92
|
+
}, [
|
|
93
|
+
values
|
|
94
|
+
]);
|
|
95
|
+
const markCopied = React.useCallback((keyPaths)=>{
|
|
96
|
+
setCopiedPaths((paths)=>{
|
|
97
|
+
const added = keyPaths.filter((keyPath)=>!paths.includes(keyPath));
|
|
98
|
+
return added.length > 0 ? [
|
|
99
|
+
...paths,
|
|
100
|
+
...added
|
|
101
|
+
] : paths;
|
|
102
|
+
});
|
|
103
|
+
}, []);
|
|
104
|
+
return /*#__PURE__*/ jsx(CopiedComponentsContextProvider, {
|
|
105
|
+
copiedPaths: copiedPaths,
|
|
106
|
+
markCopied: markCopied,
|
|
107
|
+
children: children
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
/* -------------------------------------------------------------------------------------------------
|
|
111
|
+
* useCopiedComponents
|
|
112
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
113
|
+
* @description Inserts copied components in a repeatable component or a dynamic zone field and
|
|
114
|
+
* tells which of its rows are copies. Without a `CopiedComponentsProvider` the copies are still
|
|
115
|
+
* inserted, they're just not flagged.
|
|
116
|
+
*/ const useCopiedComponents = (name)=>{
|
|
117
|
+
const copiedPaths = useCopiedComponentsContext('useCopiedComponents', (state)=>state.copiedPaths, false);
|
|
118
|
+
const markCopied = useCopiedComponentsContext('useCopiedComponents', (state)=>state.markCopied, false);
|
|
119
|
+
const { value, onChange } = useField(name);
|
|
120
|
+
const fieldKeyPath = useForm('useCopiedComponents', (state)=>getFieldKeyPath(state.values, name));
|
|
121
|
+
const isCopied = React.useCallback((tempKey)=>copiedPaths?.includes(getComponentKeyPath(fieldKeyPath, tempKey)) ?? false, [
|
|
122
|
+
copiedPaths,
|
|
123
|
+
fieldKeyPath
|
|
124
|
+
]);
|
|
125
|
+
/**
|
|
126
|
+
* The rows are added with their keys already set, so the copies are flagged by key rather than
|
|
127
|
+
* recognised among the rows that appear next.
|
|
128
|
+
*/ const insertCopies = React.useCallback((items)=>{
|
|
129
|
+
const rows = Array.isArray(value) ? value : [];
|
|
130
|
+
const lastKey = rows.map(getTempKey).filter((key)=>key !== undefined && key !== '').sort().pop() ?? null;
|
|
131
|
+
const keys = generateNKeysBetween(lastKey, null, items.length);
|
|
132
|
+
onChange(name, [
|
|
133
|
+
...rows,
|
|
134
|
+
...items.map((item, index)=>withCopyMarker({
|
|
135
|
+
...item,
|
|
136
|
+
__temp_key__: keys[index]
|
|
137
|
+
}))
|
|
138
|
+
]);
|
|
139
|
+
markCopied?.(keys.map((key)=>getComponentKeyPath(fieldKeyPath, key)));
|
|
140
|
+
}, [
|
|
141
|
+
fieldKeyPath,
|
|
142
|
+
markCopied,
|
|
143
|
+
name,
|
|
144
|
+
onChange,
|
|
145
|
+
value
|
|
146
|
+
]);
|
|
147
|
+
return {
|
|
148
|
+
isCopied,
|
|
149
|
+
insertCopies
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
/* -------------------------------------------------------------------------------------------------
|
|
153
|
+
* useCopiedComponent
|
|
154
|
+
* -----------------------------------------------------------------------------------------------*/ /**
|
|
155
|
+
* @description Puts a copied component in a non-repeatable component field and tells whether the
|
|
156
|
+
* field holds a copy. The flag is set on the field itself: resetting the field drops it, so a
|
|
157
|
+
* component added afterwards isn't flagged. Without a `CopiedComponentsProvider` the copy is still
|
|
158
|
+
* put in place, it's just not flagged.
|
|
159
|
+
*/ const useCopiedComponent = (name)=>{
|
|
160
|
+
const copiedPaths = useCopiedComponentsContext('useCopiedComponent', (state)=>state.copiedPaths, false);
|
|
161
|
+
const markCopied = useCopiedComponentsContext('useCopiedComponent', (state)=>state.markCopied, false);
|
|
162
|
+
const { onChange } = useField(name);
|
|
163
|
+
const fieldKeyPath = useForm('useCopiedComponent', (state)=>getFieldKeyPath(state.values, name));
|
|
164
|
+
const isCopied = copiedPaths?.includes(fieldKeyPath) ?? false;
|
|
165
|
+
const insertCopy = React.useCallback((item)=>{
|
|
166
|
+
onChange(name, withCopyMarker(item));
|
|
167
|
+
markCopied?.([
|
|
168
|
+
fieldKeyPath
|
|
169
|
+
]);
|
|
170
|
+
}, [
|
|
171
|
+
fieldKeyPath,
|
|
172
|
+
markCopied,
|
|
173
|
+
name,
|
|
174
|
+
onChange
|
|
175
|
+
]);
|
|
176
|
+
return {
|
|
177
|
+
isCopied,
|
|
178
|
+
insertCopy
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export { CopiedComponentsProvider, getFieldKeyPath, useCopiedComponent, useCopiedComponents };
|
|
183
|
+
//# sourceMappingURL=CopiedComponents.mjs.map
|