@strapi/upload 5.51.2 → 5.52.1

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 (253) hide show
  1. package/dist/admin/future/App.js +3 -3
  2. package/dist/admin/future/App.js.map +1 -1
  3. package/dist/admin/future/App.mjs +4 -4
  4. package/dist/admin/future/App.mjs.map +1 -1
  5. package/dist/admin/future/components/BetaNotice.js +72 -0
  6. package/dist/admin/future/components/BetaNotice.js.map +1 -0
  7. package/dist/admin/future/components/BetaNotice.mjs +70 -0
  8. package/dist/admin/future/components/BetaNotice.mjs.map +1 -0
  9. package/dist/admin/future/components/Drawer.js +16 -3
  10. package/dist/admin/future/components/Drawer.js.map +1 -1
  11. package/dist/admin/future/components/Drawer.mjs +16 -3
  12. package/dist/admin/future/components/Drawer.mjs.map +1 -1
  13. package/dist/admin/future/components/TruncatedText.js +76 -0
  14. package/dist/admin/future/components/TruncatedText.js.map +1 -0
  15. package/dist/admin/future/components/TruncatedText.mjs +74 -0
  16. package/dist/admin/future/components/TruncatedText.mjs.map +1 -0
  17. package/dist/admin/future/hooks/useAIMetadataEnabled.js +39 -0
  18. package/dist/admin/future/hooks/useAIMetadataEnabled.js.map +1 -0
  19. package/dist/admin/future/hooks/useAIMetadataEnabled.mjs +37 -0
  20. package/dist/admin/future/hooks/useAIMetadataEnabled.mjs.map +1 -0
  21. package/dist/admin/future/hooks/useTracking.js +57 -0
  22. package/dist/admin/future/hooks/useTracking.js.map +1 -0
  23. package/dist/admin/future/hooks/useTracking.mjs +53 -0
  24. package/dist/admin/future/hooks/useTracking.mjs.map +1 -0
  25. package/dist/admin/future/pages/Assets/AssetsPage.js +328 -139
  26. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  27. package/dist/admin/future/pages/Assets/AssetsPage.mjs +332 -143
  28. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  29. package/dist/admin/future/pages/Assets/components/ActionsMenuContent.js +46 -0
  30. package/dist/admin/future/pages/Assets/components/ActionsMenuContent.js.map +1 -0
  31. package/dist/admin/future/pages/Assets/components/ActionsMenuContent.mjs +44 -0
  32. package/dist/admin/future/pages/Assets/components/ActionsMenuContent.mjs.map +1 -0
  33. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +328 -0
  34. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -0
  35. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +326 -0
  36. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -0
  37. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +35 -14
  38. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  39. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +35 -14
  40. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  41. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +74 -53
  42. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  43. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +74 -54
  44. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  45. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +92 -28
  46. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
  47. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +94 -30
  48. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  49. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +26 -4
  50. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -1
  51. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +27 -5
  52. package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
  53. package/dist/admin/future/pages/Assets/components/AssetsTable.js +172 -60
  54. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
  55. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +175 -63
  56. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
  57. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +64 -132
  58. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
  59. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +64 -132
  60. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
  61. package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js +123 -76
  62. package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js.map +1 -1
  63. package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs +126 -79
  64. package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs.map +1 -1
  65. package/dist/admin/future/pages/Assets/components/BusyOverlay.js +36 -0
  66. package/dist/admin/future/pages/Assets/components/BusyOverlay.js.map +1 -0
  67. package/dist/admin/future/pages/Assets/components/BusyOverlay.mjs +34 -0
  68. package/dist/admin/future/pages/Assets/components/BusyOverlay.mjs.map +1 -0
  69. package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.js +131 -0
  70. package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.js.map +1 -0
  71. package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.mjs +129 -0
  72. package/dist/admin/future/pages/Assets/components/DeleteItemsDialog.mjs.map +1 -0
  73. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +27 -17
  74. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
  75. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +28 -18
  76. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
  77. package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.js +28 -31
  78. package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.js.map +1 -1
  79. package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.mjs +28 -31
  80. package/dist/admin/future/pages/Assets/components/Dnd/buildDragSet.mjs.map +1 -1
  81. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js +10 -15
  82. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js.map +1 -1
  83. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs +10 -15
  84. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs.map +1 -1
  85. package/dist/admin/future/pages/Assets/components/FilterBadges.js +13 -4
  86. package/dist/admin/future/pages/Assets/components/FilterBadges.js.map +1 -1
  87. package/dist/admin/future/pages/Assets/components/FilterBadges.mjs +13 -4
  88. package/dist/admin/future/pages/Assets/components/FilterBadges.mjs.map +1 -1
  89. package/dist/admin/future/pages/Assets/components/FilterMenu.js +259 -63
  90. package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -1
  91. package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +262 -66
  92. package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -1
  93. package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js +146 -0
  94. package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js.map +1 -0
  95. package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs +144 -0
  96. package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs.map +1 -0
  97. package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.js → FolderFormDialog.js} +62 -16
  98. package/dist/admin/future/pages/Assets/components/FolderFormDialog.js.map +1 -0
  99. package/dist/admin/future/pages/Assets/components/{CreateFolderDialog.mjs → FolderFormDialog.mjs} +64 -18
  100. package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs.map +1 -0
  101. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +132 -229
  102. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  103. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +135 -232
  104. package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  105. package/dist/admin/future/pages/Assets/components/SortMenu.js +14 -0
  106. package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
  107. package/dist/admin/future/pages/Assets/components/SortMenu.mjs +14 -0
  108. package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
  109. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +5 -0
  110. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  111. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +6 -1
  112. package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  113. package/dist/admin/future/pages/Assets/hooks/useBusyAssets.js +47 -0
  114. package/dist/admin/future/pages/Assets/hooks/useBusyAssets.js.map +1 -0
  115. package/dist/admin/future/pages/Assets/hooks/useBusyAssets.mjs +44 -0
  116. package/dist/admin/future/pages/Assets/hooks/useBusyAssets.mjs.map +1 -0
  117. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +203 -62
  118. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
  119. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +204 -63
  120. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
  121. package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.js +75 -0
  122. package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.js.map +1 -0
  123. package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.mjs +73 -0
  124. package/dist/admin/future/pages/Assets/hooks/useInfiniteScrollSentinel.mjs.map +1 -0
  125. package/dist/admin/future/pages/Assets/utils/selection.js +17 -0
  126. package/dist/admin/future/pages/Assets/utils/selection.js.map +1 -1
  127. package/dist/admin/future/pages/Assets/utils/selection.mjs +17 -1
  128. package/dist/admin/future/pages/Assets/utils/selection.mjs.map +1 -1
  129. package/dist/admin/future/services/api.js +31 -8
  130. package/dist/admin/future/services/api.js.map +1 -1
  131. package/dist/admin/future/services/api.mjs +31 -8
  132. package/dist/admin/future/services/api.mjs.map +1 -1
  133. package/dist/admin/future/services/assets.js +22 -23
  134. package/dist/admin/future/services/assets.js.map +1 -1
  135. package/dist/admin/future/services/assets.mjs +22 -23
  136. package/dist/admin/future/services/assets.mjs.map +1 -1
  137. package/dist/admin/future/services/folders.js +37 -2
  138. package/dist/admin/future/services/folders.js.map +1 -1
  139. package/dist/admin/future/services/folders.mjs +37 -3
  140. package/dist/admin/future/services/folders.mjs.map +1 -1
  141. package/dist/admin/future/utils/buildDragSetFromSelection.js +7 -5
  142. package/dist/admin/future/utils/buildDragSetFromSelection.js.map +1 -1
  143. package/dist/admin/future/utils/buildDragSetFromSelection.mjs +7 -5
  144. package/dist/admin/future/utils/buildDragSetFromSelection.mjs.map +1 -1
  145. package/dist/admin/future/utils/formatMoveSuccessMessage.js +12 -1
  146. package/dist/admin/future/utils/formatMoveSuccessMessage.js.map +1 -1
  147. package/dist/admin/future/utils/formatMoveSuccessMessage.mjs +12 -1
  148. package/dist/admin/future/utils/formatMoveSuccessMessage.mjs.map +1 -1
  149. package/dist/admin/future/utils/getRelationId.js +24 -0
  150. package/dist/admin/future/utils/getRelationId.js.map +1 -0
  151. package/dist/admin/future/utils/getRelationId.mjs +22 -0
  152. package/dist/admin/future/utils/getRelationId.mjs.map +1 -0
  153. package/dist/admin/future/utils/isEventFromWithin.js +14 -0
  154. package/dist/admin/future/utils/isEventFromWithin.js.map +1 -0
  155. package/dist/admin/future/utils/isEventFromWithin.mjs +12 -0
  156. package/dist/admin/future/utils/isEventFromWithin.mjs.map +1 -0
  157. package/dist/admin/future/utils/itemLocations.js +40 -0
  158. package/dist/admin/future/utils/itemLocations.js.map +1 -0
  159. package/dist/admin/future/utils/itemLocations.mjs +36 -0
  160. package/dist/admin/future/utils/itemLocations.mjs.map +1 -0
  161. package/dist/admin/future/utils/itemSource.js +36 -0
  162. package/dist/admin/future/utils/itemSource.js.map +1 -0
  163. package/dist/admin/future/utils/itemSource.mjs +32 -0
  164. package/dist/admin/future/utils/itemSource.mjs.map +1 -0
  165. package/dist/admin/hooks/useAIMetadataJob.js +1 -1
  166. package/dist/admin/hooks/useAIMetadataJob.js.map +1 -1
  167. package/dist/admin/hooks/useAIMetadataJob.mjs +1 -1
  168. package/dist/admin/hooks/useAIMetadataJob.mjs.map +1 -1
  169. package/dist/admin/index.js +11 -17
  170. package/dist/admin/index.js.map +1 -1
  171. package/dist/admin/index.mjs +12 -18
  172. package/dist/admin/index.mjs.map +1 -1
  173. package/dist/admin/pages/SettingsPage/SettingsPage.js +2 -2
  174. package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
  175. package/dist/admin/pages/SettingsPage/SettingsPage.mjs +2 -2
  176. package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
  177. package/dist/admin/src/future/App.d.ts +1 -1
  178. package/dist/admin/src/future/components/BetaNotice.d.ts +11 -0
  179. package/dist/admin/src/future/components/Drawer.d.ts +5 -1
  180. package/dist/admin/src/future/components/TruncatedText.d.ts +32 -0
  181. package/dist/admin/src/future/hooks/useAIMetadataEnabled.d.ts +26 -0
  182. package/dist/admin/src/future/hooks/useTracking.d.ts +29 -0
  183. package/dist/admin/src/future/pages/Assets/components/ActionsMenuContent.d.ts +33 -0
  184. package/dist/admin/src/future/pages/Assets/components/AssetActionsMenu.d.ts +26 -0
  185. package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +16 -0
  186. package/dist/admin/src/future/pages/Assets/components/BulkActionsBar.d.ts +8 -1
  187. package/dist/admin/src/future/pages/Assets/components/BulkMoveDialog.d.ts +17 -6
  188. package/dist/admin/src/future/pages/Assets/components/BusyOverlay.d.ts +9 -0
  189. package/dist/admin/src/future/pages/Assets/components/DeleteItemsDialog.d.ts +27 -0
  190. package/dist/admin/src/future/pages/Assets/components/Dnd/AssetsDndProvider.d.ts +8 -1
  191. package/dist/admin/src/future/pages/Assets/components/Dnd/buildDragSet.d.ts +18 -3
  192. package/dist/admin/src/future/pages/Assets/components/Dnd/useAssetDnd.d.ts +2 -1
  193. package/dist/admin/src/future/pages/Assets/components/FilterBadges.d.ts +3 -1
  194. package/dist/admin/src/future/pages/Assets/components/FilterMenu.d.ts +4 -0
  195. package/dist/admin/src/future/pages/Assets/components/FolderActionsMenu.d.ts +21 -0
  196. package/dist/admin/src/future/pages/Assets/components/FolderFormDialog.d.ts +16 -0
  197. package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +2 -0
  198. package/dist/admin/src/future/pages/Assets/hooks/useBusyAssets.d.ts +38 -0
  199. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +20 -6
  200. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteScrollSentinel.d.ts +41 -0
  201. package/dist/admin/src/future/pages/Assets/utils/selection.d.ts +10 -0
  202. package/dist/admin/src/future/services/api.d.ts +6 -7
  203. package/dist/admin/src/future/services/folders.d.ts +6 -1
  204. package/dist/admin/src/future/utils/buildDragSetFromSelection.d.ts +4 -3
  205. package/dist/admin/src/future/utils/formatMoveSuccessMessage.d.ts +7 -1
  206. package/dist/admin/src/future/utils/getRelationId.d.ts +11 -0
  207. package/dist/admin/src/future/utils/isEventFromWithin.d.ts +11 -0
  208. package/dist/admin/src/future/utils/itemLocations.d.ts +31 -0
  209. package/dist/admin/src/future/utils/itemSource.d.ts +22 -0
  210. package/dist/admin/translations/en.json.js +25 -4
  211. package/dist/admin/translations/en.json.js.map +1 -1
  212. package/dist/admin/translations/en.json.mjs +25 -4
  213. package/dist/admin/translations/en.json.mjs.map +1 -1
  214. package/dist/server/controllers/admin-file.js +27 -9
  215. package/dist/server/controllers/admin-file.js.map +1 -1
  216. package/dist/server/controllers/admin-file.mjs +27 -9
  217. package/dist/server/controllers/admin-file.mjs.map +1 -1
  218. package/dist/server/controllers/admin-upload.js +24 -8
  219. package/dist/server/controllers/admin-upload.js.map +1 -1
  220. package/dist/server/controllers/admin-upload.mjs +24 -8
  221. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  222. package/dist/server/routes/admin.js +41 -21
  223. package/dist/server/routes/admin.js.map +1 -1
  224. package/dist/server/routes/admin.mjs +41 -21
  225. package/dist/server/routes/admin.mjs.map +1 -1
  226. package/dist/server/services/ai-metadata.js.map +1 -1
  227. package/dist/server/services/ai-metadata.mjs.map +1 -1
  228. package/dist/server/services/image-manipulation.js.map +1 -1
  229. package/dist/server/services/image-manipulation.mjs.map +1 -1
  230. package/dist/server/src/controllers/admin-file.d.ts +29 -8
  231. package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
  232. package/dist/server/src/controllers/admin-upload.d.ts +20 -4
  233. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  234. package/dist/server/src/controllers/index.d.ts +4 -4
  235. package/dist/server/src/index.d.ts +4 -4
  236. package/dist/server/src/routes/admin.d.ts.map +1 -1
  237. package/dist/server/src/services/ai-metadata.d.ts +2 -2
  238. package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
  239. package/dist/server/src/services/image-manipulation.d.ts +0 -5
  240. package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
  241. package/dist/shared/contracts/ai-metadata-jobs.d.ts +10 -32
  242. package/dist/shared/contracts/ai-metadata-jobs.d.ts.map +1 -1
  243. package/dist/shared/contracts/files.d.ts +10 -10
  244. package/dist/shared/contracts/files.d.ts.map +1 -1
  245. package/package.json +9 -9
  246. package/dist/admin/future/pages/Assets/components/CreateFolderDialog.js.map +0 -1
  247. package/dist/admin/future/pages/Assets/components/CreateFolderDialog.mjs.map +0 -1
  248. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js +0 -33
  249. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.js.map +0 -1
  250. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs +0 -31
  251. package/dist/admin/future/pages/Assets/components/FolderTree/filterFolderTree.mjs.map +0 -1
  252. package/dist/admin/src/future/pages/Assets/components/CreateFolderDialog.d.ts +0 -8
  253. package/dist/admin/src/future/pages/Assets/components/FolderTree/filterFolderTree.d.ts +0 -16
@@ -0,0 +1,74 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useRef, useState } from 'react';
3
+ import { Tooltip, Typography } from '@strapi/design-system';
4
+
5
+ /**
6
+ * Text that ellipsizes, with a tooltip carrying the full value once it actually
7
+ * does. Used for folder and asset names, which are user-supplied and routinely
8
+ * longer than the column, card or rail holding them.
9
+ *
10
+ * The tooltip is conditional rather than always-on: a permanent tooltip would
11
+ * make every short name hoverable for no reason, and would announce a
12
+ * description that merely repeats the visible text.
13
+ *
14
+ * Whether the text is truncated can't be derived from the string — it depends on
15
+ * the rendered width — so it has to be measured. That measurement happens when
16
+ * the pointer or focus arrives, not at mount.
17
+ *
18
+ * Measuring at mount is the obvious approach and it does not work here. The
19
+ * reading is only correct once the row's width constraint has reached this span,
20
+ * and the tree remounts its rows during first render: the instance that survives
21
+ * can take its one measurement while still unconstrained, conclude it fits, and
22
+ * be stuck there. Nothing corrects it afterwards, because a ResizeObserver on
23
+ * this span never fires again — an ancestor clamps the row, so the text
24
+ * overflows inside a box whose own size stops changing.
25
+ *
26
+ * Reading on hover sidesteps all of that. It is the only moment the answer is
27
+ * needed, the layout is settled by then, and nothing is cached across remounts
28
+ * or resizes that could go stale.
29
+ */ const TruncatedText = ({ children, ...props })=>{
30
+ const textRef = useRef(null);
31
+ const [isTruncated, setIsTruncated] = useState(false);
32
+ const checkTruncation = ()=>{
33
+ const el = textRef.current;
34
+ if (el) {
35
+ setIsTruncated(el.scrollWidth > el.clientWidth);
36
+ }
37
+ };
38
+ // A ref callback rather than useRef alone, so the first measurement happens
39
+ // when the node attaches and again whenever it is replaced. The tree remounts
40
+ // its rows during first render, and a value measured against the discarded
41
+ // node would never be revisited — this re-runs against the node that survives.
42
+ const attachRef = (el)=>{
43
+ textRef.current = el;
44
+ if (el) {
45
+ checkTruncation();
46
+ }
47
+ };
48
+ // The Tooltip stays mounted and the *label* is what's conditional, rather than
49
+ // swapping between a wrapped and unwrapped span. Swapping loses the first
50
+ // hover: the measurement that decides to show a tooltip is itself triggered by
51
+ // the pointer arriving, so the trigger would mount underneath a pointer that
52
+ // has already entered, and Radix — which starts watching at mount — sees no
53
+ // enter event and stays closed until the pointer leaves and returns.
54
+ //
55
+ // With `label` empty the DS Tooltip renders its child as-is and attaches
56
+ // nothing, so untruncated text still costs no DOM node and announces no
57
+ // description duplicating what is already on screen.
58
+ return /*#__PURE__*/ jsx(Tooltip, {
59
+ label: isTruncated ? children : undefined,
60
+ children: /*#__PURE__*/ jsx(Typography, {
61
+ ref: attachRef,
62
+ ellipsis: true,
63
+ // Focus is covered as well as hover: the tooltip has to be reachable by
64
+ // keyboard, and these rows are buttons.
65
+ onPointerEnter: checkTruncation,
66
+ onFocus: checkTruncation,
67
+ ...props,
68
+ children: children
69
+ })
70
+ });
71
+ };
72
+
73
+ export { TruncatedText };
74
+ //# sourceMappingURL=TruncatedText.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruncatedText.mjs","sources":["../../../../admin/src/future/components/TruncatedText.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\n\nimport { Tooltip, Typography, type TypographyProps } from '@strapi/design-system';\n\ninterface TruncatedTextProps extends Omit<TypographyProps, 'children' | 'ellipsis'> {\n /** The full text. Doubles as the tooltip content once it no longer fits. */\n children: string;\n}\n\n/**\n * Text that ellipsizes, with a tooltip carrying the full value once it actually\n * does. Used for folder and asset names, which are user-supplied and routinely\n * longer than the column, card or rail holding them.\n *\n * The tooltip is conditional rather than always-on: a permanent tooltip would\n * make every short name hoverable for no reason, and would announce a\n * description that merely repeats the visible text.\n *\n * Whether the text is truncated can't be derived from the string — it depends on\n * the rendered width — so it has to be measured. That measurement happens when\n * the pointer or focus arrives, not at mount.\n *\n * Measuring at mount is the obvious approach and it does not work here. The\n * reading is only correct once the row's width constraint has reached this span,\n * and the tree remounts its rows during first render: the instance that survives\n * can take its one measurement while still unconstrained, conclude it fits, and\n * be stuck there. Nothing corrects it afterwards, because a ResizeObserver on\n * this span never fires again — an ancestor clamps the row, so the text\n * overflows inside a box whose own size stops changing.\n *\n * Reading on hover sidesteps all of that. It is the only moment the answer is\n * needed, the layout is settled by then, and nothing is cached across remounts\n * or resizes that could go stale.\n */\nexport const TruncatedText = ({ children, ...props }: TruncatedTextProps) => {\n const textRef = useRef<HTMLSpanElement | null>(null);\n const [isTruncated, setIsTruncated] = useState(false);\n\n const checkTruncation = () => {\n const el = textRef.current;\n\n if (el) {\n setIsTruncated(el.scrollWidth > el.clientWidth);\n }\n };\n\n // A ref callback rather than useRef alone, so the first measurement happens\n // when the node attaches and again whenever it is replaced. The tree remounts\n // its rows during first render, and a value measured against the discarded\n // node would never be revisited — this re-runs against the node that survives.\n const attachRef = (el: HTMLSpanElement | null) => {\n textRef.current = el;\n\n if (el) {\n checkTruncation();\n }\n };\n\n // The Tooltip stays mounted and the *label* is what's conditional, rather than\n // swapping between a wrapped and unwrapped span. Swapping loses the first\n // hover: the measurement that decides to show a tooltip is itself triggered by\n // the pointer arriving, so the trigger would mount underneath a pointer that\n // has already entered, and Radix — which starts watching at mount — sees no\n // enter event and stays closed until the pointer leaves and returns.\n //\n // With `label` empty the DS Tooltip renders its child as-is and attaches\n // nothing, so untruncated text still costs no DOM node and announces no\n // description duplicating what is already on screen.\n return (\n <Tooltip label={isTruncated ? children : undefined}>\n <Typography\n ref={attachRef}\n ellipsis\n // Focus is covered as well as hover: the tooltip has to be reachable by\n // keyboard, and these rows are buttons.\n onPointerEnter={checkTruncation}\n onFocus={checkTruncation}\n {...props}\n >\n {children}\n </Typography>\n </Tooltip>\n );\n};\n"],"names":["TruncatedText","children","props","textRef","useRef","isTruncated","setIsTruncated","useState","checkTruncation","el","current","scrollWidth","clientWidth","attachRef","_jsx","Tooltip","label","undefined","Typography","ref","ellipsis","onPointerEnter","onFocus"],"mappings":";;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;UAyBaA,aAAAA,GAAgB,CAAC,EAAEC,QAAQ,EAAE,GAAGC,KAAAA,EAA2B,GAAA;AACtE,IAAA,MAAMC,UAAUC,MAAAA,CAA+B,IAAA,CAAA;AAC/C,IAAA,MAAM,CAACC,WAAAA,EAAaC,cAAAA,CAAe,GAAGC,QAAAA,CAAS,KAAA,CAAA;AAE/C,IAAA,MAAMC,eAAAA,GAAkB,IAAA;QACtB,MAAMC,EAAAA,GAAKN,QAAQO,OAAO;AAE1B,QAAA,IAAID,EAAAA,EAAI;AACNH,YAAAA,cAAAA,CAAeG,EAAAA,CAAGE,WAAW,GAAGF,EAAAA,CAAGG,WAAW,CAAA;AAChD,QAAA;AACF,IAAA,CAAA;;;;;AAMA,IAAA,MAAMC,YAAY,CAACJ,EAAAA,GAAAA;AACjBN,QAAAA,OAAAA,CAAQO,OAAO,GAAGD,EAAAA;AAElB,QAAA,IAAIA,EAAAA,EAAI;AACND,YAAAA,eAAAA,EAAAA;AACF,QAAA;AACF,IAAA,CAAA;;;;;;;;;;;AAYA,IAAA,qBACEM,GAAA,CAACC,OAAAA,EAAAA;AAAQC,QAAAA,KAAAA,EAAOX,cAAcJ,QAAAA,GAAWgB,SAAAA;AACvC,QAAA,QAAA,gBAAAH,GAAA,CAACI,UAAAA,EAAAA;YACCC,GAAAA,EAAKN,SAAAA;YACLO,QAAQ,EAAA,IAAA;;;YAGRC,cAAAA,EAAgBb,eAAAA;YAChBc,OAAAA,EAASd,eAAAA;AACR,YAAA,GAAGN,KAAK;AAERD,YAAAA,QAAAA,EAAAA;;;AAIT;;;;"}
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ var ee = require('@strapi/admin/strapi-admin/ee');
4
+ var constants = require('../../shared/constants.js');
5
+ var settings = require('../services/settings.js');
6
+
7
+ /**
8
+ * Whether the replace flow will actually regenerate AI metadata, so the UI only
9
+ * promises it when it happens.
10
+ *
11
+ * Two independent gates, both required — `GET /upload/settings` returns the
12
+ * stored `aiMetadata` toggle on its own, which stays `true` (its default) on
13
+ * licenses without AI, so the setting alone over-promises. The server's own
14
+ * check (`aiMetadata.isEnabled()`) ANDs the same two conditions.
15
+ *
16
+ * Pass `{ mime }` to add the third gate the replace flow applies: it only
17
+ * regenerates metadata for images the AI provider can read
18
+ * (`admin-upload.replaceFile` → `aiMetadata.processFiles`, which filters on this
19
+ * same allowlist). Promising it for a PDF — or for a GIF, which clears the
20
+ * server's looser `image/*` gate but is skipped by the provider — would describe
21
+ * something that never happens.
22
+ *
23
+ * The argument is an object rather than a bare `mime` so the two intents stay
24
+ * distinguishable: `File.mime` is optional on the contract, so a positional
25
+ * parameter let `useAIMetadataEnabled(asset.mime)` collapse into the ungated
26
+ * call whenever the mime was missing — silently taking the permissive path this
27
+ * hook exists to close. `useAIMetadataEnabled({ mime: undefined })` still gates
28
+ * (and fails closed); only an omitted `options` skips the mime check.
29
+ */ const useAIMetadataEnabled = (options)=>{
30
+ const isAIAvailable = ee.useAIAvailability();
31
+ const { data: settings$1 } = settings.useGetUploadSettingsQuery();
32
+ if (!isAIAvailable || !(settings$1?.data?.aiMetadata ?? false)) {
33
+ return false;
34
+ }
35
+ return options === undefined ? true : constants.isAIMetadataSupportedMime(options.mime);
36
+ };
37
+
38
+ exports.useAIMetadataEnabled = useAIMetadataEnabled;
39
+ //# sourceMappingURL=useAIMetadataEnabled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAIMetadataEnabled.js","sources":["../../../../admin/src/future/hooks/useAIMetadataEnabled.ts"],"sourcesContent":["import { useAIAvailability } from '@strapi/admin/strapi-admin/ee';\n\nimport { isAIMetadataSupportedMime } from '../../../../shared/constants';\nimport { useGetUploadSettingsQuery } from '../services/settings';\n\n/**\n * Whether the replace flow will actually regenerate AI metadata, so the UI only\n * promises it when it happens.\n *\n * Two independent gates, both required — `GET /upload/settings` returns the\n * stored `aiMetadata` toggle on its own, which stays `true` (its default) on\n * licenses without AI, so the setting alone over-promises. The server's own\n * check (`aiMetadata.isEnabled()`) ANDs the same two conditions.\n *\n * Pass `{ mime }` to add the third gate the replace flow applies: it only\n * regenerates metadata for images the AI provider can read\n * (`admin-upload.replaceFile` → `aiMetadata.processFiles`, which filters on this\n * same allowlist). Promising it for a PDF — or for a GIF, which clears the\n * server's looser `image/*` gate but is skipped by the provider — would describe\n * something that never happens.\n *\n * The argument is an object rather than a bare `mime` so the two intents stay\n * distinguishable: `File.mime` is optional on the contract, so a positional\n * parameter let `useAIMetadataEnabled(asset.mime)` collapse into the ungated\n * call whenever the mime was missing — silently taking the permissive path this\n * hook exists to close. `useAIMetadataEnabled({ mime: undefined })` still gates\n * (and fails closed); only an omitted `options` skips the mime check.\n */\nexport const useAIMetadataEnabled = (options?: { mime?: string | null }): boolean => {\n const isAIAvailable = useAIAvailability();\n const { data: settings } = useGetUploadSettingsQuery();\n\n if (!isAIAvailable || !(settings?.data?.aiMetadata ?? false)) {\n return false;\n }\n\n return options === undefined ? true : isAIMetadataSupportedMime(options.mime);\n};\n"],"names":["useAIMetadataEnabled","options","isAIAvailable","useAIAvailability","data","settings","useGetUploadSettingsQuery","aiMetadata","undefined","isAIMetadataSupportedMime","mime"],"mappings":";;;;;;AAKA;;;;;;;;;;;;;;;;;;;;;;IAuBO,MAAMA,oBAAAA,GAAuB,CAACC,OAAAA,GAAAA;AACnC,IAAA,MAAMC,aAAAA,GAAgBC,oBAAAA,EAAAA;AACtB,IAAA,MAAM,EAAEC,IAAAA,EAAMC,UAAQ,EAAE,GAAGC,kCAAAA,EAAAA;IAE3B,IAAI,CAACJ,iBAAiB,EAAEG,YAAUD,IAAAA,EAAMG,UAAAA,IAAc,KAAI,CAAA,EAAI;QAC5D,OAAO,KAAA;AACT,IAAA;AAEA,IAAA,OAAON,OAAAA,KAAYO,SAAAA,GAAY,IAAA,GAAOC,mCAAAA,CAA0BR,QAAQS,IAAI,CAAA;AAC9E;;;;"}
@@ -0,0 +1,37 @@
1
+ import { useAIAvailability } from '@strapi/admin/strapi-admin/ee';
2
+ import { isAIMetadataSupportedMime } from '../../shared/constants.mjs';
3
+ import { useGetUploadSettingsQuery } from '../services/settings.mjs';
4
+
5
+ /**
6
+ * Whether the replace flow will actually regenerate AI metadata, so the UI only
7
+ * promises it when it happens.
8
+ *
9
+ * Two independent gates, both required — `GET /upload/settings` returns the
10
+ * stored `aiMetadata` toggle on its own, which stays `true` (its default) on
11
+ * licenses without AI, so the setting alone over-promises. The server's own
12
+ * check (`aiMetadata.isEnabled()`) ANDs the same two conditions.
13
+ *
14
+ * Pass `{ mime }` to add the third gate the replace flow applies: it only
15
+ * regenerates metadata for images the AI provider can read
16
+ * (`admin-upload.replaceFile` → `aiMetadata.processFiles`, which filters on this
17
+ * same allowlist). Promising it for a PDF — or for a GIF, which clears the
18
+ * server's looser `image/*` gate but is skipped by the provider — would describe
19
+ * something that never happens.
20
+ *
21
+ * The argument is an object rather than a bare `mime` so the two intents stay
22
+ * distinguishable: `File.mime` is optional on the contract, so a positional
23
+ * parameter let `useAIMetadataEnabled(asset.mime)` collapse into the ungated
24
+ * call whenever the mime was missing — silently taking the permissive path this
25
+ * hook exists to close. `useAIMetadataEnabled({ mime: undefined })` still gates
26
+ * (and fails closed); only an omitted `options` skips the mime check.
27
+ */ const useAIMetadataEnabled = (options)=>{
28
+ const isAIAvailable = useAIAvailability();
29
+ const { data: settings } = useGetUploadSettingsQuery();
30
+ if (!isAIAvailable || !(settings?.data?.aiMetadata ?? false)) {
31
+ return false;
32
+ }
33
+ return options === undefined ? true : isAIMetadataSupportedMime(options.mime);
34
+ };
35
+
36
+ export { useAIMetadataEnabled };
37
+ //# sourceMappingURL=useAIMetadataEnabled.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAIMetadataEnabled.mjs","sources":["../../../../admin/src/future/hooks/useAIMetadataEnabled.ts"],"sourcesContent":["import { useAIAvailability } from '@strapi/admin/strapi-admin/ee';\n\nimport { isAIMetadataSupportedMime } from '../../../../shared/constants';\nimport { useGetUploadSettingsQuery } from '../services/settings';\n\n/**\n * Whether the replace flow will actually regenerate AI metadata, so the UI only\n * promises it when it happens.\n *\n * Two independent gates, both required — `GET /upload/settings` returns the\n * stored `aiMetadata` toggle on its own, which stays `true` (its default) on\n * licenses without AI, so the setting alone over-promises. The server's own\n * check (`aiMetadata.isEnabled()`) ANDs the same two conditions.\n *\n * Pass `{ mime }` to add the third gate the replace flow applies: it only\n * regenerates metadata for images the AI provider can read\n * (`admin-upload.replaceFile` → `aiMetadata.processFiles`, which filters on this\n * same allowlist). Promising it for a PDF — or for a GIF, which clears the\n * server's looser `image/*` gate but is skipped by the provider — would describe\n * something that never happens.\n *\n * The argument is an object rather than a bare `mime` so the two intents stay\n * distinguishable: `File.mime` is optional on the contract, so a positional\n * parameter let `useAIMetadataEnabled(asset.mime)` collapse into the ungated\n * call whenever the mime was missing — silently taking the permissive path this\n * hook exists to close. `useAIMetadataEnabled({ mime: undefined })` still gates\n * (and fails closed); only an omitted `options` skips the mime check.\n */\nexport const useAIMetadataEnabled = (options?: { mime?: string | null }): boolean => {\n const isAIAvailable = useAIAvailability();\n const { data: settings } = useGetUploadSettingsQuery();\n\n if (!isAIAvailable || !(settings?.data?.aiMetadata ?? false)) {\n return false;\n }\n\n return options === undefined ? true : isAIMetadataSupportedMime(options.mime);\n};\n"],"names":["useAIMetadataEnabled","options","isAIAvailable","useAIAvailability","data","settings","useGetUploadSettingsQuery","aiMetadata","undefined","isAIMetadataSupportedMime","mime"],"mappings":";;;;AAKA;;;;;;;;;;;;;;;;;;;;;;IAuBO,MAAMA,oBAAAA,GAAuB,CAACC,OAAAA,GAAAA;AACnC,IAAA,MAAMC,aAAAA,GAAgBC,iBAAAA,EAAAA;AACtB,IAAA,MAAM,EAAEC,IAAAA,EAAMC,QAAQ,EAAE,GAAGC,yBAAAA,EAAAA;IAE3B,IAAI,CAACJ,iBAAiB,EAAEG,UAAUD,IAAAA,EAAMG,UAAAA,IAAc,KAAI,CAAA,EAAI;QAC5D,OAAO,KAAA;AACT,IAAA;AAEA,IAAA,OAAON,OAAAA,KAAYO,SAAAA,GAAY,IAAA,GAAOC,yBAAAA,CAA0BR,QAAQS,IAAI,CAAA;AAC9E;;;;"}
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var strapiAdmin = require('@strapi/admin/strapi-admin');
5
+ var ee = require('@strapi/admin/strapi-admin/ee');
6
+ var settings = require('../services/settings.js');
7
+
8
+ /**
9
+ * Media Library version tag stamped on every event fired from the new
10
+ * (`src/future`) Media Library. Legacy events omit it, so analytics can filter
11
+ * new usage from the old plan while both trees emit the SAME event names (see
12
+ * CMS-246). Bump this if a future revamp ever needs its own bucket.
13
+ */ const MEDIA_LIBRARY_VERSION = 'v2';
14
+ /**
15
+ * `location` value for every new Media Library event. The new tree is the
16
+ * standalone Media Library page, which the legacy plan tags `'upload'` (as
17
+ * opposed to `'content-manager'` for the asset-picker modal). Kept identical so
18
+ * migrated events line up with the legacy ones on the `location` axis.
19
+ */ const MEDIA_LIBRARY_LOCATION = 'upload';
20
+ /**
21
+ * Tracking wrapper scoped to the new Media Library. Mirrors the legacy
22
+ * `admin/src/hooks/useTracking` — it forwards to the admin `trackUsage` and
23
+ * injects `isAiMediaLibraryConfigured` when AI is available — and additionally
24
+ * stamps `mediaLibraryVersion` on every event so the migrated plan stays
25
+ * distinguishable from the legacy one.
26
+ *
27
+ * The cast mirrors the legacy wrapper: these two properties are cross-cutting
28
+ * media-tracking metadata that the admin `TrackingEvent` type does not (and
29
+ * should not) enumerate per event.
30
+ */ const useTracking = ()=>{
31
+ const { trackUsage: trackStrapiUsage } = strapiAdmin.useTracking();
32
+ const { data } = settings.useGetUploadSettingsQuery();
33
+ const isAiAvailable = ee.useAIAvailability();
34
+ // Memoised so consumers can safely list `trackUsage` in effect deps (the
35
+ // search-input debounce commit does) without re-firing every render.
36
+ const trackUsage = React.useCallback((event, properties)=>{
37
+ return trackStrapiUsage(event, {
38
+ ...properties,
39
+ ...isAiAvailable ? {
40
+ isAiMediaLibraryConfigured: Boolean(data?.data?.aiMetadata)
41
+ } : {},
42
+ mediaLibraryVersion: MEDIA_LIBRARY_VERSION
43
+ });
44
+ }, [
45
+ trackStrapiUsage,
46
+ isAiAvailable,
47
+ data
48
+ ]);
49
+ return {
50
+ trackUsage
51
+ };
52
+ };
53
+
54
+ exports.MEDIA_LIBRARY_LOCATION = MEDIA_LIBRARY_LOCATION;
55
+ exports.MEDIA_LIBRARY_VERSION = MEDIA_LIBRARY_VERSION;
56
+ exports.useTracking = useTracking;
57
+ //# sourceMappingURL=useTracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTracking.js","sources":["../../../../admin/src/future/hooks/useTracking.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { useTracking as useStrapiTracking, type TrackingEvent } from '@strapi/admin/strapi-admin';\nimport { useAIAvailability } from '@strapi/admin/strapi-admin/ee';\n\nimport { useGetUploadSettingsQuery } from '../services/settings';\n\n/**\n * Media Library version tag stamped on every event fired from the new\n * (`src/future`) Media Library. Legacy events omit it, so analytics can filter\n * new usage from the old plan while both trees emit the SAME event names (see\n * CMS-246). Bump this if a future revamp ever needs its own bucket.\n */\nexport const MEDIA_LIBRARY_VERSION = 'v2';\n\n/**\n * `location` value for every new Media Library event. The new tree is the\n * standalone Media Library page, which the legacy plan tags `'upload'` (as\n * opposed to `'content-manager'` for the asset-picker modal). Kept identical so\n * migrated events line up with the legacy ones on the `location` axis.\n */\nexport const MEDIA_LIBRARY_LOCATION = 'upload';\n\n/**\n * Tracking wrapper scoped to the new Media Library. Mirrors the legacy\n * `admin/src/hooks/useTracking` — it forwards to the admin `trackUsage` and\n * injects `isAiMediaLibraryConfigured` when AI is available — and additionally\n * stamps `mediaLibraryVersion` on every event so the migrated plan stays\n * distinguishable from the legacy one.\n *\n * The cast mirrors the legacy wrapper: these two properties are cross-cutting\n * media-tracking metadata that the admin `TrackingEvent` type does not (and\n * should not) enumerate per event.\n */\nexport const useTracking = () => {\n const { trackUsage: trackStrapiUsage } = useStrapiTracking();\n const { data } = useGetUploadSettingsQuery();\n const isAiAvailable = useAIAvailability();\n\n // Memoised so consumers can safely list `trackUsage` in effect deps (the\n // search-input debounce commit does) without re-firing every render.\n const trackUsage = useCallback(\n <TEvent extends TrackingEvent>(event: TEvent['name'], properties?: TEvent['properties']) => {\n return trackStrapiUsage(event, {\n ...properties,\n ...(isAiAvailable ? { isAiMediaLibraryConfigured: Boolean(data?.data?.aiMetadata) } : {}),\n mediaLibraryVersion: MEDIA_LIBRARY_VERSION,\n } as TEvent['properties']);\n },\n [trackStrapiUsage, isAiAvailable, data]\n );\n\n return { trackUsage };\n};\n"],"names":["MEDIA_LIBRARY_VERSION","MEDIA_LIBRARY_LOCATION","useTracking","trackUsage","trackStrapiUsage","useStrapiTracking","data","useGetUploadSettingsQuery","isAiAvailable","useAIAvailability","useCallback","event","properties","isAiMediaLibraryConfigured","Boolean","aiMetadata","mediaLibraryVersion"],"mappings":";;;;;;;AAOA;;;;;IAMO,MAAMA,qBAAAA,GAAwB;AAErC;;;;;IAMO,MAAMC,sBAAAA,GAAyB;AAEtC;;;;;;;;;;UAWaC,WAAAA,GAAc,IAAA;AACzB,IAAA,MAAM,EAAEC,UAAAA,EAAYC,gBAAgB,EAAE,GAAGC,uBAAAA,EAAAA;IACzC,MAAM,EAAEC,IAAI,EAAE,GAAGC,kCAAAA,EAAAA;AACjB,IAAA,MAAMC,aAAAA,GAAgBC,oBAAAA,EAAAA;;;IAItB,MAAMN,UAAAA,GAAaO,iBAAAA,CACjB,CAA+BC,KAAAA,EAAuBC,UAAAA,GAAAA;AACpD,QAAA,OAAOR,iBAAiBO,KAAAA,EAAO;AAC7B,YAAA,GAAGC,UAAU;AACb,YAAA,GAAIJ,aAAAA,GAAgB;gBAAEK,0BAAAA,EAA4BC,OAAAA,CAAQR,MAAMA,IAAAA,EAAMS,UAAAA;AAAY,aAAA,GAAI,EAAE;YACxFC,mBAAAA,EAAqBhB;AACvB,SAAA,CAAA;IACF,CAAA,EACA;AAACI,QAAAA,gBAAAA;AAAkBI,QAAAA,aAAAA;AAAeF,QAAAA;AAAK,KAAA,CAAA;IAGzC,OAAO;AAAEH,QAAAA;AAAW,KAAA;AACtB;;;;;;"}
@@ -0,0 +1,53 @@
1
+ import { useCallback } from 'react';
2
+ import { useTracking as useTracking$1 } from '@strapi/admin/strapi-admin';
3
+ import { useAIAvailability } from '@strapi/admin/strapi-admin/ee';
4
+ import { useGetUploadSettingsQuery } from '../services/settings.mjs';
5
+
6
+ /**
7
+ * Media Library version tag stamped on every event fired from the new
8
+ * (`src/future`) Media Library. Legacy events omit it, so analytics can filter
9
+ * new usage from the old plan while both trees emit the SAME event names (see
10
+ * CMS-246). Bump this if a future revamp ever needs its own bucket.
11
+ */ const MEDIA_LIBRARY_VERSION = 'v2';
12
+ /**
13
+ * `location` value for every new Media Library event. The new tree is the
14
+ * standalone Media Library page, which the legacy plan tags `'upload'` (as
15
+ * opposed to `'content-manager'` for the asset-picker modal). Kept identical so
16
+ * migrated events line up with the legacy ones on the `location` axis.
17
+ */ const MEDIA_LIBRARY_LOCATION = 'upload';
18
+ /**
19
+ * Tracking wrapper scoped to the new Media Library. Mirrors the legacy
20
+ * `admin/src/hooks/useTracking` — it forwards to the admin `trackUsage` and
21
+ * injects `isAiMediaLibraryConfigured` when AI is available — and additionally
22
+ * stamps `mediaLibraryVersion` on every event so the migrated plan stays
23
+ * distinguishable from the legacy one.
24
+ *
25
+ * The cast mirrors the legacy wrapper: these two properties are cross-cutting
26
+ * media-tracking metadata that the admin `TrackingEvent` type does not (and
27
+ * should not) enumerate per event.
28
+ */ const useTracking = ()=>{
29
+ const { trackUsage: trackStrapiUsage } = useTracking$1();
30
+ const { data } = useGetUploadSettingsQuery();
31
+ const isAiAvailable = useAIAvailability();
32
+ // Memoised so consumers can safely list `trackUsage` in effect deps (the
33
+ // search-input debounce commit does) without re-firing every render.
34
+ const trackUsage = useCallback((event, properties)=>{
35
+ return trackStrapiUsage(event, {
36
+ ...properties,
37
+ ...isAiAvailable ? {
38
+ isAiMediaLibraryConfigured: Boolean(data?.data?.aiMetadata)
39
+ } : {},
40
+ mediaLibraryVersion: MEDIA_LIBRARY_VERSION
41
+ });
42
+ }, [
43
+ trackStrapiUsage,
44
+ isAiAvailable,
45
+ data
46
+ ]);
47
+ return {
48
+ trackUsage
49
+ };
50
+ };
51
+
52
+ export { MEDIA_LIBRARY_LOCATION, MEDIA_LIBRARY_VERSION, useTracking };
53
+ //# sourceMappingURL=useTracking.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTracking.mjs","sources":["../../../../admin/src/future/hooks/useTracking.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { useTracking as useStrapiTracking, type TrackingEvent } from '@strapi/admin/strapi-admin';\nimport { useAIAvailability } from '@strapi/admin/strapi-admin/ee';\n\nimport { useGetUploadSettingsQuery } from '../services/settings';\n\n/**\n * Media Library version tag stamped on every event fired from the new\n * (`src/future`) Media Library. Legacy events omit it, so analytics can filter\n * new usage from the old plan while both trees emit the SAME event names (see\n * CMS-246). Bump this if a future revamp ever needs its own bucket.\n */\nexport const MEDIA_LIBRARY_VERSION = 'v2';\n\n/**\n * `location` value for every new Media Library event. The new tree is the\n * standalone Media Library page, which the legacy plan tags `'upload'` (as\n * opposed to `'content-manager'` for the asset-picker modal). Kept identical so\n * migrated events line up with the legacy ones on the `location` axis.\n */\nexport const MEDIA_LIBRARY_LOCATION = 'upload';\n\n/**\n * Tracking wrapper scoped to the new Media Library. Mirrors the legacy\n * `admin/src/hooks/useTracking` — it forwards to the admin `trackUsage` and\n * injects `isAiMediaLibraryConfigured` when AI is available — and additionally\n * stamps `mediaLibraryVersion` on every event so the migrated plan stays\n * distinguishable from the legacy one.\n *\n * The cast mirrors the legacy wrapper: these two properties are cross-cutting\n * media-tracking metadata that the admin `TrackingEvent` type does not (and\n * should not) enumerate per event.\n */\nexport const useTracking = () => {\n const { trackUsage: trackStrapiUsage } = useStrapiTracking();\n const { data } = useGetUploadSettingsQuery();\n const isAiAvailable = useAIAvailability();\n\n // Memoised so consumers can safely list `trackUsage` in effect deps (the\n // search-input debounce commit does) without re-firing every render.\n const trackUsage = useCallback(\n <TEvent extends TrackingEvent>(event: TEvent['name'], properties?: TEvent['properties']) => {\n return trackStrapiUsage(event, {\n ...properties,\n ...(isAiAvailable ? { isAiMediaLibraryConfigured: Boolean(data?.data?.aiMetadata) } : {}),\n mediaLibraryVersion: MEDIA_LIBRARY_VERSION,\n } as TEvent['properties']);\n },\n [trackStrapiUsage, isAiAvailable, data]\n );\n\n return { trackUsage };\n};\n"],"names":["MEDIA_LIBRARY_VERSION","MEDIA_LIBRARY_LOCATION","useTracking","trackUsage","trackStrapiUsage","useStrapiTracking","data","useGetUploadSettingsQuery","isAiAvailable","useAIAvailability","useCallback","event","properties","isAiMediaLibraryConfigured","Boolean","aiMetadata","mediaLibraryVersion"],"mappings":";;;;;AAOA;;;;;IAMO,MAAMA,qBAAAA,GAAwB;AAErC;;;;;IAMO,MAAMC,sBAAAA,GAAyB;AAEtC;;;;;;;;;;UAWaC,WAAAA,GAAc,IAAA;AACzB,IAAA,MAAM,EAAEC,UAAAA,EAAYC,gBAAgB,EAAE,GAAGC,aAAAA,EAAAA;IACzC,MAAM,EAAEC,IAAI,EAAE,GAAGC,yBAAAA,EAAAA;AACjB,IAAA,MAAMC,aAAAA,GAAgBC,iBAAAA,EAAAA;;;IAItB,MAAMN,UAAAA,GAAaO,WAAAA,CACjB,CAA+BC,KAAAA,EAAuBC,UAAAA,GAAAA;AACpD,QAAA,OAAOR,iBAAiBO,KAAAA,EAAO;AAC7B,YAAA,GAAGC,UAAU;AACb,YAAA,GAAIJ,aAAAA,GAAgB;gBAAEK,0BAAAA,EAA4BC,OAAAA,CAAQR,MAAMA,IAAAA,EAAMS,UAAAA;AAAY,aAAA,GAAI,EAAE;YACxFC,mBAAAA,EAAqBhB;AACvB,SAAA,CAAA;IACF,CAAA,EACA;AAACI,QAAAA,gBAAAA;AAAkBI,QAAAA,aAAAA;AAAeF,QAAAA;AAAK,KAAA,CAAA;IAGzC,OAAO;AAAEH,QAAAA;AAAW,KAAA;AACtB;;;;"}