@strapi/upload 5.52.3 → 5.54.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/future/components/Drawer.js +6 -3
- package/dist/admin/future/components/Drawer.js.map +1 -1
- package/dist/admin/future/components/Drawer.mjs +6 -3
- package/dist/admin/future/components/Drawer.mjs.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.js +9 -8
- package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.mjs +9 -8
- package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.js +16 -4
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +16 -4
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +5 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +5 -0
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +19 -4
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +19 -4
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +35 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +35 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +10 -0
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +10 -0
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +9 -0
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +10 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +132 -88
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +135 -91
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +7 -0
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +7 -0
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js +4 -1
- package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs +4 -1
- package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.js +181 -0
- package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.mjs +179 -0
- package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/constants.js +22 -0
- package/dist/admin/future/pages/Assets/constants.js.map +1 -1
- package/dist/admin/future/pages/Assets/constants.mjs +19 -1
- package/dist/admin/future/pages/Assets/constants.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +65 -10
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +66 -11
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.js +111 -0
- package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.mjs +109 -0
- package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.mjs.map +1 -0
- package/dist/admin/future/services/api.js +17 -0
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +18 -1
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/store/uploadProgress.js +31 -22
- package/dist/admin/future/store/uploadProgress.js.map +1 -1
- package/dist/admin/future/store/uploadProgress.mjs +31 -22
- package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
- package/dist/admin/index.js +11 -10
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +11 -10
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/future/components/Drawer.d.ts +10 -0
- package/dist/admin/src/future/pages/Assets/components/MainAreaContextMenu.d.ts +28 -0
- package/dist/admin/src/future/pages/Assets/constants.d.ts +20 -0
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +4 -0
- package/dist/admin/src/future/pages/Assets/hooks/useListScrollRestoration.d.ts +15 -0
- package/dist/admin/src/future/store/uploadProgress.d.ts +14 -20
- package/dist/admin/translations/en.json.js +1 -3
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +1 -3
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/bootstrap.js +11 -0
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +11 -0
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +31 -1
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +31 -1
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/controllers/utils/find-entity-and-check-permissions.js +15 -4
- package/dist/server/controllers/utils/find-entity-and-check-permissions.js.map +1 -1
- package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs +15 -4
- package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs.map +1 -1
- package/dist/server/controllers/utils/folders.js +1 -1
- package/dist/server/controllers/utils/folders.js.map +1 -1
- package/dist/server/controllers/utils/folders.mjs +1 -1
- package/dist/server/controllers/utils/folders.mjs.map +1 -1
- package/dist/server/mcp/ambient-instance.js +46 -0
- package/dist/server/mcp/ambient-instance.js.map +1 -0
- package/dist/server/mcp/ambient-instance.mjs +43 -0
- package/dist/server/mcp/ambient-instance.mjs.map +1 -0
- package/dist/server/mcp/handlers/constants.js +60 -0
- package/dist/server/mcp/handlers/constants.js.map +1 -0
- package/dist/server/mcp/handlers/constants.mjs +45 -0
- package/dist/server/mcp/handlers/constants.mjs.map +1 -0
- package/dist/server/mcp/handlers/folder-handlers.js +308 -0
- package/dist/server/mcp/handlers/folder-handlers.js.map +1 -0
- package/dist/server/mcp/handlers/folder-handlers.mjs +303 -0
- package/dist/server/mcp/handlers/folder-handlers.mjs.map +1 -0
- package/dist/server/mcp/handlers/read-handlers.js +134 -0
- package/dist/server/mcp/handlers/read-handlers.js.map +1 -0
- package/dist/server/mcp/handlers/read-handlers.mjs +130 -0
- package/dist/server/mcp/handlers/read-handlers.mjs.map +1 -0
- package/dist/server/mcp/handlers/write-handlers.js +315 -0
- package/dist/server/mcp/handlers/write-handlers.js.map +1 -0
- package/dist/server/mcp/handlers/write-handlers.mjs +311 -0
- package/dist/server/mcp/handlers/write-handlers.mjs.map +1 -0
- package/dist/server/mcp/permissions.js +36 -0
- package/dist/server/mcp/permissions.js.map +1 -0
- package/dist/server/mcp/permissions.mjs +33 -0
- package/dist/server/mcp/permissions.mjs.map +1 -0
- package/dist/server/mcp/register-upload-mcp-tools.js +235 -0
- package/dist/server/mcp/register-upload-mcp-tools.js.map +1 -0
- package/dist/server/mcp/register-upload-mcp-tools.mjs +232 -0
- package/dist/server/mcp/register-upload-mcp-tools.mjs.map +1 -0
- package/dist/server/mcp/sanitizers/sanitize-media.js +97 -0
- package/dist/server/mcp/sanitizers/sanitize-media.js.map +1 -0
- package/dist/server/mcp/sanitizers/sanitize-media.mjs +93 -0
- package/dist/server/mcp/sanitizers/sanitize-media.mjs.map +1 -0
- package/dist/server/mcp/schemas/input-schemas.js +206 -0
- package/dist/server/mcp/schemas/input-schemas.js.map +1 -0
- package/dist/server/mcp/schemas/input-schemas.mjs +190 -0
- package/dist/server/mcp/schemas/input-schemas.mjs.map +1 -0
- package/dist/server/mcp/schemas/output-schemas.js +158 -0
- package/dist/server/mcp/schemas/output-schemas.js.map +1 -0
- package/dist/server/mcp/schemas/output-schemas.mjs +142 -0
- package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -0
- package/dist/server/mcp/utils.js +14 -0
- package/dist/server/mcp/utils.js.map +1 -0
- package/dist/server/mcp/utils.mjs +12 -0
- package/dist/server/mcp/utils.mjs.map +1 -0
- package/dist/server/media-library-default-notice.js +42 -0
- package/dist/server/media-library-default-notice.js.map +1 -0
- package/dist/server/media-library-default-notice.mjs +40 -0
- package/dist/server/media-library-default-notice.mjs.map +1 -0
- package/dist/server/register.js +5 -0
- package/dist/server/register.js.map +1 -1
- package/dist/server/register.mjs +5 -0
- package/dist/server/register.mjs.map +1 -1
- package/dist/server/services/folder.js.map +1 -1
- package/dist/server/services/folder.mjs.map +1 -1
- package/dist/server/services/upload.js +34 -10
- package/dist/server/services/upload.js.map +1 -1
- package/dist/server/services/upload.mjs +34 -10
- package/dist/server/services/upload.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +1 -0
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/find-entity-and-check-permissions.d.ts +14 -1
- package/dist/server/src/controllers/utils/find-entity-and-check-permissions.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/folders.d.ts +2 -1
- package/dist/server/src/controllers/utils/folders.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +10 -2
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/mcp/ambient-instance.d.ts +65 -0
- package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/constants.d.ts +48 -0
- package/dist/server/src/mcp/handlers/constants.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/folder-handlers.d.ts +49 -0
- package/dist/server/src/mcp/handlers/folder-handlers.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/index.d.ts +5 -0
- package/dist/server/src/mcp/handlers/index.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/read-handlers.d.ts +35 -0
- package/dist/server/src/mcp/handlers/read-handlers.d.ts.map +1 -0
- package/dist/server/src/mcp/handlers/write-handlers.d.ts +66 -0
- package/dist/server/src/mcp/handlers/write-handlers.d.ts.map +1 -0
- package/dist/server/src/mcp/index.d.ts +3 -0
- package/dist/server/src/mcp/index.d.ts.map +1 -0
- package/dist/server/src/mcp/permissions.d.ts +22 -0
- package/dist/server/src/mcp/permissions.d.ts.map +1 -0
- package/dist/server/src/mcp/register-upload-mcp-tools.d.ts +29 -0
- package/dist/server/src/mcp/register-upload-mcp-tools.d.ts.map +1 -0
- package/dist/server/src/mcp/sanitizers/sanitize-media.d.ts +63 -0
- package/dist/server/src/mcp/sanitizers/sanitize-media.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/index.d.ts +3 -0
- package/dist/server/src/mcp/schemas/index.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/input-schemas.d.ts +148 -0
- package/dist/server/src/mcp/schemas/input-schemas.d.ts.map +1 -0
- package/dist/server/src/mcp/schemas/output-schemas.d.ts +276 -0
- package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -0
- package/dist/server/src/mcp/types.d.ts +19 -0
- package/dist/server/src/mcp/types.d.ts.map +1 -0
- package/dist/server/src/mcp/utils.d.ts +4 -0
- package/dist/server/src/mcp/utils.d.ts.map +1 -0
- package/dist/server/src/media-library-default-notice.d.ts +19 -0
- package/dist/server/src/media-library-default-notice.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/services/folder.d.ts +6 -2
- package/dist/server/src/services/folder.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +10 -2
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/upload.d.ts +10 -1
- package/dist/server/src/services/upload.d.ts.map +1 -1
- package/dist/server/src/types.d.ts +2 -2
- package/dist/server/src/types.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -1
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/server/utils/index.js +2 -2
- package/dist/server/utils/index.js.map +1 -1
- package/dist/server/utils/index.mjs +2 -2
- package/dist/server/utils/index.mjs.map +1 -1
- package/dist/shared/contracts/files.d.ts +22 -0
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/package.json +7 -6
- package/dist/admin/future/components/BetaNotice.js +0 -72
- package/dist/admin/future/components/BetaNotice.js.map +0 -1
- package/dist/admin/future/components/BetaNotice.mjs +0 -70
- package/dist/admin/future/components/BetaNotice.mjs.map +0 -1
- package/dist/admin/src/future/components/BetaNotice.d.ts +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsPage.mjs","sources":["../../../../../admin/src/future/pages/Assets/AssetsPage.tsx"],"sourcesContent":["import { useRef, useCallback, useMemo, useState, useEffect, type ChangeEvent } from 'react';\n\nimport * as ToggleGroup from '@radix-ui/react-toggle-group';\nimport { Layouts, Page, useElementOnScreen, usePersistentState } from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Flex,\n Loader,\n MenuItem,\n SimpleMenu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport {\n ChevronDown,\n Files,\n Folder as FolderIcon,\n GridFour as GridIcon,\n Link,\n List,\n} from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled, css } from 'styled-components';\n\nimport { typeFromMime } from '../../../utils/typeFromMime';\nimport { BetaNotice } from '../../components/BetaNotice';\nimport { useAIMetadataEnabled } from '../../hooks/useAIMetadataEnabled';\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../hooks/useTracking';\nimport { useUploadFromUrlsMutation, useUploadFilesMutation } from '../../services/api';\nimport { useGetFolderQuery, useGetFoldersQuery } from '../../services/folders';\nimport { useGetUploadSettingsQuery } from '../../services/settings';\nimport { buildItemLocations, type ItemLocations } from '../../utils/itemLocations';\nimport { getTranslationKey } from '../../utils/translations';\n\nimport {\n AssetDetailsDrawer,\n useAssetDetailsParam,\n} from './components/AssetDetails/AssetDetailsDrawer';\nimport { AssetsGrid } from './components/AssetsGrid';\nimport { AssetsSearchInput } from './components/AssetsSearchInput';\nimport { AssetsTable } from './components/AssetsTable';\nimport { BulkActionsBar } from './components/BulkActionsBar';\nimport { AssetsDndProvider } from './components/Dnd/AssetsDndProvider';\nimport { DropFilesMessage, DropZoneWithOverlay } from './components/DropZone/UploadDropZone';\nimport { UploadDropZoneProvider } from './components/DropZone/UploadDropZoneContext';\nimport { EmptyState, FilteredEmptyState } from './components/EmptyState';\nimport { FilterBadges } from './components/FilterBadges';\nimport { FilterMenu } from './components/FilterMenu';\nimport { FolderFormDialog } from './components/FolderFormDialog';\nimport { FolderTree } from './components/FolderTree/FolderTree';\nimport { ImportFromUrlDialog } from './components/ImportFromUrlDialog';\nimport { SortMenu } from './components/SortMenu';\nimport { localStorageKeys, viewOptions } from './constants';\nimport { useAssetSearch } from './hooks/useAssetSearch';\nimport { AssetSelectionProvider, useAssetSelection } from './hooks/useAssetSelection';\nimport { BusyAssetsProvider } from './hooks/useBusyAssets';\nimport { useFolderInfo } from './hooks/useFolderInfo';\nimport { useFolderNavigation } from './hooks/useFolderNavigation';\nimport { useInfiniteAssets } from './hooks/useInfiniteAssets';\nimport { useInfiniteScrollSentinel } from './hooks/useInfiniteScrollSentinel';\nimport { useListFilters } from './hooks/useListFilters';\nimport { useListSort, type FoldersPosition } from './hooks/useListSort';\nimport { buildAssetFilters } from './utils/buildAssetFilters';\nimport { getListQueryKey } from './utils/listQueryKey';\nimport { mergeMixedList } from './utils/mergeMixedList';\nimport { buildRenderedKeys } from './utils/renderedKeys';\n\nimport type { File, UploadFileInfo } from '../../../../../shared/contracts/files';\nimport type { Folder } from '../../../../../shared/contracts/folders';\n\n// The negative bottom margin shrinks the trigger area by a pixel so the 1px\n// sentinel sitting exactly at the fold (when a page's rows happen to fill the\n// viewport) reads as \"not visible\" and doesn't pull an extra page. It still\n// triggers as soon as the sentinel scrolls a hair into view. Tune the bottom\n// value if the list over- or under-fetches near the fold.\nconst INTERSECTION_OPTIONS: IntersectionObserverInit = {\n threshold: 0,\n rootMargin: '0px 0px -1px 0px',\n};\n\n// Module-level so the header sentinel's observer isn't rebuilt every render.\nconst HEADER_SENTINEL_OPTIONS: IntersectionObserverInit = { threshold: 0 };\n\nconst ITEM_COUNT_MESSAGE = {\n id: getTranslationKey('header.content.item-count'),\n defaultMessage: '{count, plural, =1 {# item} other {# items}}',\n};\n\nconst SEARCH_RESULTS_COUNT_MESSAGES = {\n both: {\n id: getTranslationKey('header.search-results.count'),\n defaultMessage:\n '{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 asset} other {# assets}}',\n },\n folders: {\n id: getTranslationKey('header.search-results.count.folders'),\n defaultMessage: '{numberFolders, plural, one {1 folder} other {# folders}}',\n },\n assets: {\n id: getTranslationKey('header.search-results.count.assets'),\n defaultMessage: '{numberAssets, plural, =0 {0 assets} one {1 asset} other {# assets}}',\n },\n};\n\nconst getSearchResultsCountMessage = (numberFolders: number, numberAssets: number) => {\n if (numberFolders === 0) {\n return SEARCH_RESULTS_COUNT_MESSAGES.assets;\n }\n\n if (numberAssets === 0) {\n return SEARCH_RESULTS_COUNT_MESSAGES.folders;\n }\n\n return SEARCH_RESULTS_COUNT_MESSAGES.both;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsView\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsViewProps {\n view: number;\n folders: Folder[];\n isLoadingFolders: boolean;\n assets: File[];\n isLoadingAssets: boolean;\n isFetchingMore: boolean;\n hasNextPage: boolean;\n fetchNextPage: () => void;\n error: unknown;\n locations: ItemLocations;\n searchQuery: string;\n assetsSort: string;\n foldersPosition: FoldersPosition;\n hasActiveFilters: boolean;\n onClearFilters: () => void;\n onAssetItemClick: (assetId: number) => void;\n onAddAssets: () => void;\n canAddAssets: boolean;\n onClearSearch: () => void;\n}\n\nconst AssetsView = ({\n view,\n folders,\n isLoadingFolders,\n assets,\n isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n error,\n locations,\n searchQuery,\n assetsSort,\n foldersPosition,\n hasActiveFilters,\n onClearFilters,\n onAssetItemClick,\n onAddAssets,\n canAddAssets,\n onClearSearch,\n}: AssetsViewProps) => {\n const { formatMessage } = useIntl();\n\n const isGridView = view === viewOptions.GRID;\n const isLoading = isLoadingAssets || isLoadingFolders;\n\n // \"Folders: Mixed with files\" — interleave the complete folder list into the\n // loaded asset stream client-side, following the active sort. Table view\n // only: the grid always keeps folders in their own band on top.\n const mixedItems = useMemo(\n () =>\n foldersPosition === 'mixed' && !isGridView\n ? mergeMixedList({ folders, assets, sort: assetsSort, hasNextPage })\n : null,\n [foldersPosition, isGridView, folders, assets, assetsSort, hasNextPage]\n );\n\n // Derived once here so the table, the grid and the bulk bar all agree on what\n // is on screen — in mixed mode that is not simply every folder.\n const renderedKeys = buildRenderedKeys({ folders, assets, mixedItems });\n\n const loadMoreRef = useInfiniteScrollSentinel({\n hasNextPage,\n isFetchingMore,\n onLoadMore: fetchNextPage,\n options: INTERSECTION_OPTIONS,\n });\n\n if (isLoading) {\n return (\n <Flex justifyContent=\"center\" padding={8}>\n <Loader>{formatMessage({ id: 'app.loading', defaultMessage: 'Loading...' })}</Loader>\n </Flex>\n );\n }\n\n if (error) {\n return (\n <Box padding={8}>\n <Typography textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('list.assets.error'),\n defaultMessage: 'An error occurred while fetching assets.',\n })}\n </Typography>\n </Box>\n );\n }\n\n if (folders.length === 0 && assets.length === 0) {\n // While searching, the search empty state wins (it names the query); a\n // filter-only dead end gets the filtered variant with its Clear action.\n return hasActiveFilters && !searchQuery ? (\n <FilteredEmptyState onClearFilters={onClearFilters} />\n ) : (\n <EmptyState\n onAddAssets={onAddAssets}\n canAddAssets={canAddAssets}\n searchQuery={searchQuery}\n onClearSearch={onClearSearch}\n />\n );\n }\n return (\n <>\n {isGridView ? (\n <AssetsGrid\n folders={folders}\n assets={assets}\n renderedKeys={renderedKeys}\n onAssetItemClick={onAssetItemClick}\n />\n ) : (\n <AssetsTable\n assets={assets}\n folders={folders}\n mixedItems={mixedItems}\n renderedKeys={renderedKeys}\n onAssetItemClick={onAssetItemClick}\n />\n )}\n <div ref={loadMoreRef} style={{ height: 1 }} />\n {isFetchingMore && (\n <Flex justifyContent=\"center\" padding={4}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('list.assets.loading-more'),\n defaultMessage: 'Loading more assets...',\n })}\n </Loader>\n </Flex>\n )}\n {/* Lives here rather than in `AssetsPage` so it can read the loaded\n assets: the AI metadata action needs their mime types to know what\n the provider can handle. `position: fixed` keeps it visually anchored\n regardless of where it sits in the tree. */}\n <BulkActionsBar assets={assets} renderedKeys={renderedKeys} locations={locations} />\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ClearSelectionOnChange\n *\n * Selection is list-scoped: it resets when the user is looking at a different list.\n * The list fingerprint is getListQueryKey() — folder, search, sort, filter.\n *\n * Hybrid rule: infinite scroll does not change the key (selection persists), and\n * neither does the table/grid toggle — both views render the same list.\n * Search/sort/filter changes do (selection clears) — same mental model as folder nav.\n * -----------------------------------------------------------------------------------------------*/\n\ninterface ClearSelectionOnChangeProps {\n listQueryKey: string;\n}\n\nconst ClearSelectionOnChange = ({ listQueryKey }: ClearSelectionOnChangeProps) => {\n const { clear } = useAssetSelection();\n\n useEffect(() => {\n clear();\n }, [listQueryKey, clear]);\n\n return null;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsPage\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * Mirrors the design-system Toggle look (grey track, white active segment\n * card) — reproduced locally because the DS component is a labels-only\n * boolean input (no icons) and paints its left segment in danger red. Here\n * both segments use the primary blue when active.\n */\nconst StyledToggleGroup = styled(ToggleGroup.Root)`\n display: flex;\n padding: ${({ theme }) => theme.spaces[1]};\n background: ${({ theme }) => theme.colors.neutral100};\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n`;\n\nconst StyledToggleItem = styled(ToggleGroup.Item)`\n display: flex;\n flex: 1 1 50%;\n align-items: center;\n justify-content: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: 0.6rem ${({ theme }) => theme.spaces[3]};\n border: 1px solid transparent;\n border-radius: ${({ theme }) => theme.borderRadius};\n background: transparent;\n color: ${({ theme }) => theme.colors.neutral600};\n cursor: pointer;\n font-size: ${({ theme }) => theme.fontSizes[1]};\n font-weight: ${({ theme }) => theme.fontWeights.semiBold};\n white-space: nowrap;\n\n &:hover {\n color: ${({ theme }) => theme.colors.neutral700};\n }\n\n &[data-state='on'] {\n background: ${({ theme }) => theme.colors.neutral0};\n border-color: ${({ theme }) => theme.colors.neutral200};\n color: ${({ theme }) => theme.colors.primary600};\n }\n\n svg {\n width: 1.6rem;\n height: 1.6rem;\n }\n`;\n\n// A single sticky header — same layout scrolled or not, so the toolbar\n// alignment can't reflow the way the shared sticky header did. Once the list\n// scrolls under it, it shrinks (reduced vertical padding + a shadow to lift it\n// off the rows), like the sticky headers elsewhere in the admin. Horizontal\n// padding stays responsive (passed as props); only the vertical rhythm + shadow\n// change here so they can animate.\nconst StickyHeader = styled(Box)<{ $compact: boolean }>`\n position: sticky;\n top: 0;\n z-index: 2;\n /* Transparent at rest (the grey page shows through); an opaque background +\n shadow appear only once it sticks and content scrolls under it. */\n background: transparent;\n /* Horizontal padding matches the list's default spacing (Layouts.Content /\n RESPONSIVE_DEFAULT_SPACING: 4 / 6 / 10) so the header lines up with the rows. */\n padding: ${({ theme }) => `${theme.spaces[6]} ${theme.spaces[4]}`};\n transition:\n padding 0.2s ease,\n background 0.2s ease,\n box-shadow 0.2s ease;\n\n ${({ theme }) => theme.breakpoints.medium} {\n padding-left: ${({ theme }) => theme.spaces[6]};\n padding-right: ${({ theme }) => theme.spaces[6]};\n }\n ${({ theme }) => theme.breakpoints.large} {\n padding-left: ${({ theme }) => theme.spaces[10]};\n padding-right: ${({ theme }) => theme.spaces[10]};\n }\n\n /* Compacting is scoped to medium and up, where the header actually sticks. On\n mobile it scrolls away with the list, so shrinking it mid-scroll animated a\n header the user could no longer see — the transition read as a glitch on the\n way back up rather than as the header settling. */\n ${({ $compact, theme }) =>\n $compact &&\n css`\n ${theme.breakpoints.medium} {\n padding-top: ${theme.spaces[3]};\n padding-bottom: ${theme.spaces[3]};\n padding-left: ${theme.spaces[4]};\n padding-right: ${theme.spaces[4]};\n background: ${theme.colors.neutral0};\n box-shadow: ${theme.shadows.tableShadow};\n }\n ${theme.breakpoints.large} {\n padding-left: ${theme.spaces[6]};\n padding-right: ${theme.spaces[6]};\n }\n `}\n`;\n\n// New button aligns with the title, not the toolbar.\nconst TitleRow = styled(Flex)`\n justify-content: space-between;\n align-items: flex-start;\n gap: ${({ theme }) => theme.spaces[4]};\n\n h1 {\n font-size: 1.8rem;\n }\n`;\n\n// Two groups in source order (Filter, Search / Sort, Toggle). Mobile: stacked —\n// Filter+Search on row 1, Sort+Toggle on row 2. Desktop (large+): one row,\n// Filter+Search on the left, Sort+Toggle pushed right.\nconst Toolbar = styled(Flex)<{ $compact: boolean }>`\n margin-top: ${({ theme }) => theme.spaces[5]};\n flex-direction: column;\n align-items: stretch;\n gap: ${({ theme }) => theme.spaces[3]};\n transition: margin-top 0.2s ease;\n\n /* Tightening the gap to the title belongs to the compact header, so it is\n scoped to the breakpoints that compact. On mobile the header never sticks,\n and this was the last thing still shifting as the page scrolled. */\n ${({ $compact, theme }) =>\n $compact &&\n css`\n ${theme.breakpoints.medium} {\n margin-top: ${theme.spaces[2]};\n }\n `}\n\n ${({ theme }) => theme.breakpoints.large} {\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n }\n`;\n\nconst ToolbarGroup = styled(Flex)`\n align-items: center;\n gap: ${({ theme }) => theme.spaces[3]};\n`;\n\n// Filter + Search. On mobile the group fills the row (search grows into it);\n// on desktop it keeps its intrinsic size and sits at the left edge.\nconst FilterSearchGroup = styled(ToolbarGroup)``;\n\n// Sort + Toggle. Mobile: spread across the row (Sort left, Toggle right).\n// Desktop: sit together at the right edge (space-between on the toolbar leaves\n// the empty space between the search and here).\nconst SortToggleGroup = styled(ToolbarGroup)`\n justify-content: space-between;\n\n ${({ theme }) => theme.breakpoints.large} {\n justify-content: flex-end;\n flex: 0 0 auto;\n }\n`;\n\n// Fills the row on mobile; intrinsic width on desktop.\nconst SearchSlot = styled(Box)`\n flex: 1;\n\n ${({ theme }) => theme.breakpoints.large} {\n flex: 0 1 auto;\n }\n`;\n\n// Toggle labels are hidden below desktop — icons only (buttons keep aria-label).\nconst ToggleLabel = styled.span`\n display: none;\n\n ${({ theme }) => theme.breakpoints.large} {\n display: inline;\n }\n`;\n\nexport const AssetsPage = () => {\n const { formatMessage } = useIntl();\n const { openDetails } = useAssetDetailsParam();\n const { canCreate, canUpdate } = useMediaLibraryPermissions();\n\n const { currentFolderId, navigateToFolderId, navigateToRoot } = useFolderNavigation();\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 const { title, itemCount } = useFolderInfo(currentFolderId);\n\n const { searchQuery, isSearching, clearSearch } = useAssetSearch();\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: assetPageSubscribers,\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 // Both move affordances (drag and the bulk bar) resolve each item's parent\n // from the rows on screen — while searching, results are global and the\n // folder currently open says nothing about where an item lives.\n const itemLocations = useMemo(() => buildItemLocations(assets, folders), [assets, folders]);\n\n const itemCountLabel = formatMessage(ITEM_COUNT_MESSAGE, { count: itemCount });\n\n const searchResultsTitle = formatMessage(\n {\n id: getTranslationKey('header.search-results'),\n defaultMessage: 'Search results for \"{query}\"',\n },\n { query: searchQuery }\n );\n const numberFolders = folders.length;\n const numberAssets = pagination?.total ?? 0;\n\n const searchResultsCountLabel = formatMessage(\n getSearchResultsCountMessage(numberFolders, numberAssets),\n { numberFolders, numberAssets }\n );\n\n let pageHeaderTitle: string;\n if (isSearching) {\n pageHeaderTitle = `${searchResultsTitle} (${searchResultsCountLabel})`;\n } else if (title) {\n pageHeaderTitle = `${title} (${itemCountLabel})`;\n } else {\n pageHeaderTitle = formatMessage({ id: 'app.loading', defaultMessage: 'Loading...' });\n }\n\n const [isCreateFolderDialogOpen, setIsCreateFolderDialogOpen] = useState(false);\n\n // View state\n const [view, setView] = usePersistentState(localStorageKeys.view, viewOptions.GRID);\n const isGridView = view === viewOptions.GRID;\n\n // Dialog state\n const [isUrlDialogOpen, setIsUrlDialogOpen] = useState(false);\n\n // Refs\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadDropZoneRef = useRef<HTMLDivElement>(null);\n\n // Shrink the sticky header once the list scrolls beneath it. A zero-height\n // sentinel sits at the very top of the scroll content; when it leaves the\n // viewport we're scrolled → compact.\n const [isHeaderCompact, setIsHeaderCompact] = useState(false);\n const onHeaderSentinelVisibility = useCallback(\n (isVisible: boolean) => setIsHeaderCompact(!isVisible),\n []\n );\n const headerSentinelRef = useElementOnScreen<HTMLDivElement>(\n onHeaderSentinelVisibility,\n HEADER_SENTINEL_OPTIONS\n );\n\n // Upload handlers\n const [uploadFiles] = useUploadFilesMutation();\n const [uploadFromUrls] = useUploadFromUrlsMutation();\n // `concurrentUploadRequests` echoes the app config. Missing settings (still\n // loading, no permission) fall back to sequential — never faster than the\n // server asked for.\n const { data: settings } = useGetUploadSettingsQuery();\n const concurrency = settings?.data?.concurrentUploadRequests ?? 1;\n // Drives the post-upload AI metadata phase shown per row in the progress\n // dialog. No mime argument: the files are not known until they are picked,\n // and the server filters the batch on the same allowlist anyway.\n const isAiMetadataEnabled = useAIMetadataEnabled();\n const { trackUsage } = useTracking();\n\n const uploadFilesToFolder = async (files: globalThis.File[], folderId: number | null) => {\n if (files.length === 0) return;\n\n // Mirror the legacy `willAddMediaLibraryAssets` payload: the count of files\n // about to upload, broken down by asset type.\n const assetsCountByType = files.reduce<Record<string, number>>((acc, file) => {\n const type = typeFromMime(file.type);\n acc[type] = (acc[type] ?? 0) + 1;\n return acc;\n }, {});\n trackUsage('willAddMediaLibraryAssets', {\n location: MEDIA_LIBRARY_LOCATION,\n ...assetsCountByType,\n });\n\n const formData = new FormData();\n const fileInfoArray: UploadFileInfo[] = [];\n\n files.forEach((file) => {\n formData.append('files', file);\n fileInfoArray.push({\n name: file.name,\n caption: null,\n alternativeText: null,\n folder: folderId,\n });\n });\n\n formData.append('fileInfo', JSON.stringify(fileInfoArray));\n try {\n await uploadFiles({\n formData,\n totalFiles: files.length,\n concurrency,\n generateAiMetadata: Boolean(isAiMetadataEnabled),\n }).unwrap();\n } catch {\n // Error is already dispatched to store from the API queryFn\n }\n };\n\n const handleFileSelect = () => {\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (files && files.length > 0) {\n trackUsage('didSelectFile', { source: 'computer', location: MEDIA_LIBRARY_LOCATION });\n await uploadFilesToFolder(Array.from(files), currentFolderId);\n }\n e.target.value = '';\n };\n\n const handleDrop = async (files: globalThis.File[]) => {\n // Defence in depth: the provider is `disabled` without `assets.create`\n // (so onDrop won't fire), but guard here too in case it's ever wired live.\n if (!canCreate) return;\n trackUsage('didSelectFile', { source: 'computer', location: MEDIA_LIBRARY_LOCATION });\n await uploadFilesToFolder(files, currentFolderId);\n };\n\n const handleUrlUpload = async (urls: string[]) => {\n trackUsage('didSelectFile', { source: 'url', location: MEDIA_LIBRARY_LOCATION });\n // Counts-by-type aren't available client-side for the URL flow (the server\n // fetches the files), so this fires the event with location only.\n trackUsage('willAddMediaLibraryAssets', { location: MEDIA_LIBRARY_LOCATION });\n try {\n await uploadFromUrls({\n urls,\n folderId: currentFolderId,\n generateAiMetadata: Boolean(isAiMetadataEnabled),\n }).unwrap();\n } catch {\n // Error is already dispatched to store from the API queryFn\n }\n };\n\n // The view is deliberately absent: table and grid render the same list, so\n // toggling views keeps the selection.\n const listQueryKey = getListQueryKey({\n folderId: currentFolderId,\n search: searchQuery,\n // Folder position changes the render order too — selection must reset.\n sort: `${listSort.assetsSort};folders=${listSort.foldersPosition}`,\n filter: listFilters.serialized || null,\n });\n\n return (\n <>\n <UploadDropZoneProvider onDrop={handleDrop} disabled={!canCreate}>\n <AssetSelectionProvider disabled={!canUpdate}>\n <BusyAssetsProvider>\n <AssetsDndProvider locations={itemLocations}>\n <ClearSelectionOnChange listQueryKey={listQueryKey} />\n <Layouts.Root\n sideNav={\n <FolderTree\n currentFolderId={currentFolderId}\n showActiveFolder={!isSearching}\n onSelectFolder={navigateToFolderId}\n />\n }\n >\n <Page.Main>\n <Box ref={uploadDropZoneRef}>\n <VisuallyHidden>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} multiple />\n </VisuallyHidden>\n\n {/* Zero-height marker: leaves the viewport as soon as the list\n scrolls, flipping the header into its compact state. */}\n <Box ref={headerSentinelRef} height={0} aria-hidden />\n\n <StickyHeader $compact={isHeaderCompact}>\n <TitleRow>\n <Typography variant=\"alpha\" tag=\"h1\">\n {pageHeaderTitle}\n </Typography>\n {canCreate && (\n <SimpleMenu\n popoverPlacement=\"bottom-end\"\n variant=\"default\"\n endIcon={<ChevronDown />}\n label={formatMessage({\n id: getTranslationKey('new'),\n defaultMessage: 'New',\n })}\n >\n <MenuItem\n onSelect={() => setIsCreateFolderDialogOpen(true)}\n startIcon={<FolderIcon />}\n >\n {formatMessage({\n id: getTranslationKey('folder.create.title'),\n defaultMessage: 'New folder',\n })}\n </MenuItem>\n <MenuItem onSelect={handleFileSelect} startIcon={<Files />}>\n {formatMessage({\n id: getTranslationKey('import-files'),\n defaultMessage: 'Import files',\n })}\n </MenuItem>\n <MenuItem\n onSelect={() => setIsUrlDialogOpen(true)}\n startIcon={<Link />}\n >\n {formatMessage({\n id: getTranslationKey('import-from-url'),\n defaultMessage: 'Import from URL',\n })}\n </MenuItem>\n </SimpleMenu>\n )}\n </TitleRow>\n\n <Toolbar $compact={isHeaderCompact}>\n <FilterSearchGroup>\n <Box>\n <FilterMenu listFilters={listFilters} />\n </Box>\n <SearchSlot>\n <AssetsSearchInput />\n </SearchSlot>\n </FilterSearchGroup>\n <SortToggleGroup>\n <Box>\n <SortMenu sort={listSort} showFoldersGroup={!isGridView} />\n </Box>\n <StyledToggleGroup\n type=\"single\"\n value={isGridView ? 'grid' : 'table'}\n onValueChange={(value) =>\n value &&\n setView(value === 'grid' ? viewOptions.GRID : viewOptions.TABLE)\n }\n aria-label={formatMessage({\n id: getTranslationKey('view.switch.label'),\n defaultMessage: 'View options',\n })}\n >\n <StyledToggleItem\n value=\"table\"\n aria-label={formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\n >\n <List />\n <ToggleLabel>\n {formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\n </ToggleLabel>\n </StyledToggleItem>\n <StyledToggleItem\n value=\"grid\"\n aria-label={formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n >\n <GridIcon />\n <ToggleLabel>\n {formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n </ToggleLabel>\n </StyledToggleItem>\n </StyledToggleGroup>\n </SortToggleGroup>\n </Toolbar>\n\n <FilterBadges listFilters={listFilters} compact={isHeaderCompact} />\n </StickyHeader>\n\n <Layouts.Content>\n <BetaNotice />\n {/* Renders nothing — keeps every loaded page's query subscribed\n so a rename/delete refreshes the whole list. */}\n {assetPageSubscribers}\n <DropZoneWithOverlay>\n <DropFilesMessage\n uploadDropZoneRef={uploadDropZoneRef}\n folderName={title}\n />\n <AssetsView\n view={view}\n folders={folders}\n isLoadingFolders={isLoadingFolders}\n assets={assets}\n isLoadingAssets={isLoadingAssets}\n isFetchingMore={isFetchingMore}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n error={assetsError}\n locations={itemLocations}\n searchQuery={searchQuery}\n assetsSort={listSort.assetsSort}\n foldersPosition={listSort.foldersPosition}\n hasActiveFilters={listFilters.filters.length > 0}\n onClearFilters={listFilters.clearFilters}\n onAssetItemClick={openDetails}\n onAddAssets={handleFileSelect}\n canAddAssets={canCreate}\n onClearSearch={clearSearch}\n />\n </DropZoneWithOverlay>\n </Layouts.Content>\n </Box>\n </Page.Main>\n </Layouts.Root>\n </AssetsDndProvider>\n </BusyAssetsProvider>\n </AssetSelectionProvider>\n </UploadDropZoneProvider>\n <FolderFormDialog\n open={isCreateFolderDialogOpen}\n mode=\"create\"\n parentFolderName={title}\n parentFolderId={currentFolderId}\n onClose={() => setIsCreateFolderDialogOpen(false)}\n />\n <ImportFromUrlDialog\n open={isUrlDialogOpen}\n onClose={() => setIsUrlDialogOpen(false)}\n onUpload={handleUrlUpload}\n />\n <AssetDetailsDrawer />\n </>\n );\n};\n"],"names":["INTERSECTION_OPTIONS","threshold","rootMargin","HEADER_SENTINEL_OPTIONS","ITEM_COUNT_MESSAGE","id","getTranslationKey","defaultMessage","SEARCH_RESULTS_COUNT_MESSAGES","both","folders","assets","getSearchResultsCountMessage","numberFolders","numberAssets","AssetsView","view","isLoadingFolders","isLoadingAssets","isFetchingMore","hasNextPage","fetchNextPage","error","locations","searchQuery","assetsSort","foldersPosition","hasActiveFilters","onClearFilters","onAssetItemClick","onAddAssets","canAddAssets","onClearSearch","formatMessage","useIntl","isGridView","viewOptions","GRID","isLoading","mixedItems","useMemo","mergeMixedList","sort","renderedKeys","buildRenderedKeys","loadMoreRef","useInfiniteScrollSentinel","onLoadMore","options","_jsx","Flex","justifyContent","padding","Loader","Box","Typography","textColor","length","FilteredEmptyState","EmptyState","_jsxs","_Fragment","AssetsGrid","AssetsTable","div","ref","style","height","BulkActionsBar","ClearSelectionOnChange","listQueryKey","clear","useAssetSelection","useEffect","StyledToggleGroup","styled","ToggleGroup","Root","theme","spaces","colors","neutral100","neutral200","borderRadius","StyledToggleItem","Item","neutral600","fontSizes","fontWeights","semiBold","neutral700","neutral0","primary600","StickyHeader","breakpoints","medium","large","$compact","css","shadows","tableShadow","TitleRow","Toolbar","ToolbarGroup","FilterSearchGroup","SortToggleGroup","SearchSlot","ToggleLabel","span","AssetsPage","openDetails","useAssetDetailsParam","canCreate","canUpdate","useMediaLibraryPermissions","currentFolderId","navigateToFolderId","navigateToRoot","useFolderNavigation","currentFolderError","useGetFolderQuery","skip","name","title","itemCount","useFolderInfo","isSearching","clearSearch","useAssetSearch","listSort","useListSort","listFilters","useListFilters","builtFilters","buildAssetFilters","filters","Date","serialized","subscribers","assetPageSubscribers","pagination","assetsError","useInfiniteAssets","folder","search","undefined","fileClauses","enabled","showFiles","data","fetchedFolders","useGetFoldersQuery","parentId","foldersSort","folderClauses","showFolders","itemLocations","buildItemLocations","itemCountLabel","count","searchResultsTitle","query","total","searchResultsCountLabel","pageHeaderTitle","isCreateFolderDialogOpen","setIsCreateFolderDialogOpen","useState","setView","usePersistentState","localStorageKeys","isUrlDialogOpen","setIsUrlDialogOpen","fileInputRef","useRef","uploadDropZoneRef","isHeaderCompact","setIsHeaderCompact","onHeaderSentinelVisibility","useCallback","isVisible","headerSentinelRef","useElementOnScreen","uploadFiles","useUploadFilesMutation","uploadFromUrls","useUploadFromUrlsMutation","settings","useGetUploadSettingsQuery","concurrency","concurrentUploadRequests","isAiMetadataEnabled","useAIMetadataEnabled","trackUsage","useTracking","uploadFilesToFolder","files","folderId","assetsCountByType","reduce","acc","file","type","typeFromMime","location","MEDIA_LIBRARY_LOCATION","formData","FormData","fileInfoArray","forEach","append","push","caption","alternativeText","JSON","stringify","totalFiles","generateAiMetadata","Boolean","unwrap","handleFileSelect","current","click","handleFileChange","e","target","source","Array","from","value","handleDrop","handleUrlUpload","urls","getListQueryKey","filter","UploadDropZoneProvider","onDrop","disabled","AssetSelectionProvider","BusyAssetsProvider","AssetsDndProvider","Layouts","sideNav","FolderTree","showActiveFolder","onSelectFolder","Page","Main","VisuallyHidden","input","onChange","multiple","aria-hidden","variant","tag","SimpleMenu","popoverPlacement","endIcon","ChevronDown","label","MenuItem","onSelect","startIcon","FolderIcon","Files","Link","FilterMenu","AssetsSearchInput","SortMenu","showFoldersGroup","onValueChange","TABLE","aria-label","List","GridIcon","FilterBadges","compact","Content","BetaNotice","DropZoneWithOverlay","DropFilesMessage","folderName","clearFilters","FolderFormDialog","open","mode","parentFolderName","parentFolderId","onClose","ImportFromUrlDialog","onUpload","AssetDetailsDrawer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AssetsPage.mjs","sources":["../../../../../admin/src/future/pages/Assets/AssetsPage.tsx"],"sourcesContent":["import { useRef, useCallback, useMemo, useState, useEffect, type ChangeEvent } from 'react';\n\nimport * as ToggleGroup from '@radix-ui/react-toggle-group';\nimport { Layouts, Page, useElementOnScreen, usePersistentState } from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Flex,\n Loader,\n MenuItem,\n SimpleMenu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport {\n ChevronDown,\n Files,\n Folder as FolderIcon,\n GridFour as GridIcon,\n Link,\n List,\n} from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled, css } from 'styled-components';\n\nimport { typeFromMime } from '../../../utils/typeFromMime';\nimport { useAIMetadataEnabled } from '../../hooks/useAIMetadataEnabled';\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../hooks/useTracking';\nimport { useUploadFromUrlsMutation, useUploadFilesMutation } from '../../services/api';\nimport { useGetFolderQuery, useGetFoldersQuery } from '../../services/folders';\nimport { useGetUploadSettingsQuery } from '../../services/settings';\nimport { buildItemLocations, type ItemLocations } from '../../utils/itemLocations';\nimport { getTranslationKey } from '../../utils/translations';\n\nimport {\n AssetDetailsDrawer,\n useAssetDetailsParam,\n} from './components/AssetDetails/AssetDetailsDrawer';\nimport { AssetsGrid } from './components/AssetsGrid';\nimport { AssetsSearchInput } from './components/AssetsSearchInput';\nimport { AssetsTable } from './components/AssetsTable';\nimport { BulkActionsBar } from './components/BulkActionsBar';\nimport { AssetsDndProvider } from './components/Dnd/AssetsDndProvider';\nimport { DropFilesMessage, DropZoneWithOverlay } from './components/DropZone/UploadDropZone';\nimport { UploadDropZoneProvider } from './components/DropZone/UploadDropZoneContext';\nimport { EmptyState, FilteredEmptyState } from './components/EmptyState';\nimport { FilterBadges } from './components/FilterBadges';\nimport { FilterMenu } from './components/FilterMenu';\nimport { FolderFormDialog } from './components/FolderFormDialog';\nimport { FolderTree } from './components/FolderTree/FolderTree';\nimport { ImportFromUrlDialog } from './components/ImportFromUrlDialog';\nimport { MainAreaContextMenu } from './components/MainAreaContextMenu';\nimport { SortMenu } from './components/SortMenu';\nimport { localStorageKeys, viewOptions } from './constants';\nimport { useAssetSearch } from './hooks/useAssetSearch';\nimport { AssetSelectionProvider, useAssetSelection } from './hooks/useAssetSelection';\nimport { BusyAssetsProvider } from './hooks/useBusyAssets';\nimport { useFolderInfo } from './hooks/useFolderInfo';\nimport { useFolderNavigation } from './hooks/useFolderNavigation';\nimport { useInfiniteAssets } from './hooks/useInfiniteAssets';\nimport { useInfiniteScrollSentinel } from './hooks/useInfiniteScrollSentinel';\nimport { useListFilters } from './hooks/useListFilters';\nimport { useListScrollRestoration } from './hooks/useListScrollRestoration';\nimport { useListSort, type FoldersPosition } from './hooks/useListSort';\nimport { buildAssetFilters } from './utils/buildAssetFilters';\nimport { getListQueryKey } from './utils/listQueryKey';\nimport { mergeMixedList } from './utils/mergeMixedList';\nimport { buildRenderedKeys } from './utils/renderedKeys';\n\nimport type { File, UploadFileInfo } from '../../../../../shared/contracts/files';\nimport type { Folder } from '../../../../../shared/contracts/folders';\n\n// The negative bottom margin shrinks the trigger area by a pixel so the 1px\n// sentinel sitting exactly at the fold (when a page's rows happen to fill the\n// viewport) reads as \"not visible\" and doesn't pull an extra page. It still\n// triggers as soon as the sentinel scrolls a hair into view. Tune the bottom\n// value if the list over- or under-fetches near the fold.\nconst INTERSECTION_OPTIONS: IntersectionObserverInit = {\n threshold: 0,\n rootMargin: '0px 0px -1px 0px',\n};\n\n// Module-level so the header sentinel's observer isn't rebuilt every render.\nconst HEADER_SENTINEL_OPTIONS: IntersectionObserverInit = { threshold: 0 };\n\nconst ITEM_COUNT_MESSAGE = {\n id: getTranslationKey('header.content.item-count'),\n defaultMessage: '{count, plural, =1 {# item} other {# items}}',\n};\n\nconst SEARCH_RESULTS_COUNT_MESSAGES = {\n both: {\n id: getTranslationKey('header.search-results.count'),\n defaultMessage:\n '{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 asset} other {# assets}}',\n },\n folders: {\n id: getTranslationKey('header.search-results.count.folders'),\n defaultMessage: '{numberFolders, plural, one {1 folder} other {# folders}}',\n },\n assets: {\n id: getTranslationKey('header.search-results.count.assets'),\n defaultMessage: '{numberAssets, plural, =0 {0 assets} one {1 asset} other {# assets}}',\n },\n};\n\nconst getSearchResultsCountMessage = (numberFolders: number, numberAssets: number) => {\n if (numberFolders === 0) {\n return SEARCH_RESULTS_COUNT_MESSAGES.assets;\n }\n\n if (numberAssets === 0) {\n return SEARCH_RESULTS_COUNT_MESSAGES.folders;\n }\n\n return SEARCH_RESULTS_COUNT_MESSAGES.both;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsView\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsViewProps {\n view: number;\n folders: Folder[];\n isLoadingFolders: boolean;\n assets: File[];\n isLoadingAssets: boolean;\n isFetchingMore: boolean;\n hasNextPage: boolean;\n fetchNextPage: () => void;\n error: unknown;\n locations: ItemLocations;\n searchQuery: string;\n assetsSort: string;\n foldersPosition: FoldersPosition;\n hasActiveFilters: boolean;\n onClearFilters: () => void;\n onAssetItemClick: (assetId: number) => void;\n onAddAssets: () => void;\n canAddAssets: boolean;\n onClearSearch: () => void;\n}\n\nconst AssetsView = ({\n view,\n folders,\n isLoadingFolders,\n assets,\n isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n error,\n locations,\n searchQuery,\n assetsSort,\n foldersPosition,\n hasActiveFilters,\n onClearFilters,\n onAssetItemClick,\n onAddAssets,\n canAddAssets,\n onClearSearch,\n}: AssetsViewProps) => {\n const { formatMessage } = useIntl();\n\n const isGridView = view === viewOptions.GRID;\n const isLoading = isLoadingAssets || isLoadingFolders;\n\n // \"Folders: Mixed with files\" — interleave the complete folder list into the\n // loaded asset stream client-side, following the active sort. Table view\n // only: the grid always keeps folders in their own band on top.\n const mixedItems = useMemo(\n () =>\n foldersPosition === 'mixed' && !isGridView\n ? mergeMixedList({ folders, assets, sort: assetsSort, hasNextPage })\n : null,\n [foldersPosition, isGridView, folders, assets, assetsSort, hasNextPage]\n );\n\n // Derived once here so the table, the grid and the bulk bar all agree on what\n // is on screen — in mixed mode that is not simply every folder.\n const renderedKeys = buildRenderedKeys({ folders, assets, mixedItems });\n\n const loadMoreRef = useInfiniteScrollSentinel({\n hasNextPage,\n isFetchingMore,\n onLoadMore: fetchNextPage,\n options: INTERSECTION_OPTIONS,\n });\n\n if (isLoading) {\n return (\n <Flex justifyContent=\"center\" padding={8}>\n <Loader>{formatMessage({ id: 'app.loading', defaultMessage: 'Loading...' })}</Loader>\n </Flex>\n );\n }\n\n if (error) {\n return (\n <Box padding={8}>\n <Typography textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('list.assets.error'),\n defaultMessage: 'An error occurred while fetching assets.',\n })}\n </Typography>\n </Box>\n );\n }\n\n if (folders.length === 0 && assets.length === 0) {\n // While searching, the search empty state wins (it names the query); a\n // filter-only dead end gets the filtered variant with its Clear action.\n return hasActiveFilters && !searchQuery ? (\n <FilteredEmptyState onClearFilters={onClearFilters} />\n ) : (\n <EmptyState\n onAddAssets={onAddAssets}\n canAddAssets={canAddAssets}\n searchQuery={searchQuery}\n onClearSearch={onClearSearch}\n />\n );\n }\n return (\n <>\n {isGridView ? (\n <AssetsGrid\n folders={folders}\n assets={assets}\n renderedKeys={renderedKeys}\n onAssetItemClick={onAssetItemClick}\n />\n ) : (\n <AssetsTable\n assets={assets}\n folders={folders}\n mixedItems={mixedItems}\n renderedKeys={renderedKeys}\n onAssetItemClick={onAssetItemClick}\n />\n )}\n <div ref={loadMoreRef} style={{ height: 1 }} />\n {isFetchingMore && (\n <Flex justifyContent=\"center\" padding={4}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('list.assets.loading-more'),\n defaultMessage: 'Loading more assets...',\n })}\n </Loader>\n </Flex>\n )}\n {/* Lives here rather than in `AssetsPage` so it can read the loaded\n assets: the AI metadata action needs their mime types to know what\n the provider can handle. `position: fixed` keeps it visually anchored\n regardless of where it sits in the tree. */}\n <BulkActionsBar assets={assets} renderedKeys={renderedKeys} locations={locations} />\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ClearSelectionOnChange\n *\n * Selection is list-scoped: it resets when the user is looking at a different list.\n * The list fingerprint is getListQueryKey() — folder, search, sort, filter.\n *\n * Hybrid rule: infinite scroll does not change the key (selection persists), and\n * neither does the table/grid toggle — both views render the same list.\n * Search/sort/filter changes do (selection clears) — same mental model as folder nav.\n * -----------------------------------------------------------------------------------------------*/\n\ninterface ClearSelectionOnChangeProps {\n listQueryKey: string;\n}\n\nconst ClearSelectionOnChange = ({ listQueryKey }: ClearSelectionOnChangeProps) => {\n const { clear } = useAssetSelection();\n\n useEffect(() => {\n clear();\n }, [listQueryKey, clear]);\n\n return null;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsPage\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * Mirrors the design-system Toggle look (grey track, white active segment\n * card) — reproduced locally because the DS component is a labels-only\n * boolean input (no icons) and paints its left segment in danger red. Here\n * both segments use the primary blue when active.\n */\nconst StyledToggleGroup = styled(ToggleGroup.Root)`\n display: flex;\n padding: ${({ theme }) => theme.spaces[1]};\n background: ${({ theme }) => theme.colors.neutral100};\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n`;\n\nconst StyledToggleItem = styled(ToggleGroup.Item)`\n display: flex;\n flex: 1 1 50%;\n align-items: center;\n justify-content: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: 0.6rem ${({ theme }) => theme.spaces[3]};\n border: 1px solid transparent;\n border-radius: ${({ theme }) => theme.borderRadius};\n background: transparent;\n color: ${({ theme }) => theme.colors.neutral600};\n cursor: pointer;\n font-size: ${({ theme }) => theme.fontSizes[1]};\n font-weight: ${({ theme }) => theme.fontWeights.semiBold};\n white-space: nowrap;\n\n &:hover {\n color: ${({ theme }) => theme.colors.neutral700};\n }\n\n &[data-state='on'] {\n background: ${({ theme }) => theme.colors.neutral0};\n border-color: ${({ theme }) => theme.colors.neutral200};\n color: ${({ theme }) => theme.colors.primary600};\n }\n\n svg {\n width: 1.6rem;\n height: 1.6rem;\n }\n`;\n\n// A single sticky header — same layout scrolled or not, so the toolbar\n// alignment can't reflow the way the shared sticky header did. Once the list\n// scrolls under it, it shrinks (reduced vertical padding + a shadow to lift it\n// off the rows), like the sticky headers elsewhere in the admin. Horizontal\n// padding stays responsive (passed as props); only the vertical rhythm + shadow\n// change here so they can animate.\nconst StickyHeader = styled(Box)<{ $compact: boolean }>`\n position: sticky;\n top: 0;\n z-index: 2;\n /* Transparent at rest (the grey page shows through); an opaque background +\n shadow appear only once it sticks and content scrolls under it. */\n background: transparent;\n /* Horizontal padding matches the list's default spacing (Layouts.Content /\n RESPONSIVE_DEFAULT_SPACING: 4 / 6 / 10) so the header lines up with the rows. */\n padding: ${({ theme }) => `${theme.spaces[6]} ${theme.spaces[4]}`};\n transition:\n padding 0.2s ease,\n background 0.2s ease,\n box-shadow 0.2s ease;\n\n ${({ theme }) => theme.breakpoints.medium} {\n padding-left: ${({ theme }) => theme.spaces[6]};\n padding-right: ${({ theme }) => theme.spaces[6]};\n }\n ${({ theme }) => theme.breakpoints.large} {\n padding-left: ${({ theme }) => theme.spaces[10]};\n padding-right: ${({ theme }) => theme.spaces[10]};\n }\n\n /* Compacting is scoped to medium and up, where the header actually sticks. On\n mobile it scrolls away with the list, so shrinking it mid-scroll animated a\n header the user could no longer see — the transition read as a glitch on the\n way back up rather than as the header settling. */\n ${({ $compact, theme }) =>\n $compact &&\n css`\n ${theme.breakpoints.medium} {\n padding-top: ${theme.spaces[3]};\n padding-bottom: ${theme.spaces[3]};\n padding-left: ${theme.spaces[4]};\n padding-right: ${theme.spaces[4]};\n background: ${theme.colors.neutral0};\n box-shadow: ${theme.shadows.tableShadow};\n }\n ${theme.breakpoints.large} {\n padding-left: ${theme.spaces[6]};\n padding-right: ${theme.spaces[6]};\n }\n `}\n`;\n\n// New button aligns with the title, not the toolbar.\nconst TitleRow = styled(Flex)`\n justify-content: space-between;\n align-items: flex-start;\n gap: ${({ theme }) => theme.spaces[4]};\n\n h1 {\n font-size: 1.8rem;\n }\n`;\n\n// Two groups in source order (Filter, Search / Sort, Toggle). Mobile: stacked —\n// Filter+Search on row 1, Sort+Toggle on row 2. Desktop (large+): one row,\n// Filter+Search on the left, Sort+Toggle pushed right.\nconst Toolbar = styled(Flex)<{ $compact: boolean }>`\n margin-top: ${({ theme }) => theme.spaces[5]};\n flex-direction: column;\n align-items: stretch;\n gap: ${({ theme }) => theme.spaces[3]};\n transition: margin-top 0.2s ease;\n\n /* Tightening the gap to the title belongs to the compact header, so it is\n scoped to the breakpoints that compact. On mobile the header never sticks,\n and this was the last thing still shifting as the page scrolled. */\n ${({ $compact, theme }) =>\n $compact &&\n css`\n ${theme.breakpoints.medium} {\n margin-top: ${theme.spaces[2]};\n }\n `}\n\n ${({ theme }) => theme.breakpoints.large} {\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n }\n`;\n\nconst ToolbarGroup = styled(Flex)`\n align-items: center;\n gap: ${({ theme }) => theme.spaces[3]};\n`;\n\n// Filter + Search. On mobile the group fills the row (search grows into it);\n// on desktop it keeps its intrinsic size and sits at the left edge.\nconst FilterSearchGroup = styled(ToolbarGroup)``;\n\n// Sort + Toggle. Mobile: spread across the row (Sort left, Toggle right).\n// Desktop: sit together at the right edge (space-between on the toolbar leaves\n// the empty space between the search and here).\nconst SortToggleGroup = styled(ToolbarGroup)`\n justify-content: space-between;\n\n ${({ theme }) => theme.breakpoints.large} {\n justify-content: flex-end;\n flex: 0 0 auto;\n }\n`;\n\n// Fills the row on mobile; intrinsic width on desktop.\nconst SearchSlot = styled(Box)`\n flex: 1;\n\n ${({ theme }) => theme.breakpoints.large} {\n flex: 0 1 auto;\n }\n`;\n\n// Toggle labels are hidden below desktop — icons only (buttons keep aria-label).\nconst ToggleLabel = styled.span`\n display: none;\n\n ${({ theme }) => theme.breakpoints.large} {\n display: inline;\n }\n`;\n\nexport const AssetsPage = () => {\n const { formatMessage } = useIntl();\n const { openDetails } = useAssetDetailsParam();\n const { canCreate, canUpdate } = useMediaLibraryPermissions();\n\n const { currentFolderId, navigateToFolderId, navigateToRoot } = useFolderNavigation();\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 const { title, itemCount } = useFolderInfo(currentFolderId);\n\n const { searchQuery, isSearching, clearSearch } = useAssetSearch();\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: assetPageSubscribers,\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 // Both move affordances (drag and the bulk bar) resolve each item's parent\n // from the rows on screen — while searching, results are global and the\n // folder currently open says nothing about where an item lives.\n const itemLocations = useMemo(() => buildItemLocations(assets, folders), [assets, folders]);\n\n const itemCountLabel = formatMessage(ITEM_COUNT_MESSAGE, { count: itemCount });\n\n const searchResultsTitle = formatMessage(\n {\n id: getTranslationKey('header.search-results'),\n defaultMessage: 'Search results for \"{query}\"',\n },\n { query: searchQuery }\n );\n const numberFolders = folders.length;\n const numberAssets = pagination?.total ?? 0;\n\n const searchResultsCountLabel = formatMessage(\n getSearchResultsCountMessage(numberFolders, numberAssets),\n { numberFolders, numberAssets }\n );\n\n let pageHeaderTitle: string;\n if (isSearching) {\n pageHeaderTitle = `${searchResultsTitle} (${searchResultsCountLabel})`;\n } else if (title) {\n pageHeaderTitle = `${title} (${itemCountLabel})`;\n } else {\n pageHeaderTitle = formatMessage({ id: 'app.loading', defaultMessage: 'Loading...' });\n }\n\n const [isCreateFolderDialogOpen, setIsCreateFolderDialogOpen] = useState(false);\n\n // View state\n const [view, setView] = usePersistentState(localStorageKeys.view, viewOptions.GRID);\n const isGridView = view === viewOptions.GRID;\n\n // Dialog state\n const [isUrlDialogOpen, setIsUrlDialogOpen] = useState(false);\n\n // Refs\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadDropZoneRef = useRef<HTMLDivElement>(null);\n\n // Shrink the sticky header once the list scrolls beneath it. A zero-height\n // sentinel sits at the very top of the scroll content; when it leaves the\n // viewport we're scrolled → compact.\n const [isHeaderCompact, setIsHeaderCompact] = useState(false);\n const onHeaderSentinelVisibility = useCallback(\n (isVisible: boolean) => setIsHeaderCompact(!isVisible),\n []\n );\n const headerSentinelRef = useElementOnScreen<HTMLDivElement>(\n onHeaderSentinelVisibility,\n HEADER_SENTINEL_OPTIONS\n );\n\n // Upload handlers\n const [uploadFiles] = useUploadFilesMutation();\n const [uploadFromUrls] = useUploadFromUrlsMutation();\n // `concurrentUploadRequests` echoes the app config. Missing settings (still\n // loading, no permission) fall back to sequential — never faster than the\n // server asked for.\n const { data: settings } = useGetUploadSettingsQuery();\n const concurrency = settings?.data?.concurrentUploadRequests ?? 1;\n // Drives the post-upload AI metadata phase shown per row in the progress\n // dialog. No mime argument: the files are not known until they are picked,\n // and the server filters the batch on the same allowlist anyway.\n const isAiMetadataEnabled = useAIMetadataEnabled();\n const { trackUsage } = useTracking();\n\n const uploadFilesToFolder = async (files: globalThis.File[], folderId: number | null) => {\n if (files.length === 0) return;\n\n // Mirror the legacy `willAddMediaLibraryAssets` payload: the count of files\n // about to upload, broken down by asset type.\n const assetsCountByType = files.reduce<Record<string, number>>((acc, file) => {\n const type = typeFromMime(file.type);\n acc[type] = (acc[type] ?? 0) + 1;\n return acc;\n }, {});\n trackUsage('willAddMediaLibraryAssets', {\n location: MEDIA_LIBRARY_LOCATION,\n ...assetsCountByType,\n });\n\n const formData = new FormData();\n const fileInfoArray: UploadFileInfo[] = [];\n\n files.forEach((file) => {\n formData.append('files', file);\n fileInfoArray.push({\n name: file.name,\n caption: null,\n alternativeText: null,\n folder: folderId,\n });\n });\n\n formData.append('fileInfo', JSON.stringify(fileInfoArray));\n try {\n await uploadFiles({\n formData,\n totalFiles: files.length,\n concurrency,\n generateAiMetadata: Boolean(isAiMetadataEnabled),\n }).unwrap();\n } catch {\n // Error is already dispatched to store from the API queryFn\n }\n };\n\n const handleFileSelect = () => {\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (files && files.length > 0) {\n trackUsage('didSelectFile', { source: 'computer', location: MEDIA_LIBRARY_LOCATION });\n await uploadFilesToFolder(Array.from(files), currentFolderId);\n }\n e.target.value = '';\n };\n\n const handleDrop = async (files: globalThis.File[]) => {\n // Defence in depth: the provider is `disabled` without `assets.create`\n // (so onDrop won't fire), but guard here too in case it's ever wired live.\n if (!canCreate) return;\n trackUsage('didSelectFile', { source: 'computer', location: MEDIA_LIBRARY_LOCATION });\n await uploadFilesToFolder(files, currentFolderId);\n };\n\n const handleUrlUpload = async (urls: string[]) => {\n trackUsage('didSelectFile', { source: 'url', location: MEDIA_LIBRARY_LOCATION });\n // Counts-by-type aren't available client-side for the URL flow (the server\n // fetches the files), so this fires the event with location only.\n trackUsage('willAddMediaLibraryAssets', { location: MEDIA_LIBRARY_LOCATION });\n try {\n await uploadFromUrls({\n urls,\n folderId: currentFolderId,\n generateAiMetadata: Boolean(isAiMetadataEnabled),\n }).unwrap();\n } catch {\n // Error is already dispatched to store from the API queryFn\n }\n };\n\n // The view is deliberately absent: table and grid render the same list, so\n // toggling views keeps the selection.\n const listQueryKey = getListQueryKey({\n folderId: currentFolderId,\n search: searchQuery,\n // Folder position changes the render order too — selection must reset.\n sort: `${listSort.assetsSort};folders=${listSort.foldersPosition}`,\n filter: listFilters.serialized || null,\n });\n\n const scrollAnchorRef = useListScrollRestoration(listQueryKey);\n\n return (\n <>\n <UploadDropZoneProvider onDrop={handleDrop} disabled={!canCreate}>\n <AssetSelectionProvider disabled={!canUpdate}>\n <BusyAssetsProvider>\n <AssetsDndProvider locations={itemLocations}>\n <ClearSelectionOnChange listQueryKey={listQueryKey} />\n <Layouts.Root\n sideNav={\n <FolderTree\n currentFolderId={currentFolderId}\n showActiveFolder={!isSearching}\n onSelectFolder={navigateToFolderId}\n />\n }\n >\n <Page.Main>\n <Box ref={uploadDropZoneRef}>\n <VisuallyHidden>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} multiple />\n </VisuallyHidden>\n\n {/* Zero-height marker: leaves the viewport as soon as the list\n scrolls, flipping the header into its compact state. */}\n <Box ref={headerSentinelRef} height={0} aria-hidden />\n <Box ref={scrollAnchorRef} height={0} aria-hidden />\n\n {/* Renders no wrapper: it listens on the scrolling column\n itself, so the header band and the padding below the list\n are both in the hit area. Interactive controls, the table\n header row and the list items are excluded — see\n MainAreaContextMenu. */}\n <MainAreaContextMenu\n disabled={!canCreate}\n onCreateFolder={() => setIsCreateFolderDialogOpen(true)}\n onImportFiles={handleFileSelect}\n onImportFromUrl={() => setIsUrlDialogOpen(true)}\n />\n <StickyHeader $compact={isHeaderCompact}>\n <TitleRow>\n <Typography variant=\"alpha\" tag=\"h1\">\n {pageHeaderTitle}\n </Typography>\n {canCreate && (\n <SimpleMenu\n popoverPlacement=\"bottom-end\"\n variant=\"default\"\n endIcon={<ChevronDown />}\n label={formatMessage({\n id: getTranslationKey('new'),\n defaultMessage: 'New',\n })}\n >\n <MenuItem\n onSelect={() => setIsCreateFolderDialogOpen(true)}\n startIcon={<FolderIcon />}\n >\n {formatMessage({\n id: getTranslationKey('folder.create.title'),\n defaultMessage: 'New folder',\n })}\n </MenuItem>\n <MenuItem onSelect={handleFileSelect} startIcon={<Files />}>\n {formatMessage({\n id: getTranslationKey('import-files'),\n defaultMessage: 'File upload',\n })}\n </MenuItem>\n <MenuItem\n onSelect={() => setIsUrlDialogOpen(true)}\n startIcon={<Link />}\n >\n {formatMessage({\n id: getTranslationKey('import-from-url'),\n defaultMessage: 'File upload from URL',\n })}\n </MenuItem>\n </SimpleMenu>\n )}\n </TitleRow>\n\n <Toolbar $compact={isHeaderCompact}>\n <FilterSearchGroup>\n <Box>\n <FilterMenu listFilters={listFilters} />\n </Box>\n <SearchSlot>\n <AssetsSearchInput />\n </SearchSlot>\n </FilterSearchGroup>\n <SortToggleGroup>\n <Box>\n <SortMenu sort={listSort} showFoldersGroup={!isGridView} />\n </Box>\n <StyledToggleGroup\n type=\"single\"\n value={isGridView ? 'grid' : 'table'}\n onValueChange={(value) =>\n value &&\n setView(value === 'grid' ? viewOptions.GRID : viewOptions.TABLE)\n }\n aria-label={formatMessage({\n id: getTranslationKey('view.switch.label'),\n defaultMessage: 'View options',\n })}\n >\n <StyledToggleItem\n value=\"table\"\n aria-label={formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\n >\n <List />\n <ToggleLabel>\n {formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\n </ToggleLabel>\n </StyledToggleItem>\n <StyledToggleItem\n value=\"grid\"\n aria-label={formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n >\n <GridIcon />\n <ToggleLabel>\n {formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n </ToggleLabel>\n </StyledToggleItem>\n </StyledToggleGroup>\n </SortToggleGroup>\n </Toolbar>\n\n <FilterBadges listFilters={listFilters} compact={isHeaderCompact} />\n </StickyHeader>\n\n <Layouts.Content>\n {/* Renders nothing — keeps every loaded page's query subscribed\n so a rename/delete refreshes the whole list. */}\n {assetPageSubscribers}\n <DropZoneWithOverlay>\n <DropFilesMessage\n uploadDropZoneRef={uploadDropZoneRef}\n folderName={title}\n />\n <AssetsView\n view={view}\n folders={folders}\n isLoadingFolders={isLoadingFolders}\n assets={assets}\n isLoadingAssets={isLoadingAssets}\n isFetchingMore={isFetchingMore}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n error={assetsError}\n locations={itemLocations}\n searchQuery={searchQuery}\n assetsSort={listSort.assetsSort}\n foldersPosition={listSort.foldersPosition}\n hasActiveFilters={listFilters.filters.length > 0}\n onClearFilters={listFilters.clearFilters}\n onAssetItemClick={openDetails}\n onAddAssets={handleFileSelect}\n canAddAssets={canCreate}\n onClearSearch={clearSearch}\n />\n </DropZoneWithOverlay>\n </Layouts.Content>\n </Box>\n </Page.Main>\n </Layouts.Root>\n </AssetsDndProvider>\n </BusyAssetsProvider>\n </AssetSelectionProvider>\n </UploadDropZoneProvider>\n <FolderFormDialog\n open={isCreateFolderDialogOpen}\n mode=\"create\"\n parentFolderName={title}\n parentFolderId={currentFolderId}\n onClose={() => setIsCreateFolderDialogOpen(false)}\n />\n <ImportFromUrlDialog\n open={isUrlDialogOpen}\n onClose={() => setIsUrlDialogOpen(false)}\n onUpload={handleUrlUpload}\n />\n <AssetDetailsDrawer />\n </>\n );\n};\n"],"names":["INTERSECTION_OPTIONS","threshold","rootMargin","HEADER_SENTINEL_OPTIONS","ITEM_COUNT_MESSAGE","id","getTranslationKey","defaultMessage","SEARCH_RESULTS_COUNT_MESSAGES","both","folders","assets","getSearchResultsCountMessage","numberFolders","numberAssets","AssetsView","view","isLoadingFolders","isLoadingAssets","isFetchingMore","hasNextPage","fetchNextPage","error","locations","searchQuery","assetsSort","foldersPosition","hasActiveFilters","onClearFilters","onAssetItemClick","onAddAssets","canAddAssets","onClearSearch","formatMessage","useIntl","isGridView","viewOptions","GRID","isLoading","mixedItems","useMemo","mergeMixedList","sort","renderedKeys","buildRenderedKeys","loadMoreRef","useInfiniteScrollSentinel","onLoadMore","options","_jsx","Flex","justifyContent","padding","Loader","Box","Typography","textColor","length","FilteredEmptyState","EmptyState","_jsxs","_Fragment","AssetsGrid","AssetsTable","div","ref","style","height","BulkActionsBar","ClearSelectionOnChange","listQueryKey","clear","useAssetSelection","useEffect","StyledToggleGroup","styled","ToggleGroup","Root","theme","spaces","colors","neutral100","neutral200","borderRadius","StyledToggleItem","Item","neutral600","fontSizes","fontWeights","semiBold","neutral700","neutral0","primary600","StickyHeader","breakpoints","medium","large","$compact","css","shadows","tableShadow","TitleRow","Toolbar","ToolbarGroup","FilterSearchGroup","SortToggleGroup","SearchSlot","ToggleLabel","span","AssetsPage","openDetails","useAssetDetailsParam","canCreate","canUpdate","useMediaLibraryPermissions","currentFolderId","navigateToFolderId","navigateToRoot","useFolderNavigation","currentFolderError","useGetFolderQuery","skip","name","title","itemCount","useFolderInfo","isSearching","clearSearch","useAssetSearch","listSort","useListSort","listFilters","useListFilters","builtFilters","buildAssetFilters","filters","Date","serialized","subscribers","assetPageSubscribers","pagination","assetsError","useInfiniteAssets","folder","search","undefined","fileClauses","enabled","showFiles","data","fetchedFolders","useGetFoldersQuery","parentId","foldersSort","folderClauses","showFolders","itemLocations","buildItemLocations","itemCountLabel","count","searchResultsTitle","query","total","searchResultsCountLabel","pageHeaderTitle","isCreateFolderDialogOpen","setIsCreateFolderDialogOpen","useState","setView","usePersistentState","localStorageKeys","isUrlDialogOpen","setIsUrlDialogOpen","fileInputRef","useRef","uploadDropZoneRef","isHeaderCompact","setIsHeaderCompact","onHeaderSentinelVisibility","useCallback","isVisible","headerSentinelRef","useElementOnScreen","uploadFiles","useUploadFilesMutation","uploadFromUrls","useUploadFromUrlsMutation","settings","useGetUploadSettingsQuery","concurrency","concurrentUploadRequests","isAiMetadataEnabled","useAIMetadataEnabled","trackUsage","useTracking","uploadFilesToFolder","files","folderId","assetsCountByType","reduce","acc","file","type","typeFromMime","location","MEDIA_LIBRARY_LOCATION","formData","FormData","fileInfoArray","forEach","append","push","caption","alternativeText","JSON","stringify","totalFiles","generateAiMetadata","Boolean","unwrap","handleFileSelect","current","click","handleFileChange","e","target","source","Array","from","value","handleDrop","handleUrlUpload","urls","getListQueryKey","filter","scrollAnchorRef","useListScrollRestoration","UploadDropZoneProvider","onDrop","disabled","AssetSelectionProvider","BusyAssetsProvider","AssetsDndProvider","Layouts","sideNav","FolderTree","showActiveFolder","onSelectFolder","Page","Main","VisuallyHidden","input","onChange","multiple","aria-hidden","MainAreaContextMenu","onCreateFolder","onImportFiles","onImportFromUrl","variant","tag","SimpleMenu","popoverPlacement","endIcon","ChevronDown","label","MenuItem","onSelect","startIcon","FolderIcon","Files","Link","FilterMenu","AssetsSearchInput","SortMenu","showFoldersGroup","onValueChange","TABLE","aria-label","List","GridIcon","FilterBadges","compact","Content","DropZoneWithOverlay","DropFilesMessage","folderName","clearFilters","FolderFormDialog","open","mode","parentFolderName","parentFolderId","onClose","ImportFromUrlDialog","onUpload","AssetDetailsDrawer"],"mappings":"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"}
|
|
@@ -168,6 +168,11 @@ var DeleteItemsDialog = require('./DeleteItemsDialog.js');
|
|
|
168
168
|
children: /*#__PURE__*/ jsxRuntime.jsx("input", {
|
|
169
169
|
ref: fileInputRef,
|
|
170
170
|
type: "file",
|
|
171
|
+
// Replacing swaps the bytes of an existing asset, so the picker offers
|
|
172
|
+
// only its own type. Without this the picker accepted anything and a
|
|
173
|
+
// JPG could come back as PNG bytes still served under a `.jpg` url,
|
|
174
|
+
// since replace preserves hash and ext by design.
|
|
175
|
+
accept: asset.mime ?? '',
|
|
171
176
|
multiple: false,
|
|
172
177
|
onChange: handleFileChange,
|
|
173
178
|
"aria-hidden": true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetActionsMenu.js","sources":["../../../../../../admin/src/future/pages/Assets/components/AssetActionsMenu.tsx"],"sourcesContent":["import { useMemo, useRef, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Dialog,\n Flex,\n IconButton,\n Menu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { ArrowRight, ArrowsCounterClockwise, Download, Link, More, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useAIMetadataEnabled } from '../../../hooks/useAIMetadataEnabled';\nimport { useApiErrorMessage } from '../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport { useReplaceAssetMutation } from '../../../services/assets';\nimport { downloadFile } from '../../../utils/downloadFile';\nimport { prefixFileUrlWithBackendUrl } from '../../../utils/files';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { useBusyAssetsOptional } from '../hooks/useBusyAssets';\nimport { assetKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\n\nimport type { File } from '../../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetActionsMenuProps {\n asset: File;\n /** Drag data for this asset, so the move dialog validates against its real folder. */\n dragData: DragFileData;\n}\n\n/**\n * The \"...\" menu on an asset row/card. Always acts on that one asset, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance) — the file mirror of `FolderActionsMenu`.\n *\n * Replace / copy link / download duplicate what the details drawer offers as\n * icon buttons, so the same action is one click away without opening the asset\n * first. They are re-implemented rather than lifted out of the drawer: the\n * drawer versions render as `IconButton`s and report through its in-drawer toast\n * slot, neither of which fits a menu item on a row.\n *\n * A successful move or delete deselects this one asset and leaves the rest of\n * the selection intact: the mutations only invalidate RTK tags, so without it an\n * `asset:<id>` key for a file that has been deleted — or has moved out of this\n * list — would linger. The other selected rows are untouched, which is the whole\n * point of the menu being a single-item affordance.\n */\nexport const AssetActionsMenu = ({ asset, dragData }: AssetActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n // Absent in the asset picker and in unit tests: the replace still runs, it\n // just renders no row-level overlay.\n const markBusy = useBusyAssetsOptional()?.markBusy ?? (() => () => {});\n const {\n canUpdate,\n canDownload,\n canCopyLink,\n isLoading: isLoadingPermissions,\n } = useMediaLibraryPermissions();\n const [replaceAsset, { isLoading: isReplacing }] = useReplaceAssetMutation();\n const aiEnabled = useAIMetadataEnabled({ mime: asset.mime });\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isReplaceOpen, setIsReplaceOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Confirm first, then open the native picker, so the user only commits to\n // replacing after acknowledging the warning (same order as the drawer).\n const handleReplaceContinue = () => {\n setIsReplaceOpen(false);\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n // Reset the native input so the same file can be picked again later.\n event.target.value = '';\n\n if (!file) {\n return;\n }\n\n // The menu has closed by the time the picker returns, so `isReplacing` has\n // nothing left to disable and the row would otherwise sit inert for the\n // whole upload. Marking the asset busy puts the same overlay the drawer\n // uses on the row/card, cleared when the mutation settles either way.\n const releaseBusy = markBusy(\n asset.id,\n formatMessage({\n id: getTranslationKey('asset-details.replace.loading'),\n defaultMessage: 'Replacing the file…',\n })\n );\n\n let res;\n try {\n res = await replaceAsset({ id: asset.id, file, fileInfo: { name: asset.name } });\n } finally {\n releaseBusy();\n }\n\n if ('error' in res) {\n toggleNotification({\n type: 'danger',\n message: getErrorMessage(\n res.error,\n formatMessage({\n id: getTranslationKey('asset-details.replace.error'),\n defaultMessage: 'Failed to replace the file.',\n })\n ),\n });\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslationKey('asset-details.replace.success'),\n defaultMessage: 'File replaced.',\n }),\n });\n };\n\n const handleCopyLink = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('asset-details.copy-link.success'),\n defaultMessage: 'Link copied.',\n }\n : {\n id: getTranslationKey('asset-details.copy-link.error'),\n defaultMessage: 'Failed to copy the link.',\n }\n ),\n });\n };\n\n const handleDownload = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n setIsDownloading(true);\n\n try {\n await downloadFile(url, asset.name);\n } catch {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('asset-details.download.error'),\n defaultMessage: 'Failed to download the file.',\n }),\n });\n } finally {\n setIsDownloading(false);\n }\n };\n\n // Two permission-gated groups: replace/copy-link/download above, move/delete\n // below. The separator earns its place only when both survive the gate —\n // `canUpdate` alone puts Replace in the top group, which is not enough.\n const hasTopGroup = canUpdate || canCopyLink || canDownload;\n const hasBottomGroup = canUpdate;\n const showSeparator = (canCopyLink || canDownload) && hasBottomGroup;\n\n // A role can read the library while holding none of these, and an empty\n // popup is worse than no trigger at all. Every flag is `false` until the\n // RBAC check settles, so wait for it — otherwise the trigger unmounts and\n // remounts on first paint for everyone.\n if (!isLoadingPermissions && !hasTopGroup && !hasBottomGroup) {\n return null;\n }\n\n return (\n <>\n <VisuallyHidden>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple={false}\n onChange={handleFileChange}\n aria-hidden\n tabIndex={-1}\n />\n </VisuallyHidden>\n {/* Non-modal: Radix's default `modal` marks the rest of the document\n `aria-hidden` and blocks pointer events while the menu is open, so\n clicking a sibling row's trigger only dismissed this one — leaving\n every menu you touched to be closed one click at a time. Non-modal\n dismissal treats that click as both \"close this\" and \"open that\". */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* `ActionsMenuContent` replaces the design system's flat 15rem clamp\n with the height Radix actually measured, and un-hides the scrollbar\n it would otherwise overflow into. See that file for why. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canUpdate && (\n <Menu.Item\n startIcon={<ArrowsCounterClockwise />}\n disabled={isReplacing}\n onSelect={() => setIsReplaceOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.replace'),\n defaultMessage: 'Replace media',\n })}\n </Menu.Item>\n )}\n {canCopyLink && (\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.copy-link'),\n defaultMessage: 'Copy link to media',\n })}\n </Menu.Item>\n )}\n {canDownload && (\n <Menu.Item startIcon={<Download />} disabled={isDownloading} onSelect={handleDownload}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.download'),\n defaultMessage: 'Download media',\n })}\n </Menu.Item>\n )}\n {showSeparator && <Menu.Separator />}\n {canUpdate && (\n <>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item\n startIcon={<Trash />}\n variant=\"danger\"\n onSelect={() => setIsDeleteOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.delete'),\n defaultMessage: 'Delete',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n <Dialog.Root open={isReplaceOpen} onOpenChange={setIsReplaceOpen}>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.title'),\n defaultMessage: 'Replace this media file?',\n })}\n </Dialog.Header>\n <Dialog.Body textAlign=\"center\">\n <Flex direction=\"column\" textAlign=\"center\">\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description'),\n defaultMessage: 'Current content will be permanently replaced.',\n })}\n </Typography>\n {aiEnabled ? (\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description.ai'),\n defaultMessage: 'AI will generate new metadata after upload.',\n })}\n </Typography>\n ) : null}\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" fullWidth>\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"secondary\" onClick={handleReplaceContinue} fullWidth>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.continue'),\n defaultMessage: 'Continue',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n {/* Both dialogs live inside the row, so a background refetch that drops the\n row would take an open dialog with it. Nothing invalidates until the\n mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [asset.id], folderIds: [] }}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n </>\n );\n};\n"],"names":["AssetActionsMenu","asset","dragData","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","markBusy","useBusyAssetsOptional","canUpdate","canDownload","canCopyLink","isLoading","isLoadingPermissions","useMediaLibraryPermissions","replaceAsset","isReplacing","useReplaceAssetMutation","aiEnabled","useAIMetadataEnabled","mime","fileInputRef","useRef","isReplaceOpen","setIsReplaceOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","isDownloading","setIsDownloading","moveItems","useMemo","handleReplaceContinue","current","click","handleFileChange","event","file","target","files","value","releaseBusy","id","getTranslationKey","defaultMessage","res","fileInfo","name","type","message","error","handleCopyLink","url","prefixFileUrlWithBackendUrl","didCopy","handleDownload","downloadFile","hasTopGroup","hasBottomGroup","showSeparator","_jsxs","_Fragment","_jsx","VisuallyHidden","input","ref","multiple","onChange","aria-hidden","tabIndex","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","ArrowsCounterClockwise","disabled","onSelect","Link","Download","Separator","ArrowRight","Trash","Dialog","open","onOpenChange","Content","Header","Body","textAlign","Flex","direction","Typography","Footer","Cancel","Button","fullWidth","Action","onClick","BulkMoveDialog","onClose","items","onSuccess","assetKey","DeleteItemsDialog","fileIds","folderIds"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AssetActionsMenu.js","sources":["../../../../../../admin/src/future/pages/Assets/components/AssetActionsMenu.tsx"],"sourcesContent":["import { useMemo, useRef, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Dialog,\n Flex,\n IconButton,\n Menu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { ArrowRight, ArrowsCounterClockwise, Download, Link, More, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useAIMetadataEnabled } from '../../../hooks/useAIMetadataEnabled';\nimport { useApiErrorMessage } from '../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport { useReplaceAssetMutation } from '../../../services/assets';\nimport { downloadFile } from '../../../utils/downloadFile';\nimport { prefixFileUrlWithBackendUrl } from '../../../utils/files';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { useBusyAssetsOptional } from '../hooks/useBusyAssets';\nimport { assetKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\n\nimport type { File } from '../../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetActionsMenuProps {\n asset: File;\n /** Drag data for this asset, so the move dialog validates against its real folder. */\n dragData: DragFileData;\n}\n\n/**\n * The \"...\" menu on an asset row/card. Always acts on that one asset, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance) — the file mirror of `FolderActionsMenu`.\n *\n * Replace / copy link / download duplicate what the details drawer offers as\n * icon buttons, so the same action is one click away without opening the asset\n * first. They are re-implemented rather than lifted out of the drawer: the\n * drawer versions render as `IconButton`s and report through its in-drawer toast\n * slot, neither of which fits a menu item on a row.\n *\n * A successful move or delete deselects this one asset and leaves the rest of\n * the selection intact: the mutations only invalidate RTK tags, so without it an\n * `asset:<id>` key for a file that has been deleted — or has moved out of this\n * list — would linger. The other selected rows are untouched, which is the whole\n * point of the menu being a single-item affordance.\n */\nexport const AssetActionsMenu = ({ asset, dragData }: AssetActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n // Absent in the asset picker and in unit tests: the replace still runs, it\n // just renders no row-level overlay.\n const markBusy = useBusyAssetsOptional()?.markBusy ?? (() => () => {});\n const {\n canUpdate,\n canDownload,\n canCopyLink,\n isLoading: isLoadingPermissions,\n } = useMediaLibraryPermissions();\n const [replaceAsset, { isLoading: isReplacing }] = useReplaceAssetMutation();\n const aiEnabled = useAIMetadataEnabled({ mime: asset.mime });\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isReplaceOpen, setIsReplaceOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Confirm first, then open the native picker, so the user only commits to\n // replacing after acknowledging the warning (same order as the drawer).\n const handleReplaceContinue = () => {\n setIsReplaceOpen(false);\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n // Reset the native input so the same file can be picked again later.\n event.target.value = '';\n\n if (!file) {\n return;\n }\n\n // The menu has closed by the time the picker returns, so `isReplacing` has\n // nothing left to disable and the row would otherwise sit inert for the\n // whole upload. Marking the asset busy puts the same overlay the drawer\n // uses on the row/card, cleared when the mutation settles either way.\n const releaseBusy = markBusy(\n asset.id,\n formatMessage({\n id: getTranslationKey('asset-details.replace.loading'),\n defaultMessage: 'Replacing the file…',\n })\n );\n\n let res;\n try {\n res = await replaceAsset({ id: asset.id, file, fileInfo: { name: asset.name } });\n } finally {\n releaseBusy();\n }\n\n if ('error' in res) {\n toggleNotification({\n type: 'danger',\n message: getErrorMessage(\n res.error,\n formatMessage({\n id: getTranslationKey('asset-details.replace.error'),\n defaultMessage: 'Failed to replace the file.',\n })\n ),\n });\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslationKey('asset-details.replace.success'),\n defaultMessage: 'File replaced.',\n }),\n });\n };\n\n const handleCopyLink = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('asset-details.copy-link.success'),\n defaultMessage: 'Link copied.',\n }\n : {\n id: getTranslationKey('asset-details.copy-link.error'),\n defaultMessage: 'Failed to copy the link.',\n }\n ),\n });\n };\n\n const handleDownload = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n setIsDownloading(true);\n\n try {\n await downloadFile(url, asset.name);\n } catch {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('asset-details.download.error'),\n defaultMessage: 'Failed to download the file.',\n }),\n });\n } finally {\n setIsDownloading(false);\n }\n };\n\n // Two permission-gated groups: replace/copy-link/download above, move/delete\n // below. The separator earns its place only when both survive the gate —\n // `canUpdate` alone puts Replace in the top group, which is not enough.\n const hasTopGroup = canUpdate || canCopyLink || canDownload;\n const hasBottomGroup = canUpdate;\n const showSeparator = (canCopyLink || canDownload) && hasBottomGroup;\n\n // A role can read the library while holding none of these, and an empty\n // popup is worse than no trigger at all. Every flag is `false` until the\n // RBAC check settles, so wait for it — otherwise the trigger unmounts and\n // remounts on first paint for everyone.\n if (!isLoadingPermissions && !hasTopGroup && !hasBottomGroup) {\n return null;\n }\n\n return (\n <>\n <VisuallyHidden>\n <input\n ref={fileInputRef}\n type=\"file\"\n // Replacing swaps the bytes of an existing asset, so the picker offers\n // only its own type. Without this the picker accepted anything and a\n // JPG could come back as PNG bytes still served under a `.jpg` url,\n // since replace preserves hash and ext by design.\n accept={asset.mime ?? ''}\n multiple={false}\n onChange={handleFileChange}\n aria-hidden\n tabIndex={-1}\n />\n </VisuallyHidden>\n {/* Non-modal: Radix's default `modal` marks the rest of the document\n `aria-hidden` and blocks pointer events while the menu is open, so\n clicking a sibling row's trigger only dismissed this one — leaving\n every menu you touched to be closed one click at a time. Non-modal\n dismissal treats that click as both \"close this\" and \"open that\". */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* `ActionsMenuContent` replaces the design system's flat 15rem clamp\n with the height Radix actually measured, and un-hides the scrollbar\n it would otherwise overflow into. See that file for why. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canUpdate && (\n <Menu.Item\n startIcon={<ArrowsCounterClockwise />}\n disabled={isReplacing}\n onSelect={() => setIsReplaceOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.replace'),\n defaultMessage: 'Replace media',\n })}\n </Menu.Item>\n )}\n {canCopyLink && (\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.copy-link'),\n defaultMessage: 'Copy link to media',\n })}\n </Menu.Item>\n )}\n {canDownload && (\n <Menu.Item startIcon={<Download />} disabled={isDownloading} onSelect={handleDownload}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.download'),\n defaultMessage: 'Download media',\n })}\n </Menu.Item>\n )}\n {showSeparator && <Menu.Separator />}\n {canUpdate && (\n <>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item\n startIcon={<Trash />}\n variant=\"danger\"\n onSelect={() => setIsDeleteOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.delete'),\n defaultMessage: 'Delete',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n <Dialog.Root open={isReplaceOpen} onOpenChange={setIsReplaceOpen}>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.title'),\n defaultMessage: 'Replace this media file?',\n })}\n </Dialog.Header>\n <Dialog.Body textAlign=\"center\">\n <Flex direction=\"column\" textAlign=\"center\">\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description'),\n defaultMessage: 'Current content will be permanently replaced.',\n })}\n </Typography>\n {aiEnabled ? (\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description.ai'),\n defaultMessage: 'AI will generate new metadata after upload.',\n })}\n </Typography>\n ) : null}\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" fullWidth>\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"secondary\" onClick={handleReplaceContinue} fullWidth>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.continue'),\n defaultMessage: 'Continue',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n {/* Both dialogs live inside the row, so a background refetch that drops the\n row would take an open dialog with it. Nothing invalidates until the\n mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [asset.id], folderIds: [] }}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n </>\n );\n};\n"],"names":["AssetActionsMenu","asset","dragData","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","markBusy","useBusyAssetsOptional","canUpdate","canDownload","canCopyLink","isLoading","isLoadingPermissions","useMediaLibraryPermissions","replaceAsset","isReplacing","useReplaceAssetMutation","aiEnabled","useAIMetadataEnabled","mime","fileInputRef","useRef","isReplaceOpen","setIsReplaceOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","isDownloading","setIsDownloading","moveItems","useMemo","handleReplaceContinue","current","click","handleFileChange","event","file","target","files","value","releaseBusy","id","getTranslationKey","defaultMessage","res","fileInfo","name","type","message","error","handleCopyLink","url","prefixFileUrlWithBackendUrl","didCopy","handleDownload","downloadFile","hasTopGroup","hasBottomGroup","showSeparator","_jsxs","_Fragment","_jsx","VisuallyHidden","input","ref","accept","multiple","onChange","aria-hidden","tabIndex","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","ArrowsCounterClockwise","disabled","onSelect","Link","Download","Separator","ArrowRight","Trash","Dialog","open","onOpenChange","Content","Header","Body","textAlign","Flex","direction","Typography","Footer","Cancel","Button","fullWidth","Action","onClick","BulkMoveDialog","onClose","items","onSuccess","assetKey","DeleteItemsDialog","fileIds","folderIds"],"mappings":"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"}
|
|
@@ -166,6 +166,11 @@ import { DeleteItemsDialog } from './DeleteItemsDialog.mjs';
|
|
|
166
166
|
children: /*#__PURE__*/ jsx("input", {
|
|
167
167
|
ref: fileInputRef,
|
|
168
168
|
type: "file",
|
|
169
|
+
// Replacing swaps the bytes of an existing asset, so the picker offers
|
|
170
|
+
// only its own type. Without this the picker accepted anything and a
|
|
171
|
+
// JPG could come back as PNG bytes still served under a `.jpg` url,
|
|
172
|
+
// since replace preserves hash and ext by design.
|
|
173
|
+
accept: asset.mime ?? '',
|
|
169
174
|
multiple: false,
|
|
170
175
|
onChange: handleFileChange,
|
|
171
176
|
"aria-hidden": true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetActionsMenu.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/AssetActionsMenu.tsx"],"sourcesContent":["import { useMemo, useRef, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Dialog,\n Flex,\n IconButton,\n Menu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { ArrowRight, ArrowsCounterClockwise, Download, Link, More, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useAIMetadataEnabled } from '../../../hooks/useAIMetadataEnabled';\nimport { useApiErrorMessage } from '../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport { useReplaceAssetMutation } from '../../../services/assets';\nimport { downloadFile } from '../../../utils/downloadFile';\nimport { prefixFileUrlWithBackendUrl } from '../../../utils/files';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { useBusyAssetsOptional } from '../hooks/useBusyAssets';\nimport { assetKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\n\nimport type { File } from '../../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetActionsMenuProps {\n asset: File;\n /** Drag data for this asset, so the move dialog validates against its real folder. */\n dragData: DragFileData;\n}\n\n/**\n * The \"...\" menu on an asset row/card. Always acts on that one asset, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance) — the file mirror of `FolderActionsMenu`.\n *\n * Replace / copy link / download duplicate what the details drawer offers as\n * icon buttons, so the same action is one click away without opening the asset\n * first. They are re-implemented rather than lifted out of the drawer: the\n * drawer versions render as `IconButton`s and report through its in-drawer toast\n * slot, neither of which fits a menu item on a row.\n *\n * A successful move or delete deselects this one asset and leaves the rest of\n * the selection intact: the mutations only invalidate RTK tags, so without it an\n * `asset:<id>` key for a file that has been deleted — or has moved out of this\n * list — would linger. The other selected rows are untouched, which is the whole\n * point of the menu being a single-item affordance.\n */\nexport const AssetActionsMenu = ({ asset, dragData }: AssetActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n // Absent in the asset picker and in unit tests: the replace still runs, it\n // just renders no row-level overlay.\n const markBusy = useBusyAssetsOptional()?.markBusy ?? (() => () => {});\n const {\n canUpdate,\n canDownload,\n canCopyLink,\n isLoading: isLoadingPermissions,\n } = useMediaLibraryPermissions();\n const [replaceAsset, { isLoading: isReplacing }] = useReplaceAssetMutation();\n const aiEnabled = useAIMetadataEnabled({ mime: asset.mime });\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isReplaceOpen, setIsReplaceOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Confirm first, then open the native picker, so the user only commits to\n // replacing after acknowledging the warning (same order as the drawer).\n const handleReplaceContinue = () => {\n setIsReplaceOpen(false);\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n // Reset the native input so the same file can be picked again later.\n event.target.value = '';\n\n if (!file) {\n return;\n }\n\n // The menu has closed by the time the picker returns, so `isReplacing` has\n // nothing left to disable and the row would otherwise sit inert for the\n // whole upload. Marking the asset busy puts the same overlay the drawer\n // uses on the row/card, cleared when the mutation settles either way.\n const releaseBusy = markBusy(\n asset.id,\n formatMessage({\n id: getTranslationKey('asset-details.replace.loading'),\n defaultMessage: 'Replacing the file…',\n })\n );\n\n let res;\n try {\n res = await replaceAsset({ id: asset.id, file, fileInfo: { name: asset.name } });\n } finally {\n releaseBusy();\n }\n\n if ('error' in res) {\n toggleNotification({\n type: 'danger',\n message: getErrorMessage(\n res.error,\n formatMessage({\n id: getTranslationKey('asset-details.replace.error'),\n defaultMessage: 'Failed to replace the file.',\n })\n ),\n });\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslationKey('asset-details.replace.success'),\n defaultMessage: 'File replaced.',\n }),\n });\n };\n\n const handleCopyLink = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('asset-details.copy-link.success'),\n defaultMessage: 'Link copied.',\n }\n : {\n id: getTranslationKey('asset-details.copy-link.error'),\n defaultMessage: 'Failed to copy the link.',\n }\n ),\n });\n };\n\n const handleDownload = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n setIsDownloading(true);\n\n try {\n await downloadFile(url, asset.name);\n } catch {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('asset-details.download.error'),\n defaultMessage: 'Failed to download the file.',\n }),\n });\n } finally {\n setIsDownloading(false);\n }\n };\n\n // Two permission-gated groups: replace/copy-link/download above, move/delete\n // below. The separator earns its place only when both survive the gate —\n // `canUpdate` alone puts Replace in the top group, which is not enough.\n const hasTopGroup = canUpdate || canCopyLink || canDownload;\n const hasBottomGroup = canUpdate;\n const showSeparator = (canCopyLink || canDownload) && hasBottomGroup;\n\n // A role can read the library while holding none of these, and an empty\n // popup is worse than no trigger at all. Every flag is `false` until the\n // RBAC check settles, so wait for it — otherwise the trigger unmounts and\n // remounts on first paint for everyone.\n if (!isLoadingPermissions && !hasTopGroup && !hasBottomGroup) {\n return null;\n }\n\n return (\n <>\n <VisuallyHidden>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple={false}\n onChange={handleFileChange}\n aria-hidden\n tabIndex={-1}\n />\n </VisuallyHidden>\n {/* Non-modal: Radix's default `modal` marks the rest of the document\n `aria-hidden` and blocks pointer events while the menu is open, so\n clicking a sibling row's trigger only dismissed this one — leaving\n every menu you touched to be closed one click at a time. Non-modal\n dismissal treats that click as both \"close this\" and \"open that\". */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* `ActionsMenuContent` replaces the design system's flat 15rem clamp\n with the height Radix actually measured, and un-hides the scrollbar\n it would otherwise overflow into. See that file for why. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canUpdate && (\n <Menu.Item\n startIcon={<ArrowsCounterClockwise />}\n disabled={isReplacing}\n onSelect={() => setIsReplaceOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.replace'),\n defaultMessage: 'Replace media',\n })}\n </Menu.Item>\n )}\n {canCopyLink && (\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.copy-link'),\n defaultMessage: 'Copy link to media',\n })}\n </Menu.Item>\n )}\n {canDownload && (\n <Menu.Item startIcon={<Download />} disabled={isDownloading} onSelect={handleDownload}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.download'),\n defaultMessage: 'Download media',\n })}\n </Menu.Item>\n )}\n {showSeparator && <Menu.Separator />}\n {canUpdate && (\n <>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item\n startIcon={<Trash />}\n variant=\"danger\"\n onSelect={() => setIsDeleteOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.delete'),\n defaultMessage: 'Delete',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n <Dialog.Root open={isReplaceOpen} onOpenChange={setIsReplaceOpen}>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.title'),\n defaultMessage: 'Replace this media file?',\n })}\n </Dialog.Header>\n <Dialog.Body textAlign=\"center\">\n <Flex direction=\"column\" textAlign=\"center\">\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description'),\n defaultMessage: 'Current content will be permanently replaced.',\n })}\n </Typography>\n {aiEnabled ? (\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description.ai'),\n defaultMessage: 'AI will generate new metadata after upload.',\n })}\n </Typography>\n ) : null}\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" fullWidth>\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"secondary\" onClick={handleReplaceContinue} fullWidth>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.continue'),\n defaultMessage: 'Continue',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n {/* Both dialogs live inside the row, so a background refetch that drops the\n row would take an open dialog with it. Nothing invalidates until the\n mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [asset.id], folderIds: [] }}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n </>\n );\n};\n"],"names":["AssetActionsMenu","asset","dragData","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","markBusy","useBusyAssetsOptional","canUpdate","canDownload","canCopyLink","isLoading","isLoadingPermissions","useMediaLibraryPermissions","replaceAsset","isReplacing","useReplaceAssetMutation","aiEnabled","useAIMetadataEnabled","mime","fileInputRef","useRef","isReplaceOpen","setIsReplaceOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","isDownloading","setIsDownloading","moveItems","useMemo","handleReplaceContinue","current","click","handleFileChange","event","file","target","files","value","releaseBusy","id","getTranslationKey","defaultMessage","res","fileInfo","name","type","message","error","handleCopyLink","url","prefixFileUrlWithBackendUrl","didCopy","handleDownload","downloadFile","hasTopGroup","hasBottomGroup","showSeparator","_jsxs","_Fragment","_jsx","VisuallyHidden","input","ref","multiple","onChange","aria-hidden","tabIndex","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","ArrowsCounterClockwise","disabled","onSelect","Link","Download","Separator","ArrowRight","Trash","Dialog","open","onOpenChange","Content","Header","Body","textAlign","Flex","direction","Typography","Footer","Cancel","Button","fullWidth","Action","onClick","BulkMoveDialog","onClose","items","onSuccess","assetKey","DeleteItemsDialog","fileIds","folderIds"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AssetActionsMenu.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/AssetActionsMenu.tsx"],"sourcesContent":["import { useMemo, useRef, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Dialog,\n Flex,\n IconButton,\n Menu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { ArrowRight, ArrowsCounterClockwise, Download, Link, More, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useAIMetadataEnabled } from '../../../hooks/useAIMetadataEnabled';\nimport { useApiErrorMessage } from '../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport { useReplaceAssetMutation } from '../../../services/assets';\nimport { downloadFile } from '../../../utils/downloadFile';\nimport { prefixFileUrlWithBackendUrl } from '../../../utils/files';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { useBusyAssetsOptional } from '../hooks/useBusyAssets';\nimport { assetKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\n\nimport type { File } from '../../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetActionsMenuProps {\n asset: File;\n /** Drag data for this asset, so the move dialog validates against its real folder. */\n dragData: DragFileData;\n}\n\n/**\n * The \"...\" menu on an asset row/card. Always acts on that one asset, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance) — the file mirror of `FolderActionsMenu`.\n *\n * Replace / copy link / download duplicate what the details drawer offers as\n * icon buttons, so the same action is one click away without opening the asset\n * first. They are re-implemented rather than lifted out of the drawer: the\n * drawer versions render as `IconButton`s and report through its in-drawer toast\n * slot, neither of which fits a menu item on a row.\n *\n * A successful move or delete deselects this one asset and leaves the rest of\n * the selection intact: the mutations only invalidate RTK tags, so without it an\n * `asset:<id>` key for a file that has been deleted — or has moved out of this\n * list — would linger. The other selected rows are untouched, which is the whole\n * point of the menu being a single-item affordance.\n */\nexport const AssetActionsMenu = ({ asset, dragData }: AssetActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n // Absent in the asset picker and in unit tests: the replace still runs, it\n // just renders no row-level overlay.\n const markBusy = useBusyAssetsOptional()?.markBusy ?? (() => () => {});\n const {\n canUpdate,\n canDownload,\n canCopyLink,\n isLoading: isLoadingPermissions,\n } = useMediaLibraryPermissions();\n const [replaceAsset, { isLoading: isReplacing }] = useReplaceAssetMutation();\n const aiEnabled = useAIMetadataEnabled({ mime: asset.mime });\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isReplaceOpen, setIsReplaceOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Confirm first, then open the native picker, so the user only commits to\n // replacing after acknowledging the warning (same order as the drawer).\n const handleReplaceContinue = () => {\n setIsReplaceOpen(false);\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n // Reset the native input so the same file can be picked again later.\n event.target.value = '';\n\n if (!file) {\n return;\n }\n\n // The menu has closed by the time the picker returns, so `isReplacing` has\n // nothing left to disable and the row would otherwise sit inert for the\n // whole upload. Marking the asset busy puts the same overlay the drawer\n // uses on the row/card, cleared when the mutation settles either way.\n const releaseBusy = markBusy(\n asset.id,\n formatMessage({\n id: getTranslationKey('asset-details.replace.loading'),\n defaultMessage: 'Replacing the file…',\n })\n );\n\n let res;\n try {\n res = await replaceAsset({ id: asset.id, file, fileInfo: { name: asset.name } });\n } finally {\n releaseBusy();\n }\n\n if ('error' in res) {\n toggleNotification({\n type: 'danger',\n message: getErrorMessage(\n res.error,\n formatMessage({\n id: getTranslationKey('asset-details.replace.error'),\n defaultMessage: 'Failed to replace the file.',\n })\n ),\n });\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslationKey('asset-details.replace.success'),\n defaultMessage: 'File replaced.',\n }),\n });\n };\n\n const handleCopyLink = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('asset-details.copy-link.success'),\n defaultMessage: 'Link copied.',\n }\n : {\n id: getTranslationKey('asset-details.copy-link.error'),\n defaultMessage: 'Failed to copy the link.',\n }\n ),\n });\n };\n\n const handleDownload = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n setIsDownloading(true);\n\n try {\n await downloadFile(url, asset.name);\n } catch {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('asset-details.download.error'),\n defaultMessage: 'Failed to download the file.',\n }),\n });\n } finally {\n setIsDownloading(false);\n }\n };\n\n // Two permission-gated groups: replace/copy-link/download above, move/delete\n // below. The separator earns its place only when both survive the gate —\n // `canUpdate` alone puts Replace in the top group, which is not enough.\n const hasTopGroup = canUpdate || canCopyLink || canDownload;\n const hasBottomGroup = canUpdate;\n const showSeparator = (canCopyLink || canDownload) && hasBottomGroup;\n\n // A role can read the library while holding none of these, and an empty\n // popup is worse than no trigger at all. Every flag is `false` until the\n // RBAC check settles, so wait for it — otherwise the trigger unmounts and\n // remounts on first paint for everyone.\n if (!isLoadingPermissions && !hasTopGroup && !hasBottomGroup) {\n return null;\n }\n\n return (\n <>\n <VisuallyHidden>\n <input\n ref={fileInputRef}\n type=\"file\"\n // Replacing swaps the bytes of an existing asset, so the picker offers\n // only its own type. Without this the picker accepted anything and a\n // JPG could come back as PNG bytes still served under a `.jpg` url,\n // since replace preserves hash and ext by design.\n accept={asset.mime ?? ''}\n multiple={false}\n onChange={handleFileChange}\n aria-hidden\n tabIndex={-1}\n />\n </VisuallyHidden>\n {/* Non-modal: Radix's default `modal` marks the rest of the document\n `aria-hidden` and blocks pointer events while the menu is open, so\n clicking a sibling row's trigger only dismissed this one — leaving\n every menu you touched to be closed one click at a time. Non-modal\n dismissal treats that click as both \"close this\" and \"open that\". */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* `ActionsMenuContent` replaces the design system's flat 15rem clamp\n with the height Radix actually measured, and un-hides the scrollbar\n it would otherwise overflow into. See that file for why. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canUpdate && (\n <Menu.Item\n startIcon={<ArrowsCounterClockwise />}\n disabled={isReplacing}\n onSelect={() => setIsReplaceOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.replace'),\n defaultMessage: 'Replace media',\n })}\n </Menu.Item>\n )}\n {canCopyLink && (\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.copy-link'),\n defaultMessage: 'Copy link to media',\n })}\n </Menu.Item>\n )}\n {canDownload && (\n <Menu.Item startIcon={<Download />} disabled={isDownloading} onSelect={handleDownload}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.download'),\n defaultMessage: 'Download media',\n })}\n </Menu.Item>\n )}\n {showSeparator && <Menu.Separator />}\n {canUpdate && (\n <>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item\n startIcon={<Trash />}\n variant=\"danger\"\n onSelect={() => setIsDeleteOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.delete'),\n defaultMessage: 'Delete',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n <Dialog.Root open={isReplaceOpen} onOpenChange={setIsReplaceOpen}>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.title'),\n defaultMessage: 'Replace this media file?',\n })}\n </Dialog.Header>\n <Dialog.Body textAlign=\"center\">\n <Flex direction=\"column\" textAlign=\"center\">\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description'),\n defaultMessage: 'Current content will be permanently replaced.',\n })}\n </Typography>\n {aiEnabled ? (\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description.ai'),\n defaultMessage: 'AI will generate new metadata after upload.',\n })}\n </Typography>\n ) : null}\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" fullWidth>\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"secondary\" onClick={handleReplaceContinue} fullWidth>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.continue'),\n defaultMessage: 'Continue',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n {/* Both dialogs live inside the row, so a background refetch that drops the\n row would take an open dialog with it. Nothing invalidates until the\n mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [asset.id], folderIds: [] }}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n </>\n );\n};\n"],"names":["AssetActionsMenu","asset","dragData","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","markBusy","useBusyAssetsOptional","canUpdate","canDownload","canCopyLink","isLoading","isLoadingPermissions","useMediaLibraryPermissions","replaceAsset","isReplacing","useReplaceAssetMutation","aiEnabled","useAIMetadataEnabled","mime","fileInputRef","useRef","isReplaceOpen","setIsReplaceOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","isDownloading","setIsDownloading","moveItems","useMemo","handleReplaceContinue","current","click","handleFileChange","event","file","target","files","value","releaseBusy","id","getTranslationKey","defaultMessage","res","fileInfo","name","type","message","error","handleCopyLink","url","prefixFileUrlWithBackendUrl","didCopy","handleDownload","downloadFile","hasTopGroup","hasBottomGroup","showSeparator","_jsxs","_Fragment","_jsx","VisuallyHidden","input","ref","accept","multiple","onChange","aria-hidden","tabIndex","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","ArrowsCounterClockwise","disabled","onSelect","Link","Download","Separator","ArrowRight","Trash","Dialog","open","onOpenChange","Content","Header","Body","textAlign","Flex","direction","Typography","Footer","Cancel","Button","fullWidth","Action","onClick","BulkMoveDialog","onClose","items","onSuccess","assetKey","DeleteItemsDialog","fileIds","folderIds"],"mappings":"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"}
|