@strapi/upload 5.59.0 → 5.61.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 (295) hide show
  1. package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.js +434 -0
  2. package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.js.map +1 -0
  3. package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.mjs +432 -0
  4. package/dist/admin/components/AssetPickerDialog/AssetPickerDialog.mjs.map +1 -0
  5. package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.js +91 -0
  6. package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.js.map +1 -0
  7. package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.mjs +89 -0
  8. package/dist/admin/components/AssetPickerDialog/FolderBreadcrumbs.mjs.map +1 -0
  9. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.js +29 -0
  10. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.js.map +1 -0
  11. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.mjs +27 -0
  12. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.mjs.map +1 -0
  13. package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.js +178 -0
  14. package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.js.map +1 -0
  15. package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.mjs +175 -0
  16. package/dist/admin/components/AssetPickerDialog/PickerSelectionProvider.mjs.map +1 -0
  17. package/dist/admin/components/AssetPickerDialog/SortableSelection.js +143 -0
  18. package/dist/admin/components/AssetPickerDialog/SortableSelection.js.map +1 -0
  19. package/dist/admin/components/AssetPickerDialog/SortableSelection.mjs +141 -0
  20. package/dist/admin/components/AssetPickerDialog/SortableSelection.mjs.map +1 -0
  21. package/dist/admin/components/AssetPickerDialog/pickerSelection.js +49 -0
  22. package/dist/admin/components/AssetPickerDialog/pickerSelection.js.map +1 -0
  23. package/dist/admin/components/AssetPickerDialog/pickerSelection.mjs +41 -0
  24. package/dist/admin/components/AssetPickerDialog/pickerSelection.mjs.map +1 -0
  25. package/dist/admin/components/Drawer.js +12 -7
  26. package/dist/admin/components/Drawer.js.map +1 -1
  27. package/dist/admin/components/Drawer.mjs +12 -7
  28. package/dist/admin/components/Drawer.mjs.map +1 -1
  29. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.js +188 -0
  30. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.js.map +1 -0
  31. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.mjs +186 -0
  32. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.mjs.map +1 -0
  33. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js +9 -4
  34. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js.map +1 -1
  35. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs +9 -4
  36. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs.map +1 -1
  37. package/dist/admin/components/MediaLibraryInput/AssetCard.js +240 -0
  38. package/dist/admin/components/MediaLibraryInput/AssetCard.js.map +1 -0
  39. package/dist/admin/components/MediaLibraryInput/AssetCard.mjs +237 -0
  40. package/dist/admin/components/MediaLibraryInput/AssetCard.mjs.map +1 -0
  41. package/dist/admin/components/MediaLibraryInput/AssetCarousel.js +161 -0
  42. package/dist/admin/components/MediaLibraryInput/AssetCarousel.js.map +1 -0
  43. package/dist/admin/components/MediaLibraryInput/AssetCarousel.mjs +159 -0
  44. package/dist/admin/components/MediaLibraryInput/AssetCarousel.mjs.map +1 -0
  45. package/dist/admin/components/MediaLibraryInput/AssetDropZone.js +76 -49
  46. package/dist/admin/components/MediaLibraryInput/AssetDropZone.js.map +1 -1
  47. package/dist/admin/components/MediaLibraryInput/AssetDropZone.mjs +77 -50
  48. package/dist/admin/components/MediaLibraryInput/AssetDropZone.mjs.map +1 -1
  49. package/dist/admin/components/MediaLibraryInput/AssetPreview.js +109 -0
  50. package/dist/admin/components/MediaLibraryInput/AssetPreview.js.map +1 -0
  51. package/dist/admin/components/MediaLibraryInput/AssetPreview.mjs +106 -0
  52. package/dist/admin/components/MediaLibraryInput/AssetPreview.mjs.map +1 -0
  53. package/dist/admin/components/MediaLibraryInput/AssetRow.js +146 -79
  54. package/dist/admin/components/MediaLibraryInput/AssetRow.js.map +1 -1
  55. package/dist/admin/components/MediaLibraryInput/AssetRow.mjs +148 -82
  56. package/dist/admin/components/MediaLibraryInput/AssetRow.mjs.map +1 -1
  57. package/dist/admin/components/MediaLibraryInput/FieldControls.js +32 -0
  58. package/dist/admin/components/MediaLibraryInput/FieldControls.js.map +1 -0
  59. package/dist/admin/components/MediaLibraryInput/FieldControls.mjs +29 -0
  60. package/dist/admin/components/MediaLibraryInput/FieldControls.mjs.map +1 -0
  61. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js +163 -111
  62. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -1
  63. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs +162 -114
  64. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -1
  65. package/dist/admin/components/MediaLibraryInput/UploadProgressBar.js +42 -0
  66. package/dist/admin/components/MediaLibraryInput/UploadProgressBar.js.map +1 -0
  67. package/dist/admin/components/MediaLibraryInput/UploadProgressBar.mjs +40 -0
  68. package/dist/admin/components/MediaLibraryInput/UploadProgressBar.mjs.map +1 -0
  69. package/dist/admin/components/MediaLibraryInput/openAssetDetails.js +46 -0
  70. package/dist/admin/components/MediaLibraryInput/openAssetDetails.js.map +1 -0
  71. package/dist/admin/components/MediaLibraryInput/openAssetDetails.mjs +43 -0
  72. package/dist/admin/components/MediaLibraryInput/openAssetDetails.mjs.map +1 -0
  73. package/dist/admin/components/MediaLibraryInput/useFieldUploads.js +122 -0
  74. package/dist/admin/components/MediaLibraryInput/useFieldUploads.js.map +1 -0
  75. package/dist/admin/components/MediaLibraryInput/useFieldUploads.mjs +120 -0
  76. package/dist/admin/components/MediaLibraryInput/useFieldUploads.mjs.map +1 -0
  77. package/dist/admin/components/UploadProgressDialog.js +2 -1
  78. package/dist/admin/components/UploadProgressDialog.js.map +1 -1
  79. package/dist/admin/components/UploadProgressDialog.mjs +2 -1
  80. package/dist/admin/components/UploadProgressDialog.mjs.map +1 -1
  81. package/dist/admin/hooks/useMediaLibraryPermissions.js +12 -2
  82. package/dist/admin/hooks/useMediaLibraryPermissions.js.map +1 -1
  83. package/dist/admin/hooks/useMediaLibraryPermissions.mjs +12 -2
  84. package/dist/admin/hooks/useMediaLibraryPermissions.mjs.map +1 -1
  85. package/dist/admin/index.js +10 -1
  86. package/dist/admin/index.js.map +1 -1
  87. package/dist/admin/index.mjs +10 -1
  88. package/dist/admin/index.mjs.map +1 -1
  89. package/dist/admin/pages/Assets/AssetsPage.js +14 -303
  90. package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
  91. package/dist/admin/pages/Assets/AssetsPage.mjs +13 -282
  92. package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
  93. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +2 -2
  94. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +181 -65
  95. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  96. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +184 -69
  97. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  98. package/dist/admin/pages/Assets/components/AssetDetails/AssetPreview.mjs +1 -1
  99. package/dist/admin/pages/Assets/components/AssetsGrid.js +142 -31
  100. package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
  101. package/dist/admin/pages/Assets/components/AssetsGrid.mjs +145 -34
  102. package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  103. package/dist/admin/pages/Assets/components/AssetsSearchInput.js +43 -2
  104. package/dist/admin/pages/Assets/components/AssetsSearchInput.js.map +1 -1
  105. package/dist/admin/pages/Assets/components/AssetsSearchInput.mjs +45 -4
  106. package/dist/admin/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
  107. package/dist/admin/pages/Assets/components/AssetsTable.js +58 -34
  108. package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
  109. package/dist/admin/pages/Assets/components/AssetsTable.mjs +60 -36
  110. package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
  111. package/dist/admin/pages/Assets/components/AssetsView.js +145 -0
  112. package/dist/admin/pages/Assets/components/AssetsView.js.map +1 -0
  113. package/dist/admin/pages/Assets/components/AssetsView.mjs +143 -0
  114. package/dist/admin/pages/Assets/components/AssetsView.mjs.map +1 -0
  115. package/dist/admin/pages/Assets/components/BulkActionsBar.mjs +1 -1
  116. package/dist/admin/pages/Assets/components/BusyOverlay.mjs +1 -1
  117. package/dist/admin/pages/Assets/components/Dnd/DragOverlayChip.mjs +1 -1
  118. package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.js +40 -0
  119. package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.js.map +1 -0
  120. package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.mjs +38 -0
  121. package/dist/admin/pages/Assets/components/Dnd/ReorderHandle.mjs.map +1 -0
  122. package/dist/admin/pages/Assets/components/Dnd/assetSortable.js +29 -0
  123. package/dist/admin/pages/Assets/components/Dnd/assetSortable.js.map +1 -0
  124. package/dist/admin/pages/Assets/components/Dnd/assetSortable.mjs +24 -0
  125. package/dist/admin/pages/Assets/components/Dnd/assetSortable.mjs.map +1 -0
  126. package/dist/admin/pages/Assets/components/Dnd/dndIds.js +5 -0
  127. package/dist/admin/pages/Assets/components/Dnd/dndIds.js.map +1 -1
  128. package/dist/admin/pages/Assets/components/Dnd/dndIds.mjs +5 -1
  129. package/dist/admin/pages/Assets/components/Dnd/dndIds.mjs.map +1 -1
  130. package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.js +41 -13
  131. package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.js.map +1 -1
  132. package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.mjs +41 -13
  133. package/dist/admin/pages/Assets/components/Dnd/useAssetDnd.mjs.map +1 -1
  134. package/dist/admin/pages/Assets/components/FilterBadges.mjs +2 -2
  135. package/dist/admin/pages/Assets/components/FilterMenu.mjs +2 -2
  136. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js +274 -55
  137. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  138. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs +277 -59
  139. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  140. package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.js +32 -0
  141. package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.js.map +1 -0
  142. package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.mjs +29 -0
  143. package/dist/admin/pages/Assets/components/FolderTree/collapsedBranch.mjs.map +1 -0
  144. package/dist/admin/pages/Assets/components/ViewToggle.js +126 -0
  145. package/dist/admin/pages/Assets/components/ViewToggle.js.map +1 -0
  146. package/dist/admin/pages/Assets/components/ViewToggle.mjs +104 -0
  147. package/dist/admin/pages/Assets/components/ViewToggle.mjs.map +1 -0
  148. package/dist/admin/pages/Assets/hooks/useAssetSearch.js +2 -2
  149. package/dist/admin/pages/Assets/hooks/useAssetSearch.js.map +1 -1
  150. package/dist/admin/pages/Assets/hooks/useAssetSearch.mjs +2 -2
  151. package/dist/admin/pages/Assets/hooks/useAssetSearch.mjs.map +1 -1
  152. package/dist/admin/pages/Assets/hooks/useAssetSelection.js +19 -1
  153. package/dist/admin/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  154. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs +20 -3
  155. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  156. package/dist/admin/pages/Assets/hooks/useAssetsList.js +87 -0
  157. package/dist/admin/pages/Assets/hooks/useAssetsList.js.map +1 -0
  158. package/dist/admin/pages/Assets/hooks/useAssetsList.mjs +85 -0
  159. package/dist/admin/pages/Assets/hooks/useAssetsList.mjs.map +1 -0
  160. package/dist/admin/pages/Assets/hooks/useBusyAssets.mjs +1 -1
  161. package/dist/admin/pages/Assets/hooks/useFolderNavigation.js +2 -1
  162. package/dist/admin/pages/Assets/hooks/useFolderNavigation.js.map +1 -1
  163. package/dist/admin/pages/Assets/hooks/useFolderNavigation.mjs +3 -2
  164. package/dist/admin/pages/Assets/hooks/useFolderNavigation.mjs.map +1 -1
  165. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.js +2 -6
  166. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.js.map +1 -1
  167. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.mjs +2 -6
  168. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.mjs.map +1 -1
  169. package/dist/admin/pages/Assets/hooks/useListFilters.js +2 -1
  170. package/dist/admin/pages/Assets/hooks/useListFilters.js.map +1 -1
  171. package/dist/admin/pages/Assets/hooks/useListFilters.mjs +3 -2
  172. package/dist/admin/pages/Assets/hooks/useListFilters.mjs.map +1 -1
  173. package/dist/admin/pages/Assets/hooks/useListQueryParams.js +80 -0
  174. package/dist/admin/pages/Assets/hooks/useListQueryParams.js.map +1 -0
  175. package/dist/admin/pages/Assets/hooks/useListQueryParams.mjs +77 -0
  176. package/dist/admin/pages/Assets/hooks/useListQueryParams.mjs.map +1 -0
  177. package/dist/admin/pages/Assets/hooks/useListSettings.js +32 -0
  178. package/dist/admin/pages/Assets/hooks/useListSettings.js.map +1 -0
  179. package/dist/admin/pages/Assets/hooks/useListSettings.mjs +29 -0
  180. package/dist/admin/pages/Assets/hooks/useListSettings.mjs.map +1 -0
  181. package/dist/admin/pages/Assets/hooks/useListSort.js +2 -1
  182. package/dist/admin/pages/Assets/hooks/useListSort.js.map +1 -1
  183. package/dist/admin/pages/Assets/hooks/useListSort.mjs +3 -2
  184. package/dist/admin/pages/Assets/hooks/useListSort.mjs.map +1 -1
  185. package/dist/admin/services/api.js +92 -7
  186. package/dist/admin/services/api.js.map +1 -1
  187. package/dist/admin/services/api.mjs +91 -9
  188. package/dist/admin/services/api.mjs.map +1 -1
  189. package/dist/admin/src/components/AssetPickerDialog/AssetPickerDialog.d.ts +19 -0
  190. package/dist/admin/src/components/AssetPickerDialog/FolderBreadcrumbs.d.ts +10 -0
  191. package/dist/admin/src/components/AssetPickerDialog/MediaLibraryPickerDialog.d.ts +19 -0
  192. package/dist/admin/src/components/AssetPickerDialog/PickerSelectionProvider.d.ts +28 -0
  193. package/dist/admin/src/components/AssetPickerDialog/SortableSelection.d.ts +12 -0
  194. package/dist/admin/src/components/AssetPickerDialog/pickerSelection.d.ts +26 -0
  195. package/dist/admin/src/components/Drawer.d.ts +8 -0
  196. package/dist/admin/src/components/EditorFileDropZone/EditorFileDropZone.d.ts +21 -0
  197. package/dist/admin/src/components/MediaLibraryInput/AddAssetMenu.d.ts +7 -1
  198. package/dist/admin/src/components/MediaLibraryInput/AssetCard.d.ts +25 -0
  199. package/dist/admin/src/components/MediaLibraryInput/AssetCarousel.d.ts +16 -0
  200. package/dist/admin/src/components/MediaLibraryInput/AssetDropZone.d.ts +11 -3
  201. package/dist/admin/src/components/MediaLibraryInput/AssetPreview.d.ts +17 -0
  202. package/dist/admin/src/components/MediaLibraryInput/AssetRow.d.ts +13 -3
  203. package/dist/admin/src/components/MediaLibraryInput/FieldControls.d.ts +19 -0
  204. package/dist/admin/src/components/MediaLibraryInput/MediaLibraryInput.d.ts +3 -1
  205. package/dist/admin/src/components/MediaLibraryInput/UploadProgressBar.d.ts +7 -0
  206. package/dist/admin/src/components/MediaLibraryInput/openAssetDetails.d.ts +10 -0
  207. package/dist/admin/src/components/MediaLibraryInput/useFieldUploads.d.ts +31 -0
  208. package/dist/admin/src/hooks/useMediaLibraryPermissions.d.ts +2 -0
  209. package/dist/admin/src/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +41 -5
  210. package/dist/admin/src/pages/Assets/components/AssetsGrid.d.ts +3 -1
  211. package/dist/admin/src/pages/Assets/components/AssetsSearchInput.d.ts +11 -1
  212. package/dist/admin/src/pages/Assets/components/AssetsView.d.ts +29 -0
  213. package/dist/admin/src/pages/Assets/components/Dnd/ReorderHandle.d.ts +12 -0
  214. package/dist/admin/src/pages/Assets/components/Dnd/assetSortable.d.ts +37 -0
  215. package/dist/admin/src/pages/Assets/components/Dnd/dndIds.d.ts +5 -0
  216. package/dist/admin/src/pages/Assets/components/Dnd/useAssetDnd.d.ts +23 -2
  217. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTree.d.ts +1 -0
  218. package/dist/admin/src/pages/Assets/components/FolderTree/collapsedBranch.d.ts +21 -0
  219. package/dist/admin/src/pages/Assets/components/ViewToggle.d.ts +8 -0
  220. package/dist/admin/src/pages/Assets/hooks/useAssetSelection.d.ts +26 -0
  221. package/dist/admin/src/pages/Assets/hooks/useAssetsList.d.ts +30 -0
  222. package/dist/admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.d.ts +2 -6
  223. package/dist/admin/src/pages/Assets/hooks/useListQueryParams.d.ts +27 -0
  224. package/dist/admin/src/pages/Assets/hooks/useListSettings.d.ts +29 -0
  225. package/dist/admin/src/services/api.d.ts +24 -1
  226. package/dist/admin/src/store/uploadProgress.d.ts +14 -1
  227. package/dist/admin/src/utils/findFolderPath.d.ts +6 -0
  228. package/dist/admin/src/utils/isAllowedAssetType.d.ts +14 -0
  229. package/dist/admin/store/uploadProgress.js +30 -3
  230. package/dist/admin/store/uploadProgress.js.map +1 -1
  231. package/dist/admin/store/uploadProgress.mjs +29 -4
  232. package/dist/admin/store/uploadProgress.mjs.map +1 -1
  233. package/dist/admin/translations/en.json.js +24 -0
  234. package/dist/admin/translations/en.json.js.map +1 -1
  235. package/dist/admin/translations/en.json.mjs +24 -0
  236. package/dist/admin/translations/en.json.mjs.map +1 -1
  237. package/dist/admin/utils/findFolderPath.js +26 -0
  238. package/dist/admin/utils/findFolderPath.js.map +1 -0
  239. package/dist/admin/utils/findFolderPath.mjs +24 -0
  240. package/dist/admin/utils/findFolderPath.mjs.map +1 -0
  241. package/dist/admin/utils/isAllowedAssetType.js +33 -0
  242. package/dist/admin/utils/isAllowedAssetType.js.map +1 -0
  243. package/dist/admin/utils/isAllowedAssetType.mjs +31 -0
  244. package/dist/admin/utils/isAllowedAssetType.mjs.map +1 -0
  245. package/dist/server/audit-logs.js +264 -0
  246. package/dist/server/audit-logs.js.map +1 -0
  247. package/dist/server/audit-logs.mjs +255 -0
  248. package/dist/server/audit-logs.mjs.map +1 -0
  249. package/dist/server/bootstrap.js +4 -0
  250. package/dist/server/bootstrap.js.map +1 -1
  251. package/dist/server/bootstrap.mjs +4 -0
  252. package/dist/server/bootstrap.mjs.map +1 -1
  253. package/dist/server/controllers/admin-folder-file.js +23 -1
  254. package/dist/server/controllers/admin-folder-file.js.map +1 -1
  255. package/dist/server/controllers/admin-folder-file.mjs +23 -1
  256. package/dist/server/controllers/admin-folder-file.mjs.map +1 -1
  257. package/dist/server/controllers/admin-settings.js +5 -1
  258. package/dist/server/controllers/admin-settings.js.map +1 -1
  259. package/dist/server/controllers/admin-settings.mjs +5 -1
  260. package/dist/server/controllers/admin-settings.mjs.map +1 -1
  261. package/dist/server/services/folder.js +48 -1
  262. package/dist/server/services/folder.js.map +1 -1
  263. package/dist/server/services/folder.mjs +48 -1
  264. package/dist/server/services/folder.mjs.map +1 -1
  265. package/dist/server/services/image-manipulation.js +14 -7
  266. package/dist/server/services/image-manipulation.js.map +1 -1
  267. package/dist/server/services/image-manipulation.mjs +14 -7
  268. package/dist/server/services/image-manipulation.mjs.map +1 -1
  269. package/dist/server/services/upload.js +100 -16
  270. package/dist/server/services/upload.js.map +1 -1
  271. package/dist/server/services/upload.mjs +102 -18
  272. package/dist/server/services/upload.mjs.map +1 -1
  273. package/dist/server/src/audit-logs.d.ts +142 -0
  274. package/dist/server/src/audit-logs.d.ts.map +1 -0
  275. package/dist/server/src/bootstrap.d.ts.map +1 -1
  276. package/dist/server/src/controllers/admin-folder-file.d.ts.map +1 -1
  277. package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
  278. package/dist/server/src/index.d.ts +4 -4
  279. package/dist/server/src/index.d.ts.map +1 -1
  280. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
  281. package/dist/server/src/services/extensions/utils.d.ts +11 -11
  282. package/dist/server/src/services/folder.d.ts.map +1 -1
  283. package/dist/server/src/services/image-manipulation.d.ts +4 -4
  284. package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
  285. package/dist/server/src/services/index.d.ts +4 -4
  286. package/dist/server/src/services/index.d.ts.map +1 -1
  287. package/dist/server/src/services/upload.d.ts.map +1 -1
  288. package/dist/server/src/types.d.ts +63 -12
  289. package/dist/server/src/types.d.ts.map +1 -1
  290. package/package.json +11 -16
  291. package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.js +0 -45
  292. package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.js.map +0 -1
  293. package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.mjs +0 -43
  294. package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.mjs.map +0 -1
  295. package/dist/admin/src/components/MediaLibraryInput/NoLibraryAccessDialog.d.ts +0 -10
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var strapiAdmin = require('@strapi/admin/strapi-admin');
4
+ var useListQueryParams = require('./useListQueryParams.js');
4
5
 
5
6
  /**
6
7
  * Filter state for the assets list, backed by a single `?filters=` query param
@@ -130,7 +131,7 @@ const serializeBadge = (filter)=>{
130
131
  };
131
132
  const serializeFilters = (filters)=>filters.map(serializeBadge).join(';');
132
133
  const useListFilters = ()=>{
133
- const [{ query }, setQuery] = strapiAdmin.useQueryParams();
134
+ const [{ query }, setQuery] = useListQueryParams.useListQueryParams();
134
135
  const filters = parseFiltersParam(query?.filters);
135
136
  // `replace: true` on every write: filters are edited in rapid micro-steps
136
137
  // (each checkbox of the keep-open Type submenu, each badge segment edit), so
@@ -1 +1 @@
1
- {"version":3,"file":"useListFilters.js","sources":["../../../../../admin/src/pages/Assets/hooks/useListFilters.ts"],"sourcesContent":["import { useQueryParams, withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\n/**\n * Filter state for the assets list, backed by a single `?filters=` query param\n * so the applied filters are shareable and survive Back/refresh.\n *\n * Serialized grammar — badges separated by `;`, one badge is\n * `<field>:<condition>:<value>`:\n *\n * - `type:is:picture,audio` / `type:not:folder`\n * - `created:within:1week` / `updated:notwithin:3months` / `created:exact:1day`\n * - `created:rangeis:2024-01-01..2024-04-07` / `created:rangenot:...`\n *\n * Relative presets stay relative in the URL on purpose: the badge label\n * (\"1 week ago\") remains truthful forever and a shared link means \"within the\n * last week from whenever it is opened\". Resolution to absolute timestamps\n * happens at query-build time (see utils/buildAssetFilters.ts).\n *\n * Several badges for the same field are allowed, even contradictory ones —\n * everything is combined with AND; contradictions simply produce the filtered\n * empty state.\n */\n\nexport const TYPE_VALUES = ['folder', 'picture', 'audio', 'video', 'document'] as const;\nexport type TypeValue = (typeof TYPE_VALUES)[number];\n\nexport const DATE_PRESETS = [\n '1day',\n '3days',\n '1week',\n '1month',\n '3months',\n '6months',\n '1year',\n] as const;\nexport type DatePreset = (typeof DATE_PRESETS)[number];\n\nexport type TypeCondition = 'is' | 'isNot';\nexport type PresetCondition = 'isExactly' | 'withinLast' | 'notWithinLast';\nexport type RangeCondition = 'is' | 'isNot';\n\nexport type DateField = 'createdAt' | 'updatedAt';\n\nexport interface TypeFilter {\n kind: 'type';\n condition: TypeCondition;\n values: TypeValue[];\n}\n\nexport interface DatePresetFilter {\n kind: 'date';\n field: DateField;\n mode: 'preset';\n condition: PresetCondition;\n preset: DatePreset;\n}\n\nexport interface DateRangeFilter {\n kind: 'date';\n field: DateField;\n mode: 'range';\n condition: RangeCondition;\n /** Calendar dates, `YYYY-MM-DD`, inclusive on both ends. */\n from: string;\n to: string;\n}\n\nexport type DateFilter = DatePresetFilter | DateRangeFilter;\nexport type ListFilter = TypeFilter | DateFilter;\n\nconst FIELD_TOKENS: Record<string, DateField> = {\n created: 'createdAt',\n updated: 'updatedAt',\n};\nconst FIELD_TOKEN_BY_FIELD: Record<DateField, string> = {\n createdAt: 'created',\n updatedAt: 'updated',\n};\n\nconst PRESET_CONDITION_TOKENS: Record<string, PresetCondition> = {\n exact: 'isExactly',\n within: 'withinLast',\n notwithin: 'notWithinLast',\n};\nconst PRESET_TOKEN_BY_CONDITION: Record<PresetCondition, string> = {\n isExactly: 'exact',\n withinLast: 'within',\n notWithinLast: 'notwithin',\n};\n\nconst RANGE_CONDITION_TOKENS: Record<string, RangeCondition> = {\n rangeis: 'is',\n rangenot: 'isNot',\n};\nconst RANGE_TOKEN_BY_CONDITION: Record<RangeCondition, string> = {\n is: 'rangeis',\n isNot: 'rangenot',\n};\n\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isTypeValue = (value: string): value is TypeValue =>\n (TYPE_VALUES as readonly string[]).includes(value);\n\nconst isDatePreset = (value: string): value is DatePreset =>\n (DATE_PRESETS as readonly string[]).includes(value);\n\nconst parseBadge = (raw: string): ListFilter | null => {\n const [field, condition, value] = raw.split(':');\n\n if (!field || !condition || !value) {\n return null;\n }\n\n if (field === 'type') {\n if (condition !== 'is' && condition !== 'not') {\n return null;\n }\n const values = value.split(',').filter(isTypeValue);\n\n return values.length > 0\n ? { kind: 'type', condition: condition === 'is' ? 'is' : 'isNot', values }\n : null;\n }\n\n const dateField = FIELD_TOKENS[field];\n if (!dateField) {\n return null;\n }\n\n if (condition in PRESET_CONDITION_TOKENS) {\n return isDatePreset(value)\n ? {\n kind: 'date',\n field: dateField,\n mode: 'preset',\n condition: PRESET_CONDITION_TOKENS[condition],\n preset: value,\n }\n : null;\n }\n\n if (condition in RANGE_CONDITION_TOKENS) {\n const [from, to] = value.split('..');\n\n return DATE_RE.test(from ?? '') && DATE_RE.test(to ?? '')\n ? {\n kind: 'date',\n field: dateField,\n mode: 'range',\n condition: RANGE_CONDITION_TOKENS[condition],\n from,\n to,\n }\n : null;\n }\n\n return null;\n};\n\n/**\n * `unknown` on purpose: the query string is user-editable, and qs parses\n * shapes like `?filters[]=a&filters[]=b` into arrays — the guard is what\n * makes the caller's `?filters=` type an assertion rather than a crash.\n */\nexport const parseFiltersParam = (raw: unknown): ListFilter[] => {\n if (typeof raw !== 'string' || raw === '') {\n return [];\n }\n\n return raw\n .split(';')\n .map(parseBadge)\n .filter((filter): filter is ListFilter => filter !== null);\n};\n\nconst serializeBadge = (filter: ListFilter): string => {\n if (filter.kind === 'type') {\n return `type:${filter.condition === 'is' ? 'is' : 'not'}:${filter.values.join(',')}`;\n }\n\n const field = FIELD_TOKEN_BY_FIELD[filter.field];\n\n if (filter.mode === 'preset') {\n return `${field}:${PRESET_TOKEN_BY_CONDITION[filter.condition]}:${filter.preset}`;\n }\n\n return `${field}:${RANGE_TOKEN_BY_CONDITION[filter.condition]}:${filter.from}..${filter.to}`;\n};\n\nexport const serializeFilters = (filters: ListFilter[]): string =>\n filters.map(serializeBadge).join(';');\n\nexport interface ListFilters {\n filters: ListFilter[];\n /** Serialized form — stable fingerprint for list-identity (selection reset). */\n serialized: string;\n addFilter: (filter: ListFilter) => void;\n /** Replaces the badge at `index` (condition or value edited in place). */\n updateFilter: (index: number, filter: ListFilter) => void;\n removeFilter: (index: number) => void;\n clearFilters: () => void;\n}\n\nexport const useListFilters = (): ListFilters => {\n const [{ query }, setQuery] = useQueryParams<{ filters?: string; _q?: string }>();\n\n const filters = parseFiltersParam(query?.filters);\n\n // `replace: true` on every write: filters are edited in rapid micro-steps\n // (each checkbox of the keep-open Type submenu, each badge segment edit), so\n // pushing would turn one logical change into a stack of Back entries. The\n // URL stays shareable and refresh-safe either way.\n const writeFilters = (next: ListFilter[]) => {\n if (next.length === 0) {\n setQuery(withEncodedUserParams(query, { filters: undefined }), 'push', true);\n } else {\n setQuery(withEncodedUserParams(query, { filters: serializeFilters(next) }), 'push', true);\n }\n };\n\n return {\n filters,\n serialized: serializeFilters(filters),\n addFilter: (filter) => writeFilters([...filters, filter]),\n updateFilter: (index, filter) =>\n writeFilters(filters.map((f, i) => (i === index ? filter : f))),\n removeFilter: (index) => writeFilters(filters.filter((_, i) => i !== index)),\n clearFilters: () => writeFilters([]),\n };\n};\n"],"names":["TYPE_VALUES","DATE_PRESETS","FIELD_TOKENS","created","updated","FIELD_TOKEN_BY_FIELD","createdAt","updatedAt","PRESET_CONDITION_TOKENS","exact","within","notwithin","PRESET_TOKEN_BY_CONDITION","isExactly","withinLast","notWithinLast","RANGE_CONDITION_TOKENS","rangeis","rangenot","RANGE_TOKEN_BY_CONDITION","is","isNot","DATE_RE","isTypeValue","value","includes","isDatePreset","parseBadge","raw","field","condition","split","values","filter","length","kind","dateField","mode","preset","from","to","test","parseFiltersParam","map","serializeBadge","join","serializeFilters","filters","useListFilters","query","setQuery","useQueryParams","writeFilters","next","withEncodedUserParams","undefined","serialized","addFilter","updateFilter","index","f","i","removeFilter","_","clearFilters"],"mappings":"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"}
1
+ {"version":3,"file":"useListFilters.js","sources":["../../../../../admin/src/pages/Assets/hooks/useListFilters.ts"],"sourcesContent":["import { withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\nimport { useListQueryParams } from './useListQueryParams';\n\n/**\n * Filter state for the assets list, backed by a single `?filters=` query param\n * so the applied filters are shareable and survive Back/refresh.\n *\n * Serialized grammar — badges separated by `;`, one badge is\n * `<field>:<condition>:<value>`:\n *\n * - `type:is:picture,audio` / `type:not:folder`\n * - `created:within:1week` / `updated:notwithin:3months` / `created:exact:1day`\n * - `created:rangeis:2024-01-01..2024-04-07` / `created:rangenot:...`\n *\n * Relative presets stay relative in the URL on purpose: the badge label\n * (\"1 week ago\") remains truthful forever and a shared link means \"within the\n * last week from whenever it is opened\". Resolution to absolute timestamps\n * happens at query-build time (see utils/buildAssetFilters.ts).\n *\n * Several badges for the same field are allowed, even contradictory ones —\n * everything is combined with AND; contradictions simply produce the filtered\n * empty state.\n */\n\nexport const TYPE_VALUES = ['folder', 'picture', 'audio', 'video', 'document'] as const;\nexport type TypeValue = (typeof TYPE_VALUES)[number];\n\nexport const DATE_PRESETS = [\n '1day',\n '3days',\n '1week',\n '1month',\n '3months',\n '6months',\n '1year',\n] as const;\nexport type DatePreset = (typeof DATE_PRESETS)[number];\n\nexport type TypeCondition = 'is' | 'isNot';\nexport type PresetCondition = 'isExactly' | 'withinLast' | 'notWithinLast';\nexport type RangeCondition = 'is' | 'isNot';\n\nexport type DateField = 'createdAt' | 'updatedAt';\n\nexport interface TypeFilter {\n kind: 'type';\n condition: TypeCondition;\n values: TypeValue[];\n}\n\nexport interface DatePresetFilter {\n kind: 'date';\n field: DateField;\n mode: 'preset';\n condition: PresetCondition;\n preset: DatePreset;\n}\n\nexport interface DateRangeFilter {\n kind: 'date';\n field: DateField;\n mode: 'range';\n condition: RangeCondition;\n /** Calendar dates, `YYYY-MM-DD`, inclusive on both ends. */\n from: string;\n to: string;\n}\n\nexport type DateFilter = DatePresetFilter | DateRangeFilter;\nexport type ListFilter = TypeFilter | DateFilter;\n\nconst FIELD_TOKENS: Record<string, DateField> = {\n created: 'createdAt',\n updated: 'updatedAt',\n};\nconst FIELD_TOKEN_BY_FIELD: Record<DateField, string> = {\n createdAt: 'created',\n updatedAt: 'updated',\n};\n\nconst PRESET_CONDITION_TOKENS: Record<string, PresetCondition> = {\n exact: 'isExactly',\n within: 'withinLast',\n notwithin: 'notWithinLast',\n};\nconst PRESET_TOKEN_BY_CONDITION: Record<PresetCondition, string> = {\n isExactly: 'exact',\n withinLast: 'within',\n notWithinLast: 'notwithin',\n};\n\nconst RANGE_CONDITION_TOKENS: Record<string, RangeCondition> = {\n rangeis: 'is',\n rangenot: 'isNot',\n};\nconst RANGE_TOKEN_BY_CONDITION: Record<RangeCondition, string> = {\n is: 'rangeis',\n isNot: 'rangenot',\n};\n\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isTypeValue = (value: string): value is TypeValue =>\n (TYPE_VALUES as readonly string[]).includes(value);\n\nconst isDatePreset = (value: string): value is DatePreset =>\n (DATE_PRESETS as readonly string[]).includes(value);\n\nconst parseBadge = (raw: string): ListFilter | null => {\n const [field, condition, value] = raw.split(':');\n\n if (!field || !condition || !value) {\n return null;\n }\n\n if (field === 'type') {\n if (condition !== 'is' && condition !== 'not') {\n return null;\n }\n const values = value.split(',').filter(isTypeValue);\n\n return values.length > 0\n ? { kind: 'type', condition: condition === 'is' ? 'is' : 'isNot', values }\n : null;\n }\n\n const dateField = FIELD_TOKENS[field];\n if (!dateField) {\n return null;\n }\n\n if (condition in PRESET_CONDITION_TOKENS) {\n return isDatePreset(value)\n ? {\n kind: 'date',\n field: dateField,\n mode: 'preset',\n condition: PRESET_CONDITION_TOKENS[condition],\n preset: value,\n }\n : null;\n }\n\n if (condition in RANGE_CONDITION_TOKENS) {\n const [from, to] = value.split('..');\n\n return DATE_RE.test(from ?? '') && DATE_RE.test(to ?? '')\n ? {\n kind: 'date',\n field: dateField,\n mode: 'range',\n condition: RANGE_CONDITION_TOKENS[condition],\n from,\n to,\n }\n : null;\n }\n\n return null;\n};\n\n/**\n * `unknown` on purpose: the query string is user-editable, and qs parses\n * shapes like `?filters[]=a&filters[]=b` into arrays — the guard is what\n * makes the caller's `?filters=` type an assertion rather than a crash.\n */\nexport const parseFiltersParam = (raw: unknown): ListFilter[] => {\n if (typeof raw !== 'string' || raw === '') {\n return [];\n }\n\n return raw\n .split(';')\n .map(parseBadge)\n .filter((filter): filter is ListFilter => filter !== null);\n};\n\nconst serializeBadge = (filter: ListFilter): string => {\n if (filter.kind === 'type') {\n return `type:${filter.condition === 'is' ? 'is' : 'not'}:${filter.values.join(',')}`;\n }\n\n const field = FIELD_TOKEN_BY_FIELD[filter.field];\n\n if (filter.mode === 'preset') {\n return `${field}:${PRESET_TOKEN_BY_CONDITION[filter.condition]}:${filter.preset}`;\n }\n\n return `${field}:${RANGE_TOKEN_BY_CONDITION[filter.condition]}:${filter.from}..${filter.to}`;\n};\n\nexport const serializeFilters = (filters: ListFilter[]): string =>\n filters.map(serializeBadge).join(';');\n\nexport interface ListFilters {\n filters: ListFilter[];\n /** Serialized form — stable fingerprint for list-identity (selection reset). */\n serialized: string;\n addFilter: (filter: ListFilter) => void;\n /** Replaces the badge at `index` (condition or value edited in place). */\n updateFilter: (index: number, filter: ListFilter) => void;\n removeFilter: (index: number) => void;\n clearFilters: () => void;\n}\n\nexport const useListFilters = (): ListFilters => {\n const [{ query }, setQuery] = useListQueryParams<{ filters?: string; _q?: string }>();\n\n const filters = parseFiltersParam(query?.filters);\n\n // `replace: true` on every write: filters are edited in rapid micro-steps\n // (each checkbox of the keep-open Type submenu, each badge segment edit), so\n // pushing would turn one logical change into a stack of Back entries. The\n // URL stays shareable and refresh-safe either way.\n const writeFilters = (next: ListFilter[]) => {\n if (next.length === 0) {\n setQuery(withEncodedUserParams(query, { filters: undefined }), 'push', true);\n } else {\n setQuery(withEncodedUserParams(query, { filters: serializeFilters(next) }), 'push', true);\n }\n };\n\n return {\n filters,\n serialized: serializeFilters(filters),\n addFilter: (filter) => writeFilters([...filters, filter]),\n updateFilter: (index, filter) =>\n writeFilters(filters.map((f, i) => (i === index ? filter : f))),\n removeFilter: (index) => writeFilters(filters.filter((_, i) => i !== index)),\n clearFilters: () => writeFilters([]),\n };\n};\n"],"names":["TYPE_VALUES","DATE_PRESETS","FIELD_TOKENS","created","updated","FIELD_TOKEN_BY_FIELD","createdAt","updatedAt","PRESET_CONDITION_TOKENS","exact","within","notwithin","PRESET_TOKEN_BY_CONDITION","isExactly","withinLast","notWithinLast","RANGE_CONDITION_TOKENS","rangeis","rangenot","RANGE_TOKEN_BY_CONDITION","is","isNot","DATE_RE","isTypeValue","value","includes","isDatePreset","parseBadge","raw","field","condition","split","values","filter","length","kind","dateField","mode","preset","from","to","test","parseFiltersParam","map","serializeBadge","join","serializeFilters","filters","useListFilters","query","setQuery","useListQueryParams","writeFilters","next","withEncodedUserParams","undefined","serialized","addFilter","updateFilter","index","f","i","removeFilter","_","clearFilters"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { useQueryParams, withEncodedUserParams } from '@strapi/admin/strapi-admin';
1
+ import { withEncodedUserParams } from '@strapi/admin/strapi-admin';
2
+ import { useListQueryParams } from './useListQueryParams.mjs';
2
3
 
3
4
  /**
4
5
  * Filter state for the assets list, backed by a single `?filters=` query param
@@ -128,7 +129,7 @@ const serializeBadge = (filter)=>{
128
129
  };
129
130
  const serializeFilters = (filters)=>filters.map(serializeBadge).join(';');
130
131
  const useListFilters = ()=>{
131
- const [{ query }, setQuery] = useQueryParams();
132
+ const [{ query }, setQuery] = useListQueryParams();
132
133
  const filters = parseFiltersParam(query?.filters);
133
134
  // `replace: true` on every write: filters are edited in rapid micro-steps
134
135
  // (each checkbox of the keep-open Type submenu, each badge segment edit), so
@@ -1 +1 @@
1
- {"version":3,"file":"useListFilters.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useListFilters.ts"],"sourcesContent":["import { useQueryParams, withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\n/**\n * Filter state for the assets list, backed by a single `?filters=` query param\n * so the applied filters are shareable and survive Back/refresh.\n *\n * Serialized grammar — badges separated by `;`, one badge is\n * `<field>:<condition>:<value>`:\n *\n * - `type:is:picture,audio` / `type:not:folder`\n * - `created:within:1week` / `updated:notwithin:3months` / `created:exact:1day`\n * - `created:rangeis:2024-01-01..2024-04-07` / `created:rangenot:...`\n *\n * Relative presets stay relative in the URL on purpose: the badge label\n * (\"1 week ago\") remains truthful forever and a shared link means \"within the\n * last week from whenever it is opened\". Resolution to absolute timestamps\n * happens at query-build time (see utils/buildAssetFilters.ts).\n *\n * Several badges for the same field are allowed, even contradictory ones —\n * everything is combined with AND; contradictions simply produce the filtered\n * empty state.\n */\n\nexport const TYPE_VALUES = ['folder', 'picture', 'audio', 'video', 'document'] as const;\nexport type TypeValue = (typeof TYPE_VALUES)[number];\n\nexport const DATE_PRESETS = [\n '1day',\n '3days',\n '1week',\n '1month',\n '3months',\n '6months',\n '1year',\n] as const;\nexport type DatePreset = (typeof DATE_PRESETS)[number];\n\nexport type TypeCondition = 'is' | 'isNot';\nexport type PresetCondition = 'isExactly' | 'withinLast' | 'notWithinLast';\nexport type RangeCondition = 'is' | 'isNot';\n\nexport type DateField = 'createdAt' | 'updatedAt';\n\nexport interface TypeFilter {\n kind: 'type';\n condition: TypeCondition;\n values: TypeValue[];\n}\n\nexport interface DatePresetFilter {\n kind: 'date';\n field: DateField;\n mode: 'preset';\n condition: PresetCondition;\n preset: DatePreset;\n}\n\nexport interface DateRangeFilter {\n kind: 'date';\n field: DateField;\n mode: 'range';\n condition: RangeCondition;\n /** Calendar dates, `YYYY-MM-DD`, inclusive on both ends. */\n from: string;\n to: string;\n}\n\nexport type DateFilter = DatePresetFilter | DateRangeFilter;\nexport type ListFilter = TypeFilter | DateFilter;\n\nconst FIELD_TOKENS: Record<string, DateField> = {\n created: 'createdAt',\n updated: 'updatedAt',\n};\nconst FIELD_TOKEN_BY_FIELD: Record<DateField, string> = {\n createdAt: 'created',\n updatedAt: 'updated',\n};\n\nconst PRESET_CONDITION_TOKENS: Record<string, PresetCondition> = {\n exact: 'isExactly',\n within: 'withinLast',\n notwithin: 'notWithinLast',\n};\nconst PRESET_TOKEN_BY_CONDITION: Record<PresetCondition, string> = {\n isExactly: 'exact',\n withinLast: 'within',\n notWithinLast: 'notwithin',\n};\n\nconst RANGE_CONDITION_TOKENS: Record<string, RangeCondition> = {\n rangeis: 'is',\n rangenot: 'isNot',\n};\nconst RANGE_TOKEN_BY_CONDITION: Record<RangeCondition, string> = {\n is: 'rangeis',\n isNot: 'rangenot',\n};\n\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isTypeValue = (value: string): value is TypeValue =>\n (TYPE_VALUES as readonly string[]).includes(value);\n\nconst isDatePreset = (value: string): value is DatePreset =>\n (DATE_PRESETS as readonly string[]).includes(value);\n\nconst parseBadge = (raw: string): ListFilter | null => {\n const [field, condition, value] = raw.split(':');\n\n if (!field || !condition || !value) {\n return null;\n }\n\n if (field === 'type') {\n if (condition !== 'is' && condition !== 'not') {\n return null;\n }\n const values = value.split(',').filter(isTypeValue);\n\n return values.length > 0\n ? { kind: 'type', condition: condition === 'is' ? 'is' : 'isNot', values }\n : null;\n }\n\n const dateField = FIELD_TOKENS[field];\n if (!dateField) {\n return null;\n }\n\n if (condition in PRESET_CONDITION_TOKENS) {\n return isDatePreset(value)\n ? {\n kind: 'date',\n field: dateField,\n mode: 'preset',\n condition: PRESET_CONDITION_TOKENS[condition],\n preset: value,\n }\n : null;\n }\n\n if (condition in RANGE_CONDITION_TOKENS) {\n const [from, to] = value.split('..');\n\n return DATE_RE.test(from ?? '') && DATE_RE.test(to ?? '')\n ? {\n kind: 'date',\n field: dateField,\n mode: 'range',\n condition: RANGE_CONDITION_TOKENS[condition],\n from,\n to,\n }\n : null;\n }\n\n return null;\n};\n\n/**\n * `unknown` on purpose: the query string is user-editable, and qs parses\n * shapes like `?filters[]=a&filters[]=b` into arrays — the guard is what\n * makes the caller's `?filters=` type an assertion rather than a crash.\n */\nexport const parseFiltersParam = (raw: unknown): ListFilter[] => {\n if (typeof raw !== 'string' || raw === '') {\n return [];\n }\n\n return raw\n .split(';')\n .map(parseBadge)\n .filter((filter): filter is ListFilter => filter !== null);\n};\n\nconst serializeBadge = (filter: ListFilter): string => {\n if (filter.kind === 'type') {\n return `type:${filter.condition === 'is' ? 'is' : 'not'}:${filter.values.join(',')}`;\n }\n\n const field = FIELD_TOKEN_BY_FIELD[filter.field];\n\n if (filter.mode === 'preset') {\n return `${field}:${PRESET_TOKEN_BY_CONDITION[filter.condition]}:${filter.preset}`;\n }\n\n return `${field}:${RANGE_TOKEN_BY_CONDITION[filter.condition]}:${filter.from}..${filter.to}`;\n};\n\nexport const serializeFilters = (filters: ListFilter[]): string =>\n filters.map(serializeBadge).join(';');\n\nexport interface ListFilters {\n filters: ListFilter[];\n /** Serialized form — stable fingerprint for list-identity (selection reset). */\n serialized: string;\n addFilter: (filter: ListFilter) => void;\n /** Replaces the badge at `index` (condition or value edited in place). */\n updateFilter: (index: number, filter: ListFilter) => void;\n removeFilter: (index: number) => void;\n clearFilters: () => void;\n}\n\nexport const useListFilters = (): ListFilters => {\n const [{ query }, setQuery] = useQueryParams<{ filters?: string; _q?: string }>();\n\n const filters = parseFiltersParam(query?.filters);\n\n // `replace: true` on every write: filters are edited in rapid micro-steps\n // (each checkbox of the keep-open Type submenu, each badge segment edit), so\n // pushing would turn one logical change into a stack of Back entries. The\n // URL stays shareable and refresh-safe either way.\n const writeFilters = (next: ListFilter[]) => {\n if (next.length === 0) {\n setQuery(withEncodedUserParams(query, { filters: undefined }), 'push', true);\n } else {\n setQuery(withEncodedUserParams(query, { filters: serializeFilters(next) }), 'push', true);\n }\n };\n\n return {\n filters,\n serialized: serializeFilters(filters),\n addFilter: (filter) => writeFilters([...filters, filter]),\n updateFilter: (index, filter) =>\n writeFilters(filters.map((f, i) => (i === index ? filter : f))),\n removeFilter: (index) => writeFilters(filters.filter((_, i) => i !== index)),\n clearFilters: () => writeFilters([]),\n };\n};\n"],"names":["TYPE_VALUES","DATE_PRESETS","FIELD_TOKENS","created","updated","FIELD_TOKEN_BY_FIELD","createdAt","updatedAt","PRESET_CONDITION_TOKENS","exact","within","notwithin","PRESET_TOKEN_BY_CONDITION","isExactly","withinLast","notWithinLast","RANGE_CONDITION_TOKENS","rangeis","rangenot","RANGE_TOKEN_BY_CONDITION","is","isNot","DATE_RE","isTypeValue","value","includes","isDatePreset","parseBadge","raw","field","condition","split","values","filter","length","kind","dateField","mode","preset","from","to","test","parseFiltersParam","map","serializeBadge","join","serializeFilters","filters","useListFilters","query","setQuery","useQueryParams","writeFilters","next","withEncodedUserParams","undefined","serialized","addFilter","updateFilter","index","f","i","removeFilter","_","clearFilters"],"mappings":"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"}
1
+ {"version":3,"file":"useListFilters.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useListFilters.ts"],"sourcesContent":["import { withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\nimport { useListQueryParams } from './useListQueryParams';\n\n/**\n * Filter state for the assets list, backed by a single `?filters=` query param\n * so the applied filters are shareable and survive Back/refresh.\n *\n * Serialized grammar — badges separated by `;`, one badge is\n * `<field>:<condition>:<value>`:\n *\n * - `type:is:picture,audio` / `type:not:folder`\n * - `created:within:1week` / `updated:notwithin:3months` / `created:exact:1day`\n * - `created:rangeis:2024-01-01..2024-04-07` / `created:rangenot:...`\n *\n * Relative presets stay relative in the URL on purpose: the badge label\n * (\"1 week ago\") remains truthful forever and a shared link means \"within the\n * last week from whenever it is opened\". Resolution to absolute timestamps\n * happens at query-build time (see utils/buildAssetFilters.ts).\n *\n * Several badges for the same field are allowed, even contradictory ones —\n * everything is combined with AND; contradictions simply produce the filtered\n * empty state.\n */\n\nexport const TYPE_VALUES = ['folder', 'picture', 'audio', 'video', 'document'] as const;\nexport type TypeValue = (typeof TYPE_VALUES)[number];\n\nexport const DATE_PRESETS = [\n '1day',\n '3days',\n '1week',\n '1month',\n '3months',\n '6months',\n '1year',\n] as const;\nexport type DatePreset = (typeof DATE_PRESETS)[number];\n\nexport type TypeCondition = 'is' | 'isNot';\nexport type PresetCondition = 'isExactly' | 'withinLast' | 'notWithinLast';\nexport type RangeCondition = 'is' | 'isNot';\n\nexport type DateField = 'createdAt' | 'updatedAt';\n\nexport interface TypeFilter {\n kind: 'type';\n condition: TypeCondition;\n values: TypeValue[];\n}\n\nexport interface DatePresetFilter {\n kind: 'date';\n field: DateField;\n mode: 'preset';\n condition: PresetCondition;\n preset: DatePreset;\n}\n\nexport interface DateRangeFilter {\n kind: 'date';\n field: DateField;\n mode: 'range';\n condition: RangeCondition;\n /** Calendar dates, `YYYY-MM-DD`, inclusive on both ends. */\n from: string;\n to: string;\n}\n\nexport type DateFilter = DatePresetFilter | DateRangeFilter;\nexport type ListFilter = TypeFilter | DateFilter;\n\nconst FIELD_TOKENS: Record<string, DateField> = {\n created: 'createdAt',\n updated: 'updatedAt',\n};\nconst FIELD_TOKEN_BY_FIELD: Record<DateField, string> = {\n createdAt: 'created',\n updatedAt: 'updated',\n};\n\nconst PRESET_CONDITION_TOKENS: Record<string, PresetCondition> = {\n exact: 'isExactly',\n within: 'withinLast',\n notwithin: 'notWithinLast',\n};\nconst PRESET_TOKEN_BY_CONDITION: Record<PresetCondition, string> = {\n isExactly: 'exact',\n withinLast: 'within',\n notWithinLast: 'notwithin',\n};\n\nconst RANGE_CONDITION_TOKENS: Record<string, RangeCondition> = {\n rangeis: 'is',\n rangenot: 'isNot',\n};\nconst RANGE_TOKEN_BY_CONDITION: Record<RangeCondition, string> = {\n is: 'rangeis',\n isNot: 'rangenot',\n};\n\nconst DATE_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isTypeValue = (value: string): value is TypeValue =>\n (TYPE_VALUES as readonly string[]).includes(value);\n\nconst isDatePreset = (value: string): value is DatePreset =>\n (DATE_PRESETS as readonly string[]).includes(value);\n\nconst parseBadge = (raw: string): ListFilter | null => {\n const [field, condition, value] = raw.split(':');\n\n if (!field || !condition || !value) {\n return null;\n }\n\n if (field === 'type') {\n if (condition !== 'is' && condition !== 'not') {\n return null;\n }\n const values = value.split(',').filter(isTypeValue);\n\n return values.length > 0\n ? { kind: 'type', condition: condition === 'is' ? 'is' : 'isNot', values }\n : null;\n }\n\n const dateField = FIELD_TOKENS[field];\n if (!dateField) {\n return null;\n }\n\n if (condition in PRESET_CONDITION_TOKENS) {\n return isDatePreset(value)\n ? {\n kind: 'date',\n field: dateField,\n mode: 'preset',\n condition: PRESET_CONDITION_TOKENS[condition],\n preset: value,\n }\n : null;\n }\n\n if (condition in RANGE_CONDITION_TOKENS) {\n const [from, to] = value.split('..');\n\n return DATE_RE.test(from ?? '') && DATE_RE.test(to ?? '')\n ? {\n kind: 'date',\n field: dateField,\n mode: 'range',\n condition: RANGE_CONDITION_TOKENS[condition],\n from,\n to,\n }\n : null;\n }\n\n return null;\n};\n\n/**\n * `unknown` on purpose: the query string is user-editable, and qs parses\n * shapes like `?filters[]=a&filters[]=b` into arrays — the guard is what\n * makes the caller's `?filters=` type an assertion rather than a crash.\n */\nexport const parseFiltersParam = (raw: unknown): ListFilter[] => {\n if (typeof raw !== 'string' || raw === '') {\n return [];\n }\n\n return raw\n .split(';')\n .map(parseBadge)\n .filter((filter): filter is ListFilter => filter !== null);\n};\n\nconst serializeBadge = (filter: ListFilter): string => {\n if (filter.kind === 'type') {\n return `type:${filter.condition === 'is' ? 'is' : 'not'}:${filter.values.join(',')}`;\n }\n\n const field = FIELD_TOKEN_BY_FIELD[filter.field];\n\n if (filter.mode === 'preset') {\n return `${field}:${PRESET_TOKEN_BY_CONDITION[filter.condition]}:${filter.preset}`;\n }\n\n return `${field}:${RANGE_TOKEN_BY_CONDITION[filter.condition]}:${filter.from}..${filter.to}`;\n};\n\nexport const serializeFilters = (filters: ListFilter[]): string =>\n filters.map(serializeBadge).join(';');\n\nexport interface ListFilters {\n filters: ListFilter[];\n /** Serialized form — stable fingerprint for list-identity (selection reset). */\n serialized: string;\n addFilter: (filter: ListFilter) => void;\n /** Replaces the badge at `index` (condition or value edited in place). */\n updateFilter: (index: number, filter: ListFilter) => void;\n removeFilter: (index: number) => void;\n clearFilters: () => void;\n}\n\nexport const useListFilters = (): ListFilters => {\n const [{ query }, setQuery] = useListQueryParams<{ filters?: string; _q?: string }>();\n\n const filters = parseFiltersParam(query?.filters);\n\n // `replace: true` on every write: filters are edited in rapid micro-steps\n // (each checkbox of the keep-open Type submenu, each badge segment edit), so\n // pushing would turn one logical change into a stack of Back entries. The\n // URL stays shareable and refresh-safe either way.\n const writeFilters = (next: ListFilter[]) => {\n if (next.length === 0) {\n setQuery(withEncodedUserParams(query, { filters: undefined }), 'push', true);\n } else {\n setQuery(withEncodedUserParams(query, { filters: serializeFilters(next) }), 'push', true);\n }\n };\n\n return {\n filters,\n serialized: serializeFilters(filters),\n addFilter: (filter) => writeFilters([...filters, filter]),\n updateFilter: (index, filter) =>\n writeFilters(filters.map((f, i) => (i === index ? filter : f))),\n removeFilter: (index) => writeFilters(filters.filter((_, i) => i !== index)),\n clearFilters: () => writeFilters([]),\n };\n};\n"],"names":["TYPE_VALUES","DATE_PRESETS","FIELD_TOKENS","created","updated","FIELD_TOKEN_BY_FIELD","createdAt","updatedAt","PRESET_CONDITION_TOKENS","exact","within","notwithin","PRESET_TOKEN_BY_CONDITION","isExactly","withinLast","notWithinLast","RANGE_CONDITION_TOKENS","rangeis","rangenot","RANGE_TOKEN_BY_CONDITION","is","isNot","DATE_RE","isTypeValue","value","includes","isDatePreset","parseBadge","raw","field","condition","split","values","filter","length","kind","dateField","mode","preset","from","to","test","parseFiltersParam","map","serializeBadge","join","serializeFilters","filters","useListFilters","query","setQuery","useListQueryParams","writeFilters","next","withEncodedUserParams","undefined","serialized","addFilter","updateFilter","index","f","i","removeFilter","_","clearFilters"],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var strapiAdmin = require('@strapi/admin/strapi-admin');
5
+ var qs = require('qs');
6
+
7
+ const ListQueryStateContext = React.createContext(null);
8
+ /**
9
+ * Keeps the list query (folder, search, filters, sort) in memory instead of the
10
+ * URL, for surfaces hosted inside another page — the Content Manager asset
11
+ * picker would otherwise overwrite the entry's own URL. Without this provider,
12
+ * `useListQueryParams` falls back to the URL, which is what the Media Library
13
+ * page relies on.
14
+ */ const ListQueryStateProvider = ({ children })=>{
15
+ const [search, setSearch] = React.useState('');
16
+ const value = React.useMemo(()=>({
17
+ search,
18
+ setSearch
19
+ }), [
20
+ search
21
+ ]);
22
+ return React.createElement(ListQueryStateContext.Provider, {
23
+ value
24
+ }, children);
25
+ };
26
+ /**
27
+ * Drop-in for `useQueryParams` used by the list hooks. The in-memory store keeps
28
+ * a serialized search string and goes through the same `qs` round trip as the
29
+ * URL, so callers that pre-encode values (`withEncodedUserParams`,
30
+ * `encodeSearchQuery`) read back exactly what they would from the URL.
31
+ */ const useListQueryParams = ()=>{
32
+ const urlQueryParams = strapiAdmin.useQueryParams();
33
+ const memoryState = React.useContext(ListQueryStateContext);
34
+ const memorySearch = memoryState?.search ?? '';
35
+ const setMemorySearch = memoryState?.setSearch;
36
+ const memoryQuery = React.useMemo(()=>qs.parse(memorySearch), [
37
+ memorySearch
38
+ ]);
39
+ const setMemoryQuery = React.useCallback((nextParams, method = 'push')=>{
40
+ if (!setMemorySearch) {
41
+ return;
42
+ }
43
+ setMemorySearch((currentSearch)=>{
44
+ const currentQuery = qs.parse(currentSearch);
45
+ let nextQuery;
46
+ if (method === 'remove') {
47
+ nextQuery = {
48
+ ...currentQuery
49
+ };
50
+ Object.keys(nextParams).forEach((key)=>{
51
+ delete nextQuery[key];
52
+ });
53
+ } else {
54
+ nextQuery = {
55
+ ...currentQuery,
56
+ ...nextParams
57
+ };
58
+ }
59
+ return qs.stringify(nextQuery, {
60
+ encode: false
61
+ });
62
+ });
63
+ }, [
64
+ setMemorySearch
65
+ ]);
66
+ if (!memoryState) {
67
+ return urlQueryParams;
68
+ }
69
+ return [
70
+ {
71
+ query: memoryQuery,
72
+ rawQuery: memorySearch
73
+ },
74
+ setMemoryQuery
75
+ ];
76
+ };
77
+
78
+ exports.ListQueryStateProvider = ListQueryStateProvider;
79
+ exports.useListQueryParams = useListQueryParams;
80
+ //# sourceMappingURL=useListQueryParams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListQueryParams.js","sources":["../../../../../admin/src/pages/Assets/hooks/useListQueryParams.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useMemo,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\n\nimport { useQueryParams } from '@strapi/admin/strapi-admin';\nimport { parse, stringify } from 'qs';\n\ntype SetQuery<TQuery> = (nextParams: TQuery, method?: 'push' | 'remove', replace?: boolean) => void;\n\ninterface ListQueryState {\n search: string;\n setSearch: Dispatch<SetStateAction<string>>;\n}\n\nconst ListQueryStateContext = createContext<ListQueryState | null>(null);\n\ninterface ListQueryStateProviderProps {\n children: ReactNode;\n}\n\n/**\n * Keeps the list query (folder, search, filters, sort) in memory instead of the\n * URL, for surfaces hosted inside another page — the Content Manager asset\n * picker would otherwise overwrite the entry's own URL. Without this provider,\n * `useListQueryParams` falls back to the URL, which is what the Media Library\n * page relies on.\n */\nexport const ListQueryStateProvider = ({ children }: ListQueryStateProviderProps) => {\n const [search, setSearch] = useState('');\n const value = useMemo(() => ({ search, setSearch }), [search]);\n\n return createElement(ListQueryStateContext.Provider, { value }, children);\n};\n\n/**\n * Drop-in for `useQueryParams` used by the list hooks. The in-memory store keeps\n * a serialized search string and goes through the same `qs` round trip as the\n * URL, so callers that pre-encode values (`withEncodedUserParams`,\n * `encodeSearchQuery`) read back exactly what they would from the URL.\n */\nexport const useListQueryParams = <TQuery extends object>() => {\n const urlQueryParams = useQueryParams<TQuery>();\n const memoryState = useContext(ListQueryStateContext);\n\n const memorySearch = memoryState?.search ?? '';\n const setMemorySearch = memoryState?.setSearch;\n\n const memoryQuery = useMemo(() => parse(memorySearch) as TQuery, [memorySearch]);\n\n const setMemoryQuery = useCallback<SetQuery<TQuery>>(\n (nextParams, method = 'push') => {\n if (!setMemorySearch) {\n return;\n }\n\n setMemorySearch((currentSearch) => {\n const currentQuery = parse(currentSearch) as Partial<TQuery>;\n let nextQuery: Partial<TQuery>;\n\n if (method === 'remove') {\n nextQuery = { ...currentQuery };\n Object.keys(nextParams).forEach((key) => {\n delete nextQuery[key as keyof TQuery];\n });\n } else {\n nextQuery = { ...currentQuery, ...nextParams };\n }\n\n return stringify(nextQuery, { encode: false });\n });\n },\n [setMemorySearch]\n );\n\n if (!memoryState) {\n return urlQueryParams;\n }\n\n return [{ query: memoryQuery, rawQuery: memorySearch }, setMemoryQuery] as const;\n};\n"],"names":["ListQueryStateContext","createContext","ListQueryStateProvider","children","search","setSearch","useState","value","useMemo","createElement","Provider","useListQueryParams","urlQueryParams","useQueryParams","memoryState","useContext","memorySearch","setMemorySearch","memoryQuery","parse","setMemoryQuery","useCallback","nextParams","method","currentSearch","currentQuery","nextQuery","Object","keys","forEach","key","stringify","encode","query","rawQuery"],"mappings":";;;;;;AAsBA,MAAMA,wBAAwBC,mBAAAA,CAAqC,IAAA,CAAA;AAMnE;;;;;;AAMC,IACM,MAAMC,sBAAAA,GAAyB,CAAC,EAAEC,QAAQ,EAA+B,GAAA;AAC9E,IAAA,MAAM,CAACC,MAAAA,EAAQC,SAAAA,CAAU,GAAGC,cAAAA,CAAS,EAAA,CAAA;IACrC,MAAMC,KAAAA,GAAQC,aAAAA,CAAQ,KAAO;AAAEJ,YAAAA,MAAAA;AAAQC,YAAAA;AAAU,SAAA,CAAA,EAAI;AAACD,QAAAA;AAAO,KAAA,CAAA;IAE7D,OAAOK,mBAAAA,CAAcT,qBAAAA,CAAsBU,QAAQ,EAAE;AAAEH,QAAAA;KAAM,EAAGJ,QAAAA,CAAAA;AAClE;AAEA;;;;;UAMaQ,kBAAAA,GAAqB,IAAA;AAChC,IAAA,MAAMC,cAAAA,GAAiBC,0BAAAA,EAAAA;AACvB,IAAA,MAAMC,cAAcC,gBAAAA,CAAWf,qBAAAA,CAAAA;IAE/B,MAAMgB,YAAAA,GAAeF,aAAaV,MAAAA,IAAU,EAAA;AAC5C,IAAA,MAAMa,kBAAkBH,WAAAA,EAAaT,SAAAA;AAErC,IAAA,MAAMa,WAAAA,GAAcV,aAAAA,CAAQ,IAAMW,QAAAA,CAAMH,YAAAA,CAAAA,EAAyB;AAACA,QAAAA;AAAa,KAAA,CAAA;AAE/E,IAAA,MAAMI,cAAAA,GAAiBC,iBAAAA,CACrB,CAACC,UAAAA,EAAYC,SAAS,MAAM,GAAA;AAC1B,QAAA,IAAI,CAACN,eAAAA,EAAiB;AACpB,YAAA;AACF,QAAA;AAEAA,QAAAA,eAAAA,CAAgB,CAACO,aAAAA,GAAAA;AACf,YAAA,MAAMC,eAAeN,QAAAA,CAAMK,aAAAA,CAAAA;YAC3B,IAAIE,SAAAA;AAEJ,YAAA,IAAIH,WAAW,QAAA,EAAU;gBACvBG,SAAAA,GAAY;AAAE,oBAAA,GAAGD;AAAa,iBAAA;AAC9BE,gBAAAA,MAAAA,CAAOC,IAAI,CAACN,UAAAA,CAAAA,CAAYO,OAAO,CAAC,CAACC,GAAAA,GAAAA;oBAC/B,OAAOJ,SAAS,CAACI,GAAAA,CAAoB;AACvC,gBAAA,CAAA,CAAA;YACF,CAAA,MAAO;gBACLJ,SAAAA,GAAY;AAAE,oBAAA,GAAGD,YAAY;AAAE,oBAAA,GAAGH;AAAW,iBAAA;AAC/C,YAAA;AAEA,YAAA,OAAOS,aAAUL,SAAAA,EAAW;gBAAEM,MAAAA,EAAQ;AAAM,aAAA,CAAA;AAC9C,QAAA,CAAA,CAAA;IACF,CAAA,EACA;AAACf,QAAAA;AAAgB,KAAA,CAAA;AAGnB,IAAA,IAAI,CAACH,WAAAA,EAAa;QAChB,OAAOF,cAAAA;AACT,IAAA;IAEA,OAAO;AAAC,QAAA;YAAEqB,KAAAA,EAAOf,WAAAA;YAAagB,QAAAA,EAAUlB;AAAa,SAAA;AAAGI,QAAAA;AAAe,KAAA;AACzE;;;;;"}
@@ -0,0 +1,77 @@
1
+ import { createContext, useState, useMemo, createElement, useContext, useCallback } from 'react';
2
+ import { useQueryParams } from '@strapi/admin/strapi-admin';
3
+ import { parse, stringify } from 'qs';
4
+
5
+ const ListQueryStateContext = createContext(null);
6
+ /**
7
+ * Keeps the list query (folder, search, filters, sort) in memory instead of the
8
+ * URL, for surfaces hosted inside another page — the Content Manager asset
9
+ * picker would otherwise overwrite the entry's own URL. Without this provider,
10
+ * `useListQueryParams` falls back to the URL, which is what the Media Library
11
+ * page relies on.
12
+ */ const ListQueryStateProvider = ({ children })=>{
13
+ const [search, setSearch] = useState('');
14
+ const value = useMemo(()=>({
15
+ search,
16
+ setSearch
17
+ }), [
18
+ search
19
+ ]);
20
+ return createElement(ListQueryStateContext.Provider, {
21
+ value
22
+ }, children);
23
+ };
24
+ /**
25
+ * Drop-in for `useQueryParams` used by the list hooks. The in-memory store keeps
26
+ * a serialized search string and goes through the same `qs` round trip as the
27
+ * URL, so callers that pre-encode values (`withEncodedUserParams`,
28
+ * `encodeSearchQuery`) read back exactly what they would from the URL.
29
+ */ const useListQueryParams = ()=>{
30
+ const urlQueryParams = useQueryParams();
31
+ const memoryState = useContext(ListQueryStateContext);
32
+ const memorySearch = memoryState?.search ?? '';
33
+ const setMemorySearch = memoryState?.setSearch;
34
+ const memoryQuery = useMemo(()=>parse(memorySearch), [
35
+ memorySearch
36
+ ]);
37
+ const setMemoryQuery = useCallback((nextParams, method = 'push')=>{
38
+ if (!setMemorySearch) {
39
+ return;
40
+ }
41
+ setMemorySearch((currentSearch)=>{
42
+ const currentQuery = parse(currentSearch);
43
+ let nextQuery;
44
+ if (method === 'remove') {
45
+ nextQuery = {
46
+ ...currentQuery
47
+ };
48
+ Object.keys(nextParams).forEach((key)=>{
49
+ delete nextQuery[key];
50
+ });
51
+ } else {
52
+ nextQuery = {
53
+ ...currentQuery,
54
+ ...nextParams
55
+ };
56
+ }
57
+ return stringify(nextQuery, {
58
+ encode: false
59
+ });
60
+ });
61
+ }, [
62
+ setMemorySearch
63
+ ]);
64
+ if (!memoryState) {
65
+ return urlQueryParams;
66
+ }
67
+ return [
68
+ {
69
+ query: memoryQuery,
70
+ rawQuery: memorySearch
71
+ },
72
+ setMemoryQuery
73
+ ];
74
+ };
75
+
76
+ export { ListQueryStateProvider, useListQueryParams };
77
+ //# sourceMappingURL=useListQueryParams.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListQueryParams.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useListQueryParams.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useMemo,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\n\nimport { useQueryParams } from '@strapi/admin/strapi-admin';\nimport { parse, stringify } from 'qs';\n\ntype SetQuery<TQuery> = (nextParams: TQuery, method?: 'push' | 'remove', replace?: boolean) => void;\n\ninterface ListQueryState {\n search: string;\n setSearch: Dispatch<SetStateAction<string>>;\n}\n\nconst ListQueryStateContext = createContext<ListQueryState | null>(null);\n\ninterface ListQueryStateProviderProps {\n children: ReactNode;\n}\n\n/**\n * Keeps the list query (folder, search, filters, sort) in memory instead of the\n * URL, for surfaces hosted inside another page — the Content Manager asset\n * picker would otherwise overwrite the entry's own URL. Without this provider,\n * `useListQueryParams` falls back to the URL, which is what the Media Library\n * page relies on.\n */\nexport const ListQueryStateProvider = ({ children }: ListQueryStateProviderProps) => {\n const [search, setSearch] = useState('');\n const value = useMemo(() => ({ search, setSearch }), [search]);\n\n return createElement(ListQueryStateContext.Provider, { value }, children);\n};\n\n/**\n * Drop-in for `useQueryParams` used by the list hooks. The in-memory store keeps\n * a serialized search string and goes through the same `qs` round trip as the\n * URL, so callers that pre-encode values (`withEncodedUserParams`,\n * `encodeSearchQuery`) read back exactly what they would from the URL.\n */\nexport const useListQueryParams = <TQuery extends object>() => {\n const urlQueryParams = useQueryParams<TQuery>();\n const memoryState = useContext(ListQueryStateContext);\n\n const memorySearch = memoryState?.search ?? '';\n const setMemorySearch = memoryState?.setSearch;\n\n const memoryQuery = useMemo(() => parse(memorySearch) as TQuery, [memorySearch]);\n\n const setMemoryQuery = useCallback<SetQuery<TQuery>>(\n (nextParams, method = 'push') => {\n if (!setMemorySearch) {\n return;\n }\n\n setMemorySearch((currentSearch) => {\n const currentQuery = parse(currentSearch) as Partial<TQuery>;\n let nextQuery: Partial<TQuery>;\n\n if (method === 'remove') {\n nextQuery = { ...currentQuery };\n Object.keys(nextParams).forEach((key) => {\n delete nextQuery[key as keyof TQuery];\n });\n } else {\n nextQuery = { ...currentQuery, ...nextParams };\n }\n\n return stringify(nextQuery, { encode: false });\n });\n },\n [setMemorySearch]\n );\n\n if (!memoryState) {\n return urlQueryParams;\n }\n\n return [{ query: memoryQuery, rawQuery: memorySearch }, setMemoryQuery] as const;\n};\n"],"names":["ListQueryStateContext","createContext","ListQueryStateProvider","children","search","setSearch","useState","value","useMemo","createElement","Provider","useListQueryParams","urlQueryParams","useQueryParams","memoryState","useContext","memorySearch","setMemorySearch","memoryQuery","parse","setMemoryQuery","useCallback","nextParams","method","currentSearch","currentQuery","nextQuery","Object","keys","forEach","key","stringify","encode","query","rawQuery"],"mappings":";;;;AAsBA,MAAMA,wBAAwBC,aAAAA,CAAqC,IAAA,CAAA;AAMnE;;;;;;AAMC,IACM,MAAMC,sBAAAA,GAAyB,CAAC,EAAEC,QAAQ,EAA+B,GAAA;AAC9E,IAAA,MAAM,CAACC,MAAAA,EAAQC,SAAAA,CAAU,GAAGC,QAAAA,CAAS,EAAA,CAAA;IACrC,MAAMC,KAAAA,GAAQC,OAAAA,CAAQ,KAAO;AAAEJ,YAAAA,MAAAA;AAAQC,YAAAA;AAAU,SAAA,CAAA,EAAI;AAACD,QAAAA;AAAO,KAAA,CAAA;IAE7D,OAAOK,aAAAA,CAAcT,qBAAAA,CAAsBU,QAAQ,EAAE;AAAEH,QAAAA;KAAM,EAAGJ,QAAAA,CAAAA;AAClE;AAEA;;;;;UAMaQ,kBAAAA,GAAqB,IAAA;AAChC,IAAA,MAAMC,cAAAA,GAAiBC,cAAAA,EAAAA;AACvB,IAAA,MAAMC,cAAcC,UAAAA,CAAWf,qBAAAA,CAAAA;IAE/B,MAAMgB,YAAAA,GAAeF,aAAaV,MAAAA,IAAU,EAAA;AAC5C,IAAA,MAAMa,kBAAkBH,WAAAA,EAAaT,SAAAA;AAErC,IAAA,MAAMa,WAAAA,GAAcV,OAAAA,CAAQ,IAAMW,KAAAA,CAAMH,YAAAA,CAAAA,EAAyB;AAACA,QAAAA;AAAa,KAAA,CAAA;AAE/E,IAAA,MAAMI,cAAAA,GAAiBC,WAAAA,CACrB,CAACC,UAAAA,EAAYC,SAAS,MAAM,GAAA;AAC1B,QAAA,IAAI,CAACN,eAAAA,EAAiB;AACpB,YAAA;AACF,QAAA;AAEAA,QAAAA,eAAAA,CAAgB,CAACO,aAAAA,GAAAA;AACf,YAAA,MAAMC,eAAeN,KAAAA,CAAMK,aAAAA,CAAAA;YAC3B,IAAIE,SAAAA;AAEJ,YAAA,IAAIH,WAAW,QAAA,EAAU;gBACvBG,SAAAA,GAAY;AAAE,oBAAA,GAAGD;AAAa,iBAAA;AAC9BE,gBAAAA,MAAAA,CAAOC,IAAI,CAACN,UAAAA,CAAAA,CAAYO,OAAO,CAAC,CAACC,GAAAA,GAAAA;oBAC/B,OAAOJ,SAAS,CAACI,GAAAA,CAAoB;AACvC,gBAAA,CAAA,CAAA;YACF,CAAA,MAAO;gBACLJ,SAAAA,GAAY;AAAE,oBAAA,GAAGD,YAAY;AAAE,oBAAA,GAAGH;AAAW,iBAAA;AAC/C,YAAA;AAEA,YAAA,OAAOS,UAAUL,SAAAA,EAAW;gBAAEM,MAAAA,EAAQ;AAAM,aAAA,CAAA;AAC9C,QAAA,CAAA,CAAA;IACF,CAAA,EACA;AAACf,QAAAA;AAAgB,KAAA,CAAA;AAGnB,IAAA,IAAI,CAACH,WAAAA,EAAa;QAChB,OAAOF,cAAAA;AACT,IAAA;IAEA,OAAO;AAAC,QAAA;YAAEqB,KAAAA,EAAOf,WAAAA;YAAagB,QAAAA,EAAUlB;AAAa,SAAA;AAAGI,QAAAA;AAAe,KAAA;AACzE;;;;"}
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ const DEFAULT_LIST_SETTINGS = {
6
+ showItemActions: true,
7
+ showSectionHeadings: false,
8
+ gridMinTileWidth: '240px',
9
+ showGridSelectAll: false
10
+ };
11
+ const ListSettingsContext = React.createContext(DEFAULT_LIST_SETTINGS);
12
+ const ListSettingsProvider = ({ children, showItemActions = DEFAULT_LIST_SETTINGS.showItemActions, showSectionHeadings = DEFAULT_LIST_SETTINGS.showSectionHeadings, gridMinTileWidth = DEFAULT_LIST_SETTINGS.gridMinTileWidth, showGridSelectAll = DEFAULT_LIST_SETTINGS.showGridSelectAll })=>{
13
+ const value = React.useMemo(()=>({
14
+ showItemActions,
15
+ showSectionHeadings,
16
+ gridMinTileWidth,
17
+ showGridSelectAll
18
+ }), [
19
+ showItemActions,
20
+ showSectionHeadings,
21
+ gridMinTileWidth,
22
+ showGridSelectAll
23
+ ]);
24
+ return React.createElement(ListSettingsContext.Provider, {
25
+ value
26
+ }, children);
27
+ };
28
+ /** Without a provider, returns the Media Library page's settings. */ const useListSettings = ()=>React.useContext(ListSettingsContext);
29
+
30
+ exports.ListSettingsProvider = ListSettingsProvider;
31
+ exports.useListSettings = useListSettings;
32
+ //# sourceMappingURL=useListSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListSettings.js","sources":["../../../../../admin/src/pages/Assets/hooks/useListSettings.ts"],"sourcesContent":["import { createContext, createElement, useContext, useMemo, type ReactNode } from 'react';\n\ninterface ListSettings {\n /**\n * Management affordances on list items: the right-click menu and the bulk\n * actions bar. A picker hosted elsewhere (the Content Manager asset picker)\n * turns them off — choosing an asset is not the place to delete or move it.\n */\n showItemActions: boolean;\n /**\n * \"Folders (n)\" / \"Assets (n)\" headings above each grid section, with a\n * divider between them. The page carries the count in its own header instead.\n */\n showSectionHeadings: boolean;\n /** Narrowest a grid tile may get before the grid drops a column. */\n gridMinTileWidth: string;\n /**\n * A \"Select all\" checkbox beside the grid's \"Assets (n)\" heading, the grid's\n * counterpart of the table's header checkbox. The page reaches select-all\n * from its bulk actions bar instead.\n */\n showGridSelectAll: boolean;\n}\n\nconst DEFAULT_LIST_SETTINGS: ListSettings = {\n showItemActions: true,\n showSectionHeadings: false,\n gridMinTileWidth: '240px',\n showGridSelectAll: false,\n};\n\nconst ListSettingsContext = createContext<ListSettings>(DEFAULT_LIST_SETTINGS);\n\ninterface ListSettingsProviderProps extends Partial<ListSettings> {\n children: ReactNode;\n}\n\nexport const ListSettingsProvider = ({\n children,\n showItemActions = DEFAULT_LIST_SETTINGS.showItemActions,\n showSectionHeadings = DEFAULT_LIST_SETTINGS.showSectionHeadings,\n gridMinTileWidth = DEFAULT_LIST_SETTINGS.gridMinTileWidth,\n showGridSelectAll = DEFAULT_LIST_SETTINGS.showGridSelectAll,\n}: ListSettingsProviderProps) => {\n const value = useMemo(\n () => ({ showItemActions, showSectionHeadings, gridMinTileWidth, showGridSelectAll }),\n [showItemActions, showSectionHeadings, gridMinTileWidth, showGridSelectAll]\n );\n\n return createElement(ListSettingsContext.Provider, { value }, children);\n};\n\n/** Without a provider, returns the Media Library page's settings. */\nexport const useListSettings = () => useContext(ListSettingsContext);\n"],"names":["DEFAULT_LIST_SETTINGS","showItemActions","showSectionHeadings","gridMinTileWidth","showGridSelectAll","ListSettingsContext","createContext","ListSettingsProvider","children","value","useMemo","createElement","Provider","useListSettings","useContext"],"mappings":";;;;AAwBA,MAAMA,qBAAAA,GAAsC;IAC1CC,eAAAA,EAAiB,IAAA;IACjBC,mBAAAA,EAAqB,KAAA;IACrBC,gBAAAA,EAAkB,OAAA;IAClBC,iBAAAA,EAAmB;AACrB,CAAA;AAEA,MAAMC,sBAAsBC,mBAAAA,CAA4BN,qBAAAA,CAAAA;AAMjD,MAAMO,uBAAuB,CAAC,EACnCC,QAAQ,EACRP,eAAAA,GAAkBD,sBAAsBC,eAAe,EACvDC,sBAAsBF,qBAAAA,CAAsBE,mBAAmB,EAC/DC,gBAAAA,GAAmBH,qBAAAA,CAAsBG,gBAAgB,EACzDC,iBAAAA,GAAoBJ,qBAAAA,CAAsBI,iBAAiB,EACjC,GAAA;IAC1B,MAAMK,KAAAA,GAAQC,aAAAA,CACZ,KAAO;AAAET,YAAAA,eAAAA;AAAiBC,YAAAA,mBAAAA;AAAqBC,YAAAA,gBAAAA;AAAkBC,YAAAA;AAAkB,SAAA,CAAA,EACnF;AAACH,QAAAA,eAAAA;AAAiBC,QAAAA,mBAAAA;AAAqBC,QAAAA,gBAAAA;AAAkBC,QAAAA;AAAkB,KAAA,CAAA;IAG7E,OAAOO,mBAAAA,CAAcN,mBAAAA,CAAoBO,QAAQ,EAAE;AAAEH,QAAAA;KAAM,EAAGD,QAAAA,CAAAA;AAChE;AAEA,sEACO,MAAMK,eAAAA,GAAkB,IAAMC,iBAAWT,mBAAAA;;;;;"}
@@ -0,0 +1,29 @@
1
+ import { createContext, useMemo, createElement, useContext } from 'react';
2
+
3
+ const DEFAULT_LIST_SETTINGS = {
4
+ showItemActions: true,
5
+ showSectionHeadings: false,
6
+ gridMinTileWidth: '240px',
7
+ showGridSelectAll: false
8
+ };
9
+ const ListSettingsContext = createContext(DEFAULT_LIST_SETTINGS);
10
+ const ListSettingsProvider = ({ children, showItemActions = DEFAULT_LIST_SETTINGS.showItemActions, showSectionHeadings = DEFAULT_LIST_SETTINGS.showSectionHeadings, gridMinTileWidth = DEFAULT_LIST_SETTINGS.gridMinTileWidth, showGridSelectAll = DEFAULT_LIST_SETTINGS.showGridSelectAll })=>{
11
+ const value = useMemo(()=>({
12
+ showItemActions,
13
+ showSectionHeadings,
14
+ gridMinTileWidth,
15
+ showGridSelectAll
16
+ }), [
17
+ showItemActions,
18
+ showSectionHeadings,
19
+ gridMinTileWidth,
20
+ showGridSelectAll
21
+ ]);
22
+ return createElement(ListSettingsContext.Provider, {
23
+ value
24
+ }, children);
25
+ };
26
+ /** Without a provider, returns the Media Library page's settings. */ const useListSettings = ()=>useContext(ListSettingsContext);
27
+
28
+ export { ListSettingsProvider, useListSettings };
29
+ //# sourceMappingURL=useListSettings.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useListSettings.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useListSettings.ts"],"sourcesContent":["import { createContext, createElement, useContext, useMemo, type ReactNode } from 'react';\n\ninterface ListSettings {\n /**\n * Management affordances on list items: the right-click menu and the bulk\n * actions bar. A picker hosted elsewhere (the Content Manager asset picker)\n * turns them off — choosing an asset is not the place to delete or move it.\n */\n showItemActions: boolean;\n /**\n * \"Folders (n)\" / \"Assets (n)\" headings above each grid section, with a\n * divider between them. The page carries the count in its own header instead.\n */\n showSectionHeadings: boolean;\n /** Narrowest a grid tile may get before the grid drops a column. */\n gridMinTileWidth: string;\n /**\n * A \"Select all\" checkbox beside the grid's \"Assets (n)\" heading, the grid's\n * counterpart of the table's header checkbox. The page reaches select-all\n * from its bulk actions bar instead.\n */\n showGridSelectAll: boolean;\n}\n\nconst DEFAULT_LIST_SETTINGS: ListSettings = {\n showItemActions: true,\n showSectionHeadings: false,\n gridMinTileWidth: '240px',\n showGridSelectAll: false,\n};\n\nconst ListSettingsContext = createContext<ListSettings>(DEFAULT_LIST_SETTINGS);\n\ninterface ListSettingsProviderProps extends Partial<ListSettings> {\n children: ReactNode;\n}\n\nexport const ListSettingsProvider = ({\n children,\n showItemActions = DEFAULT_LIST_SETTINGS.showItemActions,\n showSectionHeadings = DEFAULT_LIST_SETTINGS.showSectionHeadings,\n gridMinTileWidth = DEFAULT_LIST_SETTINGS.gridMinTileWidth,\n showGridSelectAll = DEFAULT_LIST_SETTINGS.showGridSelectAll,\n}: ListSettingsProviderProps) => {\n const value = useMemo(\n () => ({ showItemActions, showSectionHeadings, gridMinTileWidth, showGridSelectAll }),\n [showItemActions, showSectionHeadings, gridMinTileWidth, showGridSelectAll]\n );\n\n return createElement(ListSettingsContext.Provider, { value }, children);\n};\n\n/** Without a provider, returns the Media Library page's settings. */\nexport const useListSettings = () => useContext(ListSettingsContext);\n"],"names":["DEFAULT_LIST_SETTINGS","showItemActions","showSectionHeadings","gridMinTileWidth","showGridSelectAll","ListSettingsContext","createContext","ListSettingsProvider","children","value","useMemo","createElement","Provider","useListSettings","useContext"],"mappings":";;AAwBA,MAAMA,qBAAAA,GAAsC;IAC1CC,eAAAA,EAAiB,IAAA;IACjBC,mBAAAA,EAAqB,KAAA;IACrBC,gBAAAA,EAAkB,OAAA;IAClBC,iBAAAA,EAAmB;AACrB,CAAA;AAEA,MAAMC,sBAAsBC,aAAAA,CAA4BN,qBAAAA,CAAAA;AAMjD,MAAMO,uBAAuB,CAAC,EACnCC,QAAQ,EACRP,eAAAA,GAAkBD,sBAAsBC,eAAe,EACvDC,sBAAsBF,qBAAAA,CAAsBE,mBAAmB,EAC/DC,gBAAAA,GAAmBH,qBAAAA,CAAsBG,gBAAgB,EACzDC,iBAAAA,GAAoBJ,qBAAAA,CAAsBI,iBAAiB,EACjC,GAAA;IAC1B,MAAMK,KAAAA,GAAQC,OAAAA,CACZ,KAAO;AAAET,YAAAA,eAAAA;AAAiBC,YAAAA,mBAAAA;AAAqBC,YAAAA,gBAAAA;AAAkBC,YAAAA;AAAkB,SAAA,CAAA,EACnF;AAACH,QAAAA,eAAAA;AAAiBC,QAAAA,mBAAAA;AAAqBC,QAAAA,gBAAAA;AAAkBC,QAAAA;AAAkB,KAAA,CAAA;IAG7E,OAAOO,aAAAA,CAAcN,mBAAAA,CAAoBO,QAAQ,EAAE;AAAEH,QAAAA;KAAM,EAAGD,QAAAA,CAAAA;AAChE;AAEA,sEACO,MAAMK,eAAAA,GAAkB,IAAMC,WAAWT,mBAAAA;;;;"}
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var strapiAdmin = require('@strapi/admin/strapi-admin');
4
+ var useListQueryParams = require('./useListQueryParams.js');
4
5
 
5
6
  /**
6
7
  * Sort state for the assets list, backed by URL query params so the current
@@ -64,7 +65,7 @@ const serializeSort = (sortBy, direction)=>{
64
65
  return rules.filter((rule)=>Boolean(rule)).join(',');
65
66
  };
66
67
  const useListSort = ()=>{
67
- const [{ query }, setQuery] = strapiAdmin.useQueryParams();
68
+ const [{ query }, setQuery] = useListQueryParams.useListQueryParams();
68
69
  const { sortBy, direction, isExplicit } = parseSortParam(query?.sort);
69
70
  const foldersPosition = query?.folders === 'mixed' ? 'mixed' : 'top';
70
71
  const writeSort = (nextSortBy, nextDirection)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"useListSort.js","sources":["../../../../../admin/src/pages/Assets/hooks/useListSort.ts"],"sourcesContent":["import { useQueryParams, withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\n/**\n * Sort state for the assets list, backed by URL query params so the current\n * ordering is shareable and survives Back/refresh:\n *\n * - `?sort=<rule>` — a single whitelisted rule. Omitted → default (most\n * recent updates).\n * - `?folders=mixed` — folders interleaved with files. Omitted → folders on top.\n *\n * The date rules and the direction rules are mutually exclusive: exactly one\n * rule is active at a time (one checkmark total, like the design mock). Picking\n * an option in one group clears the other; clearing the active option falls\n * back to the default — an unsorted list is not a state the UI offers.\n */\n\nexport const SORT_BY_RULES = {\n oldestUploads: 'createdAt:ASC',\n mostRecentUpdates: 'updatedAt:DESC',\n} as const;\n\nexport const SORT_DIRECTION_RULES = {\n nameAsc: 'name:ASC',\n nameDesc: 'name:DESC',\n sizeAsc: 'size:ASC',\n sizeDesc: 'size:DESC',\n} as const;\n\nexport type SortByKey = keyof typeof SORT_BY_RULES;\nexport type SortDirectionKey = keyof typeof SORT_DIRECTION_RULES;\nexport type FoldersPosition = 'top' | 'mixed';\n\nconst DEFAULT_SORT_BY: SortByKey = 'mostRecentUpdates';\n\nconst SORT_BY_BY_RULE = Object.fromEntries(\n Object.entries(SORT_BY_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortByKey>;\n\nconst SORT_DIRECTION_BY_RULE = Object.fromEntries(\n Object.entries(SORT_DIRECTION_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortDirectionKey>;\n\ninterface ParsedSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n /** False when the state is the fallback default (no recognized rule in the URL). */\n isExplicit: boolean;\n}\n\n/** Parses `?sort=` — the first recognized rule wins, unknown rules are dropped. */\nconst parseSortParam = (raw: string | undefined): ParsedSort => {\n for (const rule of (raw ?? '').split(',')) {\n if (rule in SORT_BY_BY_RULE) {\n return { sortBy: SORT_BY_BY_RULE[rule], direction: null, isExplicit: true };\n }\n if (rule in SORT_DIRECTION_BY_RULE) {\n return { sortBy: null, direction: SORT_DIRECTION_BY_RULE[rule], isExplicit: true };\n }\n }\n\n return { sortBy: DEFAULT_SORT_BY, direction: null, isExplicit: false };\n};\n\nconst serializeSort = (sortBy: SortByKey | null, direction: SortDirectionKey | null): string => {\n const rules: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && SORT_DIRECTION_RULES[direction],\n ];\n\n return rules.filter((rule): rule is string => Boolean(rule)).join(',');\n};\n\nexport interface ListSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n foldersPosition: FoldersPosition;\n /**\n * The active rule for the files query, e.g. `updatedAt:DESC` — always a\n * single rule since the sort groups are mutually exclusive.\n */\n assetsSort: string;\n /**\n * Rule applicable to the folders query. In the default state (no sort in the\n * URL) folders keep their alphabetical order so the band matches the sidebar\n * tree; an explicit user sort applies, except size rules (folders have no\n * `size` column), which fall back to alphabetical.\n */\n foldersSort: string;\n setSortBy: (key: SortByKey | null) => void;\n setDirection: (key: SortDirectionKey | null) => void;\n setFoldersPosition: (position: FoldersPosition) => void;\n}\n\nexport const useListSort = (): ListSort => {\n const [{ query }, setQuery] = useQueryParams<{\n sort?: string;\n folders?: string;\n _q?: string;\n }>();\n\n const { sortBy, direction, isExplicit } = parseSortParam(query?.sort);\n const foldersPosition: FoldersPosition = query?.folders === 'mixed' ? 'mixed' : 'top';\n\n const writeSort = (nextSortBy: SortByKey | null, nextDirection: SortDirectionKey | null) => {\n // Exactly one active rule: clearing the active one falls back to default.\n if (nextSortBy === null && nextDirection === null) {\n nextSortBy = DEFAULT_SORT_BY;\n }\n\n const serialized = serializeSort(nextSortBy, nextDirection);\n\n if (nextSortBy === DEFAULT_SORT_BY && nextDirection === null) {\n setQuery(withEncodedUserParams(query, { sort: undefined }));\n } else {\n setQuery(withEncodedUserParams(query, { sort: serialized }));\n }\n };\n\n // Groups are mutually exclusive — picking in one clears the other.\n const setSortBy = (key: SortByKey | null) => writeSort(key, null);\n const setDirection = (key: SortDirectionKey | null) => writeSort(null, key);\n\n const setFoldersPosition = (position: FoldersPosition) => {\n if (position === 'mixed') {\n setQuery(withEncodedUserParams(query, { folders: 'mixed' }));\n } else {\n setQuery(withEncodedUserParams(query, { folders: undefined }));\n }\n };\n\n const assetsSort = serializeSort(sortBy, direction);\n const folderRuleCandidates: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && !direction.startsWith('size') ? SORT_DIRECTION_RULES[direction] : null,\n ];\n const folderRules = folderRuleCandidates.filter((rule): rule is string => Boolean(rule));\n // Default state keeps folders alphabetical (matches the sidebar tree) — only\n // an explicit user sort reorders the folders band.\n const foldersSort = isExplicit && folderRules.length > 0 ? folderRules.join(',') : 'name:ASC';\n\n return {\n sortBy,\n direction,\n foldersPosition,\n assetsSort,\n foldersSort,\n setSortBy,\n setDirection,\n setFoldersPosition,\n };\n};\n"],"names":["SORT_BY_RULES","oldestUploads","mostRecentUpdates","SORT_DIRECTION_RULES","nameAsc","nameDesc","sizeAsc","sizeDesc","DEFAULT_SORT_BY","SORT_BY_BY_RULE","Object","fromEntries","entries","map","key","rule","SORT_DIRECTION_BY_RULE","parseSortParam","raw","split","sortBy","direction","isExplicit","serializeSort","rules","filter","Boolean","join","useListSort","query","setQuery","useQueryParams","sort","foldersPosition","folders","writeSort","nextSortBy","nextDirection","serialized","withEncodedUserParams","undefined","setSortBy","setDirection","setFoldersPosition","position","assetsSort","folderRuleCandidates","startsWith","folderRules","foldersSort","length"],"mappings":"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"}
1
+ {"version":3,"file":"useListSort.js","sources":["../../../../../admin/src/pages/Assets/hooks/useListSort.ts"],"sourcesContent":["import { withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\nimport { useListQueryParams } from './useListQueryParams';\n\n/**\n * Sort state for the assets list, backed by URL query params so the current\n * ordering is shareable and survives Back/refresh:\n *\n * - `?sort=<rule>` — a single whitelisted rule. Omitted → default (most\n * recent updates).\n * - `?folders=mixed` — folders interleaved with files. Omitted → folders on top.\n *\n * The date rules and the direction rules are mutually exclusive: exactly one\n * rule is active at a time (one checkmark total, like the design mock). Picking\n * an option in one group clears the other; clearing the active option falls\n * back to the default — an unsorted list is not a state the UI offers.\n */\n\nexport const SORT_BY_RULES = {\n oldestUploads: 'createdAt:ASC',\n mostRecentUpdates: 'updatedAt:DESC',\n} as const;\n\nexport const SORT_DIRECTION_RULES = {\n nameAsc: 'name:ASC',\n nameDesc: 'name:DESC',\n sizeAsc: 'size:ASC',\n sizeDesc: 'size:DESC',\n} as const;\n\nexport type SortByKey = keyof typeof SORT_BY_RULES;\nexport type SortDirectionKey = keyof typeof SORT_DIRECTION_RULES;\nexport type FoldersPosition = 'top' | 'mixed';\n\nconst DEFAULT_SORT_BY: SortByKey = 'mostRecentUpdates';\n\nconst SORT_BY_BY_RULE = Object.fromEntries(\n Object.entries(SORT_BY_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortByKey>;\n\nconst SORT_DIRECTION_BY_RULE = Object.fromEntries(\n Object.entries(SORT_DIRECTION_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortDirectionKey>;\n\ninterface ParsedSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n /** False when the state is the fallback default (no recognized rule in the URL). */\n isExplicit: boolean;\n}\n\n/** Parses `?sort=` — the first recognized rule wins, unknown rules are dropped. */\nconst parseSortParam = (raw: string | undefined): ParsedSort => {\n for (const rule of (raw ?? '').split(',')) {\n if (rule in SORT_BY_BY_RULE) {\n return { sortBy: SORT_BY_BY_RULE[rule], direction: null, isExplicit: true };\n }\n if (rule in SORT_DIRECTION_BY_RULE) {\n return { sortBy: null, direction: SORT_DIRECTION_BY_RULE[rule], isExplicit: true };\n }\n }\n\n return { sortBy: DEFAULT_SORT_BY, direction: null, isExplicit: false };\n};\n\nconst serializeSort = (sortBy: SortByKey | null, direction: SortDirectionKey | null): string => {\n const rules: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && SORT_DIRECTION_RULES[direction],\n ];\n\n return rules.filter((rule): rule is string => Boolean(rule)).join(',');\n};\n\nexport interface ListSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n foldersPosition: FoldersPosition;\n /**\n * The active rule for the files query, e.g. `updatedAt:DESC` — always a\n * single rule since the sort groups are mutually exclusive.\n */\n assetsSort: string;\n /**\n * Rule applicable to the folders query. In the default state (no sort in the\n * URL) folders keep their alphabetical order so the band matches the sidebar\n * tree; an explicit user sort applies, except size rules (folders have no\n * `size` column), which fall back to alphabetical.\n */\n foldersSort: string;\n setSortBy: (key: SortByKey | null) => void;\n setDirection: (key: SortDirectionKey | null) => void;\n setFoldersPosition: (position: FoldersPosition) => void;\n}\n\nexport const useListSort = (): ListSort => {\n const [{ query }, setQuery] = useListQueryParams<{\n sort?: string;\n folders?: string;\n _q?: string;\n }>();\n\n const { sortBy, direction, isExplicit } = parseSortParam(query?.sort);\n const foldersPosition: FoldersPosition = query?.folders === 'mixed' ? 'mixed' : 'top';\n\n const writeSort = (nextSortBy: SortByKey | null, nextDirection: SortDirectionKey | null) => {\n // Exactly one active rule: clearing the active one falls back to default.\n if (nextSortBy === null && nextDirection === null) {\n nextSortBy = DEFAULT_SORT_BY;\n }\n\n const serialized = serializeSort(nextSortBy, nextDirection);\n\n if (nextSortBy === DEFAULT_SORT_BY && nextDirection === null) {\n setQuery(withEncodedUserParams(query, { sort: undefined }));\n } else {\n setQuery(withEncodedUserParams(query, { sort: serialized }));\n }\n };\n\n // Groups are mutually exclusive — picking in one clears the other.\n const setSortBy = (key: SortByKey | null) => writeSort(key, null);\n const setDirection = (key: SortDirectionKey | null) => writeSort(null, key);\n\n const setFoldersPosition = (position: FoldersPosition) => {\n if (position === 'mixed') {\n setQuery(withEncodedUserParams(query, { folders: 'mixed' }));\n } else {\n setQuery(withEncodedUserParams(query, { folders: undefined }));\n }\n };\n\n const assetsSort = serializeSort(sortBy, direction);\n const folderRuleCandidates: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && !direction.startsWith('size') ? SORT_DIRECTION_RULES[direction] : null,\n ];\n const folderRules = folderRuleCandidates.filter((rule): rule is string => Boolean(rule));\n // Default state keeps folders alphabetical (matches the sidebar tree) — only\n // an explicit user sort reorders the folders band.\n const foldersSort = isExplicit && folderRules.length > 0 ? folderRules.join(',') : 'name:ASC';\n\n return {\n sortBy,\n direction,\n foldersPosition,\n assetsSort,\n foldersSort,\n setSortBy,\n setDirection,\n setFoldersPosition,\n };\n};\n"],"names":["SORT_BY_RULES","oldestUploads","mostRecentUpdates","SORT_DIRECTION_RULES","nameAsc","nameDesc","sizeAsc","sizeDesc","DEFAULT_SORT_BY","SORT_BY_BY_RULE","Object","fromEntries","entries","map","key","rule","SORT_DIRECTION_BY_RULE","parseSortParam","raw","split","sortBy","direction","isExplicit","serializeSort","rules","filter","Boolean","join","useListSort","query","setQuery","useListQueryParams","sort","foldersPosition","folders","writeSort","nextSortBy","nextDirection","serialized","withEncodedUserParams","undefined","setSortBy","setDirection","setFoldersPosition","position","assetsSort","folderRuleCandidates","startsWith","folderRules","foldersSort","length"],"mappings":";;;;;AAIA;;;;;;;;;;;;UAcaA,aAAAA,GAAgB;IAC3BC,aAAAA,EAAe,eAAA;IACfC,iBAAAA,EAAmB;AACrB;MAEaC,oBAAAA,GAAuB;IAClCC,OAAAA,EAAS,UAAA;IACTC,QAAAA,EAAU,WAAA;IACVC,OAAAA,EAAS,UAAA;IACTC,QAAAA,EAAU;AACZ;AAMA,MAAMC,eAAAA,GAA6B,mBAAA;AAEnC,MAAMC,eAAAA,GAAkBC,MAAAA,CAAOC,WAAW,CACxCD,OAAOE,OAAO,CAACZ,aAAAA,CAAAA,CAAea,GAAG,CAAC,CAAC,CAACC,GAAAA,EAAKC,KAAK,GAAK;AAACA,QAAAA,IAAAA;AAAMD,QAAAA;AAAI,KAAA,CAAA,CAAA;AAGhE,MAAME,sBAAAA,GAAyBN,MAAAA,CAAOC,WAAW,CAC/CD,OAAOE,OAAO,CAACT,oBAAAA,CAAAA,CAAsBU,GAAG,CAAC,CAAC,CAACC,GAAAA,EAAKC,KAAK,GAAK;AAACA,QAAAA,IAAAA;AAAMD,QAAAA;AAAI,KAAA,CAAA,CAAA;AAUvE,oFACA,MAAMG,cAAAA,GAAiB,CAACC,GAAAA,GAAAA;IACtB,KAAK,MAAMH,QAAQ,CAACG,OAAO,EAAC,EAAGC,KAAK,CAAC,GAAA,CAAA,CAAM;AACzC,QAAA,IAAIJ,QAAQN,eAAAA,EAAiB;YAC3B,OAAO;gBAAEW,MAAAA,EAAQX,eAAe,CAACM,IAAAA,CAAK;gBAAEM,SAAAA,EAAW,IAAA;gBAAMC,UAAAA,EAAY;AAAK,aAAA;AAC5E,QAAA;AACA,QAAA,IAAIP,QAAQC,sBAAAA,EAAwB;YAClC,OAAO;gBAAEI,MAAAA,EAAQ,IAAA;gBAAMC,SAAAA,EAAWL,sBAAsB,CAACD,IAAAA,CAAK;gBAAEO,UAAAA,EAAY;AAAK,aAAA;AACnF,QAAA;AACF,IAAA;IAEA,OAAO;QAAEF,MAAAA,EAAQZ,eAAAA;QAAiBa,SAAAA,EAAW,IAAA;QAAMC,UAAAA,EAAY;AAAM,KAAA;AACvE,CAAA;AAEA,MAAMC,aAAAA,GAAgB,CAACH,MAAAA,EAA0BC,SAAAA,GAAAA;AAC/C,IAAA,MAAMG,KAAAA,GAA2B;QAC/BJ,MAAAA,IAAUpB,aAAa,CAACoB,MAAAA,CAAO;QAC/BC,SAAAA,IAAalB,oBAAoB,CAACkB,SAAAA;AACnC,KAAA;IAED,OAAOG,KAAAA,CAAMC,MAAM,CAAC,CAACV,OAAyBW,OAAAA,CAAQX,IAAAA,CAAAA,CAAAA,CAAOY,IAAI,CAAC,GAAA,CAAA;AACpE,CAAA;MAuBaC,WAAAA,GAAc,IAAA;AACzB,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,qCAAAA,EAAAA;IAM9B,MAAM,EAAEX,MAAM,EAAEC,SAAS,EAAEC,UAAU,EAAE,GAAGL,cAAAA,CAAeY,KAAAA,EAAOG,IAAAA,CAAAA;AAChE,IAAA,MAAMC,eAAAA,GAAmCJ,KAAAA,EAAOK,OAAAA,KAAY,OAAA,GAAU,OAAA,GAAU,KAAA;IAEhF,MAAMC,SAAAA,GAAY,CAACC,UAAAA,EAA8BC,aAAAA,GAAAA;;QAE/C,IAAID,UAAAA,KAAe,IAAA,IAAQC,aAAAA,KAAkB,IAAA,EAAM;YACjDD,UAAAA,GAAa5B,eAAAA;AACf,QAAA;QAEA,MAAM8B,UAAAA,GAAaf,cAAca,UAAAA,EAAYC,aAAAA,CAAAA;QAE7C,IAAID,UAAAA,KAAe5B,eAAAA,IAAmB6B,aAAAA,KAAkB,IAAA,EAAM;AAC5DP,YAAAA,QAAAA,CAASS,kCAAsBV,KAAAA,EAAO;gBAAEG,IAAAA,EAAMQ;AAAU,aAAA,CAAA,CAAA;QAC1D,CAAA,MAAO;AACLV,YAAAA,QAAAA,CAASS,kCAAsBV,KAAAA,EAAO;gBAAEG,IAAAA,EAAMM;AAAW,aAAA,CAAA,CAAA;AAC3D,QAAA;AACF,IAAA,CAAA;;AAGA,IAAA,MAAMG,SAAAA,GAAY,CAAC3B,GAAAA,GAA0BqB,SAAAA,CAAUrB,GAAAA,EAAK,IAAA,CAAA;AAC5D,IAAA,MAAM4B,YAAAA,GAAe,CAAC5B,GAAAA,GAAiCqB,SAAAA,CAAU,IAAA,EAAMrB,GAAAA,CAAAA;AAEvE,IAAA,MAAM6B,qBAAqB,CAACC,QAAAA,GAAAA;AAC1B,QAAA,IAAIA,aAAa,OAAA,EAAS;AACxBd,YAAAA,QAAAA,CAASS,kCAAsBV,KAAAA,EAAO;gBAAEK,OAAAA,EAAS;AAAQ,aAAA,CAAA,CAAA;QAC3D,CAAA,MAAO;AACLJ,YAAAA,QAAAA,CAASS,kCAAsBV,KAAAA,EAAO;gBAAEK,OAAAA,EAASM;AAAU,aAAA,CAAA,CAAA;AAC7D,QAAA;AACF,IAAA,CAAA;IAEA,MAAMK,UAAAA,GAAatB,cAAcH,MAAAA,EAAQC,SAAAA,CAAAA;AACzC,IAAA,MAAMyB,oBAAAA,GAA0C;QAC9C1B,MAAAA,IAAUpB,aAAa,CAACoB,MAAAA,CAAO;QAC/BC,SAAAA,IAAa,CAACA,UAAU0B,UAAU,CAAC,UAAU5C,oBAAoB,CAACkB,UAAU,GAAG;AAChF,KAAA;AACD,IAAA,MAAM2B,cAAcF,oBAAAA,CAAqBrB,MAAM,CAAC,CAACV,OAAyBW,OAAAA,CAAQX,IAAAA,CAAAA,CAAAA;;;IAGlF,MAAMkC,WAAAA,GAAc3B,cAAc0B,WAAAA,CAAYE,MAAM,GAAG,CAAA,GAAIF,WAAAA,CAAYrB,IAAI,CAAC,GAAA,CAAA,GAAO,UAAA;IAEnF,OAAO;AACLP,QAAAA,MAAAA;AACAC,QAAAA,SAAAA;AACAY,QAAAA,eAAAA;AACAY,QAAAA,UAAAA;AACAI,QAAAA,WAAAA;AACAR,QAAAA,SAAAA;AACAC,QAAAA,YAAAA;AACAC,QAAAA;AACF,KAAA;AACF;;;;;;"}
@@ -1,4 +1,5 @@
1
- import { useQueryParams, withEncodedUserParams } from '@strapi/admin/strapi-admin';
1
+ import { withEncodedUserParams } from '@strapi/admin/strapi-admin';
2
+ import { useListQueryParams } from './useListQueryParams.mjs';
2
3
 
3
4
  /**
4
5
  * Sort state for the assets list, backed by URL query params so the current
@@ -62,7 +63,7 @@ const serializeSort = (sortBy, direction)=>{
62
63
  return rules.filter((rule)=>Boolean(rule)).join(',');
63
64
  };
64
65
  const useListSort = ()=>{
65
- const [{ query }, setQuery] = useQueryParams();
66
+ const [{ query }, setQuery] = useListQueryParams();
66
67
  const { sortBy, direction, isExplicit } = parseSortParam(query?.sort);
67
68
  const foldersPosition = query?.folders === 'mixed' ? 'mixed' : 'top';
68
69
  const writeSort = (nextSortBy, nextDirection)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"useListSort.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useListSort.ts"],"sourcesContent":["import { useQueryParams, withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\n/**\n * Sort state for the assets list, backed by URL query params so the current\n * ordering is shareable and survives Back/refresh:\n *\n * - `?sort=<rule>` — a single whitelisted rule. Omitted → default (most\n * recent updates).\n * - `?folders=mixed` — folders interleaved with files. Omitted → folders on top.\n *\n * The date rules and the direction rules are mutually exclusive: exactly one\n * rule is active at a time (one checkmark total, like the design mock). Picking\n * an option in one group clears the other; clearing the active option falls\n * back to the default — an unsorted list is not a state the UI offers.\n */\n\nexport const SORT_BY_RULES = {\n oldestUploads: 'createdAt:ASC',\n mostRecentUpdates: 'updatedAt:DESC',\n} as const;\n\nexport const SORT_DIRECTION_RULES = {\n nameAsc: 'name:ASC',\n nameDesc: 'name:DESC',\n sizeAsc: 'size:ASC',\n sizeDesc: 'size:DESC',\n} as const;\n\nexport type SortByKey = keyof typeof SORT_BY_RULES;\nexport type SortDirectionKey = keyof typeof SORT_DIRECTION_RULES;\nexport type FoldersPosition = 'top' | 'mixed';\n\nconst DEFAULT_SORT_BY: SortByKey = 'mostRecentUpdates';\n\nconst SORT_BY_BY_RULE = Object.fromEntries(\n Object.entries(SORT_BY_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortByKey>;\n\nconst SORT_DIRECTION_BY_RULE = Object.fromEntries(\n Object.entries(SORT_DIRECTION_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortDirectionKey>;\n\ninterface ParsedSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n /** False when the state is the fallback default (no recognized rule in the URL). */\n isExplicit: boolean;\n}\n\n/** Parses `?sort=` — the first recognized rule wins, unknown rules are dropped. */\nconst parseSortParam = (raw: string | undefined): ParsedSort => {\n for (const rule of (raw ?? '').split(',')) {\n if (rule in SORT_BY_BY_RULE) {\n return { sortBy: SORT_BY_BY_RULE[rule], direction: null, isExplicit: true };\n }\n if (rule in SORT_DIRECTION_BY_RULE) {\n return { sortBy: null, direction: SORT_DIRECTION_BY_RULE[rule], isExplicit: true };\n }\n }\n\n return { sortBy: DEFAULT_SORT_BY, direction: null, isExplicit: false };\n};\n\nconst serializeSort = (sortBy: SortByKey | null, direction: SortDirectionKey | null): string => {\n const rules: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && SORT_DIRECTION_RULES[direction],\n ];\n\n return rules.filter((rule): rule is string => Boolean(rule)).join(',');\n};\n\nexport interface ListSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n foldersPosition: FoldersPosition;\n /**\n * The active rule for the files query, e.g. `updatedAt:DESC` — always a\n * single rule since the sort groups are mutually exclusive.\n */\n assetsSort: string;\n /**\n * Rule applicable to the folders query. In the default state (no sort in the\n * URL) folders keep their alphabetical order so the band matches the sidebar\n * tree; an explicit user sort applies, except size rules (folders have no\n * `size` column), which fall back to alphabetical.\n */\n foldersSort: string;\n setSortBy: (key: SortByKey | null) => void;\n setDirection: (key: SortDirectionKey | null) => void;\n setFoldersPosition: (position: FoldersPosition) => void;\n}\n\nexport const useListSort = (): ListSort => {\n const [{ query }, setQuery] = useQueryParams<{\n sort?: string;\n folders?: string;\n _q?: string;\n }>();\n\n const { sortBy, direction, isExplicit } = parseSortParam(query?.sort);\n const foldersPosition: FoldersPosition = query?.folders === 'mixed' ? 'mixed' : 'top';\n\n const writeSort = (nextSortBy: SortByKey | null, nextDirection: SortDirectionKey | null) => {\n // Exactly one active rule: clearing the active one falls back to default.\n if (nextSortBy === null && nextDirection === null) {\n nextSortBy = DEFAULT_SORT_BY;\n }\n\n const serialized = serializeSort(nextSortBy, nextDirection);\n\n if (nextSortBy === DEFAULT_SORT_BY && nextDirection === null) {\n setQuery(withEncodedUserParams(query, { sort: undefined }));\n } else {\n setQuery(withEncodedUserParams(query, { sort: serialized }));\n }\n };\n\n // Groups are mutually exclusive — picking in one clears the other.\n const setSortBy = (key: SortByKey | null) => writeSort(key, null);\n const setDirection = (key: SortDirectionKey | null) => writeSort(null, key);\n\n const setFoldersPosition = (position: FoldersPosition) => {\n if (position === 'mixed') {\n setQuery(withEncodedUserParams(query, { folders: 'mixed' }));\n } else {\n setQuery(withEncodedUserParams(query, { folders: undefined }));\n }\n };\n\n const assetsSort = serializeSort(sortBy, direction);\n const folderRuleCandidates: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && !direction.startsWith('size') ? SORT_DIRECTION_RULES[direction] : null,\n ];\n const folderRules = folderRuleCandidates.filter((rule): rule is string => Boolean(rule));\n // Default state keeps folders alphabetical (matches the sidebar tree) — only\n // an explicit user sort reorders the folders band.\n const foldersSort = isExplicit && folderRules.length > 0 ? folderRules.join(',') : 'name:ASC';\n\n return {\n sortBy,\n direction,\n foldersPosition,\n assetsSort,\n foldersSort,\n setSortBy,\n setDirection,\n setFoldersPosition,\n };\n};\n"],"names":["SORT_BY_RULES","oldestUploads","mostRecentUpdates","SORT_DIRECTION_RULES","nameAsc","nameDesc","sizeAsc","sizeDesc","DEFAULT_SORT_BY","SORT_BY_BY_RULE","Object","fromEntries","entries","map","key","rule","SORT_DIRECTION_BY_RULE","parseSortParam","raw","split","sortBy","direction","isExplicit","serializeSort","rules","filter","Boolean","join","useListSort","query","setQuery","useQueryParams","sort","foldersPosition","folders","writeSort","nextSortBy","nextDirection","serialized","withEncodedUserParams","undefined","setSortBy","setDirection","setFoldersPosition","position","assetsSort","folderRuleCandidates","startsWith","folderRules","foldersSort","length"],"mappings":"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"}
1
+ {"version":3,"file":"useListSort.mjs","sources":["../../../../../admin/src/pages/Assets/hooks/useListSort.ts"],"sourcesContent":["import { withEncodedUserParams } from '@strapi/admin/strapi-admin';\n\nimport { useListQueryParams } from './useListQueryParams';\n\n/**\n * Sort state for the assets list, backed by URL query params so the current\n * ordering is shareable and survives Back/refresh:\n *\n * - `?sort=<rule>` — a single whitelisted rule. Omitted → default (most\n * recent updates).\n * - `?folders=mixed` — folders interleaved with files. Omitted → folders on top.\n *\n * The date rules and the direction rules are mutually exclusive: exactly one\n * rule is active at a time (one checkmark total, like the design mock). Picking\n * an option in one group clears the other; clearing the active option falls\n * back to the default — an unsorted list is not a state the UI offers.\n */\n\nexport const SORT_BY_RULES = {\n oldestUploads: 'createdAt:ASC',\n mostRecentUpdates: 'updatedAt:DESC',\n} as const;\n\nexport const SORT_DIRECTION_RULES = {\n nameAsc: 'name:ASC',\n nameDesc: 'name:DESC',\n sizeAsc: 'size:ASC',\n sizeDesc: 'size:DESC',\n} as const;\n\nexport type SortByKey = keyof typeof SORT_BY_RULES;\nexport type SortDirectionKey = keyof typeof SORT_DIRECTION_RULES;\nexport type FoldersPosition = 'top' | 'mixed';\n\nconst DEFAULT_SORT_BY: SortByKey = 'mostRecentUpdates';\n\nconst SORT_BY_BY_RULE = Object.fromEntries(\n Object.entries(SORT_BY_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortByKey>;\n\nconst SORT_DIRECTION_BY_RULE = Object.fromEntries(\n Object.entries(SORT_DIRECTION_RULES).map(([key, rule]) => [rule, key])\n) as Record<string, SortDirectionKey>;\n\ninterface ParsedSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n /** False when the state is the fallback default (no recognized rule in the URL). */\n isExplicit: boolean;\n}\n\n/** Parses `?sort=` — the first recognized rule wins, unknown rules are dropped. */\nconst parseSortParam = (raw: string | undefined): ParsedSort => {\n for (const rule of (raw ?? '').split(',')) {\n if (rule in SORT_BY_BY_RULE) {\n return { sortBy: SORT_BY_BY_RULE[rule], direction: null, isExplicit: true };\n }\n if (rule in SORT_DIRECTION_BY_RULE) {\n return { sortBy: null, direction: SORT_DIRECTION_BY_RULE[rule], isExplicit: true };\n }\n }\n\n return { sortBy: DEFAULT_SORT_BY, direction: null, isExplicit: false };\n};\n\nconst serializeSort = (sortBy: SortByKey | null, direction: SortDirectionKey | null): string => {\n const rules: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && SORT_DIRECTION_RULES[direction],\n ];\n\n return rules.filter((rule): rule is string => Boolean(rule)).join(',');\n};\n\nexport interface ListSort {\n sortBy: SortByKey | null;\n direction: SortDirectionKey | null;\n foldersPosition: FoldersPosition;\n /**\n * The active rule for the files query, e.g. `updatedAt:DESC` — always a\n * single rule since the sort groups are mutually exclusive.\n */\n assetsSort: string;\n /**\n * Rule applicable to the folders query. In the default state (no sort in the\n * URL) folders keep their alphabetical order so the band matches the sidebar\n * tree; an explicit user sort applies, except size rules (folders have no\n * `size` column), which fall back to alphabetical.\n */\n foldersSort: string;\n setSortBy: (key: SortByKey | null) => void;\n setDirection: (key: SortDirectionKey | null) => void;\n setFoldersPosition: (position: FoldersPosition) => void;\n}\n\nexport const useListSort = (): ListSort => {\n const [{ query }, setQuery] = useListQueryParams<{\n sort?: string;\n folders?: string;\n _q?: string;\n }>();\n\n const { sortBy, direction, isExplicit } = parseSortParam(query?.sort);\n const foldersPosition: FoldersPosition = query?.folders === 'mixed' ? 'mixed' : 'top';\n\n const writeSort = (nextSortBy: SortByKey | null, nextDirection: SortDirectionKey | null) => {\n // Exactly one active rule: clearing the active one falls back to default.\n if (nextSortBy === null && nextDirection === null) {\n nextSortBy = DEFAULT_SORT_BY;\n }\n\n const serialized = serializeSort(nextSortBy, nextDirection);\n\n if (nextSortBy === DEFAULT_SORT_BY && nextDirection === null) {\n setQuery(withEncodedUserParams(query, { sort: undefined }));\n } else {\n setQuery(withEncodedUserParams(query, { sort: serialized }));\n }\n };\n\n // Groups are mutually exclusive — picking in one clears the other.\n const setSortBy = (key: SortByKey | null) => writeSort(key, null);\n const setDirection = (key: SortDirectionKey | null) => writeSort(null, key);\n\n const setFoldersPosition = (position: FoldersPosition) => {\n if (position === 'mixed') {\n setQuery(withEncodedUserParams(query, { folders: 'mixed' }));\n } else {\n setQuery(withEncodedUserParams(query, { folders: undefined }));\n }\n };\n\n const assetsSort = serializeSort(sortBy, direction);\n const folderRuleCandidates: (string | null)[] = [\n sortBy && SORT_BY_RULES[sortBy],\n direction && !direction.startsWith('size') ? SORT_DIRECTION_RULES[direction] : null,\n ];\n const folderRules = folderRuleCandidates.filter((rule): rule is string => Boolean(rule));\n // Default state keeps folders alphabetical (matches the sidebar tree) — only\n // an explicit user sort reorders the folders band.\n const foldersSort = isExplicit && folderRules.length > 0 ? folderRules.join(',') : 'name:ASC';\n\n return {\n sortBy,\n direction,\n foldersPosition,\n assetsSort,\n foldersSort,\n setSortBy,\n setDirection,\n setFoldersPosition,\n };\n};\n"],"names":["SORT_BY_RULES","oldestUploads","mostRecentUpdates","SORT_DIRECTION_RULES","nameAsc","nameDesc","sizeAsc","sizeDesc","DEFAULT_SORT_BY","SORT_BY_BY_RULE","Object","fromEntries","entries","map","key","rule","SORT_DIRECTION_BY_RULE","parseSortParam","raw","split","sortBy","direction","isExplicit","serializeSort","rules","filter","Boolean","join","useListSort","query","setQuery","useListQueryParams","sort","foldersPosition","folders","writeSort","nextSortBy","nextDirection","serialized","withEncodedUserParams","undefined","setSortBy","setDirection","setFoldersPosition","position","assetsSort","folderRuleCandidates","startsWith","folderRules","foldersSort","length"],"mappings":"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"}