@strapi/upload 5.51.1 → 5.51.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/dist/admin/components/AssetCard/VideoPreview.js +1 -1
  2. package/dist/admin/components/AssetCard/VideoPreview.js.map +1 -1
  3. package/dist/admin/components/AssetCard/VideoPreview.mjs +1 -1
  4. package/dist/admin/components/AssetCard/VideoPreview.mjs.map +1 -1
  5. package/dist/admin/components/TableList/TableList.js +1 -1
  6. package/dist/admin/components/TableList/TableList.js.map +1 -1
  7. package/dist/admin/components/TableList/TableList.mjs +1 -1
  8. package/dist/admin/components/TableList/TableList.mjs.map +1 -1
  9. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js +21 -4
  10. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js.map +1 -1
  11. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs +21 -4
  12. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs.map +1 -1
  13. package/dist/admin/future/components/Drawer.js +3 -1
  14. package/dist/admin/future/components/Drawer.js.map +1 -1
  15. package/dist/admin/future/components/Drawer.mjs +3 -1
  16. package/dist/admin/future/components/Drawer.mjs.map +1 -1
  17. package/dist/admin/future/components/UploadProgressDialog.js +200 -27
  18. package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
  19. package/dist/admin/future/components/UploadProgressDialog.mjs +203 -30
  20. package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
  21. package/dist/admin/future/hooks/useMediaLibraryPermissions.js +35 -0
  22. package/dist/admin/future/hooks/useMediaLibraryPermissions.js.map +1 -0
  23. package/dist/admin/future/hooks/useMediaLibraryPermissions.mjs +33 -0
  24. package/dist/admin/future/hooks/useMediaLibraryPermissions.mjs.map +1 -0
  25. package/dist/admin/future/pages/Assets/AssetsPage.js +203 -78
  26. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  27. package/dist/admin/future/pages/Assets/AssetsPage.mjs +200 -75
  28. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  29. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +75 -32
  30. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  31. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +75 -32
  32. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  33. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +46 -19
  34. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  35. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +47 -20
  36. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  37. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +5 -2
  38. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
  39. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +5 -2
  40. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  41. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +100 -0
  42. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -0
  43. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +98 -0
  44. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -0
  45. package/dist/admin/future/pages/Assets/components/AssetsTable.js +10 -4
  46. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
  47. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +10 -4
  48. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
  49. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +140 -22
  50. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
  51. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +142 -24
  52. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
  53. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.js +193 -0
  54. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.js.map +1 -0
  55. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.mjs +191 -0
  56. package/dist/admin/future/pages/Assets/components/DateRangeCalendar.mjs.map +1 -0
  57. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +18 -1
  58. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
  59. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +18 -1
  60. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
  61. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js +13 -3
  62. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -1
  63. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +13 -3
  64. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -1
  65. package/dist/admin/future/pages/Assets/components/EmptyState.js +62 -3
  66. package/dist/admin/future/pages/Assets/components/EmptyState.js.map +1 -1
  67. package/dist/admin/future/pages/Assets/components/EmptyState.mjs +62 -4
  68. package/dist/admin/future/pages/Assets/components/EmptyState.mjs.map +1 -1
  69. package/dist/admin/future/pages/Assets/components/FilterBadges.js +408 -0
  70. package/dist/admin/future/pages/Assets/components/FilterBadges.js.map +1 -0
  71. package/dist/admin/future/pages/Assets/components/FilterBadges.mjs +406 -0
  72. package/dist/admin/future/pages/Assets/components/FilterBadges.mjs.map +1 -0
  73. package/dist/admin/future/pages/Assets/components/FilterMenu.js +273 -0
  74. package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -0
  75. package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +267 -0
  76. package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -0
  77. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +76 -19
  78. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  79. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +78 -21
  80. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  81. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js +33 -0
  82. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js.map +1 -0
  83. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs +31 -0
  84. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs.map +1 -0
  85. package/dist/admin/future/pages/Assets/components/SortMenu.js +21 -32
  86. package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
  87. package/dist/admin/future/pages/Assets/components/SortMenu.mjs +22 -33
  88. package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
  89. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.js +40 -0
  90. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.js.map +1 -0
  91. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.mjs +38 -0
  92. package/dist/admin/future/pages/Assets/hooks/useAssetSearch.mjs.map +1 -0
  93. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +21 -5
  94. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  95. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +21 -5
  96. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  97. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.js +33 -12
  98. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.js.map +1 -1
  99. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.mjs +33 -12
  100. package/dist/admin/future/pages/Assets/hooks/useFolderNavigation.mjs.map +1 -1
  101. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +40 -4
  102. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
  103. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +40 -4
  104. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
  105. package/dist/admin/future/pages/Assets/hooks/useListFilters.js +168 -0
  106. package/dist/admin/future/pages/Assets/hooks/useListFilters.js.map +1 -0
  107. package/dist/admin/future/pages/Assets/hooks/useListFilters.mjs +162 -0
  108. package/dist/admin/future/pages/Assets/hooks/useListFilters.mjs.map +1 -0
  109. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.js +201 -0
  110. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.js.map +1 -0
  111. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.mjs +198 -0
  112. package/dist/admin/future/pages/Assets/utils/buildAssetFilters.mjs.map +1 -0
  113. package/dist/admin/future/pages/Assets/utils/listQueryKey.js +2 -2
  114. package/dist/admin/future/pages/Assets/utils/listQueryKey.js.map +1 -1
  115. package/dist/admin/future/pages/Assets/utils/listQueryKey.mjs +2 -2
  116. package/dist/admin/future/pages/Assets/utils/listQueryKey.mjs.map +1 -1
  117. package/dist/admin/future/services/api.js +163 -28
  118. package/dist/admin/future/services/api.js.map +1 -1
  119. package/dist/admin/future/services/api.mjs +163 -30
  120. package/dist/admin/future/services/api.mjs.map +1 -1
  121. package/dist/admin/future/services/assets.js +29 -17
  122. package/dist/admin/future/services/assets.js.map +1 -1
  123. package/dist/admin/future/services/assets.mjs +29 -17
  124. package/dist/admin/future/services/assets.mjs.map +1 -1
  125. package/dist/admin/future/services/folders.js +29 -17
  126. package/dist/admin/future/services/folders.js.map +1 -1
  127. package/dist/admin/future/services/folders.mjs +29 -17
  128. package/dist/admin/future/services/folders.mjs.map +1 -1
  129. package/dist/admin/future/services/settings.js +10 -3
  130. package/dist/admin/future/services/settings.js.map +1 -1
  131. package/dist/admin/future/services/settings.mjs +10 -3
  132. package/dist/admin/future/services/settings.mjs.map +1 -1
  133. package/dist/admin/future/store/uploadProgress.js +109 -2
  134. package/dist/admin/future/store/uploadProgress.js.map +1 -1
  135. package/dist/admin/future/store/uploadProgress.mjs +105 -3
  136. package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
  137. package/dist/admin/future/utils/searchQueryParam.js +11 -0
  138. package/dist/admin/future/utils/searchQueryParam.js.map +1 -0
  139. package/dist/admin/future/utils/searchQueryParam.mjs +9 -0
  140. package/dist/admin/future/utils/searchQueryParam.mjs.map +1 -0
  141. package/dist/admin/hooks/useSelectionState.js +2 -4
  142. package/dist/admin/hooks/useSelectionState.js.map +1 -1
  143. package/dist/admin/hooks/useSelectionState.mjs +2 -4
  144. package/dist/admin/hooks/useSelectionState.mjs.map +1 -1
  145. package/dist/admin/shared/constants.js +43 -0
  146. package/dist/admin/shared/constants.js.map +1 -0
  147. package/dist/admin/shared/constants.mjs +38 -0
  148. package/dist/admin/shared/constants.mjs.map +1 -0
  149. package/dist/admin/src/future/hooks/useMediaLibraryPermissions.d.ts +21 -0
  150. package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetCropEditor.d.ts +7 -1
  151. package/dist/admin/src/future/pages/Assets/components/AssetsSearchInput.d.ts +5 -0
  152. package/dist/admin/src/future/pages/Assets/components/BulkActionsBar.d.ts +14 -1
  153. package/dist/admin/src/future/pages/Assets/components/DateRangeCalendar.d.ts +8 -0
  154. package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZoneContext.d.ts +8 -1
  155. package/dist/admin/src/future/pages/Assets/components/EmptyState.d.ts +18 -1
  156. package/dist/admin/src/future/pages/Assets/components/FilterBadges.d.ts +6 -0
  157. package/dist/admin/src/future/pages/Assets/components/FilterMenu.d.ts +22 -0
  158. package/dist/admin/src/future/pages/Assets/components/FolderTree/FolderTree.d.ts +13 -4
  159. package/dist/admin/src/future/pages/Assets/components/FolderTree/filterFolderTree.d.ts +16 -0
  160. package/dist/admin/src/future/pages/Assets/components/SortMenu.d.ts +6 -0
  161. package/dist/admin/src/future/pages/Assets/hooks/useAssetSearch.d.ts +12 -0
  162. package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +8 -1
  163. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +13 -3
  164. package/dist/admin/src/future/pages/Assets/hooks/useListFilters.d.ts +69 -0
  165. package/dist/admin/src/future/pages/Assets/utils/buildAssetFilters.d.ts +46 -0
  166. package/dist/admin/src/future/pages/Assets/utils/listQueryKey.d.ts +3 -4
  167. package/dist/admin/src/future/services/api.d.ts +53 -5
  168. package/dist/admin/src/future/services/assets.d.ts +9 -1
  169. package/dist/admin/src/future/services/folders.d.ts +3 -0
  170. package/dist/admin/src/future/services/settings.d.ts +2 -2
  171. package/dist/admin/src/future/store/uploadProgress.d.ts +83 -1
  172. package/dist/admin/src/future/utils/searchQueryParam.d.ts +7 -0
  173. package/dist/admin/src/hooks/useAiAvailability.d.ts +1 -1
  174. package/dist/admin/src/hooks/useEditAsset.d.ts +4 -4
  175. package/dist/admin/src/hooks/useEditFolder.d.ts +4 -4
  176. package/dist/admin/src/hooks/useSettings.d.ts +1 -0
  177. package/dist/admin/src/hooks/useTracking.d.ts +1 -1
  178. package/dist/admin/src/hooks/useUpload.d.ts +1 -1
  179. package/dist/admin/translations/en.json.js +53 -3
  180. package/dist/admin/translations/en.json.js.map +1 -1
  181. package/dist/admin/translations/en.json.mjs +53 -3
  182. package/dist/admin/translations/en.json.mjs.map +1 -1
  183. package/dist/admin/utils/urlYupSchema.js +33 -9
  184. package/dist/admin/utils/urlYupSchema.js.map +1 -1
  185. package/dist/admin/utils/urlYupSchema.mjs +33 -9
  186. package/dist/admin/utils/urlYupSchema.mjs.map +1 -1
  187. package/dist/server/config.js +13 -5
  188. package/dist/server/config.js.map +1 -1
  189. package/dist/server/config.mjs +13 -5
  190. package/dist/server/config.mjs.map +1 -1
  191. package/dist/server/constants.js.map +1 -1
  192. package/dist/server/constants.mjs.map +1 -1
  193. package/dist/server/controllers/admin-file.js +30 -0
  194. package/dist/server/controllers/admin-file.js.map +1 -1
  195. package/dist/server/controllers/admin-file.mjs +30 -0
  196. package/dist/server/controllers/admin-file.mjs.map +1 -1
  197. package/dist/server/controllers/admin-settings.js +20 -2
  198. package/dist/server/controllers/admin-settings.js.map +1 -1
  199. package/dist/server/controllers/admin-settings.mjs +21 -3
  200. package/dist/server/controllers/admin-settings.mjs.map +1 -1
  201. package/dist/server/controllers/content-api.js +1 -2
  202. package/dist/server/controllers/content-api.js.map +1 -1
  203. package/dist/server/controllers/content-api.mjs +2 -2
  204. package/dist/server/controllers/content-api.mjs.map +1 -1
  205. package/dist/server/controllers/validation/admin/ai-metadata.js +12 -0
  206. package/dist/server/controllers/validation/admin/ai-metadata.js.map +1 -0
  207. package/dist/server/controllers/validation/admin/ai-metadata.mjs +10 -0
  208. package/dist/server/controllers/validation/admin/ai-metadata.mjs.map +1 -0
  209. package/dist/server/controllers/validation/admin/settings.js +4 -1
  210. package/dist/server/controllers/validation/admin/settings.js.map +1 -1
  211. package/dist/server/controllers/validation/admin/settings.mjs +1 -1
  212. package/dist/server/controllers/validation/admin/settings.mjs.map +1 -1
  213. package/dist/server/routes/admin.js +18 -0
  214. package/dist/server/routes/admin.js.map +1 -1
  215. package/dist/server/routes/admin.mjs +18 -0
  216. package/dist/server/routes/admin.mjs.map +1 -1
  217. package/dist/server/services/ai-metadata.js +108 -11
  218. package/dist/server/services/ai-metadata.js.map +1 -1
  219. package/dist/server/services/ai-metadata.mjs +108 -11
  220. package/dist/server/services/ai-metadata.mjs.map +1 -1
  221. package/dist/server/services/file.js +86 -13
  222. package/dist/server/services/file.js.map +1 -1
  223. package/dist/server/services/file.mjs +87 -14
  224. package/dist/server/services/file.mjs.map +1 -1
  225. package/dist/server/services/image-manipulation.js +4 -4
  226. package/dist/server/services/image-manipulation.js.map +1 -1
  227. package/dist/server/services/image-manipulation.mjs +4 -4
  228. package/dist/server/services/image-manipulation.mjs.map +1 -1
  229. package/dist/server/shared/constants.js +43 -0
  230. package/dist/server/shared/constants.js.map +1 -0
  231. package/dist/server/shared/constants.mjs +38 -0
  232. package/dist/server/shared/constants.mjs.map +1 -0
  233. package/dist/server/src/config.d.ts +2 -0
  234. package/dist/server/src/config.d.ts.map +1 -1
  235. package/dist/server/src/constants.d.ts +2 -1
  236. package/dist/server/src/constants.d.ts.map +1 -1
  237. package/dist/server/src/controllers/admin-file.d.ts +10 -0
  238. package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
  239. package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
  240. package/dist/server/src/controllers/index.d.ts +1 -0
  241. package/dist/server/src/controllers/index.d.ts.map +1 -1
  242. package/dist/server/src/controllers/validation/admin/ai-metadata.d.ts +2 -0
  243. package/dist/server/src/controllers/validation/admin/ai-metadata.d.ts.map +1 -0
  244. package/dist/server/src/controllers/validation/admin/settings.d.ts +1 -1
  245. package/dist/server/src/controllers/validation/admin/settings.d.ts.map +1 -1
  246. package/dist/server/src/index.d.ts +7 -1
  247. package/dist/server/src/index.d.ts.map +1 -1
  248. package/dist/server/src/routes/admin.d.ts.map +1 -1
  249. package/dist/server/src/services/ai-metadata.d.ts +19 -0
  250. package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
  251. package/dist/server/src/services/file.d.ts +12 -2
  252. package/dist/server/src/services/file.d.ts.map +1 -1
  253. package/dist/server/src/services/index.d.ts +4 -1
  254. package/dist/server/src/services/index.d.ts.map +1 -1
  255. package/dist/server/src/types.d.ts +3 -0
  256. package/dist/server/src/types.d.ts.map +1 -1
  257. package/dist/shared/constants.d.ts +35 -0
  258. package/dist/shared/constants.d.ts.map +1 -0
  259. package/dist/shared/contracts/files.d.ts +25 -0
  260. package/dist/shared/contracts/files.d.ts.map +1 -1
  261. package/dist/shared/contracts/settings.d.ts +7 -0
  262. package/package.json +7 -7
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Constants shared by the upload server and the admin panel.
3
+ *
4
+ * The server stays authoritative — it validates and rejects — but the admin
5
+ * needs the same values to disable actions up front rather than letting the
6
+ * user discover a limit through a failed request.
7
+ */ /**
8
+ * Image formats the AI metadata provider can read.
9
+ *
10
+ * Anything outside this list (non-images, but also exotic image formats like
11
+ * SVG or TIFF) is reported as `skipped` instead of being sent.
12
+ *
13
+ * @see https://ai.google.dev/gemini-api/docs/image-understanding
14
+ */ const AI_METADATA_SUPPORTED_IMAGE_TYPES = [
15
+ 'image/png',
16
+ 'image/jpeg',
17
+ 'image/webp',
18
+ 'image/heic',
19
+ 'image/heif'
20
+ ];
21
+ /**
22
+ * Whether the AI metadata provider can generate metadata for this mime type.
23
+ */ const isAIMetadataSupportedMime = (mime)=>AI_METADATA_SUPPORTED_IMAGE_TYPES.includes(mime);
24
+ /**
25
+ * Number of images sent to the AI server per request when generating metadata
26
+ * for an explicit selection. Matches the URL cap of the bulk URL upload flow.
27
+ */ const AI_METADATA_CHUNK_SIZE = 20;
28
+ /**
29
+ * Upper bound on a single synchronous AI metadata request.
30
+ *
31
+ * The selection is processed in sequential chunks inside one HTTP request, so
32
+ * an unbounded selection means an unbounded request — long past most proxy and
33
+ * load balancer timeouts, with no way for the client to learn what was written.
34
+ * Rejecting with a 400 lets the UI ask for a smaller selection instead.
35
+ */ const AI_METADATA_MAX_FILES = AI_METADATA_CHUNK_SIZE * 2;
36
+
37
+ export { AI_METADATA_CHUNK_SIZE, AI_METADATA_MAX_FILES, AI_METADATA_SUPPORTED_IMAGE_TYPES, isAIMetadataSupportedMime };
38
+ //# sourceMappingURL=constants.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.mjs","sources":["../../../shared/constants.ts"],"sourcesContent":["/**\n * Constants shared by the upload server and the admin panel.\n *\n * The server stays authoritative — it validates and rejects — but the admin\n * needs the same values to disable actions up front rather than letting the\n * user discover a limit through a failed request.\n */\n\n/**\n * Image formats the AI metadata provider can read.\n *\n * Anything outside this list (non-images, but also exotic image formats like\n * SVG or TIFF) is reported as `skipped` instead of being sent.\n *\n * @see https://ai.google.dev/gemini-api/docs/image-understanding\n */\nexport const AI_METADATA_SUPPORTED_IMAGE_TYPES = [\n 'image/png',\n 'image/jpeg',\n 'image/webp',\n 'image/heic',\n 'image/heif',\n] as const;\n\nexport type AIMetadataSupportedImageType = (typeof AI_METADATA_SUPPORTED_IMAGE_TYPES)[number];\n\n/**\n * Whether the AI metadata provider can generate metadata for this mime type.\n */\nexport const isAIMetadataSupportedMime = (mime?: string | null): boolean =>\n AI_METADATA_SUPPORTED_IMAGE_TYPES.includes(mime as AIMetadataSupportedImageType);\n\n/**\n * Number of images sent to the AI server per request when generating metadata\n * for an explicit selection. Matches the URL cap of the bulk URL upload flow.\n */\nexport const AI_METADATA_CHUNK_SIZE = 20;\n\n/**\n * Upper bound on a single synchronous AI metadata request.\n *\n * The selection is processed in sequential chunks inside one HTTP request, so\n * an unbounded selection means an unbounded request — long past most proxy and\n * load balancer timeouts, with no way for the client to learn what was written.\n * Rejecting with a 400 lets the UI ask for a smaller selection instead.\n */\nexport const AI_METADATA_MAX_FILES = AI_METADATA_CHUNK_SIZE * 2;\n"],"names":["AI_METADATA_SUPPORTED_IMAGE_TYPES","isAIMetadataSupportedMime","mime","includes","AI_METADATA_CHUNK_SIZE","AI_METADATA_MAX_FILES"],"mappings":"AAAA;;;;;;;;;;;;;UAgBaA,iCAAAA,GAAoC;AAC/C,IAAA,WAAA;AACA,IAAA,YAAA;AACA,IAAA,YAAA;AACA,IAAA,YAAA;AACA,IAAA;;AAKF;;UAGaC,yBAAAA,GAA4B,CAACC,OACxCF,iCAAAA,CAAkCG,QAAQ,CAACD,IAAAA;AAE7C;;;IAIO,MAAME,sBAAAA,GAAyB;AAEtC;;;;;;;AAOC,IACM,MAAMC,qBAAAA,GAAwBD,sBAAAA,GAAyB;;;;"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * RBAC gate for the future Media Library UI. Mirrors the legacy hook of the
3
+ * same name: the server already enforces every action route-side (assets and
4
+ * folder operations share the asset permissions — folder create requires
5
+ * `assets.create`, folder rename/move/delete require `assets.update`); this
6
+ * hook is what keeps the UI honest so users don't discover a missing
7
+ * permission through a 403.
8
+ *
9
+ * - `canCreate` — upload (files, from URL) and New folder
10
+ * - `canUpdate` — edit details, replace, crop, move (dnd + bulk), delete
11
+ * (single + bulk), AI metadata — the `assets.update` action covers
12
+ * "Update (crop, details, replace) + delete" by definition
13
+ * - `canDownload` / `canCopyLink` — the matching drawer actions
14
+ */
15
+ export declare const useMediaLibraryPermissions: () => {
16
+ isLoading: boolean;
17
+ canCreate: boolean;
18
+ canUpdate: boolean;
19
+ canDownload: boolean;
20
+ canCopyLink: boolean;
21
+ };
@@ -5,6 +5,12 @@ interface AssetCropEditorProps {
5
5
  onClose: () => void;
6
6
  onApply: (file: globalThis.File, focalPoint: FocalPoint) => void;
7
7
  onSaveAsCopy: (file: globalThis.File, focalPoint: FocalPoint) => void;
8
+ /**
9
+ * "Save as copy" creates a new asset (`assets.create`), a different permission
10
+ * from cropping in place (`assets.update`). Hidden when the user lacks it, so
11
+ * an update-only role can't trigger a 403.
12
+ */
13
+ canSaveAsCopy: boolean;
8
14
  }
9
- export declare const AssetCropEditor: ({ asset, isBusy, onClose, onApply, onSaveAsCopy, }: AssetCropEditorProps) => import("react/jsx-runtime").JSX.Element;
15
+ export declare const AssetCropEditor: ({ asset, isBusy, onClose, onApply, onSaveAsCopy, canSaveAsCopy, }: AssetCropEditorProps) => import("react/jsx-runtime").JSX.Element;
10
16
  export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Keyword search over the whole Media Library. Owns the typing state and the
3
+ * debounce; `useAssetSearch` owns the `?_q=` URL param.
4
+ */
5
+ export declare const AssetsSearchInput: () => import("react/jsx-runtime").JSX.Element;
@@ -1 +1,14 @@
1
- export declare const BulkActionsBar: () => import("react/jsx-runtime").JSX.Element | null;
1
+ import type { File } from '../../../../../../shared/contracts/files';
2
+ interface BulkActionsBarProps {
3
+ /**
4
+ * The assets currently rendered in the list, used to resolve the mime types
5
+ * of the selection — the bar needs them to know which selected assets the AI
6
+ * provider can actually read.
7
+ *
8
+ * Selection is page-scoped and cleared whenever the list identity changes, so
9
+ * every selected asset id is guaranteed to appear here.
10
+ */
11
+ assets?: File[];
12
+ }
13
+ export declare const BulkActionsBar: ({ assets }: BulkActionsBarProps) => import("react/jsx-runtime").JSX.Element | null;
14
+ export {};
@@ -0,0 +1,8 @@
1
+ interface DateRangeCalendarProps {
2
+ /** `YYYY-MM-DD`, both set when editing an existing range badge. */
3
+ from?: string;
4
+ to?: string;
5
+ onSelect: (from: string, to: string) => void;
6
+ }
7
+ export declare const DateRangeCalendar: ({ from, to, onSelect }: DateRangeCalendarProps) => import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -3,8 +3,15 @@ type DropHandler = (files: File[]) => void | Promise<void>;
3
3
  interface UploadDropZoneProps {
4
4
  children: ReactNode;
5
5
  onDrop?: DropHandler;
6
+ /**
7
+ * When true, the zone never enters the dragging state and never fires
8
+ * `onDrop` — no overlay, no "drop here" invitation. Used to hide the whole
9
+ * upload affordance from users without `assets.create`, so they don't drag a
10
+ * file onto an inviting target that then silently discards it.
11
+ */
12
+ disabled?: boolean;
6
13
  }
7
- export declare const UploadDropZoneProvider: ({ children, onDrop }: UploadDropZoneProps) => import("react/jsx-runtime").JSX.Element;
14
+ export declare const UploadDropZoneProvider: ({ children, onDrop, disabled, }: UploadDropZoneProps) => import("react/jsx-runtime").JSX.Element;
8
15
  export declare const useUploadDropZone: () => {
9
16
  isDragging: boolean;
10
17
  };
@@ -1,5 +1,13 @@
1
1
  interface EmptyStateProps {
2
2
  onAddAssets: () => void;
3
+ /**
4
+ * RBAC gate — without `assets.create` the "Add assets" CTA is hidden.
5
+ * Required (not defaulted) so a permission gate can't silently regress to
6
+ * permissive when a future call site forgets to pass it.
7
+ */
8
+ canAddAssets: boolean;
9
+ searchQuery?: string;
10
+ onClearSearch?: () => void;
3
11
  }
4
12
  /**
5
13
  * Empty state for the assets list (both views) when the current folder holds
@@ -7,5 +15,14 @@ interface EmptyStateProps {
7
15
  * as New > File upload; drag-and-drop upload keeps working since the page-wide
8
16
  * drop zone wraps this component.
9
17
  */
10
- export declare const EmptyState: ({ onAddAssets }: EmptyStateProps) => import("react/jsx-runtime").JSX.Element;
18
+ export declare const EmptyState: ({ onAddAssets, canAddAssets, searchQuery, onClearSearch, }: EmptyStateProps) => import("react/jsx-runtime").JSX.Element;
19
+ interface FilteredEmptyStateProps {
20
+ onClearFilters: () => void;
21
+ }
22
+ /**
23
+ * Empty state when active filters match nothing (including contradictory
24
+ * badges — allowed by design). Distinct from the no-content state: the library
25
+ * has items, the filters exclude them all.
26
+ */
27
+ export declare const FilteredEmptyState: ({ onClearFilters }: FilteredEmptyStateProps) => import("react/jsx-runtime").JSX.Element;
11
28
  export {};
@@ -0,0 +1,6 @@
1
+ import { type ListFilters } from '../hooks/useListFilters';
2
+ interface FilterBadgesProps {
3
+ listFilters: ListFilters;
4
+ }
5
+ export declare const FilterBadges: ({ listFilters }: FilterBadgesProps) => import("react/jsx-runtime").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,22 @@
1
+ import { type DateField, type DatePreset, type ListFilters, type TypeValue } from '../hooks/useListFilters';
2
+ import type { MessageDescriptor } from 'react-intl';
3
+ export declare const TYPE_LABELS: Record<TypeValue, MessageDescriptor>;
4
+ export declare const PRESET_LABELS: Record<DatePreset, MessageDescriptor>;
5
+ export declare const DATE_FIELD_LABELS: Record<DateField, MessageDescriptor>;
6
+ /** Every panel of the filter tree shares this fixed width (design). */
7
+ export declare const FILTER_PANEL_WIDTH = "24.2rem";
8
+ interface FilterMenuProps {
9
+ listFilters: ListFilters;
10
+ }
11
+ /**
12
+ * Toolbar "Filter" dropdown. Picking anything ADDS a badge (editing happens on
13
+ * the badge itself, see FilterBadges):
14
+ *
15
+ * - Type → keep-open checkbox list; the badge is created/updated live with the
16
+ * checked set (`is` by default, condition editable on the badge).
17
+ * - Creation date / Last modified → preset list (single pick, `within the
18
+ * last` by default) + "Select date range" (creation date only) opening the
19
+ * range calendar; a completed range adds an `is` range badge.
20
+ */
21
+ export declare const FilterMenu: ({ listFilters }: FilterMenuProps) => import("react/jsx-runtime").JSX.Element;
22
+ export {};
@@ -1,5 +1,10 @@
1
1
  interface FolderTreeProps {
2
2
  currentFolderId: number | null;
3
+ /**
4
+ * Set to `false` while a global asset search is active: the results span the
5
+ * whole library, so highlighting one folder would misrepresent them.
6
+ * */
7
+ showActiveFolder?: boolean;
3
8
  onSelectFolder: (folderId: number | null) => void;
4
9
  }
5
10
  /**
@@ -7,13 +12,17 @@ interface FolderTreeProps {
7
12
  * and renders:
8
13
  *
9
14
  * 1. A "Media library" title
10
- * 2. A "Home" entry that clears the folder query param
11
- * 3. A "FOLDERS" section header
12
- * 4. The folder tree itself
15
+ * 2. A filter input that prunes the tree to matching destinations
16
+ * 3. A "Home" entry that clears the folder query param
17
+ * 4. A "FOLDERS" section header
18
+ * 5. The folder tree itself
19
+ *
20
+ * The filter is purely local: it never touches the URL and never affects the
21
+ * asset list, which has its own independent search in the content toolbar.
13
22
  *
14
23
  * Presentational with respect to routing — navigation is delegated to the parent
15
24
  * via `onSelectFolder` so the URL stays the single source of truth (see
16
25
  * `useFolderNavigation`).
17
26
  */
18
- export declare const FolderTree: ({ currentFolderId, onSelectFolder }: FolderTreeProps) => import("react/jsx-runtime").JSX.Element;
27
+ export declare const FolderTree: ({ currentFolderId, showActiveFolder, onSelectFolder, }: FolderTreeProps) => import("react/jsx-runtime").JSX.Element;
19
28
  export {};
@@ -0,0 +1,16 @@
1
+ import type { FolderNode } from '../../../../../../../shared/contracts/folders';
2
+ interface FilterFolderTreeResult {
3
+ nodes: FolderNode[];
4
+ /**
5
+ * Ancestors of a match, which have to be expanded for the match to be
6
+ * reachable.
7
+ */
8
+ expandedIds: number[];
9
+ }
10
+ /**
11
+ * Prunes the folder tree to nodes that match, or that have a matching
12
+ * descendant, so a match deep in the hierarchy stays reachable with its ancestor
13
+ * chain intact.
14
+ */
15
+ export declare const filterFolderTree: (nodes: FolderNode[], matches: (name: string) => boolean) => FilterFolderTreeResult;
16
+ export {};
@@ -12,6 +12,12 @@ interface SortMenuProps {
12
12
  * option keeps the menu open (`onSelect` preventDefault) so several facets can
13
13
  * be tuned in one visit; clicking a checked facet clears it (the hook
14
14
  * guarantees at least one sort rule stays active).
15
+ *
16
+ * Each section is single-select, so its items are radios: the checkmark icon is
17
+ * decorative, and `aria-checked` is what assistive tech reads. The DS `Menu`
18
+ * exposes no `RadioItem`, but `Menu.Item` forwards extra props onto the element
19
+ * it renders through Radix's `asChild`, where they take precedence over Radix's
20
+ * own `role="menuitem"`.
15
21
  */
16
22
  export declare const SortMenu: ({ sort, showFoldersGroup }: SortMenuProps) => import("react/jsx-runtime").JSX.Element;
17
23
  export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Reads and writes the global asset search term held in `?_q=`.
3
+ *
4
+ * Debouncing is the input component's job (see `AssetsSearchInput`) — this hook
5
+ * is a thin URL accessor so every consumer reads the same source of truth.
6
+ */
7
+ export declare const useAssetSearch: () => {
8
+ searchQuery: string;
9
+ isSearching: boolean;
10
+ setSearchQuery: (value: string) => void;
11
+ clearSearch: () => void;
12
+ };
@@ -32,8 +32,15 @@ export interface AssetSelection {
32
32
  }
33
33
  interface AssetSelectionProviderProps {
34
34
  children: ReactNode;
35
+ /**
36
+ * When true, selection is inert: every mutator is a no-op and nothing ever
37
+ * reads as selected. Every bulk action is gated on `assets.update`, so a user
38
+ * without it has nothing to select for — the views also hide the checkboxes,
39
+ * and this makes the remaining paths (click-to-select, Space key) do nothing.
40
+ */
41
+ disabled?: boolean;
35
42
  }
36
- export declare const AssetSelectionProvider: ({ children }: AssetSelectionProviderProps) => import("react").FunctionComponentElement<import("react").ProviderProps<AssetSelection | null>>;
43
+ export declare const AssetSelectionProvider: ({ children, disabled, }: AssetSelectionProviderProps) => import("react").FunctionComponentElement<import("react").ProviderProps<AssetSelection | null>>;
37
44
  export declare const useAssetSelection: () => AssetSelection;
38
45
  export declare const useAssetSelectionOptional: () => AssetSelection | null;
39
46
  export {};
@@ -1,12 +1,22 @@
1
- import type { File } from '../../../../../../shared/contracts/files';
1
+ import type { File, Pagination } from '../../../../../../shared/contracts/files';
2
2
  declare const PAGE_SIZE = 20;
3
3
  interface UseInfiniteAssetsOptions {
4
4
  folder?: number | null;
5
5
  sort?: string;
6
+ search?: string;
7
+ /** Extra `filters[$and]` entries for the files query. */
8
+ filters?: Record<string, unknown>[];
9
+ /**
10
+ * Stable fingerprint of `filters` — a change resets the accumulated pages
11
+ * (the array identity itself changes every render).
12
+ */
13
+ filtersKey?: string;
14
+ /** Structural switch: an `is [folder]`-only type badge means no file can match. */
15
+ enabled?: boolean;
6
16
  }
7
- declare const useInfiniteAssets: ({ folder, sort }?: UseInfiniteAssetsOptions) => {
17
+ declare const useInfiniteAssets: ({ folder, sort, search, filters, filtersKey, enabled, }?: UseInfiniteAssetsOptions) => {
8
18
  assets: File[];
9
- pagination: import("../../../../../../shared/contracts/files").Pagination | undefined;
19
+ pagination: Pagination | undefined;
10
20
  isLoading: boolean;
11
21
  isFetchingMore: boolean;
12
22
  hasNextPage: boolean;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Filter state for the assets list, backed by a single `?filters=` query param
3
+ * so the applied filters are shareable and survive Back/refresh.
4
+ *
5
+ * Serialized grammar — badges separated by `;`, one badge is
6
+ * `<field>:<condition>:<value>`:
7
+ *
8
+ * - `type:is:picture,audio` / `type:not:folder`
9
+ * - `created:within:1week` / `updated:notwithin:3months` / `created:exact:1day`
10
+ * - `created:rangeis:2024-01-01..2024-04-07` / `created:rangenot:...`
11
+ *
12
+ * Relative presets stay relative in the URL on purpose: the badge label
13
+ * ("1 week ago") remains truthful forever and a shared link means "within the
14
+ * last week from whenever it is opened". Resolution to absolute timestamps
15
+ * happens at query-build time (see utils/buildAssetFilters.ts).
16
+ *
17
+ * Several badges for the same field are allowed, even contradictory ones —
18
+ * everything is combined with AND; contradictions simply produce the filtered
19
+ * empty state.
20
+ */
21
+ export declare const TYPE_VALUES: readonly ["folder", "picture", "audio", "video", "document"];
22
+ export type TypeValue = (typeof TYPE_VALUES)[number];
23
+ export declare const DATE_PRESETS: readonly ["1day", "3days", "1week", "1month", "3months", "6months", "1year"];
24
+ export type DatePreset = (typeof DATE_PRESETS)[number];
25
+ export type TypeCondition = 'is' | 'isNot';
26
+ export type PresetCondition = 'isExactly' | 'withinLast' | 'notWithinLast';
27
+ export type RangeCondition = 'is' | 'isNot';
28
+ export type DateField = 'createdAt' | 'updatedAt';
29
+ export interface TypeFilter {
30
+ kind: 'type';
31
+ condition: TypeCondition;
32
+ values: TypeValue[];
33
+ }
34
+ export interface DatePresetFilter {
35
+ kind: 'date';
36
+ field: DateField;
37
+ mode: 'preset';
38
+ condition: PresetCondition;
39
+ preset: DatePreset;
40
+ }
41
+ export interface DateRangeFilter {
42
+ kind: 'date';
43
+ field: DateField;
44
+ mode: 'range';
45
+ condition: RangeCondition;
46
+ /** Calendar dates, `YYYY-MM-DD`, inclusive on both ends. */
47
+ from: string;
48
+ to: string;
49
+ }
50
+ export type DateFilter = DatePresetFilter | DateRangeFilter;
51
+ export type ListFilter = TypeFilter | DateFilter;
52
+ /**
53
+ * `unknown` on purpose: the query string is user-editable, and qs parses
54
+ * shapes like `?filters[]=a&filters[]=b` into arrays — the guard is what
55
+ * makes the caller's `?filters=` type an assertion rather than a crash.
56
+ */
57
+ export declare const parseFiltersParam: (raw: unknown) => ListFilter[];
58
+ export declare const serializeFilters: (filters: ListFilter[]) => string;
59
+ export interface ListFilters {
60
+ filters: ListFilter[];
61
+ /** Serialized form — stable fingerprint for list-identity (selection reset). */
62
+ serialized: string;
63
+ addFilter: (filter: ListFilter) => void;
64
+ /** Replaces the badge at `index` (condition or value edited in place). */
65
+ updateFilter: (index: number, filter: ListFilter) => void;
66
+ removeFilter: (index: number) => void;
67
+ clearFilters: () => void;
68
+ }
69
+ export declare const useListFilters: () => ListFilters;
@@ -0,0 +1,46 @@
1
+ import { type ListFilter } from '../hooks/useListFilters';
2
+ /**
3
+ * Translates the URL filter model into Strapi `filters[$and]` entries for the
4
+ * files and folders queries, and decides the structural visibility of both
5
+ * sections.
6
+ *
7
+ * Relative presets resolve against `now` at build time — the URL stays
8
+ * relative ("within the last week"), only the outgoing query is absolute.
9
+ *
10
+ * Semantics:
11
+ * - Every badge is one `$and` entry (badges combine with AND, per ticket).
12
+ * - Type: `folder` is not a mime — it acts structurally on the folders
13
+ * section. The remaining values map to mime clauses; `document` is the
14
+ * legacy catch-all (mime contains none of image/audio/video — audio
15
+ * included in the exclusion, fixing the legacy quirk).
16
+ * - Dates apply to files and folders alike (folders have both timestamps).
17
+ * - "is exactly <preset>" means the calendar day of `now - delta`.
18
+ * - Ranges are inclusive on both ends (start-of-day .. end-of-day).
19
+ */
20
+ type QueryClause = Record<string, unknown>;
21
+ /**
22
+ * Parses `YYYY-MM-DD` as a local calendar date — NOT `new Date(value)`, which
23
+ * treats date-only strings as UTC midnight and shifts the day in every
24
+ * timezone west of UTC. Shared by the query builder, the badge labels and the
25
+ * range calendar so all three agree on which day a range endpoint means.
26
+ */
27
+ export declare const parseCalendarDate: (value: string) => Date;
28
+ export interface BuiltFilters {
29
+ /** Extra `$and` entries for the files query. */
30
+ fileClauses: QueryClause[];
31
+ /** Extra `$and` entries for the folders query (dates only). */
32
+ folderClauses: QueryClause[];
33
+ /**
34
+ * Whether the folders section can show at all. A type badge decides it by
35
+ * evaluating "folder" like any other value: `is` shows folders only when
36
+ * folder is selected; `is not` hides them only when folder is selected.
37
+ */
38
+ showFolders: boolean;
39
+ /**
40
+ * Whether the files list can show at all — false when an `is` type badge
41
+ * selects only "folder" (no file can match).
42
+ */
43
+ showFiles: boolean;
44
+ }
45
+ export declare const buildAssetFilters: (filters: ListFilter[], now: Date) => BuiltFilters;
46
+ export {};
@@ -9,14 +9,13 @@
9
9
  * same list, so the selection survives the toggle.
10
10
  * - Infinite scroll (load more) does NOT change any segment → selection persists.
11
11
  *
12
- * Search/filter use stable defaults until their header controls are wired;
13
- * follow-up PRs only pass real values — no selection logic changes needed.
12
+ * Filter uses a stable default until its header control is wired; that follow-up
13
+ * only passes a real value — no selection logic changes needed.
14
14
  */
15
15
  export interface ListQueryKeyInput {
16
16
  folderId: number | null;
17
- /** Empty string until search UI ships. */
18
17
  search: string;
19
- /** Null until sort UI ships. */
18
+ /** Composite of asset sort and folder position — both change the render order. */
20
19
  sort: string | null;
21
20
  /** Null until filter UI ships. */
22
21
  filter: string | null;
@@ -1,11 +1,20 @@
1
- import type { CreateFilesStream, File as UploadedFile, UploadFileInfo } from '../../../../shared/contracts/files';
1
+ import { Dispatch } from '@reduxjs/toolkit';
2
+ import type { CreateFilesStream, File as UploadedFile, UnstableGenerateAIMetadata, UploadFileInfo } from '../../../../shared/contracts/files';
2
3
  interface UploadFilesArgs {
3
4
  formData: FormData;
4
5
  totalFiles: number;
6
+ /**
7
+ * How many files to upload in parallel — the `concurrentUploadRequests`
8
+ * settings value. Defaults to 1 (sequential).
9
+ */
10
+ concurrency?: number;
11
+ /** Whether AI metadata generation is enabled (EE AI available + `settings.aiMetadata`). */
12
+ generateAiMetadata: boolean;
5
13
  }
6
14
  interface UploadFromUrlsArgs {
7
15
  urls: string[];
8
16
  folderId: number | null;
17
+ generateAiMetadata: boolean;
9
18
  }
10
19
  /**
11
20
  * A single file plus the `fileInfo` it was queued with.
@@ -22,10 +31,33 @@ interface UploadEntry {
22
31
  * Called from the UploadProgressDialog when the user clicks cancel or close.
23
32
  */
24
33
  export declare const abortUpload: (uploadId: number) => void;
34
+ /**
35
+ * Kicks off AI metadata generation for a freshly uploaded file.
36
+ *
37
+ * Deliberately fire-and-forget — the caller must NOT await it:
38
+ * - generation for file N overlaps the upload of file N+1;
39
+ * - a generation failure can never affect the upload result (the upload already
40
+ * succeeded), which is why the promise is fully swallowed here.
41
+ *
42
+ * Every uploaded file is sent, including non-images: the server already classifies
43
+ * them (`ai-metadata.generateForFiles` returns `skipped` for anything whose mime
44
+ * isn't `image/*`) and duplicating that rule here would let the two drift apart.
45
+ * The upshot is that a non-image now reports "Metadata generation skipped" rather
46
+ * than silently showing no metadata state at all.
47
+ */
48
+ export declare const maybeGenerateMetadata: ({ file, index, uploadId, enabled, dispatch, }: {
49
+ file: UploadedFile;
50
+ index: number;
51
+ uploadId: number;
52
+ enabled: boolean;
53
+ dispatch: Dispatch;
54
+ }) => void;
25
55
  declare const uploadApi: import("@reduxjs/toolkit/query").Api<import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, import("@reduxjs/toolkit/dist/query/endpointDefinitions").UpdateDefinitions<{}, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", never> & {
26
56
  /**
27
- * Upload files sequentially, one request per file, to `/upload/unstable/upload-file`.
28
- * Real per-file byte progress comes from `XHR.upload.onprogress`.
57
+ * Upload files to `/upload/unstable/upload-file`, one request per file,
58
+ * through a worker pool of `concurrency` parallel requests (default 1 =
59
+ * sequential). Real per-file byte progress comes from
60
+ * `XHR.upload.onprogress`.
29
61
  */
30
62
  uploadFiles: import("@reduxjs/toolkit/query").MutationDefinition<UploadFilesArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">;
31
63
  /**
@@ -39,7 +71,7 @@ declare const uploadApi: import("@reduxjs/toolkit/query").Api<import("@reduxjs/t
39
71
  /**
40
72
  * Retry uploading cancelled files.
41
73
  * Maps cancelled rows back to their original entries and re-runs only those
42
- * through the same sequential loop with a fresh AbortController.
74
+ * through the same upload pool with a fresh AbortController.
43
75
  */
44
76
  retryCancelledFiles: import("@reduxjs/toolkit/query").MutationDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">;
45
77
  /**
@@ -47,6 +79,22 @@ declare const uploadApi: import("@reduxjs/toolkit/query").Api<import("@reduxjs/t
47
79
  * Sends URLs to the server which fetches and uploads them (SSE flow, unchanged).
48
80
  */
49
81
  uploadFromUrls: import("@reduxjs/toolkit/query").MutationDefinition<UploadFromUrlsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", CreateFilesStream.Response, "adminApi">;
82
+ /**
83
+ * Generate AI metadata (alt text + caption) for the given assets.
84
+ * Synchronous: resolves once every file has been processed and reports the
85
+ * outcome per file, so non-images and individual failures don't fail the
86
+ * whole batch. Existing alt text and captions are never overwritten.
87
+ *
88
+ * Lives here rather than in `assets.ts` because the upload flows dispatch it
89
+ * directly via `initiate()` after each file completes, and `assets.ts` already
90
+ * imports from this module — defining it there would be a circular import.
91
+ * Re-exported from `assets.ts` for the components that consume the hook.
92
+ */
93
+ generateAiMetadata: import("@reduxjs/toolkit/query").MutationDefinition<{
94
+ fileIds: number[];
95
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UnstableGenerateAIMetadata.FileResult[], "adminApi">;
50
96
  }, "adminApi", "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/dist/query/react").reactHooksModuleName>;
51
- export declare const useUploadFilesMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadFilesArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">>, useUploadFileSilentlyMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadEntry, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile, "adminApi">>, useRetryCancelledFilesMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">>, useUploadFromUrlsMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadFromUrlsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", CreateFilesStream.Response, "adminApi">>;
97
+ export declare const useUploadFilesMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadFilesArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">>, useUploadFileSilentlyMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadEntry, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile, "adminApi">>, useRetryCancelledFilesMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UploadedFile[], "adminApi">>, useUploadFromUrlsMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UploadFromUrlsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", CreateFilesStream.Response, "adminApi">>, useGenerateAiMetadataMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
98
+ fileIds: number[];
99
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", UnstableGenerateAIMetadata.FileResult[], "adminApi">>;
52
100
  export { uploadApi };
@@ -4,6 +4,9 @@ interface GetAssetsParams {
4
4
  pageSize?: number;
5
5
  folder?: number | null;
6
6
  sort?: string;
7
+ search?: string;
8
+ /** Extra `filters[$and]` entries (list filters), AND-ed with the folder/search scope. */
9
+ filters?: Record<string, unknown>[];
7
10
  }
8
11
  interface GetAssetsResponse {
9
12
  results: File[];
@@ -22,4 +25,9 @@ export declare const useGetAssetsQuery: import("@reduxjs/toolkit/dist/query/reac
22
25
  fileIds: number[];
23
26
  folderIds: number[];
24
27
  }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", unknown, "adminApi">>;
25
- export {};
28
+ /**
29
+ * `generateAiMetadata` is defined in `./api` (the upload flows dispatch it directly
30
+ * after each file completes, and this module imports from there) — re-exported here
31
+ * so asset components keep a single import site for asset-related hooks.
32
+ */
33
+ export { useGenerateAiMetadataMutation } from './api';
@@ -11,6 +11,9 @@ interface GetFoldersParams {
11
11
  parentId?: number | null;
12
12
  /** Comma-separated rules, e.g. `updatedAt:DESC,name:ASC`. Defaults to alphabetical. */
13
13
  sort?: string;
14
+ search?: string;
15
+ /** Extra `filters[$and]` entries (list filters), AND-ed with the parent/search scope. */
16
+ filters?: Record<string, unknown>[];
14
17
  }
15
18
  interface BulkMoveParams {
16
19
  fileIds?: number[];
@@ -1,2 +1,2 @@
1
- declare const useGetSettingsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", import("../../../../shared/contracts/settings").Settings, "adminApi">>;
2
- export { useGetSettingsQuery };
1
+ declare const useGetUploadSettingsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@strapi/admin/strapi-admin").QueryArguments, unknown, import("@strapi/admin/strapi-admin").BaseQueryError | import("@reduxjs/toolkit").SerializedError, {}, {}>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AiUsage" | "AiFeatureConfig" | "Asset" | "Folder", import("../../../../shared/contracts/settings").Settings, "adminApi">>;
2
+ export { useGetUploadSettingsQuery };