@strapi/upload 5.51.1 → 5.52.0

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