@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 @@
1
+ {"version":3,"file":"BetaNotice.mjs","sources":["../../../../admin/src/future/components/BetaNotice.tsx"],"sourcesContent":["import { usePersistentState } from '@strapi/admin/strapi-admin';\nimport { Alert, Box, Flex, Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../utils/translations';\n\n/**\n * The beta indicator is a notice rather than a badge on the page header: that\n * header's title follows the folder you are in, so a badge attached to it would\n * read as \"this folder is beta\". This notice covers the whole Media Library, and\n * stays dismissed once a tester has read it.\n *\n * It renders inside `Layouts.Content` so it picks up the content column's gutter.\n * Rendered above the layout instead, it would span the full viewport width and\n * sit over the folder sidebar.\n */\nexport const BetaNotice = () => {\n const { formatMessage } = useIntl();\n const [isBetaNoticeDismissed, setIsBetaNoticeDismissed] = usePersistentState(\n 'STRAPI_UPLOAD_LIBRARY_BETA_NOTICE_DISMISSED',\n false\n );\n\n if (isBetaNoticeDismissed) {\n return null;\n }\n\n return (\n <Box paddingBottom={4}>\n <Alert\n variant=\"default\"\n onClose={() => setIsBetaNoticeDismissed(true)}\n closeLabel={formatMessage({\n id: getTranslationKey('beta.notice.close'),\n defaultMessage: 'Close',\n })}\n title={formatMessage({\n id: getTranslationKey('plugin.name'),\n defaultMessage: 'Media Library',\n })}\n >\n {/* `Alert` renders its children inside a `<p>`, so everything here stays\n inline to keep the markup valid. That rules out `Badge`, which always\n renders a `<div>` — the badge below reproduces its look on a `<span>`. */}\n <Flex tag=\"span\" gap={2} alignItems=\"center\">\n <Box\n tag=\"span\"\n background=\"neutral150\"\n hasRadius\n paddingLeft={2}\n paddingRight={2}\n shrink={0}\n >\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslationKey('beta.badge'),\n defaultMessage: 'Beta',\n })}\n </Typography>\n </Box>\n <Typography tag=\"span\">\n {formatMessage({\n id: getTranslationKey('beta.notice.content'),\n defaultMessage:\n 'This is a beta version of the Media Library. Some features are still in progress — please report any issue you run into.',\n })}\n </Typography>\n </Flex>\n </Alert>\n </Box>\n );\n};\n"],"names":["BetaNotice","formatMessage","useIntl","isBetaNoticeDismissed","setIsBetaNoticeDismissed","usePersistentState","_jsx","Box","paddingBottom","Alert","variant","onClose","closeLabel","id","getTranslationKey","defaultMessage","title","_jsxs","Flex","tag","gap","alignItems","background","hasRadius","paddingLeft","paddingRight","shrink","Typography","textColor"],"mappings":";;;;;;AAMA;;;;;;;;;UAUaA,UAAAA,GAAa,IAAA;IACxB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAM,CAACC,qBAAAA,EAAuBC,wBAAAA,CAAyB,GAAGC,mBACxD,6CAAA,EACA,KAAA,CAAA;AAGF,IAAA,IAAIF,qBAAAA,EAAuB;QACzB,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,qBACEG,GAAA,CAACC,GAAAA,EAAAA;QAAIC,aAAAA,EAAe,CAAA;AAClB,QAAA,QAAA,gBAAAF,GAAA,CAACG,KAAAA,EAAAA;YACCC,OAAAA,EAAQ,SAAA;AACRC,YAAAA,OAAAA,EAAS,IAAMP,wBAAAA,CAAyB,IAAA,CAAA;AACxCQ,YAAAA,UAAAA,EAAYX,aAAAA,CAAc;AACxBY,gBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,mBAAA,CAAA;gBACtBC,cAAAA,EAAgB;AAClB,aAAA,CAAA;AACAC,YAAAA,KAAAA,EAAOf,aAAAA,CAAc;AACnBY,gBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,aAAA,CAAA;gBACtBC,cAAAA,EAAgB;AAClB,aAAA,CAAA;AAKA,YAAA,QAAA,gBAAAE,IAAA,CAACC,IAAAA,EAAAA;gBAAKC,GAAAA,EAAI,MAAA;gBAAOC,GAAAA,EAAK,CAAA;gBAAGC,UAAAA,EAAW,QAAA;;kCAClCf,GAAA,CAACC,GAAAA,EAAAA;wBACCY,GAAAA,EAAI,MAAA;wBACJG,UAAAA,EAAW,YAAA;wBACXC,SAAS,EAAA,IAAA;wBACTC,WAAAA,EAAa,CAAA;wBACbC,YAAAA,EAAc,CAAA;wBACdC,MAAAA,EAAQ,CAAA;AAER,wBAAA,QAAA,gBAAApB,GAAA,CAACqB,UAAAA,EAAAA;4BAAWjB,OAAAA,EAAQ,OAAA;4BAAQkB,SAAAA,EAAU,YAAA;sCACnC3B,aAAAA,CAAc;AACbY,gCAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,YAAA,CAAA;gCACtBC,cAAAA,EAAgB;AAClB,6BAAA;;;kCAGJT,GAAA,CAACqB,UAAAA,EAAAA;wBAAWR,GAAAA,EAAI,MAAA;kCACblB,aAAAA,CAAc;AACbY,4BAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,qBAAA,CAAA;4BACtBC,cAAAA,EACE;AACJ,yBAAA;;;;;;AAMZ;;;;"}
@@ -78,7 +78,14 @@ const DrawerContainer = styledComponents.styled(designSystem.Flex)`
78
78
  flex-direction: column;
79
79
  position: fixed;
80
80
  bottom: 0;
81
+ /* Mobile: full-bleed sheet. Anchoring to the right at a fixed width left a
82
+ dead gutter on every phone wider than the panel, and the panel only filled
83
+ the screen once the viewport happened to be narrower than it. Below the
84
+ medium breakpoint the panel is the screen; medium+ restores the
85
+ right-anchored rail. */
86
+ left: 0;
81
87
  right: 0;
88
+ width: 100%;
82
89
  padding: ${({ theme })=>theme.spaces[2]};
83
90
  max-width: 100%;
84
91
  /* Sit just below the overlay token (300) so that:
@@ -88,8 +95,14 @@ const DrawerContainer = styledComponents.styled(designSystem.Flex)`
88
95
  drawer (e.g. the asset details "delete" confirm) cover the drawer. */
89
96
  z-index: 200;
90
97
  overflow: hidden;
91
- width: ${({ width })=>width ?? '400px'};
92
- max-height: ${({ maxHeight })=>maxHeight ?? '100vh'};
98
+ /* dvh, not vh: anchored to the bottom, a 100vh cap on mobile (visual
99
+ viewport < 100vh under the URL bar) would push the drawer top off-screen. */
100
+ max-height: ${({ $maxHeight })=>$maxHeight ?? '100dvh'};
101
+
102
+ ${({ theme })=>theme.breakpoints.medium} {
103
+ left: auto;
104
+ width: ${({ $width })=>$width ?? '400px'};
105
+ }
93
106
 
94
107
  &:focus {
95
108
  outline: none;
@@ -137,7 +150,7 @@ const CloseIconButton = styledComponents.styled(designSystem.IconButton)`
137
150
  background: transparent;
138
151
  }
139
152
  `;
140
- const DrawerBody = /*#__PURE__*/ React__namespace.forwardRef(({ animationDirection, children, ...props }, ref)=>/*#__PURE__*/ jsxRuntime.jsx(Dialog__namespace.Content, {
153
+ const DrawerBody = /*#__PURE__*/ React__namespace.forwardRef(({ animationDirection, width, maxHeight, children, ...props }, ref)=>/*#__PURE__*/ jsxRuntime.jsx(Dialog__namespace.Content, {
141
154
  ref: ref,
142
155
  forceMount: true,
143
156
  asChild: true,
@@ -146,6 +159,8 @@ const DrawerBody = /*#__PURE__*/ React__namespace.forwardRef(({ animationDirecti
146
159
  "data-animation-direction": animationDirection,
147
160
  children: /*#__PURE__*/ jsxRuntime.jsx(DrawerContainer, {
148
161
  $animationDirection: animationDirection,
162
+ $width: width,
163
+ $maxHeight: maxHeight,
149
164
  ...props,
150
165
  children: /*#__PURE__*/ jsxRuntime.jsx(DrawerContent, {
151
166
  children: children
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","sources":["../../../../admin/src/future/components/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport * as Dialog from '@radix-ui/react-dialog';\nimport { Box, ScrollArea, IconButton, Flex, FlexProps } from '@strapi/design-system';\nimport { Cross } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { keyframes, styled } from 'styled-components';\n\n/** Duration of the close animation in ms. Use for timing cleanup (e.g. removing URL params). */\nexport const DRAWER_CLOSE_ANIMATION_MS = 300;\n\n/* -------------------------------------------------------------------------------------------------\n * Animations\n * -----------------------------------------------------------------------------------------------*/\n\n// Direction: up\nconst slideUpFromBottomIn = keyframes`\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n`;\n\nconst slideUpFromBottomOut = keyframes`\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n`;\n\n// Direction: left\nconst slideLeftFromRightIn = keyframes`\n from {\n opacity: 0;\n transform: translateX(100%);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\nconst slideLeftFromRightOut = keyframes`\n from {\n opacity: 1;\n transform: translateX(0);\n }\n to {\n opacity: 0;\n transform: translateX(100%);\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Styled components\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerContainerProps {\n $animationDirection?: DrawerBodyProps['animationDirection'];\n}\n\nconst DrawerContainer = styled(Flex)<DrawerContainerProps>`\n flex-direction: column;\n position: fixed;\n bottom: 0;\n right: 0;\n padding: ${({ theme }) => theme.spaces[2]};\n max-width: 100%;\n /* Sit just below the overlay token (300) so that:\n - popovers (500) and tooltips (1000) rendered from descendant components\n surface above the drawer panel,\n - AlertDialog overlays (300) and contents (310) opened from inside the\n drawer (e.g. the asset details \"delete\" confirm) cover the drawer. */\n z-index: 200;\n overflow: hidden;\n width: ${({ width }) => width ?? '400px'};\n max-height: ${({ maxHeight }) => maxHeight ?? '100vh'};\n\n &:focus {\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n &[data-state='open'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomIn : slideLeftFromRightIn}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n }\n\n &[data-state='closed'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomOut : slideLeftFromRightOut}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n pointer-events: none;\n }\n }\n`;\n\nconst DrawerContent = styled(Box)`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n background-color: ${({ theme }) => theme.colors.neutral0};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n overflow: hidden;\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\ninterface CollapsibleContentProps {\n $isVisible: boolean;\n}\n\nconst CollapsibleContent = styled(Box)<CollapsibleContentProps>`\n display: grid;\n flex: 1;\n min-height: 0;\n grid-template-rows: ${({ $isVisible }) => ($isVisible ? '1fr' : '0fr')};\n transition: grid-template-rows 0.3s ease-in-out;\n\n > div {\n overflow: hidden;\n min-height: 0;\n }\n`;\n\nconst CloseIconButton = styled(IconButton)`\n &:hover {\n background: transparent;\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Body\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerBodyProps extends FlexProps {\n animationDirection?: 'up' | 'left';\n children: React.ReactNode;\n}\n\nconst DrawerBody = React.forwardRef<HTMLDivElement, DrawerBodyProps>(\n ({ animationDirection, children, ...props }, ref) => (\n <Dialog.Content\n ref={ref}\n forceMount\n asChild\n onPointerDownOutside={(e) => e.preventDefault()}\n onInteractOutside={(e) => e.preventDefault()}\n data-animation-direction={animationDirection}\n >\n <DrawerContainer $animationDirection={animationDirection} {...props}>\n <DrawerContent>{children}</DrawerContent>\n </DrawerContainer>\n </Dialog.Content>\n )\n);\nDrawerBody.displayName = 'DrawerBody';\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Root\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerRootProps {\n isVisible?: boolean;\n onClose?: () => void;\n children: React.ReactNode;\n}\n\nconst DrawerRoot = ({ isVisible, onClose, children }: DrawerRootProps): React.ReactElement => (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(nextVisible) => !nextVisible && onClose?.()}\n modal={false}\n >\n <Dialog.Portal>{children}</Dialog.Portal>\n </Dialog.Root>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Content - composable content slot (collapsible when isContentExpanded is used)\n * Contains a scrollable area\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerScrollableContentProps {\n children: React.ReactNode;\n /** When provided, content can collapse/expand (e.g. for minimize). Omit to always show. */\n isContentExpanded?: boolean;\n}\n\nconst DrawerScrollableContent = ({\n children,\n isContentExpanded = true,\n}: DrawerScrollableContentProps) => (\n <CollapsibleContent $isVisible={isContentExpanded} data-collapsed={!isContentExpanded}>\n <ScrollArea>{children}</ScrollArea>\n </CollapsibleContent>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.CloseButton - composable close icon button (Cross icon by default)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerCloseButtonProps extends React.PropsWithChildren {\n onClose: () => void;\n label?: string;\n}\n\nconst DrawerCloseButton = ({ onClose, label, children }: DrawerCloseButtonProps) => {\n const { formatMessage } = useIntl();\n const labelMessage = label ?? formatMessage({ id: 'global.close', defaultMessage: 'Close' });\n return (\n <CloseIconButton onClick={onClose} label={labelMessage} variant=\"ghost\">\n {children ?? <Cross />}\n </CloseIconButton>\n );\n};\n\nconst Drawer = {\n Root: DrawerRoot,\n Body: DrawerBody,\n ScrollableContent: DrawerScrollableContent,\n CloseButton: DrawerCloseButton,\n Title: Dialog.Title,\n Description: Dialog.Description,\n};\n\nexport { Drawer };\n"],"names":["DRAWER_CLOSE_ANIMATION_MS","slideUpFromBottomIn","keyframes","slideUpFromBottomOut","slideLeftFromRightIn","slideLeftFromRightOut","DrawerContainer","styled","Flex","theme","spaces","width","maxHeight","$animationDirection","DrawerContent","Box","colors","neutral0","borderRadius","shadows","popupShadow","neutral150","CollapsibleContent","$isVisible","CloseIconButton","IconButton","DrawerBody","React","forwardRef","animationDirection","children","props","ref","_jsx","Dialog","Content","forceMount","asChild","onPointerDownOutside","e","preventDefault","onInteractOutside","data-animation-direction","displayName","DrawerRoot","isVisible","onClose","Root","open","onOpenChange","nextVisible","modal","Portal","DrawerScrollableContent","isContentExpanded","data-collapsed","ScrollArea","DrawerCloseButton","label","formatMessage","useIntl","labelMessage","id","defaultMessage","onClick","variant","Cross","Drawer","Body","ScrollableContent","CloseButton","Title","Description"],"mappings":"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"}
1
+ {"version":3,"file":"Drawer.js","sources":["../../../../admin/src/future/components/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport * as Dialog from '@radix-ui/react-dialog';\nimport { Box, ScrollArea, IconButton, Flex, FlexProps } from '@strapi/design-system';\nimport { Cross } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { keyframes, styled } from 'styled-components';\n\n/** Duration of the close animation in ms. Use for timing cleanup (e.g. removing URL params). */\nexport const DRAWER_CLOSE_ANIMATION_MS = 300;\n\n/* -------------------------------------------------------------------------------------------------\n * Animations\n * -----------------------------------------------------------------------------------------------*/\n\n// Direction: up\nconst slideUpFromBottomIn = keyframes`\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n`;\n\nconst slideUpFromBottomOut = keyframes`\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n`;\n\n// Direction: left\nconst slideLeftFromRightIn = keyframes`\n from {\n opacity: 0;\n transform: translateX(100%);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\nconst slideLeftFromRightOut = keyframes`\n from {\n opacity: 1;\n transform: translateX(0);\n }\n to {\n opacity: 0;\n transform: translateX(100%);\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Styled components\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerContainerProps {\n $animationDirection?: DrawerBodyProps['animationDirection'];\n $width?: string;\n $maxHeight?: string;\n}\n\nconst DrawerContainer = styled(Flex)<DrawerContainerProps>`\n flex-direction: column;\n position: fixed;\n bottom: 0;\n /* Mobile: full-bleed sheet. Anchoring to the right at a fixed width left a\n dead gutter on every phone wider than the panel, and the panel only filled\n the screen once the viewport happened to be narrower than it. Below the\n medium breakpoint the panel is the screen; medium+ restores the\n right-anchored rail. */\n left: 0;\n right: 0;\n width: 100%;\n padding: ${({ theme }) => theme.spaces[2]};\n max-width: 100%;\n /* Sit just below the overlay token (300) so that:\n - popovers (500) and tooltips (1000) rendered from descendant components\n surface above the drawer panel,\n - AlertDialog overlays (300) and contents (310) opened from inside the\n drawer (e.g. the asset details \"delete\" confirm) cover the drawer. */\n z-index: 200;\n overflow: hidden;\n /* dvh, not vh: anchored to the bottom, a 100vh cap on mobile (visual\n viewport < 100vh under the URL bar) would push the drawer top off-screen. */\n max-height: ${({ $maxHeight }) => $maxHeight ?? '100dvh'};\n\n ${({ theme }) => theme.breakpoints.medium} {\n left: auto;\n width: ${({ $width }) => $width ?? '400px'};\n }\n\n &:focus {\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n &[data-state='open'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomIn : slideLeftFromRightIn}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n }\n\n &[data-state='closed'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomOut : slideLeftFromRightOut}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n pointer-events: none;\n }\n }\n`;\n\nconst DrawerContent = styled(Box)`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n background-color: ${({ theme }) => theme.colors.neutral0};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n overflow: hidden;\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\ninterface CollapsibleContentProps {\n $isVisible: boolean;\n}\n\nconst CollapsibleContent = styled(Box)<CollapsibleContentProps>`\n display: grid;\n flex: 1;\n min-height: 0;\n grid-template-rows: ${({ $isVisible }) => ($isVisible ? '1fr' : '0fr')};\n transition: grid-template-rows 0.3s ease-in-out;\n\n > div {\n overflow: hidden;\n min-height: 0;\n }\n`;\n\nconst CloseIconButton = styled(IconButton)`\n &:hover {\n background: transparent;\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Body\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerBodyProps extends Omit<FlexProps, 'width' | 'maxHeight'> {\n animationDirection?: 'up' | 'left';\n /** Width of the panel from the medium breakpoint up. Mobile is always full-bleed. */\n width?: string;\n /** Cap on the panel height. Defaults to the dynamic viewport height. */\n maxHeight?: string;\n children: React.ReactNode;\n}\n\nconst DrawerBody = React.forwardRef<HTMLDivElement, DrawerBodyProps>(\n ({ animationDirection, width, maxHeight, children, ...props }, ref) => (\n <Dialog.Content\n ref={ref}\n forceMount\n asChild\n onPointerDownOutside={(e) => e.preventDefault()}\n onInteractOutside={(e) => e.preventDefault()}\n data-animation-direction={animationDirection}\n >\n {/* width/maxHeight go through transient props so the DS Flex never emits a\n competing `width` rule that would outrank the mobile full-bleed one. */}\n <DrawerContainer\n $animationDirection={animationDirection}\n $width={width}\n $maxHeight={maxHeight}\n {...props}\n >\n <DrawerContent>{children}</DrawerContent>\n </DrawerContainer>\n </Dialog.Content>\n )\n);\nDrawerBody.displayName = 'DrawerBody';\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Root\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerRootProps {\n isVisible?: boolean;\n onClose?: () => void;\n children: React.ReactNode;\n}\n\nconst DrawerRoot = ({ isVisible, onClose, children }: DrawerRootProps): React.ReactElement => (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(nextVisible) => !nextVisible && onClose?.()}\n modal={false}\n >\n <Dialog.Portal>{children}</Dialog.Portal>\n </Dialog.Root>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Content - composable content slot (collapsible when isContentExpanded is used)\n * Contains a scrollable area\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerScrollableContentProps {\n children: React.ReactNode;\n /** When provided, content can collapse/expand (e.g. for minimize). Omit to always show. */\n isContentExpanded?: boolean;\n}\n\nconst DrawerScrollableContent = ({\n children,\n isContentExpanded = true,\n}: DrawerScrollableContentProps) => (\n <CollapsibleContent $isVisible={isContentExpanded} data-collapsed={!isContentExpanded}>\n <ScrollArea>{children}</ScrollArea>\n </CollapsibleContent>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.CloseButton - composable close icon button (Cross icon by default)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerCloseButtonProps extends React.PropsWithChildren {\n onClose: () => void;\n label?: string;\n}\n\nconst DrawerCloseButton = ({ onClose, label, children }: DrawerCloseButtonProps) => {\n const { formatMessage } = useIntl();\n const labelMessage = label ?? formatMessage({ id: 'global.close', defaultMessage: 'Close' });\n return (\n <CloseIconButton onClick={onClose} label={labelMessage} variant=\"ghost\">\n {children ?? <Cross />}\n </CloseIconButton>\n );\n};\n\nconst Drawer = {\n Root: DrawerRoot,\n Body: DrawerBody,\n ScrollableContent: DrawerScrollableContent,\n CloseButton: DrawerCloseButton,\n Title: Dialog.Title,\n Description: Dialog.Description,\n};\n\nexport { Drawer };\n"],"names":["DRAWER_CLOSE_ANIMATION_MS","slideUpFromBottomIn","keyframes","slideUpFromBottomOut","slideLeftFromRightIn","slideLeftFromRightOut","DrawerContainer","styled","Flex","theme","spaces","$maxHeight","breakpoints","medium","$width","$animationDirection","DrawerContent","Box","colors","neutral0","borderRadius","shadows","popupShadow","neutral150","CollapsibleContent","$isVisible","CloseIconButton","IconButton","DrawerBody","React","forwardRef","animationDirection","width","maxHeight","children","props","ref","_jsx","Dialog","Content","forceMount","asChild","onPointerDownOutside","e","preventDefault","onInteractOutside","data-animation-direction","displayName","DrawerRoot","isVisible","onClose","Root","open","onOpenChange","nextVisible","modal","Portal","DrawerScrollableContent","isContentExpanded","data-collapsed","ScrollArea","DrawerCloseButton","label","formatMessage","useIntl","labelMessage","id","defaultMessage","onClick","variant","Cross","Drawer","Body","ScrollableContent","CloseButton","Title","Description"],"mappings":"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"}
@@ -55,7 +55,14 @@ const DrawerContainer = styled(Flex)`
55
55
  flex-direction: column;
56
56
  position: fixed;
57
57
  bottom: 0;
58
+ /* Mobile: full-bleed sheet. Anchoring to the right at a fixed width left a
59
+ dead gutter on every phone wider than the panel, and the panel only filled
60
+ the screen once the viewport happened to be narrower than it. Below the
61
+ medium breakpoint the panel is the screen; medium+ restores the
62
+ right-anchored rail. */
63
+ left: 0;
58
64
  right: 0;
65
+ width: 100%;
59
66
  padding: ${({ theme })=>theme.spaces[2]};
60
67
  max-width: 100%;
61
68
  /* Sit just below the overlay token (300) so that:
@@ -65,8 +72,14 @@ const DrawerContainer = styled(Flex)`
65
72
  drawer (e.g. the asset details "delete" confirm) cover the drawer. */
66
73
  z-index: 200;
67
74
  overflow: hidden;
68
- width: ${({ width })=>width ?? '400px'};
69
- max-height: ${({ maxHeight })=>maxHeight ?? '100vh'};
75
+ /* dvh, not vh: anchored to the bottom, a 100vh cap on mobile (visual
76
+ viewport < 100vh under the URL bar) would push the drawer top off-screen. */
77
+ max-height: ${({ $maxHeight })=>$maxHeight ?? '100dvh'};
78
+
79
+ ${({ theme })=>theme.breakpoints.medium} {
80
+ left: auto;
81
+ width: ${({ $width })=>$width ?? '400px'};
82
+ }
70
83
 
71
84
  &:focus {
72
85
  outline: none;
@@ -114,7 +127,7 @@ const CloseIconButton = styled(IconButton)`
114
127
  background: transparent;
115
128
  }
116
129
  `;
117
- const DrawerBody = /*#__PURE__*/ React.forwardRef(({ animationDirection, children, ...props }, ref)=>/*#__PURE__*/ jsx(Dialog.Content, {
130
+ const DrawerBody = /*#__PURE__*/ React.forwardRef(({ animationDirection, width, maxHeight, children, ...props }, ref)=>/*#__PURE__*/ jsx(Dialog.Content, {
118
131
  ref: ref,
119
132
  forceMount: true,
120
133
  asChild: true,
@@ -123,6 +136,8 @@ const DrawerBody = /*#__PURE__*/ React.forwardRef(({ animationDirection, childre
123
136
  "data-animation-direction": animationDirection,
124
137
  children: /*#__PURE__*/ jsx(DrawerContainer, {
125
138
  $animationDirection: animationDirection,
139
+ $width: width,
140
+ $maxHeight: maxHeight,
126
141
  ...props,
127
142
  children: /*#__PURE__*/ jsx(DrawerContent, {
128
143
  children: children
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.mjs","sources":["../../../../admin/src/future/components/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport * as Dialog from '@radix-ui/react-dialog';\nimport { Box, ScrollArea, IconButton, Flex, FlexProps } from '@strapi/design-system';\nimport { Cross } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { keyframes, styled } from 'styled-components';\n\n/** Duration of the close animation in ms. Use for timing cleanup (e.g. removing URL params). */\nexport const DRAWER_CLOSE_ANIMATION_MS = 300;\n\n/* -------------------------------------------------------------------------------------------------\n * Animations\n * -----------------------------------------------------------------------------------------------*/\n\n// Direction: up\nconst slideUpFromBottomIn = keyframes`\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n`;\n\nconst slideUpFromBottomOut = keyframes`\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n`;\n\n// Direction: left\nconst slideLeftFromRightIn = keyframes`\n from {\n opacity: 0;\n transform: translateX(100%);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\nconst slideLeftFromRightOut = keyframes`\n from {\n opacity: 1;\n transform: translateX(0);\n }\n to {\n opacity: 0;\n transform: translateX(100%);\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Styled components\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerContainerProps {\n $animationDirection?: DrawerBodyProps['animationDirection'];\n}\n\nconst DrawerContainer = styled(Flex)<DrawerContainerProps>`\n flex-direction: column;\n position: fixed;\n bottom: 0;\n right: 0;\n padding: ${({ theme }) => theme.spaces[2]};\n max-width: 100%;\n /* Sit just below the overlay token (300) so that:\n - popovers (500) and tooltips (1000) rendered from descendant components\n surface above the drawer panel,\n - AlertDialog overlays (300) and contents (310) opened from inside the\n drawer (e.g. the asset details \"delete\" confirm) cover the drawer. */\n z-index: 200;\n overflow: hidden;\n width: ${({ width }) => width ?? '400px'};\n max-height: ${({ maxHeight }) => maxHeight ?? '100vh'};\n\n &:focus {\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n &[data-state='open'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomIn : slideLeftFromRightIn}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n }\n\n &[data-state='closed'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomOut : slideLeftFromRightOut}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n pointer-events: none;\n }\n }\n`;\n\nconst DrawerContent = styled(Box)`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n background-color: ${({ theme }) => theme.colors.neutral0};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n overflow: hidden;\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\ninterface CollapsibleContentProps {\n $isVisible: boolean;\n}\n\nconst CollapsibleContent = styled(Box)<CollapsibleContentProps>`\n display: grid;\n flex: 1;\n min-height: 0;\n grid-template-rows: ${({ $isVisible }) => ($isVisible ? '1fr' : '0fr')};\n transition: grid-template-rows 0.3s ease-in-out;\n\n > div {\n overflow: hidden;\n min-height: 0;\n }\n`;\n\nconst CloseIconButton = styled(IconButton)`\n &:hover {\n background: transparent;\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Body\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerBodyProps extends FlexProps {\n animationDirection?: 'up' | 'left';\n children: React.ReactNode;\n}\n\nconst DrawerBody = React.forwardRef<HTMLDivElement, DrawerBodyProps>(\n ({ animationDirection, children, ...props }, ref) => (\n <Dialog.Content\n ref={ref}\n forceMount\n asChild\n onPointerDownOutside={(e) => e.preventDefault()}\n onInteractOutside={(e) => e.preventDefault()}\n data-animation-direction={animationDirection}\n >\n <DrawerContainer $animationDirection={animationDirection} {...props}>\n <DrawerContent>{children}</DrawerContent>\n </DrawerContainer>\n </Dialog.Content>\n )\n);\nDrawerBody.displayName = 'DrawerBody';\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Root\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerRootProps {\n isVisible?: boolean;\n onClose?: () => void;\n children: React.ReactNode;\n}\n\nconst DrawerRoot = ({ isVisible, onClose, children }: DrawerRootProps): React.ReactElement => (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(nextVisible) => !nextVisible && onClose?.()}\n modal={false}\n >\n <Dialog.Portal>{children}</Dialog.Portal>\n </Dialog.Root>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Content - composable content slot (collapsible when isContentExpanded is used)\n * Contains a scrollable area\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerScrollableContentProps {\n children: React.ReactNode;\n /** When provided, content can collapse/expand (e.g. for minimize). Omit to always show. */\n isContentExpanded?: boolean;\n}\n\nconst DrawerScrollableContent = ({\n children,\n isContentExpanded = true,\n}: DrawerScrollableContentProps) => (\n <CollapsibleContent $isVisible={isContentExpanded} data-collapsed={!isContentExpanded}>\n <ScrollArea>{children}</ScrollArea>\n </CollapsibleContent>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.CloseButton - composable close icon button (Cross icon by default)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerCloseButtonProps extends React.PropsWithChildren {\n onClose: () => void;\n label?: string;\n}\n\nconst DrawerCloseButton = ({ onClose, label, children }: DrawerCloseButtonProps) => {\n const { formatMessage } = useIntl();\n const labelMessage = label ?? formatMessage({ id: 'global.close', defaultMessage: 'Close' });\n return (\n <CloseIconButton onClick={onClose} label={labelMessage} variant=\"ghost\">\n {children ?? <Cross />}\n </CloseIconButton>\n );\n};\n\nconst Drawer = {\n Root: DrawerRoot,\n Body: DrawerBody,\n ScrollableContent: DrawerScrollableContent,\n CloseButton: DrawerCloseButton,\n Title: Dialog.Title,\n Description: Dialog.Description,\n};\n\nexport { Drawer };\n"],"names":["DRAWER_CLOSE_ANIMATION_MS","slideUpFromBottomIn","keyframes","slideUpFromBottomOut","slideLeftFromRightIn","slideLeftFromRightOut","DrawerContainer","styled","Flex","theme","spaces","width","maxHeight","$animationDirection","DrawerContent","Box","colors","neutral0","borderRadius","shadows","popupShadow","neutral150","CollapsibleContent","$isVisible","CloseIconButton","IconButton","DrawerBody","React","forwardRef","animationDirection","children","props","ref","_jsx","Dialog","Content","forceMount","asChild","onPointerDownOutside","e","preventDefault","onInteractOutside","data-animation-direction","displayName","DrawerRoot","isVisible","onClose","Root","open","onOpenChange","nextVisible","modal","Portal","DrawerScrollableContent","isContentExpanded","data-collapsed","ScrollArea","DrawerCloseButton","label","formatMessage","useIntl","labelMessage","id","defaultMessage","onClick","variant","Cross","Drawer","Body","ScrollableContent","CloseButton","Title","Description"],"mappings":"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"}
1
+ {"version":3,"file":"Drawer.mjs","sources":["../../../../admin/src/future/components/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport * as Dialog from '@radix-ui/react-dialog';\nimport { Box, ScrollArea, IconButton, Flex, FlexProps } from '@strapi/design-system';\nimport { Cross } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { keyframes, styled } from 'styled-components';\n\n/** Duration of the close animation in ms. Use for timing cleanup (e.g. removing URL params). */\nexport const DRAWER_CLOSE_ANIMATION_MS = 300;\n\n/* -------------------------------------------------------------------------------------------------\n * Animations\n * -----------------------------------------------------------------------------------------------*/\n\n// Direction: up\nconst slideUpFromBottomIn = keyframes`\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n`;\n\nconst slideUpFromBottomOut = keyframes`\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n`;\n\n// Direction: left\nconst slideLeftFromRightIn = keyframes`\n from {\n opacity: 0;\n transform: translateX(100%);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n`;\n\nconst slideLeftFromRightOut = keyframes`\n from {\n opacity: 1;\n transform: translateX(0);\n }\n to {\n opacity: 0;\n transform: translateX(100%);\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Styled components\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerContainerProps {\n $animationDirection?: DrawerBodyProps['animationDirection'];\n $width?: string;\n $maxHeight?: string;\n}\n\nconst DrawerContainer = styled(Flex)<DrawerContainerProps>`\n flex-direction: column;\n position: fixed;\n bottom: 0;\n /* Mobile: full-bleed sheet. Anchoring to the right at a fixed width left a\n dead gutter on every phone wider than the panel, and the panel only filled\n the screen once the viewport happened to be narrower than it. Below the\n medium breakpoint the panel is the screen; medium+ restores the\n right-anchored rail. */\n left: 0;\n right: 0;\n width: 100%;\n padding: ${({ theme }) => theme.spaces[2]};\n max-width: 100%;\n /* Sit just below the overlay token (300) so that:\n - popovers (500) and tooltips (1000) rendered from descendant components\n surface above the drawer panel,\n - AlertDialog overlays (300) and contents (310) opened from inside the\n drawer (e.g. the asset details \"delete\" confirm) cover the drawer. */\n z-index: 200;\n overflow: hidden;\n /* dvh, not vh: anchored to the bottom, a 100vh cap on mobile (visual\n viewport < 100vh under the URL bar) would push the drawer top off-screen. */\n max-height: ${({ $maxHeight }) => $maxHeight ?? '100dvh'};\n\n ${({ theme }) => theme.breakpoints.medium} {\n left: auto;\n width: ${({ $width }) => $width ?? '400px'};\n }\n\n &:focus {\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n &[data-state='open'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomIn : slideLeftFromRightIn}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n }\n\n &[data-state='closed'] {\n animation: ${({ $animationDirection }) =>\n $animationDirection === 'up' ? slideUpFromBottomOut : slideLeftFromRightOut}\n ${DRAWER_CLOSE_ANIMATION_MS}ms cubic-bezier(0.32, 0.72, 0, 1) forwards;\n pointer-events: none;\n }\n }\n`;\n\nconst DrawerContent = styled(Box)`\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n background-color: ${({ theme }) => theme.colors.neutral0};\n border-radius: ${({ theme }) => theme.borderRadius};\n box-shadow: ${({ theme }) => theme.shadows.popupShadow};\n overflow: hidden;\n border: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\ninterface CollapsibleContentProps {\n $isVisible: boolean;\n}\n\nconst CollapsibleContent = styled(Box)<CollapsibleContentProps>`\n display: grid;\n flex: 1;\n min-height: 0;\n grid-template-rows: ${({ $isVisible }) => ($isVisible ? '1fr' : '0fr')};\n transition: grid-template-rows 0.3s ease-in-out;\n\n > div {\n overflow: hidden;\n min-height: 0;\n }\n`;\n\nconst CloseIconButton = styled(IconButton)`\n &:hover {\n background: transparent;\n }\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Body\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerBodyProps extends Omit<FlexProps, 'width' | 'maxHeight'> {\n animationDirection?: 'up' | 'left';\n /** Width of the panel from the medium breakpoint up. Mobile is always full-bleed. */\n width?: string;\n /** Cap on the panel height. Defaults to the dynamic viewport height. */\n maxHeight?: string;\n children: React.ReactNode;\n}\n\nconst DrawerBody = React.forwardRef<HTMLDivElement, DrawerBodyProps>(\n ({ animationDirection, width, maxHeight, children, ...props }, ref) => (\n <Dialog.Content\n ref={ref}\n forceMount\n asChild\n onPointerDownOutside={(e) => e.preventDefault()}\n onInteractOutside={(e) => e.preventDefault()}\n data-animation-direction={animationDirection}\n >\n {/* width/maxHeight go through transient props so the DS Flex never emits a\n competing `width` rule that would outrank the mobile full-bleed one. */}\n <DrawerContainer\n $animationDirection={animationDirection}\n $width={width}\n $maxHeight={maxHeight}\n {...props}\n >\n <DrawerContent>{children}</DrawerContent>\n </DrawerContainer>\n </Dialog.Content>\n )\n);\nDrawerBody.displayName = 'DrawerBody';\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Root\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerRootProps {\n isVisible?: boolean;\n onClose?: () => void;\n children: React.ReactNode;\n}\n\nconst DrawerRoot = ({ isVisible, onClose, children }: DrawerRootProps): React.ReactElement => (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(nextVisible) => !nextVisible && onClose?.()}\n modal={false}\n >\n <Dialog.Portal>{children}</Dialog.Portal>\n </Dialog.Root>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.Content - composable content slot (collapsible when isContentExpanded is used)\n * Contains a scrollable area\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerScrollableContentProps {\n children: React.ReactNode;\n /** When provided, content can collapse/expand (e.g. for minimize). Omit to always show. */\n isContentExpanded?: boolean;\n}\n\nconst DrawerScrollableContent = ({\n children,\n isContentExpanded = true,\n}: DrawerScrollableContentProps) => (\n <CollapsibleContent $isVisible={isContentExpanded} data-collapsed={!isContentExpanded}>\n <ScrollArea>{children}</ScrollArea>\n </CollapsibleContent>\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Drawer.CloseButton - composable close icon button (Cross icon by default)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DrawerCloseButtonProps extends React.PropsWithChildren {\n onClose: () => void;\n label?: string;\n}\n\nconst DrawerCloseButton = ({ onClose, label, children }: DrawerCloseButtonProps) => {\n const { formatMessage } = useIntl();\n const labelMessage = label ?? formatMessage({ id: 'global.close', defaultMessage: 'Close' });\n return (\n <CloseIconButton onClick={onClose} label={labelMessage} variant=\"ghost\">\n {children ?? <Cross />}\n </CloseIconButton>\n );\n};\n\nconst Drawer = {\n Root: DrawerRoot,\n Body: DrawerBody,\n ScrollableContent: DrawerScrollableContent,\n CloseButton: DrawerCloseButton,\n Title: Dialog.Title,\n Description: Dialog.Description,\n};\n\nexport { Drawer };\n"],"names":["DRAWER_CLOSE_ANIMATION_MS","slideUpFromBottomIn","keyframes","slideUpFromBottomOut","slideLeftFromRightIn","slideLeftFromRightOut","DrawerContainer","styled","Flex","theme","spaces","$maxHeight","breakpoints","medium","$width","$animationDirection","DrawerContent","Box","colors","neutral0","borderRadius","shadows","popupShadow","neutral150","CollapsibleContent","$isVisible","CloseIconButton","IconButton","DrawerBody","React","forwardRef","animationDirection","width","maxHeight","children","props","ref","_jsx","Dialog","Content","forceMount","asChild","onPointerDownOutside","e","preventDefault","onInteractOutside","data-animation-direction","displayName","DrawerRoot","isVisible","onClose","Root","open","onOpenChange","nextVisible","modal","Portal","DrawerScrollableContent","isContentExpanded","data-collapsed","ScrollArea","DrawerCloseButton","label","formatMessage","useIntl","labelMessage","id","defaultMessage","onClick","variant","Cross","Drawer","Body","ScrollableContent","CloseButton","Title","Description"],"mappings":"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"}
@@ -14,7 +14,7 @@ var Drawer = require('./Drawer.js');
14
14
 
15
15
  /* -------------------------------------------------------------------------------------------------
16
16
  * DialogHeader
17
- * -----------------------------------------------------------------------------------------------*/ const HeaderStatusMessage = ({ title, subtitle })=>{
17
+ * -----------------------------------------------------------------------------------------------*/ const HeaderStatusMessage = ({ title, subtitle, metadataSubtitle })=>{
18
18
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
19
19
  direction: "column",
20
20
  alignItems: "flex-start",
@@ -32,6 +32,11 @@ var Drawer = require('./Drawer.js');
32
32
  textColor: "neutral600",
33
33
  children: subtitle
34
34
  })
35
+ }),
36
+ metadataSubtitle && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
37
+ variant: "pi",
38
+ textColor: "neutral600",
39
+ children: metadataSubtitle
35
40
  })
36
41
  ]
37
42
  });
@@ -48,8 +53,52 @@ const HeaderStatusIcon = styledComponents.styled(designSystem.Flex)`
48
53
  const HeaderStatusWrapper = styledComponents.styled(designSystem.Flex)`
49
54
  align-items: center;
50
55
  `;
51
- const HeaderStatus = ({ status, progress, totalFiles, successfulCount, errorCount })=>{
56
+ const HeaderStatus = ({ status, progress, totalFiles, successfulCount, errorCount, metadataProgress, isGeneratingMetadata, metadataOutcome })=>{
52
57
  const { formatMessage } = reactIntl.useIntl();
58
+ // Completion is upload-driven, so the terminal header can appear while metadata is
59
+ // still generating — the subtitle keeps ticking underneath until it settles.
60
+ //
61
+ // Gated on work actually being in flight rather than on `progress < 100`: in a
62
+ // sequential batch the percentage touches 100% between files, which would blink the
63
+ // subtitle out and back in on every upload.
64
+ //
65
+ // Once the phase settles the line is not dropped but replaced with the outcome, so the
66
+ // header keeps confirming what happened instead of silently losing the message.
67
+ const metadataSubtitle = (()=>{
68
+ if (metadataProgress !== null && isGeneratingMetadata) {
69
+ return formatMessage({
70
+ id: translations.getTranslationKey('upload.progress.generatingMetadata.withCount'),
71
+ defaultMessage: 'Generating metadata with AI ({percentage}%)'
72
+ }, {
73
+ percentage: metadataProgress
74
+ });
75
+ }
76
+ if (metadataOutcome === null) {
77
+ return undefined;
78
+ }
79
+ // Only `generated` rows had metadata written, so only they can be reported as a
80
+ // success. With none, there is nothing to confirm — an all-skipped batch of
81
+ // non-images would otherwise read as "generated on 0 files". Per-row sublines
82
+ // already spell out skipped and failed outcomes.
83
+ if (metadataOutcome.generated === 0) {
84
+ return undefined;
85
+ }
86
+ if (metadataOutcome.failed > 0) {
87
+ return formatMessage({
88
+ id: translations.getTranslationKey('upload.progress.metadataGenerated.withFailures'),
89
+ defaultMessage: '{generatedCount} generated, {failedCount} failed'
90
+ }, {
91
+ generatedCount: metadataOutcome.generated,
92
+ failedCount: metadataOutcome.failed
93
+ });
94
+ }
95
+ return formatMessage({
96
+ id: translations.getTranslationKey('upload.progress.metadataGenerated.withCount'),
97
+ defaultMessage: '{count, plural, one {Metadata successfully generated on # file} other {Metadata successfully generated on # files}}'
98
+ }, {
99
+ count: metadataOutcome.generated
100
+ });
101
+ })();
53
102
  if (status === 'error') {
54
103
  return /*#__PURE__*/ jsxRuntime.jsxs(HeaderStatusWrapper, {
55
104
  children: [
@@ -98,7 +147,8 @@ const HeaderStatus = ({ status, progress, totalFiles, successfulCount, errorCoun
98
147
  id: translations.getTranslationKey('upload.progress.success'),
99
148
  defaultMessage: 'Upload successful!'
100
149
  }),
101
- subtitle: subtitle
150
+ subtitle: subtitle,
151
+ metadataSubtitle: metadataSubtitle
102
152
  })
103
153
  ]
104
154
  });
@@ -120,7 +170,8 @@ const HeaderStatus = ({ status, progress, totalFiles, successfulCount, errorCoun
120
170
  subtitle: formatMessage({
121
171
  id: translations.getTranslationKey('upload.progress.canceled.subtitle'),
122
172
  defaultMessage: 'Some files were not uploaded'
123
- })
173
+ }),
174
+ metadataSubtitle: metadataSubtitle
124
175
  })
125
176
  ]
126
177
  });
@@ -142,7 +193,8 @@ const HeaderStatus = ({ status, progress, totalFiles, successfulCount, errorCoun
142
193
  }, {
143
194
  total: totalFiles,
144
195
  percentage: progressPercentage
145
- })
196
+ }),
197
+ metadataSubtitle: metadataSubtitle
146
198
  })
147
199
  ]
148
200
  });
@@ -177,6 +229,9 @@ const DialogHeader = ({ handleClose })=>{
177
229
  const { formatMessage } = reactIntl.useIntl();
178
230
  const { isMinimized, files, uploadId, totalFiles } = hooks.useTypedSelector((state)=>state.uploadProgress);
179
231
  const progress = hooks.useTypedSelector(uploadProgress.selectAggregateProgress);
232
+ const metadataProgress = hooks.useTypedSelector(uploadProgress.selectMetadataProgress);
233
+ const isGeneratingMetadata = hooks.useTypedSelector(uploadProgress.selectIsGeneratingMetadata);
234
+ const metadataOutcome = hooks.useTypedSelector(uploadProgress.selectMetadataOutcome);
180
235
  const dispatch = hooks.useTypedDispatch();
181
236
  const [retryCancelledFiles] = api.useRetryCancelledFilesMutation();
182
237
  // The batch is complete once every file has reached a terminal state. Byte-weighted
@@ -220,7 +275,10 @@ const DialogHeader = ({ handleClose })=>{
220
275
  progress: progress,
221
276
  totalFiles: totalFiles,
222
277
  successfulCount: successfulCount,
223
- errorCount: errorCount
278
+ errorCount: errorCount,
279
+ metadataProgress: metadataProgress,
280
+ isGeneratingMetadata: isGeneratingMetadata,
281
+ metadataOutcome: metadataOutcome
224
282
  }),
225
283
  /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
226
284
  gap: 1,
@@ -230,7 +288,7 @@ const DialogHeader = ({ handleClose })=>{
230
288
  fontWeight: "bold",
231
289
  children: formatMessage({
232
290
  id: translations.getTranslationKey('upload.progress.cancel'),
233
- defaultMessage: 'Cancel'
291
+ defaultMessage: 'Cancel all'
234
292
  })
235
293
  }),
236
294
  hasCancelledFiles && /*#__PURE__*/ jsxRuntime.jsx(designSystem.TextButton, {
@@ -293,6 +351,52 @@ const DeterminateBar = ({ percent })=>{
293
351
  })
294
352
  });
295
353
  };
354
+ const INDETERMINATE_INDICATOR_WIDTH = 40;
355
+ /**
356
+ * `translateX` percentages resolve against the *indicator's* own width, not the track's.
357
+ * So -100% is exactly "fully off the left edge" regardless of the width above, and the
358
+ * end offset converts a full track width into those same own-width units. Both ends sit
359
+ * flush off-track, which keeps entry and exit symmetric — a smaller start offset would
360
+ * make the bar pop in already partly visible.
361
+ */ const indeterminateSlide = styledComponents.keyframes`
362
+ from {
363
+ transform: translateX(-100%);
364
+ }
365
+ to {
366
+ transform: translateX(${100 / INDETERMINATE_INDICATOR_WIDTH * 100}%);
367
+ }
368
+ `;
369
+ const IndeterminateIndicator = styledComponents.styled.div`
370
+ height: 100%;
371
+ width: ${INDETERMINATE_INDICATOR_WIDTH}%;
372
+ background-color: ${({ theme })=>theme.colors.primary700};
373
+ border-radius: 4px;
374
+ /* Linear, not an eased curve: the DS easings decelerate to a stop, which on a loop
375
+ reads as a stall at the wrap point. Constant speed is what makes it read as a sweep. */
376
+ animation: ${indeterminateSlide} 1.2s linear infinite;
377
+
378
+ /* A perpetually moving bar is a vestibular trigger; fall back to a static track fill. */
379
+ @media (prefers-reduced-motion: reduce) {
380
+ animation: none;
381
+ width: 100%;
382
+ opacity: 0.5;
383
+ }
384
+ `;
385
+ /**
386
+ * Progress bar for work whose completion fraction is genuinely unknowable, rather
387
+ * than merely unknown-yet: the AI metadata endpoint answers in one go, and the URL
388
+ * flow can't report bytes until the server has fetched the file and knows its size.
389
+ *
390
+ * Deliberately omits `aria-valuenow` — that absence is precisely how ARIA conveys
391
+ * an indeterminate progressbar, so assistive tech announces "busy" instead of "0%".
392
+ */ const IndeterminateBar = ()=>{
393
+ return /*#__PURE__*/ jsxRuntime.jsx(ProgressTrack, {
394
+ role: "progressbar",
395
+ "aria-valuemin": 0,
396
+ "aria-valuemax": 100,
397
+ children: /*#__PURE__*/ jsxRuntime.jsx(IndeterminateIndicator, {})
398
+ });
399
+ };
296
400
  const FileRow = ({ icon, fileName, children })=>{
297
401
  return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
298
402
  direction: "column",
@@ -317,6 +421,62 @@ const FileRow = ({ icon, fileName, children })=>{
317
421
  ]
318
422
  });
319
423
  };
424
+ /**
425
+ * Icon + subline for a successfully uploaded row, keyed by its metadata phase.
426
+ * `'none'` covers rows that never entered the phase — AI metadata disabled — and
427
+ * renders exactly as before this feature existed. Non-images do enter the phase and
428
+ * land on `skipped`.
429
+ *
430
+ * `skipped` uses a neutral `Information` icon, deliberately distinct from
431
+ * generated/failed/cancelled — skipping is an expected outcome for a non-image, not a
432
+ * problem to flag.
433
+ */ const COMPLETED_ROW_PRESENTATION = {
434
+ none: {
435
+ icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
436
+ fill: "success500"
437
+ }),
438
+ message: {
439
+ id: translations.getTranslationKey('upload.progress.file.uploaded'),
440
+ defaultMessage: 'Uploaded'
441
+ }
442
+ },
443
+ generating: {
444
+ icon: /*#__PURE__*/ jsxRuntime.jsx(icons.Sparkle, {
445
+ fill: "primary600"
446
+ }),
447
+ message: {
448
+ id: translations.getTranslationKey('upload.progress.file.generatingMetadata'),
449
+ defaultMessage: 'Uploaded • Generating metadata…'
450
+ }
451
+ },
452
+ generated: {
453
+ icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
454
+ fill: "success500"
455
+ }),
456
+ message: {
457
+ id: translations.getTranslationKey('upload.progress.file.metadataGenerated'),
458
+ defaultMessage: 'Uploaded • Metadata generated'
459
+ }
460
+ },
461
+ skipped: {
462
+ icon: /*#__PURE__*/ jsxRuntime.jsx(icons.Information, {
463
+ fill: "neutral500"
464
+ }),
465
+ message: {
466
+ id: translations.getTranslationKey('upload.progress.file.metadataSkipped'),
467
+ defaultMessage: 'Upload complete • Metadata generation skipped'
468
+ }
469
+ },
470
+ failed: {
471
+ icon: /*#__PURE__*/ jsxRuntime.jsx(icons.WarningCircle, {
472
+ fill: "warning500"
473
+ }),
474
+ message: {
475
+ id: translations.getTranslationKey('upload.progress.file.metadataFailed'),
476
+ defaultMessage: 'Upload complete • Metadata generation failed'
477
+ }
478
+ }
479
+ };
320
480
  const FileRowRenderer = ({ file })=>{
321
481
  const { formatMessage } = reactIntl.useIntl();
322
482
  const isError = file.status === 'error';
@@ -324,7 +484,16 @@ const FileRowRenderer = ({ file })=>{
324
484
  const isCompleted = file.status === 'complete';
325
485
  const isCancelled = file.status === 'cancelled';
326
486
  if (isCurrentFile) {
327
- const percent = file.size > 0 ? file.uploadedBytes / file.size * 100 : 0;
487
+ // Determinate only once bytes are actually being reported a known `size` is not
488
+ // enough. The two upload flows differ here:
489
+ // - the direct-file flow streams real byte counts from XHR, so `uploadedBytes`
490
+ // climbs and a determinate bar is meaningful;
491
+ // - the URL flow learns the size from the `file:uploading` SSE event but receives
492
+ // no incremental counts at all (the next event is `file:complete`), so
493
+ // `uploadedBytes` stays 0 for the whole transfer.
494
+ // Keying off `size` alone froze URL rows at a determinate 0% for the entire upload;
495
+ // keying off reported bytes keeps them animating until there is a fraction to show.
496
+ const hasReportedProgress = file.size > 0 && file.uploadedBytes > 0;
328
497
  return /*#__PURE__*/ jsxRuntime.jsxs(FileRow, {
329
498
  icon: /*#__PURE__*/ jsxRuntime.jsx(icons.ArrowsCounterClockwise, {
330
499
  fill: "secondary600"
@@ -339,9 +508,9 @@ const FileRowRenderer = ({ file })=>{
339
508
  defaultMessage: 'Uploading...'
340
509
  })
341
510
  }),
342
- /*#__PURE__*/ jsxRuntime.jsx(DeterminateBar, {
343
- percent: percent
344
- })
511
+ hasReportedProgress ? /*#__PURE__*/ jsxRuntime.jsx(DeterminateBar, {
512
+ percent: file.uploadedBytes / file.size * 100
513
+ }) : /*#__PURE__*/ jsxRuntime.jsx(IndeterminateBar, {})
345
514
  ]
346
515
  });
347
516
  }
@@ -375,19 +544,20 @@ const FileRowRenderer = ({ file })=>{
375
544
  });
376
545
  }
377
546
  if (isCompleted) {
378
- return /*#__PURE__*/ jsxRuntime.jsx(FileRow, {
379
- icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
380
- fill: "success500"
381
- }),
547
+ // The upload succeeded; the metadata phase (if any) drives both the icon and the
548
+ // subline from here on — a metadata failure shows a warning, not an upload error.
549
+ const { icon, message } = COMPLETED_ROW_PRESENTATION[file.metadataStatus ?? 'none'];
550
+ return /*#__PURE__*/ jsxRuntime.jsxs(FileRow, {
551
+ icon: icon,
382
552
  fileName: file.name,
383
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
384
- variant: "pi",
385
- textColor: "neutral600",
386
- children: formatMessage({
387
- id: translations.getTranslationKey('upload.progress.file.uploaded'),
388
- defaultMessage: 'Uploaded'
389
- })
390
- })
553
+ children: [
554
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
555
+ variant: "pi",
556
+ textColor: "neutral600",
557
+ children: formatMessage(message)
558
+ }),
559
+ file.metadataStatus === 'generating' && /*#__PURE__*/ jsxRuntime.jsx(IndeterminateBar, {})
560
+ ]
391
561
  });
392
562
  }
393
563
  return null;
@@ -400,7 +570,10 @@ const CompletedFilesList = styledComponents.styled(designSystem.Flex)`
400
570
  const UploadProgressDialog = ()=>{
401
571
  const dispatch = hooks.useTypedDispatch();
402
572
  const { isVisible, isMinimized, files } = hooks.useTypedSelector((state)=>state.uploadProgress);
403
- const currentFile = files.find((f)=>f.status === 'uploading');
573
+ // With concurrent uploads several files are `uploading` at once — render every
574
+ // in-flight row, not just the first (a `find` here dated to the strictly
575
+ // sequential era and hid all but the lowest-index worker's row).
576
+ const uploadingFiles = files.filter((f)=>f.status === 'uploading');
404
577
  const completedFiles = files.filter((f)=>f.status === 'complete' || f.status === 'error' || f.status === 'cancelled').sort((a, b)=>{
405
578
  // Sort priority: error > cancelled > complete
406
579
  const priority = {
@@ -437,9 +610,9 @@ const UploadProgressDialog = ()=>{
437
610
  paddingLeft: 4,
438
611
  paddingRight: 4,
439
612
  children: [
440
- currentFile && /*#__PURE__*/ jsxRuntime.jsx(FileRowRenderer, {
441
- file: currentFile
442
- }),
613
+ uploadingFiles.map((file)=>/*#__PURE__*/ jsxRuntime.jsx(FileRowRenderer, {
614
+ file: file
615
+ }, file.index)),
443
616
  completedFiles.length > 0 && /*#__PURE__*/ jsxRuntime.jsx(CompletedFilesList, {
444
617
  children: completedFiles.map((file)=>/*#__PURE__*/ jsxRuntime.jsx(FileRowRenderer, {
445
618
  file: file