@strapi/upload 5.55.1 → 5.57.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 (304) hide show
  1. package/dist/admin/hooks/useAIMetadataAvailability.js +14 -0
  2. package/dist/admin/hooks/useAIMetadataAvailability.js.map +1 -0
  3. package/dist/admin/hooks/useAIMetadataAvailability.mjs +12 -0
  4. package/dist/admin/hooks/useAIMetadataAvailability.mjs.map +1 -0
  5. package/dist/admin/hooks/useAIMetadataEnabled.js +7 -5
  6. package/dist/admin/hooks/useAIMetadataEnabled.js.map +1 -1
  7. package/dist/admin/hooks/useAIMetadataEnabled.mjs +7 -5
  8. package/dist/admin/hooks/useAIMetadataEnabled.mjs.map +1 -1
  9. package/dist/admin/hooks/useTracking.js +4 -10
  10. package/dist/admin/hooks/useTracking.js.map +1 -1
  11. package/dist/admin/hooks/useTracking.mjs +5 -10
  12. package/dist/admin/hooks/useTracking.mjs.map +1 -1
  13. package/dist/admin/legacy/hooks/useAIMetadataAvailability.js +14 -0
  14. package/dist/admin/legacy/hooks/useAIMetadataAvailability.js.map +1 -0
  15. package/dist/admin/legacy/hooks/useAIMetadataAvailability.mjs +12 -0
  16. package/dist/admin/legacy/hooks/useAIMetadataAvailability.mjs.map +1 -0
  17. package/dist/admin/legacy/hooks/useAIMetadataEnabled.js +23 -0
  18. package/dist/admin/legacy/hooks/useAIMetadataEnabled.js.map +1 -0
  19. package/dist/admin/legacy/hooks/useAIMetadataEnabled.mjs +21 -0
  20. package/dist/admin/legacy/hooks/useAIMetadataEnabled.mjs.map +1 -0
  21. package/dist/admin/legacy/hooks/useTracking.js +5 -3
  22. package/dist/admin/legacy/hooks/useTracking.js.map +1 -1
  23. package/dist/admin/legacy/hooks/useTracking.mjs +5 -3
  24. package/dist/admin/legacy/hooks/useTracking.mjs.map +1 -1
  25. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js +2 -1
  26. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -1
  27. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs +2 -1
  28. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -1
  29. package/dist/admin/legacy/pages/App/MediaLibrary.js +6 -5
  30. package/dist/admin/legacy/pages/App/MediaLibrary.js.map +1 -1
  31. package/dist/admin/legacy/pages/App/MediaLibrary.mjs +6 -5
  32. package/dist/admin/legacy/pages/App/MediaLibrary.mjs.map +1 -1
  33. package/dist/admin/pages/Assets/AssetsPage.js +24 -12
  34. package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
  35. package/dist/admin/pages/Assets/AssetsPage.mjs +25 -13
  36. package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
  37. package/dist/admin/pages/Assets/components/AssetActions.js +326 -0
  38. package/dist/admin/pages/Assets/components/AssetActions.js.map +1 -0
  39. package/dist/admin/pages/Assets/components/AssetActions.mjs +324 -0
  40. package/dist/admin/pages/Assets/components/AssetActions.mjs.map +1 -0
  41. package/dist/admin/pages/Assets/components/AssetActionsMenu.js +28 -309
  42. package/dist/admin/pages/Assets/components/AssetActionsMenu.js.map +1 -1
  43. package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs +31 -312
  44. package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
  45. package/dist/admin/pages/Assets/components/AssetContextMenu.js +79 -0
  46. package/dist/admin/pages/Assets/components/AssetContextMenu.js.map +1 -0
  47. package/dist/admin/pages/Assets/components/AssetContextMenu.mjs +77 -0
  48. package/dist/admin/pages/Assets/components/AssetContextMenu.mjs.map +1 -0
  49. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js +87 -5
  50. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  51. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +89 -7
  52. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  53. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +3 -3
  54. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  55. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +3 -3
  56. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  57. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js +62 -5
  58. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js.map +1 -1
  59. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs +60 -6
  60. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs.map +1 -1
  61. package/dist/admin/pages/Assets/components/AssetsGrid.js +27 -4
  62. package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
  63. package/dist/admin/pages/Assets/components/AssetsGrid.mjs +27 -4
  64. package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  65. package/dist/admin/pages/Assets/components/AssetsTable.js +27 -4
  66. package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
  67. package/dist/admin/pages/Assets/components/AssetsTable.mjs +27 -4
  68. package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
  69. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js +77 -0
  70. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js.map +1 -0
  71. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs +75 -0
  72. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs.map +1 -0
  73. package/dist/admin/pages/Assets/components/DeleteItemsDialog.js +4 -2
  74. package/dist/admin/pages/Assets/components/DeleteItemsDialog.js.map +1 -1
  75. package/dist/admin/pages/Assets/components/DeleteItemsDialog.mjs +4 -2
  76. package/dist/admin/pages/Assets/components/DeleteItemsDialog.mjs.map +1 -1
  77. package/dist/admin/pages/Assets/components/FolderActions.js +139 -0
  78. package/dist/admin/pages/Assets/components/FolderActions.js.map +1 -0
  79. package/dist/admin/pages/Assets/components/FolderActions.mjs +137 -0
  80. package/dist/admin/pages/Assets/components/FolderActions.mjs.map +1 -0
  81. package/dist/admin/pages/Assets/components/FolderActionsMenu.js +25 -119
  82. package/dist/admin/pages/Assets/components/FolderActionsMenu.js.map +1 -1
  83. package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs +27 -121
  84. package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs.map +1 -1
  85. package/dist/admin/pages/Assets/components/FolderContextMenu.js +67 -0
  86. package/dist/admin/pages/Assets/components/FolderContextMenu.js.map +1 -0
  87. package/dist/admin/pages/Assets/components/FolderContextMenu.mjs +65 -0
  88. package/dist/admin/pages/Assets/components/FolderContextMenu.mjs.map +1 -0
  89. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js +139 -45
  90. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  91. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs +140 -47
  92. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  93. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js +115 -0
  94. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js.map +1 -0
  95. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs +113 -0
  96. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs.map +1 -0
  97. package/dist/admin/pages/Assets/components/ItemContextMenu.js +125 -0
  98. package/dist/admin/pages/Assets/components/ItemContextMenu.js.map +1 -0
  99. package/dist/admin/pages/Assets/components/ItemContextMenu.mjs +122 -0
  100. package/dist/admin/pages/Assets/components/ItemContextMenu.mjs.map +1 -0
  101. package/dist/admin/pages/Assets/components/MainAreaContextMenu.js +88 -63
  102. package/dist/admin/pages/Assets/components/MainAreaContextMenu.js.map +1 -1
  103. package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs +88 -63
  104. package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -1
  105. package/dist/admin/pages/Assets/components/SelectionActions.js +111 -0
  106. package/dist/admin/pages/Assets/components/SelectionActions.js.map +1 -0
  107. package/dist/admin/pages/Assets/components/SelectionActions.mjs +109 -0
  108. package/dist/admin/pages/Assets/components/SelectionActions.mjs.map +1 -0
  109. package/dist/admin/pages/Assets/components/SelectionContextMenu.js +82 -0
  110. package/dist/admin/pages/Assets/components/SelectionContextMenu.js.map +1 -0
  111. package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs +80 -0
  112. package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs.map +1 -0
  113. package/dist/admin/pages/Assets/hooks/useAssetSelection.js +10 -0
  114. package/dist/admin/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  115. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs +10 -0
  116. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  117. package/dist/admin/pages/SettingsPage/SettingsPage.js +10 -3
  118. package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
  119. package/dist/admin/pages/SettingsPage/SettingsPage.mjs +10 -3
  120. package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
  121. package/dist/admin/services/api.js.map +1 -1
  122. package/dist/admin/services/api.mjs.map +1 -1
  123. package/dist/admin/src/hooks/useAIMetadataAvailability.d.ts +5 -0
  124. package/dist/admin/src/hooks/useAIMetadataEnabled.d.ts +5 -3
  125. package/dist/admin/src/hooks/useTracking.d.ts +0 -7
  126. package/dist/admin/src/legacy/components/EditAssetDialog/PreviewBox/PreviewComponents.d.ts +2 -2
  127. package/dist/admin/src/legacy/hooks/useAIMetadataAvailability.d.ts +5 -0
  128. package/dist/admin/src/legacy/hooks/useAIMetadataEnabled.d.ts +12 -0
  129. package/dist/admin/src/legacy/hooks/useSettings.d.ts +1 -0
  130. package/dist/admin/src/pages/Assets/components/ActionsMenuContent.d.ts +2 -2
  131. package/dist/admin/src/pages/Assets/components/AssetActions.d.ts +70 -0
  132. package/dist/admin/src/pages/Assets/components/AssetActionsMenu.d.ts +5 -14
  133. package/dist/admin/src/pages/Assets/components/AssetContextMenu.d.ts +27 -0
  134. package/dist/admin/src/pages/Assets/components/AssetDetails/useCropImg.d.ts +16 -0
  135. package/dist/admin/src/pages/Assets/components/CursorAnchoredMenu.d.ts +32 -0
  136. package/dist/admin/src/pages/Assets/components/FolderActions.d.ts +48 -0
  137. package/dist/admin/src/pages/Assets/components/FolderActionsMenu.d.ts +4 -8
  138. package/dist/admin/src/pages/Assets/components/FolderContextMenu.d.ts +21 -0
  139. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTree.d.ts +5 -1
  140. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTreeRowMenu.d.ts +25 -0
  141. package/dist/admin/src/pages/Assets/components/ItemContextMenu.d.ts +53 -0
  142. package/dist/admin/src/pages/Assets/components/MainAreaContextMenu.d.ts +15 -1
  143. package/dist/admin/src/pages/Assets/components/SelectionActions.d.ts +40 -0
  144. package/dist/admin/src/pages/Assets/components/SelectionContextMenu.d.ts +25 -0
  145. package/dist/admin/src/pages/Assets/hooks/useAssetSelection.d.ts +5 -0
  146. package/dist/admin/src/utils/mediaLibraryVersion.d.ts +18 -0
  147. package/dist/admin/translations/en.json.js +9 -3
  148. package/dist/admin/translations/en.json.js.map +1 -1
  149. package/dist/admin/translations/en.json.mjs +9 -3
  150. package/dist/admin/translations/en.json.mjs.map +1 -1
  151. package/dist/admin/utils/mediaLibraryVersion.js +24 -0
  152. package/dist/admin/utils/mediaLibraryVersion.js.map +1 -0
  153. package/dist/admin/utils/mediaLibraryVersion.mjs +20 -0
  154. package/dist/admin/utils/mediaLibraryVersion.mjs.map +1 -0
  155. package/dist/server/bootstrap.js +7 -0
  156. package/dist/server/bootstrap.js.map +1 -1
  157. package/dist/server/bootstrap.mjs +7 -0
  158. package/dist/server/bootstrap.mjs.map +1 -1
  159. package/dist/server/controllers/admin-file.js +2 -2
  160. package/dist/server/controllers/admin-file.js.map +1 -1
  161. package/dist/server/controllers/admin-file.mjs +2 -2
  162. package/dist/server/controllers/admin-file.mjs.map +1 -1
  163. package/dist/server/controllers/admin-folder-file.js +51 -4
  164. package/dist/server/controllers/admin-folder-file.js.map +1 -1
  165. package/dist/server/controllers/admin-folder-file.mjs +52 -5
  166. package/dist/server/controllers/admin-folder-file.mjs.map +1 -1
  167. package/dist/server/controllers/admin-folder.js +5 -5
  168. package/dist/server/controllers/admin-folder.js.map +1 -1
  169. package/dist/server/controllers/admin-folder.mjs +5 -5
  170. package/dist/server/controllers/admin-folder.mjs.map +1 -1
  171. package/dist/server/controllers/admin-settings.js +2 -1
  172. package/dist/server/controllers/admin-settings.js.map +1 -1
  173. package/dist/server/controllers/admin-settings.mjs +2 -1
  174. package/dist/server/controllers/admin-settings.mjs.map +1 -1
  175. package/dist/server/controllers/content-api.js +30 -7
  176. package/dist/server/controllers/content-api.js.map +1 -1
  177. package/dist/server/controllers/content-api.mjs +30 -7
  178. package/dist/server/controllers/content-api.mjs.map +1 -1
  179. package/dist/server/controllers/validation/admin/folder-file.js +4 -4
  180. package/dist/server/controllers/validation/admin/folder-file.js.map +1 -1
  181. package/dist/server/controllers/validation/admin/folder-file.mjs +2 -2
  182. package/dist/server/controllers/validation/admin/folder-file.mjs.map +1 -1
  183. package/dist/server/controllers/validation/admin/folder.js +3 -4
  184. package/dist/server/controllers/validation/admin/folder.js.map +1 -1
  185. package/dist/server/controllers/validation/admin/folder.mjs +3 -4
  186. package/dist/server/controllers/validation/admin/folder.mjs.map +1 -1
  187. package/dist/server/controllers/validation/admin/upload.js +1 -2
  188. package/dist/server/controllers/validation/admin/upload.js.map +1 -1
  189. package/dist/server/controllers/validation/admin/upload.mjs +1 -2
  190. package/dist/server/controllers/validation/admin/upload.mjs.map +1 -1
  191. package/dist/server/controllers/validation/admin/utils.js +1 -2
  192. package/dist/server/controllers/validation/admin/utils.js.map +1 -1
  193. package/dist/server/controllers/validation/admin/utils.mjs +1 -2
  194. package/dist/server/controllers/validation/admin/utils.mjs.map +1 -1
  195. package/dist/server/errors.js +12 -0
  196. package/dist/server/errors.js.map +1 -0
  197. package/dist/server/errors.mjs +10 -0
  198. package/dist/server/errors.mjs.map +1 -0
  199. package/dist/server/migrations/unsign-richtext-and-blocks-urls.js +2 -2
  200. package/dist/server/migrations/unsign-richtext-and-blocks-urls.js.map +1 -1
  201. package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs +1 -1
  202. package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs.map +1 -1
  203. package/dist/server/routes/content-api.js +3 -3
  204. package/dist/server/routes/content-api.js.map +1 -1
  205. package/dist/server/routes/content-api.mjs +3 -3
  206. package/dist/server/routes/content-api.mjs.map +1 -1
  207. package/dist/server/routes/validation/upload.js +8 -0
  208. package/dist/server/routes/validation/upload.js.map +1 -1
  209. package/dist/server/routes/validation/upload.mjs +8 -0
  210. package/dist/server/routes/validation/upload.mjs.map +1 -1
  211. package/dist/server/services/ai-metadata-provider.js +83 -0
  212. package/dist/server/services/ai-metadata-provider.js.map +1 -0
  213. package/dist/server/services/ai-metadata-provider.mjs +61 -0
  214. package/dist/server/services/ai-metadata-provider.mjs.map +1 -0
  215. package/dist/server/services/ai-metadata-strapi-managed.js +48 -0
  216. package/dist/server/services/ai-metadata-strapi-managed.js.map +1 -0
  217. package/dist/server/services/ai-metadata-strapi-managed.mjs +46 -0
  218. package/dist/server/services/ai-metadata-strapi-managed.mjs.map +1 -0
  219. package/dist/server/services/ai-metadata.js +5 -58
  220. package/dist/server/services/ai-metadata.js.map +1 -1
  221. package/dist/server/services/ai-metadata.mjs +6 -39
  222. package/dist/server/services/ai-metadata.mjs.map +1 -1
  223. package/dist/server/services/api-upload-folder.js +3 -3
  224. package/dist/server/services/api-upload-folder.js.map +1 -1
  225. package/dist/server/services/api-upload-folder.mjs +3 -3
  226. package/dist/server/services/api-upload-folder.mjs.map +1 -1
  227. package/dist/server/services/extensions/utils.js +19 -15
  228. package/dist/server/services/extensions/utils.js.map +1 -1
  229. package/dist/server/services/extensions/utils.mjs +19 -15
  230. package/dist/server/services/extensions/utils.mjs.map +1 -1
  231. package/dist/server/services/file.js +2 -2
  232. package/dist/server/services/file.js.map +1 -1
  233. package/dist/server/services/file.mjs +1 -1
  234. package/dist/server/services/file.mjs.map +1 -1
  235. package/dist/server/services/folder.js +9 -6
  236. package/dist/server/services/folder.js.map +1 -1
  237. package/dist/server/services/folder.mjs +9 -6
  238. package/dist/server/services/folder.mjs.map +1 -1
  239. package/dist/server/services/index.js +3 -1
  240. package/dist/server/services/index.js.map +1 -1
  241. package/dist/server/services/index.mjs +3 -1
  242. package/dist/server/services/index.mjs.map +1 -1
  243. package/dist/server/services/metrics.js +1 -1
  244. package/dist/server/services/metrics.js.map +1 -1
  245. package/dist/server/services/metrics.mjs +1 -1
  246. package/dist/server/services/metrics.mjs.map +1 -1
  247. package/dist/server/services/provider.js +3 -4
  248. package/dist/server/services/provider.js.map +1 -1
  249. package/dist/server/services/provider.mjs +3 -4
  250. package/dist/server/services/provider.mjs.map +1 -1
  251. package/dist/server/services/upload.js +5 -6
  252. package/dist/server/services/upload.js.map +1 -1
  253. package/dist/server/services/upload.mjs +4 -5
  254. package/dist/server/services/upload.mjs.map +1 -1
  255. package/dist/server/services/weekly-metrics.js +2 -2
  256. package/dist/server/services/weekly-metrics.js.map +1 -1
  257. package/dist/server/services/weekly-metrics.mjs +2 -2
  258. package/dist/server/services/weekly-metrics.mjs.map +1 -1
  259. package/dist/server/src/bootstrap.d.ts.map +1 -1
  260. package/dist/server/src/controllers/admin-folder-file.d.ts.map +1 -1
  261. package/dist/server/src/controllers/admin-folder.d.ts.map +1 -1
  262. package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
  263. package/dist/server/src/controllers/content-api.d.ts.map +1 -1
  264. package/dist/server/src/controllers/validation/admin/folder.d.ts.map +1 -1
  265. package/dist/server/src/controllers/validation/admin/upload.d.ts.map +1 -1
  266. package/dist/server/src/controllers/validation/admin/utils.d.ts.map +1 -1
  267. package/dist/server/src/errors.d.ts +6 -0
  268. package/dist/server/src/errors.d.ts.map +1 -0
  269. package/dist/server/src/index.d.ts +6 -1
  270. package/dist/server/src/index.d.ts.map +1 -1
  271. package/dist/server/src/mcp/ambient-instance.d.ts +3 -1
  272. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
  273. package/dist/server/src/routes/validation/upload.d.ts +4 -0
  274. package/dist/server/src/routes/validation/upload.d.ts.map +1 -1
  275. package/dist/server/src/services/ai-metadata-provider.d.ts +26 -0
  276. package/dist/server/src/services/ai-metadata-provider.d.ts.map +1 -0
  277. package/dist/server/src/services/ai-metadata-strapi-managed.d.ts +7 -0
  278. package/dist/server/src/services/ai-metadata-strapi-managed.d.ts.map +1 -0
  279. package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
  280. package/dist/server/src/services/extensions/utils.d.ts +33 -1
  281. package/dist/server/src/services/extensions/utils.d.ts.map +1 -1
  282. package/dist/server/src/services/folder.d.ts +5 -2
  283. package/dist/server/src/services/folder.d.ts.map +1 -1
  284. package/dist/server/src/services/index.d.ts +6 -1
  285. package/dist/server/src/services/index.d.ts.map +1 -1
  286. package/dist/server/src/services/provider.d.ts.map +1 -1
  287. package/dist/server/src/services/upload.d.ts.map +1 -1
  288. package/dist/server/src/utils/images.d.ts +2 -2
  289. package/dist/server/src/utils/images.d.ts.map +1 -1
  290. package/dist/server/src/utils/index.d.ts +2 -0
  291. package/dist/server/src/utils/index.d.ts.map +1 -1
  292. package/dist/server/utils/images.js +6 -7
  293. package/dist/server/utils/images.js.map +1 -1
  294. package/dist/server/utils/images.mjs +6 -7
  295. package/dist/server/utils/images.mjs.map +1 -1
  296. package/dist/server/utils/index.js.map +1 -1
  297. package/dist/server/utils/index.mjs.map +1 -1
  298. package/dist/shared/contracts/settings.d.ts +6 -0
  299. package/package.json +11 -11
  300. package/dist/admin/legacy/hooks/useAiAvailability.js +0 -22
  301. package/dist/admin/legacy/hooks/useAiAvailability.js.map +0 -1
  302. package/dist/admin/legacy/hooks/useAiAvailability.mjs +0 -20
  303. package/dist/admin/legacy/hooks/useAiAvailability.mjs.map +0 -1
  304. package/dist/admin/src/legacy/hooks/useAiAvailability.d.ts +0 -4
@@ -1,331 +1,50 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useRef, useState, useMemo } from 'react';
3
- import { useClipboard, useNotification } from '@strapi/admin/strapi-admin';
4
- import { VisuallyHidden, Menu, IconButton, Dialog, Flex, Typography, Button } from '@strapi/design-system';
5
- import { More, ArrowsCounterClockwise, Link, Download, ArrowRight, Trash } from '@strapi/icons';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { Menu, IconButton } from '@strapi/design-system';
3
+ import { More } from '@strapi/icons';
6
4
  import { useIntl } from 'react-intl';
7
- import { useAIMetadataEnabled } from '../../../hooks/useAIMetadataEnabled.mjs';
8
- import { useApiErrorMessage } from '../../../hooks/useApiErrorMessage.mjs';
9
- import { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions.mjs';
10
- import { useReplaceAssetMutation } from '../../../services/assets.mjs';
11
- import { downloadFile } from '../../../utils/downloadFile.mjs';
12
- import { prefixFileUrlWithBackendUrl } from '../../../utils/files.mjs';
13
5
  import { getTranslationKey } from '../../../utils/translations.mjs';
14
- import { useAssetSelection } from '../hooks/useAssetSelection.mjs';
15
- import { useBusyAssetsOptional } from '../hooks/useBusyAssets.mjs';
16
- import { assetKey } from '../utils/selection.mjs';
17
6
  import { ActionsMenuContent } from './ActionsMenuContent.mjs';
18
- import { BulkMoveDialog } from './BulkMoveDialog.mjs';
19
- import { DeleteItemsDialog } from './DeleteItemsDialog.mjs';
7
+ import { AssetActions } from './AssetActions.mjs';
20
8
 
21
9
  /**
22
10
  * The "..." menu on an asset row/card. Always acts on that one asset, whatever
23
- * the current multi-selection is (the bulk actions bar is the selection-scoped
24
- * affordance) — the file mirror of `FolderActionsMenu`.
11
+ * the current multi-selection is (the bulk actions bar and the right-click menu
12
+ * are the selection-scoped affordances) — the file mirror of `FolderActionsMenu`.
25
13
  *
26
- * Replace / copy link / download duplicate what the details drawer offers as
27
- * icon buttons, so the same action is one click away without opening the asset
28
- * first. They are re-implemented rather than lifted out of the drawer: the
29
- * drawer versions render as `IconButton`s and report through its in-drawer toast
30
- * slot, neither of which fits a menu item on a row.
31
- *
32
- * A successful move or delete deselects this one asset and leaves the rest of
33
- * the selection intact: the mutations only invalidate RTK tags, so without it an
34
- * `asset:<id>` key for a file that has been deleted — or has moved out of this
35
- * list — would linger. The other selected rows are untouched, which is the whole
36
- * point of the menu being a single-item affordance.
14
+ * The actions themselves live in `AssetActions`, shared with
15
+ * `AssetContextMenu`. This component is only the trigger.
37
16
  */ const AssetActionsMenu = ({ asset, dragData })=>{
38
17
  const { formatMessage } = useIntl();
39
- const getErrorMessage = useApiErrorMessage();
40
- const { copy } = useClipboard();
41
- const { toggleNotification } = useNotification();
42
- const { deselect } = useAssetSelection();
43
- // Absent in the asset picker and in unit tests: the replace still runs, it
44
- // just renders no row-level overlay.
45
- const markBusy = useBusyAssetsOptional()?.markBusy ?? (()=>()=>{});
46
- const { canUpdate, canDownload, canCopyLink, isLoading: isLoadingPermissions } = useMediaLibraryPermissions();
47
- const [replaceAsset, { isLoading: isReplacing }] = useReplaceAssetMutation();
48
- const aiEnabled = useAIMetadataEnabled({
49
- mime: asset.mime
50
- });
51
- const fileInputRef = useRef(null);
52
- const [isReplaceOpen, setIsReplaceOpen] = useState(false);
53
- const [isMoveOpen, setIsMoveOpen] = useState(false);
54
- const [isDeleteOpen, setIsDeleteOpen] = useState(false);
55
- const [isDownloading, setIsDownloading] = useState(false);
56
- // Stable identity: the move dialog memoizes its destination walk on it.
57
- const moveItems = useMemo(()=>[
58
- dragData
59
- ], [
60
- dragData
61
- ]);
62
- // Confirm first, then open the native picker, so the user only commits to
63
- // replacing after acknowledging the warning (same order as the drawer).
64
- const handleReplaceContinue = ()=>{
65
- setIsReplaceOpen(false);
66
- fileInputRef.current?.click();
67
- };
68
- const handleFileChange = async (event)=>{
69
- const file = event.target.files?.[0];
70
- // Reset the native input so the same file can be picked again later.
71
- event.target.value = '';
72
- if (!file) {
73
- return;
74
- }
75
- // The menu has closed by the time the picker returns, so `isReplacing` has
76
- // nothing left to disable and the row would otherwise sit inert for the
77
- // whole upload. Marking the asset busy puts the same overlay the drawer
78
- // uses on the row/card, cleared when the mutation settles either way.
79
- const releaseBusy = markBusy(asset.id, formatMessage({
80
- id: getTranslationKey('asset-details.replace.loading'),
81
- defaultMessage: 'Replacing the file…'
82
- }));
83
- let res;
84
- try {
85
- res = await replaceAsset({
86
- id: asset.id,
87
- file,
88
- fileInfo: {
89
- name: asset.name
90
- }
91
- });
92
- } finally{
93
- releaseBusy();
94
- }
95
- if ('error' in res) {
96
- toggleNotification({
97
- type: 'danger',
98
- message: getErrorMessage(res.error, formatMessage({
99
- id: getTranslationKey('asset-details.replace.error'),
100
- defaultMessage: 'Failed to replace the file.'
101
- }))
102
- });
103
- return;
104
- }
105
- toggleNotification({
106
- type: 'success',
107
- message: formatMessage({
108
- id: getTranslationKey('asset-details.replace.success'),
109
- defaultMessage: 'File replaced.'
110
- })
111
- });
112
- };
113
- const handleCopyLink = async ()=>{
114
- const url = prefixFileUrlWithBackendUrl(asset.url);
115
- if (!url) {
116
- return;
117
- }
118
- const didCopy = await copy(url);
119
- toggleNotification({
120
- type: didCopy ? 'success' : 'danger',
121
- message: formatMessage(didCopy ? {
122
- id: getTranslationKey('asset-details.copy-link.success'),
123
- defaultMessage: 'Link copied.'
124
- } : {
125
- id: getTranslationKey('asset-details.copy-link.error'),
126
- defaultMessage: 'Failed to copy the link.'
127
- })
128
- });
129
- };
130
- const handleDownload = async ()=>{
131
- const url = prefixFileUrlWithBackendUrl(asset.url);
132
- if (!url) {
133
- return;
134
- }
135
- setIsDownloading(true);
136
- try {
137
- await downloadFile(url, asset.name);
138
- } catch {
139
- toggleNotification({
140
- type: 'danger',
141
- message: formatMessage({
142
- id: getTranslationKey('asset-details.download.error'),
143
- defaultMessage: 'Failed to download the file.'
144
- })
145
- });
146
- } finally{
147
- setIsDownloading(false);
148
- }
149
- };
150
- // Two permission-gated groups: replace/copy-link/download above, move/delete
151
- // below. The separator earns its place only when both survive the gate —
152
- // `canUpdate` alone puts Replace in the top group, which is not enough.
153
- const hasTopGroup = canUpdate || canCopyLink || canDownload;
154
- const hasBottomGroup = canUpdate;
155
- const showSeparator = (canCopyLink || canDownload) && hasBottomGroup;
156
- // A role can read the library while holding none of these, and an empty
157
- // popup is worse than no trigger at all. Every flag is `false` until the
158
- // RBAC check settles, so wait for it — otherwise the trigger unmounts and
159
- // remounts on first paint for everyone.
160
- if (!isLoadingPermissions && !hasTopGroup && !hasBottomGroup) {
161
- return null;
162
- }
163
- return /*#__PURE__*/ jsxs(Fragment, {
164
- children: [
165
- /*#__PURE__*/ jsx(VisuallyHidden, {
166
- children: /*#__PURE__*/ jsx("input", {
167
- ref: fileInputRef,
168
- type: "file",
169
- // Replacing swaps the bytes of an existing asset, so the picker offers
170
- // only its own type. Without this the picker accepted anything and a
171
- // JPG could come back as PNG bytes still served under a `.jpg` url,
172
- // since replace preserves hash and ext by design.
173
- accept: asset.mime ?? '',
174
- multiple: false,
175
- onChange: handleFileChange,
176
- "aria-hidden": true,
177
- tabIndex: -1
178
- })
179
- }),
180
- /*#__PURE__*/ jsxs(Menu.Root, {
181
- modal: false,
18
+ return /*#__PURE__*/ jsx(AssetActions, {
19
+ asset: asset,
20
+ dragData: dragData,
21
+ children: ({ items, dialogs, hasActions })=>// A role can read the library while holding none of these, and an empty
22
+ // popup is worse than no trigger at all.
23
+ hasActions ? /*#__PURE__*/ jsxs(Fragment, {
182
24
  children: [
183
- /*#__PURE__*/ jsx(Menu.Trigger, {
184
- tag: IconButton,
185
- icon: /*#__PURE__*/ jsx(More, {}),
186
- variant: "ghost",
187
- label: formatMessage({
188
- id: getTranslationKey('control-card.more-actions'),
189
- defaultMessage: 'More actions'
190
- })
191
- }),
192
- /*#__PURE__*/ jsxs(ActionsMenuContent, {
193
- popoverPlacement: "bottom-end",
194
- zIndex: 2,
195
- minWidth: "22rem",
25
+ /*#__PURE__*/ jsxs(Menu.Root, {
26
+ modal: false,
196
27
  children: [
197
- canUpdate && /*#__PURE__*/ jsx(Menu.Item, {
198
- startIcon: /*#__PURE__*/ jsx(ArrowsCounterClockwise, {}),
199
- disabled: isReplacing,
200
- onSelect: ()=>setIsReplaceOpen(true),
201
- children: formatMessage({
202
- id: getTranslationKey('list.assets.actions.replace'),
203
- defaultMessage: 'Replace media'
28
+ /*#__PURE__*/ jsx(Menu.Trigger, {
29
+ tag: IconButton,
30
+ icon: /*#__PURE__*/ jsx(More, {}),
31
+ variant: "ghost",
32
+ label: formatMessage({
33
+ id: getTranslationKey('control-card.more-actions'),
34
+ defaultMessage: 'More actions'
204
35
  })
205
36
  }),
206
- canCopyLink && /*#__PURE__*/ jsx(Menu.Item, {
207
- startIcon: /*#__PURE__*/ jsx(Link, {}),
208
- onSelect: handleCopyLink,
209
- children: formatMessage({
210
- id: getTranslationKey('list.assets.actions.copy-link'),
211
- defaultMessage: 'Copy link to media'
212
- })
213
- }),
214
- canDownload && /*#__PURE__*/ jsx(Menu.Item, {
215
- startIcon: /*#__PURE__*/ jsx(Download, {}),
216
- disabled: isDownloading,
217
- onSelect: handleDownload,
218
- children: formatMessage({
219
- id: getTranslationKey('list.assets.actions.download'),
220
- defaultMessage: 'Download media'
221
- })
222
- }),
223
- showSeparator && /*#__PURE__*/ jsx(Menu.Separator, {}),
224
- canUpdate && /*#__PURE__*/ jsxs(Fragment, {
225
- children: [
226
- /*#__PURE__*/ jsx(Menu.Item, {
227
- startIcon: /*#__PURE__*/ jsx(ArrowRight, {}),
228
- onSelect: ()=>setIsMoveOpen(true),
229
- children: formatMessage({
230
- id: getTranslationKey('list.assets.actions.move'),
231
- defaultMessage: 'Move to folder'
232
- })
233
- }),
234
- /*#__PURE__*/ jsx(Menu.Item, {
235
- startIcon: /*#__PURE__*/ jsx(Trash, {}),
236
- variant: "danger",
237
- onSelect: ()=>setIsDeleteOpen(true),
238
- children: formatMessage({
239
- id: getTranslationKey('list.assets.actions.delete'),
240
- defaultMessage: 'Delete'
241
- })
242
- })
243
- ]
37
+ /*#__PURE__*/ jsx(ActionsMenuContent, {
38
+ popoverPlacement: "bottom-end",
39
+ zIndex: 2,
40
+ minWidth: "22rem",
41
+ children: items
244
42
  })
245
43
  ]
246
- })
44
+ }),
45
+ dialogs
247
46
  ]
248
- }),
249
- /*#__PURE__*/ jsx(Dialog.Root, {
250
- open: isReplaceOpen,
251
- onOpenChange: setIsReplaceOpen,
252
- children: /*#__PURE__*/ jsxs(Dialog.Content, {
253
- children: [
254
- /*#__PURE__*/ jsx(Dialog.Header, {
255
- children: formatMessage({
256
- id: getTranslationKey('asset-details.replace.title'),
257
- defaultMessage: 'Replace this media file?'
258
- })
259
- }),
260
- /*#__PURE__*/ jsx(Dialog.Body, {
261
- textAlign: "center",
262
- children: /*#__PURE__*/ jsxs(Flex, {
263
- direction: "column",
264
- textAlign: "center",
265
- children: [
266
- /*#__PURE__*/ jsx(Typography, {
267
- variant: "omega",
268
- children: formatMessage({
269
- id: getTranslationKey('asset-details.replace.description'),
270
- defaultMessage: 'Current content will be permanently replaced.'
271
- })
272
- }),
273
- aiEnabled ? /*#__PURE__*/ jsx(Typography, {
274
- variant: "omega",
275
- children: formatMessage({
276
- id: getTranslationKey('asset-details.replace.description.ai'),
277
- defaultMessage: 'AI will generate new metadata after upload.'
278
- })
279
- }) : null
280
- ]
281
- })
282
- }),
283
- /*#__PURE__*/ jsxs(Dialog.Footer, {
284
- children: [
285
- /*#__PURE__*/ jsx(Dialog.Cancel, {
286
- children: /*#__PURE__*/ jsx(Button, {
287
- variant: "tertiary",
288
- fullWidth: true,
289
- children: formatMessage({
290
- id: 'app.components.Button.cancel',
291
- defaultMessage: 'Cancel'
292
- })
293
- })
294
- }),
295
- /*#__PURE__*/ jsx(Dialog.Action, {
296
- children: /*#__PURE__*/ jsx(Button, {
297
- variant: "secondary",
298
- onClick: handleReplaceContinue,
299
- fullWidth: true,
300
- children: formatMessage({
301
- id: getTranslationKey('asset-details.replace.continue'),
302
- defaultMessage: 'Continue'
303
- })
304
- })
305
- })
306
- ]
307
- })
308
- ]
309
- })
310
- }),
311
- isMoveOpen && /*#__PURE__*/ jsx(BulkMoveDialog, {
312
- open: true,
313
- onClose: ()=>setIsMoveOpen(false),
314
- items: moveItems,
315
- onSuccess: ()=>deselect(assetKey(asset.id))
316
- }),
317
- isDeleteOpen && /*#__PURE__*/ jsx(DeleteItemsDialog, {
318
- open: true,
319
- onClose: ()=>setIsDeleteOpen(false),
320
- target: {
321
- fileIds: [
322
- asset.id
323
- ],
324
- folderIds: []
325
- },
326
- onSuccess: ()=>deselect(assetKey(asset.id))
327
- })
328
- ]
47
+ }) : null
329
48
  });
330
49
  };
331
50
 
@@ -1 +1 @@
1
- {"version":3,"file":"AssetActionsMenu.mjs","sources":["../../../../../admin/src/pages/Assets/components/AssetActionsMenu.tsx"],"sourcesContent":["import { useMemo, useRef, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport {\n Button,\n Dialog,\n Flex,\n IconButton,\n Menu,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { ArrowRight, ArrowsCounterClockwise, Download, Link, More, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useAIMetadataEnabled } from '../../../hooks/useAIMetadataEnabled';\nimport { useApiErrorMessage } from '../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport { useReplaceAssetMutation } from '../../../services/assets';\nimport { downloadFile } from '../../../utils/downloadFile';\nimport { prefixFileUrlWithBackendUrl } from '../../../utils/files';\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { useBusyAssetsOptional } from '../hooks/useBusyAssets';\nimport { assetKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\n\nimport type { File } from '../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetActionsMenuProps {\n asset: File;\n /** Drag data for this asset, so the move dialog validates against its real folder. */\n dragData: DragFileData;\n}\n\n/**\n * The \"...\" menu on an asset row/card. Always acts on that one asset, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance) — the file mirror of `FolderActionsMenu`.\n *\n * Replace / copy link / download duplicate what the details drawer offers as\n * icon buttons, so the same action is one click away without opening the asset\n * first. They are re-implemented rather than lifted out of the drawer: the\n * drawer versions render as `IconButton`s and report through its in-drawer toast\n * slot, neither of which fits a menu item on a row.\n *\n * A successful move or delete deselects this one asset and leaves the rest of\n * the selection intact: the mutations only invalidate RTK tags, so without it an\n * `asset:<id>` key for a file that has been deleted — or has moved out of this\n * list — would linger. The other selected rows are untouched, which is the whole\n * point of the menu being a single-item affordance.\n */\nexport const AssetActionsMenu = ({ asset, dragData }: AssetActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n // Absent in the asset picker and in unit tests: the replace still runs, it\n // just renders no row-level overlay.\n const markBusy = useBusyAssetsOptional()?.markBusy ?? (() => () => {});\n const {\n canUpdate,\n canDownload,\n canCopyLink,\n isLoading: isLoadingPermissions,\n } = useMediaLibraryPermissions();\n const [replaceAsset, { isLoading: isReplacing }] = useReplaceAssetMutation();\n const aiEnabled = useAIMetadataEnabled({ mime: asset.mime });\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isReplaceOpen, setIsReplaceOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Confirm first, then open the native picker, so the user only commits to\n // replacing after acknowledging the warning (same order as the drawer).\n const handleReplaceContinue = () => {\n setIsReplaceOpen(false);\n fileInputRef.current?.click();\n };\n\n const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n // Reset the native input so the same file can be picked again later.\n event.target.value = '';\n\n if (!file) {\n return;\n }\n\n // The menu has closed by the time the picker returns, so `isReplacing` has\n // nothing left to disable and the row would otherwise sit inert for the\n // whole upload. Marking the asset busy puts the same overlay the drawer\n // uses on the row/card, cleared when the mutation settles either way.\n const releaseBusy = markBusy(\n asset.id,\n formatMessage({\n id: getTranslationKey('asset-details.replace.loading'),\n defaultMessage: 'Replacing the file…',\n })\n );\n\n let res;\n try {\n res = await replaceAsset({ id: asset.id, file, fileInfo: { name: asset.name } });\n } finally {\n releaseBusy();\n }\n\n if ('error' in res) {\n toggleNotification({\n type: 'danger',\n message: getErrorMessage(\n res.error,\n formatMessage({\n id: getTranslationKey('asset-details.replace.error'),\n defaultMessage: 'Failed to replace the file.',\n })\n ),\n });\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslationKey('asset-details.replace.success'),\n defaultMessage: 'File replaced.',\n }),\n });\n };\n\n const handleCopyLink = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('asset-details.copy-link.success'),\n defaultMessage: 'Link copied.',\n }\n : {\n id: getTranslationKey('asset-details.copy-link.error'),\n defaultMessage: 'Failed to copy the link.',\n }\n ),\n });\n };\n\n const handleDownload = async () => {\n const url = prefixFileUrlWithBackendUrl(asset.url);\n\n if (!url) {\n return;\n }\n\n setIsDownloading(true);\n\n try {\n await downloadFile(url, asset.name);\n } catch {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: getTranslationKey('asset-details.download.error'),\n defaultMessage: 'Failed to download the file.',\n }),\n });\n } finally {\n setIsDownloading(false);\n }\n };\n\n // Two permission-gated groups: replace/copy-link/download above, move/delete\n // below. The separator earns its place only when both survive the gate —\n // `canUpdate` alone puts Replace in the top group, which is not enough.\n const hasTopGroup = canUpdate || canCopyLink || canDownload;\n const hasBottomGroup = canUpdate;\n const showSeparator = (canCopyLink || canDownload) && hasBottomGroup;\n\n // A role can read the library while holding none of these, and an empty\n // popup is worse than no trigger at all. Every flag is `false` until the\n // RBAC check settles, so wait for it — otherwise the trigger unmounts and\n // remounts on first paint for everyone.\n if (!isLoadingPermissions && !hasTopGroup && !hasBottomGroup) {\n return null;\n }\n\n return (\n <>\n <VisuallyHidden>\n <input\n ref={fileInputRef}\n type=\"file\"\n // Replacing swaps the bytes of an existing asset, so the picker offers\n // only its own type. Without this the picker accepted anything and a\n // JPG could come back as PNG bytes still served under a `.jpg` url,\n // since replace preserves hash and ext by design.\n accept={asset.mime ?? ''}\n multiple={false}\n onChange={handleFileChange}\n aria-hidden\n tabIndex={-1}\n />\n </VisuallyHidden>\n {/* Non-modal: Radix's default `modal` marks the rest of the document\n `aria-hidden` and blocks pointer events while the menu is open, so\n clicking a sibling row's trigger only dismissed this one — leaving\n every menu you touched to be closed one click at a time. Non-modal\n dismissal treats that click as both \"close this\" and \"open that\". */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* `ActionsMenuContent` replaces the design system's flat 15rem clamp\n with the height Radix actually measured, and un-hides the scrollbar\n it would otherwise overflow into. See that file for why. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canUpdate && (\n <Menu.Item\n startIcon={<ArrowsCounterClockwise />}\n disabled={isReplacing}\n onSelect={() => setIsReplaceOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.replace'),\n defaultMessage: 'Replace media',\n })}\n </Menu.Item>\n )}\n {canCopyLink && (\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.copy-link'),\n defaultMessage: 'Copy link to media',\n })}\n </Menu.Item>\n )}\n {canDownload && (\n <Menu.Item startIcon={<Download />} disabled={isDownloading} onSelect={handleDownload}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.download'),\n defaultMessage: 'Download media',\n })}\n </Menu.Item>\n )}\n {showSeparator && <Menu.Separator />}\n {canUpdate && (\n <>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.assets.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item\n startIcon={<Trash />}\n variant=\"danger\"\n onSelect={() => setIsDeleteOpen(true)}\n >\n {formatMessage({\n id: getTranslationKey('list.assets.actions.delete'),\n defaultMessage: 'Delete',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n <Dialog.Root open={isReplaceOpen} onOpenChange={setIsReplaceOpen}>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.title'),\n defaultMessage: 'Replace this media file?',\n })}\n </Dialog.Header>\n <Dialog.Body textAlign=\"center\">\n <Flex direction=\"column\" textAlign=\"center\">\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description'),\n defaultMessage: 'Current content will be permanently replaced.',\n })}\n </Typography>\n {aiEnabled ? (\n <Typography variant=\"omega\">\n {formatMessage({\n id: getTranslationKey('asset-details.replace.description.ai'),\n defaultMessage: 'AI will generate new metadata after upload.',\n })}\n </Typography>\n ) : null}\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\" fullWidth>\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"secondary\" onClick={handleReplaceContinue} fullWidth>\n {formatMessage({\n id: getTranslationKey('asset-details.replace.continue'),\n defaultMessage: 'Continue',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n {/* Both dialogs live inside the row, so a background refetch that drops the\n row would take an open dialog with it. Nothing invalidates until the\n mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [asset.id], folderIds: [] }}\n onSuccess={() => deselect(assetKey(asset.id))}\n />\n )}\n </>\n );\n};\n"],"names":["AssetActionsMenu","asset","dragData","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","markBusy","useBusyAssetsOptional","canUpdate","canDownload","canCopyLink","isLoading","isLoadingPermissions","useMediaLibraryPermissions","replaceAsset","isReplacing","useReplaceAssetMutation","aiEnabled","useAIMetadataEnabled","mime","fileInputRef","useRef","isReplaceOpen","setIsReplaceOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","isDownloading","setIsDownloading","moveItems","useMemo","handleReplaceContinue","current","click","handleFileChange","event","file","target","files","value","releaseBusy","id","getTranslationKey","defaultMessage","res","fileInfo","name","type","message","error","handleCopyLink","url","prefixFileUrlWithBackendUrl","didCopy","handleDownload","downloadFile","hasTopGroup","hasBottomGroup","showSeparator","_jsxs","_Fragment","_jsx","VisuallyHidden","input","ref","accept","multiple","onChange","aria-hidden","tabIndex","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","ArrowsCounterClockwise","disabled","onSelect","Link","Download","Separator","ArrowRight","Trash","Dialog","open","onOpenChange","Content","Header","Body","textAlign","Flex","direction","Typography","Footer","Cancel","Button","fullWidth","Action","onClick","BulkMoveDialog","onClose","items","onSuccess","assetKey","DeleteItemsDialog","fileIds","folderIds"],"mappings":"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"}
1
+ {"version":3,"file":"AssetActionsMenu.mjs","sources":["../../../../../admin/src/pages/Assets/components/AssetActionsMenu.tsx"],"sourcesContent":["import { IconButton, Menu } from '@strapi/design-system';\nimport { More } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { AssetActions } from './AssetActions';\n\nimport type { File } from '../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetActionsMenuProps {\n asset: File;\n /** Drag data for this asset, so the move dialog validates against its real folder. */\n dragData: DragFileData;\n}\n\n/**\n * The \"...\" menu on an asset row/card. Always acts on that one asset, whatever\n * the current multi-selection is (the bulk actions bar and the right-click menu\n * are the selection-scoped affordances) — the file mirror of `FolderActionsMenu`.\n *\n * The actions themselves live in `AssetActions`, shared with\n * `AssetContextMenu`. This component is only the trigger.\n */\nexport const AssetActionsMenu = ({ asset, dragData }: AssetActionsMenuProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <AssetActions asset={asset} dragData={dragData}>\n {({ items, dialogs, hasActions }) =>\n // A role can read the library while holding none of these, and an empty\n // popup is worse than no trigger at all.\n hasActions ? (\n <>\n {/* Non-modal: Radix's default `modal` marks the rest of the document\n `aria-hidden` and blocks pointer events while the menu is open, so\n clicking a sibling row's trigger only dismissed this one — leaving\n every menu you touched to be closed one click at a time. Non-modal\n dismissal treats that click as both \"close this\" and \"open that\". */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* `ActionsMenuContent` replaces the design system's flat 15rem clamp\n with the height Radix actually measured, and un-hides the scrollbar\n it would otherwise overflow into. See that file for why. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {items}\n </ActionsMenuContent>\n </Menu.Root>\n {dialogs}\n </>\n ) : null\n }\n </AssetActions>\n );\n};\n"],"names":["AssetActionsMenu","asset","dragData","formatMessage","useIntl","_jsx","AssetActions","items","dialogs","hasActions","_jsxs","_Fragment","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","label","id","getTranslationKey","defaultMessage","ActionsMenuContent","popoverPlacement","zIndex","minWidth"],"mappings":";;;;;;;;AAkBA;;;;;;;UAQaA,gBAAAA,GAAmB,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAAyB,GAAA;IACzE,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,qBACEC,GAAA,CAACC,YAAAA,EAAAA;QAAaL,KAAAA,EAAOA,KAAAA;QAAOC,QAAAA,EAAUA,QAAAA;kBACnC,CAAC,EAAEK,KAAK,EAAEC,OAAO,EAAEC,UAAU,EAAE;;YAG9BA,UAAAA,iBACEC,IAAA,CAAAC,QAAA,EAAA;;AAME,kCAAAD,IAAA,CAACE,KAAKC,IAAI,EAAA;wBAACC,KAAAA,EAAO,KAAA;;AAChB,0CAAAT,GAAA,CAACO,KAAKG,OAAO,EAAA;gCACXC,GAAAA,EAAKC,UAAAA;AACLC,gCAAAA,IAAAA,gBAAMb,GAAA,CAACc,IAAAA,EAAAA,EAAAA,CAAAA;gCACPC,OAAAA,EAAQ,OAAA;AACRC,gCAAAA,KAAAA,EAAOlB,aAAAA,CAAc;AACnBmB,oCAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,2BAAA,CAAA;oCACtBC,cAAAA,EAAgB;AAClB,iCAAA;;0CAKFnB,GAAA,CAACoB,kBAAAA,EAAAA;gCAAmBC,gBAAAA,EAAiB,YAAA;gCAAaC,MAAAA,EAAQ,CAAA;gCAAGC,QAAAA,EAAS,OAAA;AACnErB,gCAAAA,QAAAA,EAAAA;;;;AAGJC,oBAAAA;;AAED,aAAA,CAAA,GAAA;;AAIZ;;;;"}
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var reactIntl = require('react-intl');
6
+ var translations = require('../../../utils/translations.js');
7
+ var AssetActions = require('./AssetActions.js');
8
+ var CursorAnchoredMenu = require('./CursorAnchoredMenu.js');
9
+
10
+ /**
11
+ * The right-click twin of `AssetActionsMenu`: same actions, opened at the
12
+ * cursor instead of from the row's `•••`. Both render what `AssetActions`
13
+ * gives them, so the two can't offer different things.
14
+ *
15
+ * Picking "Replace", "Move" or "Delete" closes the menu and opens a dialog in
16
+ * the same tick, and that dialog is rendered here — so the menu being shut and
17
+ * this being unmounted are two different things, tracked apart. Unmounting
18
+ * early would take the dialog with it, and for "Replace" the hidden file input
19
+ * too, which is why `isBusy` also covers the native picker.
20
+ */ const AssetContextMenu = ({ asset, dragData, permissions, position, returnFocusTo, onClose })=>{
21
+ const { formatMessage } = reactIntl.useIntl();
22
+ const [isMenuOpen, setIsMenuOpen] = React.useState(true);
23
+ return /*#__PURE__*/ jsxRuntime.jsx(AssetActions.AssetActions, {
24
+ asset: asset,
25
+ dragData: dragData,
26
+ permissions: permissions,
27
+ children: ({ items, dialogs, hasActions, isBusy })=>/*#__PURE__*/ jsxRuntime.jsx(AssetContextMenuBody, {
28
+ hasActions: hasActions,
29
+ isBusy: isBusy,
30
+ isMenuOpen: isMenuOpen,
31
+ onMenuClose: ()=>setIsMenuOpen(false),
32
+ onClose: onClose,
33
+ position: position,
34
+ returnFocusTo: returnFocusTo,
35
+ label: formatMessage({
36
+ id: translations.getTranslationKey('list.assets.context-menu.label'),
37
+ defaultMessage: 'Asset actions'
38
+ }),
39
+ items: items,
40
+ dialogs: dialogs
41
+ })
42
+ });
43
+ };
44
+ /**
45
+ * Split out because the "nothing left on screen" effect can't run inside the
46
+ * render prop above — hooks don't belong in a callback.
47
+ */ const AssetContextMenuBody = ({ hasActions, isBusy, isMenuOpen, onMenuClose, onClose, position, returnFocusTo, label, items, dialogs })=>{
48
+ React.useEffect(()=>{
49
+ // The menu is shut and nothing took its place — no dialog, no file picker
50
+ // — or the role has no permitted action, so there was never a menu at all.
51
+ if (!hasActions || !isMenuOpen && !isBusy) {
52
+ onClose();
53
+ }
54
+ }, [
55
+ hasActions,
56
+ isMenuOpen,
57
+ isBusy,
58
+ onClose
59
+ ]);
60
+ if (!hasActions) {
61
+ return null;
62
+ }
63
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
64
+ children: [
65
+ /*#__PURE__*/ jsxRuntime.jsx(CursorAnchoredMenu.CursorAnchoredMenu, {
66
+ position: position,
67
+ open: isMenuOpen,
68
+ label: label,
69
+ returnFocusTo: returnFocusTo,
70
+ onClose: onMenuClose,
71
+ children: items
72
+ }),
73
+ dialogs
74
+ ]
75
+ });
76
+ };
77
+
78
+ exports.AssetContextMenu = AssetContextMenu;
79
+ //# sourceMappingURL=AssetContextMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetContextMenu.js","sources":["../../../../../admin/src/pages/Assets/components/AssetContextMenu.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\n\nimport { AssetActions, type AssetActionPermissions } from './AssetActions';\nimport { CursorAnchoredMenu, type CursorPosition } from './CursorAnchoredMenu';\n\nimport type { File } from '../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetContextMenuProps {\n asset: File;\n dragData: DragFileData;\n /** Resolved by the provider, so this menu never renders while RBAC loads. */\n permissions: AssetActionPermissions;\n position: CursorPosition;\n returnFocusTo: HTMLElement | null;\n /** Mounted only while it has something on screen, so the parent drops it on this. */\n onClose: () => void;\n}\n\n/**\n * The right-click twin of `AssetActionsMenu`: same actions, opened at the\n * cursor instead of from the row's `•••`. Both render what `AssetActions`\n * gives them, so the two can't offer different things.\n *\n * Picking \"Replace\", \"Move\" or \"Delete\" closes the menu and opens a dialog in\n * the same tick, and that dialog is rendered here — so the menu being shut and\n * this being unmounted are two different things, tracked apart. Unmounting\n * early would take the dialog with it, and for \"Replace\" the hidden file input\n * too, which is why `isBusy` also covers the native picker.\n */\nexport const AssetContextMenu = ({\n asset,\n dragData,\n permissions,\n position,\n returnFocusTo,\n onClose,\n}: AssetContextMenuProps) => {\n const { formatMessage } = useIntl();\n const [isMenuOpen, setIsMenuOpen] = useState(true);\n\n return (\n <AssetActions asset={asset} dragData={dragData} permissions={permissions}>\n {({ items, dialogs, hasActions, isBusy }) => (\n <AssetContextMenuBody\n hasActions={hasActions}\n isBusy={isBusy}\n isMenuOpen={isMenuOpen}\n onMenuClose={() => setIsMenuOpen(false)}\n onClose={onClose}\n position={position}\n returnFocusTo={returnFocusTo}\n label={formatMessage({\n id: getTranslationKey('list.assets.context-menu.label'),\n defaultMessage: 'Asset actions',\n })}\n items={items}\n dialogs={dialogs}\n />\n )}\n </AssetActions>\n );\n};\n\ninterface AssetContextMenuBodyProps {\n hasActions: boolean;\n isBusy: boolean;\n isMenuOpen: boolean;\n onMenuClose: () => void;\n onClose: () => void;\n position: CursorPosition;\n returnFocusTo: HTMLElement | null;\n label: string;\n items: React.ReactNode;\n dialogs: React.ReactNode;\n}\n\n/**\n * Split out because the \"nothing left on screen\" effect can't run inside the\n * render prop above — hooks don't belong in a callback.\n */\nconst AssetContextMenuBody = ({\n hasActions,\n isBusy,\n isMenuOpen,\n onMenuClose,\n onClose,\n position,\n returnFocusTo,\n label,\n items,\n dialogs,\n}: AssetContextMenuBodyProps) => {\n useEffect(() => {\n // The menu is shut and nothing took its place — no dialog, no file picker\n // — or the role has no permitted action, so there was never a menu at all.\n if (!hasActions || (!isMenuOpen && !isBusy)) {\n onClose();\n }\n }, [hasActions, isMenuOpen, isBusy, onClose]);\n\n if (!hasActions) {\n return null;\n }\n\n return (\n <>\n <CursorAnchoredMenu\n position={position}\n open={isMenuOpen}\n label={label}\n returnFocusTo={returnFocusTo}\n onClose={onMenuClose}\n >\n {items}\n </CursorAnchoredMenu>\n {dialogs}\n </>\n );\n};\n"],"names":["AssetContextMenu","asset","dragData","permissions","position","returnFocusTo","onClose","formatMessage","useIntl","isMenuOpen","setIsMenuOpen","useState","_jsx","AssetActions","items","dialogs","hasActions","isBusy","AssetContextMenuBody","onMenuClose","label","id","getTranslationKey","defaultMessage","useEffect","_jsxs","_Fragment","CursorAnchoredMenu","open"],"mappings":";;;;;;;;;AAuBA;;;;;;;;;;AAUC,IACM,MAAMA,gBAAAA,GAAmB,CAAC,EAC/BC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXC,QAAQ,EACRC,aAAa,EACbC,OAAO,EACe,GAAA;IACtB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAM,CAACC,UAAAA,EAAYC,aAAAA,CAAc,GAAGC,cAAAA,CAAS,IAAA,CAAA;AAE7C,IAAA,qBACEC,cAAA,CAACC,yBAAAA,EAAAA;QAAaZ,KAAAA,EAAOA,KAAAA;QAAOC,QAAAA,EAAUA,QAAAA;QAAUC,WAAAA,EAAaA,WAAAA;kBAC1D,CAAC,EAAEW,KAAK,EAAEC,OAAO,EAAEC,UAAU,EAAEC,MAAM,EAAE,iBACtCL,cAAA,CAACM,oBAAAA,EAAAA;gBACCF,UAAAA,EAAYA,UAAAA;gBACZC,MAAAA,EAAQA,MAAAA;gBACRR,UAAAA,EAAYA,UAAAA;AACZU,gBAAAA,WAAAA,EAAa,IAAMT,aAAAA,CAAc,KAAA,CAAA;gBACjCJ,OAAAA,EAASA,OAAAA;gBACTF,QAAAA,EAAUA,QAAAA;gBACVC,aAAAA,EAAeA,aAAAA;AACfe,gBAAAA,KAAAA,EAAOb,aAAAA,CAAc;AACnBc,oBAAAA,EAAAA,EAAIC,8BAAAA,CAAkB,gCAAA,CAAA;oBACtBC,cAAAA,EAAgB;AAClB,iBAAA,CAAA;gBACAT,KAAAA,EAAOA,KAAAA;gBACPC,OAAAA,EAASA;;;AAKnB;AAeA;;;IAIA,MAAMG,uBAAuB,CAAC,EAC5BF,UAAU,EACVC,MAAM,EACNR,UAAU,EACVU,WAAW,EACXb,OAAO,EACPF,QAAQ,EACRC,aAAa,EACbe,KAAK,EACLN,KAAK,EACLC,OAAO,EACmB,GAAA;IAC1BS,eAAAA,CAAU,IAAA;;;AAGR,QAAA,IAAI,CAACR,UAAAA,IAAe,CAACP,UAAAA,IAAc,CAACQ,MAAAA,EAAS;AAC3CX,YAAAA,OAAAA,EAAAA;AACF,QAAA;IACF,CAAA,EAAG;AAACU,QAAAA,UAAAA;AAAYP,QAAAA,UAAAA;AAAYQ,QAAAA,MAAAA;AAAQX,QAAAA;AAAQ,KAAA,CAAA;AAE5C,IAAA,IAAI,CAACU,UAAAA,EAAY;QACf,OAAO,IAAA;AACT,IAAA;IAEA,qBACES,eAAA,CAAAC,mBAAA,EAAA;;0BACEd,cAAA,CAACe,qCAAAA,EAAAA;gBACCvB,QAAAA,EAAUA,QAAAA;gBACVwB,IAAAA,EAAMnB,UAAAA;gBACNW,KAAAA,EAAOA,KAAAA;gBACPf,aAAAA,EAAeA,aAAAA;gBACfC,OAAAA,EAASa,WAAAA;AAERL,gBAAAA,QAAAA,EAAAA;;AAEFC,YAAAA;;;AAGP,CAAA;;;;"}
@@ -0,0 +1,77 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useIntl } from 'react-intl';
4
+ import { getTranslationKey } from '../../../utils/translations.mjs';
5
+ import { AssetActions } from './AssetActions.mjs';
6
+ import { CursorAnchoredMenu } from './CursorAnchoredMenu.mjs';
7
+
8
+ /**
9
+ * The right-click twin of `AssetActionsMenu`: same actions, opened at the
10
+ * cursor instead of from the row's `•••`. Both render what `AssetActions`
11
+ * gives them, so the two can't offer different things.
12
+ *
13
+ * Picking "Replace", "Move" or "Delete" closes the menu and opens a dialog in
14
+ * the same tick, and that dialog is rendered here — so the menu being shut and
15
+ * this being unmounted are two different things, tracked apart. Unmounting
16
+ * early would take the dialog with it, and for "Replace" the hidden file input
17
+ * too, which is why `isBusy` also covers the native picker.
18
+ */ const AssetContextMenu = ({ asset, dragData, permissions, position, returnFocusTo, onClose })=>{
19
+ const { formatMessage } = useIntl();
20
+ const [isMenuOpen, setIsMenuOpen] = useState(true);
21
+ return /*#__PURE__*/ jsx(AssetActions, {
22
+ asset: asset,
23
+ dragData: dragData,
24
+ permissions: permissions,
25
+ children: ({ items, dialogs, hasActions, isBusy })=>/*#__PURE__*/ jsx(AssetContextMenuBody, {
26
+ hasActions: hasActions,
27
+ isBusy: isBusy,
28
+ isMenuOpen: isMenuOpen,
29
+ onMenuClose: ()=>setIsMenuOpen(false),
30
+ onClose: onClose,
31
+ position: position,
32
+ returnFocusTo: returnFocusTo,
33
+ label: formatMessage({
34
+ id: getTranslationKey('list.assets.context-menu.label'),
35
+ defaultMessage: 'Asset actions'
36
+ }),
37
+ items: items,
38
+ dialogs: dialogs
39
+ })
40
+ });
41
+ };
42
+ /**
43
+ * Split out because the "nothing left on screen" effect can't run inside the
44
+ * render prop above — hooks don't belong in a callback.
45
+ */ const AssetContextMenuBody = ({ hasActions, isBusy, isMenuOpen, onMenuClose, onClose, position, returnFocusTo, label, items, dialogs })=>{
46
+ useEffect(()=>{
47
+ // The menu is shut and nothing took its place — no dialog, no file picker
48
+ // — or the role has no permitted action, so there was never a menu at all.
49
+ if (!hasActions || !isMenuOpen && !isBusy) {
50
+ onClose();
51
+ }
52
+ }, [
53
+ hasActions,
54
+ isMenuOpen,
55
+ isBusy,
56
+ onClose
57
+ ]);
58
+ if (!hasActions) {
59
+ return null;
60
+ }
61
+ return /*#__PURE__*/ jsxs(Fragment, {
62
+ children: [
63
+ /*#__PURE__*/ jsx(CursorAnchoredMenu, {
64
+ position: position,
65
+ open: isMenuOpen,
66
+ label: label,
67
+ returnFocusTo: returnFocusTo,
68
+ onClose: onMenuClose,
69
+ children: items
70
+ }),
71
+ dialogs
72
+ ]
73
+ });
74
+ };
75
+
76
+ export { AssetContextMenu };
77
+ //# sourceMappingURL=AssetContextMenu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetContextMenu.mjs","sources":["../../../../../admin/src/pages/Assets/components/AssetContextMenu.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\n\nimport { AssetActions, type AssetActionPermissions } from './AssetActions';\nimport { CursorAnchoredMenu, type CursorPosition } from './CursorAnchoredMenu';\n\nimport type { File } from '../../../../../shared/contracts/files';\nimport type { DragFileData } from '../../../types/dnd';\n\ninterface AssetContextMenuProps {\n asset: File;\n dragData: DragFileData;\n /** Resolved by the provider, so this menu never renders while RBAC loads. */\n permissions: AssetActionPermissions;\n position: CursorPosition;\n returnFocusTo: HTMLElement | null;\n /** Mounted only while it has something on screen, so the parent drops it on this. */\n onClose: () => void;\n}\n\n/**\n * The right-click twin of `AssetActionsMenu`: same actions, opened at the\n * cursor instead of from the row's `•••`. Both render what `AssetActions`\n * gives them, so the two can't offer different things.\n *\n * Picking \"Replace\", \"Move\" or \"Delete\" closes the menu and opens a dialog in\n * the same tick, and that dialog is rendered here — so the menu being shut and\n * this being unmounted are two different things, tracked apart. Unmounting\n * early would take the dialog with it, and for \"Replace\" the hidden file input\n * too, which is why `isBusy` also covers the native picker.\n */\nexport const AssetContextMenu = ({\n asset,\n dragData,\n permissions,\n position,\n returnFocusTo,\n onClose,\n}: AssetContextMenuProps) => {\n const { formatMessage } = useIntl();\n const [isMenuOpen, setIsMenuOpen] = useState(true);\n\n return (\n <AssetActions asset={asset} dragData={dragData} permissions={permissions}>\n {({ items, dialogs, hasActions, isBusy }) => (\n <AssetContextMenuBody\n hasActions={hasActions}\n isBusy={isBusy}\n isMenuOpen={isMenuOpen}\n onMenuClose={() => setIsMenuOpen(false)}\n onClose={onClose}\n position={position}\n returnFocusTo={returnFocusTo}\n label={formatMessage({\n id: getTranslationKey('list.assets.context-menu.label'),\n defaultMessage: 'Asset actions',\n })}\n items={items}\n dialogs={dialogs}\n />\n )}\n </AssetActions>\n );\n};\n\ninterface AssetContextMenuBodyProps {\n hasActions: boolean;\n isBusy: boolean;\n isMenuOpen: boolean;\n onMenuClose: () => void;\n onClose: () => void;\n position: CursorPosition;\n returnFocusTo: HTMLElement | null;\n label: string;\n items: React.ReactNode;\n dialogs: React.ReactNode;\n}\n\n/**\n * Split out because the \"nothing left on screen\" effect can't run inside the\n * render prop above — hooks don't belong in a callback.\n */\nconst AssetContextMenuBody = ({\n hasActions,\n isBusy,\n isMenuOpen,\n onMenuClose,\n onClose,\n position,\n returnFocusTo,\n label,\n items,\n dialogs,\n}: AssetContextMenuBodyProps) => {\n useEffect(() => {\n // The menu is shut and nothing took its place — no dialog, no file picker\n // — or the role has no permitted action, so there was never a menu at all.\n if (!hasActions || (!isMenuOpen && !isBusy)) {\n onClose();\n }\n }, [hasActions, isMenuOpen, isBusy, onClose]);\n\n if (!hasActions) {\n return null;\n }\n\n return (\n <>\n <CursorAnchoredMenu\n position={position}\n open={isMenuOpen}\n label={label}\n returnFocusTo={returnFocusTo}\n onClose={onMenuClose}\n >\n {items}\n </CursorAnchoredMenu>\n {dialogs}\n </>\n );\n};\n"],"names":["AssetContextMenu","asset","dragData","permissions","position","returnFocusTo","onClose","formatMessage","useIntl","isMenuOpen","setIsMenuOpen","useState","_jsx","AssetActions","items","dialogs","hasActions","isBusy","AssetContextMenuBody","onMenuClose","label","id","getTranslationKey","defaultMessage","useEffect","_jsxs","_Fragment","CursorAnchoredMenu","open"],"mappings":";;;;;;;AAuBA;;;;;;;;;;AAUC,IACM,MAAMA,gBAAAA,GAAmB,CAAC,EAC/BC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXC,QAAQ,EACRC,aAAa,EACbC,OAAO,EACe,GAAA;IACtB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAM,CAACC,UAAAA,EAAYC,aAAAA,CAAc,GAAGC,QAAAA,CAAS,IAAA,CAAA;AAE7C,IAAA,qBACEC,GAAA,CAACC,YAAAA,EAAAA;QAAaZ,KAAAA,EAAOA,KAAAA;QAAOC,QAAAA,EAAUA,QAAAA;QAAUC,WAAAA,EAAaA,WAAAA;kBAC1D,CAAC,EAAEW,KAAK,EAAEC,OAAO,EAAEC,UAAU,EAAEC,MAAM,EAAE,iBACtCL,GAAA,CAACM,oBAAAA,EAAAA;gBACCF,UAAAA,EAAYA,UAAAA;gBACZC,MAAAA,EAAQA,MAAAA;gBACRR,UAAAA,EAAYA,UAAAA;AACZU,gBAAAA,WAAAA,EAAa,IAAMT,aAAAA,CAAc,KAAA,CAAA;gBACjCJ,OAAAA,EAASA,OAAAA;gBACTF,QAAAA,EAAUA,QAAAA;gBACVC,aAAAA,EAAeA,aAAAA;AACfe,gBAAAA,KAAAA,EAAOb,aAAAA,CAAc;AACnBc,oBAAAA,EAAAA,EAAIC,iBAAAA,CAAkB,gCAAA,CAAA;oBACtBC,cAAAA,EAAgB;AAClB,iBAAA,CAAA;gBACAT,KAAAA,EAAOA,KAAAA;gBACPC,OAAAA,EAASA;;;AAKnB;AAeA;;;IAIA,MAAMG,uBAAuB,CAAC,EAC5BF,UAAU,EACVC,MAAM,EACNR,UAAU,EACVU,WAAW,EACXb,OAAO,EACPF,QAAQ,EACRC,aAAa,EACbe,KAAK,EACLN,KAAK,EACLC,OAAO,EACmB,GAAA;IAC1BS,SAAAA,CAAU,IAAA;;;AAGR,QAAA,IAAI,CAACR,UAAAA,IAAe,CAACP,UAAAA,IAAc,CAACQ,MAAAA,EAAS;AAC3CX,YAAAA,OAAAA,EAAAA;AACF,QAAA;IACF,CAAA,EAAG;AAACU,QAAAA,UAAAA;AAAYP,QAAAA,UAAAA;AAAYQ,QAAAA,MAAAA;AAAQX,QAAAA;AAAQ,KAAA,CAAA;AAE5C,IAAA,IAAI,CAACU,UAAAA,EAAY;QACf,OAAO,IAAA;AACT,IAAA;IAEA,qBACES,IAAA,CAAAC,QAAA,EAAA;;0BACEd,GAAA,CAACe,kBAAAA,EAAAA;gBACCvB,QAAAA,EAAUA,QAAAA;gBACVwB,IAAAA,EAAMnB,UAAAA;gBACNW,KAAAA,EAAOA,KAAAA;gBACPf,aAAAA,EAAeA,aAAAA;gBACfC,OAAAA,EAASa,WAAAA;AAERL,gBAAAA,QAAAA,EAAAA;;AAEFC,YAAAA;;;AAGP,CAAA;;;;"}