@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.
Files changed (262) hide show
  1. package/dist/admin/components/AssetCard/VideoPreview.js +1 -1
  2. package/dist/admin/components/AssetCard/VideoPreview.js.map +1 -1
  3. package/dist/admin/components/AssetCard/VideoPreview.mjs +1 -1
  4. package/dist/admin/components/AssetCard/VideoPreview.mjs.map +1 -1
  5. package/dist/admin/components/TableList/TableList.js +1 -1
  6. package/dist/admin/components/TableList/TableList.js.map +1 -1
  7. package/dist/admin/components/TableList/TableList.mjs +1 -1
  8. package/dist/admin/components/TableList/TableList.mjs.map +1 -1
  9. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js +21 -4
  10. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js.map +1 -1
  11. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs +21 -4
  12. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs.map +1 -1
  13. package/dist/admin/future/components/Drawer.js +3 -1
  14. package/dist/admin/future/components/Drawer.js.map +1 -1
  15. package/dist/admin/future/components/Drawer.mjs +3 -1
  16. package/dist/admin/future/components/Drawer.mjs.map +1 -1
  17. package/dist/admin/future/components/UploadProgressDialog.js +200 -27
  18. package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
  19. package/dist/admin/future/components/UploadProgressDialog.mjs +203 -30
  20. package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
  21. package/dist/admin/future/hooks/useMediaLibraryPermissions.js +35 -0
  22. package/dist/admin/future/hooks/useMediaLibraryPermissions.js.map +1 -0
  23. package/dist/admin/future/hooks/useMediaLibraryPermissions.mjs +33 -0
  24. package/dist/admin/future/hooks/useMediaLibraryPermissions.mjs.map +1 -0
  25. package/dist/admin/future/pages/Assets/AssetsPage.js +203 -78
  26. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  27. package/dist/admin/future/pages/Assets/AssetsPage.mjs +200 -75
  28. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  29. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +75 -32
  30. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  31. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +75 -32
  32. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  33. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +46 -19
  34. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  35. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +47 -20
  36. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  37. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +5 -2
  38. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
  39. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +5 -2
  40. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  41. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +100 -0
  42. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -0
  43. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +98 -0
  44. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -0
  45. package/dist/admin/future/pages/Assets/components/AssetsTable.js +10 -4
  46. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
  47. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +10 -4
  48. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
  49. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +140 -22
  50. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
  51. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +142 -24
  52. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
  53. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.js +193 -0
  54. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.js.map +1 -0
  55. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.mjs +191 -0
  56. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.mjs.map +1 -0
  57. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +18 -1
  58. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
  59. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +18 -1
  60. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
  61. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js +13 -3
  62. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -1
  63. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +13 -3
  64. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -1
  65. package/dist/admin/future/pages/Assets/components/EmptyState.js +62 -3
  66. package/dist/admin/future/pages/Assets/components/EmptyState.js.map +1 -1
  67. package/dist/admin/future/pages/Assets/components/EmptyState.mjs +62 -4
  68. package/dist/admin/future/pages/Assets/components/EmptyState.mjs.map +1 -1
  69. package/dist/admin/future/pages/Assets/components/FilterBadges.js +408 -0
  70. package/dist/admin/future/pages/Assets/components/FilterBadges.js.map +1 -0
  71. package/dist/admin/future/pages/Assets/components/FilterBadges.mjs +406 -0
  72. package/dist/admin/future/pages/Assets/components/FilterBadges.mjs.map +1 -0
  73. package/dist/admin/future/pages/Assets/components/FilterMenu.js +273 -0
  74. package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -0
  75. package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +267 -0
  76. package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -0
  77. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +76 -19
  78. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  79. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +78 -21
  80. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  81. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js +33 -0
  82. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js.map +1 -0
  83. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs +31 -0
  84. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs.map +1 -0
  85. package/dist/admin/future/pages/Assets/components/SortMenu.js +21 -32
  86. package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
  87. package/dist/admin/future/pages/Assets/components/SortMenu.mjs +22 -33
  88. package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
  89. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.js +40 -0
  90. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.js.map +1 -0
  91. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.mjs +38 -0
  92. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.mjs.map +1 -0
  93. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +21 -5
  94. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  95. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +21 -5
  96. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  97. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.js +33 -12
  98. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.js.map +1 -1
  99. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.mjs +33 -12
  100. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.mjs.map +1 -1
  101. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +40 -4
  102. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
  103. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +40 -4
  104. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
  105. package/dist/admin/future/pages/Assets/hooks/useListFilters.js +168 -0
  106. package/dist/admin/future/pages/Assets/hooks/useListFilters.js.map +1 -0
  107. package/dist/admin/future/pages/Assets/hooks/useListFilters.mjs +162 -0
  108. package/dist/admin/future/pages/Assets/hooks/useListFilters.mjs.map +1 -0
  109. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.js +201 -0
  110. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.js.map +1 -0
  111. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.mjs +198 -0
  112. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.mjs.map +1 -0
  113. package/dist/admin/future/pages/Assets/utils/listQueryKey.js +2 -2
  114. package/dist/admin/future/pages/Assets/utils/listQueryKey.js.map +1 -1
  115. package/dist/admin/future/pages/Assets/utils/listQueryKey.mjs +2 -2
  116. package/dist/admin/future/pages/Assets/utils/listQueryKey.mjs.map +1 -1
  117. package/dist/admin/future/services/api.js +163 -28
  118. package/dist/admin/future/services/api.js.map +1 -1
  119. package/dist/admin/future/services/api.mjs +163 -30
  120. package/dist/admin/future/services/api.mjs.map +1 -1
  121. package/dist/admin/future/services/assets.js +29 -17
  122. package/dist/admin/future/services/assets.js.map +1 -1
  123. package/dist/admin/future/services/assets.mjs +29 -17
  124. package/dist/admin/future/services/assets.mjs.map +1 -1
  125. package/dist/admin/future/services/folders.js +29 -17
  126. package/dist/admin/future/services/folders.js.map +1 -1
  127. package/dist/admin/future/services/folders.mjs +29 -17
  128. package/dist/admin/future/services/folders.mjs.map +1 -1
  129. package/dist/admin/future/services/settings.js +10 -3
  130. package/dist/admin/future/services/settings.js.map +1 -1
  131. package/dist/admin/future/services/settings.mjs +10 -3
  132. package/dist/admin/future/services/settings.mjs.map +1 -1
  133. package/dist/admin/future/store/uploadProgress.js +109 -2
  134. package/dist/admin/future/store/uploadProgress.js.map +1 -1
  135. package/dist/admin/future/store/uploadProgress.mjs +105 -3
  136. package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
  137. package/dist/admin/future/utils/searchQueryParam.js +11 -0
  138. package/dist/admin/future/utils/searchQueryParam.js.map +1 -0
  139. package/dist/admin/future/utils/searchQueryParam.mjs +9 -0
  140. package/dist/admin/future/utils/searchQueryParam.mjs.map +1 -0
  141. package/dist/admin/hooks/useSelectionState.js +2 -4
  142. package/dist/admin/hooks/useSelectionState.js.map +1 -1
  143. package/dist/admin/hooks/useSelectionState.mjs +2 -4
  144. package/dist/admin/hooks/useSelectionState.mjs.map +1 -1
  145. package/dist/admin/shared/constants.js +43 -0
  146. package/dist/admin/shared/constants.js.map +1 -0
  147. package/dist/admin/shared/constants.mjs +38 -0
  148. package/dist/admin/shared/constants.mjs.map +1 -0
  149. package/dist/admin/src/future/hooks/useMediaLibraryPermissions.d.ts +21 -0
  150. package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetCropEditor.d.ts +7 -1
  151. package/dist/admin/src/future/pages/Assets/components/AssetsSearchInput.d.ts +5 -0
  152. package/dist/admin/src/future/pages/Assets/components/BulkActionsBar.d.ts +14 -1
  153. package/dist/admin/src/future/pages/Assets/components/DateRangeCalendar.d.ts +8 -0
  154. package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZoneContext.d.ts +8 -1
  155. package/dist/admin/src/future/pages/Assets/components/EmptyState.d.ts +18 -1
  156. package/dist/admin/src/future/pages/Assets/components/FilterBadges.d.ts +6 -0
  157. package/dist/admin/src/future/pages/Assets/components/FilterMenu.d.ts +22 -0
  158. package/dist/admin/src/future/pages/Assets/components/FolderTree/FolderTree.d.ts +13 -4
  159. package/dist/admin/src/future/pages/Assets/components/FolderTree/filterFolderTree.d.ts +16 -0
  160. package/dist/admin/src/future/pages/Assets/components/SortMenu.d.ts +6 -0
  161. package/dist/admin/src/future/pages/Assets/hooks/useAssetSearch.d.ts +12 -0
  162. package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +8 -1
  163. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +13 -3
  164. package/dist/admin/src/future/pages/Assets/hooks/useListFilters.d.ts +69 -0
  165. package/dist/admin/src/future/pages/Assets/utils/buildAssetFilters.d.ts +46 -0
  166. package/dist/admin/src/future/pages/Assets/utils/listQueryKey.d.ts +3 -4
  167. package/dist/admin/src/future/services/api.d.ts +53 -5
  168. package/dist/admin/src/future/services/assets.d.ts +9 -1
  169. package/dist/admin/src/future/services/folders.d.ts +3 -0
  170. package/dist/admin/src/future/services/settings.d.ts +2 -2
  171. package/dist/admin/src/future/store/uploadProgress.d.ts +83 -1
  172. package/dist/admin/src/future/utils/searchQueryParam.d.ts +7 -0
  173. package/dist/admin/src/hooks/useAiAvailability.d.ts +1 -1
  174. package/dist/admin/src/hooks/useEditAsset.d.ts +4 -4
  175. package/dist/admin/src/hooks/useEditFolder.d.ts +4 -4
  176. package/dist/admin/src/hooks/useSettings.d.ts +1 -0
  177. package/dist/admin/src/hooks/useTracking.d.ts +1 -1
  178. package/dist/admin/src/hooks/useUpload.d.ts +1 -1
  179. package/dist/admin/translations/en.json.js +53 -3
  180. package/dist/admin/translations/en.json.js.map +1 -1
  181. package/dist/admin/translations/en.json.mjs +53 -3
  182. package/dist/admin/translations/en.json.mjs.map +1 -1
  183. package/dist/admin/utils/urlYupSchema.js +33 -9
  184. package/dist/admin/utils/urlYupSchema.js.map +1 -1
  185. package/dist/admin/utils/urlYupSchema.mjs +33 -9
  186. package/dist/admin/utils/urlYupSchema.mjs.map +1 -1
  187. package/dist/server/config.js +13 -5
  188. package/dist/server/config.js.map +1 -1
  189. package/dist/server/config.mjs +13 -5
  190. package/dist/server/config.mjs.map +1 -1
  191. package/dist/server/constants.js.map +1 -1
  192. package/dist/server/constants.mjs.map +1 -1
  193. package/dist/server/controllers/admin-file.js +30 -0
  194. package/dist/server/controllers/admin-file.js.map +1 -1
  195. package/dist/server/controllers/admin-file.mjs +30 -0
  196. package/dist/server/controllers/admin-file.mjs.map +1 -1
  197. package/dist/server/controllers/admin-settings.js +20 -2
  198. package/dist/server/controllers/admin-settings.js.map +1 -1
  199. package/dist/server/controllers/admin-settings.mjs +21 -3
  200. package/dist/server/controllers/admin-settings.mjs.map +1 -1
  201. package/dist/server/controllers/content-api.js +1 -2
  202. package/dist/server/controllers/content-api.js.map +1 -1
  203. package/dist/server/controllers/content-api.mjs +2 -2
  204. package/dist/server/controllers/content-api.mjs.map +1 -1
  205. package/dist/server/controllers/validation/admin/ai-metadata.js +12 -0
  206. package/dist/server/controllers/validation/admin/ai-metadata.js.map +1 -0
  207. package/dist/server/controllers/validation/admin/ai-metadata.mjs +10 -0
  208. package/dist/server/controllers/validation/admin/ai-metadata.mjs.map +1 -0
  209. package/dist/server/controllers/validation/admin/settings.js +4 -1
  210. package/dist/server/controllers/validation/admin/settings.js.map +1 -1
  211. package/dist/server/controllers/validation/admin/settings.mjs +1 -1
  212. package/dist/server/controllers/validation/admin/settings.mjs.map +1 -1
  213. package/dist/server/routes/admin.js +18 -0
  214. package/dist/server/routes/admin.js.map +1 -1
  215. package/dist/server/routes/admin.mjs +18 -0
  216. package/dist/server/routes/admin.mjs.map +1 -1
  217. package/dist/server/services/ai-metadata.js +108 -11
  218. package/dist/server/services/ai-metadata.js.map +1 -1
  219. package/dist/server/services/ai-metadata.mjs +108 -11
  220. package/dist/server/services/ai-metadata.mjs.map +1 -1
  221. package/dist/server/services/file.js +86 -13
  222. package/dist/server/services/file.js.map +1 -1
  223. package/dist/server/services/file.mjs +87 -14
  224. package/dist/server/services/file.mjs.map +1 -1
  225. package/dist/server/services/image-manipulation.js +4 -4
  226. package/dist/server/services/image-manipulation.js.map +1 -1
  227. package/dist/server/services/image-manipulation.mjs +4 -4
  228. package/dist/server/services/image-manipulation.mjs.map +1 -1
  229. package/dist/server/shared/constants.js +43 -0
  230. package/dist/server/shared/constants.js.map +1 -0
  231. package/dist/server/shared/constants.mjs +38 -0
  232. package/dist/server/shared/constants.mjs.map +1 -0
  233. package/dist/server/src/config.d.ts +2 -0
  234. package/dist/server/src/config.d.ts.map +1 -1
  235. package/dist/server/src/constants.d.ts +2 -1
  236. package/dist/server/src/constants.d.ts.map +1 -1
  237. package/dist/server/src/controllers/admin-file.d.ts +10 -0
  238. package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
  239. package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
  240. package/dist/server/src/controllers/index.d.ts +1 -0
  241. package/dist/server/src/controllers/index.d.ts.map +1 -1
  242. package/dist/server/src/controllers/validation/admin/ai-metadata.d.ts +2 -0
  243. package/dist/server/src/controllers/validation/admin/ai-metadata.d.ts.map +1 -0
  244. package/dist/server/src/controllers/validation/admin/settings.d.ts +1 -1
  245. package/dist/server/src/controllers/validation/admin/settings.d.ts.map +1 -1
  246. package/dist/server/src/index.d.ts +7 -1
  247. package/dist/server/src/index.d.ts.map +1 -1
  248. package/dist/server/src/routes/admin.d.ts.map +1 -1
  249. package/dist/server/src/services/ai-metadata.d.ts +19 -0
  250. package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
  251. package/dist/server/src/services/file.d.ts +12 -2
  252. package/dist/server/src/services/file.d.ts.map +1 -1
  253. package/dist/server/src/services/index.d.ts +4 -1
  254. package/dist/server/src/services/index.d.ts.map +1 -1
  255. package/dist/server/src/types.d.ts +3 -0
  256. package/dist/server/src/types.d.ts.map +1 -1
  257. package/dist/shared/constants.d.ts +35 -0
  258. package/dist/shared/constants.d.ts.map +1 -0
  259. package/dist/shared/contracts/files.d.ts +25 -0
  260. package/dist/shared/contracts/files.d.ts.map +1 -1
  261. package/dist/shared/contracts/settings.d.ts +7 -0
  262. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"BulkActionsBar.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/BulkActionsBar.tsx"],"sourcesContent":["import { useState, type MouseEvent } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Box, Button, Dialog, Flex, IconButton, Typography } from '@strapi/design-system';\nimport { ArrowRight, Cross, Sparkle, Trash, WarningCircle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useAIAvailability } from '../../../../hooks/useAiAvailability';\nimport { useBulkDeleteItemsMutation } from '../../../services/assets';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\n\nimport { BulkMoveDialog } from './BulkMoveDialog';\n\n/**\n * Floating bulk action bar for the future Media Library.\n *\n * TODO: create-metadata control is a styled stub (toast on click)\n */\nconst Bar = styled(Flex)`\n position: fixed;\n bottom: ${({ theme }) => theme.spaces[4]};\n left: 50%;\n transform: translateX(-50%);\n z-index: ${({ theme }) => theme.zIndices.popover};\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) =>\n `${theme.spaces[3]} ${theme.spaces[2]} ${theme.spaces[3]} ${theme.spaces[6]}`};\n background: ${({ theme }) => theme.colors.neutral0};\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n`;\n\nconst ActionCluster = styled(Flex)`\n margin-left: auto;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n`;\n\nconst VerticalDivider = styled(Box)`\n width: 1px;\n align-self: stretch;\n background: ${({ theme }) => theme.colors.neutral150};\n margin-left: ${({ theme }) => theme.spaces[1]};\n`;\n\nexport const BulkActionsBar = () => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { isEnabled: isAiMetadataEnabled } = useAIAvailability();\n const { selectedIds, selectedFolderIds, clear } = useAssetSelection();\n const [bulkDeleteItems, { isLoading: isDeleting }] = useBulkDeleteItemsMutation();\n const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);\n const [isMoveDialogOpen, setIsMoveDialogOpen] = useState(false);\n\n const count = selectedIds.size + selectedFolderIds.size;\n\n const showStubNotification = (translationKey: string, defaultMessage: string) => {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: getTranslationKey(translationKey),\n defaultMessage,\n }),\n });\n };\n\n const handleConfirmDelete = async (e: MouseEvent) => {\n // Radix AlertDialog.Action closes the dialog on click by default; prevent\n // that so the dialog stays open showing the loader while the request runs\n // (a bulk delete can take a while depending on the number of assets).\n e.preventDefault();\n\n // Guard re-entry while pending.\n if (isDeleting) {\n return;\n }\n\n const res = await bulkDeleteItems({\n fileIds: Array.from(selectedIds),\n folderIds: Array.from(selectedFolderIds),\n });\n\n if ('error' in res) {\n // Keep the dialog open and the selection intact so the user can retry\n // (Confirm again) or Cancel; only surface the error toast.\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('list.bulk-actions.delete.error'),\n defaultMessage: 'An error occurred while deleting the items.',\n }),\n });\n return;\n }\n\n setIsDeleteDialogOpen(false);\n toggleNotification({\n type: 'success',\n message: formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.delete.success'),\n defaultMessage:\n '{count, plural, =1 {# item has been deleted} other {# items have been deleted}}',\n },\n { count }\n ),\n });\n clear();\n };\n\n if (count === 0) {\n return null;\n }\n\n return (\n <Bar\n tag=\"section\"\n role=\"region\"\n aria-label={formatMessage({\n id: getTranslationKey('list.bulk-actions.label'),\n defaultMessage: 'Bulk actions',\n })}\n >\n <Typography fontWeight=\"bold\" textColor=\"neutral800\" marginRight={4}>\n {formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.selected-count'),\n defaultMessage: '{count, plural, =1 {# item selected} other {# items selected}}',\n },\n { count }\n )}\n </Typography>\n\n <ActionCluster>\n {isAiMetadataEnabled && (\n <Button\n size=\"S\"\n startIcon={<Sparkle />}\n disabled={isDeleting}\n onClick={() =>\n showStubNotification(\n 'list.bulk-actions.create-metadata-not-available',\n \"Generate metadata isn't available yet\"\n )\n }\n >\n {formatMessage({\n id: getTranslationKey('list.bulk-actions.create-metadata'),\n defaultMessage: 'Create metadata',\n })}\n </Button>\n )}\n\n <IconButton\n variant=\"tertiary\"\n disabled={isDeleting}\n label={formatMessage({\n id: getTranslationKey('list.bulk-actions.move'),\n defaultMessage: 'Move',\n })}\n onClick={() => setIsMoveDialogOpen(true)}\n >\n <ArrowRight />\n </IconButton>\n <BulkMoveDialog open={isMoveDialogOpen} onClose={() => setIsMoveDialogOpen(false)} />\n\n <Dialog.Root\n open={isDeleteDialogOpen}\n onOpenChange={(open: boolean) => {\n // The dialog must stay open while the request runs — a bulk delete\n // can't be aborted halfway, so the loader is the source of truth.\n if (!isDeleting) {\n setIsDeleteDialogOpen(open);\n }\n }}\n >\n <Dialog.Trigger>\n <IconButton\n variant=\"danger-light\"\n disabled={isDeleting}\n label={formatMessage({\n id: getTranslationKey('list.bulk-actions.delete'),\n defaultMessage: 'Delete',\n })}\n >\n <Trash />\n </IconButton>\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.delete.confirm.title'),\n defaultMessage: 'Delete {count, plural, =1 {# item} other {# items}}?',\n },\n { count }\n )}\n </Dialog.Header>\n <Dialog.Body\n icon={<WarningCircle width=\"24px\" height=\"24px\" fill=\"danger600\" />}\n textAlign=\"center\"\n >\n <Typography>\n {formatMessage({\n id: getTranslationKey(\n 'list.bulk-actions.delete.confirm.description.are-you-sure'\n ),\n defaultMessage:\n 'These items cannot be recovered once deleted, and deleting a folder also deletes everything inside it. If they are currently in use, linked content will break and image containers will be empty.',\n })}\n </Typography>\n <Typography>\n {formatMessage({\n id: getTranslationKey(\n 'list.bulk-actions.delete.confirm.description.cant-be-undone'\n ),\n defaultMessage:\n 'This action can’t be undone. Deleting a folder also removes everything inside it, and any linked content will break – media asset containers will appear empty.',\n })}\n </Typography>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" disabled={isDeleting} fullWidth>\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button\n variant=\"danger-light\"\n loading={isDeleting}\n onClick={handleConfirmDelete}\n fullWidth\n >\n {formatMessage({\n id: 'app.components.Button.confirm',\n defaultMessage: 'Confirm',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n </ActionCluster>\n\n <VerticalDivider aria-hidden />\n\n <IconButton\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('list.bulk-actions.clear'),\n defaultMessage: 'Clear selection',\n })}\n onClick={clear}\n disabled={isDeleting}\n >\n <Cross />\n </IconButton>\n </Bar>\n );\n};\n"],"names":["Bar","styled","Flex","theme","spaces","zIndices","popover","colors","neutral0","neutral150","borderRadius","shadows","popupShadow","ActionCluster","VerticalDivider","Box","BulkActionsBar","formatMessage","useIntl","toggleNotification","useNotification","isEnabled","isAiMetadataEnabled","useAIAvailability","selectedIds","selectedFolderIds","clear","useAssetSelection","bulkDeleteItems","isLoading","isDeleting","useBulkDeleteItemsMutation","isDeleteDialogOpen","setIsDeleteDialogOpen","useState","isMoveDialogOpen","setIsMoveDialogOpen","count","size","showStubNotification","translationKey","defaultMessage","type","message","id","getTranslationKey","handleConfirmDelete","e","preventDefault","res","fileIds","Array","from","folderIds","_jsxs","tag","role","aria-label","_jsx","Typography","fontWeight","textColor","marginRight","Button","startIcon","Sparkle","disabled","onClick","IconButton","variant","label","ArrowRight","BulkMoveDialog","open","onClose","Dialog","Root","onOpenChange","Trigger","Trash","Content","Header","Body","icon","WarningCircle","width","height","fill","textAlign","Footer","Cancel","fullWidth","Action","loading","aria-hidden","Cross"],"mappings":";;;;;;;;;;;;;AAeA;;;;AAIC,IACD,MAAMA,GAAAA,GAAMC,MAAAA,CAAOC,IAAAA,CAAK;;UAEd,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC;;;WAGhC,EAAE,CAAC,EAAED,KAAK,EAAE,GAAKA,KAAAA,CAAME,QAAQ,CAACC,OAAO,CAAC;;OAE5C,EAAE,CAAC,EAAEH,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC;AAC7B,WAAA,EAAE,CAAC,EAAED,KAAK,EAAE,GACnB,CAAA,EAAGA,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC,CAAC,EAAED,MAAMC,MAAM,CAAC,CAAA,CAAE,CAAC,CAAC,EAAED,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC,CAAC,EAAED,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,EAAE,CAAC;cACpE,EAAE,CAAC,EAAED,KAAK,EAAE,GAAKA,KAAAA,CAAMI,MAAM,CAACC,QAAQ,CAAC;oBACjC,EAAE,CAAC,EAAEL,KAAK,EAAE,GAAKA,KAAAA,CAAMI,MAAM,CAACE,UAAU,CAAC;AAC5C,iBAAA,EAAE,CAAC,EAAEN,KAAK,EAAE,GAAKA,KAAAA,CAAMO,YAAY,CAAC;cACvC,EAAE,CAAC,EAAEP,KAAK,EAAE,GAAKA,KAAAA,CAAMQ,OAAO,CAACC,WAAW,CAAC;AACzD,CAAC;AAED,MAAMC,aAAAA,GAAgBZ,MAAAA,CAAOC,IAAAA,CAAK;;;OAG3B,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC;AACxC,CAAC;AAED,MAAMU,eAAAA,GAAkBb,MAAAA,CAAOc,GAAAA,CAAI;;;cAGrB,EAAE,CAAC,EAAEZ,KAAK,EAAE,GAAKA,KAAAA,CAAMI,MAAM,CAACE,UAAU,CAAC;eACxC,EAAE,CAAC,EAAEN,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC;AAChD,CAAC;MAEYY,cAAAA,GAAiB,IAAA;IAC5B,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;IAC1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,eAAAA,EAAAA;AAC/B,IAAA,MAAM,EAAEC,SAAAA,EAAWC,mBAAmB,EAAE,GAAGC,iBAAAA,EAAAA;AAC3C,IAAA,MAAM,EAAEC,WAAW,EAAEC,iBAAiB,EAAEC,KAAK,EAAE,GAAGC,iBAAAA,EAAAA;AAClD,IAAA,MAAM,CAACC,eAAAA,EAAiB,EAAEC,WAAWC,UAAU,EAAE,CAAC,GAAGC,0BAAAA,EAAAA;AACrD,IAAA,MAAM,CAACC,kBAAAA,EAAoBC,qBAAAA,CAAsB,GAAGC,QAAAA,CAAS,KAAA,CAAA;AAC7D,IAAA,MAAM,CAACC,gBAAAA,EAAkBC,mBAAAA,CAAoB,GAAGF,QAAAA,CAAS,KAAA,CAAA;AAEzD,IAAA,MAAMG,KAAAA,GAAQb,WAAAA,CAAYc,IAAI,GAAGb,kBAAkBa,IAAI;IAEvD,MAAMC,oBAAAA,GAAuB,CAACC,cAAAA,EAAwBC,cAAAA,GAAAA;QACpDtB,kBAAAA,CAAmB;YACjBuB,IAAAA,EAAM,MAAA;AACNC,YAAAA,OAAAA,EAAS1B,aAAAA,CAAc;AACrB2B,gBAAAA,EAAAA,EAAIC,iBAAAA,CAAkBL,cAAAA,CAAAA;AACtBC,gBAAAA;AACF,aAAA;AACF,SAAA,CAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMK,sBAAsB,OAAOC,CAAAA,GAAAA;;;;AAIjCA,QAAAA,CAAAA,CAAEC,cAAc,EAAA;;AAGhB,QAAA,IAAIlB,UAAAA,EAAY;AACd,YAAA;AACF,QAAA;QAEA,MAAMmB,GAAAA,GAAM,MAAMrB,eAAAA,CAAgB;YAChCsB,OAAAA,EAASC,KAAAA,CAAMC,IAAI,CAAC5B,WAAAA,CAAAA;YACpB6B,SAAAA,EAAWF,KAAAA,CAAMC,IAAI,CAAC3B,iBAAAA;AACxB,SAAA,CAAA;AAEA,QAAA,IAAI,WAAWwB,GAAAA,EAAK;;;YAGlB9B,kBAAAA,CAAmB;gBACjBuB,IAAAA,EAAM,QAAA;AACNC,gBAAAA,OAAAA,EAAS1B,aAAAA,CAAc;AACrB2B,oBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,gCAAA,CAAA;oBACtBJ,cAAAA,EAAgB;AAClB,iBAAA;AACF,aAAA,CAAA;AACA,YAAA;AACF,QAAA;QAEAR,qBAAAA,CAAsB,KAAA,CAAA;QACtBd,kBAAAA,CAAmB;YACjBuB,IAAAA,EAAM,SAAA;AACNC,YAAAA,OAAAA,EAAS1B,aAAAA,CACP;AACE2B,gBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,kCAAA,CAAA;gBACtBJ,cAAAA,EACE;aACJ,EACA;AAAEJ,gBAAAA;AAAM,aAAA;AAEZ,SAAA,CAAA;AACAX,QAAAA,KAAAA,EAAAA;AACF,IAAA,CAAA;AAEA,IAAA,IAAIW,UAAU,CAAA,EAAG;QACf,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,qBACEiB,IAAA,CAACtD,GAAAA,EAAAA;QACCuD,GAAAA,EAAI,SAAA;QACJC,IAAAA,EAAK,QAAA;AACLC,QAAAA,YAAAA,EAAYxC,aAAAA,CAAc;AACxB2B,YAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,yBAAA,CAAA;YACtBJ,cAAAA,EAAgB;AAClB,SAAA,CAAA;;0BAEAiB,GAAA,CAACC,UAAAA,EAAAA;gBAAWC,UAAAA,EAAW,MAAA;gBAAOC,SAAAA,EAAU,YAAA;gBAAaC,WAAAA,EAAa,CAAA;0BAC/D7C,aAAAA,CACC;AACE2B,oBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,kCAAA,CAAA;oBACtBJ,cAAAA,EAAgB;iBAClB,EACA;AAAEJ,oBAAAA;AAAM,iBAAA;;0BAIZiB,IAAA,CAACzC,aAAAA,EAAAA;;AACES,oBAAAA,mBAAAA,kBACCoC,GAAA,CAACK,MAAAA,EAAAA;wBACCzB,IAAAA,EAAK,GAAA;AACL0B,wBAAAA,SAAAA,gBAAWN,GAAA,CAACO,OAAAA,EAAAA,EAAAA,CAAAA;wBACZC,QAAAA,EAAUpC,UAAAA;wBACVqC,OAAAA,EAAS,IACP5B,qBACE,iDAAA,EACA,uCAAA,CAAA;kCAIHtB,aAAAA,CAAc;AACb2B,4BAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,mCAAA,CAAA;4BACtBJ,cAAAA,EAAgB;AAClB,yBAAA;;kCAIJiB,GAAA,CAACU,UAAAA,EAAAA;wBACCC,OAAAA,EAAQ,UAAA;wBACRH,QAAAA,EAAUpC,UAAAA;AACVwC,wBAAAA,KAAAA,EAAOrD,aAAAA,CAAc;AACnB2B,4BAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,wBAAA,CAAA;4BACtBJ,cAAAA,EAAgB;AAClB,yBAAA,CAAA;AACA0B,wBAAAA,OAAAA,EAAS,IAAM/B,mBAAAA,CAAoB,IAAA,CAAA;AAEnC,wBAAA,QAAA,gBAAAsB,GAAA,CAACa,UAAAA,EAAAA,EAAAA;;kCAEHb,GAAA,CAACc,cAAAA,EAAAA;wBAAeC,IAAAA,EAAMtC,gBAAAA;AAAkBuC,wBAAAA,OAAAA,EAAS,IAAMtC,mBAAAA,CAAoB,KAAA;;AAE3E,kCAAAkB,IAAA,CAACqB,OAAOC,IAAI,EAAA;wBACVH,IAAAA,EAAMzC,kBAAAA;AACN6C,wBAAAA,YAAAA,EAAc,CAACJ,IAAAA,GAAAA;;;AAGb,4BAAA,IAAI,CAAC3C,UAAAA,EAAY;gCACfG,qBAAAA,CAAsBwC,IAAAA,CAAAA;AACxB,4BAAA;AACF,wBAAA,CAAA;;AAEA,0CAAAf,GAAA,CAACiB,OAAOG,OAAO,EAAA;AACb,gCAAA,QAAA,gBAAApB,GAAA,CAACU,UAAAA,EAAAA;oCACCC,OAAAA,EAAQ,cAAA;oCACRH,QAAAA,EAAUpC,UAAAA;AACVwC,oCAAAA,KAAAA,EAAOrD,aAAAA,CAAc;AACnB2B,wCAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,0BAAA,CAAA;wCACtBJ,cAAAA,EAAgB;AAClB,qCAAA,CAAA;AAEA,oCAAA,QAAA,gBAAAiB,GAAA,CAACqB,KAAAA,EAAAA,EAAAA;;;AAGL,0CAAAzB,IAAA,CAACqB,OAAOK,OAAO,EAAA;;AACb,kDAAAtB,GAAA,CAACiB,OAAOM,MAAM,EAAA;kDACXhE,aAAAA,CACC;AACE2B,4CAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,wCAAA,CAAA;4CACtBJ,cAAAA,EAAgB;yCAClB,EACA;AAAEJ,4CAAAA;AAAM,yCAAA;;AAGZ,kDAAAiB,IAAA,CAACqB,OAAOO,IAAI,EAAA;AACVC,wCAAAA,IAAAA,gBAAMzB,GAAA,CAAC0B,aAAAA,EAAAA;4CAAcC,KAAAA,EAAM,MAAA;4CAAOC,MAAAA,EAAO,MAAA;4CAAOC,IAAAA,EAAK;;wCACrDC,SAAAA,EAAU,QAAA;;0DAEV9B,GAAA,CAACC,UAAAA,EAAAA;0DACE1C,aAAAA,CAAc;AACb2B,oDAAAA,EAAAA,EAAIC,iBAAAA,CACF,2DAAA,CAAA;oDAEFJ,cAAAA,EACE;AACJ,iDAAA;;0DAEFiB,GAAA,CAACC,UAAAA,EAAAA;0DACE1C,aAAAA,CAAc;AACb2B,oDAAAA,EAAAA,EAAIC,iBAAAA,CACF,6DAAA,CAAA;oDAEFJ,cAAAA,EACE;AACJ,iDAAA;;;;AAGJ,kDAAAa,IAAA,CAACqB,OAAOc,MAAM,EAAA;;AACZ,0DAAA/B,GAAA,CAACiB,OAAOe,MAAM,EAAA;AACZ,gDAAA,QAAA,gBAAAhC,GAAA,CAACK,MAAAA,EAAAA;oDAAOM,OAAAA,EAAQ,UAAA;oDAAWH,QAAAA,EAAUpC,UAAAA;oDAAY6D,SAAS,EAAA,IAAA;8DACvD1E,aAAAA,CAAc;wDAAE2B,EAAAA,EAAI,8BAAA;wDAAgCH,cAAAA,EAAgB;AAAS,qDAAA;;;AAGlF,0DAAAiB,GAAA,CAACiB,OAAOiB,MAAM,EAAA;AACZ,gDAAA,QAAA,gBAAAlC,GAAA,CAACK,MAAAA,EAAAA;oDACCM,OAAAA,EAAQ,cAAA;oDACRwB,OAAAA,EAAS/D,UAAAA;oDACTqC,OAAAA,EAASrB,mBAAAA;oDACT6C,SAAS,EAAA,IAAA;8DAER1E,aAAAA,CAAc;wDACb2B,EAAAA,EAAI,+BAAA;wDACJH,cAAAA,EAAgB;AAClB,qDAAA;;;;;;;;;;;0BAQZiB,GAAA,CAAC5C,eAAAA,EAAAA;gBAAgBgF,aAAW,EAAA;;0BAE5BpC,GAAA,CAACU,UAAAA,EAAAA;gBACCC,OAAAA,EAAQ,OAAA;AACRC,gBAAAA,KAAAA,EAAOrD,aAAAA,CAAc;AACnB2B,oBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,yBAAA,CAAA;oBACtBJ,cAAAA,EAAgB;AAClB,iBAAA,CAAA;gBACA0B,OAAAA,EAASzC,KAAAA;gBACTwC,QAAAA,EAAUpC,UAAAA;AAEV,gBAAA,QAAA,gBAAA4B,GAAA,CAACqC,KAAAA,EAAAA,EAAAA;;;;AAIT;;;;"}
1
+ {"version":3,"file":"BulkActionsBar.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/BulkActionsBar.tsx"],"sourcesContent":["import { useMemo, useState, type MouseEvent } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Box, Button, Dialog, Flex, IconButton, Tooltip, Typography } from '@strapi/design-system';\nimport { ArrowRight, Cross, Sparkle, Trash, WarningCircle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport {\n AI_METADATA_MAX_FILES,\n isAIMetadataSupportedMime,\n} from '../../../../../../shared/constants';\nimport { useAIAvailability } from '../../../../hooks/useAiAvailability';\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport {\n useBulkDeleteItemsMutation,\n useGenerateAiMetadataMutation,\n} from '../../../services/assets';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\n\nimport { BulkMoveDialog } from './BulkMoveDialog';\n\nimport type { File } from '../../../../../../shared/contracts/files';\n\n/**\n * Floating bulk action bar for the future Media Library.\n */\nconst Bar = styled(Flex)`\n position: fixed;\n bottom: ${({ theme }) => theme.spaces[4]};\n left: 50%;\n transform: translateX(-50%);\n z-index: ${({ theme }) => theme.zIndices.popover};\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) =>\n `${theme.spaces[3]} ${theme.spaces[2]} ${theme.spaces[3]} ${theme.spaces[6]}`};\n background: ${({ theme }) => theme.colors.neutral0};\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n`;\n\nconst ActionCluster = styled(Flex)`\n margin-left: auto;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n`;\n\nconst VerticalDivider = styled(Box)`\n width: 1px;\n align-self: stretch;\n background: ${({ theme }) => theme.colors.neutral150};\n margin-left: ${({ theme }) => theme.spaces[1]};\n`;\n\ninterface BulkActionsBarProps {\n /**\n * The assets currently rendered in the list, used to resolve the mime types\n * of the selection — the bar needs them to know which selected assets the AI\n * provider can actually read.\n *\n * Selection is page-scoped and cleared whenever the list identity changes, so\n * every selected asset id is guaranteed to appear here.\n */\n assets?: File[];\n}\n\nexport const BulkActionsBar = ({ assets = [] }: BulkActionsBarProps) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { isEnabled: isAiMetadataEnabled } = useAIAvailability();\n // Every bulk action (move, delete, metadata) is an `assets.update` mutation\n // server-side — one flag gates the whole cluster.\n const { canUpdate } = useMediaLibraryPermissions();\n const { selectedIds, selectedFolderIds, clear } = useAssetSelection();\n const [bulkDeleteItems, { isLoading: isDeleting }] = useBulkDeleteItemsMutation();\n const [generateAiMetadata, { isLoading: isGeneratingMetadata }] = useGenerateAiMetadataMutation();\n const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);\n const [isMoveDialogOpen, setIsMoveDialogOpen] = useState(false);\n\n const count = selectedIds.size + selectedFolderIds.size;\n const isBusy = isDeleting || isGeneratingMetadata;\n\n /**\n * The server processes the whole selection inside a single request and\n * rejects anything above the cap with a 400. Disable the action up front so\n * the limit is discoverable before the user commits to a request.\n */\n const isOverMetadataLimit = selectedIds.size > AI_METADATA_MAX_FILES;\n\n /**\n * How many selected assets the AI provider can actually read. The server\n * stays authoritative — it still reports what it skipped — but a selection\n * with nothing eligible (a lone PDF, say) would only ever come back fully\n * skipped, so there is no point sending it.\n */\n const eligibleCount = useMemo(() => {\n const mimeById = new Map(assets.map(({ id, mime }) => [id, mime]));\n\n return [...selectedIds].filter((id) => isAIMetadataSupportedMime(mimeById.get(id))).length;\n }, [assets, selectedIds]);\n\n const hasNoEligibleAssets = selectedIds.size > 0 && eligibleCount === 0;\n\n /**\n * Why the action is unavailable, surfaced on hover. `undefined` leaves the\n * button without a tooltip — either it is usable, or it is disabled for a\n * reason the selection count already makes obvious.\n */\n let metadataDisabledReason: string | undefined;\n\n if (isOverMetadataLimit) {\n metadataDisabledReason = formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.create-metadata.too-many'),\n defaultMessage:\n 'Metadata can be generated for up to {max} assets at a time. Select fewer assets to continue.',\n },\n { max: AI_METADATA_MAX_FILES }\n );\n } else if (hasNoEligibleAssets) {\n metadataDisabledReason = formatMessage({\n id: getTranslationKey('list.bulk-actions.create-metadata.no-eligible'),\n defaultMessage:\n 'Metadata can only be generated for images. None of the selected assets are supported.',\n });\n }\n\n /**\n * Metadata generation only applies to images — folders and unsupported files\n * in the selection are reported back rather than blocking the action.\n */\n const handleCreateMetadata = async () => {\n // Guard re-entry while pending, and never send a selection the server\n // would reject outright or skip in full.\n if (isGeneratingMetadata || isOverMetadataLimit || hasNoEligibleAssets) {\n return;\n }\n\n const fileIds = Array.from(selectedIds);\n const res = await generateAiMetadata({ fileIds });\n\n if ('error' in res) {\n // Keep the selection intact so the user can retry.\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('list.bulk-actions.create-metadata.error'),\n defaultMessage: 'An error occurred while generating metadata.',\n }),\n });\n return;\n }\n\n const successCount = res.data.filter(({ status }) => status === 'success').length;\n const skippedCount = res.data.filter(({ status }) => status === 'skipped').length;\n const errorCount = res.data.filter(({ status }) => status === 'error').length;\n // Folders are never sent, so they are not part of the response — but the\n // user selected them, and a silent omission reads as a bug.\n const folderCount = selectedFolderIds.size;\n\n if (errorCount === res.data.length) {\n // Nothing was written — treat it like a request-level failure and keep\n // the selection so the user can retry.\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('list.bulk-actions.create-metadata.error'),\n defaultMessage: 'An error occurred while generating metadata.',\n }),\n });\n return;\n }\n\n if (skippedCount === 0 && errorCount === 0 && folderCount === 0) {\n toggleNotification({\n type: 'success',\n message: formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.create-metadata.success'),\n defaultMessage:\n '{count, plural, =1 {Metadata generated for # asset} other {Metadata generated for # assets}}',\n },\n { count: successCount }\n ),\n });\n } else {\n // Partial outcome: report every bucket so the user knows what was left\n // out — including folders, which were never eligible in the first place.\n toggleNotification({\n type: 'warning',\n message: formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.create-metadata.partial'),\n defaultMessage:\n '{successCount} generated, {skippedCount} skipped (unsupported file type), {errorCount} failed{folderCount, plural, =0 {} one {, # folder ignored} other {, # folders ignored}}',\n },\n { successCount, skippedCount, errorCount, folderCount }\n ),\n });\n }\n\n clear();\n };\n\n const handleConfirmDelete = async (e: MouseEvent) => {\n // Radix AlertDialog.Action closes the dialog on click by default; prevent\n // that so the dialog stays open showing the loader while the request runs\n // (a bulk delete can take a while depending on the number of assets).\n e.preventDefault();\n\n // Guard re-entry while pending.\n if (isDeleting) {\n return;\n }\n\n const res = await bulkDeleteItems({\n fileIds: Array.from(selectedIds),\n folderIds: Array.from(selectedFolderIds),\n });\n\n if ('error' in res) {\n // Keep the dialog open and the selection intact so the user can retry\n // (Confirm again) or Cancel; only surface the error toast.\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('list.bulk-actions.delete.error'),\n defaultMessage: 'An error occurred while deleting the items.',\n }),\n });\n return;\n }\n\n setIsDeleteDialogOpen(false);\n toggleNotification({\n type: 'success',\n message: formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.delete.success'),\n defaultMessage:\n '{count, plural, =1 {# item has been deleted} other {# items have been deleted}}',\n },\n { count }\n ),\n });\n clear();\n };\n\n // Every bulk action is behind `assets.update`; with nothing selected, or\n // without the permission, the bar has nothing to offer — drop it entirely\n // rather than show a count + \"Clear selection\" over no actions (mirrors the\n // drawer footer, which hides when no permitted action survives).\n if (count === 0 || !canUpdate) {\n return null;\n }\n\n return (\n <Bar\n tag=\"section\"\n role=\"region\"\n aria-label={formatMessage({\n id: getTranslationKey('list.bulk-actions.label'),\n defaultMessage: 'Bulk actions',\n })}\n >\n <Typography fontWeight=\"bold\" textColor=\"neutral800\" marginRight={4}>\n {formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.selected-count'),\n defaultMessage: '{count, plural, =1 {# item selected} other {# items selected}}',\n },\n { count }\n )}\n </Typography>\n\n {/* Past the early return the user always has `assets.update`, so the\n individual actions no longer re-check it. */}\n <ActionCluster>\n {isAiMetadataEnabled && (\n <Tooltip label={metadataDisabledReason}>\n {/* Wrapped so the tooltip still receives pointer events while the\n button itself is disabled. */}\n <Box>\n <Button\n size=\"S\"\n startIcon={<Sparkle />}\n disabled={\n isBusy || selectedIds.size === 0 || isOverMetadataLimit || hasNoEligibleAssets\n }\n loading={isGeneratingMetadata}\n onClick={handleCreateMetadata}\n >\n {formatMessage({\n id: getTranslationKey('list.bulk-actions.create-metadata'),\n defaultMessage: 'Create metadata',\n })}\n </Button>\n </Box>\n </Tooltip>\n )}\n\n <IconButton\n variant=\"tertiary\"\n disabled={isBusy}\n label={formatMessage({\n id: getTranslationKey('list.bulk-actions.move'),\n defaultMessage: 'Move',\n })}\n onClick={() => setIsMoveDialogOpen(true)}\n >\n <ArrowRight />\n </IconButton>\n <BulkMoveDialog open={isMoveDialogOpen} onClose={() => setIsMoveDialogOpen(false)} />\n\n <Dialog.Root\n open={isDeleteDialogOpen}\n onOpenChange={(open: boolean) => {\n // The dialog must stay open while the request runs — a bulk delete\n // can't be aborted halfway, so the loader is the source of truth.\n if (!isDeleting) {\n setIsDeleteDialogOpen(open);\n }\n }}\n >\n <Dialog.Trigger>\n <IconButton\n variant=\"danger-light\"\n disabled={isBusy}\n label={formatMessage({\n id: getTranslationKey('list.bulk-actions.delete'),\n defaultMessage: 'Delete',\n })}\n >\n <Trash />\n </IconButton>\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage(\n {\n id: getTranslationKey('list.bulk-actions.delete.confirm.title'),\n defaultMessage: 'Delete {count, plural, =1 {# item} other {# items}}?',\n },\n { count }\n )}\n </Dialog.Header>\n <Dialog.Body\n icon={<WarningCircle width=\"24px\" height=\"24px\" fill=\"danger600\" />}\n textAlign=\"center\"\n >\n <Typography>\n {formatMessage({\n id: getTranslationKey(\n 'list.bulk-actions.delete.confirm.description.are-you-sure'\n ),\n defaultMessage:\n 'These items cannot be recovered once deleted, and deleting a folder also deletes everything inside it. If they are currently in use, linked content will break and image containers will be empty.',\n })}\n </Typography>\n <Typography>\n {formatMessage({\n id: getTranslationKey(\n 'list.bulk-actions.delete.confirm.description.cant-be-undone'\n ),\n defaultMessage:\n 'This action can’t be undone. Deleting a folder also removes everything inside it, and any linked content will break – media asset containers will appear empty.',\n })}\n </Typography>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" disabled={isDeleting} fullWidth>\n {formatMessage({\n id: 'app.components.Button.cancel',\n defaultMessage: 'Cancel',\n })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button\n variant=\"danger-light\"\n loading={isDeleting}\n onClick={handleConfirmDelete}\n fullWidth\n >\n {formatMessage({\n id: 'app.components.Button.confirm',\n defaultMessage: 'Confirm',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n </ActionCluster>\n\n <VerticalDivider aria-hidden />\n\n <IconButton\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('list.bulk-actions.clear'),\n defaultMessage: 'Clear selection',\n })}\n onClick={clear}\n disabled={isBusy}\n >\n <Cross />\n </IconButton>\n </Bar>\n );\n};\n"],"names":["Bar","styled","Flex","theme","spaces","zIndices","popover","colors","neutral0","neutral150","borderRadius","shadows","popupShadow","ActionCluster","VerticalDivider","Box","BulkActionsBar","assets","formatMessage","useIntl","toggleNotification","useNotification","isEnabled","isAiMetadataEnabled","useAIAvailability","canUpdate","useMediaLibraryPermissions","selectedIds","selectedFolderIds","clear","useAssetSelection","bulkDeleteItems","isLoading","isDeleting","useBulkDeleteItemsMutation","generateAiMetadata","isGeneratingMetadata","useGenerateAiMetadataMutation","isDeleteDialogOpen","setIsDeleteDialogOpen","useState","isMoveDialogOpen","setIsMoveDialogOpen","count","size","isBusy","isOverMetadataLimit","AI_METADATA_MAX_FILES","eligibleCount","useMemo","mimeById","Map","map","id","mime","filter","isAIMetadataSupportedMime","get","length","hasNoEligibleAssets","metadataDisabledReason","getTranslationKey","defaultMessage","max","handleCreateMetadata","fileIds","Array","from","res","type","message","successCount","data","status","skippedCount","errorCount","folderCount","handleConfirmDelete","e","preventDefault","folderIds","_jsxs","tag","role","aria-label","_jsx","Typography","fontWeight","textColor","marginRight","Tooltip","label","Button","startIcon","Sparkle","disabled","loading","onClick","IconButton","variant","ArrowRight","BulkMoveDialog","open","onClose","Dialog","Root","onOpenChange","Trigger","Trash","Content","Header","Body","icon","WarningCircle","width","height","fill","textAlign","Footer","Cancel","fullWidth","Action","aria-hidden","Cross"],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var designSystem = require('@strapi/design-system');
6
+ var icons = require('@strapi/icons');
7
+ var reactIntl = require('react-intl');
8
+ var styledComponents = require('styled-components');
9
+ var translations = require('../../../utils/translations.js');
10
+
11
+ /**
12
+ * Month-grid range picker: first click sets the start, second click the end
13
+ * (clicks are reordered when the second date is before the first). The DS only
14
+ * ships a single-value DatePicker, so the range grid is built locally.
15
+ *
16
+ * Month/year move via chevrons rather than the mock's dropdowns — nested
17
+ * popovers inside a dropdown menu fight Radix's outside-interaction handling.
18
+ */ const DayCell = styledComponents.styled.button`
19
+ width: 3rem;
20
+ height: 3rem;
21
+ border: none;
22
+ border-radius: ${({ theme })=>theme.borderRadius};
23
+ cursor: pointer;
24
+ font: inherit;
25
+ color: ${({ theme, $isEdge, $isMuted })=>{
26
+ if ($isEdge) return theme.colors.primary600;
27
+ if ($isMuted) return theme.colors.neutral400;
28
+ return theme.colors.neutral800;
29
+ }};
30
+ background: ${({ theme, $inRange, $isEdge })=>{
31
+ if ($isEdge) return theme.colors.primary200;
32
+ if ($inRange) return theme.colors.primary100;
33
+ return 'transparent';
34
+ }};
35
+
36
+ &:hover {
37
+ background: ${({ theme })=>theme.colors.primary100};
38
+ }
39
+
40
+ &:focus-visible {
41
+ outline: 2px solid ${({ theme })=>theme.colors.primary600};
42
+ outline-offset: -2px;
43
+ }
44
+ `;
45
+ const toKey = (date)=>{
46
+ const month = `${date.getMonth() + 1}`.padStart(2, '0');
47
+ const day = `${date.getDate()}`.padStart(2, '0');
48
+ return `${date.getFullYear()}-${month}-${day}`;
49
+ };
50
+ const fromKey = (key)=>{
51
+ const [year, month, day] = key.split('-').map(Number);
52
+ return new Date(year, month - 1, day);
53
+ };
54
+ /** Monday-first weeks covering the given month, padded with adjacent days. */ const buildWeeks = (year, month)=>{
55
+ const first = new Date(year, month, 1);
56
+ const start = new Date(first.getTime());
57
+ start.setDate(first.getDate() - (first.getDay() + 6) % 7);
58
+ const weeks = [];
59
+ const cursor = new Date(start.getTime());
60
+ do {
61
+ const week = [];
62
+ for(let i = 0; i < 7; i += 1){
63
+ week.push(new Date(cursor.getTime()));
64
+ cursor.setDate(cursor.getDate() + 1);
65
+ }
66
+ weeks.push(week);
67
+ }while (cursor.getMonth() === month && cursor.getFullYear() === year)
68
+ return weeks;
69
+ };
70
+ const DateRangeCalendar = ({ from, to, onSelect })=>{
71
+ const { formatMessage, formatDate } = reactIntl.useIntl();
72
+ const initialMonth = from ? fromKey(from) : new Date();
73
+ const [viewYear, setViewYear] = React.useState(initialMonth.getFullYear());
74
+ const [viewMonth, setViewMonth] = React.useState(initialMonth.getMonth());
75
+ // In-progress selection: set on the first click, cleared on commit.
76
+ const [pendingStart, setPendingStart] = React.useState(null);
77
+ const rangeStart = pendingStart ?? from ?? null;
78
+ const rangeEnd = pendingStart ? null : to ?? null;
79
+ const moveMonth = (delta)=>{
80
+ const next = new Date(viewYear, viewMonth + delta, 1);
81
+ setViewYear(next.getFullYear());
82
+ setViewMonth(next.getMonth());
83
+ };
84
+ const handleDayClick = (day)=>{
85
+ const key = toKey(day);
86
+ if (!pendingStart) {
87
+ setPendingStart(key);
88
+ return;
89
+ }
90
+ const [start, end] = key < pendingStart ? [
91
+ key,
92
+ pendingStart
93
+ ] : [
94
+ pendingStart,
95
+ key
96
+ ];
97
+ setPendingStart(null);
98
+ onSelect(start, end);
99
+ };
100
+ const weeks = buildWeeks(viewYear, viewMonth);
101
+ const weekDayLabels = weeks[0].map((day)=>formatDate(day, {
102
+ weekday: 'short'
103
+ }).slice(0, 2));
104
+ return(// role="group" (not "application"): these are plain buttons — hijacking
105
+ // the screen reader's own key handling would take away navigation and
106
+ // give nothing back.
107
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
108
+ padding: 2,
109
+ width: "100%",
110
+ role: "group",
111
+ "aria-label": formatMessage({
112
+ id: translations.getTranslationKey('list.filters.calendar.label'),
113
+ defaultMessage: 'Select date range'
114
+ }),
115
+ "data-testid": "date-range-calendar",
116
+ children: [
117
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
118
+ justifyContent: "space-between",
119
+ alignItems: "center",
120
+ paddingBottom: 2,
121
+ children: [
122
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
123
+ variant: "ghost",
124
+ label: formatMessage({
125
+ id: translations.getTranslationKey('list.filters.calendar.previous-month'),
126
+ defaultMessage: 'Previous month'
127
+ }),
128
+ onClick: ()=>moveMonth(-1),
129
+ children: /*#__PURE__*/ jsxRuntime.jsx(icons.ChevronLeft, {})
130
+ }),
131
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
132
+ fontWeight: "semiBold",
133
+ textColor: "neutral800",
134
+ children: formatDate(new Date(viewYear, viewMonth, 1), {
135
+ month: 'long',
136
+ year: 'numeric'
137
+ })
138
+ }),
139
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
140
+ variant: "ghost",
141
+ label: formatMessage({
142
+ id: translations.getTranslationKey('list.filters.calendar.next-month'),
143
+ defaultMessage: 'Next month'
144
+ }),
145
+ onClick: ()=>moveMonth(1),
146
+ children: /*#__PURE__*/ jsxRuntime.jsx(icons.ChevronRight, {})
147
+ })
148
+ ]
149
+ }),
150
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
151
+ children: weekDayLabels.map((label, index)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
152
+ width: "3rem",
153
+ height: "2.4rem",
154
+ justifyContent: "center",
155
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
156
+ variant: "pi",
157
+ fontWeight: "semiBold",
158
+ textColor: "neutral600",
159
+ children: label
160
+ })
161
+ }, index))
162
+ }),
163
+ weeks.map((week, weekIndex)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
164
+ children: week.map((day)=>{
165
+ const key = toKey(day);
166
+ const isEdge = key === rangeStart || key === rangeEnd;
167
+ const inRange = rangeStart !== null && rangeEnd !== null && key > rangeStart && key < rangeEnd;
168
+ return /*#__PURE__*/ jsxRuntime.jsxs(DayCell, {
169
+ type: "button",
170
+ $isEdge: isEdge,
171
+ $inRange: inRange,
172
+ $isMuted: day.getMonth() !== viewMonth,
173
+ onClick: ()=>handleDayClick(day),
174
+ children: [
175
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
176
+ children: formatDate(day, {
177
+ dateStyle: 'long'
178
+ })
179
+ }),
180
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
181
+ "aria-hidden": true,
182
+ children: day.getDate()
183
+ })
184
+ ]
185
+ }, key);
186
+ })
187
+ }, weekIndex))
188
+ ]
189
+ }));
190
+ };
191
+
192
+ exports.DateRangeCalendar = DateRangeCalendar;
193
+ //# sourceMappingURL=DateRangeCalendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateRangeCalendar.js","sources":["../../../../../../admin/src/future/pages/Assets/components/DateRangeCalendar.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { Box, Flex, IconButton, Typography, VisuallyHidden } from '@strapi/design-system';\nimport { ChevronLeft, ChevronRight } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../utils/translations';\n\n/**\n * Month-grid range picker: first click sets the start, second click the end\n * (clicks are reordered when the second date is before the first). The DS only\n * ships a single-value DatePicker, so the range grid is built locally.\n *\n * Month/year move via chevrons rather than the mock's dropdowns — nested\n * popovers inside a dropdown menu fight Radix's outside-interaction handling.\n */\n\nconst DayCell = styled.button<{ $inRange?: boolean; $isEdge?: boolean; $isMuted?: boolean }>`\n width: 3rem;\n height: 3rem;\n border: none;\n border-radius: ${({ theme }) => theme.borderRadius};\n cursor: pointer;\n font: inherit;\n color: ${({ theme, $isEdge, $isMuted }) => {\n if ($isEdge) return theme.colors.primary600;\n if ($isMuted) return theme.colors.neutral400;\n return theme.colors.neutral800;\n }};\n background: ${({ theme, $inRange, $isEdge }) => {\n if ($isEdge) return theme.colors.primary200;\n if ($inRange) return theme.colors.primary100;\n return 'transparent';\n }};\n\n &:hover {\n background: ${({ theme }) => theme.colors.primary100};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n`;\n\nconst toKey = (date: Date): string => {\n const month = `${date.getMonth() + 1}`.padStart(2, '0');\n const day = `${date.getDate()}`.padStart(2, '0');\n return `${date.getFullYear()}-${month}-${day}`;\n};\n\nconst fromKey = (key: string): Date => {\n const [year, month, day] = key.split('-').map(Number);\n return new Date(year, month - 1, day);\n};\n\n/** Monday-first weeks covering the given month, padded with adjacent days. */\nconst buildWeeks = (year: number, month: number): Date[][] => {\n const first = new Date(year, month, 1);\n const start = new Date(first.getTime());\n start.setDate(first.getDate() - ((first.getDay() + 6) % 7));\n\n const weeks: Date[][] = [];\n const cursor = new Date(start.getTime());\n\n do {\n const week: Date[] = [];\n for (let i = 0; i < 7; i += 1) {\n week.push(new Date(cursor.getTime()));\n cursor.setDate(cursor.getDate() + 1);\n }\n weeks.push(week);\n } while (cursor.getMonth() === month && cursor.getFullYear() === year);\n\n return weeks;\n};\n\ninterface DateRangeCalendarProps {\n /** `YYYY-MM-DD`, both set when editing an existing range badge. */\n from?: string;\n to?: string;\n onSelect: (from: string, to: string) => void;\n}\n\nexport const DateRangeCalendar = ({ from, to, onSelect }: DateRangeCalendarProps) => {\n const { formatMessage, formatDate } = useIntl();\n\n const initialMonth = from ? fromKey(from) : new Date();\n const [viewYear, setViewYear] = useState(initialMonth.getFullYear());\n const [viewMonth, setViewMonth] = useState(initialMonth.getMonth());\n // In-progress selection: set on the first click, cleared on commit.\n const [pendingStart, setPendingStart] = useState<string | null>(null);\n\n const rangeStart = pendingStart ?? from ?? null;\n const rangeEnd = pendingStart ? null : (to ?? null);\n\n const moveMonth = (delta: number) => {\n const next = new Date(viewYear, viewMonth + delta, 1);\n setViewYear(next.getFullYear());\n setViewMonth(next.getMonth());\n };\n\n const handleDayClick = (day: Date) => {\n const key = toKey(day);\n\n if (!pendingStart) {\n setPendingStart(key);\n return;\n }\n\n const [start, end] = key < pendingStart ? [key, pendingStart] : [pendingStart, key];\n setPendingStart(null);\n onSelect(start, end);\n };\n\n const weeks = buildWeeks(viewYear, viewMonth);\n const weekDayLabels = weeks[0].map((day) => formatDate(day, { weekday: 'short' }).slice(0, 2));\n\n return (\n // role=\"group\" (not \"application\"): these are plain buttons — hijacking\n // the screen reader's own key handling would take away navigation and\n // give nothing back.\n <Box\n padding={2}\n width=\"100%\"\n role=\"group\"\n aria-label={formatMessage({\n id: getTranslationKey('list.filters.calendar.label'),\n defaultMessage: 'Select date range',\n })}\n data-testid=\"date-range-calendar\"\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" paddingBottom={2}>\n <IconButton\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('list.filters.calendar.previous-month'),\n defaultMessage: 'Previous month',\n })}\n onClick={() => moveMonth(-1)}\n >\n <ChevronLeft />\n </IconButton>\n <Typography fontWeight=\"semiBold\" textColor=\"neutral800\">\n {formatDate(new Date(viewYear, viewMonth, 1), { month: 'long', year: 'numeric' })}\n </Typography>\n <IconButton\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('list.filters.calendar.next-month'),\n defaultMessage: 'Next month',\n })}\n onClick={() => moveMonth(1)}\n >\n <ChevronRight />\n </IconButton>\n </Flex>\n\n <Flex>\n {weekDayLabels.map((label, index) => (\n <Flex key={index} width=\"3rem\" height=\"2.4rem\" justifyContent=\"center\">\n <Typography variant=\"pi\" fontWeight=\"semiBold\" textColor=\"neutral600\">\n {label}\n </Typography>\n </Flex>\n ))}\n </Flex>\n\n {weeks.map((week, weekIndex) => (\n <Flex key={weekIndex}>\n {week.map((day) => {\n const key = toKey(day);\n const isEdge = key === rangeStart || key === rangeEnd;\n const inRange =\n rangeStart !== null && rangeEnd !== null && key > rangeStart && key < rangeEnd;\n\n return (\n <DayCell\n key={key}\n type=\"button\"\n $isEdge={isEdge}\n $inRange={inRange}\n $isMuted={day.getMonth() !== viewMonth}\n onClick={() => handleDayClick(day)}\n >\n <VisuallyHidden>{formatDate(day, { dateStyle: 'long' })}</VisuallyHidden>\n <span aria-hidden>{day.getDate()}</span>\n </DayCell>\n );\n })}\n </Flex>\n ))}\n </Box>\n );\n};\n"],"names":["DayCell","styled","button","theme","borderRadius","$isEdge","$isMuted","colors","primary600","neutral400","neutral800","$inRange","primary200","primary100","toKey","date","month","getMonth","padStart","day","getDate","getFullYear","fromKey","key","year","split","map","Number","Date","buildWeeks","first","start","getTime","setDate","getDay","weeks","cursor","week","i","push","DateRangeCalendar","from","to","onSelect","formatMessage","formatDate","useIntl","initialMonth","viewYear","setViewYear","useState","viewMonth","setViewMonth","pendingStart","setPendingStart","rangeStart","rangeEnd","moveMonth","delta","next","handleDayClick","end","weekDayLabels","weekday","slice","_jsxs","Box","padding","width","role","aria-label","id","getTranslationKey","defaultMessage","data-testid","Flex","justifyContent","alignItems","paddingBottom","_jsx","IconButton","variant","label","onClick","ChevronLeft","Typography","fontWeight","textColor","ChevronRight","index","height","weekIndex","isEdge","inRange","type","VisuallyHidden","dateStyle","span","aria-hidden"],"mappings":"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"}
@@ -0,0 +1,191 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { Box, Flex, IconButton, Typography, VisuallyHidden } from '@strapi/design-system';
4
+ import { ChevronLeft, ChevronRight } from '@strapi/icons';
5
+ import { useIntl } from 'react-intl';
6
+ import { styled } from 'styled-components';
7
+ import { getTranslationKey } from '../../../utils/translations.mjs';
8
+
9
+ /**
10
+ * Month-grid range picker: first click sets the start, second click the end
11
+ * (clicks are reordered when the second date is before the first). The DS only
12
+ * ships a single-value DatePicker, so the range grid is built locally.
13
+ *
14
+ * Month/year move via chevrons rather than the mock's dropdowns — nested
15
+ * popovers inside a dropdown menu fight Radix's outside-interaction handling.
16
+ */ const DayCell = styled.button`
17
+ width: 3rem;
18
+ height: 3rem;
19
+ border: none;
20
+ border-radius: ${({ theme })=>theme.borderRadius};
21
+ cursor: pointer;
22
+ font: inherit;
23
+ color: ${({ theme, $isEdge, $isMuted })=>{
24
+ if ($isEdge) return theme.colors.primary600;
25
+ if ($isMuted) return theme.colors.neutral400;
26
+ return theme.colors.neutral800;
27
+ }};
28
+ background: ${({ theme, $inRange, $isEdge })=>{
29
+ if ($isEdge) return theme.colors.primary200;
30
+ if ($inRange) return theme.colors.primary100;
31
+ return 'transparent';
32
+ }};
33
+
34
+ &:hover {
35
+ background: ${({ theme })=>theme.colors.primary100};
36
+ }
37
+
38
+ &:focus-visible {
39
+ outline: 2px solid ${({ theme })=>theme.colors.primary600};
40
+ outline-offset: -2px;
41
+ }
42
+ `;
43
+ const toKey = (date)=>{
44
+ const month = `${date.getMonth() + 1}`.padStart(2, '0');
45
+ const day = `${date.getDate()}`.padStart(2, '0');
46
+ return `${date.getFullYear()}-${month}-${day}`;
47
+ };
48
+ const fromKey = (key)=>{
49
+ const [year, month, day] = key.split('-').map(Number);
50
+ return new Date(year, month - 1, day);
51
+ };
52
+ /** Monday-first weeks covering the given month, padded with adjacent days. */ const buildWeeks = (year, month)=>{
53
+ const first = new Date(year, month, 1);
54
+ const start = new Date(first.getTime());
55
+ start.setDate(first.getDate() - (first.getDay() + 6) % 7);
56
+ const weeks = [];
57
+ const cursor = new Date(start.getTime());
58
+ do {
59
+ const week = [];
60
+ for(let i = 0; i < 7; i += 1){
61
+ week.push(new Date(cursor.getTime()));
62
+ cursor.setDate(cursor.getDate() + 1);
63
+ }
64
+ weeks.push(week);
65
+ }while (cursor.getMonth() === month && cursor.getFullYear() === year)
66
+ return weeks;
67
+ };
68
+ const DateRangeCalendar = ({ from, to, onSelect })=>{
69
+ const { formatMessage, formatDate } = useIntl();
70
+ const initialMonth = from ? fromKey(from) : new Date();
71
+ const [viewYear, setViewYear] = useState(initialMonth.getFullYear());
72
+ const [viewMonth, setViewMonth] = useState(initialMonth.getMonth());
73
+ // In-progress selection: set on the first click, cleared on commit.
74
+ const [pendingStart, setPendingStart] = useState(null);
75
+ const rangeStart = pendingStart ?? from ?? null;
76
+ const rangeEnd = pendingStart ? null : to ?? null;
77
+ const moveMonth = (delta)=>{
78
+ const next = new Date(viewYear, viewMonth + delta, 1);
79
+ setViewYear(next.getFullYear());
80
+ setViewMonth(next.getMonth());
81
+ };
82
+ const handleDayClick = (day)=>{
83
+ const key = toKey(day);
84
+ if (!pendingStart) {
85
+ setPendingStart(key);
86
+ return;
87
+ }
88
+ const [start, end] = key < pendingStart ? [
89
+ key,
90
+ pendingStart
91
+ ] : [
92
+ pendingStart,
93
+ key
94
+ ];
95
+ setPendingStart(null);
96
+ onSelect(start, end);
97
+ };
98
+ const weeks = buildWeeks(viewYear, viewMonth);
99
+ const weekDayLabels = weeks[0].map((day)=>formatDate(day, {
100
+ weekday: 'short'
101
+ }).slice(0, 2));
102
+ return(// role="group" (not "application"): these are plain buttons — hijacking
103
+ // the screen reader's own key handling would take away navigation and
104
+ // give nothing back.
105
+ /*#__PURE__*/ jsxs(Box, {
106
+ padding: 2,
107
+ width: "100%",
108
+ role: "group",
109
+ "aria-label": formatMessage({
110
+ id: getTranslationKey('list.filters.calendar.label'),
111
+ defaultMessage: 'Select date range'
112
+ }),
113
+ "data-testid": "date-range-calendar",
114
+ children: [
115
+ /*#__PURE__*/ jsxs(Flex, {
116
+ justifyContent: "space-between",
117
+ alignItems: "center",
118
+ paddingBottom: 2,
119
+ children: [
120
+ /*#__PURE__*/ jsx(IconButton, {
121
+ variant: "ghost",
122
+ label: formatMessage({
123
+ id: getTranslationKey('list.filters.calendar.previous-month'),
124
+ defaultMessage: 'Previous month'
125
+ }),
126
+ onClick: ()=>moveMonth(-1),
127
+ children: /*#__PURE__*/ jsx(ChevronLeft, {})
128
+ }),
129
+ /*#__PURE__*/ jsx(Typography, {
130
+ fontWeight: "semiBold",
131
+ textColor: "neutral800",
132
+ children: formatDate(new Date(viewYear, viewMonth, 1), {
133
+ month: 'long',
134
+ year: 'numeric'
135
+ })
136
+ }),
137
+ /*#__PURE__*/ jsx(IconButton, {
138
+ variant: "ghost",
139
+ label: formatMessage({
140
+ id: getTranslationKey('list.filters.calendar.next-month'),
141
+ defaultMessage: 'Next month'
142
+ }),
143
+ onClick: ()=>moveMonth(1),
144
+ children: /*#__PURE__*/ jsx(ChevronRight, {})
145
+ })
146
+ ]
147
+ }),
148
+ /*#__PURE__*/ jsx(Flex, {
149
+ children: weekDayLabels.map((label, index)=>/*#__PURE__*/ jsx(Flex, {
150
+ width: "3rem",
151
+ height: "2.4rem",
152
+ justifyContent: "center",
153
+ children: /*#__PURE__*/ jsx(Typography, {
154
+ variant: "pi",
155
+ fontWeight: "semiBold",
156
+ textColor: "neutral600",
157
+ children: label
158
+ })
159
+ }, index))
160
+ }),
161
+ weeks.map((week, weekIndex)=>/*#__PURE__*/ jsx(Flex, {
162
+ children: week.map((day)=>{
163
+ const key = toKey(day);
164
+ const isEdge = key === rangeStart || key === rangeEnd;
165
+ const inRange = rangeStart !== null && rangeEnd !== null && key > rangeStart && key < rangeEnd;
166
+ return /*#__PURE__*/ jsxs(DayCell, {
167
+ type: "button",
168
+ $isEdge: isEdge,
169
+ $inRange: inRange,
170
+ $isMuted: day.getMonth() !== viewMonth,
171
+ onClick: ()=>handleDayClick(day),
172
+ children: [
173
+ /*#__PURE__*/ jsx(VisuallyHidden, {
174
+ children: formatDate(day, {
175
+ dateStyle: 'long'
176
+ })
177
+ }),
178
+ /*#__PURE__*/ jsx("span", {
179
+ "aria-hidden": true,
180
+ children: day.getDate()
181
+ })
182
+ ]
183
+ }, key);
184
+ })
185
+ }, weekIndex))
186
+ ]
187
+ }));
188
+ };
189
+
190
+ export { DateRangeCalendar };
191
+ //# sourceMappingURL=DateRangeCalendar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateRangeCalendar.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/DateRangeCalendar.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { Box, Flex, IconButton, Typography, VisuallyHidden } from '@strapi/design-system';\nimport { ChevronLeft, ChevronRight } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../utils/translations';\n\n/**\n * Month-grid range picker: first click sets the start, second click the end\n * (clicks are reordered when the second date is before the first). The DS only\n * ships a single-value DatePicker, so the range grid is built locally.\n *\n * Month/year move via chevrons rather than the mock's dropdowns — nested\n * popovers inside a dropdown menu fight Radix's outside-interaction handling.\n */\n\nconst DayCell = styled.button<{ $inRange?: boolean; $isEdge?: boolean; $isMuted?: boolean }>`\n width: 3rem;\n height: 3rem;\n border: none;\n border-radius: ${({ theme }) => theme.borderRadius};\n cursor: pointer;\n font: inherit;\n color: ${({ theme, $isEdge, $isMuted }) => {\n if ($isEdge) return theme.colors.primary600;\n if ($isMuted) return theme.colors.neutral400;\n return theme.colors.neutral800;\n }};\n background: ${({ theme, $inRange, $isEdge }) => {\n if ($isEdge) return theme.colors.primary200;\n if ($inRange) return theme.colors.primary100;\n return 'transparent';\n }};\n\n &:hover {\n background: ${({ theme }) => theme.colors.primary100};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n`;\n\nconst toKey = (date: Date): string => {\n const month = `${date.getMonth() + 1}`.padStart(2, '0');\n const day = `${date.getDate()}`.padStart(2, '0');\n return `${date.getFullYear()}-${month}-${day}`;\n};\n\nconst fromKey = (key: string): Date => {\n const [year, month, day] = key.split('-').map(Number);\n return new Date(year, month - 1, day);\n};\n\n/** Monday-first weeks covering the given month, padded with adjacent days. */\nconst buildWeeks = (year: number, month: number): Date[][] => {\n const first = new Date(year, month, 1);\n const start = new Date(first.getTime());\n start.setDate(first.getDate() - ((first.getDay() + 6) % 7));\n\n const weeks: Date[][] = [];\n const cursor = new Date(start.getTime());\n\n do {\n const week: Date[] = [];\n for (let i = 0; i < 7; i += 1) {\n week.push(new Date(cursor.getTime()));\n cursor.setDate(cursor.getDate() + 1);\n }\n weeks.push(week);\n } while (cursor.getMonth() === month && cursor.getFullYear() === year);\n\n return weeks;\n};\n\ninterface DateRangeCalendarProps {\n /** `YYYY-MM-DD`, both set when editing an existing range badge. */\n from?: string;\n to?: string;\n onSelect: (from: string, to: string) => void;\n}\n\nexport const DateRangeCalendar = ({ from, to, onSelect }: DateRangeCalendarProps) => {\n const { formatMessage, formatDate } = useIntl();\n\n const initialMonth = from ? fromKey(from) : new Date();\n const [viewYear, setViewYear] = useState(initialMonth.getFullYear());\n const [viewMonth, setViewMonth] = useState(initialMonth.getMonth());\n // In-progress selection: set on the first click, cleared on commit.\n const [pendingStart, setPendingStart] = useState<string | null>(null);\n\n const rangeStart = pendingStart ?? from ?? null;\n const rangeEnd = pendingStart ? null : (to ?? null);\n\n const moveMonth = (delta: number) => {\n const next = new Date(viewYear, viewMonth + delta, 1);\n setViewYear(next.getFullYear());\n setViewMonth(next.getMonth());\n };\n\n const handleDayClick = (day: Date) => {\n const key = toKey(day);\n\n if (!pendingStart) {\n setPendingStart(key);\n return;\n }\n\n const [start, end] = key < pendingStart ? [key, pendingStart] : [pendingStart, key];\n setPendingStart(null);\n onSelect(start, end);\n };\n\n const weeks = buildWeeks(viewYear, viewMonth);\n const weekDayLabels = weeks[0].map((day) => formatDate(day, { weekday: 'short' }).slice(0, 2));\n\n return (\n // role=\"group\" (not \"application\"): these are plain buttons — hijacking\n // the screen reader's own key handling would take away navigation and\n // give nothing back.\n <Box\n padding={2}\n width=\"100%\"\n role=\"group\"\n aria-label={formatMessage({\n id: getTranslationKey('list.filters.calendar.label'),\n defaultMessage: 'Select date range',\n })}\n data-testid=\"date-range-calendar\"\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" paddingBottom={2}>\n <IconButton\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('list.filters.calendar.previous-month'),\n defaultMessage: 'Previous month',\n })}\n onClick={() => moveMonth(-1)}\n >\n <ChevronLeft />\n </IconButton>\n <Typography fontWeight=\"semiBold\" textColor=\"neutral800\">\n {formatDate(new Date(viewYear, viewMonth, 1), { month: 'long', year: 'numeric' })}\n </Typography>\n <IconButton\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('list.filters.calendar.next-month'),\n defaultMessage: 'Next month',\n })}\n onClick={() => moveMonth(1)}\n >\n <ChevronRight />\n </IconButton>\n </Flex>\n\n <Flex>\n {weekDayLabels.map((label, index) => (\n <Flex key={index} width=\"3rem\" height=\"2.4rem\" justifyContent=\"center\">\n <Typography variant=\"pi\" fontWeight=\"semiBold\" textColor=\"neutral600\">\n {label}\n </Typography>\n </Flex>\n ))}\n </Flex>\n\n {weeks.map((week, weekIndex) => (\n <Flex key={weekIndex}>\n {week.map((day) => {\n const key = toKey(day);\n const isEdge = key === rangeStart || key === rangeEnd;\n const inRange =\n rangeStart !== null && rangeEnd !== null && key > rangeStart && key < rangeEnd;\n\n return (\n <DayCell\n key={key}\n type=\"button\"\n $isEdge={isEdge}\n $inRange={inRange}\n $isMuted={day.getMonth() !== viewMonth}\n onClick={() => handleDayClick(day)}\n >\n <VisuallyHidden>{formatDate(day, { dateStyle: 'long' })}</VisuallyHidden>\n <span aria-hidden>{day.getDate()}</span>\n </DayCell>\n );\n })}\n </Flex>\n ))}\n </Box>\n );\n};\n"],"names":["DayCell","styled","button","theme","borderRadius","$isEdge","$isMuted","colors","primary600","neutral400","neutral800","$inRange","primary200","primary100","toKey","date","month","getMonth","padStart","day","getDate","getFullYear","fromKey","key","year","split","map","Number","Date","buildWeeks","first","start","getTime","setDate","getDay","weeks","cursor","week","i","push","DateRangeCalendar","from","to","onSelect","formatMessage","formatDate","useIntl","initialMonth","viewYear","setViewYear","useState","viewMonth","setViewMonth","pendingStart","setPendingStart","rangeStart","rangeEnd","moveMonth","delta","next","handleDayClick","end","weekDayLabels","weekday","slice","_jsxs","Box","padding","width","role","aria-label","id","getTranslationKey","defaultMessage","data-testid","Flex","justifyContent","alignItems","paddingBottom","_jsx","IconButton","variant","label","onClick","ChevronLeft","Typography","fontWeight","textColor","ChevronRight","index","height","weekIndex","isEdge","inRange","type","VisuallyHidden","dateStyle","span","aria-hidden"],"mappings":"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"}
@@ -6,6 +6,7 @@ var core = require('@dnd-kit/core');
6
6
  var strapiAdmin = require('@strapi/admin/strapi-admin');
7
7
  var designSystem = require('@strapi/design-system');
8
8
  var reactIntl = require('react-intl');
9
+ var useMediaLibraryPermissions = require('../../../../hooks/useMediaLibraryPermissions.js');
9
10
  var folders = require('../../../../services/folders.js');
10
11
  var buildBulkMovePayload = require('../../../../utils/buildBulkMovePayload.js');
11
12
  var canDropItemOnFolder = require('../../../../utils/canDropItemOnFolder.js');
@@ -42,6 +43,10 @@ const resolveDestination = (overId)=>{
42
43
  }
43
44
  return null;
44
45
  };
46
+ // Activation distance no real pointer gesture will ever reach — used to keep a
47
+ // constant-length sensor array while disabling drag for users without the move
48
+ // permission (see the note in the provider).
49
+ const DRAG_DISABLED_DISTANCE = Number.MAX_SAFE_INTEGER;
45
50
  const AssetsDndProvider = ({ children })=>{
46
51
  const { formatMessage } = reactIntl.useIntl();
47
52
  const { toggleNotification } = strapiAdmin.useNotification();
@@ -64,9 +69,21 @@ const AssetsDndProvider = ({ children })=>{
64
69
  setLiveAnnouncement('');
65
70
  requestAnimationFrame(()=>setLiveAnnouncement(message));
66
71
  }, []);
72
+ // Moving is a mutation (bulk-move → `assets.update`); without the permission
73
+ // pointer drag must never activate. Keyboard moves go through BulkMoveDialog,
74
+ // which is itself gated.
75
+ //
76
+ // The gate has to keep BOTH the `useSensor`/`useSensors` calls AND the sensor
77
+ // array's length constant across renders: `canUpdate` starts false and flips
78
+ // true once the RBAC check resolves, and dnd-kit keys internal memos/effects
79
+ // on the sensor list, erroring if its size changes ("argument changed size
80
+ // between renders"). So adding/removing a sensor is out — instead keep one
81
+ // PointerSensor always and push its activation distance out of reach when the
82
+ // user can't move, which no real drag gesture will ever satisfy.
83
+ const { canUpdate } = useMediaLibraryPermissions.useMediaLibraryPermissions();
67
84
  const sensors = core.useSensors(core.useSensor(core.PointerSensor, {
68
85
  activationConstraint: {
69
- distance: 8
86
+ distance: canUpdate ? 8 : DRAG_DISABLED_DISTANCE
70
87
  }
71
88
  }));
72
89
  const validDropTargets = React.useMemo(()=>computeValidDropTargets.computeValidDropTargets(dragItems, folderStructure), [