@strapi/upload 5.59.0 → 5.61.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/AssetPickerDialog/AssetPickerDialog.js +434 -0
- package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.js.map +1 -0
- package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.mjs +432 -0
- package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.mjs.map +1 -0
- package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.js +91 -0
- package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.js.map +1 -0
- package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.mjs +89 -0
- package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.mjs.map +1 -0
- package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.js +29 -0
- package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.js.map +1 -0
- package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.mjs +27 -0
- package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.mjs.map +1 -0
- package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.js +178 -0
- package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.js.map +1 -0
- package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.mjs +175 -0
- package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.mjs.map +1 -0
- package/dist/admin/components/AssetPickerDialog/SortableSelection.js +143 -0
- package/dist/admin/components/AssetPickerDialog/SortableSelection.js.map +1 -0
- package/dist/admin/components/AssetPickerDialog/SortableSelection.mjs +141 -0
- package/dist/admin/components/AssetPickerDialog/SortableSelection.mjs.map +1 -0
- package/dist/admin/components/AssetPickerDialog/pickerSelection.js +49 -0
- package/dist/admin/components/AssetPickerDialog/pickerSelection.js.map +1 -0
- package/dist/admin/components/AssetPickerDialog/pickerSelection.mjs +41 -0
- package/dist/admin/components/AssetPickerDialog/pickerSelection.mjs.map +1 -0
- package/dist/admin/components/Drawer.js +12 -7
- package/dist/admin/components/Drawer.js.map +1 -1
- package/dist/admin/components/Drawer.mjs +12 -7
- package/dist/admin/components/Drawer.mjs.map +1 -1
- package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.js +188 -0
- package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.js.map +1 -0
- package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.mjs +186 -0
- package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js +9 -4
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js.map +1 -1
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs +9 -4
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs.map +1 -1
- package/dist/admin/components/MediaLibraryInput/AssetCard.js +240 -0
- package/dist/admin/components/MediaLibraryInput/AssetCard.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetCard.mjs +237 -0
- package/dist/admin/components/MediaLibraryInput/AssetCard.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetCarousel.js +161 -0
- package/dist/admin/components/MediaLibraryInput/AssetCarousel.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetCarousel.mjs +159 -0
- package/dist/admin/components/MediaLibraryInput/AssetCarousel.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.js +76 -49
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.js.map +1 -1
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.mjs +77 -50
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.mjs.map +1 -1
- package/dist/admin/components/MediaLibraryInput/AssetPreview.js +109 -0
- package/dist/admin/components/MediaLibraryInput/AssetPreview.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetPreview.mjs +106 -0
- package/dist/admin/components/MediaLibraryInput/AssetPreview.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetRow.js +146 -79
- package/dist/admin/components/MediaLibraryInput/AssetRow.js.map +1 -1
- package/dist/admin/components/MediaLibraryInput/AssetRow.mjs +148 -82
- package/dist/admin/components/MediaLibraryInput/AssetRow.mjs.map +1 -1
- package/dist/admin/components/MediaLibraryInput/FieldControls.js +32 -0
- package/dist/admin/components/MediaLibraryInput/FieldControls.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/FieldControls.mjs +29 -0
- package/dist/admin/components/MediaLibraryInput/FieldControls.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js +163 -111
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -1
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs +162 -114
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -1
- package/dist/admin/components/MediaLibraryInput/UploadProgressBar.js +42 -0
- package/dist/admin/components/MediaLibraryInput/UploadProgressBar.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/UploadProgressBar.mjs +40 -0
- package/dist/admin/components/MediaLibraryInput/UploadProgressBar.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/openAssetDetails.js +46 -0
- package/dist/admin/components/MediaLibraryInput/openAssetDetails.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/openAssetDetails.mjs +43 -0
- package/dist/admin/components/MediaLibraryInput/openAssetDetails.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/useFieldUploads.js +122 -0
- package/dist/admin/components/MediaLibraryInput/useFieldUploads.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/useFieldUploads.mjs +120 -0
- package/dist/admin/components/MediaLibraryInput/useFieldUploads.mjs.map +1 -0
- package/dist/admin/components/UploadProgressDialog.js +2 -1
- package/dist/admin/components/UploadProgressDialog.js.map +1 -1
- package/dist/admin/components/UploadProgressDialog.mjs +2 -1
- package/dist/admin/components/UploadProgressDialog.mjs.map +1 -1
- package/dist/admin/hooks/useMediaLibraryPermissions.js +12 -2
- package/dist/admin/hooks/useMediaLibraryPermissions.js.map +1 -1
- package/dist/admin/hooks/useMediaLibraryPermissions.mjs +12 -2
- package/dist/admin/hooks/useMediaLibraryPermissions.mjs.map +1 -1
- package/dist/admin/index.js +10 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +10 -1
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/pages/Assets/AssetsPage.js +14 -303
- package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/pages/Assets/AssetsPage.mjs +13 -282
- package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +2 -2
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +181 -65
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +184 -69
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/AssetPreview.mjs +1 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.js +142 -31
- package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.mjs +145 -34
- package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsSearchInput.js +43 -2
- package/dist/admin/pages/Assets/components/AssetsSearchInput.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsSearchInput.mjs +45 -4
- package/dist/admin/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsTable.js +58 -34
- package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsTable.mjs +60 -36
- package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsView.js +145 -0
- package/dist/admin/pages/Assets/components/AssetsView.js.map +1 -0
- package/dist/admin/pages/Assets/components/AssetsView.mjs +143 -0
- package/dist/admin/pages/Assets/components/AssetsView.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/BulkActionsBar.mjs +1 -1
- package/dist/admin/pages/Assets/components/BusyOverlay.mjs +1 -1
- package/dist/admin/pages/Assets/components/Dnd/DragOverlayChip.mjs +1 -1
- package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.js +40 -0
- package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.js.map +1 -0
- package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.mjs +38 -0
- package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/Dnd/assetSortable.js +29 -0
- package/dist/admin/pages/Assets/components/Dnd/assetSortable.js.map +1 -0
- package/dist/admin/pages/Assets/components/Dnd/assetSortable.mjs +24 -0
- package/dist/admin/pages/Assets/components/Dnd/assetSortable.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/Dnd/dndIds.js +5 -0
- package/dist/admin/pages/Assets/components/Dnd/dndIds.js.map +1 -1
- package/dist/admin/pages/Assets/components/Dnd/dndIds.mjs +5 -1
- package/dist/admin/pages/Assets/components/Dnd/dndIds.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.js +41 -13
- package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.js.map +1 -1
- package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.mjs +41 -13
- package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/FilterBadges.mjs +2 -2
- package/dist/admin/pages/Assets/components/FilterMenu.mjs +2 -2
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js +274 -55
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs +277 -59
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.js +32 -0
- package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.js.map +1 -0
- package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.mjs +29 -0
- package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/ViewToggle.js +126 -0
- package/dist/admin/pages/Assets/components/ViewToggle.js.map +1 -0
- package/dist/admin/pages/Assets/components/ViewToggle.mjs +104 -0
- package/dist/admin/pages/Assets/components/ViewToggle.mjs.map +1 -0
- package/dist/admin/pages/Assets/hooks/useAssetSearch.js +2 -2
- package/dist/admin/pages/Assets/hooks/useAssetSearch.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useAssetSearch.mjs +2 -2
- package/dist/admin/pages/Assets/hooks/useAssetSearch.mjs.map +1 -1
- package/dist/admin/pages/Assets/hooks/useAssetSelection.js +19 -1
- package/dist/admin/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs +20 -3
- package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
- package/dist/admin/pages/Assets/hooks/useAssetsList.js +87 -0
- package/dist/admin/pages/Assets/hooks/useAssetsList.js.map +1 -0
- package/dist/admin/pages/Assets/hooks/useAssetsList.mjs +85 -0
- package/dist/admin/pages/Assets/hooks/useAssetsList.mjs.map +1 -0
- package/dist/admin/pages/Assets/hooks/useBusyAssets.mjs +1 -1
- package/dist/admin/pages/Assets/hooks/useFolderNavigation.js +2 -1
- package/dist/admin/pages/Assets/hooks/useFolderNavigation.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useFolderNavigation.mjs +3 -2
- package/dist/admin/pages/Assets/hooks/useFolderNavigation.mjs.map +1 -1
- package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.js +2 -6
- package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.mjs +2 -6
- package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.mjs.map +1 -1
- package/dist/admin/pages/Assets/hooks/useListFilters.js +2 -1
- package/dist/admin/pages/Assets/hooks/useListFilters.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useListFilters.mjs +3 -2
- package/dist/admin/pages/Assets/hooks/useListFilters.mjs.map +1 -1
- package/dist/admin/pages/Assets/hooks/useListQueryParams.js +80 -0
- package/dist/admin/pages/Assets/hooks/useListQueryParams.js.map +1 -0
- package/dist/admin/pages/Assets/hooks/useListQueryParams.mjs +77 -0
- package/dist/admin/pages/Assets/hooks/useListQueryParams.mjs.map +1 -0
- package/dist/admin/pages/Assets/hooks/useListSettings.js +32 -0
- package/dist/admin/pages/Assets/hooks/useListSettings.js.map +1 -0
- package/dist/admin/pages/Assets/hooks/useListSettings.mjs +29 -0
- package/dist/admin/pages/Assets/hooks/useListSettings.mjs.map +1 -0
- package/dist/admin/pages/Assets/hooks/useListSort.js +2 -1
- package/dist/admin/pages/Assets/hooks/useListSort.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useListSort.mjs +3 -2
- package/dist/admin/pages/Assets/hooks/useListSort.mjs.map +1 -1
- package/dist/admin/services/api.js +92 -7
- package/dist/admin/services/api.js.map +1 -1
- package/dist/admin/services/api.mjs +91 -9
- package/dist/admin/services/api.mjs.map +1 -1
- package/dist/admin/src/components/AssetPickerDialog/AssetPickerDialog.d.ts +19 -0
- package/dist/admin/src/components/AssetPickerDialog/FolderBreadcrumbs.d.ts +10 -0
- package/dist/admin/src/components/AssetPickerDialog/MediaLibraryPickerDialog.d.ts +19 -0
- package/dist/admin/src/components/AssetPickerDialog/PickerSelectionProvider.d.ts +28 -0
- package/dist/admin/src/components/AssetPickerDialog/SortableSelection.d.ts +12 -0
- package/dist/admin/src/components/AssetPickerDialog/pickerSelection.d.ts +26 -0
- package/dist/admin/src/components/Drawer.d.ts +8 -0
- package/dist/admin/src/components/EditorFileDropZone/EditorFileDropZone.d.ts +21 -0
- package/dist/admin/src/components/MediaLibraryInput/AddAssetMenu.d.ts +7 -1
- package/dist/admin/src/components/MediaLibraryInput/AssetCard.d.ts +25 -0
- package/dist/admin/src/components/MediaLibraryInput/AssetCarousel.d.ts +16 -0
- package/dist/admin/src/components/MediaLibraryInput/AssetDropZone.d.ts +11 -3
- package/dist/admin/src/components/MediaLibraryInput/AssetPreview.d.ts +17 -0
- package/dist/admin/src/components/MediaLibraryInput/AssetRow.d.ts +13 -3
- package/dist/admin/src/components/MediaLibraryInput/FieldControls.d.ts +19 -0
- package/dist/admin/src/components/MediaLibraryInput/MediaLibraryInput.d.ts +3 -1
- package/dist/admin/src/components/MediaLibraryInput/UploadProgressBar.d.ts +7 -0
- package/dist/admin/src/components/MediaLibraryInput/openAssetDetails.d.ts +10 -0
- package/dist/admin/src/components/MediaLibraryInput/useFieldUploads.d.ts +31 -0
- package/dist/admin/src/hooks/useMediaLibraryPermissions.d.ts +2 -0
- package/dist/admin/src/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +41 -5
- package/dist/admin/src/pages/Assets/components/AssetsGrid.d.ts +3 -1
- package/dist/admin/src/pages/Assets/components/AssetsSearchInput.d.ts +11 -1
- package/dist/admin/src/pages/Assets/components/AssetsView.d.ts +29 -0
- package/dist/admin/src/pages/Assets/components/Dnd/ReorderHandle.d.ts +12 -0
- package/dist/admin/src/pages/Assets/components/Dnd/assetSortable.d.ts +37 -0
- package/dist/admin/src/pages/Assets/components/Dnd/dndIds.d.ts +5 -0
- package/dist/admin/src/pages/Assets/components/Dnd/useAssetDnd.d.ts +23 -2
- package/dist/admin/src/pages/Assets/components/FolderTree/FolderTree.d.ts +1 -0
- package/dist/admin/src/pages/Assets/components/FolderTree/collapsedBranch.d.ts +21 -0
- package/dist/admin/src/pages/Assets/components/ViewToggle.d.ts +8 -0
- package/dist/admin/src/pages/Assets/hooks/useAssetSelection.d.ts +26 -0
- package/dist/admin/src/pages/Assets/hooks/useAssetsList.d.ts +30 -0
- package/dist/admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.d.ts +2 -6
- package/dist/admin/src/pages/Assets/hooks/useListQueryParams.d.ts +27 -0
- package/dist/admin/src/pages/Assets/hooks/useListSettings.d.ts +29 -0
- package/dist/admin/src/services/api.d.ts +24 -1
- package/dist/admin/src/store/uploadProgress.d.ts +14 -1
- package/dist/admin/src/utils/findFolderPath.d.ts +6 -0
- package/dist/admin/src/utils/isAllowedAssetType.d.ts +14 -0
- package/dist/admin/store/uploadProgress.js +30 -3
- package/dist/admin/store/uploadProgress.js.map +1 -1
- package/dist/admin/store/uploadProgress.mjs +29 -4
- package/dist/admin/store/uploadProgress.mjs.map +1 -1
- package/dist/admin/translations/en.json.js +24 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +24 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/utils/findFolderPath.js +26 -0
- package/dist/admin/utils/findFolderPath.js.map +1 -0
- package/dist/admin/utils/findFolderPath.mjs +24 -0
- package/dist/admin/utils/findFolderPath.mjs.map +1 -0
- package/dist/admin/utils/isAllowedAssetType.js +33 -0
- package/dist/admin/utils/isAllowedAssetType.js.map +1 -0
- package/dist/admin/utils/isAllowedAssetType.mjs +31 -0
- package/dist/admin/utils/isAllowedAssetType.mjs.map +1 -0
- package/dist/server/audit-logs.js +264 -0
- package/dist/server/audit-logs.js.map +1 -0
- package/dist/server/audit-logs.mjs +255 -0
- package/dist/server/audit-logs.mjs.map +1 -0
- package/dist/server/bootstrap.js +4 -0
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +4 -0
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/admin-folder-file.js +23 -1
- package/dist/server/controllers/admin-folder-file.js.map +1 -1
- package/dist/server/controllers/admin-folder-file.mjs +23 -1
- package/dist/server/controllers/admin-folder-file.mjs.map +1 -1
- package/dist/server/controllers/admin-settings.js +5 -1
- package/dist/server/controllers/admin-settings.js.map +1 -1
- package/dist/server/controllers/admin-settings.mjs +5 -1
- package/dist/server/controllers/admin-settings.mjs.map +1 -1
- package/dist/server/services/folder.js +48 -1
- package/dist/server/services/folder.js.map +1 -1
- package/dist/server/services/folder.mjs +48 -1
- package/dist/server/services/folder.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js +14 -7
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs +14 -7
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/services/upload.js +100 -16
- package/dist/server/services/upload.js.map +1 -1
- package/dist/server/services/upload.mjs +102 -18
- package/dist/server/services/upload.mjs.map +1 -1
- package/dist/server/src/audit-logs.d.ts +142 -0
- package/dist/server/src/audit-logs.d.ts.map +1 -0
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-folder-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
- package/dist/server/src/services/extensions/utils.d.ts +11 -11
- package/dist/server/src/services/folder.d.ts.map +1 -1
- package/dist/server/src/services/image-manipulation.d.ts +4 -4
- package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/upload.d.ts.map +1 -1
- package/dist/server/src/types.d.ts +63 -12
- package/dist/server/src/types.d.ts.map +1 -1
- package/package.json +11 -16
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.js +0 -45
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.js.map +0 -1
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.mjs +0 -43
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.mjs.map +0 -1
- package/dist/admin/src/components/MediaLibraryInput/NoLibraryAccessDialog.d.ts +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.mjs","sources":["../../../admin/src/components/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport * as Dialog from '@radix-ui/react-dialog';\nimport { Box, ScrollArea, IconButton, Flex, FlexProps } from '@strapi/design-system';\nimport { Cross } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { keyframes, styled } from 'styled-components';\n\n/** Duration of the close animation in ms. Use for timing cleanup (e.g. removing URL params). */\nexport const DRAWER_CLOSE_ANIMATION_MS = 300;\n\n/* -------------------------------------------------------------------------------------------------\n * Animations\n * -----------------------------------------------------------------------------------------------*/\n\n// Direction: up\nconst slideUpFromBottomIn = keyframes`\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n`;\n\nconst slideUpFromBottomOut = keyframes`\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n`;\n\n// Direction: left\nconst slideLeftFromRightIn = keyframes`\n from {\n opacity: 0;\n transform: translateX(100%);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\nconst slideLeftFromRightOut = keyframes`\n from {\n opacity: 1;\n transform: translateX(0);\n }\n to {\n opacity: 0;\n transform: translateX(100%);\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Styled components\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerContainerProps {\n $animationDirection?: DrawerBodyProps['animationDirection'];\n $width?: string;\n $maxHeight?: string;\n}\n\nconst DrawerContainer = styled(Flex)<DrawerContainerProps>`\n flex-direction: column;\n position: fixed;\n bottom: 0;\n /* Mobile: full-bleed sheet. Anchoring to the right at a fixed width left a\n dead gutter on every phone wider than the panel, and the panel only filled\n the screen once the viewport happened to be narrower than it. Below the\n medium breakpoint the panel is the screen; medium+ restores the\n right-anchored rail. */\n left: 0;\n right: 0;\n width: 100%;\n padding: ${({ theme }) => theme.spaces[2]};\n max-width: 100%;\n /* Sit just below the overlay token (300) so that:\n - popovers (500) and tooltips (1000) rendered from descendant components\n surface above the drawer panel,\n - AlertDialog overlays (300) and contents (310) opened from inside the\n drawer (e.g. the asset details \"delete\" confirm) cover the drawer. */\n z-index: 200;\n overflow: hidden;\n /* dvh, not vh: anchored to the bottom, a 100vh cap on mobile (visual\n viewport < 100vh under the URL bar) would push the drawer top off-screen. */\n max-height: ${({ $maxHeight }) => $maxHeight ?? '100dvh'};\n\n ${({ theme }) => theme.breakpoints.medium} {\n left: auto;\n width: ${({ $width }) => $width ?? '400px'};\n }\n\n &:focus {\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n &[data-state='open'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomIn : slideLeftFromRightIn}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n }\n\n &[data-state='closed'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomOut : slideLeftFromRightOut}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n pointer-events: none;\n }\n }\n`;\n\nconst DrawerContent = styled(Box)`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n background-color: ${({ theme }) => theme.colors.neutral0};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n overflow: hidden;\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\ninterface CollapsibleContentProps {\n $isVisible: boolean;\n}\n\nconst CollapsibleContent = styled(Box)<CollapsibleContentProps>`\n display: grid;\n flex: 1;\n min-height: 0;\n grid-template-rows: ${({ $isVisible }) => ($isVisible ? '1fr' : '0fr')};\n transition: grid-template-rows 0.3s ease-in-out;\n\n > div {\n overflow: hidden;\n min-height: 0;\n }\n\n /* The scroll area wraps its children in a div styled inline as\n display: table, min-width: 100%. A table box grows to its content, so a\n single unbreakable string (a long file name) widens it past the scrollport\n and the panel gains a horizontal scrollbar — with nothing left to clamp the\n row, the name never truncates. Overriding to a block box makes the\n scrollport the width again, which is what the vertical-only list wants.\n Inline styles, hence the important. */\n [data-radix-scroll-area-viewport] > div {\n display: block !important;\n }\n`;\n\nconst CloseIconButton = styled(IconButton)`\n &:hover {\n background: transparent;\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Body\n * -----------------------------------------------------------------------------------------------*/\n\ntype PointerDownOutsideHandler = NonNullable<Dialog.DialogContentProps['onPointerDownOutside']>;\n\n/** Vetoes an outside interaction that would otherwise dismiss the drawer. */\nconst keepOpen = (event: { preventDefault: () => void }) => event.preventDefault();\n\ninterface DrawerBodyProps extends Omit<FlexProps, 'width' | 'maxHeight'> {\n animationDirection?: 'up' | 'left';\n /** Width of the panel from the medium breakpoint up. Mobile is always full-bleed. */\n width?: string;\n /** Cap on the panel height. Defaults to the dynamic viewport height. */\n maxHeight?: string;\n /**\n * Opt in to dismiss-on-outside-click. Omitted, an outside pointer press never\n * closes the drawer — it must be closed explicitly, as long-running panels\n * like the upload progress dialog need. Passed, the handler can still veto\n * individual presses via `event.preventDefault()`. Content rendered from\n * inside the panel but portaled elsewhere (DS dialogs, popovers, tooltips)\n * never counts as outside — Radix reads the React tree, not the DOM.\n */\n onPointerDownOutside?: PointerDownOutsideHandler;\n children: React.ReactNode;\n}\n\nconst DrawerBody = React.forwardRef<HTMLDivElement, DrawerBodyProps>(\n (\n { animationDirection, width, maxHeight, onPointerDownOutside = keepOpen, children, ...props },\n ref\n ) => (\n <Dialog.Content\n ref={ref}\n forceMount\n asChild\n onPointerDownOutside={onPointerDownOutside}\n // Non-modal, so focus legitimately moves outside (tabbing past the last\n // field); only a pointer press should ever dismiss.\n onFocusOutside={keepOpen}\n data-animation-direction={animationDirection}\n >\n {/* width/maxHeight go through transient props so the DS Flex never emits a\n competing `width` rule that would outrank the mobile full-bleed one. */}\n <DrawerContainer\n $animationDirection={animationDirection}\n $width={width}\n $maxHeight={maxHeight}\n {...props}\n >\n <DrawerContent>{children}</DrawerContent>\n </DrawerContainer>\n </Dialog.Content>\n )\n);\nDrawerBody.displayName = 'DrawerBody';\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Root\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerRootProps {\n isVisible?: boolean;\n onClose?: () => void;\n children: React.ReactNode;\n}\n\nconst DrawerRoot = ({ isVisible, onClose, children }: DrawerRootProps): React.ReactElement => (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(nextVisible) => !nextVisible && onClose?.()}\n modal={false}\n >\n <Dialog.Portal>{children}</Dialog.Portal>\n </Dialog.Root>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Content - composable content slot (collapsible when isContentExpanded is used)\n * Contains a scrollable area\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerScrollableContentProps {\n children: React.ReactNode;\n /** When provided, content can collapse/expand (e.g. for minimize). Omit to always show. */\n isContentExpanded?: boolean;\n}\n\nconst DrawerScrollableContent = ({\n children,\n isContentExpanded = true,\n}: DrawerScrollableContentProps) => (\n <CollapsibleContent $isVisible={isContentExpanded} data-collapsed={!isContentExpanded}>\n <ScrollArea>{children}</ScrollArea>\n </CollapsibleContent>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.CloseButton - composable close icon button (Cross icon by default)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerCloseButtonProps extends React.PropsWithChildren {\n onClose: () => void;\n label?: string;\n}\n\nconst DrawerCloseButton = ({ onClose, label, children }: DrawerCloseButtonProps) => {\n const { formatMessage } = useIntl();\n const labelMessage = label ?? formatMessage({ id: 'global.close', defaultMessage: 'Close' });\n return (\n <CloseIconButton onClick={onClose} label={labelMessage} variant=\"ghost\">\n {children ?? <Cross />}\n </CloseIconButton>\n );\n};\n\nconst Drawer = {\n Root: DrawerRoot,\n Body: DrawerBody,\n ScrollableContent: DrawerScrollableContent,\n CloseButton: DrawerCloseButton,\n Title: Dialog.Title,\n Description: Dialog.Description,\n};\n\nexport { Drawer };\n"],"names":["DRAWER_CLOSE_ANIMATION_MS","slideUpFromBottomIn","keyframes","slideUpFromBottomOut","slideLeftFromRightIn","slideLeftFromRightOut","DrawerContainer","styled","Flex","theme","spaces","$maxHeight","breakpoints","medium","$width","$animationDirection","DrawerContent","Box","colors","neutral0","borderRadius","shadows","popupShadow","neutral150","CollapsibleContent","$isVisible","CloseIconButton","IconButton","keepOpen","event","preventDefault","DrawerBody","React","forwardRef","animationDirection","width","maxHeight","onPointerDownOutside","children","props","ref","_jsx","Dialog","Content","forceMount","asChild","onFocusOutside","data-animation-direction","displayName","DrawerRoot","isVisible","onClose","Root","open","onOpenChange","nextVisible","modal","Portal","DrawerScrollableContent","isContentExpanded","data-collapsed","ScrollArea","DrawerCloseButton","label","formatMessage","useIntl","labelMessage","id","defaultMessage","onClick","variant","Cross","Drawer","Body","ScrollableContent","CloseButton","Title","Description"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Drawer.mjs","sources":["../../../admin/src/components/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport * as Dialog from '@radix-ui/react-dialog';\nimport { Box, ScrollArea, IconButton, Flex, FlexProps } from '@strapi/design-system';\nimport { Cross } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { keyframes, styled } from 'styled-components';\n\n/** Duration of the close animation in ms. Use for timing cleanup (e.g. removing URL params). */\nexport const DRAWER_CLOSE_ANIMATION_MS = 300;\n\n/* -------------------------------------------------------------------------------------------------\n * Animations\n * -----------------------------------------------------------------------------------------------*/\n\n// Direction: up\nconst slideUpFromBottomIn = keyframes`\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n`;\n\nconst slideUpFromBottomOut = keyframes`\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n`;\n\n// Direction: left\nconst slideLeftFromRightIn = keyframes`\n from {\n opacity: 0;\n transform: translateX(100%);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\nconst slideLeftFromRightOut = keyframes`\n from {\n opacity: 1;\n transform: translateX(0);\n }\n to {\n opacity: 0;\n transform: translateX(100%);\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Styled components\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerContainerProps {\n $animationDirection?: DrawerBodyProps['animationDirection'];\n $width?: string;\n $maxHeight?: string;\n}\n\nconst DrawerContainer = styled(Flex)<DrawerContainerProps>`\n flex-direction: column;\n position: fixed;\n bottom: 0;\n /* Mobile: full-bleed sheet. Anchoring to the right at a fixed width left a\n dead gutter on every phone wider than the panel, and the panel only filled\n the screen once the viewport happened to be narrower than it. Below the\n medium breakpoint the panel is the screen; medium+ restores the\n right-anchored rail. */\n left: 0;\n right: 0;\n width: 100%;\n padding: ${({ theme }) => theme.spaces[2]};\n max-width: 100%;\n /* On the overlay token, so ties resolve by DOM order, as they do between DS\n modals: a drawer opened from inside a modal (e.g. a media field in the\n content manager's relation modal) portals in after it and sits above its\n overlay, while a dialog opened from inside the drawer (e.g. the asset\n details \"delete\" confirm) portals in after the drawer and covers it.\n Not the modal token (310): a DS dialog's content stacks inside its own\n overlay at 300, so the drawer would cover its own confirmations.\n Popovers (500) and tooltips (1000) still surface above the panel. */\n z-index: ${({ theme }) => theme.zIndices.overlay};\n overflow: hidden;\n /* dvh, not vh: anchored to the bottom, a 100vh cap on mobile (visual\n viewport < 100vh under the URL bar) would push the drawer top off-screen. */\n max-height: ${({ $maxHeight }) => $maxHeight ?? '100dvh'};\n\n ${({ theme }) => theme.breakpoints.medium} {\n left: auto;\n width: ${({ $width }) => $width ?? '400px'};\n }\n\n &:focus {\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n &[data-state='open'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomIn : slideLeftFromRightIn}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n }\n\n &[data-state='closed'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomOut : slideLeftFromRightOut}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n pointer-events: none;\n }\n }\n`;\n\nconst DrawerContent = styled(Box)`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n background-color: ${({ theme }) => theme.colors.neutral0};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n overflow: hidden;\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\ninterface CollapsibleContentProps {\n $isVisible: boolean;\n}\n\nconst CollapsibleContent = styled(Box)<CollapsibleContentProps>`\n display: grid;\n flex: 1;\n min-height: 0;\n grid-template-rows: ${({ $isVisible }) => ($isVisible ? '1fr' : '0fr')};\n transition: grid-template-rows 0.3s ease-in-out;\n\n > div {\n overflow: hidden;\n min-height: 0;\n }\n\n /* The scroll area wraps its children in a div styled inline as\n display: table, min-width: 100%. A table box grows to its content, so a\n single unbreakable string (a long file name) widens it past the scrollport\n and the panel gains a horizontal scrollbar — with nothing left to clamp the\n row, the name never truncates. Overriding to a block box makes the\n scrollport the width again, which is what the vertical-only list wants.\n Inline styles, hence the important. */\n [data-radix-scroll-area-viewport] > div {\n display: block !important;\n }\n`;\n\nconst CloseIconButton = styled(IconButton)`\n &:hover {\n background: transparent;\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Body\n * -----------------------------------------------------------------------------------------------*/\n\ntype PointerDownOutsideHandler = NonNullable<Dialog.DialogContentProps['onPointerDownOutside']>;\ntype AutoFocusHandler = NonNullable<Dialog.DialogContentProps['onOpenAutoFocus']>;\n\n/** Vetoes an outside interaction that would otherwise dismiss the drawer. */\nconst keepOpen = (event: { preventDefault: () => void }) => event.preventDefault();\n\ninterface DrawerBodyProps extends Omit<FlexProps, 'width' | 'maxHeight'> {\n animationDirection?: 'up' | 'left';\n /** Width of the panel from the medium breakpoint up. Mobile is always full-bleed. */\n width?: string;\n /** Cap on the panel height. Defaults to the dynamic viewport height. */\n maxHeight?: string;\n /**\n * Opt in to dismiss-on-outside-click. Omitted, an outside pointer press never\n * closes the drawer — it must be closed explicitly, as long-running panels\n * like the upload progress dialog need. Passed, the handler can still veto\n * individual presses via `event.preventDefault()`. Content rendered from\n * inside the panel but portaled elsewhere (DS dialogs, popovers, tooltips)\n * never counts as outside — Radix reads the React tree, not the DOM.\n */\n onPointerDownOutside?: PointerDownOutsideHandler;\n /** Radix's hook as focus moves into the panel on open. */\n onOpenAutoFocus?: AutoFocusHandler;\n /**\n * Radix's hook as the panel gives focus back on close. Opened from state\n * rather than a `Dialog.Trigger`, it has nowhere to send it unless this does.\n */\n onCloseAutoFocus?: AutoFocusHandler;\n children: React.ReactNode;\n}\n\nconst DrawerBody = React.forwardRef<HTMLDivElement, DrawerBodyProps>(\n (\n {\n animationDirection,\n width,\n maxHeight,\n onPointerDownOutside = keepOpen,\n onOpenAutoFocus,\n onCloseAutoFocus,\n children,\n ...props\n },\n ref\n ) => (\n <Dialog.Content\n ref={ref}\n forceMount\n asChild\n onPointerDownOutside={onPointerDownOutside}\n onOpenAutoFocus={onOpenAutoFocus}\n onCloseAutoFocus={onCloseAutoFocus}\n // Non-modal, so focus legitimately moves outside (tabbing past the last\n // field); only a pointer press should ever dismiss.\n onFocusOutside={keepOpen}\n data-animation-direction={animationDirection}\n >\n {/* width/maxHeight go through transient props so the DS Flex never emits a\n competing `width` rule that would outrank the mobile full-bleed one. */}\n <DrawerContainer\n $animationDirection={animationDirection}\n $width={width}\n $maxHeight={maxHeight}\n {...props}\n >\n <DrawerContent>{children}</DrawerContent>\n </DrawerContainer>\n </Dialog.Content>\n )\n);\nDrawerBody.displayName = 'DrawerBody';\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Root\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerRootProps {\n isVisible?: boolean;\n onClose?: () => void;\n children: React.ReactNode;\n}\n\nconst DrawerRoot = ({ isVisible, onClose, children }: DrawerRootProps): React.ReactElement => (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(nextVisible) => !nextVisible && onClose?.()}\n modal={false}\n >\n <Dialog.Portal>{children}</Dialog.Portal>\n </Dialog.Root>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Content - composable content slot (collapsible when isContentExpanded is used)\n * Contains a scrollable area\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerScrollableContentProps {\n children: React.ReactNode;\n /** When provided, content can collapse/expand (e.g. for minimize). Omit to always show. */\n isContentExpanded?: boolean;\n}\n\nconst DrawerScrollableContent = ({\n children,\n isContentExpanded = true,\n}: DrawerScrollableContentProps) => (\n <CollapsibleContent $isVisible={isContentExpanded} data-collapsed={!isContentExpanded}>\n <ScrollArea>{children}</ScrollArea>\n </CollapsibleContent>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.CloseButton - composable close icon button (Cross icon by default)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerCloseButtonProps extends React.PropsWithChildren {\n onClose: () => void;\n label?: string;\n}\n\nconst DrawerCloseButton = ({ onClose, label, children }: DrawerCloseButtonProps) => {\n const { formatMessage } = useIntl();\n const labelMessage = label ?? formatMessage({ id: 'global.close', defaultMessage: 'Close' });\n return (\n <CloseIconButton onClick={onClose} label={labelMessage} variant=\"ghost\">\n {children ?? <Cross />}\n </CloseIconButton>\n );\n};\n\nconst Drawer = {\n Root: DrawerRoot,\n Body: DrawerBody,\n ScrollableContent: DrawerScrollableContent,\n CloseButton: DrawerCloseButton,\n Title: Dialog.Title,\n Description: Dialog.Description,\n};\n\nexport { Drawer };\n"],"names":["DRAWER_CLOSE_ANIMATION_MS","slideUpFromBottomIn","keyframes","slideUpFromBottomOut","slideLeftFromRightIn","slideLeftFromRightOut","DrawerContainer","styled","Flex","theme","spaces","zIndices","overlay","$maxHeight","breakpoints","medium","$width","$animationDirection","DrawerContent","Box","colors","neutral0","borderRadius","shadows","popupShadow","neutral150","CollapsibleContent","$isVisible","CloseIconButton","IconButton","keepOpen","event","preventDefault","DrawerBody","React","forwardRef","animationDirection","width","maxHeight","onPointerDownOutside","onOpenAutoFocus","onCloseAutoFocus","children","props","ref","_jsx","Dialog","Content","forceMount","asChild","onFocusOutside","data-animation-direction","displayName","DrawerRoot","isVisible","onClose","Root","open","onOpenChange","nextVisible","modal","Portal","DrawerScrollableContent","isContentExpanded","data-collapsed","ScrollArea","DrawerCloseButton","label","formatMessage","useIntl","labelMessage","id","defaultMessage","onClick","variant","Cross","Drawer","Body","ScrollableContent","CloseButton","Title","Description"],"mappings":"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"}
|
|
@@ -0,0 +1,188 @@
|
|
|
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 designSystem = require('@strapi/design-system');
|
|
7
|
+
var reactIntl = require('react-intl');
|
|
8
|
+
var styledComponents = require('styled-components');
|
|
9
|
+
var useAIMetadataEnabled = require('../../hooks/useAIMetadataEnabled.js');
|
|
10
|
+
var useMediaLibraryPermissions = require('../../hooks/useMediaLibraryPermissions.js');
|
|
11
|
+
var useTracking = require('../../hooks/useTracking.js');
|
|
12
|
+
var api = require('../../services/api.js');
|
|
13
|
+
var settings = require('../../services/settings.js');
|
|
14
|
+
var allowedMediaTypes = require('../../utils/allowedMediaTypes.js');
|
|
15
|
+
var translations = require('../../utils/translations.js');
|
|
16
|
+
var typeFromMime = require('../../utils/typeFromMime.js');
|
|
17
|
+
|
|
18
|
+
const FRAME_COLORS = {
|
|
19
|
+
accept: {
|
|
20
|
+
border: 'primary600',
|
|
21
|
+
background: 'primary100',
|
|
22
|
+
text: 'primary600'
|
|
23
|
+
},
|
|
24
|
+
reject: {
|
|
25
|
+
border: 'neutral300',
|
|
26
|
+
background: 'neutral150',
|
|
27
|
+
text: 'neutral600'
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
// Takes the place of the editor's content in its layout, so it fills the same
|
|
31
|
+
// space: the editor stacks its parts against the start, sized to their content.
|
|
32
|
+
const Root = styledComponents.styled.div`
|
|
33
|
+
position: relative;
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
flex: 1;
|
|
37
|
+
width: 100%;
|
|
38
|
+
min-height: 0;
|
|
39
|
+
`;
|
|
40
|
+
const Frame = styledComponents.styled.div`
|
|
41
|
+
position: absolute;
|
|
42
|
+
inset: ${({ theme })=>theme.spaces[2]};
|
|
43
|
+
z-index: 2;
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
border: 1px solid ${({ theme, $dragState })=>theme.colors[FRAME_COLORS[$dragState].border]};
|
|
48
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
49
|
+
background: ${({ theme, $dragState })=>theme.colors[FRAME_COLORS[$dragState].background]};
|
|
50
|
+
pointer-events: none;
|
|
51
|
+
`;
|
|
52
|
+
const hasFiles = (event)=>event.dataTransfer.types.includes('Files');
|
|
53
|
+
/**
|
|
54
|
+
* Lets an editor take files dropped onto it: they upload to the root of the
|
|
55
|
+
* Media Library, through the global upload progress dialog, and are handed
|
|
56
|
+
* back to the editor one by one. Drags that carry no file, such as an editor
|
|
57
|
+
* reordering its own blocks, pass through untouched.
|
|
58
|
+
*/ const EditorFileDropZone = ({ children, disabled = false, allowedTypes, onDropFiles })=>{
|
|
59
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
60
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
|
61
|
+
const { trackUsage } = useTracking.useTracking();
|
|
62
|
+
const [uploadFiles] = api.useUploadFilesMutation();
|
|
63
|
+
const { canRead, canCreate, isLoading } = useMediaLibraryPermissions.useMediaLibraryPermissions();
|
|
64
|
+
const { data: settings$1 } = settings.useGetUploadSettingsQuery(undefined, {
|
|
65
|
+
skip: !canRead
|
|
66
|
+
});
|
|
67
|
+
const isAiMetadataEnabled = useAIMetadataEnabled.useAIMetadataEnabled();
|
|
68
|
+
const [dragState, setDragState] = React.useState('idle');
|
|
69
|
+
// Drag events fire on every descendant crossed, so count enter/leave pairs.
|
|
70
|
+
const dragDepth = React.useRef(0);
|
|
71
|
+
const canUpload = !disabled && !isLoading && canCreate;
|
|
72
|
+
const handleDragEnter = (event)=>{
|
|
73
|
+
if (!hasFiles(event)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
dragDepth.current += 1;
|
|
78
|
+
setDragState(canUpload ? 'accept' : 'reject');
|
|
79
|
+
};
|
|
80
|
+
const handleDragLeave = (event)=>{
|
|
81
|
+
if (!hasFiles(event)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
dragDepth.current -= 1;
|
|
85
|
+
if (dragDepth.current <= 0) {
|
|
86
|
+
dragDepth.current = 0;
|
|
87
|
+
setDragState('idle');
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const handleDragOver = (event)=>{
|
|
91
|
+
if (!hasFiles(event)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// Without it the browser opens the file in the tab.
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
// `none` shows the no-drop cursor, and the browser then fires no `drop`.
|
|
97
|
+
event.dataTransfer.dropEffect = canUpload ? 'copy' : 'none';
|
|
98
|
+
};
|
|
99
|
+
const handleDrop = async (event)=>{
|
|
100
|
+
if (!hasFiles(event)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
dragDepth.current = 0;
|
|
105
|
+
setDragState('idle');
|
|
106
|
+
if (!canUpload) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const files = Array.from(event.dataTransfer.files);
|
|
110
|
+
const allowedFiles = allowedMediaTypes.filterAllowedFiles(allowedTypes, files);
|
|
111
|
+
if (allowedFiles.length < files.length) {
|
|
112
|
+
toggleNotification({
|
|
113
|
+
type: 'danger',
|
|
114
|
+
timeout: 4000,
|
|
115
|
+
message: formatMessage({
|
|
116
|
+
id: translations.getTranslationKey('input.notification.not-supported'),
|
|
117
|
+
defaultMessage: `You can't upload this type of file, only the following types are accepted – {fileTypes}`
|
|
118
|
+
}, {
|
|
119
|
+
fileTypes: (allowedTypes ?? []).join(',')
|
|
120
|
+
})
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (allowedFiles.length === 0) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const onFileUploaded = onDropFiles(event);
|
|
127
|
+
const assetsCountByType = allowedFiles.reduce((acc, file)=>{
|
|
128
|
+
const type = typeFromMime.typeFromMime(file.type);
|
|
129
|
+
acc[type] = (acc[type] ?? 0) + 1;
|
|
130
|
+
return acc;
|
|
131
|
+
}, {});
|
|
132
|
+
trackUsage('didSelectFile', {
|
|
133
|
+
source: 'computer',
|
|
134
|
+
location: 'content-manager'
|
|
135
|
+
});
|
|
136
|
+
trackUsage('willAddMediaLibraryAssets', {
|
|
137
|
+
location: 'content-manager',
|
|
138
|
+
...assetsCountByType
|
|
139
|
+
});
|
|
140
|
+
const formData = new FormData();
|
|
141
|
+
allowedFiles.forEach((file)=>formData.append('files', file));
|
|
142
|
+
formData.append('fileInfo', JSON.stringify(allowedFiles.map((file)=>({
|
|
143
|
+
name: file.name,
|
|
144
|
+
caption: null,
|
|
145
|
+
alternativeText: null,
|
|
146
|
+
folder: null
|
|
147
|
+
}))));
|
|
148
|
+
try {
|
|
149
|
+
await uploadFiles({
|
|
150
|
+
formData,
|
|
151
|
+
totalFiles: allowedFiles.length,
|
|
152
|
+
concurrency: settings$1?.data?.concurrentUploadRequests ?? 1,
|
|
153
|
+
generateAiMetadata: Boolean(isAiMetadataEnabled),
|
|
154
|
+
onFileUploaded
|
|
155
|
+
}).unwrap();
|
|
156
|
+
} catch {
|
|
157
|
+
// Errors reach the user through the progress dialog, which the mutation
|
|
158
|
+
// populates itself.
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(Root, {
|
|
162
|
+
onDragEnter: handleDragEnter,
|
|
163
|
+
onDragLeave: handleDragLeave,
|
|
164
|
+
onDragOver: handleDragOver,
|
|
165
|
+
onDrop: handleDrop,
|
|
166
|
+
children: [
|
|
167
|
+
children,
|
|
168
|
+
dragState !== 'idle' && /*#__PURE__*/ jsxRuntime.jsx(Frame, {
|
|
169
|
+
$dragState: dragState,
|
|
170
|
+
"data-testid": "editor-file-drop-zone",
|
|
171
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
172
|
+
fontWeight: "semiBold",
|
|
173
|
+
textColor: FRAME_COLORS[dragState].text,
|
|
174
|
+
children: dragState === 'accept' ? formatMessage({
|
|
175
|
+
id: translations.getTranslationKey('editor-drop-zone.accept'),
|
|
176
|
+
defaultMessage: 'Drop to upload and insert'
|
|
177
|
+
}) : formatMessage({
|
|
178
|
+
id: translations.getTranslationKey('editor-drop-zone.reject'),
|
|
179
|
+
defaultMessage: "You don't have permission to upload files"
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
]
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
exports.EditorFileDropZone = EditorFileDropZone;
|
|
188
|
+
//# sourceMappingURL=EditorFileDropZone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorFileDropZone.js","sources":["../../../../admin/src/components/EditorFileDropZone/EditorFileDropZone.tsx"],"sourcesContent":["import { useRef, useState, type DragEvent, type ReactNode } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useAIMetadataEnabled } from '../../hooks/useAIMetadataEnabled';\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { useTracking } from '../../hooks/useTracking';\nimport { useUploadFilesMutation } from '../../services/api';\nimport { useGetUploadSettingsQuery } from '../../services/settings';\nimport { filterAllowedFiles, type AllowedMediaType } from '../../utils/allowedMediaTypes';\nimport { getTranslationKey } from '../../utils/translations';\nimport { typeFromMime } from '../../utils/typeFromMime';\n\nimport type { File } from '../../../../shared/contracts/files';\n\ntype DragState = 'idle' | 'accept' | 'reject';\n\nconst FRAME_COLORS = {\n accept: { border: 'primary600', background: 'primary100', text: 'primary600' },\n reject: { border: 'neutral300', background: 'neutral150', text: 'neutral600' },\n} as const;\n\n// Takes the place of the editor's content in its layout, so it fills the same\n// space: the editor stacks its parts against the start, sized to their content.\nconst Root = styled.div`\n position: relative;\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n min-height: 0;\n`;\n\nconst Frame = styled.div<{ $dragState: Exclude<DragState, 'idle'> }>`\n position: absolute;\n inset: ${({ theme }) => theme.spaces[2]};\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid ${({ theme, $dragState }) => theme.colors[FRAME_COLORS[$dragState].border]};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme, $dragState }) => theme.colors[FRAME_COLORS[$dragState].background]};\n pointer-events: none;\n`;\n\nexport interface EditorFileDropZoneProps {\n children: ReactNode;\n disabled?: boolean;\n allowedTypes?: AllowedMediaType[];\n /**\n * Called once per accepted drop, while the drop event is still current. It\n * returns what receives each of that drop's files once uploaded, including\n * files a Retry in the progress dialog uploads later.\n */\n onDropFiles: (event: DragEvent<HTMLElement>) => (file: File) => void;\n}\n\nconst hasFiles = (event: DragEvent<HTMLElement>) => event.dataTransfer.types.includes('Files');\n\n/**\n * Lets an editor take files dropped onto it: they upload to the root of the\n * Media Library, through the global upload progress dialog, and are handed\n * back to the editor one by one. Drags that carry no file, such as an editor\n * reordering its own blocks, pass through untouched.\n */\nexport const EditorFileDropZone = ({\n children,\n disabled = false,\n allowedTypes,\n onDropFiles,\n}: EditorFileDropZoneProps) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { trackUsage } = useTracking();\n const [uploadFiles] = useUploadFilesMutation();\n const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();\n const { data: settings } = useGetUploadSettingsQuery(undefined, { skip: !canRead });\n const isAiMetadataEnabled = useAIMetadataEnabled();\n const [dragState, setDragState] = useState<DragState>('idle');\n // Drag events fire on every descendant crossed, so count enter/leave pairs.\n const dragDepth = useRef(0);\n\n const canUpload = !disabled && !isLoading && canCreate;\n\n const handleDragEnter = (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.current += 1;\n setDragState(canUpload ? 'accept' : 'reject');\n };\n\n const handleDragLeave = (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n dragDepth.current -= 1;\n\n if (dragDepth.current <= 0) {\n dragDepth.current = 0;\n setDragState('idle');\n }\n };\n\n const handleDragOver = (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n // Without it the browser opens the file in the tab.\n event.preventDefault();\n // `none` shows the no-drop cursor, and the browser then fires no `drop`.\n event.dataTransfer.dropEffect = canUpload ? 'copy' : 'none';\n };\n\n const handleDrop = async (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.current = 0;\n setDragState('idle');\n\n if (!canUpload) {\n return;\n }\n\n const files = Array.from(event.dataTransfer.files);\n const allowedFiles = filterAllowedFiles(allowedTypes, files);\n\n if (allowedFiles.length < files.length) {\n toggleNotification({\n type: 'danger',\n timeout: 4000,\n message: formatMessage(\n {\n id: getTranslationKey('input.notification.not-supported'),\n defaultMessage: `You can't upload this type of file, only the following types are accepted – {fileTypes}`,\n },\n { fileTypes: (allowedTypes ?? []).join(',') }\n ),\n });\n }\n\n if (allowedFiles.length === 0) {\n return;\n }\n\n const onFileUploaded = onDropFiles(event);\n\n const assetsCountByType = allowedFiles.reduce<Record<string, number>>((acc, file) => {\n const type = typeFromMime(file.type);\n acc[type] = (acc[type] ?? 0) + 1;\n return acc;\n }, {});\n trackUsage('didSelectFile', { source: 'computer', location: 'content-manager' });\n trackUsage('willAddMediaLibraryAssets', { location: 'content-manager', ...assetsCountByType });\n\n const formData = new FormData();\n allowedFiles.forEach((file) => formData.append('files', file));\n formData.append(\n 'fileInfo',\n JSON.stringify(\n allowedFiles.map((file) => ({\n name: file.name,\n caption: null,\n alternativeText: null,\n folder: null,\n }))\n )\n );\n\n try {\n await uploadFiles({\n formData,\n totalFiles: allowedFiles.length,\n concurrency: settings?.data?.concurrentUploadRequests ?? 1,\n generateAiMetadata: Boolean(isAiMetadataEnabled),\n onFileUploaded,\n }).unwrap();\n } catch {\n // Errors reach the user through the progress dialog, which the mutation\n // populates itself.\n }\n };\n\n return (\n <Root\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {children}\n {dragState !== 'idle' && (\n <Frame $dragState={dragState} data-testid=\"editor-file-drop-zone\">\n <Typography fontWeight=\"semiBold\" textColor={FRAME_COLORS[dragState].text}>\n {dragState === 'accept'\n ? formatMessage({\n id: getTranslationKey('editor-drop-zone.accept'),\n defaultMessage: 'Drop to upload and insert',\n })\n : formatMessage({\n id: getTranslationKey('editor-drop-zone.reject'),\n defaultMessage: \"You don't have permission to upload files\",\n })}\n </Typography>\n </Frame>\n )}\n </Root>\n );\n};\n"],"names":["FRAME_COLORS","accept","border","background","text","reject","Root","styled","div","Frame","theme","spaces","$dragState","colors","borderRadius","hasFiles","event","dataTransfer","types","includes","EditorFileDropZone","children","disabled","allowedTypes","onDropFiles","formatMessage","useIntl","toggleNotification","useNotification","trackUsage","useTracking","uploadFiles","useUploadFilesMutation","canRead","canCreate","isLoading","useMediaLibraryPermissions","data","settings","useGetUploadSettingsQuery","undefined","skip","isAiMetadataEnabled","useAIMetadataEnabled","dragState","setDragState","useState","dragDepth","useRef","canUpload","handleDragEnter","preventDefault","current","handleDragLeave","handleDragOver","dropEffect","handleDrop","files","Array","from","allowedFiles","filterAllowedFiles","length","type","timeout","message","id","getTranslationKey","defaultMessage","fileTypes","join","onFileUploaded","assetsCountByType","reduce","acc","file","typeFromMime","source","location","formData","FormData","forEach","append","JSON","stringify","map","name","caption","alternativeText","folder","totalFiles","concurrency","concurrentUploadRequests","generateAiMetadata","Boolean","unwrap","_jsxs","onDragEnter","onDragLeave","onDragOver","onDrop","_jsx","data-testid","Typography","fontWeight","textColor"],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef } from 'react';
|
|
3
|
+
import { useNotification } from '@strapi/admin/strapi-admin';
|
|
4
|
+
import { Typography } from '@strapi/design-system';
|
|
5
|
+
import { useIntl } from 'react-intl';
|
|
6
|
+
import { styled } from 'styled-components';
|
|
7
|
+
import { useAIMetadataEnabled } from '../../hooks/useAIMetadataEnabled.mjs';
|
|
8
|
+
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions.mjs';
|
|
9
|
+
import { useTracking } from '../../hooks/useTracking.mjs';
|
|
10
|
+
import { useUploadFilesMutation } from '../../services/api.mjs';
|
|
11
|
+
import { useGetUploadSettingsQuery } from '../../services/settings.mjs';
|
|
12
|
+
import { filterAllowedFiles } from '../../utils/allowedMediaTypes.mjs';
|
|
13
|
+
import { getTranslationKey } from '../../utils/translations.mjs';
|
|
14
|
+
import { typeFromMime } from '../../utils/typeFromMime.mjs';
|
|
15
|
+
|
|
16
|
+
const FRAME_COLORS = {
|
|
17
|
+
accept: {
|
|
18
|
+
border: 'primary600',
|
|
19
|
+
background: 'primary100',
|
|
20
|
+
text: 'primary600'
|
|
21
|
+
},
|
|
22
|
+
reject: {
|
|
23
|
+
border: 'neutral300',
|
|
24
|
+
background: 'neutral150',
|
|
25
|
+
text: 'neutral600'
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
// Takes the place of the editor's content in its layout, so it fills the same
|
|
29
|
+
// space: the editor stacks its parts against the start, sized to their content.
|
|
30
|
+
const Root = styled.div`
|
|
31
|
+
position: relative;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
flex: 1;
|
|
35
|
+
width: 100%;
|
|
36
|
+
min-height: 0;
|
|
37
|
+
`;
|
|
38
|
+
const Frame = styled.div`
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: ${({ theme })=>theme.spaces[2]};
|
|
41
|
+
z-index: 2;
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
border: 1px solid ${({ theme, $dragState })=>theme.colors[FRAME_COLORS[$dragState].border]};
|
|
46
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
47
|
+
background: ${({ theme, $dragState })=>theme.colors[FRAME_COLORS[$dragState].background]};
|
|
48
|
+
pointer-events: none;
|
|
49
|
+
`;
|
|
50
|
+
const hasFiles = (event)=>event.dataTransfer.types.includes('Files');
|
|
51
|
+
/**
|
|
52
|
+
* Lets an editor take files dropped onto it: they upload to the root of the
|
|
53
|
+
* Media Library, through the global upload progress dialog, and are handed
|
|
54
|
+
* back to the editor one by one. Drags that carry no file, such as an editor
|
|
55
|
+
* reordering its own blocks, pass through untouched.
|
|
56
|
+
*/ const EditorFileDropZone = ({ children, disabled = false, allowedTypes, onDropFiles })=>{
|
|
57
|
+
const { formatMessage } = useIntl();
|
|
58
|
+
const { toggleNotification } = useNotification();
|
|
59
|
+
const { trackUsage } = useTracking();
|
|
60
|
+
const [uploadFiles] = useUploadFilesMutation();
|
|
61
|
+
const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();
|
|
62
|
+
const { data: settings } = useGetUploadSettingsQuery(undefined, {
|
|
63
|
+
skip: !canRead
|
|
64
|
+
});
|
|
65
|
+
const isAiMetadataEnabled = useAIMetadataEnabled();
|
|
66
|
+
const [dragState, setDragState] = useState('idle');
|
|
67
|
+
// Drag events fire on every descendant crossed, so count enter/leave pairs.
|
|
68
|
+
const dragDepth = useRef(0);
|
|
69
|
+
const canUpload = !disabled && !isLoading && canCreate;
|
|
70
|
+
const handleDragEnter = (event)=>{
|
|
71
|
+
if (!hasFiles(event)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
dragDepth.current += 1;
|
|
76
|
+
setDragState(canUpload ? 'accept' : 'reject');
|
|
77
|
+
};
|
|
78
|
+
const handleDragLeave = (event)=>{
|
|
79
|
+
if (!hasFiles(event)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
dragDepth.current -= 1;
|
|
83
|
+
if (dragDepth.current <= 0) {
|
|
84
|
+
dragDepth.current = 0;
|
|
85
|
+
setDragState('idle');
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const handleDragOver = (event)=>{
|
|
89
|
+
if (!hasFiles(event)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Without it the browser opens the file in the tab.
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
// `none` shows the no-drop cursor, and the browser then fires no `drop`.
|
|
95
|
+
event.dataTransfer.dropEffect = canUpload ? 'copy' : 'none';
|
|
96
|
+
};
|
|
97
|
+
const handleDrop = async (event)=>{
|
|
98
|
+
if (!hasFiles(event)) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
dragDepth.current = 0;
|
|
103
|
+
setDragState('idle');
|
|
104
|
+
if (!canUpload) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const files = Array.from(event.dataTransfer.files);
|
|
108
|
+
const allowedFiles = filterAllowedFiles(allowedTypes, files);
|
|
109
|
+
if (allowedFiles.length < files.length) {
|
|
110
|
+
toggleNotification({
|
|
111
|
+
type: 'danger',
|
|
112
|
+
timeout: 4000,
|
|
113
|
+
message: formatMessage({
|
|
114
|
+
id: getTranslationKey('input.notification.not-supported'),
|
|
115
|
+
defaultMessage: `You can't upload this type of file, only the following types are accepted – {fileTypes}`
|
|
116
|
+
}, {
|
|
117
|
+
fileTypes: (allowedTypes ?? []).join(',')
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (allowedFiles.length === 0) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const onFileUploaded = onDropFiles(event);
|
|
125
|
+
const assetsCountByType = allowedFiles.reduce((acc, file)=>{
|
|
126
|
+
const type = typeFromMime(file.type);
|
|
127
|
+
acc[type] = (acc[type] ?? 0) + 1;
|
|
128
|
+
return acc;
|
|
129
|
+
}, {});
|
|
130
|
+
trackUsage('didSelectFile', {
|
|
131
|
+
source: 'computer',
|
|
132
|
+
location: 'content-manager'
|
|
133
|
+
});
|
|
134
|
+
trackUsage('willAddMediaLibraryAssets', {
|
|
135
|
+
location: 'content-manager',
|
|
136
|
+
...assetsCountByType
|
|
137
|
+
});
|
|
138
|
+
const formData = new FormData();
|
|
139
|
+
allowedFiles.forEach((file)=>formData.append('files', file));
|
|
140
|
+
formData.append('fileInfo', JSON.stringify(allowedFiles.map((file)=>({
|
|
141
|
+
name: file.name,
|
|
142
|
+
caption: null,
|
|
143
|
+
alternativeText: null,
|
|
144
|
+
folder: null
|
|
145
|
+
}))));
|
|
146
|
+
try {
|
|
147
|
+
await uploadFiles({
|
|
148
|
+
formData,
|
|
149
|
+
totalFiles: allowedFiles.length,
|
|
150
|
+
concurrency: settings?.data?.concurrentUploadRequests ?? 1,
|
|
151
|
+
generateAiMetadata: Boolean(isAiMetadataEnabled),
|
|
152
|
+
onFileUploaded
|
|
153
|
+
}).unwrap();
|
|
154
|
+
} catch {
|
|
155
|
+
// Errors reach the user through the progress dialog, which the mutation
|
|
156
|
+
// populates itself.
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
return /*#__PURE__*/ jsxs(Root, {
|
|
160
|
+
onDragEnter: handleDragEnter,
|
|
161
|
+
onDragLeave: handleDragLeave,
|
|
162
|
+
onDragOver: handleDragOver,
|
|
163
|
+
onDrop: handleDrop,
|
|
164
|
+
children: [
|
|
165
|
+
children,
|
|
166
|
+
dragState !== 'idle' && /*#__PURE__*/ jsx(Frame, {
|
|
167
|
+
$dragState: dragState,
|
|
168
|
+
"data-testid": "editor-file-drop-zone",
|
|
169
|
+
children: /*#__PURE__*/ jsx(Typography, {
|
|
170
|
+
fontWeight: "semiBold",
|
|
171
|
+
textColor: FRAME_COLORS[dragState].text,
|
|
172
|
+
children: dragState === 'accept' ? formatMessage({
|
|
173
|
+
id: getTranslationKey('editor-drop-zone.accept'),
|
|
174
|
+
defaultMessage: 'Drop to upload and insert'
|
|
175
|
+
}) : formatMessage({
|
|
176
|
+
id: getTranslationKey('editor-drop-zone.reject'),
|
|
177
|
+
defaultMessage: "You don't have permission to upload files"
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
]
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export { EditorFileDropZone };
|
|
186
|
+
//# sourceMappingURL=EditorFileDropZone.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorFileDropZone.mjs","sources":["../../../../admin/src/components/EditorFileDropZone/EditorFileDropZone.tsx"],"sourcesContent":["import { useRef, useState, type DragEvent, type ReactNode } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useAIMetadataEnabled } from '../../hooks/useAIMetadataEnabled';\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { useTracking } from '../../hooks/useTracking';\nimport { useUploadFilesMutation } from '../../services/api';\nimport { useGetUploadSettingsQuery } from '../../services/settings';\nimport { filterAllowedFiles, type AllowedMediaType } from '../../utils/allowedMediaTypes';\nimport { getTranslationKey } from '../../utils/translations';\nimport { typeFromMime } from '../../utils/typeFromMime';\n\nimport type { File } from '../../../../shared/contracts/files';\n\ntype DragState = 'idle' | 'accept' | 'reject';\n\nconst FRAME_COLORS = {\n accept: { border: 'primary600', background: 'primary100', text: 'primary600' },\n reject: { border: 'neutral300', background: 'neutral150', text: 'neutral600' },\n} as const;\n\n// Takes the place of the editor's content in its layout, so it fills the same\n// space: the editor stacks its parts against the start, sized to their content.\nconst Root = styled.div`\n position: relative;\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n min-height: 0;\n`;\n\nconst Frame = styled.div<{ $dragState: Exclude<DragState, 'idle'> }>`\n position: absolute;\n inset: ${({ theme }) => theme.spaces[2]};\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid ${({ theme, $dragState }) => theme.colors[FRAME_COLORS[$dragState].border]};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme, $dragState }) => theme.colors[FRAME_COLORS[$dragState].background]};\n pointer-events: none;\n`;\n\nexport interface EditorFileDropZoneProps {\n children: ReactNode;\n disabled?: boolean;\n allowedTypes?: AllowedMediaType[];\n /**\n * Called once per accepted drop, while the drop event is still current. It\n * returns what receives each of that drop's files once uploaded, including\n * files a Retry in the progress dialog uploads later.\n */\n onDropFiles: (event: DragEvent<HTMLElement>) => (file: File) => void;\n}\n\nconst hasFiles = (event: DragEvent<HTMLElement>) => event.dataTransfer.types.includes('Files');\n\n/**\n * Lets an editor take files dropped onto it: they upload to the root of the\n * Media Library, through the global upload progress dialog, and are handed\n * back to the editor one by one. Drags that carry no file, such as an editor\n * reordering its own blocks, pass through untouched.\n */\nexport const EditorFileDropZone = ({\n children,\n disabled = false,\n allowedTypes,\n onDropFiles,\n}: EditorFileDropZoneProps) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { trackUsage } = useTracking();\n const [uploadFiles] = useUploadFilesMutation();\n const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();\n const { data: settings } = useGetUploadSettingsQuery(undefined, { skip: !canRead });\n const isAiMetadataEnabled = useAIMetadataEnabled();\n const [dragState, setDragState] = useState<DragState>('idle');\n // Drag events fire on every descendant crossed, so count enter/leave pairs.\n const dragDepth = useRef(0);\n\n const canUpload = !disabled && !isLoading && canCreate;\n\n const handleDragEnter = (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.current += 1;\n setDragState(canUpload ? 'accept' : 'reject');\n };\n\n const handleDragLeave = (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n dragDepth.current -= 1;\n\n if (dragDepth.current <= 0) {\n dragDepth.current = 0;\n setDragState('idle');\n }\n };\n\n const handleDragOver = (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n // Without it the browser opens the file in the tab.\n event.preventDefault();\n // `none` shows the no-drop cursor, and the browser then fires no `drop`.\n event.dataTransfer.dropEffect = canUpload ? 'copy' : 'none';\n };\n\n const handleDrop = async (event: DragEvent<HTMLElement>) => {\n if (!hasFiles(event)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.current = 0;\n setDragState('idle');\n\n if (!canUpload) {\n return;\n }\n\n const files = Array.from(event.dataTransfer.files);\n const allowedFiles = filterAllowedFiles(allowedTypes, files);\n\n if (allowedFiles.length < files.length) {\n toggleNotification({\n type: 'danger',\n timeout: 4000,\n message: formatMessage(\n {\n id: getTranslationKey('input.notification.not-supported'),\n defaultMessage: `You can't upload this type of file, only the following types are accepted – {fileTypes}`,\n },\n { fileTypes: (allowedTypes ?? []).join(',') }\n ),\n });\n }\n\n if (allowedFiles.length === 0) {\n return;\n }\n\n const onFileUploaded = onDropFiles(event);\n\n const assetsCountByType = allowedFiles.reduce<Record<string, number>>((acc, file) => {\n const type = typeFromMime(file.type);\n acc[type] = (acc[type] ?? 0) + 1;\n return acc;\n }, {});\n trackUsage('didSelectFile', { source: 'computer', location: 'content-manager' });\n trackUsage('willAddMediaLibraryAssets', { location: 'content-manager', ...assetsCountByType });\n\n const formData = new FormData();\n allowedFiles.forEach((file) => formData.append('files', file));\n formData.append(\n 'fileInfo',\n JSON.stringify(\n allowedFiles.map((file) => ({\n name: file.name,\n caption: null,\n alternativeText: null,\n folder: null,\n }))\n )\n );\n\n try {\n await uploadFiles({\n formData,\n totalFiles: allowedFiles.length,\n concurrency: settings?.data?.concurrentUploadRequests ?? 1,\n generateAiMetadata: Boolean(isAiMetadataEnabled),\n onFileUploaded,\n }).unwrap();\n } catch {\n // Errors reach the user through the progress dialog, which the mutation\n // populates itself.\n }\n };\n\n return (\n <Root\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {children}\n {dragState !== 'idle' && (\n <Frame $dragState={dragState} data-testid=\"editor-file-drop-zone\">\n <Typography fontWeight=\"semiBold\" textColor={FRAME_COLORS[dragState].text}>\n {dragState === 'accept'\n ? formatMessage({\n id: getTranslationKey('editor-drop-zone.accept'),\n defaultMessage: 'Drop to upload and insert',\n })\n : formatMessage({\n id: getTranslationKey('editor-drop-zone.reject'),\n defaultMessage: \"You don't have permission to upload files\",\n })}\n </Typography>\n </Frame>\n )}\n </Root>\n );\n};\n"],"names":["FRAME_COLORS","accept","border","background","text","reject","Root","styled","div","Frame","theme","spaces","$dragState","colors","borderRadius","hasFiles","event","dataTransfer","types","includes","EditorFileDropZone","children","disabled","allowedTypes","onDropFiles","formatMessage","useIntl","toggleNotification","useNotification","trackUsage","useTracking","uploadFiles","useUploadFilesMutation","canRead","canCreate","isLoading","useMediaLibraryPermissions","data","settings","useGetUploadSettingsQuery","undefined","skip","isAiMetadataEnabled","useAIMetadataEnabled","dragState","setDragState","useState","dragDepth","useRef","canUpload","handleDragEnter","preventDefault","current","handleDragLeave","handleDragOver","dropEffect","handleDrop","files","Array","from","allowedFiles","filterAllowedFiles","length","type","timeout","message","id","getTranslationKey","defaultMessage","fileTypes","join","onFileUploaded","assetsCountByType","reduce","acc","file","typeFromMime","source","location","formData","FormData","forEach","append","JSON","stringify","map","name","caption","alternativeText","folder","totalFiles","concurrency","concurrentUploadRequests","generateAiMetadata","Boolean","unwrap","_jsxs","onDragEnter","onDragLeave","onDragOver","onDrop","_jsx","data-testid","Typography","fontWeight","textColor"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
4
5
|
var designSystem = require('@strapi/design-system');
|
|
5
6
|
var icons = require('@strapi/icons');
|
|
6
7
|
var reactIntl = require('react-intl');
|
|
@@ -8,6 +9,7 @@ var styledComponents = require('styled-components');
|
|
|
8
9
|
var useMediaLibraryPermissions = require('../../hooks/useMediaLibraryPermissions.js');
|
|
9
10
|
var ActionsMenuContent = require('../../pages/Assets/components/ActionsMenuContent.js');
|
|
10
11
|
var translations = require('../../utils/translations.js');
|
|
12
|
+
var FieldControls = require('./FieldControls.js');
|
|
11
13
|
|
|
12
14
|
// The trigger reads as a link on the label row, not as a button: no padding, no
|
|
13
15
|
// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the
|
|
@@ -71,9 +73,10 @@ const AddAssetTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
|
|
|
71
73
|
*
|
|
72
74
|
* The drop zone below keeps working whatever this shows — it is a second way
|
|
73
75
|
* in, not the only one.
|
|
74
|
-
*/ const AddAssetMenu = ({ disabled = false, onBrowseLibrary, onUploadFromDevice, onUploadFromUrl })=>{
|
|
76
|
+
*/ const AddAssetMenu = ({ disabled = false, preventOpen = false, onBrowseLibrary, onUploadFromDevice, onUploadFromUrl })=>{
|
|
75
77
|
const { formatMessage } = reactIntl.useIntl();
|
|
76
78
|
const { canRead, canCreate, isLoading } = useMediaLibraryPermissions.useMediaLibraryPermissions();
|
|
79
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
77
80
|
// `useRBAC` starts every instance at `isLoading: true` with the flags false.
|
|
78
81
|
// Until it settles, every entry shows but none can be picked: hiding them
|
|
79
82
|
// would flash a smaller menu, enabling them would lead to a 403.
|
|
@@ -83,6 +86,8 @@ const AddAssetTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
|
|
|
83
86
|
return null;
|
|
84
87
|
}
|
|
85
88
|
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Menu.Root, {
|
|
89
|
+
open: isOpen,
|
|
90
|
+
onOpenChange: (open)=>setIsOpen(open && !preventOpen),
|
|
86
91
|
children: [
|
|
87
92
|
/*#__PURE__*/ jsxRuntime.jsx(AddAssetTrigger, {
|
|
88
93
|
variant: "ghost",
|
|
@@ -100,7 +105,7 @@ const AddAssetTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
|
|
|
100
105
|
zIndex: 2,
|
|
101
106
|
minWidth: "22rem",
|
|
102
107
|
children: [
|
|
103
|
-
canBrowse && /*#__PURE__*/ jsxRuntime.jsx(
|
|
108
|
+
canBrowse && /*#__PURE__*/ jsxRuntime.jsx(FieldControls.FieldMenuItem, {
|
|
104
109
|
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Images, {}),
|
|
105
110
|
disabled: isLoading,
|
|
106
111
|
onSelect: onBrowseLibrary,
|
|
@@ -111,7 +116,7 @@ const AddAssetTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
|
|
|
111
116
|
}),
|
|
112
117
|
canUpload && /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
113
118
|
children: [
|
|
114
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
119
|
+
/*#__PURE__*/ jsxRuntime.jsx(FieldControls.FieldMenuItem, {
|
|
115
120
|
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Upload, {}),
|
|
116
121
|
disabled: isLoading,
|
|
117
122
|
onSelect: onUploadFromDevice,
|
|
@@ -120,7 +125,7 @@ const AddAssetTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
|
|
|
120
125
|
defaultMessage: 'Upload from device'
|
|
121
126
|
})
|
|
122
127
|
}),
|
|
123
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
128
|
+
/*#__PURE__*/ jsxRuntime.jsx(FieldControls.FieldMenuItem, {
|
|
124
129
|
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Link, {}),
|
|
125
130
|
disabled: isLoading,
|
|
126
131
|
onSelect: onUploadFromUrl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddAssetMenu.js","sources":["../../../../admin/src/components/MediaLibraryInput/AddAssetMenu.tsx"],"sourcesContent":["import { Menu } from '@strapi/design-system';\nimport { ChevronDown, Images, Link, Upload } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { ActionsMenuContent } from '../../pages/Assets/components/ActionsMenuContent';\nimport { getTranslationKey } from '../../utils/translations';\n\n// The trigger reads as a link on the label row, not as a button: no padding, no\n// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the\n// colour is set here and forced past the design system's own span rule.\nconst AddAssetTrigger = styled(Menu.Trigger)`\n padding: 0;\n\n // No hover treatment at all: this reads as a link on the label row, and the\n // design system's ghost button paints a primary100 plate behind it (also while\n // the menu is open, via data-state).\n &,\n &:hover,\n &[data-state='open'] {\n background: transparent;\n background-color: transparent;\n }\n\n &,\n & span,\n &:hover span {\n color: ${({ theme }) => theme.colors.primary600};\n }\n\n & span {\n font-weight: ${({ theme }) => theme.fontWeights.regular};\n }\n\n // The chevron needs the fill, not the colour: the design system paints button\n // icons with its own \"svg path { fill }\" rule per variant, and repaints them\n // again on hover — both beat an inherited color and the icon's own\n // fill=\"currentColor\". Doubled specificity so these land after those rules\n // whatever order they are injected in.\n && svg path,\n &&:hover svg path {\n fill: ${({ theme }) => theme.colors.primary600};\n }\n\n // The design system's disabled button is a bordered grey plate; this stays a\n // greyed-out link instead.\n &&[aria-disabled='true'] {\n border-color: transparent;\n background: transparent;\n }\n\n &[aria-disabled='true'],\n &[aria-disabled='true'] span {\n color: ${({ theme }) => theme.colors.neutral500};\n }\n\n &&[aria-disabled='true'] svg path {\n fill: ${({ theme }) => theme.colors.neutral500};\n }\n`;\n\ninterface AddAssetMenuProps {\n disabled?: boolean;\n onBrowseLibrary: () => void;\n onUploadFromDevice: () => void;\n onUploadFromUrl: () => void;\n}\n\n/**\n * The field's \"Add asset\" menu, on the label row.\n *\n * Browsing needs the Media Library's read permission, the two upload entries\n * `assets.create`; each entry disappears without its permission, and the\n * trigger itself goes when nothing is left to offer, rather than opening an\n * empty menu.\n *\n * The drop zone below keeps working whatever this shows — it is a second way\n * in, not the only one.\n */\nexport const AddAssetMenu = ({\n disabled = false,\n onBrowseLibrary,\n onUploadFromDevice,\n onUploadFromUrl,\n}: AddAssetMenuProps) => {\n const { formatMessage } = useIntl();\n const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();\n\n // `useRBAC` starts every instance at `isLoading: true` with the flags false.\n // Until it settles, every entry shows but none can be picked: hiding them\n // would flash a smaller menu, enabling them would lead to a 403.\n const canBrowse = isLoading || canRead;\n const canUpload = isLoading || canCreate;\n\n if (!canBrowse && !canUpload) {\n return null;\n }\n\n return (\n <Menu.Root>\n <AddAssetTrigger variant=\"ghost\" disabled={disabled} endIcon={<ChevronDown aria-hidden />}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset'),\n defaultMessage: 'Add asset',\n })}\n </AddAssetTrigger>\n\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canBrowse && (\n <
|
|
1
|
+
{"version":3,"file":"AddAssetMenu.js","sources":["../../../../admin/src/components/MediaLibraryInput/AddAssetMenu.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { Menu } from '@strapi/design-system';\nimport { ChevronDown, Images, Link, Upload } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { ActionsMenuContent } from '../../pages/Assets/components/ActionsMenuContent';\nimport { getTranslationKey } from '../../utils/translations';\n\nimport { FieldMenuItem } from './FieldControls';\n\n// The trigger reads as a link on the label row, not as a button: no padding, no\n// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the\n// colour is set here and forced past the design system's own span rule.\nconst AddAssetTrigger = styled(Menu.Trigger)`\n padding: 0;\n\n // No hover treatment at all: this reads as a link on the label row, and the\n // design system's ghost button paints a primary100 plate behind it (also while\n // the menu is open, via data-state).\n &,\n &:hover,\n &[data-state='open'] {\n background: transparent;\n background-color: transparent;\n }\n\n &,\n & span,\n &:hover span {\n color: ${({ theme }) => theme.colors.primary600};\n }\n\n & span {\n font-weight: ${({ theme }) => theme.fontWeights.regular};\n }\n\n // The chevron needs the fill, not the colour: the design system paints button\n // icons with its own \"svg path { fill }\" rule per variant, and repaints them\n // again on hover — both beat an inherited color and the icon's own\n // fill=\"currentColor\". Doubled specificity so these land after those rules\n // whatever order they are injected in.\n && svg path,\n &&:hover svg path {\n fill: ${({ theme }) => theme.colors.primary600};\n }\n\n // The design system's disabled button is a bordered grey plate; this stays a\n // greyed-out link instead.\n &&[aria-disabled='true'] {\n border-color: transparent;\n background: transparent;\n }\n\n &[aria-disabled='true'],\n &[aria-disabled='true'] span {\n color: ${({ theme }) => theme.colors.neutral500};\n }\n\n &&[aria-disabled='true'] svg path {\n fill: ${({ theme }) => theme.colors.neutral500};\n }\n`;\n\ninterface AddAssetMenuProps {\n disabled?: boolean;\n /**\n * Ignore requests to open, without looking disabled. The press still reaches\n * whatever listens for presses outside it, so an open drawer closes — or asks\n * about unsaved edits — instead of having the menu stacked over it.\n */\n preventOpen?: boolean;\n onBrowseLibrary: () => void;\n onUploadFromDevice: () => void;\n onUploadFromUrl: () => void;\n}\n\n/**\n * The field's \"Add asset\" menu, on the label row.\n *\n * Browsing needs the Media Library's read permission, the two upload entries\n * `assets.create`; each entry disappears without its permission, and the\n * trigger itself goes when nothing is left to offer, rather than opening an\n * empty menu.\n *\n * The drop zone below keeps working whatever this shows — it is a second way\n * in, not the only one.\n */\nexport const AddAssetMenu = ({\n disabled = false,\n preventOpen = false,\n onBrowseLibrary,\n onUploadFromDevice,\n onUploadFromUrl,\n}: AddAssetMenuProps) => {\n const { formatMessage } = useIntl();\n const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();\n const [isOpen, setIsOpen] = useState(false);\n\n // `useRBAC` starts every instance at `isLoading: true` with the flags false.\n // Until it settles, every entry shows but none can be picked: hiding them\n // would flash a smaller menu, enabling them would lead to a 403.\n const canBrowse = isLoading || canRead;\n const canUpload = isLoading || canCreate;\n\n if (!canBrowse && !canUpload) {\n return null;\n }\n\n return (\n <Menu.Root open={isOpen} onOpenChange={(open) => setIsOpen(open && !preventOpen)}>\n <AddAssetTrigger variant=\"ghost\" disabled={disabled} endIcon={<ChevronDown aria-hidden />}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset'),\n defaultMessage: 'Add asset',\n })}\n </AddAssetTrigger>\n\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canBrowse && (\n <FieldMenuItem startIcon={<Images />} disabled={isLoading} onSelect={onBrowseLibrary}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.browse'),\n defaultMessage: 'Browse library',\n })}\n </FieldMenuItem>\n )}\n\n {canUpload && (\n <>\n <FieldMenuItem\n startIcon={<Upload />}\n disabled={isLoading}\n onSelect={onUploadFromDevice}\n >\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.device'),\n defaultMessage: 'Upload from device',\n })}\n </FieldMenuItem>\n\n <FieldMenuItem startIcon={<Link />} disabled={isLoading} onSelect={onUploadFromUrl}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.url'),\n defaultMessage: 'Upload from URL',\n })}\n </FieldMenuItem>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n );\n};\n"],"names":["AddAssetTrigger","styled","Menu","Trigger","theme","colors","primary600","fontWeights","regular","neutral500","AddAssetMenu","disabled","preventOpen","onBrowseLibrary","onUploadFromDevice","onUploadFromUrl","formatMessage","useIntl","canRead","canCreate","isLoading","useMediaLibraryPermissions","isOpen","setIsOpen","useState","canBrowse","canUpload","_jsxs","Root","open","onOpenChange","_jsx","variant","endIcon","ChevronDown","aria-hidden","id","getTranslationKey","defaultMessage","ActionsMenuContent","popoverPlacement","zIndex","minWidth","FieldMenuItem","startIcon","Images","onSelect","_Fragment","Upload","Link"],"mappings":"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"}
|