@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,6 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
|
-
import { useQueryParams } from '@strapi/admin/strapi-admin';
|
|
3
2
|
import { encodeSearchQuery } from '../../../utils/searchQueryParam.mjs';
|
|
3
|
+
import { useListQueryParams } from './useListQueryParams.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Reads and writes the global asset search term held in `?_q=`.
|
|
@@ -8,7 +8,7 @@ import { encodeSearchQuery } from '../../../utils/searchQueryParam.mjs';
|
|
|
8
8
|
* Debouncing is the input component's job (see `AssetsSearchInput`) — this hook
|
|
9
9
|
* is a thin URL accessor so every consumer reads the same source of truth.
|
|
10
10
|
*/ const useAssetSearch = ()=>{
|
|
11
|
-
const [{ query }, setQuery] =
|
|
11
|
+
const [{ query }, setQuery] = useListQueryParams();
|
|
12
12
|
const searchQuery = query?._q ?? '';
|
|
13
13
|
const setSearchQuery = useCallback((value)=>{
|
|
14
14
|
if (value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetSearch.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetSearch.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useAssetSearch.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetSearch.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { encodeSearchQuery } from '../../../utils/searchQueryParam';\n\nimport { useListQueryParams } from './useListQueryParams';\n\n/**\n * Reads and writes the global asset search term held in `?_q=`.\n *\n * Debouncing is the input component's job (see `AssetsSearchInput`) — this hook\n * is a thin URL accessor so every consumer reads the same source of truth.\n */\nexport const useAssetSearch = () => {\n const [{ query }, setQuery] = useListQueryParams<{ _q?: string }>();\n\n const searchQuery = query?._q ?? '';\n\n const setSearchQuery = useCallback(\n (value: string) => {\n if (value) {\n setQuery({ _q: encodeSearchQuery(value) }, 'push', true);\n } else {\n setQuery({ _q: '' }, 'remove', true);\n }\n },\n [setQuery]\n );\n\n const clearSearch = useCallback(() => setSearchQuery(''), [setSearchQuery]);\n\n return {\n searchQuery,\n isSearching: searchQuery !== '',\n setSearchQuery,\n clearSearch,\n };\n};\n"],"names":["useAssetSearch","query","setQuery","useListQueryParams","searchQuery","_q","setSearchQuery","useCallback","value","encodeSearchQuery","clearSearch","isSearching"],"mappings":";;;;AAMA;;;;;UAMaA,cAAAA,GAAiB,IAAA;AAC5B,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,kBAAAA,EAAAA;IAE9B,MAAMC,WAAAA,GAAcH,OAAOI,EAAAA,IAAM,EAAA;IAEjC,MAAMC,cAAAA,GAAiBC,YACrB,CAACC,KAAAA,GAAAA;AACC,QAAA,IAAIA,KAAAA,EAAO;YACTN,QAAAA,CAAS;AAAEG,gBAAAA,EAAAA,EAAII,iBAAAA,CAAkBD,KAAAA;AAAO,aAAA,EAAG,MAAA,EAAQ,IAAA,CAAA;QACrD,CAAA,MAAO;YACLN,QAAAA,CAAS;gBAAEG,EAAAA,EAAI;AAAG,aAAA,EAAG,QAAA,EAAU,IAAA,CAAA;AACjC,QAAA;IACF,CAAA,EACA;AAACH,QAAAA;AAAS,KAAA,CAAA;AAGZ,IAAA,MAAMQ,WAAAA,GAAcH,WAAAA,CAAY,IAAMD,cAAAA,CAAe,EAAA,CAAA,EAAK;AAACA,QAAAA;AAAe,KAAA,CAAA;IAE1E,OAAO;AACLF,QAAAA,WAAAA;AACAO,QAAAA,WAAAA,EAAaP,WAAAA,KAAgB,EAAA;AAC7BE,QAAAA,cAAAA;AACAI,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
|
+
var useMediaLibraryPermissions = require('../../../hooks/useMediaLibraryPermissions.js');
|
|
4
5
|
var selection = require('../utils/selection.js');
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Exported so a host with its own selection rules (the Content Manager asset
|
|
9
|
+
* picker) can feed the same views a different implementation.
|
|
10
|
+
*/ const AssetSelectionContext = React.createContext(null);
|
|
7
11
|
const AssetSelectionProvider = ({ children, disabled = false })=>{
|
|
8
12
|
const [state, setState] = React.useState(selection.createEmptySelection);
|
|
13
|
+
// Every bulk action needs `assets.update`: without it the views show no
|
|
14
|
+
// checkboxes, whatever the host passes as `disabled`.
|
|
15
|
+
const { canUpdate } = useMediaLibraryPermissions.useMediaLibraryPermissions();
|
|
16
|
+
const isEnabled = !disabled && canUpdate;
|
|
9
17
|
const isSelected = React.useCallback((key)=>!disabled && state.selectedKeys.has(key), [
|
|
10
18
|
disabled,
|
|
11
19
|
state.selectedKeys
|
|
@@ -46,7 +54,13 @@ const AssetSelectionProvider = ({ children, disabled = false })=>{
|
|
|
46
54
|
const selectedFolderIds = React.useMemo(()=>selection.getIdsOfKind(state.selectedKeys, 'folder'), [
|
|
47
55
|
state.selectedKeys
|
|
48
56
|
]);
|
|
57
|
+
const getSelectability = React.useCallback(()=>isEnabled ? 'enabled' : 'hidden', [
|
|
58
|
+
isEnabled
|
|
59
|
+
]);
|
|
49
60
|
const value = React.useMemo(()=>({
|
|
61
|
+
isEnabled,
|
|
62
|
+
canSelectAll: true,
|
|
63
|
+
getSelectability,
|
|
50
64
|
selectedKeys: state.selectedKeys,
|
|
51
65
|
selectedIds,
|
|
52
66
|
selectedFolderIds,
|
|
@@ -57,8 +71,11 @@ const AssetSelectionProvider = ({ children, disabled = false })=>{
|
|
|
57
71
|
selectAll,
|
|
58
72
|
selectOnly,
|
|
59
73
|
deselect,
|
|
74
|
+
deselectAll: clear,
|
|
60
75
|
clear
|
|
61
76
|
}), [
|
|
77
|
+
isEnabled,
|
|
78
|
+
getSelectability,
|
|
62
79
|
state.selectedKeys,
|
|
63
80
|
selectedIds,
|
|
64
81
|
selectedFolderIds,
|
|
@@ -84,6 +101,7 @@ const useAssetSelection = ()=>{
|
|
|
84
101
|
};
|
|
85
102
|
const useAssetSelectionOptional = ()=>React.useContext(AssetSelectionContext);
|
|
86
103
|
|
|
104
|
+
exports.AssetSelectionContext = AssetSelectionContext;
|
|
87
105
|
exports.AssetSelectionProvider = AssetSelectionProvider;
|
|
88
106
|
exports.useAssetSelection = useAssetSelection;
|
|
89
107
|
exports.useAssetSelectionOptional = useAssetSelectionOptional;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetSelection.js","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetSelection.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\nimport {\n clearSelection,\n createEmptySelection,\n deselect as deselectState,\n getIdsOfKind,\n selectAll as selectAllState,\n selectRange as selectRangeState,\n toggleSelection,\n type ItemKey,\n type SelectionState,\n} from '../utils/selection';\n\n/**\n * Ephemeral, view-state-only multi-select for the future Media Library. Selection\n * is page-scoped and reset on folder navigation or sort/filter changes (the\n * table/grid toggle keeps it — same list, different presentation).\n *\n * The actual computation lives in `../utils/selection.ts` (pure + unit-tested);\n * this hook is a thin React wrapper. Assets and folders share one mechanism —\n * items are tracked as namespaced keys (`asset:1` / `folder:1`) so toggle, range\n * and select-all behave the same for both. Range / select-all receive the\n * ordered key array from the caller (the view owns the rendered order), keeping\n * the context data-source-agnostic.\n */\nexport interface AssetSelection {\n /** Every selected item key (assets and folders), render-order agnostic. */\n selectedKeys: Set<ItemKey>;\n /** Selected asset ids, derived from {@link selectedKeys}. */\n selectedIds: Set<number>;\n /** Selected folder ids, derived from {@link selectedKeys}. */\n selectedFolderIds: Set<number>;\n anchorKey: ItemKey | null;\n isSelected: (key: ItemKey) => boolean;\n /** Additive toggle (Cmd/Ctrl+click, item checkbox). */\n toggle: (key: ItemKey) => void;\n /** Shift+click — selects the contiguous range from the anchor to the target. */\n selectRange: (orderedKeys: ItemKey[], targetKey: ItemKey) => void;\n /** Header checkbox — selects every rendered item (folders and assets). */\n selectAll: (orderedKeys: ItemKey[]) => void;\n /**\n * Replaces the selection with this one key, as a right-click on an unselected\n * item does: what the menu then acts on is what the user can see is selected.\n */\n selectOnly: (key: ItemKey) => void;\n /** Row-level \"...\" menu — drops one key when its item leaves the list (move, delete). */\n deselect: (key: ItemKey) => void;\n /** Close button / folder navigation / list-identity changes. */\n clear: () => void;\n}\n\nconst AssetSelectionContext = createContext<AssetSelection | null>(null);\n\ninterface AssetSelectionProviderProps {\n children: ReactNode;\n /**\n * When true, selection is inert: every mutator is a no-op and nothing ever\n * reads as selected. Every bulk action is gated on `assets.update`, so a user\n * without it has nothing to select for — the views also hide the checkboxes,\n * and this makes the remaining paths (click-to-select, Space key) do nothing.\n */\n disabled?: boolean;\n}\n\nexport const AssetSelectionProvider = ({\n children,\n disabled = false,\n}: AssetSelectionProviderProps) => {\n const [state, setState] = useState<SelectionState>(createEmptySelection);\n\n const isSelected = useCallback(\n (key: ItemKey) => !disabled && state.selectedKeys.has(key),\n [disabled, state.selectedKeys]\n );\n\n const toggle = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState((prev) => toggleSelection(prev, key));\n },\n [disabled]\n );\n\n const selectRange = useCallback(\n (orderedKeys: ItemKey[], targetKey: ItemKey) => {\n if (disabled) return;\n setState((prev) => selectRangeState(prev, orderedKeys, targetKey));\n },\n [disabled]\n );\n\n const selectAll = useCallback(\n (orderedKeys: ItemKey[]) => {\n if (disabled) return;\n setState(selectAllState(orderedKeys));\n },\n [disabled]\n );\n\n const selectOnly = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState(selectAllState([key]));\n },\n [disabled]\n );\n\n // No `disabled` guard, like `clear`: this only ever shrinks the selection, and a\n // disabled provider has nothing in it (every additive path is guarded).\n const deselect = useCallback((key: ItemKey) => setState((prev) => deselectState(prev, key)), []);\n\n const clear = useCallback(() => setState(clearSelection()), []);\n\n const selectedIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'asset'),\n [state.selectedKeys]\n );\n const selectedFolderIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'folder'),\n [state.selectedKeys]\n );\n\n const value = useMemo<AssetSelection>(\n () => ({\n selectedKeys: state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n anchorKey: state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n clear,\n }),\n [\n state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n clear,\n ]\n );\n\n return createElement(AssetSelectionContext.Provider, { value }, children);\n};\n\nexport const useAssetSelection = () => {\n const context = useContext(AssetSelectionContext);\n\n if (!context) {\n throw new Error('useAssetSelection must be used within an AssetSelectionProvider');\n }\n\n return context;\n};\n\nexport const useAssetSelectionOptional = () => useContext(AssetSelectionContext);\n"],"names":["AssetSelectionContext","createContext","AssetSelectionProvider","children","disabled","state","setState","useState","createEmptySelection","isSelected","useCallback","key","selectedKeys","has","toggle","prev","toggleSelection","selectRange","orderedKeys","targetKey","selectRangeState","selectAll","selectAllState","selectOnly","deselect","deselectState","clear","clearSelection","selectedIds","useMemo","getIdsOfKind","selectedFolderIds","value","anchorKey","createElement","Provider","useAssetSelection","context","useContext","Error","useAssetSelectionOptional"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAssetSelection.js","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetSelection.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport {\n clearSelection,\n createEmptySelection,\n deselect as deselectState,\n getIdsOfKind,\n selectAll as selectAllState,\n selectRange as selectRangeState,\n toggleSelection,\n type ItemKey,\n type SelectionState,\n} from '../utils/selection';\n\n/**\n * Ephemeral, view-state-only multi-select for the future Media Library. Selection\n * is page-scoped and reset on folder navigation or sort/filter changes (the\n * table/grid toggle keeps it — same list, different presentation).\n *\n * The actual computation lives in `../utils/selection.ts` (pure + unit-tested);\n * this hook is a thin React wrapper. Assets and folders share one mechanism —\n * items are tracked as namespaced keys (`asset:1` / `folder:1`) so toggle, range\n * and select-all behave the same for both. Range / select-all receive the\n * ordered key array from the caller (the view owns the rendered order), keeping\n * the context data-source-agnostic.\n */\n/**\n * How an item takes part in selection: `enabled` shows a working checkbox,\n * `disabled` shows it greyed out (the item cannot be chosen here), `hidden`\n * shows none (the item is not something this selection is about).\n */\nexport type Selectability = 'enabled' | 'disabled' | 'hidden';\n\nexport interface AssetSelection {\n /**\n * Whether selection is on at all. Views show the checkbox column and\n * select-all only when it is.\n */\n isEnabled: boolean;\n /** Whether the table offers a select-all header (not on a single-value picker). */\n canSelectAll: boolean;\n getSelectability: (key: ItemKey) => Selectability;\n /** Every selected item key (assets and folders), render-order agnostic. */\n selectedKeys: Set<ItemKey>;\n /** Selected asset ids, derived from {@link selectedKeys}. */\n selectedIds: Set<number>;\n /** Selected folder ids, derived from {@link selectedKeys}. */\n selectedFolderIds: Set<number>;\n anchorKey: ItemKey | null;\n isSelected: (key: ItemKey) => boolean;\n /** Additive toggle (Cmd/Ctrl+click, item checkbox). */\n toggle: (key: ItemKey) => void;\n /** Shift+click — selects the contiguous range from the anchor to the target. */\n selectRange: (orderedKeys: ItemKey[], targetKey: ItemKey) => void;\n /** Header checkbox — selects every rendered item (folders and assets). */\n selectAll: (orderedKeys: ItemKey[]) => void;\n /**\n * Replaces the selection with this one key, as a right-click on an unselected\n * item does: what the menu then acts on is what the user can see is selected.\n */\n selectOnly: (key: ItemKey) => void;\n /** Row-level \"...\" menu — drops one key when its item leaves the list (move, delete). */\n deselect: (key: ItemKey) => void;\n /**\n * Header checkbox, when everything it covers is selected. The host decides how\n * far that reaches: the Media Library page clears the whole selection, because\n * it can still hold keys that left the list without being deselected (moved or\n * deleted from the details drawer). The picker drops only these keys.\n */\n deselectAll: (orderedKeys: ItemKey[]) => void;\n /** Close button / folder navigation / list-identity changes. */\n clear: () => void;\n}\n\n/**\n * Exported so a host with its own selection rules (the Content Manager asset\n * picker) can feed the same views a different implementation.\n */\nexport const AssetSelectionContext = createContext<AssetSelection | null>(null);\n\ninterface AssetSelectionProviderProps {\n children: ReactNode;\n /**\n * When true, selection is inert: every mutator is a no-op and nothing ever\n * reads as selected. Every bulk action is gated on `assets.update`, so a user\n * without it has nothing to select for — the views also hide the checkboxes,\n * and this makes the remaining paths (click-to-select, Space key) do nothing.\n */\n disabled?: boolean;\n}\n\nexport const AssetSelectionProvider = ({\n children,\n disabled = false,\n}: AssetSelectionProviderProps) => {\n const [state, setState] = useState<SelectionState>(createEmptySelection);\n // Every bulk action needs `assets.update`: without it the views show no\n // checkboxes, whatever the host passes as `disabled`.\n const { canUpdate } = useMediaLibraryPermissions();\n const isEnabled = !disabled && canUpdate;\n\n const isSelected = useCallback(\n (key: ItemKey) => !disabled && state.selectedKeys.has(key),\n [disabled, state.selectedKeys]\n );\n\n const toggle = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState((prev) => toggleSelection(prev, key));\n },\n [disabled]\n );\n\n const selectRange = useCallback(\n (orderedKeys: ItemKey[], targetKey: ItemKey) => {\n if (disabled) return;\n setState((prev) => selectRangeState(prev, orderedKeys, targetKey));\n },\n [disabled]\n );\n\n const selectAll = useCallback(\n (orderedKeys: ItemKey[]) => {\n if (disabled) return;\n setState(selectAllState(orderedKeys));\n },\n [disabled]\n );\n\n const selectOnly = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState(selectAllState([key]));\n },\n [disabled]\n );\n\n // No `disabled` guard, like `clear`: this only ever shrinks the selection, and a\n // disabled provider has nothing in it (every additive path is guarded).\n const deselect = useCallback((key: ItemKey) => setState((prev) => deselectState(prev, key)), []);\n\n const clear = useCallback(() => setState(clearSelection()), []);\n\n const selectedIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'asset'),\n [state.selectedKeys]\n );\n const selectedFolderIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'folder'),\n [state.selectedKeys]\n );\n\n const getSelectability = useCallback(\n (): Selectability => (isEnabled ? 'enabled' : 'hidden'),\n [isEnabled]\n );\n\n const value = useMemo<AssetSelection>(\n () => ({\n isEnabled,\n canSelectAll: true,\n getSelectability,\n selectedKeys: state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n anchorKey: state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n deselectAll: clear,\n clear,\n }),\n [\n isEnabled,\n getSelectability,\n state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n clear,\n ]\n );\n\n return createElement(AssetSelectionContext.Provider, { value }, children);\n};\n\nexport const useAssetSelection = () => {\n const context = useContext(AssetSelectionContext);\n\n if (!context) {\n throw new Error('useAssetSelection must be used within an AssetSelectionProvider');\n }\n\n return context;\n};\n\nexport const useAssetSelectionOptional = () => useContext(AssetSelectionContext);\n"],"names":["AssetSelectionContext","createContext","AssetSelectionProvider","children","disabled","state","setState","useState","createEmptySelection","canUpdate","useMediaLibraryPermissions","isEnabled","isSelected","useCallback","key","selectedKeys","has","toggle","prev","toggleSelection","selectRange","orderedKeys","targetKey","selectRangeState","selectAll","selectAllState","selectOnly","deselect","deselectState","clear","clearSelection","selectedIds","useMemo","getIdsOfKind","selectedFolderIds","getSelectability","value","canSelectAll","anchorKey","deselectAll","createElement","Provider","useAssetSelection","context","useContext","Error","useAssetSelectionOptional"],"mappings":"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"}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { useState, useCallback, useMemo, createElement,
|
|
1
|
+
import { createContext, useState, useCallback, useMemo, createElement, useContext } from 'react';
|
|
2
|
+
import { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions.mjs';
|
|
2
3
|
import { createEmptySelection, toggleSelection, selectRange, selectAll, deselect, clearSelection, getIdsOfKind } from '../utils/selection.mjs';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Exported so a host with its own selection rules (the Content Manager asset
|
|
7
|
+
* picker) can feed the same views a different implementation.
|
|
8
|
+
*/ const AssetSelectionContext = createContext(null);
|
|
5
9
|
const AssetSelectionProvider = ({ children, disabled = false })=>{
|
|
6
10
|
const [state, setState] = useState(createEmptySelection);
|
|
11
|
+
// Every bulk action needs `assets.update`: without it the views show no
|
|
12
|
+
// checkboxes, whatever the host passes as `disabled`.
|
|
13
|
+
const { canUpdate } = useMediaLibraryPermissions();
|
|
14
|
+
const isEnabled = !disabled && canUpdate;
|
|
7
15
|
const isSelected = useCallback((key)=>!disabled && state.selectedKeys.has(key), [
|
|
8
16
|
disabled,
|
|
9
17
|
state.selectedKeys
|
|
@@ -44,7 +52,13 @@ const AssetSelectionProvider = ({ children, disabled = false })=>{
|
|
|
44
52
|
const selectedFolderIds = useMemo(()=>getIdsOfKind(state.selectedKeys, 'folder'), [
|
|
45
53
|
state.selectedKeys
|
|
46
54
|
]);
|
|
55
|
+
const getSelectability = useCallback(()=>isEnabled ? 'enabled' : 'hidden', [
|
|
56
|
+
isEnabled
|
|
57
|
+
]);
|
|
47
58
|
const value = useMemo(()=>({
|
|
59
|
+
isEnabled,
|
|
60
|
+
canSelectAll: true,
|
|
61
|
+
getSelectability,
|
|
48
62
|
selectedKeys: state.selectedKeys,
|
|
49
63
|
selectedIds,
|
|
50
64
|
selectedFolderIds,
|
|
@@ -55,8 +69,11 @@ const AssetSelectionProvider = ({ children, disabled = false })=>{
|
|
|
55
69
|
selectAll: selectAll$1,
|
|
56
70
|
selectOnly,
|
|
57
71
|
deselect: deselect$1,
|
|
72
|
+
deselectAll: clear,
|
|
58
73
|
clear
|
|
59
74
|
}), [
|
|
75
|
+
isEnabled,
|
|
76
|
+
getSelectability,
|
|
60
77
|
state.selectedKeys,
|
|
61
78
|
selectedIds,
|
|
62
79
|
selectedFolderIds,
|
|
@@ -82,5 +99,5 @@ const useAssetSelection = ()=>{
|
|
|
82
99
|
};
|
|
83
100
|
const useAssetSelectionOptional = ()=>useContext(AssetSelectionContext);
|
|
84
101
|
|
|
85
|
-
export { AssetSelectionProvider, useAssetSelection, useAssetSelectionOptional };
|
|
102
|
+
export { AssetSelectionContext, AssetSelectionProvider, useAssetSelection, useAssetSelectionOptional };
|
|
86
103
|
//# sourceMappingURL=useAssetSelection.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssetSelection.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetSelection.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\nimport {\n clearSelection,\n createEmptySelection,\n deselect as deselectState,\n getIdsOfKind,\n selectAll as selectAllState,\n selectRange as selectRangeState,\n toggleSelection,\n type ItemKey,\n type SelectionState,\n} from '../utils/selection';\n\n/**\n * Ephemeral, view-state-only multi-select for the future Media Library. Selection\n * is page-scoped and reset on folder navigation or sort/filter changes (the\n * table/grid toggle keeps it — same list, different presentation).\n *\n * The actual computation lives in `../utils/selection.ts` (pure + unit-tested);\n * this hook is a thin React wrapper. Assets and folders share one mechanism —\n * items are tracked as namespaced keys (`asset:1` / `folder:1`) so toggle, range\n * and select-all behave the same for both. Range / select-all receive the\n * ordered key array from the caller (the view owns the rendered order), keeping\n * the context data-source-agnostic.\n */\nexport interface AssetSelection {\n /** Every selected item key (assets and folders), render-order agnostic. */\n selectedKeys: Set<ItemKey>;\n /** Selected asset ids, derived from {@link selectedKeys}. */\n selectedIds: Set<number>;\n /** Selected folder ids, derived from {@link selectedKeys}. */\n selectedFolderIds: Set<number>;\n anchorKey: ItemKey | null;\n isSelected: (key: ItemKey) => boolean;\n /** Additive toggle (Cmd/Ctrl+click, item checkbox). */\n toggle: (key: ItemKey) => void;\n /** Shift+click — selects the contiguous range from the anchor to the target. */\n selectRange: (orderedKeys: ItemKey[], targetKey: ItemKey) => void;\n /** Header checkbox — selects every rendered item (folders and assets). */\n selectAll: (orderedKeys: ItemKey[]) => void;\n /**\n * Replaces the selection with this one key, as a right-click on an unselected\n * item does: what the menu then acts on is what the user can see is selected.\n */\n selectOnly: (key: ItemKey) => void;\n /** Row-level \"...\" menu — drops one key when its item leaves the list (move, delete). */\n deselect: (key: ItemKey) => void;\n /** Close button / folder navigation / list-identity changes. */\n clear: () => void;\n}\n\nconst AssetSelectionContext = createContext<AssetSelection | null>(null);\n\ninterface AssetSelectionProviderProps {\n children: ReactNode;\n /**\n * When true, selection is inert: every mutator is a no-op and nothing ever\n * reads as selected. Every bulk action is gated on `assets.update`, so a user\n * without it has nothing to select for — the views also hide the checkboxes,\n * and this makes the remaining paths (click-to-select, Space key) do nothing.\n */\n disabled?: boolean;\n}\n\nexport const AssetSelectionProvider = ({\n children,\n disabled = false,\n}: AssetSelectionProviderProps) => {\n const [state, setState] = useState<SelectionState>(createEmptySelection);\n\n const isSelected = useCallback(\n (key: ItemKey) => !disabled && state.selectedKeys.has(key),\n [disabled, state.selectedKeys]\n );\n\n const toggle = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState((prev) => toggleSelection(prev, key));\n },\n [disabled]\n );\n\n const selectRange = useCallback(\n (orderedKeys: ItemKey[], targetKey: ItemKey) => {\n if (disabled) return;\n setState((prev) => selectRangeState(prev, orderedKeys, targetKey));\n },\n [disabled]\n );\n\n const selectAll = useCallback(\n (orderedKeys: ItemKey[]) => {\n if (disabled) return;\n setState(selectAllState(orderedKeys));\n },\n [disabled]\n );\n\n const selectOnly = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState(selectAllState([key]));\n },\n [disabled]\n );\n\n // No `disabled` guard, like `clear`: this only ever shrinks the selection, and a\n // disabled provider has nothing in it (every additive path is guarded).\n const deselect = useCallback((key: ItemKey) => setState((prev) => deselectState(prev, key)), []);\n\n const clear = useCallback(() => setState(clearSelection()), []);\n\n const selectedIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'asset'),\n [state.selectedKeys]\n );\n const selectedFolderIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'folder'),\n [state.selectedKeys]\n );\n\n const value = useMemo<AssetSelection>(\n () => ({\n selectedKeys: state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n anchorKey: state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n clear,\n }),\n [\n state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n clear,\n ]\n );\n\n return createElement(AssetSelectionContext.Provider, { value }, children);\n};\n\nexport const useAssetSelection = () => {\n const context = useContext(AssetSelectionContext);\n\n if (!context) {\n throw new Error('useAssetSelection must be used within an AssetSelectionProvider');\n }\n\n return context;\n};\n\nexport const useAssetSelectionOptional = () => useContext(AssetSelectionContext);\n"],"names":["AssetSelectionContext","createContext","AssetSelectionProvider","children","disabled","state","setState","useState","createEmptySelection","isSelected","useCallback","key","selectedKeys","has","toggle","prev","toggleSelection","selectRange","orderedKeys","targetKey","selectRangeState","selectAll","selectAllState","selectOnly","deselect","deselectState","clear","clearSelection","selectedIds","useMemo","getIdsOfKind","selectedFolderIds","value","anchorKey","createElement","Provider","useAssetSelection","context","useContext","Error","useAssetSelectionOptional"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAssetSelection.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetSelection.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport {\n clearSelection,\n createEmptySelection,\n deselect as deselectState,\n getIdsOfKind,\n selectAll as selectAllState,\n selectRange as selectRangeState,\n toggleSelection,\n type ItemKey,\n type SelectionState,\n} from '../utils/selection';\n\n/**\n * Ephemeral, view-state-only multi-select for the future Media Library. Selection\n * is page-scoped and reset on folder navigation or sort/filter changes (the\n * table/grid toggle keeps it — same list, different presentation).\n *\n * The actual computation lives in `../utils/selection.ts` (pure + unit-tested);\n * this hook is a thin React wrapper. Assets and folders share one mechanism —\n * items are tracked as namespaced keys (`asset:1` / `folder:1`) so toggle, range\n * and select-all behave the same for both. Range / select-all receive the\n * ordered key array from the caller (the view owns the rendered order), keeping\n * the context data-source-agnostic.\n */\n/**\n * How an item takes part in selection: `enabled` shows a working checkbox,\n * `disabled` shows it greyed out (the item cannot be chosen here), `hidden`\n * shows none (the item is not something this selection is about).\n */\nexport type Selectability = 'enabled' | 'disabled' | 'hidden';\n\nexport interface AssetSelection {\n /**\n * Whether selection is on at all. Views show the checkbox column and\n * select-all only when it is.\n */\n isEnabled: boolean;\n /** Whether the table offers a select-all header (not on a single-value picker). */\n canSelectAll: boolean;\n getSelectability: (key: ItemKey) => Selectability;\n /** Every selected item key (assets and folders), render-order agnostic. */\n selectedKeys: Set<ItemKey>;\n /** Selected asset ids, derived from {@link selectedKeys}. */\n selectedIds: Set<number>;\n /** Selected folder ids, derived from {@link selectedKeys}. */\n selectedFolderIds: Set<number>;\n anchorKey: ItemKey | null;\n isSelected: (key: ItemKey) => boolean;\n /** Additive toggle (Cmd/Ctrl+click, item checkbox). */\n toggle: (key: ItemKey) => void;\n /** Shift+click — selects the contiguous range from the anchor to the target. */\n selectRange: (orderedKeys: ItemKey[], targetKey: ItemKey) => void;\n /** Header checkbox — selects every rendered item (folders and assets). */\n selectAll: (orderedKeys: ItemKey[]) => void;\n /**\n * Replaces the selection with this one key, as a right-click on an unselected\n * item does: what the menu then acts on is what the user can see is selected.\n */\n selectOnly: (key: ItemKey) => void;\n /** Row-level \"...\" menu — drops one key when its item leaves the list (move, delete). */\n deselect: (key: ItemKey) => void;\n /**\n * Header checkbox, when everything it covers is selected. The host decides how\n * far that reaches: the Media Library page clears the whole selection, because\n * it can still hold keys that left the list without being deselected (moved or\n * deleted from the details drawer). The picker drops only these keys.\n */\n deselectAll: (orderedKeys: ItemKey[]) => void;\n /** Close button / folder navigation / list-identity changes. */\n clear: () => void;\n}\n\n/**\n * Exported so a host with its own selection rules (the Content Manager asset\n * picker) can feed the same views a different implementation.\n */\nexport const AssetSelectionContext = createContext<AssetSelection | null>(null);\n\ninterface AssetSelectionProviderProps {\n children: ReactNode;\n /**\n * When true, selection is inert: every mutator is a no-op and nothing ever\n * reads as selected. Every bulk action is gated on `assets.update`, so a user\n * without it has nothing to select for — the views also hide the checkboxes,\n * and this makes the remaining paths (click-to-select, Space key) do nothing.\n */\n disabled?: boolean;\n}\n\nexport const AssetSelectionProvider = ({\n children,\n disabled = false,\n}: AssetSelectionProviderProps) => {\n const [state, setState] = useState<SelectionState>(createEmptySelection);\n // Every bulk action needs `assets.update`: without it the views show no\n // checkboxes, whatever the host passes as `disabled`.\n const { canUpdate } = useMediaLibraryPermissions();\n const isEnabled = !disabled && canUpdate;\n\n const isSelected = useCallback(\n (key: ItemKey) => !disabled && state.selectedKeys.has(key),\n [disabled, state.selectedKeys]\n );\n\n const toggle = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState((prev) => toggleSelection(prev, key));\n },\n [disabled]\n );\n\n const selectRange = useCallback(\n (orderedKeys: ItemKey[], targetKey: ItemKey) => {\n if (disabled) return;\n setState((prev) => selectRangeState(prev, orderedKeys, targetKey));\n },\n [disabled]\n );\n\n const selectAll = useCallback(\n (orderedKeys: ItemKey[]) => {\n if (disabled) return;\n setState(selectAllState(orderedKeys));\n },\n [disabled]\n );\n\n const selectOnly = useCallback(\n (key: ItemKey) => {\n if (disabled) return;\n setState(selectAllState([key]));\n },\n [disabled]\n );\n\n // No `disabled` guard, like `clear`: this only ever shrinks the selection, and a\n // disabled provider has nothing in it (every additive path is guarded).\n const deselect = useCallback((key: ItemKey) => setState((prev) => deselectState(prev, key)), []);\n\n const clear = useCallback(() => setState(clearSelection()), []);\n\n const selectedIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'asset'),\n [state.selectedKeys]\n );\n const selectedFolderIds = useMemo(\n () => getIdsOfKind(state.selectedKeys, 'folder'),\n [state.selectedKeys]\n );\n\n const getSelectability = useCallback(\n (): Selectability => (isEnabled ? 'enabled' : 'hidden'),\n [isEnabled]\n );\n\n const value = useMemo<AssetSelection>(\n () => ({\n isEnabled,\n canSelectAll: true,\n getSelectability,\n selectedKeys: state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n anchorKey: state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n deselectAll: clear,\n clear,\n }),\n [\n isEnabled,\n getSelectability,\n state.selectedKeys,\n selectedIds,\n selectedFolderIds,\n state.anchorKey,\n isSelected,\n toggle,\n selectRange,\n selectAll,\n selectOnly,\n deselect,\n clear,\n ]\n );\n\n return createElement(AssetSelectionContext.Provider, { value }, children);\n};\n\nexport const useAssetSelection = () => {\n const context = useContext(AssetSelectionContext);\n\n if (!context) {\n throw new Error('useAssetSelection must be used within an AssetSelectionProvider');\n }\n\n return context;\n};\n\nexport const useAssetSelectionOptional = () => useContext(AssetSelectionContext);\n"],"names":["AssetSelectionContext","createContext","AssetSelectionProvider","children","disabled","state","setState","useState","createEmptySelection","canUpdate","useMediaLibraryPermissions","isEnabled","isSelected","useCallback","key","selectedKeys","has","toggle","prev","toggleSelection","selectRange","orderedKeys","targetKey","selectRangeState","selectAll","selectAllState","selectOnly","deselect","deselectState","clear","clearSelection","selectedIds","useMemo","getIdsOfKind","selectedFolderIds","getSelectability","value","canSelectAll","anchorKey","deselectAll","createElement","Provider","useAssetSelection","context","useContext","Error","useAssetSelectionOptional"],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var folders = require('../../../services/folders.js');
|
|
5
|
+
var buildAssetFilters = require('../utils/buildAssetFilters.js');
|
|
6
|
+
var useAssetSearch = require('./useAssetSearch.js');
|
|
7
|
+
var useFolderNavigation = require('./useFolderNavigation.js');
|
|
8
|
+
var useInfiniteAssets = require('./useInfiniteAssets.js');
|
|
9
|
+
var useListFilters = require('./useListFilters.js');
|
|
10
|
+
var useListSort = require('./useListSort.js');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The list behind the Media Library page and the Content Manager asset picker:
|
|
14
|
+
* the current folder, search, sort and filters, and the folders and assets they
|
|
15
|
+
* select. Where that query state lives (URL or memory) is decided by
|
|
16
|
+
* `ListQueryStateProvider`, not here.
|
|
17
|
+
*/ const useAssetsList = ()=>{
|
|
18
|
+
const folderNavigation = useFolderNavigation.useFolderNavigation();
|
|
19
|
+
const { currentFolderId, navigateToRoot } = folderNavigation;
|
|
20
|
+
// Deleted or missing folders (404) need a fetch — handled here, not in
|
|
21
|
+
// `useFolderNavigation` (which only strips malformed ?folder= values).
|
|
22
|
+
const { error: currentFolderError } = folders.useGetFolderQuery({
|
|
23
|
+
id: currentFolderId
|
|
24
|
+
}, {
|
|
25
|
+
skip: currentFolderId === null
|
|
26
|
+
});
|
|
27
|
+
React.useEffect(()=>{
|
|
28
|
+
if (currentFolderError?.name === 'NotFoundError') {
|
|
29
|
+
navigateToRoot();
|
|
30
|
+
}
|
|
31
|
+
}, [
|
|
32
|
+
currentFolderError,
|
|
33
|
+
navigateToRoot
|
|
34
|
+
]);
|
|
35
|
+
const assetSearch = useAssetSearch.useAssetSearch();
|
|
36
|
+
const { searchQuery } = assetSearch;
|
|
37
|
+
const listSort = useListSort.useListSort();
|
|
38
|
+
const listFilters = useListFilters.useListFilters();
|
|
39
|
+
// Resolve relative presets against "now" only when the filters change —
|
|
40
|
+
// keeps the query args (and RTK cache keys) stable between renders.
|
|
41
|
+
const builtFilters = React.useMemo(()=>buildAssetFilters.buildAssetFilters(listFilters.filters, new Date()), // eslint-disable-next-line react-hooks/exhaustive-deps -- serialized is the value identity of filters
|
|
42
|
+
[
|
|
43
|
+
listFilters.serialized
|
|
44
|
+
]);
|
|
45
|
+
const { assets, subscribers, pagination, isLoading: isLoadingAssets, isFetchingMore, hasNextPage, fetchNextPage, error: assetsError } = useInfiniteAssets.useInfiniteAssets({
|
|
46
|
+
// The real folder is passed even while searching: the service drops the folder
|
|
47
|
+
// filter when `search` is set, so results are still global. List filters
|
|
48
|
+
// compose with both modes.
|
|
49
|
+
folder: currentFolderId,
|
|
50
|
+
search: searchQuery || undefined,
|
|
51
|
+
sort: listSort.assetsSort,
|
|
52
|
+
filters: builtFilters.fileClauses,
|
|
53
|
+
enabled: builtFilters.showFiles
|
|
54
|
+
});
|
|
55
|
+
const { data: fetchedFolders = [], isLoading: isLoadingFolders } = folders.useGetFoldersQuery({
|
|
56
|
+
parentId: currentFolderId,
|
|
57
|
+
search: searchQuery || undefined,
|
|
58
|
+
sort: listSort.foldersSort,
|
|
59
|
+
filters: builtFilters.folderClauses
|
|
60
|
+
}, {
|
|
61
|
+
skip: !builtFilters.showFolders
|
|
62
|
+
});
|
|
63
|
+
// A type badge can exclude folders structurally (e.g. "Type is Picture").
|
|
64
|
+
const folders$1 = React.useMemo(()=>builtFilters.showFolders ? fetchedFolders : [], [
|
|
65
|
+
builtFilters.showFolders,
|
|
66
|
+
fetchedFolders
|
|
67
|
+
]);
|
|
68
|
+
return {
|
|
69
|
+
...folderNavigation,
|
|
70
|
+
...assetSearch,
|
|
71
|
+
listSort,
|
|
72
|
+
listFilters,
|
|
73
|
+
assets,
|
|
74
|
+
subscribers,
|
|
75
|
+
pagination,
|
|
76
|
+
isLoadingAssets,
|
|
77
|
+
isFetchingMore,
|
|
78
|
+
hasNextPage,
|
|
79
|
+
fetchNextPage,
|
|
80
|
+
assetsError,
|
|
81
|
+
folders: folders$1,
|
|
82
|
+
isLoadingFolders
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
exports.useAssetsList = useAssetsList;
|
|
87
|
+
//# sourceMappingURL=useAssetsList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAssetsList.js","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetsList.ts"],"sourcesContent":["import { useEffect, useMemo } from 'react';\n\nimport { useGetFolderQuery, useGetFoldersQuery } from '../../../services/folders';\nimport { buildAssetFilters } from '../utils/buildAssetFilters';\n\nimport { useAssetSearch } from './useAssetSearch';\nimport { useFolderNavigation } from './useFolderNavigation';\nimport { useInfiniteAssets } from './useInfiniteAssets';\nimport { useListFilters } from './useListFilters';\nimport { useListSort } from './useListSort';\n\n/**\n * The list behind the Media Library page and the Content Manager asset picker:\n * the current folder, search, sort and filters, and the folders and assets they\n * select. Where that query state lives (URL or memory) is decided by\n * `ListQueryStateProvider`, not here.\n */\nexport const useAssetsList = () => {\n const folderNavigation = useFolderNavigation();\n const { currentFolderId, navigateToRoot } = folderNavigation;\n\n // Deleted or missing folders (404) need a fetch — handled here, not in\n // `useFolderNavigation` (which only strips malformed ?folder= values).\n const { error: currentFolderError } = useGetFolderQuery(\n { id: currentFolderId! },\n { skip: currentFolderId === null }\n );\n\n useEffect(() => {\n if (currentFolderError?.name === 'NotFoundError') {\n navigateToRoot();\n }\n }, [currentFolderError, navigateToRoot]);\n\n const assetSearch = useAssetSearch();\n const { searchQuery } = assetSearch;\n const listSort = useListSort();\n const listFilters = useListFilters();\n\n // Resolve relative presets against \"now\" only when the filters change —\n // keeps the query args (and RTK cache keys) stable between renders.\n const builtFilters = useMemo(\n () => buildAssetFilters(listFilters.filters, new Date()),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- serialized is the value identity of filters\n [listFilters.serialized]\n );\n\n const {\n assets,\n subscribers,\n pagination,\n isLoading: isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n error: assetsError,\n } = useInfiniteAssets({\n // The real folder is passed even while searching: the service drops the folder\n // filter when `search` is set, so results are still global. List filters\n // compose with both modes.\n folder: currentFolderId,\n search: searchQuery || undefined,\n sort: listSort.assetsSort,\n filters: builtFilters.fileClauses,\n enabled: builtFilters.showFiles,\n });\n\n const { data: fetchedFolders = [], isLoading: isLoadingFolders } = useGetFoldersQuery(\n {\n parentId: currentFolderId,\n search: searchQuery || undefined,\n sort: listSort.foldersSort,\n filters: builtFilters.folderClauses,\n },\n { skip: !builtFilters.showFolders }\n );\n // A type badge can exclude folders structurally (e.g. \"Type is Picture\").\n const folders = useMemo(\n () => (builtFilters.showFolders ? fetchedFolders : []),\n [builtFilters.showFolders, fetchedFolders]\n );\n\n return {\n ...folderNavigation,\n ...assetSearch,\n listSort,\n listFilters,\n assets,\n subscribers,\n pagination,\n isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n assetsError,\n folders,\n isLoadingFolders,\n };\n};\n"],"names":["useAssetsList","folderNavigation","useFolderNavigation","currentFolderId","navigateToRoot","error","currentFolderError","useGetFolderQuery","id","skip","useEffect","name","assetSearch","useAssetSearch","searchQuery","listSort","useListSort","listFilters","useListFilters","builtFilters","useMemo","buildAssetFilters","filters","Date","serialized","assets","subscribers","pagination","isLoading","isLoadingAssets","isFetchingMore","hasNextPage","fetchNextPage","assetsError","useInfiniteAssets","folder","search","undefined","sort","assetsSort","fileClauses","enabled","showFiles","data","fetchedFolders","isLoadingFolders","useGetFoldersQuery","parentId","foldersSort","folderClauses","showFolders","folders"],"mappings":";;;;;;;;;;;AAWA;;;;;UAMaA,aAAAA,GAAgB,IAAA;AAC3B,IAAA,MAAMC,gBAAAA,GAAmBC,uCAAAA,EAAAA;AACzB,IAAA,MAAM,EAAEC,eAAe,EAAEC,cAAc,EAAE,GAAGH,gBAAAA;;;AAI5C,IAAA,MAAM,EAAEI,KAAAA,EAAOC,kBAAkB,EAAE,GAAGC,yBAAAA,CACpC;QAAEC,EAAAA,EAAIL;KAAiB,EACvB;AAAEM,QAAAA,IAAAA,EAAMN,eAAAA,KAAoB;AAAK,KAAA,CAAA;IAGnCO,eAAAA,CAAU,IAAA;QACR,IAAIJ,kBAAAA,EAAoBK,SAAS,eAAA,EAAiB;AAChDP,YAAAA,cAAAA,EAAAA;AACF,QAAA;IACF,CAAA,EAAG;AAACE,QAAAA,kBAAAA;AAAoBF,QAAAA;AAAe,KAAA,CAAA;AAEvC,IAAA,MAAMQ,WAAAA,GAAcC,6BAAAA,EAAAA;IACpB,MAAM,EAAEC,WAAW,EAAE,GAAGF,WAAAA;AACxB,IAAA,MAAMG,QAAAA,GAAWC,uBAAAA,EAAAA;AACjB,IAAA,MAAMC,WAAAA,GAAcC,6BAAAA,EAAAA;;;IAIpB,MAAMC,YAAAA,GAAeC,cACnB,IAAMC,mCAAAA,CAAkBJ,YAAYK,OAAO,EAAE,IAAIC,IAAAA,EAAAA,CAAAA;AAEjD,IAAA;AAACN,QAAAA,WAAAA,CAAYO;AAAW,KAAA,CAAA;IAG1B,MAAM,EACJC,MAAM,EACNC,WAAW,EACXC,UAAU,EACVC,WAAWC,eAAe,EAC1BC,cAAc,EACdC,WAAW,EACXC,aAAa,EACb3B,OAAO4B,WAAW,EACnB,GAAGC,mCAAAA,CAAkB;;;;QAIpBC,MAAAA,EAAQhC,eAAAA;AACRiC,QAAAA,MAAAA,EAAQtB,WAAAA,IAAeuB,SAAAA;AACvBC,QAAAA,IAAAA,EAAMvB,SAASwB,UAAU;AACzBjB,QAAAA,OAAAA,EAASH,aAAaqB,WAAW;AACjCC,QAAAA,OAAAA,EAAStB,aAAauB;AACxB,KAAA,CAAA;IAEA,MAAM,EAAEC,MAAMC,cAAAA,GAAiB,EAAE,EAAEhB,SAAAA,EAAWiB,gBAAgB,EAAE,GAAGC,0BAAAA,CACjE;QACEC,QAAAA,EAAU5C,eAAAA;AACViC,QAAAA,MAAAA,EAAQtB,WAAAA,IAAeuB,SAAAA;AACvBC,QAAAA,IAAAA,EAAMvB,SAASiC,WAAW;AAC1B1B,QAAAA,OAAAA,EAASH,aAAa8B;KACxB,EACA;QAAExC,IAAAA,EAAM,CAACU,aAAa+B;AAAY,KAAA,CAAA;;IAGpC,MAAMC,SAAAA,GAAU/B,cACd,IAAOD,YAAAA,CAAa+B,WAAW,GAAGN,cAAAA,GAAiB,EAAE,EACrD;AAACzB,QAAAA,YAAAA,CAAa+B,WAAW;AAAEN,QAAAA;AAAe,KAAA,CAAA;IAG5C,OAAO;AACL,QAAA,GAAG3C,gBAAgB;AACnB,QAAA,GAAGW,WAAW;AACdG,QAAAA,QAAAA;AACAE,QAAAA,WAAAA;AACAQ,QAAAA,MAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA,UAAAA;AACAE,QAAAA,eAAAA;AACAC,QAAAA,cAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA,aAAAA;AACAC,QAAAA,WAAAA;AACAkB,iBAAAA,SAAAA;AACAN,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
|
+
import { useGetFolderQuery, useGetFoldersQuery } from '../../../services/folders.mjs';
|
|
3
|
+
import { buildAssetFilters } from '../utils/buildAssetFilters.mjs';
|
|
4
|
+
import { useAssetSearch } from './useAssetSearch.mjs';
|
|
5
|
+
import { useFolderNavigation } from './useFolderNavigation.mjs';
|
|
6
|
+
import { useInfiniteAssets } from './useInfiniteAssets.mjs';
|
|
7
|
+
import { useListFilters } from './useListFilters.mjs';
|
|
8
|
+
import { useListSort } from './useListSort.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The list behind the Media Library page and the Content Manager asset picker:
|
|
12
|
+
* the current folder, search, sort and filters, and the folders and assets they
|
|
13
|
+
* select. Where that query state lives (URL or memory) is decided by
|
|
14
|
+
* `ListQueryStateProvider`, not here.
|
|
15
|
+
*/ const useAssetsList = ()=>{
|
|
16
|
+
const folderNavigation = useFolderNavigation();
|
|
17
|
+
const { currentFolderId, navigateToRoot } = folderNavigation;
|
|
18
|
+
// Deleted or missing folders (404) need a fetch — handled here, not in
|
|
19
|
+
// `useFolderNavigation` (which only strips malformed ?folder= values).
|
|
20
|
+
const { error: currentFolderError } = useGetFolderQuery({
|
|
21
|
+
id: currentFolderId
|
|
22
|
+
}, {
|
|
23
|
+
skip: currentFolderId === null
|
|
24
|
+
});
|
|
25
|
+
useEffect(()=>{
|
|
26
|
+
if (currentFolderError?.name === 'NotFoundError') {
|
|
27
|
+
navigateToRoot();
|
|
28
|
+
}
|
|
29
|
+
}, [
|
|
30
|
+
currentFolderError,
|
|
31
|
+
navigateToRoot
|
|
32
|
+
]);
|
|
33
|
+
const assetSearch = useAssetSearch();
|
|
34
|
+
const { searchQuery } = assetSearch;
|
|
35
|
+
const listSort = useListSort();
|
|
36
|
+
const listFilters = useListFilters();
|
|
37
|
+
// Resolve relative presets against "now" only when the filters change —
|
|
38
|
+
// keeps the query args (and RTK cache keys) stable between renders.
|
|
39
|
+
const builtFilters = useMemo(()=>buildAssetFilters(listFilters.filters, new Date()), // eslint-disable-next-line react-hooks/exhaustive-deps -- serialized is the value identity of filters
|
|
40
|
+
[
|
|
41
|
+
listFilters.serialized
|
|
42
|
+
]);
|
|
43
|
+
const { assets, subscribers, pagination, isLoading: isLoadingAssets, isFetchingMore, hasNextPage, fetchNextPage, error: assetsError } = useInfiniteAssets({
|
|
44
|
+
// The real folder is passed even while searching: the service drops the folder
|
|
45
|
+
// filter when `search` is set, so results are still global. List filters
|
|
46
|
+
// compose with both modes.
|
|
47
|
+
folder: currentFolderId,
|
|
48
|
+
search: searchQuery || undefined,
|
|
49
|
+
sort: listSort.assetsSort,
|
|
50
|
+
filters: builtFilters.fileClauses,
|
|
51
|
+
enabled: builtFilters.showFiles
|
|
52
|
+
});
|
|
53
|
+
const { data: fetchedFolders = [], isLoading: isLoadingFolders } = useGetFoldersQuery({
|
|
54
|
+
parentId: currentFolderId,
|
|
55
|
+
search: searchQuery || undefined,
|
|
56
|
+
sort: listSort.foldersSort,
|
|
57
|
+
filters: builtFilters.folderClauses
|
|
58
|
+
}, {
|
|
59
|
+
skip: !builtFilters.showFolders
|
|
60
|
+
});
|
|
61
|
+
// A type badge can exclude folders structurally (e.g. "Type is Picture").
|
|
62
|
+
const folders = useMemo(()=>builtFilters.showFolders ? fetchedFolders : [], [
|
|
63
|
+
builtFilters.showFolders,
|
|
64
|
+
fetchedFolders
|
|
65
|
+
]);
|
|
66
|
+
return {
|
|
67
|
+
...folderNavigation,
|
|
68
|
+
...assetSearch,
|
|
69
|
+
listSort,
|
|
70
|
+
listFilters,
|
|
71
|
+
assets,
|
|
72
|
+
subscribers,
|
|
73
|
+
pagination,
|
|
74
|
+
isLoadingAssets,
|
|
75
|
+
isFetchingMore,
|
|
76
|
+
hasNextPage,
|
|
77
|
+
fetchNextPage,
|
|
78
|
+
assetsError,
|
|
79
|
+
folders,
|
|
80
|
+
isLoadingFolders
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export { useAssetsList };
|
|
85
|
+
//# sourceMappingURL=useAssetsList.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAssetsList.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useAssetsList.ts"],"sourcesContent":["import { useEffect, useMemo } from 'react';\n\nimport { useGetFolderQuery, useGetFoldersQuery } from '../../../services/folders';\nimport { buildAssetFilters } from '../utils/buildAssetFilters';\n\nimport { useAssetSearch } from './useAssetSearch';\nimport { useFolderNavigation } from './useFolderNavigation';\nimport { useInfiniteAssets } from './useInfiniteAssets';\nimport { useListFilters } from './useListFilters';\nimport { useListSort } from './useListSort';\n\n/**\n * The list behind the Media Library page and the Content Manager asset picker:\n * the current folder, search, sort and filters, and the folders and assets they\n * select. Where that query state lives (URL or memory) is decided by\n * `ListQueryStateProvider`, not here.\n */\nexport const useAssetsList = () => {\n const folderNavigation = useFolderNavigation();\n const { currentFolderId, navigateToRoot } = folderNavigation;\n\n // Deleted or missing folders (404) need a fetch — handled here, not in\n // `useFolderNavigation` (which only strips malformed ?folder= values).\n const { error: currentFolderError } = useGetFolderQuery(\n { id: currentFolderId! },\n { skip: currentFolderId === null }\n );\n\n useEffect(() => {\n if (currentFolderError?.name === 'NotFoundError') {\n navigateToRoot();\n }\n }, [currentFolderError, navigateToRoot]);\n\n const assetSearch = useAssetSearch();\n const { searchQuery } = assetSearch;\n const listSort = useListSort();\n const listFilters = useListFilters();\n\n // Resolve relative presets against \"now\" only when the filters change —\n // keeps the query args (and RTK cache keys) stable between renders.\n const builtFilters = useMemo(\n () => buildAssetFilters(listFilters.filters, new Date()),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- serialized is the value identity of filters\n [listFilters.serialized]\n );\n\n const {\n assets,\n subscribers,\n pagination,\n isLoading: isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n error: assetsError,\n } = useInfiniteAssets({\n // The real folder is passed even while searching: the service drops the folder\n // filter when `search` is set, so results are still global. List filters\n // compose with both modes.\n folder: currentFolderId,\n search: searchQuery || undefined,\n sort: listSort.assetsSort,\n filters: builtFilters.fileClauses,\n enabled: builtFilters.showFiles,\n });\n\n const { data: fetchedFolders = [], isLoading: isLoadingFolders } = useGetFoldersQuery(\n {\n parentId: currentFolderId,\n search: searchQuery || undefined,\n sort: listSort.foldersSort,\n filters: builtFilters.folderClauses,\n },\n { skip: !builtFilters.showFolders }\n );\n // A type badge can exclude folders structurally (e.g. \"Type is Picture\").\n const folders = useMemo(\n () => (builtFilters.showFolders ? fetchedFolders : []),\n [builtFilters.showFolders, fetchedFolders]\n );\n\n return {\n ...folderNavigation,\n ...assetSearch,\n listSort,\n listFilters,\n assets,\n subscribers,\n pagination,\n isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n assetsError,\n folders,\n isLoadingFolders,\n };\n};\n"],"names":["useAssetsList","folderNavigation","useFolderNavigation","currentFolderId","navigateToRoot","error","currentFolderError","useGetFolderQuery","id","skip","useEffect","name","assetSearch","useAssetSearch","searchQuery","listSort","useListSort","listFilters","useListFilters","builtFilters","useMemo","buildAssetFilters","filters","Date","serialized","assets","subscribers","pagination","isLoading","isLoadingAssets","isFetchingMore","hasNextPage","fetchNextPage","assetsError","useInfiniteAssets","folder","search","undefined","sort","assetsSort","fileClauses","enabled","showFiles","data","fetchedFolders","isLoadingFolders","useGetFoldersQuery","parentId","foldersSort","folderClauses","showFolders","folders"],"mappings":";;;;;;;;;AAWA;;;;;UAMaA,aAAAA,GAAgB,IAAA;AAC3B,IAAA,MAAMC,gBAAAA,GAAmBC,mBAAAA,EAAAA;AACzB,IAAA,MAAM,EAAEC,eAAe,EAAEC,cAAc,EAAE,GAAGH,gBAAAA;;;AAI5C,IAAA,MAAM,EAAEI,KAAAA,EAAOC,kBAAkB,EAAE,GAAGC,iBAAAA,CACpC;QAAEC,EAAAA,EAAIL;KAAiB,EACvB;AAAEM,QAAAA,IAAAA,EAAMN,eAAAA,KAAoB;AAAK,KAAA,CAAA;IAGnCO,SAAAA,CAAU,IAAA;QACR,IAAIJ,kBAAAA,EAAoBK,SAAS,eAAA,EAAiB;AAChDP,YAAAA,cAAAA,EAAAA;AACF,QAAA;IACF,CAAA,EAAG;AAACE,QAAAA,kBAAAA;AAAoBF,QAAAA;AAAe,KAAA,CAAA;AAEvC,IAAA,MAAMQ,WAAAA,GAAcC,cAAAA,EAAAA;IACpB,MAAM,EAAEC,WAAW,EAAE,GAAGF,WAAAA;AACxB,IAAA,MAAMG,QAAAA,GAAWC,WAAAA,EAAAA;AACjB,IAAA,MAAMC,WAAAA,GAAcC,cAAAA,EAAAA;;;IAIpB,MAAMC,YAAAA,GAAeC,QACnB,IAAMC,iBAAAA,CAAkBJ,YAAYK,OAAO,EAAE,IAAIC,IAAAA,EAAAA,CAAAA;AAEjD,IAAA;AAACN,QAAAA,WAAAA,CAAYO;AAAW,KAAA,CAAA;IAG1B,MAAM,EACJC,MAAM,EACNC,WAAW,EACXC,UAAU,EACVC,WAAWC,eAAe,EAC1BC,cAAc,EACdC,WAAW,EACXC,aAAa,EACb3B,OAAO4B,WAAW,EACnB,GAAGC,iBAAAA,CAAkB;;;;QAIpBC,MAAAA,EAAQhC,eAAAA;AACRiC,QAAAA,MAAAA,EAAQtB,WAAAA,IAAeuB,SAAAA;AACvBC,QAAAA,IAAAA,EAAMvB,SAASwB,UAAU;AACzBjB,QAAAA,OAAAA,EAASH,aAAaqB,WAAW;AACjCC,QAAAA,OAAAA,EAAStB,aAAauB;AACxB,KAAA,CAAA;IAEA,MAAM,EAAEC,MAAMC,cAAAA,GAAiB,EAAE,EAAEhB,SAAAA,EAAWiB,gBAAgB,EAAE,GAAGC,kBAAAA,CACjE;QACEC,QAAAA,EAAU5C,eAAAA;AACViC,QAAAA,MAAAA,EAAQtB,WAAAA,IAAeuB,SAAAA;AACvBC,QAAAA,IAAAA,EAAMvB,SAASiC,WAAW;AAC1B1B,QAAAA,OAAAA,EAASH,aAAa8B;KACxB,EACA;QAAExC,IAAAA,EAAM,CAACU,aAAa+B;AAAY,KAAA,CAAA;;IAGpC,MAAMC,OAAAA,GAAU/B,QACd,IAAOD,YAAAA,CAAa+B,WAAW,GAAGN,cAAAA,GAAiB,EAAE,EACrD;AAACzB,QAAAA,YAAAA,CAAa+B,WAAW;AAAEN,QAAAA;AAAe,KAAA,CAAA;IAG5C,OAAO;AACL,QAAA,GAAG3C,gBAAgB;AACnB,QAAA,GAAGW,WAAW;AACdG,QAAAA,QAAAA;AACAE,QAAAA,WAAAA;AACAQ,QAAAA,MAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA,UAAAA;AACAE,QAAAA,eAAAA;AACAC,QAAAA,cAAAA;AACAC,QAAAA,WAAAA;AACAC,QAAAA,aAAAA;AACAC,QAAAA,WAAAA;AACAkB,QAAAA,OAAAA;AACAN,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useCallback, useMemo, createElement,
|
|
1
|
+
import { createContext, useState, useCallback, useMemo, createElement, useContext } from 'react';
|
|
2
2
|
|
|
3
3
|
const BusyAssetsContext = createContext(null);
|
|
4
4
|
const BusyAssetsProvider = ({ children })=>{
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
5
|
+
var useListQueryParams = require('./useListQueryParams.js');
|
|
5
6
|
|
|
6
7
|
const parseFolderIdFromQuery = (folder)=>{
|
|
7
8
|
if (!folder) {
|
|
@@ -11,7 +12,7 @@ const parseFolderIdFromQuery = (folder)=>{
|
|
|
11
12
|
return Number.isFinite(id) ? id : null;
|
|
12
13
|
};
|
|
13
14
|
const useFolderNavigation = ()=>{
|
|
14
|
-
const [{ query }, setQuery] =
|
|
15
|
+
const [{ query }, setQuery] = useListQueryParams.useListQueryParams();
|
|
15
16
|
const currentFolderId = parseFolderIdFromQuery(query?.folder);
|
|
16
17
|
/**
|
|
17
18
|
* Asset search is global, so keeping `_q` after a folder navigation would show
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFolderNavigation.js","sources":["../../../../../admin/src/pages/Assets/hooks/useFolderNavigation.ts"],"sourcesContent":["import { useCallback, useEffect } from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useFolderNavigation.js","sources":["../../../../../admin/src/pages/Assets/hooks/useFolderNavigation.ts"],"sourcesContent":["import { useCallback, useEffect } from 'react';\n\nimport { withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\nimport { useListQueryParams } from './useListQueryParams';\n\nimport type { Folder } from '../../../../../shared/contracts/folders';\n\nconst parseFolderIdFromQuery = (folder: string | undefined): number | null => {\n if (!folder) {\n return null;\n }\n\n const id = Number(folder);\n\n return Number.isFinite(id) ? id : null;\n};\n\ninterface FolderNavigationQuery {\n folder?: string;\n _q?: string;\n}\n\nexport const useFolderNavigation = () => {\n const [{ query }, setQuery] = useListQueryParams<FolderNavigationQuery>();\n\n const currentFolderId = parseFolderIdFromQuery(query?.folder);\n\n /**\n * Asset search is global, so keeping `_q` after a folder navigation would show\n * byte-identical results and make the navigation look broken. Clearing it here\n * — rather than at each call site — means no caller can forget.\n */\n const navigateToFolder = useCallback(\n (folder: Folder) => {\n setQuery({ folder: String(folder.id), _q: undefined });\n },\n [setQuery]\n );\n\n /**\n * Move to the Media Library root by removing the `folder` query param, and the\n * search term with it. `setQuery(_, 'remove')` deletes the keys present on the\n * first argument (values are ignored) in one navigation, so any other query\n * state (pagination, the details drawer, etc.) is preserved.\n */\n const navigateToRoot = useCallback(() => {\n setQuery({ folder: '', _q: '' }, 'remove');\n }, [setQuery]);\n\n /**\n * Strips a `?folder=` value we can't parse.\n */\n const stripFolderParam = useCallback(() => {\n setQuery(withEncodedUserParams(query, { folder: undefined }));\n }, [query, setQuery]);\n\n // Malformed ?folder= values (e.g. abc) parse as null; strip the param from the URL.\n // Deleted/missing folders (404) are handled in AssetsPage — that needs a fetch.\n useEffect(() => {\n if (query?.folder && currentFolderId === null) {\n stripFolderParam();\n }\n }, [query?.folder, currentFolderId, stripFolderParam]);\n\n /**\n * Convenience for the FolderTree sidebar: a single entry point that handles\n * both \"go home\" and \"go to folder X\" without forcing the caller to know\n * whether to call navigateToFolder or navigateToRoot.\n */\n const navigateToFolderId = useCallback(\n (folderId: number | null) => {\n if (folderId == null) {\n navigateToRoot();\n } else {\n setQuery({ folder: String(folderId), _q: undefined });\n }\n },\n [navigateToRoot, setQuery]\n );\n\n return {\n currentFolderId,\n navigateToFolder,\n navigateToRoot,\n navigateToFolderId,\n };\n};\n"],"names":["parseFolderIdFromQuery","folder","id","Number","isFinite","useFolderNavigation","query","setQuery","useListQueryParams","currentFolderId","navigateToFolder","useCallback","String","_q","undefined","navigateToRoot","stripFolderParam","withEncodedUserParams","useEffect","navigateToFolderId","folderId"],"mappings":";;;;;;AAQA,MAAMA,yBAAyB,CAACC,MAAAA,GAAAA;AAC9B,IAAA,IAAI,CAACA,MAAAA,EAAQ;QACX,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,MAAMC,KAAKC,MAAAA,CAAOF,MAAAA,CAAAA;AAElB,IAAA,OAAOE,MAAAA,CAAOC,QAAQ,CAACF,EAAAA,CAAAA,GAAMA,EAAAA,GAAK,IAAA;AACpC,CAAA;MAOaG,mBAAAA,GAAsB,IAAA;AACjC,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,qCAAAA,EAAAA;IAE9B,MAAMC,eAAAA,GAAkBT,uBAAuBM,KAAAA,EAAOL,MAAAA,CAAAA;AAEtD;;;;MAKA,MAAMS,gBAAAA,GAAmBC,iBAAAA,CACvB,CAACV,MAAAA,GAAAA;QACCM,QAAAA,CAAS;YAAEN,MAAAA,EAAQW,MAAAA,CAAOX,OAAOC,EAAE,CAAA;YAAGW,EAAAA,EAAIC;AAAU,SAAA,CAAA;IACtD,CAAA,EACA;AAACP,QAAAA;AAAS,KAAA,CAAA;AAGZ;;;;;MAMA,MAAMQ,iBAAiBJ,iBAAAA,CAAY,IAAA;QACjCJ,QAAAA,CAAS;YAAEN,MAAAA,EAAQ,EAAA;YAAIY,EAAAA,EAAI;SAAG,EAAG,QAAA,CAAA;IACnC,CAAA,EAAG;AAACN,QAAAA;AAAS,KAAA,CAAA;AAEb;;MAGA,MAAMS,mBAAmBL,iBAAAA,CAAY,IAAA;AACnCJ,QAAAA,QAAAA,CAASU,kCAAsBX,KAAAA,EAAO;YAAEL,MAAAA,EAAQa;AAAU,SAAA,CAAA,CAAA;IAC5D,CAAA,EAAG;AAACR,QAAAA,KAAAA;AAAOC,QAAAA;AAAS,KAAA,CAAA;;;IAIpBW,eAAAA,CAAU,IAAA;QACR,IAAIZ,KAAAA,EAAOL,MAAAA,IAAUQ,eAAAA,KAAoB,IAAA,EAAM;AAC7CO,YAAAA,gBAAAA,EAAAA;AACF,QAAA;IACF,CAAA,EAAG;QAACV,KAAAA,EAAOL,MAAAA;AAAQQ,QAAAA,eAAAA;AAAiBO,QAAAA;AAAiB,KAAA,CAAA;AAErD;;;;MAKA,MAAMG,kBAAAA,GAAqBR,iBAAAA,CACzB,CAACS,QAAAA,GAAAA;AACC,QAAA,IAAIA,YAAY,IAAA,EAAM;AACpBL,YAAAA,cAAAA,EAAAA;QACF,CAAA,MAAO;YACLR,QAAAA,CAAS;AAAEN,gBAAAA,MAAAA,EAAQW,MAAAA,CAAOQ,QAAAA,CAAAA;gBAAWP,EAAAA,EAAIC;AAAU,aAAA,CAAA;AACrD,QAAA;IACF,CAAA,EACA;AAACC,QAAAA,cAAAA;AAAgBR,QAAAA;AAAS,KAAA,CAAA;IAG5B,OAAO;AACLE,QAAAA,eAAAA;AACAC,QAAAA,gBAAAA;AACAK,QAAAA,cAAAA;AACAI,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { withEncodedUserParams } from '@strapi/admin/strapi-admin';
|
|
3
|
+
import { useListQueryParams } from './useListQueryParams.mjs';
|
|
3
4
|
|
|
4
5
|
const parseFolderIdFromQuery = (folder)=>{
|
|
5
6
|
if (!folder) {
|
|
@@ -9,7 +10,7 @@ const parseFolderIdFromQuery = (folder)=>{
|
|
|
9
10
|
return Number.isFinite(id) ? id : null;
|
|
10
11
|
};
|
|
11
12
|
const useFolderNavigation = ()=>{
|
|
12
|
-
const [{ query }, setQuery] =
|
|
13
|
+
const [{ query }, setQuery] = useListQueryParams();
|
|
13
14
|
const currentFolderId = parseFolderIdFromQuery(query?.folder);
|
|
14
15
|
/**
|
|
15
16
|
* Asset search is global, so keeping `_q` after a folder navigation would show
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFolderNavigation.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useFolderNavigation.ts"],"sourcesContent":["import { useCallback, useEffect } from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"file":"useFolderNavigation.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useFolderNavigation.ts"],"sourcesContent":["import { useCallback, useEffect } from 'react';\n\nimport { withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\nimport { useListQueryParams } from './useListQueryParams';\n\nimport type { Folder } from '../../../../../shared/contracts/folders';\n\nconst parseFolderIdFromQuery = (folder: string | undefined): number | null => {\n if (!folder) {\n return null;\n }\n\n const id = Number(folder);\n\n return Number.isFinite(id) ? id : null;\n};\n\ninterface FolderNavigationQuery {\n folder?: string;\n _q?: string;\n}\n\nexport const useFolderNavigation = () => {\n const [{ query }, setQuery] = useListQueryParams<FolderNavigationQuery>();\n\n const currentFolderId = parseFolderIdFromQuery(query?.folder);\n\n /**\n * Asset search is global, so keeping `_q` after a folder navigation would show\n * byte-identical results and make the navigation look broken. Clearing it here\n * — rather than at each call site — means no caller can forget.\n */\n const navigateToFolder = useCallback(\n (folder: Folder) => {\n setQuery({ folder: String(folder.id), _q: undefined });\n },\n [setQuery]\n );\n\n /**\n * Move to the Media Library root by removing the `folder` query param, and the\n * search term with it. `setQuery(_, 'remove')` deletes the keys present on the\n * first argument (values are ignored) in one navigation, so any other query\n * state (pagination, the details drawer, etc.) is preserved.\n */\n const navigateToRoot = useCallback(() => {\n setQuery({ folder: '', _q: '' }, 'remove');\n }, [setQuery]);\n\n /**\n * Strips a `?folder=` value we can't parse.\n */\n const stripFolderParam = useCallback(() => {\n setQuery(withEncodedUserParams(query, { folder: undefined }));\n }, [query, setQuery]);\n\n // Malformed ?folder= values (e.g. abc) parse as null; strip the param from the URL.\n // Deleted/missing folders (404) are handled in AssetsPage — that needs a fetch.\n useEffect(() => {\n if (query?.folder && currentFolderId === null) {\n stripFolderParam();\n }\n }, [query?.folder, currentFolderId, stripFolderParam]);\n\n /**\n * Convenience for the FolderTree sidebar: a single entry point that handles\n * both \"go home\" and \"go to folder X\" without forcing the caller to know\n * whether to call navigateToFolder or navigateToRoot.\n */\n const navigateToFolderId = useCallback(\n (folderId: number | null) => {\n if (folderId == null) {\n navigateToRoot();\n } else {\n setQuery({ folder: String(folderId), _q: undefined });\n }\n },\n [navigateToRoot, setQuery]\n );\n\n return {\n currentFolderId,\n navigateToFolder,\n navigateToRoot,\n navigateToFolderId,\n };\n};\n"],"names":["parseFolderIdFromQuery","folder","id","Number","isFinite","useFolderNavigation","query","setQuery","useListQueryParams","currentFolderId","navigateToFolder","useCallback","String","_q","undefined","navigateToRoot","stripFolderParam","withEncodedUserParams","useEffect","navigateToFolderId","folderId"],"mappings":";;;;AAQA,MAAMA,yBAAyB,CAACC,MAAAA,GAAAA;AAC9B,IAAA,IAAI,CAACA,MAAAA,EAAQ;QACX,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,MAAMC,KAAKC,MAAAA,CAAOF,MAAAA,CAAAA;AAElB,IAAA,OAAOE,MAAAA,CAAOC,QAAQ,CAACF,EAAAA,CAAAA,GAAMA,EAAAA,GAAK,IAAA;AACpC,CAAA;MAOaG,mBAAAA,GAAsB,IAAA;AACjC,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,kBAAAA,EAAAA;IAE9B,MAAMC,eAAAA,GAAkBT,uBAAuBM,KAAAA,EAAOL,MAAAA,CAAAA;AAEtD;;;;MAKA,MAAMS,gBAAAA,GAAmBC,WAAAA,CACvB,CAACV,MAAAA,GAAAA;QACCM,QAAAA,CAAS;YAAEN,MAAAA,EAAQW,MAAAA,CAAOX,OAAOC,EAAE,CAAA;YAAGW,EAAAA,EAAIC;AAAU,SAAA,CAAA;IACtD,CAAA,EACA;AAACP,QAAAA;AAAS,KAAA,CAAA;AAGZ;;;;;MAMA,MAAMQ,iBAAiBJ,WAAAA,CAAY,IAAA;QACjCJ,QAAAA,CAAS;YAAEN,MAAAA,EAAQ,EAAA;YAAIY,EAAAA,EAAI;SAAG,EAAG,QAAA,CAAA;IACnC,CAAA,EAAG;AAACN,QAAAA;AAAS,KAAA,CAAA;AAEb;;MAGA,MAAMS,mBAAmBL,WAAAA,CAAY,IAAA;AACnCJ,QAAAA,QAAAA,CAASU,sBAAsBX,KAAAA,EAAO;YAAEL,MAAAA,EAAQa;AAAU,SAAA,CAAA,CAAA;IAC5D,CAAA,EAAG;AAACR,QAAAA,KAAAA;AAAOC,QAAAA;AAAS,KAAA,CAAA;;;IAIpBW,SAAAA,CAAU,IAAA;QACR,IAAIZ,KAAAA,EAAOL,MAAAA,IAAUQ,eAAAA,KAAoB,IAAA,EAAM;AAC7CO,YAAAA,gBAAAA,EAAAA;AACF,QAAA;IACF,CAAA,EAAG;QAACV,KAAAA,EAAOL,MAAAA;AAAQQ,QAAAA,eAAAA;AAAiBO,QAAAA;AAAiB,KAAA,CAAA;AAErD;;;;MAKA,MAAMG,kBAAAA,GAAqBR,WAAAA,CACzB,CAACS,QAAAA,GAAAA;AACC,QAAA,IAAIA,YAAY,IAAA,EAAM;AACpBL,YAAAA,cAAAA,EAAAA;QACF,CAAA,MAAO;YACLR,QAAAA,CAAS;AAAEN,gBAAAA,MAAAA,EAAQW,MAAAA,CAAOQ,QAAAA,CAAAA;gBAAWP,EAAAA,EAAIC;AAAU,aAAA,CAAA;AACrD,QAAA;IACF,CAAA,EACA;AAACC,QAAAA,cAAAA;AAAgBR,QAAAA;AAAS,KAAA,CAAA;IAG5B,OAAO;AACLE,QAAAA,eAAAA;AACAC,QAAAA,gBAAAA;AACAK,QAAAA,cAAAA;AACAI,QAAAA;AACF,KAAA;AACF;;;;"}
|
|
@@ -13,12 +13,8 @@ var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
|
13
13
|
return Number.isNaN(parsed) ? null : parsed;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
* Whether the asset details drawer is open, derived purely from the URL
|
|
17
|
-
*
|
|
18
|
-
* Deliberately separate from `useAssetDetailsParam`, which additionally owns the
|
|
19
|
-
* drawer's mount lifecycle: its `shouldRenderDrawer` only stays correct in the
|
|
20
|
-
* component wired to the close animation, so a second caller would strand it at
|
|
21
|
-
* `true`. Anything that just needs the answer reads this instead.
|
|
16
|
+
* Whether the asset details drawer is open, derived purely from the URL — so it
|
|
17
|
+
* turns false as soon as closing starts, while the drawer is still sliding out.
|
|
22
18
|
*/ const useIsAssetDetailsOpen = ()=>{
|
|
23
19
|
const [{ query }] = strapiAdmin.useQueryParams();
|
|
24
20
|
return parseAssetDetailsId(query?.[ASSET_DETAILS_URL_PARAM]) !== null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIsAssetDetailsOpen.js","sources":["../../../../../admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.ts"],"sourcesContent":["import { useQueryParams } from '@strapi/admin/strapi-admin';\n\n/** Name of the parameter to look for in the URL to open the asset details drawer. */\nexport const ASSET_DETAILS_URL_PARAM = 'assetId';\n\n/**\n * The asset id in the URL, or `null` when the param is absent or unparseable.\n *\n * One definition shared by the drawer (which needs the id) and the \"is it open?\"\n * hook below, so the two can never disagree about what counts as open.\n */\nexport const parseAssetDetailsId = (raw: string | undefined): number | null => {\n const parsed = raw ? parseInt(raw, 10) : NaN;\n\n return Number.isNaN(parsed) ? null : parsed;\n};\n\n/**\n * Whether the asset details drawer is open, derived purely from the URL
|
|
1
|
+
{"version":3,"file":"useIsAssetDetailsOpen.js","sources":["../../../../../admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.ts"],"sourcesContent":["import { useQueryParams } from '@strapi/admin/strapi-admin';\n\n/** Name of the parameter to look for in the URL to open the asset details drawer. */\nexport const ASSET_DETAILS_URL_PARAM = 'assetId';\n\n/**\n * The asset id in the URL, or `null` when the param is absent or unparseable.\n *\n * One definition shared by the drawer (which needs the id) and the \"is it open?\"\n * hook below, so the two can never disagree about what counts as open.\n */\nexport const parseAssetDetailsId = (raw: string | undefined): number | null => {\n const parsed = raw ? parseInt(raw, 10) : NaN;\n\n return Number.isNaN(parsed) ? null : parsed;\n};\n\n/**\n * Whether the asset details drawer is open, derived purely from the URL — so it\n * turns false as soon as closing starts, while the drawer is still sliding out.\n */\nexport const useIsAssetDetailsOpen = (): boolean => {\n const [{ query }] = useQueryParams<{ [ASSET_DETAILS_URL_PARAM]?: string }>();\n\n return parseAssetDetailsId(query?.[ASSET_DETAILS_URL_PARAM]) !== null;\n};\n"],"names":["ASSET_DETAILS_URL_PARAM","parseAssetDetailsId","raw","parsed","parseInt","NaN","Number","isNaN","useIsAssetDetailsOpen","query","useQueryParams"],"mappings":";;;;AAEA,sFACO,MAAMA,uBAAAA,GAA0B;AAEvC;;;;;IAMO,MAAMC,mBAAAA,GAAsB,CAACC,GAAAA,GAAAA;AAClC,IAAA,MAAMC,MAAAA,GAASD,GAAAA,GAAME,QAAAA,CAASF,GAAAA,EAAK,EAAA,CAAA,GAAMG,GAAAA;AAEzC,IAAA,OAAOC,MAAAA,CAAOC,KAAK,CAACJ,MAAAA,CAAAA,GAAU,IAAA,GAAOA,MAAAA;AACvC;AAEA;;;UAIaK,qBAAAA,GAAwB,IAAA;AACnC,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,CAAC,GAAGC,0BAAAA,EAAAA;AAEpB,IAAA,OAAOT,mBAAAA,CAAoBQ,KAAAA,GAAQT,uBAAAA,CAAwB,CAAA,KAAM,IAAA;AACnE;;;;;;"}
|
|
@@ -11,12 +11,8 @@ import { useQueryParams } from '@strapi/admin/strapi-admin';
|
|
|
11
11
|
return Number.isNaN(parsed) ? null : parsed;
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
|
-
* Whether the asset details drawer is open, derived purely from the URL
|
|
15
|
-
*
|
|
16
|
-
* Deliberately separate from `useAssetDetailsParam`, which additionally owns the
|
|
17
|
-
* drawer's mount lifecycle: its `shouldRenderDrawer` only stays correct in the
|
|
18
|
-
* component wired to the close animation, so a second caller would strand it at
|
|
19
|
-
* `true`. Anything that just needs the answer reads this instead.
|
|
14
|
+
* Whether the asset details drawer is open, derived purely from the URL — so it
|
|
15
|
+
* turns false as soon as closing starts, while the drawer is still sliding out.
|
|
20
16
|
*/ const useIsAssetDetailsOpen = ()=>{
|
|
21
17
|
const [{ query }] = useQueryParams();
|
|
22
18
|
return parseAssetDetailsId(query?.[ASSET_DETAILS_URL_PARAM]) !== null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIsAssetDetailsOpen.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.ts"],"sourcesContent":["import { useQueryParams } from '@strapi/admin/strapi-admin';\n\n/** Name of the parameter to look for in the URL to open the asset details drawer. */\nexport const ASSET_DETAILS_URL_PARAM = 'assetId';\n\n/**\n * The asset id in the URL, or `null` when the param is absent or unparseable.\n *\n * One definition shared by the drawer (which needs the id) and the \"is it open?\"\n * hook below, so the two can never disagree about what counts as open.\n */\nexport const parseAssetDetailsId = (raw: string | undefined): number | null => {\n const parsed = raw ? parseInt(raw, 10) : NaN;\n\n return Number.isNaN(parsed) ? null : parsed;\n};\n\n/**\n * Whether the asset details drawer is open, derived purely from the URL
|
|
1
|
+
{"version":3,"file":"useIsAssetDetailsOpen.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.ts"],"sourcesContent":["import { useQueryParams } from '@strapi/admin/strapi-admin';\n\n/** Name of the parameter to look for in the URL to open the asset details drawer. */\nexport const ASSET_DETAILS_URL_PARAM = 'assetId';\n\n/**\n * The asset id in the URL, or `null` when the param is absent or unparseable.\n *\n * One definition shared by the drawer (which needs the id) and the \"is it open?\"\n * hook below, so the two can never disagree about what counts as open.\n */\nexport const parseAssetDetailsId = (raw: string | undefined): number | null => {\n const parsed = raw ? parseInt(raw, 10) : NaN;\n\n return Number.isNaN(parsed) ? null : parsed;\n};\n\n/**\n * Whether the asset details drawer is open, derived purely from the URL — so it\n * turns false as soon as closing starts, while the drawer is still sliding out.\n */\nexport const useIsAssetDetailsOpen = (): boolean => {\n const [{ query }] = useQueryParams<{ [ASSET_DETAILS_URL_PARAM]?: string }>();\n\n return parseAssetDetailsId(query?.[ASSET_DETAILS_URL_PARAM]) !== null;\n};\n"],"names":["ASSET_DETAILS_URL_PARAM","parseAssetDetailsId","raw","parsed","parseInt","NaN","Number","isNaN","useIsAssetDetailsOpen","query","useQueryParams"],"mappings":";;AAEA,sFACO,MAAMA,uBAAAA,GAA0B;AAEvC;;;;;IAMO,MAAMC,mBAAAA,GAAsB,CAACC,GAAAA,GAAAA;AAClC,IAAA,MAAMC,MAAAA,GAASD,GAAAA,GAAME,QAAAA,CAASF,GAAAA,EAAK,EAAA,CAAA,GAAMG,GAAAA;AAEzC,IAAA,OAAOC,MAAAA,CAAOC,KAAK,CAACJ,MAAAA,CAAAA,GAAU,IAAA,GAAOA,MAAAA;AACvC;AAEA;;;UAIaK,qBAAAA,GAAwB,IAAA;AACnC,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,CAAC,GAAGC,cAAAA,EAAAA;AAEpB,IAAA,OAAOT,mBAAAA,CAAoBQ,KAAAA,GAAQT,uBAAAA,CAAwB,CAAA,KAAM,IAAA;AACnE;;;;"}
|