@strapi/upload 5.51.1 → 5.51.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/components/AssetCard/VideoPreview.js +1 -1
- package/dist/admin/components/AssetCard/VideoPreview.js.map +1 -1
- package/dist/admin/components/AssetCard/VideoPreview.mjs +1 -1
- package/dist/admin/components/AssetCard/VideoPreview.mjs.map +1 -1
- package/dist/admin/components/TableList/TableList.js +1 -1
- package/dist/admin/components/TableList/TableList.js.map +1 -1
- package/dist/admin/components/TableList/TableList.mjs +1 -1
- package/dist/admin/components/TableList/TableList.mjs.map +1 -1
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js +21 -4
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js.map +1 -1
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs +21 -4
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs.map +1 -1
- package/dist/admin/future/components/Drawer.js +3 -1
- package/dist/admin/future/components/Drawer.js.map +1 -1
- package/dist/admin/future/components/Drawer.mjs +3 -1
- package/dist/admin/future/components/Drawer.mjs.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.js +200 -27
- package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.mjs +203 -30
- package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
- package/dist/admin/future/hooks/useMediaLibraryPermissions.js +35 -0
- package/dist/admin/future/hooks/useMediaLibraryPermissions.js.map +1 -0
- package/dist/admin/future/hooks/useMediaLibraryPermissions.mjs +33 -0
- package/dist/admin/future/hooks/useMediaLibraryPermissions.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +203 -78
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +200 -75
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +75 -32
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +75 -32
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +46 -19
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +47 -20
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +5 -2
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +5 -2
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +100 -0
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +98 -0
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +10 -4
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +10 -4
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +140 -22
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +142 -24
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/DateRangeCalendar.js +193 -0
- package/dist/admin/future/pages/Assets/components/DateRangeCalendar.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/DateRangeCalendar.mjs +191 -0
- package/dist/admin/future/pages/Assets/components/DateRangeCalendar.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +18 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +18 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js +13 -3
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +13 -3
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/EmptyState.js +62 -3
- package/dist/admin/future/pages/Assets/components/EmptyState.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/EmptyState.mjs +62 -4
- package/dist/admin/future/pages/Assets/components/EmptyState.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterBadges.js +408 -0
- package/dist/admin/future/pages/Assets/components/FilterBadges.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/FilterBadges.mjs +406 -0
- package/dist/admin/future/pages/Assets/components/FilterBadges.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/FilterMenu.js +273 -0
- package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +267 -0
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +76 -19
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +78 -21
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js +33 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs +31 -0
- package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.js +21 -32
- package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs +22 -33
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSearch.js +40 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSearch.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSearch.mjs +38 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSearch.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +21 -5
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +21 -5
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.js +33 -12
- package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.mjs +33 -12
- package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +40 -4
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +40 -4
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useListFilters.js +168 -0
- package/dist/admin/future/pages/Assets/hooks/useListFilters.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useListFilters.mjs +162 -0
- package/dist/admin/future/pages/Assets/hooks/useListFilters.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/utils/buildAssetFilters.js +201 -0
- package/dist/admin/future/pages/Assets/utils/buildAssetFilters.js.map +1 -0
- package/dist/admin/future/pages/Assets/utils/buildAssetFilters.mjs +198 -0
- package/dist/admin/future/pages/Assets/utils/buildAssetFilters.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/utils/listQueryKey.js +2 -2
- package/dist/admin/future/pages/Assets/utils/listQueryKey.js.map +1 -1
- package/dist/admin/future/pages/Assets/utils/listQueryKey.mjs +2 -2
- package/dist/admin/future/pages/Assets/utils/listQueryKey.mjs.map +1 -1
- package/dist/admin/future/services/api.js +163 -28
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +163 -30
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +29 -17
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +29 -17
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/future/services/folders.js +29 -17
- package/dist/admin/future/services/folders.js.map +1 -1
- package/dist/admin/future/services/folders.mjs +29 -17
- package/dist/admin/future/services/folders.mjs.map +1 -1
- package/dist/admin/future/services/settings.js +10 -3
- package/dist/admin/future/services/settings.js.map +1 -1
- package/dist/admin/future/services/settings.mjs +10 -3
- package/dist/admin/future/services/settings.mjs.map +1 -1
- package/dist/admin/future/store/uploadProgress.js +109 -2
- package/dist/admin/future/store/uploadProgress.js.map +1 -1
- package/dist/admin/future/store/uploadProgress.mjs +105 -3
- package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
- package/dist/admin/future/utils/searchQueryParam.js +11 -0
- package/dist/admin/future/utils/searchQueryParam.js.map +1 -0
- package/dist/admin/future/utils/searchQueryParam.mjs +9 -0
- package/dist/admin/future/utils/searchQueryParam.mjs.map +1 -0
- package/dist/admin/hooks/useSelectionState.js +2 -4
- package/dist/admin/hooks/useSelectionState.js.map +1 -1
- package/dist/admin/hooks/useSelectionState.mjs +2 -4
- package/dist/admin/hooks/useSelectionState.mjs.map +1 -1
- package/dist/admin/shared/constants.js +43 -0
- package/dist/admin/shared/constants.js.map +1 -0
- package/dist/admin/shared/constants.mjs +38 -0
- package/dist/admin/shared/constants.mjs.map +1 -0
- package/dist/admin/src/future/hooks/useMediaLibraryPermissions.d.ts +21 -0
- package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetCropEditor.d.ts +7 -1
- package/dist/admin/src/future/pages/Assets/components/AssetsSearchInput.d.ts +5 -0
- package/dist/admin/src/future/pages/Assets/components/BulkActionsBar.d.ts +14 -1
- package/dist/admin/src/future/pages/Assets/components/DateRangeCalendar.d.ts +8 -0
- package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZoneContext.d.ts +8 -1
- package/dist/admin/src/future/pages/Assets/components/EmptyState.d.ts +18 -1
- package/dist/admin/src/future/pages/Assets/components/FilterBadges.d.ts +6 -0
- package/dist/admin/src/future/pages/Assets/components/FilterMenu.d.ts +22 -0
- package/dist/admin/src/future/pages/Assets/components/FolderTree/FolderTree.d.ts +13 -4
- package/dist/admin/src/future/pages/Assets/components/FolderTree/filterFolderTree.d.ts +16 -0
- package/dist/admin/src/future/pages/Assets/components/SortMenu.d.ts +6 -0
- package/dist/admin/src/future/pages/Assets/hooks/useAssetSearch.d.ts +12 -0
- package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +8 -1
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +13 -3
- package/dist/admin/src/future/pages/Assets/hooks/useListFilters.d.ts +69 -0
- package/dist/admin/src/future/pages/Assets/utils/buildAssetFilters.d.ts +46 -0
- package/dist/admin/src/future/pages/Assets/utils/listQueryKey.d.ts +3 -4
- package/dist/admin/src/future/services/api.d.ts +53 -5
- package/dist/admin/src/future/services/assets.d.ts +9 -1
- package/dist/admin/src/future/services/folders.d.ts +3 -0
- package/dist/admin/src/future/services/settings.d.ts +2 -2
- package/dist/admin/src/future/store/uploadProgress.d.ts +83 -1
- package/dist/admin/src/future/utils/searchQueryParam.d.ts +7 -0
- package/dist/admin/src/hooks/useAiAvailability.d.ts +1 -1
- package/dist/admin/src/hooks/useEditAsset.d.ts +4 -4
- package/dist/admin/src/hooks/useEditFolder.d.ts +4 -4
- package/dist/admin/src/hooks/useSettings.d.ts +1 -0
- package/dist/admin/src/hooks/useTracking.d.ts +1 -1
- package/dist/admin/src/hooks/useUpload.d.ts +1 -1
- package/dist/admin/translations/en.json.js +53 -3
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +53 -3
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/utils/urlYupSchema.js +33 -9
- package/dist/admin/utils/urlYupSchema.js.map +1 -1
- package/dist/admin/utils/urlYupSchema.mjs +33 -9
- package/dist/admin/utils/urlYupSchema.mjs.map +1 -1
- package/dist/server/config.js +13 -5
- package/dist/server/config.js.map +1 -1
- package/dist/server/config.mjs +13 -5
- package/dist/server/config.mjs.map +1 -1
- package/dist/server/constants.js.map +1 -1
- package/dist/server/constants.mjs.map +1 -1
- package/dist/server/controllers/admin-file.js +30 -0
- package/dist/server/controllers/admin-file.js.map +1 -1
- package/dist/server/controllers/admin-file.mjs +30 -0
- package/dist/server/controllers/admin-file.mjs.map +1 -1
- package/dist/server/controllers/admin-settings.js +20 -2
- package/dist/server/controllers/admin-settings.js.map +1 -1
- package/dist/server/controllers/admin-settings.mjs +21 -3
- package/dist/server/controllers/admin-settings.mjs.map +1 -1
- package/dist/server/controllers/content-api.js +1 -2
- package/dist/server/controllers/content-api.js.map +1 -1
- package/dist/server/controllers/content-api.mjs +2 -2
- package/dist/server/controllers/content-api.mjs.map +1 -1
- package/dist/server/controllers/validation/admin/ai-metadata.js +12 -0
- package/dist/server/controllers/validation/admin/ai-metadata.js.map +1 -0
- package/dist/server/controllers/validation/admin/ai-metadata.mjs +10 -0
- package/dist/server/controllers/validation/admin/ai-metadata.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/settings.js +4 -1
- package/dist/server/controllers/validation/admin/settings.js.map +1 -1
- package/dist/server/controllers/validation/admin/settings.mjs +1 -1
- package/dist/server/controllers/validation/admin/settings.mjs.map +1 -1
- package/dist/server/routes/admin.js +18 -0
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +18 -0
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/services/ai-metadata.js +108 -11
- package/dist/server/services/ai-metadata.js.map +1 -1
- package/dist/server/services/ai-metadata.mjs +108 -11
- package/dist/server/services/ai-metadata.mjs.map +1 -1
- package/dist/server/services/file.js +86 -13
- package/dist/server/services/file.js.map +1 -1
- package/dist/server/services/file.mjs +87 -14
- package/dist/server/services/file.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js +4 -4
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs +4 -4
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/shared/constants.js +43 -0
- package/dist/server/shared/constants.js.map +1 -0
- package/dist/server/shared/constants.mjs +38 -0
- package/dist/server/shared/constants.mjs.map +1 -0
- package/dist/server/src/config.d.ts +2 -0
- package/dist/server/src/config.d.ts.map +1 -1
- package/dist/server/src/constants.d.ts +2 -1
- package/dist/server/src/constants.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-file.d.ts +10 -0
- package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/admin/ai-metadata.d.ts +2 -0
- package/dist/server/src/controllers/validation/admin/ai-metadata.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/admin/settings.d.ts +1 -1
- package/dist/server/src/controllers/validation/admin/settings.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -1
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata.d.ts +19 -0
- package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
- package/dist/server/src/services/file.d.ts +12 -2
- package/dist/server/src/services/file.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -1
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/types.d.ts +3 -0
- package/dist/server/src/types.d.ts.map +1 -1
- package/dist/shared/constants.d.ts +35 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/contracts/files.d.ts +25 -0
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/dist/shared/contracts/settings.d.ts +7 -0
- package/package.json +7 -7
|
@@ -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, 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 { ChevronDown, Files, Folder, GridFour as GridIcon, Link, List } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useUploadFromUrlsMutation, useUploadFilesMutation } from '../../services/api';\nimport { useGetFolderQuery, useGetFoldersQuery } from '../../services/folders';\nimport { getTranslationKey } from '../../utils/translations';\n\nimport {\n AssetDetailsDrawer,\n useAssetDetailsParam,\n} from './components/AssetDetails/AssetDetailsDrawer';\nimport { AssetsGrid } from './components/AssetsGrid';\nimport { AssetsTable } from './components/AssetsTable';\nimport { BulkActionsBar } from './components/BulkActionsBar';\nimport { CreateFolderDialog } from './components/CreateFolderDialog';\nimport { AssetsDndProvider } from './components/Dnd/AssetsDndProvider';\nimport { DropFilesMessage, DropZoneWithOverlay } from './components/DropZone/UploadDropZone';\nimport { UploadDropZoneProvider } from './components/DropZone/UploadDropZoneContext';\nimport { EmptyState } from './components/EmptyState';\nimport { FolderTree } from './components/FolderTree/FolderTree';\nimport { ImportFromUrlDialog } from './components/ImportFromUrlDialog';\nimport { SortMenu } from './components/SortMenu';\nimport { localStorageKeys, viewOptions } from './constants';\nimport { AssetSelectionProvider, useAssetSelection } from './hooks/useAssetSelection';\nimport { useFolderInfo } from './hooks/useFolderInfo';\nimport { useFolderNavigation } from './hooks/useFolderNavigation';\nimport { useInfiniteAssets } from './hooks/useInfiniteAssets';\nimport { useListSort, type FoldersPosition } from './hooks/useListSort';\nimport { getListQueryKey } from './utils/listQueryKey';\nimport { mergeMixedList } from './utils/mergeMixedList';\n\nimport type { UploadFileInfo } from '../../../../../shared/contracts/files';\n\nconst INTERSECTION_OPTIONS: IntersectionObserverInit = { threshold: 0.1 };\n\n/* -------------------------------------------------------------------------------------------------\n * AssetsView\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsViewProps {\n view: number;\n folderId: number | null;\n assetsSort: string;\n foldersSort: string;\n foldersPosition: FoldersPosition;\n onAssetItemClick: (assetId: number) => void;\n onAddAssets: () => void;\n}\n\nconst AssetsView = ({\n view,\n folderId,\n assetsSort,\n foldersSort,\n foldersPosition,\n onAssetItemClick,\n onAddAssets,\n}: AssetsViewProps) => {\n const { formatMessage } = useIntl();\n const {\n assets,\n isLoading: isLoadingAssets,\n isFetchingMore,\n hasNextPage,\n fetchNextPage,\n error,\n } = useInfiniteAssets({ folder: folderId, sort: assetsSort });\n const { data: folders = [], isLoading: isLoadingFolders } = useGetFoldersQuery({\n parentId: folderId,\n sort: foldersSort,\n });\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 const loadMoreRef = useElementOnScreen<HTMLDivElement>(\n useCallback(\n (isVisible) => {\n if (isVisible && hasNextPage && !isFetchingMore) {\n fetchNextPage();\n }\n },\n [hasNextPage, isFetchingMore, fetchNextPage]\n ),\n 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 return <EmptyState onAddAssets={onAddAssets} />;\n }\n return (\n <>\n {isGridView ? (\n <AssetsGrid folders={folders} assets={assets} onAssetItemClick={onAssetItemClick} />\n ) : (\n <AssetsTable\n assets={assets}\n folders={folders}\n mixedItems={mixedItems}\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 </>\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).\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\nconst HeaderWrapper = styled(Box)`\n [data-strapi-header] {\n background: ${({ theme }) => theme.colors.neutral0};\n\n h1 {\n font-size: 1.8rem;\n }\n }\n`;\n\nexport const AssetsPage = () => {\n const { formatMessage } = useIntl();\n const { openDetails } = useAssetDetailsParam();\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 const itemCountLabel = formatMessage(\n {\n id: getTranslationKey('header.content.item-count'),\n defaultMessage: '{count, plural, =1 {# item} other {# items}}',\n },\n { count: itemCount }\n );\n const pageHeaderTitle = title\n ? `${title} (${itemCountLabel})`\n : formatMessage({ id: 'app.loading', defaultMessage: 'Loading...' });\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 // Upload handlers\n const [uploadFiles] = useUploadFilesMutation();\n const [uploadFromUrls] = useUploadFromUrlsMutation();\n\n const uploadFilesToFolder = async (files: globalThis.File[], folderId: number | null) => {\n if (files.length === 0) return;\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({ formData, totalFiles: files.length }).unwrap();\n } catch (error) {\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 await uploadFilesToFolder(Array.from(files), currentFolderId);\n }\n e.target.value = '';\n };\n\n const handleDrop = async (files: globalThis.File[]) => {\n await uploadFilesToFolder(files, currentFolderId);\n };\n\n const handleUrlUpload = async (urls: string[]) => {\n try {\n await uploadFromUrls({ urls, folderId: currentFolderId }).unwrap();\n } catch (error) {\n // Error is already dispatched to store from the API queryFn\n }\n };\n\n const listSort = useListSort();\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: '', // TODO: wire when building header search\n // Folder position changes the render order too — selection must reset.\n sort: `${listSort.assetsSort};folders=${listSort.foldersPosition}`,\n filter: null, // TODO: wire when building header filters\n });\n\n return (\n <>\n <UploadDropZoneProvider onDrop={handleDrop}>\n <AssetSelectionProvider>\n <AssetsDndProvider>\n <ClearSelectionOnChange listQueryKey={listQueryKey} />\n <Box ref={uploadDropZoneRef}>\n <Layouts.Root\n minHeight=\"100vh\"\n background=\"neutral0\"\n sideNav={\n <FolderTree\n currentFolderId={currentFolderId}\n onSelectFolder={navigateToFolderId}\n />\n }\n >\n <VisuallyHidden>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} multiple />\n </VisuallyHidden>\n\n <HeaderWrapper>\n <Layouts.Header\n title={pageHeaderTitle}\n primaryAction={\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={<Folder />}\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 onSelect={() => setIsUrlDialogOpen(true)} startIcon={<Link />}>\n {formatMessage({\n id: getTranslationKey('import-from-url'),\n defaultMessage: 'Import from URL',\n })}\n </MenuItem>\n </SimpleMenu>\n }\n subtitle={\n <Flex justifyContent=\"space-between\" alignItems=\"center\" gap={4} width=\"100%\">\n <Flex gap={4} alignItems=\"center\">\n TODO: Filters and search\n </Flex>\n\n <Flex gap={4} alignItems=\"stretch\">\n <SortMenu sort={listSort} showFoldersGroup={!isGridView} />\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 {formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\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 {formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n </StyledToggleItem>\n </StyledToggleGroup>\n </Flex>\n </Flex>\n }\n />\n </HeaderWrapper>\n\n <Layouts.Content>\n <DropZoneWithOverlay>\n <DropFilesMessage uploadDropZoneRef={uploadDropZoneRef} folderName={title} />\n <AssetsView\n view={view}\n folderId={currentFolderId}\n assetsSort={listSort.assetsSort}\n foldersSort={listSort.foldersSort}\n foldersPosition={listSort.foldersPosition}\n onAssetItemClick={openDetails}\n onAddAssets={handleFileSelect}\n />\n </DropZoneWithOverlay>\n </Layouts.Content>\n </Layouts.Root>\n </Box>\n <BulkActionsBar />\n </AssetsDndProvider>\n </AssetSelectionProvider>\n </UploadDropZoneProvider>\n <CreateFolderDialog\n open={isCreateFolderDialogOpen}\n folderName={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","AssetsView","view","folderId","assetsSort","foldersSort","foldersPosition","onAssetItemClick","onAddAssets","formatMessage","useIntl","assets","isLoading","isLoadingAssets","isFetchingMore","hasNextPage","fetchNextPage","error","useInfiniteAssets","folder","sort","data","folders","isLoadingFolders","useGetFoldersQuery","parentId","isGridView","viewOptions","GRID","mixedItems","useMemo","mergeMixedList","loadMoreRef","useElementOnScreen","useCallback","isVisible","_jsx","Flex","justifyContent","padding","Loader","id","defaultMessage","Box","Typography","textColor","getTranslationKey","length","EmptyState","_jsxs","_Fragment","AssetsGrid","AssetsTable","div","ref","style","height","ClearSelectionOnChange","listQueryKey","clear","useAssetSelection","useEffect","StyledToggleGroup","styled","ToggleGroup","Root","theme","spaces","colors","neutral100","neutral200","borderRadius","StyledToggleItem","Item","neutral600","fontSizes","fontWeights","semiBold","neutral700","neutral0","primary600","HeaderWrapper","AssetsPage","openDetails","useAssetDetailsParam","currentFolderId","navigateToFolderId","navigateToRoot","useFolderNavigation","currentFolderError","useGetFolderQuery","skip","name","title","itemCount","useFolderInfo","itemCountLabel","count","pageHeaderTitle","isCreateFolderDialogOpen","setIsCreateFolderDialogOpen","useState","setView","usePersistentState","localStorageKeys","isUrlDialogOpen","setIsUrlDialogOpen","fileInputRef","useRef","uploadDropZoneRef","uploadFiles","useUploadFilesMutation","uploadFromUrls","useUploadFromUrlsMutation","uploadFilesToFolder","files","formData","FormData","fileInfoArray","forEach","file","append","push","caption","alternativeText","JSON","stringify","totalFiles","unwrap","handleFileSelect","current","click","handleFileChange","e","target","Array","from","value","handleDrop","handleUrlUpload","urls","listSort","useListSort","getListQueryKey","search","filter","UploadDropZoneProvider","onDrop","AssetSelectionProvider","AssetsDndProvider","Layouts","minHeight","background","sideNav","FolderTree","onSelectFolder","VisuallyHidden","input","type","onChange","multiple","Header","primaryAction","SimpleMenu","popoverPlacement","variant","endIcon","ChevronDown","label","MenuItem","onSelect","startIcon","Folder","Files","Link","subtitle","alignItems","gap","width","SortMenu","showFoldersGroup","onValueChange","TABLE","aria-label","List","GridIcon","Content","DropZoneWithOverlay","DropFilesMessage","folderName","BulkActionsBar","CreateFolderDialog","open","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, 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 } from 'styled-components';\n\nimport { useAIAvailability } from '../../../hooks/useAiAvailability';\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { useUploadFromUrlsMutation, useUploadFilesMutation } from '../../services/api';\nimport { useGetFolderQuery, useGetFoldersQuery } from '../../services/folders';\nimport { useGetUploadSettingsQuery } from '../../services/settings';\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 { CreateFolderDialog } from './components/CreateFolderDialog';\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 { 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 { useFolderInfo } from './hooks/useFolderInfo';\nimport { useFolderNavigation } from './hooks/useFolderNavigation';\nimport { useInfiniteAssets } from './hooks/useInfiniteAssets';\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';\n\nimport type { File, UploadFileInfo } from '../../../../../shared/contracts/files';\nimport type { Folder } from '../../../../../shared/contracts/folders';\n\nconst INTERSECTION_OPTIONS: IntersectionObserverInit = { threshold: 0.1 };\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 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 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 const loadMoreRef = useElementOnScreen<HTMLDivElement>(\n useCallback(\n (isVisible) => {\n if (isVisible && hasNextPage && !isFetchingMore) {\n fetchNextPage();\n }\n },\n [hasNextPage, isFetchingMore, fetchNextPage]\n ),\n 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 folders={folders} assets={assets} onAssetItemClick={onAssetItemClick} />\n ) : (\n <AssetsTable\n assets={assets}\n folders={folders}\n mixedItems={mixedItems}\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} />\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\nconst HeaderWrapper = styled(Box)`\n [data-strapi-header] {\n background: ${({ theme }) => theme.colors.neutral0};\n\n h1 {\n font-size: 1.8rem;\n }\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 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 filtersKey: listFilters.serialized,\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 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 // 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 dialog.\n const { isEnabled: isAiMetadataEnabled } = useAIAvailability();\n\n const uploadFilesToFolder = async (files: globalThis.File[], folderId: number | null) => {\n if (files.length === 0) return;\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 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 await uploadFilesToFolder(files, currentFolderId);\n };\n\n const handleUrlUpload = async (urls: string[]) => {\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 <AssetsDndProvider>\n <ClearSelectionOnChange listQueryKey={listQueryKey} />\n <Box ref={uploadDropZoneRef}>\n <Layouts.Root\n minHeight=\"100vh\"\n background=\"neutral0\"\n sideNav={\n <FolderTree\n currentFolderId={currentFolderId}\n showActiveFolder={!isSearching}\n onSelectFolder={navigateToFolderId}\n />\n }\n >\n <VisuallyHidden>\n <input type=\"file\" ref={fileInputRef} onChange={handleFileChange} multiple />\n </VisuallyHidden>\n\n <HeaderWrapper>\n <Layouts.Header\n title={pageHeaderTitle}\n primaryAction={\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 onSelect={() => setIsUrlDialogOpen(true)} startIcon={<Link />}>\n {formatMessage({\n id: getTranslationKey('import-from-url'),\n defaultMessage: 'Import from URL',\n })}\n </MenuItem>\n </SimpleMenu>\n )\n }\n subtitle={\n <>\n <Flex\n justifyContent=\"space-between\"\n alignItems=\"center\"\n gap={4}\n width=\"100%\"\n >\n <Flex gap={4} alignItems=\"center\">\n <FilterMenu listFilters={listFilters} />\n <AssetsSearchInput />\n </Flex>\n\n <Flex gap={4} alignItems=\"center\">\n <SortMenu sort={listSort} showFoldersGroup={!isGridView} />\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 {formatMessage({\n id: getTranslationKey('view.table'),\n defaultMessage: 'Table view',\n })}\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 {formatMessage({\n id: getTranslationKey('view.grid'),\n defaultMessage: 'Grid view',\n })}\n </StyledToggleItem>\n </StyledToggleGroup>\n </Flex>\n </Flex>\n <FilterBadges listFilters={listFilters} />\n </>\n }\n />\n </HeaderWrapper>\n\n <Layouts.Content>\n <DropZoneWithOverlay>\n <DropFilesMessage uploadDropZoneRef={uploadDropZoneRef} folderName={title} />\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 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 </Layouts.Root>\n </Box>\n </AssetsDndProvider>\n </AssetSelectionProvider>\n </UploadDropZoneProvider>\n <CreateFolderDialog\n open={isCreateFolderDialogOpen}\n folderName={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","ITEM_COUNT_MESSAGE","id","getTranslationKey","defaultMessage","SEARCH_RESULTS_COUNT_MESSAGES","both","folders","assets","getSearchResultsCountMessage","numberFolders","numberAssets","AssetsView","view","isLoadingFolders","isLoadingAssets","isFetchingMore","hasNextPage","fetchNextPage","error","searchQuery","assetsSort","foldersPosition","hasActiveFilters","onClearFilters","onAssetItemClick","onAddAssets","canAddAssets","onClearSearch","formatMessage","useIntl","isGridView","viewOptions","GRID","isLoading","mixedItems","useMemo","mergeMixedList","sort","loadMoreRef","useElementOnScreen","useCallback","isVisible","_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","HeaderWrapper","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","pagination","assetsError","useInfiniteAssets","folder","search","undefined","fileClauses","filtersKey","enabled","showFiles","data","fetchedFolders","useGetFoldersQuery","parentId","foldersSort","folderClauses","showFolders","itemCountLabel","count","searchResultsTitle","query","total","searchResultsCountLabel","pageHeaderTitle","isCreateFolderDialogOpen","setIsCreateFolderDialogOpen","useState","setView","usePersistentState","localStorageKeys","isUrlDialogOpen","setIsUrlDialogOpen","fileInputRef","useRef","uploadDropZoneRef","uploadFiles","useUploadFilesMutation","uploadFromUrls","useUploadFromUrlsMutation","settings","useGetUploadSettingsQuery","concurrency","concurrentUploadRequests","isEnabled","isAiMetadataEnabled","useAIAvailability","uploadFilesToFolder","files","folderId","formData","FormData","fileInfoArray","forEach","file","append","push","caption","alternativeText","JSON","stringify","totalFiles","generateAiMetadata","Boolean","unwrap","handleFileSelect","current","click","handleFileChange","e","target","Array","from","value","handleDrop","handleUrlUpload","urls","getListQueryKey","filter","UploadDropZoneProvider","onDrop","disabled","AssetSelectionProvider","AssetsDndProvider","Layouts","minHeight","background","sideNav","FolderTree","showActiveFolder","onSelectFolder","VisuallyHidden","input","type","onChange","multiple","Header","primaryAction","SimpleMenu","popoverPlacement","variant","endIcon","ChevronDown","label","MenuItem","onSelect","startIcon","FolderIcon","Files","Link","subtitle","alignItems","gap","width","FilterMenu","AssetsSearchInput","SortMenu","showFoldersGroup","onValueChange","TABLE","aria-label","List","GridIcon","FilterBadges","Content","DropZoneWithOverlay","DropFilesMessage","folderName","clearFilters","CreateFolderDialog","open","parentFolderId","onClose","ImportFromUrlDialog","onUpload","AssetDetailsDrawer"],"mappings":"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"}
|
|
@@ -47,6 +47,8 @@ const Overlay = styledComponents.styled(designSystem.Flex)`
|
|
|
47
47
|
border-radius: ${({ theme })=>theme.borderRadius};
|
|
48
48
|
border: 1px solid ${({ theme })=>theme.colors.neutral150};
|
|
49
49
|
background: ${({ theme })=>theme.colors.neutral0};
|
|
50
|
+
/* Focused programmatically on open (tabIndex -1) — no visible ring needed. */
|
|
51
|
+
outline: none;
|
|
50
52
|
`;
|
|
51
53
|
const HeaderBar = styledComponents.styled(designSystem.Flex)`
|
|
52
54
|
width: 100%;
|
|
@@ -56,6 +58,9 @@ const HeaderBar = styledComponents.styled(designSystem.Flex)`
|
|
|
56
58
|
background: ${({ theme })=>theme.colors.neutral0};
|
|
57
59
|
`;
|
|
58
60
|
// Fills the remaining space between header/footer; checkerboard pattern.
|
|
61
|
+
// The horizontal padding keeps the image off the viewport edges — the corner
|
|
62
|
+
// handles overhang the image by half their size, and on narrow (mobile)
|
|
63
|
+
// screens an edge-to-edge image leaves nothing to grab.
|
|
59
64
|
const Body = styledComponents.styled(designSystem.Box)`
|
|
60
65
|
width: 100%;
|
|
61
66
|
position: relative;
|
|
@@ -65,6 +70,7 @@ const Body = styledComponents.styled(designSystem.Box)`
|
|
|
65
70
|
align-items: center;
|
|
66
71
|
justify-content: center;
|
|
67
72
|
overflow: hidden;
|
|
73
|
+
padding: 0 ${({ theme })=>theme.spaces[4]};
|
|
68
74
|
background: repeating-conic-gradient(
|
|
69
75
|
${({ theme })=>theme.colors.neutral100} 0% 25%,
|
|
70
76
|
${({ theme })=>theme.colors.neutral0} 0% 50%
|
|
@@ -95,6 +101,9 @@ const CropOverlay = styledComponents.styled.div`
|
|
|
95
101
|
border: 1px dashed ${({ theme })=>theme.colors.primary600};
|
|
96
102
|
box-shadow: 0 0 0 9999px rgba(33, 33, 52, 0.5);
|
|
97
103
|
cursor: move;
|
|
104
|
+
/* Without this, touch browsers claim the gesture for scrolling and fire
|
|
105
|
+
pointercancel mid-drag — the crop drag dies while the finger is down. */
|
|
106
|
+
touch-action: none;
|
|
98
107
|
`;
|
|
99
108
|
const ResizeHandle = styledComponents.styled.button`
|
|
100
109
|
position: absolute;
|
|
@@ -106,6 +115,7 @@ const ResizeHandle = styledComponents.styled.button`
|
|
|
106
115
|
border-radius: 2px;
|
|
107
116
|
background: ${({ theme })=>theme.colors.neutral0};
|
|
108
117
|
cursor: ${({ $cursor })=>$cursor};
|
|
118
|
+
touch-action: none;
|
|
109
119
|
`;
|
|
110
120
|
const FocalPointHandle = styledComponents.styled.button`
|
|
111
121
|
position: absolute;
|
|
@@ -117,6 +127,7 @@ const FocalPointHandle = styledComponents.styled.button`
|
|
|
117
127
|
background: transparent;
|
|
118
128
|
cursor: grab;
|
|
119
129
|
padding: 0;
|
|
130
|
+
touch-action: none;
|
|
120
131
|
|
|
121
132
|
&::before {
|
|
122
133
|
content: '';
|
|
@@ -201,7 +212,7 @@ const BackgroundPreserveRatio = ()=>/*#__PURE__*/ jsxRuntime.jsx(BackgroundPrese
|
|
|
201
212
|
})
|
|
202
213
|
})
|
|
203
214
|
});
|
|
204
|
-
const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy })=>{
|
|
215
|
+
const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy, canSaveAsCopy })=>{
|
|
205
216
|
const { formatMessage } = reactIntl.useIntl();
|
|
206
217
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
207
218
|
// The InfoBox is a fixed dark surface in both themes, so its text can't use a
|
|
@@ -213,6 +224,14 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
213
224
|
const infoMutedColor = isDark ? 'neutral600' : 'neutral200';
|
|
214
225
|
const imgRef = React__namespace.useRef(null);
|
|
215
226
|
const cropAreaRef = React__namespace.useRef(null);
|
|
227
|
+
const overlayRef = React__namespace.useRef(null);
|
|
228
|
+
// FocusTrap's auto-focus lands on the first focusable element — the crop
|
|
229
|
+
// width NumberInput — which pops the keyboard on mobile the moment the
|
|
230
|
+
// editor opens. Focus the (tabIndex -1) overlay instead: keyboard users are
|
|
231
|
+
// one Tab away from the first control, Escape still reaches the trap.
|
|
232
|
+
React__namespace.useEffect(()=>{
|
|
233
|
+
overlayRef.current?.focus();
|
|
234
|
+
}, []);
|
|
216
235
|
const { init, crop, naturalSize, aspectRatio, setCropSize, setCropPosition, setAspectRatio, produceFile, width, height } = useCropImg.useCropImg();
|
|
217
236
|
const [aspectLocked, setAspectLocked] = React__namespace.useState(false);
|
|
218
237
|
// Focal point as a percentage of the crop area (matches the {x,y} contract).
|
|
@@ -242,40 +261,75 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
242
261
|
y: (event.clientY - rect.top) * ratioY
|
|
243
262
|
};
|
|
244
263
|
};
|
|
245
|
-
//
|
|
246
|
-
|
|
264
|
+
// Teardown for the drag currently in flight, so it can be run both on pointer
|
|
265
|
+
// release AND on unmount. Without the unmount path, closing the editor mid-drag
|
|
266
|
+
// (Escape, drawer close, a re-render dropping the overlay) would never fire a
|
|
267
|
+
// pointer event, leaking the window listeners and letting a stale `onMove`
|
|
268
|
+
// call `setCropPosition` on an unmounted component.
|
|
269
|
+
const activeDragCleanupRef = React__namespace.useRef(null);
|
|
270
|
+
React__namespace.useEffect(()=>{
|
|
271
|
+
return ()=>{
|
|
272
|
+
activeDragCleanupRef.current?.();
|
|
273
|
+
};
|
|
274
|
+
}, []);
|
|
275
|
+
// Track a pointer drag until the pointer is released or the browser cancels
|
|
276
|
+
// it. The pointer is captured so the drag follows the finger even once it
|
|
277
|
+
// leaves the (12px) handle it started on, and pointercancel is treated as
|
|
278
|
+
// release so an interrupted touch never leaves stale window listeners.
|
|
279
|
+
const trackPointerDrag = (event, onMove)=>{
|
|
247
280
|
event.preventDefault();
|
|
248
281
|
event.stopPropagation();
|
|
282
|
+
const { pointerId } = event;
|
|
283
|
+
try {
|
|
284
|
+
event.currentTarget.setPointerCapture(pointerId);
|
|
285
|
+
} catch {
|
|
286
|
+
// Unsupported environment (jsdom) — window listeners still track the drag.
|
|
287
|
+
}
|
|
288
|
+
const move = (e)=>{
|
|
289
|
+
if (e.pointerId !== pointerId) return;
|
|
290
|
+
onMove(e);
|
|
291
|
+
};
|
|
292
|
+
const cleanup = ()=>{
|
|
293
|
+
window.removeEventListener('pointermove', move);
|
|
294
|
+
window.removeEventListener('pointerup', end);
|
|
295
|
+
window.removeEventListener('pointercancel', end);
|
|
296
|
+
activeDragCleanupRef.current = null;
|
|
297
|
+
};
|
|
298
|
+
const end = (e)=>{
|
|
299
|
+
if (e.pointerId !== pointerId) return;
|
|
300
|
+
cleanup();
|
|
301
|
+
};
|
|
302
|
+
// Only one drag is ever live at a time; tear down any previous one first.
|
|
303
|
+
activeDragCleanupRef.current?.();
|
|
304
|
+
activeDragCleanupRef.current = cleanup;
|
|
305
|
+
window.addEventListener('pointermove', move);
|
|
306
|
+
window.addEventListener('pointerup', end);
|
|
307
|
+
window.addEventListener('pointercancel', end);
|
|
308
|
+
};
|
|
309
|
+
// Drag the entire crop rectangle.
|
|
310
|
+
const handleMovePointerDown = (event)=>{
|
|
249
311
|
const start = pointerToNatural(event);
|
|
250
312
|
if (!start) return;
|
|
251
313
|
const startCrop = {
|
|
252
314
|
...crop
|
|
253
315
|
};
|
|
254
|
-
|
|
316
|
+
trackPointerDrag(event, (e)=>{
|
|
255
317
|
const next = pointerToNatural(e);
|
|
256
318
|
if (!next) return;
|
|
257
319
|
setCropPosition({
|
|
258
320
|
x: startCrop.x + (next.x - start.x),
|
|
259
321
|
y: startCrop.y + (next.y - start.y)
|
|
260
322
|
});
|
|
261
|
-
};
|
|
262
|
-
const up = ()=>{
|
|
263
|
-
window.removeEventListener('pointermove', move);
|
|
264
|
-
window.removeEventListener('pointerup', up);
|
|
265
|
-
};
|
|
266
|
-
window.addEventListener('pointermove', move);
|
|
267
|
-
window.addEventListener('pointerup', up);
|
|
323
|
+
});
|
|
268
324
|
};
|
|
269
325
|
// Resize from a corner; the opposite corner stays anchored.
|
|
270
326
|
const handleResizePointerDown = (corner)=>(event)=>{
|
|
271
|
-
event.preventDefault();
|
|
272
|
-
event.stopPropagation();
|
|
273
327
|
const startCrop = {
|
|
274
328
|
...crop
|
|
275
329
|
};
|
|
276
330
|
const anchorX = corner === 'tl' || corner === 'bl' ? startCrop.x + startCrop.width : startCrop.x;
|
|
277
331
|
const anchorY = corner === 'tl' || corner === 'tr' ? startCrop.y + startCrop.height : startCrop.y;
|
|
278
|
-
|
|
332
|
+
trackPointerDrag(event, (e)=>{
|
|
279
333
|
const point = pointerToNatural(e);
|
|
280
334
|
if (!point) return;
|
|
281
335
|
const { x, y, width: w, height: h } = useCropImg.resolveCornerResize({
|
|
@@ -292,13 +346,7 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
292
346
|
width: w,
|
|
293
347
|
height: h
|
|
294
348
|
});
|
|
295
|
-
};
|
|
296
|
-
const up = ()=>{
|
|
297
|
-
window.removeEventListener('pointermove', move);
|
|
298
|
-
window.removeEventListener('pointerup', up);
|
|
299
|
-
};
|
|
300
|
-
window.addEventListener('pointermove', move);
|
|
301
|
-
window.addEventListener('pointerup', up);
|
|
349
|
+
});
|
|
302
350
|
};
|
|
303
351
|
const toggleAspectLock = ()=>{
|
|
304
352
|
setAspectLocked((locked)=>{
|
|
@@ -309,9 +357,7 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
309
357
|
};
|
|
310
358
|
// Drag the focal handle within the crop rectangle, clamped 0–100.
|
|
311
359
|
const handleFocalPointerDown = (event)=>{
|
|
312
|
-
event
|
|
313
|
-
event.stopPropagation();
|
|
314
|
-
const move = (e)=>{
|
|
360
|
+
trackPointerDrag(event, (e)=>{
|
|
315
361
|
const point = pointerToNatural(e);
|
|
316
362
|
if (!point) return;
|
|
317
363
|
// Convert pointer to a percentage of the current crop area.
|
|
@@ -321,13 +367,7 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
321
367
|
x: Math.round(Math.min(100, Math.max(0, px))),
|
|
322
368
|
y: Math.round(Math.min(100, Math.max(0, py)))
|
|
323
369
|
});
|
|
324
|
-
};
|
|
325
|
-
const up = ()=>{
|
|
326
|
-
window.removeEventListener('pointermove', move);
|
|
327
|
-
window.removeEventListener('pointerup', up);
|
|
328
|
-
};
|
|
329
|
-
window.addEventListener('pointermove', move);
|
|
330
|
-
window.addEventListener('pointerup', up);
|
|
370
|
+
});
|
|
331
371
|
};
|
|
332
372
|
const focalPxX = Math.round(focal.x / 100 * width);
|
|
333
373
|
const focalPxY = Math.round(focal.y / 100 * height);
|
|
@@ -377,7 +417,10 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
377
417
|
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Portal, {
|
|
378
418
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.FocusTrap, {
|
|
379
419
|
onEscape: onClose,
|
|
420
|
+
skipAutoFocus: true,
|
|
380
421
|
children: /*#__PURE__*/ jsxRuntime.jsxs(Overlay, {
|
|
422
|
+
ref: overlayRef,
|
|
423
|
+
tabIndex: -1,
|
|
381
424
|
children: [
|
|
382
425
|
/*#__PURE__*/ jsxRuntime.jsxs(HeaderBar, {
|
|
383
426
|
alignItems: "center",
|
|
@@ -666,7 +709,7 @@ const AssetCropEditor = ({ asset, isBusy = false, onClose, onApply, onSaveAsCopy
|
|
|
666
709
|
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
667
710
|
gap: 2,
|
|
668
711
|
children: [
|
|
669
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
712
|
+
canSaveAsCopy && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
670
713
|
variant: "secondary",
|
|
671
714
|
onClick: ()=>handleAction('copy'),
|
|
672
715
|
loading: isBusy,
|