@strapi/upload 5.51.2 → 5.52.1
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/future/App.js +3 -3
- package/dist/admin/future/App.js.map +1 -1
- package/dist/admin/future/App.mjs +4 -4
- package/dist/admin/future/App.mjs.map +1 -1
- package/dist/admin/future/components/BetaNotice.js +72 -0
- package/dist/admin/future/components/BetaNotice.js.map +1 -0
- package/dist/admin/future/components/BetaNotice.mjs +70 -0
- package/dist/admin/future/components/BetaNotice.mjs.map +1 -0
- package/dist/admin/future/components/Drawer.js +16 -3
- package/dist/admin/future/components/Drawer.js.map +1 -1
- package/dist/admin/future/components/Drawer.mjs +16 -3
- package/dist/admin/future/components/Drawer.mjs.map +1 -1
- package/dist/admin/future/components/TruncatedText.js +76 -0
- package/dist/admin/future/components/TruncatedText.js.map +1 -0
- package/dist/admin/future/components/TruncatedText.mjs +74 -0
- package/dist/admin/future/components/TruncatedText.mjs.map +1 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.js +39 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.js.map +1 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.mjs +37 -0
- package/dist/admin/future/hooks/useAIMetadataEnabled.mjs.map +1 -0
- package/dist/admin/future/hooks/useTracking.js +57 -0
- package/dist/admin/future/hooks/useTracking.js.map +1 -0
- package/dist/admin/future/hooks/useTracking.mjs +53 -0
- package/dist/admin/future/hooks/useTracking.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +328 -139
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +332 -143
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.js +46 -0
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.mjs +44 -0
- package/dist/admin/future/pages/Assets/components/ActionsMenuContent.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +328 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +326 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +35 -14
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +35 -14
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +74 -53
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +74 -54
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +92 -28
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +94 -30
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +26 -4
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +27 -5
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +172 -60
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +175 -63
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +64 -132
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +64 -132
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js +123 -76
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs +126 -79
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BusyOverlay.js +36 -0
- package/dist/admin/future/pages/Assets/components/BusyOverlay.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/BusyOverlay.mjs +34 -0
- package/dist/admin/future/pages/Assets/components/BusyOverlay.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.js +131 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.mjs +129 -0
- package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +27 -17
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +28 -18
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.js +28 -31
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.mjs +28 -31
- package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js +10 -15
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs +10 -15
- package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterBadges.js +13 -4
- package/dist/admin/future/pages/Assets/components/FilterBadges.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterBadges.mjs +13 -4
- package/dist/admin/future/pages/Assets/components/FilterBadges.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.js +259 -63
- package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +262 -66
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js +146 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs +144 -0
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.js → FolderFormDialog.js} +62 -16
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.mjs → FolderFormDialog.mjs} +64 -18
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +132 -229
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +135 -232
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.js +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +5 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +6 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.js +47 -0
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.mjs +44 -0
- package/dist/admin/future/pages/Assets/hooks/useBusyAssets.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +203 -62
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +204 -63
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.js +75 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.mjs +73 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/utils/selection.js +17 -0
- package/dist/admin/future/pages/Assets/utils/selection.js.map +1 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs +17 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs.map +1 -1
- package/dist/admin/future/services/api.js +31 -8
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +31 -8
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +22 -23
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +22 -23
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/future/services/folders.js +37 -2
- package/dist/admin/future/services/folders.js.map +1 -1
- package/dist/admin/future/services/folders.mjs +37 -3
- package/dist/admin/future/services/folders.mjs.map +1 -1
- package/dist/admin/future/utils/buildDragSetFromSelection.js +7 -5
- package/dist/admin/future/utils/buildDragSetFromSelection.js.map +1 -1
- package/dist/admin/future/utils/buildDragSetFromSelection.mjs +7 -5
- package/dist/admin/future/utils/buildDragSetFromSelection.mjs.map +1 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.js +12 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.js.map +1 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.mjs +12 -1
- package/dist/admin/future/utils/formatMoveSuccessMessage.mjs.map +1 -1
- package/dist/admin/future/utils/getRelationId.js +24 -0
- package/dist/admin/future/utils/getRelationId.js.map +1 -0
- package/dist/admin/future/utils/getRelationId.mjs +22 -0
- package/dist/admin/future/utils/getRelationId.mjs.map +1 -0
- package/dist/admin/future/utils/isEventFromWithin.js +14 -0
- package/dist/admin/future/utils/isEventFromWithin.js.map +1 -0
- package/dist/admin/future/utils/isEventFromWithin.mjs +12 -0
- package/dist/admin/future/utils/isEventFromWithin.mjs.map +1 -0
- package/dist/admin/future/utils/itemLocations.js +40 -0
- package/dist/admin/future/utils/itemLocations.js.map +1 -0
- package/dist/admin/future/utils/itemLocations.mjs +36 -0
- package/dist/admin/future/utils/itemLocations.mjs.map +1 -0
- package/dist/admin/future/utils/itemSource.js +36 -0
- package/dist/admin/future/utils/itemSource.js.map +1 -0
- package/dist/admin/future/utils/itemSource.mjs +32 -0
- package/dist/admin/future/utils/itemSource.mjs.map +1 -0
- package/dist/admin/hooks/useAIMetadataJob.js +1 -1
- package/dist/admin/hooks/useAIMetadataJob.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs.map +1 -1
- package/dist/admin/index.js +11 -17
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +12 -18
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.js +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
- package/dist/admin/src/future/App.d.ts +1 -1
- package/dist/admin/src/future/components/BetaNotice.d.ts +11 -0
- package/dist/admin/src/future/components/Drawer.d.ts +5 -1
- package/dist/admin/src/future/components/TruncatedText.d.ts +32 -0
- package/dist/admin/src/future/hooks/useAIMetadataEnabled.d.ts +26 -0
- package/dist/admin/src/future/hooks/useTracking.d.ts +29 -0
- package/dist/admin/src/future/pages/Assets/components/ActionsMenuContent.d.ts +33 -0
- package/dist/admin/src/future/pages/Assets/components/AssetActionsMenu.d.ts +26 -0
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +16 -0
- package/dist/admin/src/future/pages/Assets/components/BulkActionsBar.d.ts +8 -1
- package/dist/admin/src/future/pages/Assets/components/BulkMoveDialog.d.ts +17 -6
- package/dist/admin/src/future/pages/Assets/components/BusyOverlay.d.ts +9 -0
- package/dist/admin/src/future/pages/Assets/components/DeleteItemsDialog.d.ts +27 -0
- package/dist/admin/src/future/pages/Assets/components/Dnd/AssetsDndProvider.d.ts +8 -1
- package/dist/admin/src/future/pages/Assets/components/Dnd/buildDragSet.d.ts +18 -3
- package/dist/admin/src/future/pages/Assets/components/Dnd/useAssetDnd.d.ts +2 -1
- package/dist/admin/src/future/pages/Assets/components/FilterBadges.d.ts +3 -1
- package/dist/admin/src/future/pages/Assets/components/FilterMenu.d.ts +4 -0
- package/dist/admin/src/future/pages/Assets/components/FolderActionsMenu.d.ts +21 -0
- package/dist/admin/src/future/pages/Assets/components/FolderFormDialog.d.ts +16 -0
- package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +2 -0
- package/dist/admin/src/future/pages/Assets/hooks/useBusyAssets.d.ts +38 -0
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +20 -6
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteScrollSentinel.d.ts +41 -0
- package/dist/admin/src/future/pages/Assets/utils/selection.d.ts +10 -0
- package/dist/admin/src/future/services/api.d.ts +6 -7
- package/dist/admin/src/future/services/folders.d.ts +6 -1
- package/dist/admin/src/future/utils/buildDragSetFromSelection.d.ts +4 -3
- package/dist/admin/src/future/utils/formatMoveSuccessMessage.d.ts +7 -1
- package/dist/admin/src/future/utils/getRelationId.d.ts +11 -0
- package/dist/admin/src/future/utils/isEventFromWithin.d.ts +11 -0
- package/dist/admin/src/future/utils/itemLocations.d.ts +31 -0
- package/dist/admin/src/future/utils/itemSource.d.ts +22 -0
- package/dist/admin/translations/en.json.js +25 -4
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +25 -4
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/controllers/admin-file.js +27 -9
- package/dist/server/controllers/admin-file.js.map +1 -1
- package/dist/server/controllers/admin-file.mjs +27 -9
- package/dist/server/controllers/admin-file.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +24 -8
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +24 -8
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/routes/admin.js +41 -21
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +41 -21
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/services/ai-metadata.js.map +1 -1
- package/dist/server/services/ai-metadata.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/src/controllers/admin-file.d.ts +29 -8
- package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +20 -4
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +4 -4
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata.d.ts +2 -2
- package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
- package/dist/server/src/services/image-manipulation.d.ts +0 -5
- package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
- package/dist/shared/contracts/ai-metadata-jobs.d.ts +10 -32
- package/dist/shared/contracts/ai-metadata-jobs.d.ts.map +1 -1
- package/dist/shared/contracts/files.d.ts +10 -10
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/admin/future/pages/Assets/components/CreateFolderDialog.js.map +0 -1
- package/dist/admin/future/pages/Assets/components/CreateFolderDialog.mjs.map +0 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js +0 -33
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js.map +0 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs +0 -31
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs.map +0 -1
- package/dist/admin/src/future/pages/Assets/components/CreateFolderDialog.d.ts +0 -8
- package/dist/admin/src/future/pages/Assets/components/FolderTree/filterFolderTree.d.ts +0 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsSearchInput.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/AssetsSearchInput.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ChangeEvent, type FormEvent } from 'react';\n\nimport { useDebounce, useIsMobile, useQueryParams } from '@strapi/admin/strapi-admin';\nimport { Box, Searchbar, SearchForm } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSearch } from '../hooks/useAssetSearch';\n\nconst DEBOUNCE_MS = 300;\n\n/**\n * Keyword search over the whole Media Library. Owns the typing state and the\n * debounce; `useAssetSearch` owns the `?_q=` URL param.\n */\nexport const AssetsSearchInput = () => {\n const { formatMessage } = useIntl();\n const { searchQuery, setSearchQuery } = useAssetSearch();\n const isMobile = useIsMobile();\n\n const [value, setValue] = useState(searchQuery);\n const debouncedValue = useDebounce(value, DEBOUNCE_MS);\n\n // Tracks the last value the URL and the input agreed on. Without it the two\n // effects below would ping-pong: each would see the other's write as a change\n // worth reacting to.\n const lastCommittedRef = useRef(searchQuery);\n\n // Read directly rather than through `useFolderNavigation`, which strips\n // malformed `?folder=` values as a side effect.\n const [{ query }] = useQueryParams<{ folder?: string }>();\n const folderParam = query?.folder ?? '';\n const lastFolderRef = useRef(folderParam);\n\n // Commit settled input to the URL.\n useEffect(() => {\n if (debouncedValue === lastCommittedRef.current) {\n return;\n }\n\n lastCommittedRef.current = debouncedValue;\n setSearchQuery(debouncedValue);\n }, [debouncedValue, setSearchQuery]);\n\n // Re-sync on external changes — back/forward, or \"Clear search\" in the empty\n // state.\n useEffect(() => {\n if (searchQuery === lastCommittedRef.current) {\n return;\n }\n\n lastCommittedRef.current = searchQuery;\n setValue(searchQuery);\n }, [searchQuery]);\n\n // A folder navigation clears `_q`, but a term typed and never committed lives\n // only in the debounce — without this it lands afterwards and reactivates the\n // global search. `_q` alone can't see it: it was never non-empty.\n useEffect(() => {\n if (folderParam === lastFolderRef.current) {\n return;\n }\n\n lastFolderRef.current = folderParam;\n lastCommittedRef.current = searchQuery;\n setValue(searchQuery);\n }, [folderParam, searchQuery]);\n\n const searchForm = (\n <
|
|
1
|
+
{"version":3,"file":"AssetsSearchInput.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/AssetsSearchInput.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ChangeEvent, type FormEvent } from 'react';\n\nimport { useDebounce, useIsMobile, useQueryParams } from '@strapi/admin/strapi-admin';\nimport { Box, Searchbar, SearchForm } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSearch } from '../hooks/useAssetSearch';\n\nconst DEBOUNCE_MS = 300;\n\n// The DS Searchbar nests two bordered boxes: its own shell (neutral150) wrapping\n// the field (neutral200). Side by side they read as a single 2px, two-tone\n// border, which sits oddly next to the 1px neutral200 on the Filter button in the\n// same toolbar. Dropping the shell's border leaves the field's own — same width\n// and colour as the button — and costs nothing, since the focus ring lives on the\n// field too.\nconst StyledSearchForm = styled(SearchForm)`\n > div {\n border: none;\n }\n`;\n\n/**\n * Keyword search over the whole Media Library. Owns the typing state and the\n * debounce; `useAssetSearch` owns the `?_q=` URL param.\n */\nexport const AssetsSearchInput = () => {\n const { formatMessage } = useIntl();\n const { searchQuery, setSearchQuery } = useAssetSearch();\n const { trackUsage } = useTracking();\n const isMobile = useIsMobile();\n\n const [value, setValue] = useState(searchQuery);\n const debouncedValue = useDebounce(value, DEBOUNCE_MS);\n\n // Tracks the last value the URL and the input agreed on. Without it the two\n // effects below would ping-pong: each would see the other's write as a change\n // worth reacting to.\n const lastCommittedRef = useRef(searchQuery);\n\n // Read directly rather than through `useFolderNavigation`, which strips\n // malformed `?folder=` values as a side effect.\n const [{ query }] = useQueryParams<{ folder?: string }>();\n const folderParam = query?.folder ?? '';\n const lastFolderRef = useRef(folderParam);\n\n // Commit settled input to the URL.\n useEffect(() => {\n if (debouncedValue === lastCommittedRef.current) {\n return;\n }\n\n lastCommittedRef.current = debouncedValue;\n // Only a real query counts as a search — clearing the box (empty value) is\n // a reset, not a `didSearch`.\n if (debouncedValue) {\n trackUsage('didSearchMediaLibraryElements', { location: MEDIA_LIBRARY_LOCATION });\n }\n setSearchQuery(debouncedValue);\n }, [debouncedValue, setSearchQuery, trackUsage]);\n\n // Re-sync on external changes — back/forward, or \"Clear search\" in the empty\n // state.\n useEffect(() => {\n if (searchQuery === lastCommittedRef.current) {\n return;\n }\n\n lastCommittedRef.current = searchQuery;\n setValue(searchQuery);\n }, [searchQuery]);\n\n // A folder navigation clears `_q`, but a term typed and never committed lives\n // only in the debounce — without this it lands afterwards and reactivates the\n // global search. `_q` alone can't see it: it was never non-empty.\n useEffect(() => {\n if (folderParam === lastFolderRef.current) {\n return;\n }\n\n lastFolderRef.current = folderParam;\n lastCommittedRef.current = searchQuery;\n setValue(searchQuery);\n }, [folderParam, searchQuery]);\n\n const searchForm = (\n <StyledSearchForm onSubmit={(event: FormEvent<HTMLFormElement>) => event.preventDefault()}>\n <Searchbar\n name=\"search-assets\"\n value={value}\n onChange={(event: ChangeEvent<HTMLInputElement>) => setValue(event.target.value)}\n onClear={() => setValue('')}\n clearLabel={formatMessage({ id: 'clearLabel', defaultMessage: 'Clear' })}\n placeholder={formatMessage({\n id: getTranslationKey('header.search.placeholder'),\n defaultMessage: 'Search',\n })}\n size=\"S\"\n >\n {formatMessage({\n id: getTranslationKey('search.label'),\n defaultMessage: 'Search for an asset',\n })}\n </Searchbar>\n </StyledSearchForm>\n );\n\n // Mobile: fills the toolbar row (own line). Desktop: keeps its intrinsic size,\n // with empty space between it and the right-aligned Sort/Toggle group.\n if (isMobile) {\n return <Box width=\"100%\">{searchForm}</Box>;\n }\n\n return searchForm;\n};\n"],"names":["DEBOUNCE_MS","StyledSearchForm","styled","SearchForm","AssetsSearchInput","formatMessage","useIntl","searchQuery","setSearchQuery","useAssetSearch","trackUsage","useTracking","isMobile","useIsMobile","value","setValue","useState","debouncedValue","useDebounce","lastCommittedRef","useRef","query","useQueryParams","folderParam","folder","lastFolderRef","useEffect","current","location","MEDIA_LIBRARY_LOCATION","searchForm","_jsx","onSubmit","event","preventDefault","Searchbar","name","onChange","target","onClear","clearLabel","id","defaultMessage","placeholder","getTranslationKey","size","Box","width"],"mappings":";;;;;;;;;;AAWA,MAAMA,WAAAA,GAAc,GAAA;AAEpB;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,gBAAAA,GAAmBC,MAAAA,CAAOC,UAAAA,CAAW;;;;AAI3C,CAAC;AAED;;;UAIaC,iBAAAA,GAAoB,IAAA;IAC/B,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAM,EAAEC,WAAW,EAAEC,cAAc,EAAE,GAAGC,cAAAA,EAAAA;IACxC,MAAM,EAAEC,UAAU,EAAE,GAAGC,WAAAA,EAAAA;AACvB,IAAA,MAAMC,QAAAA,GAAWC,WAAAA,EAAAA;AAEjB,IAAA,MAAM,CAACC,KAAAA,EAAOC,QAAAA,CAAS,GAAGC,QAAAA,CAAST,WAAAA,CAAAA;IACnC,MAAMU,cAAAA,GAAiBC,YAAYJ,KAAAA,EAAOd,WAAAA,CAAAA;;;;AAK1C,IAAA,MAAMmB,mBAAmBC,MAAAA,CAAOb,WAAAA,CAAAA;;;AAIhC,IAAA,MAAM,CAAC,EAAEc,KAAK,EAAE,CAAC,GAAGC,cAAAA,EAAAA;IACpB,MAAMC,WAAAA,GAAcF,OAAOG,MAAAA,IAAU,EAAA;AACrC,IAAA,MAAMC,gBAAgBL,MAAAA,CAAOG,WAAAA,CAAAA;;IAG7BG,SAAAA,CAAU,IAAA;QACR,IAAIT,cAAAA,KAAmBE,gBAAAA,CAAiBQ,OAAO,EAAE;AAC/C,YAAA;AACF,QAAA;AAEAR,QAAAA,gBAAAA,CAAiBQ,OAAO,GAAGV,cAAAA;;;AAG3B,QAAA,IAAIA,cAAAA,EAAgB;AAClBP,YAAAA,UAAAA,CAAW,+BAAA,EAAiC;gBAAEkB,QAAAA,EAAUC;AAAuB,aAAA,CAAA;AACjF,QAAA;QACArB,cAAAA,CAAeS,cAAAA,CAAAA;IACjB,CAAA,EAAG;AAACA,QAAAA,cAAAA;AAAgBT,QAAAA,cAAAA;AAAgBE,QAAAA;AAAW,KAAA,CAAA;;;IAI/CgB,SAAAA,CAAU,IAAA;QACR,IAAInB,WAAAA,KAAgBY,gBAAAA,CAAiBQ,OAAO,EAAE;AAC5C,YAAA;AACF,QAAA;AAEAR,QAAAA,gBAAAA,CAAiBQ,OAAO,GAAGpB,WAAAA;QAC3BQ,QAAAA,CAASR,WAAAA,CAAAA;IACX,CAAA,EAAG;AAACA,QAAAA;AAAY,KAAA,CAAA;;;;IAKhBmB,SAAAA,CAAU,IAAA;QACR,IAAIH,WAAAA,KAAgBE,aAAAA,CAAcE,OAAO,EAAE;AACzC,YAAA;AACF,QAAA;AAEAF,QAAAA,aAAAA,CAAcE,OAAO,GAAGJ,WAAAA;AACxBJ,QAAAA,gBAAAA,CAAiBQ,OAAO,GAAGpB,WAAAA;QAC3BQ,QAAAA,CAASR,WAAAA,CAAAA;IACX,CAAA,EAAG;AAACgB,QAAAA,WAAAA;AAAahB,QAAAA;AAAY,KAAA,CAAA;AAE7B,IAAA,MAAMuB,2BACJC,GAAA,CAAC9B,gBAAAA,EAAAA;QAAiB+B,QAAAA,EAAU,CAACC,KAAAA,GAAsCA,KAAAA,CAAMC,cAAc,EAAA;AACrF,QAAA,QAAA,gBAAAH,GAAA,CAACI,SAAAA,EAAAA;YACCC,IAAAA,EAAK,eAAA;YACLtB,KAAAA,EAAOA,KAAAA;AACPuB,YAAAA,QAAAA,EAAU,CAACJ,KAAAA,GAAyClB,QAAAA,CAASkB,KAAAA,CAAMK,MAAM,CAACxB,KAAK,CAAA;AAC/EyB,YAAAA,OAAAA,EAAS,IAAMxB,QAAAA,CAAS,EAAA,CAAA;AACxByB,YAAAA,UAAAA,EAAYnC,aAAAA,CAAc;gBAAEoC,EAAAA,EAAI,YAAA;gBAAcC,cAAAA,EAAgB;AAAQ,aAAA,CAAA;AACtEC,YAAAA,WAAAA,EAAatC,aAAAA,CAAc;AACzBoC,gBAAAA,EAAAA,EAAIG,iBAAAA,CAAkB,2BAAA,CAAA;gBACtBF,cAAAA,EAAgB;AAClB,aAAA,CAAA;YACAG,IAAAA,EAAK,GAAA;sBAEJxC,aAAAA,CAAc;AACboC,gBAAAA,EAAAA,EAAIG,iBAAAA,CAAkB,cAAA,CAAA;gBACtBF,cAAAA,EAAgB;AAClB,aAAA;;;;;AAON,IAAA,IAAI9B,QAAAA,EAAU;AACZ,QAAA,qBAAOmB,GAAA,CAACe,GAAAA,EAAAA;YAAIC,KAAAA,EAAM,MAAA;AAAQjB,YAAAA,QAAAA,EAAAA;;AAC5B,IAAA;IAEA,OAAOA,UAAAA;AACT;;;;"}
|
|
@@ -6,16 +6,22 @@ var designSystem = require('@strapi/design-system');
|
|
|
6
6
|
var icons = require('@strapi/icons');
|
|
7
7
|
var reactIntl = require('react-intl');
|
|
8
8
|
var styledComponents = require('styled-components');
|
|
9
|
+
var TruncatedText = require('../../../components/TruncatedText.js');
|
|
9
10
|
var useMediaLibraryPermissions = require('../../../hooks/useMediaLibraryPermissions.js');
|
|
11
|
+
var useTracking = require('../../../hooks/useTracking.js');
|
|
10
12
|
var files = require('../../../utils/files.js');
|
|
11
13
|
var getAssetIcon = require('../../../utils/getAssetIcon.js');
|
|
14
|
+
var isEventFromWithin = require('../../../utils/isEventFromWithin.js');
|
|
12
15
|
var translations = require('../../../utils/translations.js');
|
|
13
16
|
var constants = require('../constants.js');
|
|
14
17
|
var useAssetSelection = require('../hooks/useAssetSelection.js');
|
|
18
|
+
var useBusyAssets = require('../hooks/useBusyAssets.js');
|
|
15
19
|
var useFolderNavigation = require('../hooks/useFolderNavigation.js');
|
|
16
20
|
var selection = require('../utils/selection.js');
|
|
21
|
+
var AssetActionsMenu = require('./AssetActionsMenu.js');
|
|
17
22
|
var AssetsDndProvider = require('./Dnd/AssetsDndProvider.js');
|
|
18
23
|
var useAssetDnd = require('./Dnd/useAssetDnd.js');
|
|
24
|
+
var FolderActionsMenu = require('./FolderActionsMenu.js');
|
|
19
25
|
|
|
20
26
|
const StyledTable = styledComponents.styled(designSystem.RawTable)`
|
|
21
27
|
width: 100%;
|
|
@@ -24,6 +30,28 @@ const StyledTable = styledComponents.styled(designSystem.RawTable)`
|
|
|
24
30
|
border: 1px solid ${({ theme })=>theme.colors.neutral150};
|
|
25
31
|
border-radius: 4px;
|
|
26
32
|
overflow: hidden;
|
|
33
|
+
|
|
34
|
+
/* Below desktop only the name column remains. A fixed layout makes a long
|
|
35
|
+
name ellipsize instead of widening the table past the viewport — the
|
|
36
|
+
checkbox (first) and actions (last) columns keep a fixed width and the name
|
|
37
|
+
takes the rest. Desktop keeps the content-sized auto layout. */
|
|
38
|
+
table-layout: fixed;
|
|
39
|
+
|
|
40
|
+
& td:last-child,
|
|
41
|
+
& th:last-child {
|
|
42
|
+
width: 5.6rem;
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
${({ theme })=>theme.breakpoints.large} {
|
|
47
|
+
table-layout: auto;
|
|
48
|
+
|
|
49
|
+
& td:last-child,
|
|
50
|
+
& th:last-child {
|
|
51
|
+
width: auto;
|
|
52
|
+
white-space: normal;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
27
55
|
`;
|
|
28
56
|
const StyledThead = styledComponents.styled(designSystem.RawThead)`
|
|
29
57
|
background: ${({ theme })=>theme.colors.neutral100};
|
|
@@ -45,14 +73,14 @@ const StyledTr = styledComponents.styled.tr`
|
|
|
45
73
|
height: 48px;
|
|
46
74
|
user-select: none;
|
|
47
75
|
background: ${({ theme, $isSelected })=>$isSelected ? theme.colors.primary100 : theme.colors.neutral0};
|
|
48
|
-
cursor: ${({ $isMovePending, $isInvalidDropTarget })=>{
|
|
49
|
-
if ($isMovePending) {
|
|
76
|
+
cursor: ${({ $isMovePending, $isBusy, $isInvalidDropTarget })=>{
|
|
77
|
+
if ($isMovePending || $isBusy) {
|
|
50
78
|
return 'wait';
|
|
51
79
|
}
|
|
52
80
|
return $isInvalidDropTarget ? 'not-allowed' : 'pointer';
|
|
53
81
|
}};
|
|
54
|
-
opacity: ${({ $isDragging })=>$isDragging ? 0.4 : 1};
|
|
55
|
-
pointer-events: ${({ $isMovePending })=>$isMovePending ? 'none' : 'auto'};
|
|
82
|
+
opacity: ${({ $isDragging, $isBusy })=>$isDragging || $isBusy ? 0.4 : 1};
|
|
83
|
+
pointer-events: ${({ $isMovePending, $isBusy })=>$isMovePending || $isBusy ? 'none' : 'auto'};
|
|
56
84
|
|
|
57
85
|
${({ $isValidDropTarget, theme })=>$isValidDropTarget && styledComponents.css`
|
|
58
86
|
background: ${theme.colors.primary100};
|
|
@@ -75,16 +103,29 @@ const StyledTr = styledComponents.styled.tr`
|
|
|
75
103
|
}
|
|
76
104
|
}
|
|
77
105
|
`;
|
|
78
|
-
// Leading checkbox column.
|
|
79
|
-
//
|
|
106
|
+
// Leading checkbox column. Fixed narrow width so it holds its own column under
|
|
107
|
+
// the mobile fixed table-layout (a 1% width would collapse and let the name
|
|
108
|
+
// cell's preview overlap the control).
|
|
80
109
|
const CheckboxTd = styledComponents.styled(StyledTd)`
|
|
81
|
-
width:
|
|
110
|
+
width: 5.6rem;
|
|
82
111
|
white-space: nowrap;
|
|
83
112
|
`;
|
|
84
113
|
const CheckboxTh = styledComponents.styled(StyledTh)`
|
|
85
|
-
width:
|
|
114
|
+
width: 5.6rem;
|
|
86
115
|
white-space: nowrap;
|
|
87
116
|
`;
|
|
117
|
+
// Flags an asset whose caption or alternative text is empty — mirrors the
|
|
118
|
+
// per-field warning shown in the details drawer. Pushed to the far end of the
|
|
119
|
+
// name cell (shrink 0 so a long name never crowds it out).
|
|
120
|
+
const MetadataWarning = styledComponents.styled(icons.WarningCircle)`
|
|
121
|
+
flex-shrink: 0;
|
|
122
|
+
width: 1.6rem;
|
|
123
|
+
height: 1.6rem;
|
|
124
|
+
|
|
125
|
+
path {
|
|
126
|
+
fill: ${({ theme })=>theme.colors.warning500};
|
|
127
|
+
}
|
|
128
|
+
`;
|
|
88
129
|
// The asset filename is its own interactive element: clicking it opens the
|
|
89
130
|
// details drawer instead of selecting the row.
|
|
90
131
|
const NameButton = styledComponents.styled.button`
|
|
@@ -105,8 +146,14 @@ const NameButton = styledComponents.styled.button`
|
|
|
105
146
|
border-radius: 2px;
|
|
106
147
|
}
|
|
107
148
|
`;
|
|
149
|
+
// Shields the row from its own controls (checkbox, "..." trigger) without
|
|
150
|
+
// severing propagation for the menu's portaled content — those events are React
|
|
151
|
+
// children of the cell but not DOM descendants, and Radix needs them to reach
|
|
152
|
+
// `document` to dismiss its layers.
|
|
108
153
|
const stopRowEvent = (e)=>{
|
|
109
|
-
|
|
154
|
+
if (isEventFromWithin.isEventFromWithin(e)) {
|
|
155
|
+
e.stopPropagation();
|
|
156
|
+
}
|
|
110
157
|
};
|
|
111
158
|
const AssetPreviewCell = ({ asset })=>{
|
|
112
159
|
const { ext, mime } = asset;
|
|
@@ -126,20 +173,35 @@ const AssetPreviewCell = ({ asset })=>{
|
|
|
126
173
|
});
|
|
127
174
|
};
|
|
128
175
|
const AssetRow = ({ asset, orderedItemKeys, onAssetItemClick })=>{
|
|
129
|
-
const
|
|
176
|
+
const isDesktop = strapiAdmin.useIsDesktop();
|
|
130
177
|
const { formatDate, formatMessage } = reactIntl.useIntl();
|
|
131
178
|
const { isMovePending } = AssetsDndProvider.useAssetsDndOptional() ?? {
|
|
132
179
|
isMovePending: false
|
|
133
180
|
};
|
|
134
|
-
const { attributes, listeners, setNodeRef, isDragging } = useAssetDnd.useFileDraggable(asset);
|
|
181
|
+
const { attributes, listeners, setNodeRef, isDragging, dragData } = useAssetDnd.useFileDraggable(asset);
|
|
135
182
|
const { isSelected, toggle, selectRange } = useAssetSelection.useAssetSelection();
|
|
136
183
|
const { canUpdate } = useMediaLibraryPermissions.useMediaLibraryPermissions();
|
|
184
|
+
const busyMessage = useBusyAssets.useBusyAssetsOptional()?.getBusyMessage(asset.id) ?? null;
|
|
137
185
|
const key = selection.assetKey(asset.id);
|
|
138
186
|
const selected = isSelected(key);
|
|
187
|
+
// Caption and alternative text apply to every file type — same "empty =
|
|
188
|
+
// falsy" rule as the drawer's per-field warning.
|
|
189
|
+
const isMetadataMissing = !asset.caption || !asset.alternativeText;
|
|
190
|
+
const metadataMissingLabel = formatMessage({
|
|
191
|
+
id: translations.getTranslationKey('list.table.row.metadata-missing'),
|
|
192
|
+
defaultMessage: 'This asset is missing metadata (caption or alternative text).'
|
|
193
|
+
});
|
|
139
194
|
// Plain click opens the asset details; pointer selection lives on the
|
|
140
195
|
// checkbox only. Modifier clicks keep the selection semantics: shift selects
|
|
141
196
|
// a range, cmd/ctrl toggles.
|
|
197
|
+
//
|
|
198
|
+
// The containment guard on this and the handler below is what keeps the
|
|
199
|
+
// actions menu's portaled dialogs — React children of this row — from
|
|
200
|
+
// opening the details drawer or toggling the selection.
|
|
142
201
|
const handleRowClick = (e)=>{
|
|
202
|
+
if (!isEventFromWithin.isEventFromWithin(e)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
143
205
|
if (e.shiftKey) {
|
|
144
206
|
selectRange(orderedItemKeys, key);
|
|
145
207
|
} else if (e.metaKey || e.ctrlKey) {
|
|
@@ -150,6 +212,9 @@ const AssetRow = ({ asset, orderedItemKeys, onAssetItemClick })=>{
|
|
|
150
212
|
};
|
|
151
213
|
// Desktop: Space toggles selection (additive), Enter opens the details drawer.
|
|
152
214
|
const handleKeyDown = (e)=>{
|
|
215
|
+
if (!isEventFromWithin.isEventFromWithin(e)) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
153
218
|
if (e.key === 'Enter') {
|
|
154
219
|
e.preventDefault();
|
|
155
220
|
onAssetItemClick(asset.id);
|
|
@@ -176,14 +241,20 @@ const AssetRow = ({ asset, orderedItemKeys, onAssetItemClick })=>{
|
|
|
176
241
|
...listeners,
|
|
177
242
|
$isDragging: isDragging,
|
|
178
243
|
$isMovePending: isMovePending,
|
|
244
|
+
$isBusy: busyMessage !== null,
|
|
179
245
|
$isSelected: selected,
|
|
180
246
|
tabIndex: 0,
|
|
181
247
|
role: "row",
|
|
182
248
|
onDragStart: (e)=>e.preventDefault(),
|
|
183
249
|
onClick: handleRowClick,
|
|
184
250
|
onKeyDown: handleKeyDown,
|
|
251
|
+
onPointerDown: (e)=>{
|
|
252
|
+
if (isEventFromWithin.isEventFromWithin(e)) {
|
|
253
|
+
listeners?.onPointerDown?.(e);
|
|
254
|
+
}
|
|
255
|
+
},
|
|
185
256
|
children: [
|
|
186
|
-
|
|
257
|
+
canUpdate && /*#__PURE__*/ jsxRuntime.jsx(CheckboxTd, {
|
|
187
258
|
onClick: stopRowEvent,
|
|
188
259
|
onKeyDown: stopRowEvent,
|
|
189
260
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
@@ -201,38 +272,61 @@ const AssetRow = ({ asset, orderedItemKeys, onAssetItemClick })=>{
|
|
|
201
272
|
}),
|
|
202
273
|
/*#__PURE__*/ jsxRuntime.jsx(StyledTd, {
|
|
203
274
|
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
204
|
-
gap: 3,
|
|
205
275
|
alignItems: "center",
|
|
276
|
+
justifyContent: "space-between",
|
|
277
|
+
gap: 2,
|
|
278
|
+
minWidth: 0,
|
|
206
279
|
children: [
|
|
207
|
-
/*#__PURE__*/ jsxRuntime.jsx(AssetPreviewCell, {
|
|
208
|
-
asset: asset
|
|
209
|
-
}),
|
|
210
280
|
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
211
|
-
|
|
212
|
-
alignItems: "
|
|
281
|
+
gap: 3,
|
|
282
|
+
alignItems: "center",
|
|
213
283
|
minWidth: 0,
|
|
214
284
|
children: [
|
|
215
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
children: asset.name
|
|
285
|
+
busyMessage !== null ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
286
|
+
justifyContent: "center",
|
|
287
|
+
width: "3.2rem",
|
|
288
|
+
height: "3.2rem",
|
|
289
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
|
|
290
|
+
small: true,
|
|
291
|
+
children: busyMessage
|
|
223
292
|
})
|
|
293
|
+
}) : /*#__PURE__*/ jsxRuntime.jsx(AssetPreviewCell, {
|
|
294
|
+
asset: asset
|
|
224
295
|
}),
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
296
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
297
|
+
direction: "column",
|
|
298
|
+
alignItems: "flex-start",
|
|
299
|
+
minWidth: 0,
|
|
300
|
+
children: [
|
|
301
|
+
/*#__PURE__*/ jsxRuntime.jsx(NameButton, {
|
|
302
|
+
type: "button",
|
|
303
|
+
onClick: handleNameClick,
|
|
304
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(TruncatedText.TruncatedText, {
|
|
305
|
+
textColor: "neutral800",
|
|
306
|
+
fontWeight: "semiBold",
|
|
307
|
+
children: asset.name
|
|
308
|
+
})
|
|
309
|
+
}),
|
|
310
|
+
!isDesktop && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
311
|
+
textColor: "neutral600",
|
|
312
|
+
variant: "pi",
|
|
313
|
+
children: asset.size ? files.formatBytes(asset.size, 1) : '-'
|
|
314
|
+
})
|
|
315
|
+
]
|
|
229
316
|
})
|
|
230
317
|
]
|
|
318
|
+
}),
|
|
319
|
+
isMetadataMissing && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
|
|
320
|
+
label: metadataMissingLabel,
|
|
321
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(MetadataWarning, {
|
|
322
|
+
"aria-label": metadataMissingLabel,
|
|
323
|
+
role: "img"
|
|
324
|
+
})
|
|
231
325
|
})
|
|
232
326
|
]
|
|
233
327
|
})
|
|
234
328
|
}),
|
|
235
|
-
|
|
329
|
+
isDesktop && /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
236
330
|
children: [
|
|
237
331
|
/*#__PURE__*/ jsxRuntime.jsx(StyledTd, {
|
|
238
332
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
@@ -259,16 +353,14 @@ const AssetRow = ({ asset, orderedItemKeys, onAssetItemClick })=>{
|
|
|
259
353
|
]
|
|
260
354
|
}),
|
|
261
355
|
/*#__PURE__*/ jsxRuntime.jsx(StyledTd, {
|
|
356
|
+
onClick: stopRowEvent,
|
|
357
|
+
onKeyDown: stopRowEvent,
|
|
358
|
+
onPointerDown: stopRowEvent,
|
|
262
359
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
263
360
|
justifyContent: "flex-end",
|
|
264
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
defaultMessage: 'More actions'
|
|
268
|
-
}),
|
|
269
|
-
variant: "ghost",
|
|
270
|
-
onClick: (e)=>e.stopPropagation(),
|
|
271
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(icons.More, {})
|
|
361
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(AssetActionsMenu.AssetActionsMenu, {
|
|
362
|
+
asset: asset,
|
|
363
|
+
dragData: dragData
|
|
272
364
|
})
|
|
273
365
|
})
|
|
274
366
|
})
|
|
@@ -281,7 +373,7 @@ const FolderTr = styledComponents.styled(StyledTr)`
|
|
|
281
373
|
}
|
|
282
374
|
`;
|
|
283
375
|
const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
284
|
-
const
|
|
376
|
+
const isDesktop = strapiAdmin.useIsDesktop();
|
|
285
377
|
const { formatDate, formatMessage } = reactIntl.useIntl();
|
|
286
378
|
const { navigateToFolder } = useFolderNavigation.useFolderNavigation();
|
|
287
379
|
const { isSelected, toggle, selectRange } = useAssetSelection.useAssetSelection();
|
|
@@ -289,11 +381,18 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
289
381
|
const { isMovePending } = AssetsDndProvider.useAssetsDndOptional() ?? {
|
|
290
382
|
isMovePending: false
|
|
291
383
|
};
|
|
292
|
-
const { draggable: { attributes, listeners, setNodeRef: setDragRef, isDragging }, droppable: { setNodeRef: setDropRef }, showValidDropHighlight, showInvalidDropCursor } = useAssetDnd.useFolderDraggableDroppable(folder);
|
|
384
|
+
const { dragData, draggable: { attributes, listeners, setNodeRef: setDragRef, isDragging }, droppable: { setNodeRef: setDropRef }, showValidDropHighlight, showInvalidDropCursor } = useAssetDnd.useFolderDraggableDroppable(folder);
|
|
293
385
|
const key = selection.folderKey(folder.id);
|
|
294
386
|
// Folders share the selection mechanism with assets. Only the plain-click
|
|
295
387
|
// semantic differs: it navigates into the folder instead of selecting it.
|
|
388
|
+
//
|
|
389
|
+
// The containment guard on this and the handlers below is what keeps the
|
|
390
|
+
// actions menu's portaled dialogs — React children of this row — from
|
|
391
|
+
// navigating into the folder or starting a drag.
|
|
296
392
|
const handleRowClick = (e)=>{
|
|
393
|
+
if (!isEventFromWithin.isEventFromWithin(e)) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
297
396
|
if (e.shiftKey) {
|
|
298
397
|
selectRange(orderedItemKeys, key);
|
|
299
398
|
} else if (e.metaKey || e.ctrlKey) {
|
|
@@ -304,6 +403,9 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
304
403
|
};
|
|
305
404
|
// Enter navigates into the folder, Space toggles selection (same as assets).
|
|
306
405
|
const handleKeyDown = (e)=>{
|
|
406
|
+
if (!isEventFromWithin.isEventFromWithin(e)) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
307
409
|
if (e.key === 'Enter') {
|
|
308
410
|
e.preventDefault();
|
|
309
411
|
navigateToFolder(folder);
|
|
@@ -334,11 +436,20 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
334
436
|
$isSelected: isSelected(key),
|
|
335
437
|
tabIndex: 0,
|
|
336
438
|
role: "row",
|
|
337
|
-
onDragStart: (e)=>
|
|
439
|
+
onDragStart: (e)=>{
|
|
440
|
+
if (isEventFromWithin.isEventFromWithin(e)) {
|
|
441
|
+
e.preventDefault();
|
|
442
|
+
}
|
|
443
|
+
},
|
|
338
444
|
onClick: handleRowClick,
|
|
339
445
|
onKeyDown: handleKeyDown,
|
|
446
|
+
onPointerDown: (e)=>{
|
|
447
|
+
if (isEventFromWithin.isEventFromWithin(e)) {
|
|
448
|
+
listeners?.onPointerDown?.(e);
|
|
449
|
+
}
|
|
450
|
+
},
|
|
340
451
|
children: [
|
|
341
|
-
|
|
452
|
+
canUpdate && /*#__PURE__*/ jsxRuntime.jsx(CheckboxTd, {
|
|
342
453
|
onClick: stopRowEvent,
|
|
343
454
|
onKeyDown: stopRowEvent,
|
|
344
455
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
@@ -358,6 +469,7 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
358
469
|
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
359
470
|
gap: 3,
|
|
360
471
|
alignItems: "center",
|
|
472
|
+
minWidth: 0,
|
|
361
473
|
children: [
|
|
362
474
|
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
363
475
|
justifyContent: "center",
|
|
@@ -372,16 +484,15 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
372
484
|
height: 20
|
|
373
485
|
})
|
|
374
486
|
}),
|
|
375
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
487
|
+
/*#__PURE__*/ jsxRuntime.jsx(TruncatedText.TruncatedText, {
|
|
376
488
|
textColor: "neutral800",
|
|
377
489
|
fontWeight: "semiBold",
|
|
378
|
-
ellipsis: true,
|
|
379
490
|
children: folder.name
|
|
380
491
|
})
|
|
381
492
|
]
|
|
382
493
|
})
|
|
383
494
|
}),
|
|
384
|
-
|
|
495
|
+
isDesktop && /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
385
496
|
children: [
|
|
386
497
|
/*#__PURE__*/ jsxRuntime.jsx(StyledTd, {
|
|
387
498
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
@@ -408,16 +519,14 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
408
519
|
]
|
|
409
520
|
}),
|
|
410
521
|
/*#__PURE__*/ jsxRuntime.jsx(StyledTd, {
|
|
522
|
+
onClick: stopRowEvent,
|
|
523
|
+
onKeyDown: stopRowEvent,
|
|
524
|
+
onPointerDown: stopRowEvent,
|
|
411
525
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
412
526
|
justifyContent: "flex-end",
|
|
413
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
defaultMessage: 'More actions'
|
|
417
|
-
}),
|
|
418
|
-
variant: "ghost",
|
|
419
|
-
onClick: (e)=>e.stopPropagation(),
|
|
420
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(icons.More, {})
|
|
527
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(FolderActionsMenu.FolderActionsMenu, {
|
|
528
|
+
folder: folder,
|
|
529
|
+
dragData: dragData
|
|
421
530
|
})
|
|
422
531
|
})
|
|
423
532
|
})
|
|
@@ -425,16 +534,18 @@ const FolderRow = ({ folder, orderedItemKeys })=>{
|
|
|
425
534
|
});
|
|
426
535
|
};
|
|
427
536
|
const AssetsTable = ({ assets, folders = [], mixedItems = null, onAssetItemClick })=>{
|
|
428
|
-
const
|
|
537
|
+
const isDesktop = strapiAdmin.useIsDesktop();
|
|
429
538
|
const { formatMessage } = reactIntl.useIntl();
|
|
430
539
|
const { selectedKeys, selectAll, clear } = useAssetSelection.useAssetSelection();
|
|
431
540
|
const { canUpdate } = useMediaLibraryPermissions.useMediaLibraryPermissions();
|
|
432
|
-
const
|
|
541
|
+
const { trackUsage } = useTracking.useTracking();
|
|
542
|
+
// Below the desktop breakpoint only the name (and actions) column is kept —
|
|
543
|
+
// the date/size columns don't fit; size moves under the name as a subtitle.
|
|
544
|
+
const visibleHeaders = isDesktop ? constants.TABLE_HEADERS : constants.TABLE_HEADERS.filter((h)=>h.name === 'name' || h.name === 'actions');
|
|
433
545
|
// The checkbox column is a dedicated structural column (not part of
|
|
434
|
-
// TABLE_HEADERS). Hidden
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
const showCheckboxColumn = !isMobile && canUpdate;
|
|
546
|
+
// TABLE_HEADERS). Hidden only without the update permission — every bulk
|
|
547
|
+
// action needs `assets.update`, so a read-only user has nothing to select for.
|
|
548
|
+
const showCheckboxColumn = canUpdate;
|
|
438
549
|
const colCount = visibleHeaders.length + (showCheckboxColumn ? 1 : 0);
|
|
439
550
|
const totalRows = folders.length + assets.length;
|
|
440
551
|
// Render order — folders first by default, or the interleaved mixed order.
|
|
@@ -448,6 +559,7 @@ const AssetsTable = ({ assets, folders = [], mixedItems = null, onAssetItemClick
|
|
|
448
559
|
if (allSelected) {
|
|
449
560
|
clear();
|
|
450
561
|
} else {
|
|
562
|
+
trackUsage('didSelectAllMediaLibraryElements');
|
|
451
563
|
selectAll(orderedItemKeys);
|
|
452
564
|
}
|
|
453
565
|
};
|