@strapi/upload 5.52.3 → 5.54.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 (220) hide show
  1. package/dist/admin/future/components/Drawer.js +6 -3
  2. package/dist/admin/future/components/Drawer.js.map +1 -1
  3. package/dist/admin/future/components/Drawer.mjs +6 -3
  4. package/dist/admin/future/components/Drawer.mjs.map +1 -1
  5. package/dist/admin/future/components/UploadProgressDialog.js +9 -8
  6. package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
  7. package/dist/admin/future/components/UploadProgressDialog.mjs +9 -8
  8. package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
  9. package/dist/admin/future/pages/Assets/AssetsPage.js +16 -4
  10. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  11. package/dist/admin/future/pages/Assets/AssetsPage.mjs +16 -4
  12. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  13. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +5 -0
  14. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -1
  15. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +5 -0
  16. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
  17. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +19 -4
  18. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  19. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +19 -4
  20. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  21. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +35 -1
  22. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  23. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +35 -1
  24. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  25. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +10 -0
  26. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
  27. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +10 -0
  28. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  29. package/dist/admin/future/pages/Assets/components/AssetsTable.js +9 -0
  30. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
  31. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +10 -1
  32. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
  33. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +132 -88
  34. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
  35. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +135 -91
  36. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
  37. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +7 -0
  38. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
  39. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +7 -0
  40. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
  41. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js +4 -1
  42. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js.map +1 -1
  43. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs +4 -1
  44. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs.map +1 -1
  45. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.js +181 -0
  46. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.js.map +1 -0
  47. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.mjs +179 -0
  48. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -0
  49. package/dist/admin/future/pages/Assets/constants.js +22 -0
  50. package/dist/admin/future/pages/Assets/constants.js.map +1 -1
  51. package/dist/admin/future/pages/Assets/constants.mjs +19 -1
  52. package/dist/admin/future/pages/Assets/constants.mjs.map +1 -1
  53. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +65 -10
  54. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
  55. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +66 -11
  56. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
  57. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.js +111 -0
  58. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.js.map +1 -0
  59. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.mjs +109 -0
  60. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.mjs.map +1 -0
  61. package/dist/admin/future/services/api.js +17 -0
  62. package/dist/admin/future/services/api.js.map +1 -1
  63. package/dist/admin/future/services/api.mjs +18 -1
  64. package/dist/admin/future/services/api.mjs.map +1 -1
  65. package/dist/admin/future/store/uploadProgress.js +31 -22
  66. package/dist/admin/future/store/uploadProgress.js.map +1 -1
  67. package/dist/admin/future/store/uploadProgress.mjs +31 -22
  68. package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
  69. package/dist/admin/index.js +11 -10
  70. package/dist/admin/index.js.map +1 -1
  71. package/dist/admin/index.mjs +11 -10
  72. package/dist/admin/index.mjs.map +1 -1
  73. package/dist/admin/src/future/components/Drawer.d.ts +10 -0
  74. package/dist/admin/src/future/pages/Assets/components/MainAreaContextMenu.d.ts +28 -0
  75. package/dist/admin/src/future/pages/Assets/constants.d.ts +20 -0
  76. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +4 -0
  77. package/dist/admin/src/future/pages/Assets/hooks/useListScrollRestoration.d.ts +15 -0
  78. package/dist/admin/src/future/store/uploadProgress.d.ts +14 -20
  79. package/dist/admin/translations/en.json.js +1 -3
  80. package/dist/admin/translations/en.json.js.map +1 -1
  81. package/dist/admin/translations/en.json.mjs +1 -3
  82. package/dist/admin/translations/en.json.mjs.map +1 -1
  83. package/dist/server/bootstrap.js +11 -0
  84. package/dist/server/bootstrap.js.map +1 -1
  85. package/dist/server/bootstrap.mjs +11 -0
  86. package/dist/server/bootstrap.mjs.map +1 -1
  87. package/dist/server/controllers/admin-upload.js +31 -1
  88. package/dist/server/controllers/admin-upload.js.map +1 -1
  89. package/dist/server/controllers/admin-upload.mjs +31 -1
  90. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  91. package/dist/server/controllers/utils/find-entity-and-check-permissions.js +15 -4
  92. package/dist/server/controllers/utils/find-entity-and-check-permissions.js.map +1 -1
  93. package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs +15 -4
  94. package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs.map +1 -1
  95. package/dist/server/controllers/utils/folders.js +1 -1
  96. package/dist/server/controllers/utils/folders.js.map +1 -1
  97. package/dist/server/controllers/utils/folders.mjs +1 -1
  98. package/dist/server/controllers/utils/folders.mjs.map +1 -1
  99. package/dist/server/mcp/ambient-instance.js +46 -0
  100. package/dist/server/mcp/ambient-instance.js.map +1 -0
  101. package/dist/server/mcp/ambient-instance.mjs +43 -0
  102. package/dist/server/mcp/ambient-instance.mjs.map +1 -0
  103. package/dist/server/mcp/handlers/constants.js +60 -0
  104. package/dist/server/mcp/handlers/constants.js.map +1 -0
  105. package/dist/server/mcp/handlers/constants.mjs +45 -0
  106. package/dist/server/mcp/handlers/constants.mjs.map +1 -0
  107. package/dist/server/mcp/handlers/folder-handlers.js +308 -0
  108. package/dist/server/mcp/handlers/folder-handlers.js.map +1 -0
  109. package/dist/server/mcp/handlers/folder-handlers.mjs +303 -0
  110. package/dist/server/mcp/handlers/folder-handlers.mjs.map +1 -0
  111. package/dist/server/mcp/handlers/read-handlers.js +134 -0
  112. package/dist/server/mcp/handlers/read-handlers.js.map +1 -0
  113. package/dist/server/mcp/handlers/read-handlers.mjs +130 -0
  114. package/dist/server/mcp/handlers/read-handlers.mjs.map +1 -0
  115. package/dist/server/mcp/handlers/write-handlers.js +315 -0
  116. package/dist/server/mcp/handlers/write-handlers.js.map +1 -0
  117. package/dist/server/mcp/handlers/write-handlers.mjs +311 -0
  118. package/dist/server/mcp/handlers/write-handlers.mjs.map +1 -0
  119. package/dist/server/mcp/permissions.js +36 -0
  120. package/dist/server/mcp/permissions.js.map +1 -0
  121. package/dist/server/mcp/permissions.mjs +33 -0
  122. package/dist/server/mcp/permissions.mjs.map +1 -0
  123. package/dist/server/mcp/register-upload-mcp-tools.js +235 -0
  124. package/dist/server/mcp/register-upload-mcp-tools.js.map +1 -0
  125. package/dist/server/mcp/register-upload-mcp-tools.mjs +232 -0
  126. package/dist/server/mcp/register-upload-mcp-tools.mjs.map +1 -0
  127. package/dist/server/mcp/sanitizers/sanitize-media.js +97 -0
  128. package/dist/server/mcp/sanitizers/sanitize-media.js.map +1 -0
  129. package/dist/server/mcp/sanitizers/sanitize-media.mjs +93 -0
  130. package/dist/server/mcp/sanitizers/sanitize-media.mjs.map +1 -0
  131. package/dist/server/mcp/schemas/input-schemas.js +206 -0
  132. package/dist/server/mcp/schemas/input-schemas.js.map +1 -0
  133. package/dist/server/mcp/schemas/input-schemas.mjs +190 -0
  134. package/dist/server/mcp/schemas/input-schemas.mjs.map +1 -0
  135. package/dist/server/mcp/schemas/output-schemas.js +158 -0
  136. package/dist/server/mcp/schemas/output-schemas.js.map +1 -0
  137. package/dist/server/mcp/schemas/output-schemas.mjs +142 -0
  138. package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -0
  139. package/dist/server/mcp/utils.js +14 -0
  140. package/dist/server/mcp/utils.js.map +1 -0
  141. package/dist/server/mcp/utils.mjs +12 -0
  142. package/dist/server/mcp/utils.mjs.map +1 -0
  143. package/dist/server/media-library-default-notice.js +42 -0
  144. package/dist/server/media-library-default-notice.js.map +1 -0
  145. package/dist/server/media-library-default-notice.mjs +40 -0
  146. package/dist/server/media-library-default-notice.mjs.map +1 -0
  147. package/dist/server/register.js +5 -0
  148. package/dist/server/register.js.map +1 -1
  149. package/dist/server/register.mjs +5 -0
  150. package/dist/server/register.mjs.map +1 -1
  151. package/dist/server/services/folder.js.map +1 -1
  152. package/dist/server/services/folder.mjs.map +1 -1
  153. package/dist/server/services/upload.js +34 -10
  154. package/dist/server/services/upload.js.map +1 -1
  155. package/dist/server/services/upload.mjs +34 -10
  156. package/dist/server/services/upload.mjs.map +1 -1
  157. package/dist/server/src/bootstrap.d.ts.map +1 -1
  158. package/dist/server/src/controllers/admin-upload.d.ts +1 -0
  159. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  160. package/dist/server/src/controllers/utils/find-entity-and-check-permissions.d.ts +14 -1
  161. package/dist/server/src/controllers/utils/find-entity-and-check-permissions.d.ts.map +1 -1
  162. package/dist/server/src/controllers/utils/folders.d.ts +2 -1
  163. package/dist/server/src/controllers/utils/folders.d.ts.map +1 -1
  164. package/dist/server/src/index.d.ts +10 -2
  165. package/dist/server/src/index.d.ts.map +1 -1
  166. package/dist/server/src/mcp/ambient-instance.d.ts +65 -0
  167. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -0
  168. package/dist/server/src/mcp/handlers/constants.d.ts +48 -0
  169. package/dist/server/src/mcp/handlers/constants.d.ts.map +1 -0
  170. package/dist/server/src/mcp/handlers/folder-handlers.d.ts +49 -0
  171. package/dist/server/src/mcp/handlers/folder-handlers.d.ts.map +1 -0
  172. package/dist/server/src/mcp/handlers/index.d.ts +5 -0
  173. package/dist/server/src/mcp/handlers/index.d.ts.map +1 -0
  174. package/dist/server/src/mcp/handlers/read-handlers.d.ts +35 -0
  175. package/dist/server/src/mcp/handlers/read-handlers.d.ts.map +1 -0
  176. package/dist/server/src/mcp/handlers/write-handlers.d.ts +66 -0
  177. package/dist/server/src/mcp/handlers/write-handlers.d.ts.map +1 -0
  178. package/dist/server/src/mcp/index.d.ts +3 -0
  179. package/dist/server/src/mcp/index.d.ts.map +1 -0
  180. package/dist/server/src/mcp/permissions.d.ts +22 -0
  181. package/dist/server/src/mcp/permissions.d.ts.map +1 -0
  182. package/dist/server/src/mcp/register-upload-mcp-tools.d.ts +29 -0
  183. package/dist/server/src/mcp/register-upload-mcp-tools.d.ts.map +1 -0
  184. package/dist/server/src/mcp/sanitizers/sanitize-media.d.ts +63 -0
  185. package/dist/server/src/mcp/sanitizers/sanitize-media.d.ts.map +1 -0
  186. package/dist/server/src/mcp/schemas/index.d.ts +3 -0
  187. package/dist/server/src/mcp/schemas/index.d.ts.map +1 -0
  188. package/dist/server/src/mcp/schemas/input-schemas.d.ts +148 -0
  189. package/dist/server/src/mcp/schemas/input-schemas.d.ts.map +1 -0
  190. package/dist/server/src/mcp/schemas/output-schemas.d.ts +276 -0
  191. package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -0
  192. package/dist/server/src/mcp/types.d.ts +19 -0
  193. package/dist/server/src/mcp/types.d.ts.map +1 -0
  194. package/dist/server/src/mcp/utils.d.ts +4 -0
  195. package/dist/server/src/mcp/utils.d.ts.map +1 -0
  196. package/dist/server/src/media-library-default-notice.d.ts +19 -0
  197. package/dist/server/src/media-library-default-notice.d.ts.map +1 -0
  198. package/dist/server/src/register.d.ts.map +1 -1
  199. package/dist/server/src/services/folder.d.ts +6 -2
  200. package/dist/server/src/services/folder.d.ts.map +1 -1
  201. package/dist/server/src/services/index.d.ts +10 -2
  202. package/dist/server/src/services/index.d.ts.map +1 -1
  203. package/dist/server/src/services/upload.d.ts +10 -1
  204. package/dist/server/src/services/upload.d.ts.map +1 -1
  205. package/dist/server/src/types.d.ts +2 -2
  206. package/dist/server/src/types.d.ts.map +1 -1
  207. package/dist/server/src/utils/index.d.ts +2 -1
  208. package/dist/server/src/utils/index.d.ts.map +1 -1
  209. package/dist/server/utils/index.js +2 -2
  210. package/dist/server/utils/index.js.map +1 -1
  211. package/dist/server/utils/index.mjs +2 -2
  212. package/dist/server/utils/index.mjs.map +1 -1
  213. package/dist/shared/contracts/files.d.ts +22 -0
  214. package/dist/shared/contracts/files.d.ts.map +1 -1
  215. package/package.json +7 -6
  216. package/dist/admin/future/components/BetaNotice.js +0 -72
  217. package/dist/admin/future/components/BetaNotice.js.map +0 -1
  218. package/dist/admin/future/components/BetaNotice.mjs +0 -70
  219. package/dist/admin/future/components/BetaNotice.mjs.map +0 -1
  220. package/dist/admin/src/future/components/BetaNotice.d.ts +0 -11
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsDndProvider.mjs","sources":["../../../../../../../admin/src/future/pages/Assets/components/Dnd/AssetsDndProvider.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport {\n DndContext,\n DragOverlay,\n PointerSensor,\n pointerWithin,\n useSensor,\n useSensors,\n type DragEndEvent,\n type DragStartEvent,\n} from '@dnd-kit/core';\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Flex, VisuallyHidden } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { useApiErrorMessage } from '../../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../../hooks/useMediaLibraryPermissions';\nimport { useBulkMoveMutation, useGetFolderStructureQuery } from '../../../../services/folders';\nimport { buildBulkMovePayload } from '../../../../utils/buildBulkMovePayload';\nimport { canDropItemOnFolder } from '../../../../utils/canDropItemOnFolder';\nimport { formatMoveSuccessMessage } from '../../../../utils/formatMoveSuccessMessage';\nimport { getFolderLabel } from '../../../../utils/getFolderLabel';\nimport { emptyItemLocations, type ItemLocations } from '../../../../utils/itemLocations';\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { useAssetSelectionOptional } from '../../hooks/useAssetSelection';\nimport { useFolderNavigation } from '../../hooks/useFolderNavigation';\n\nimport { buildDragSet } from './buildDragSet';\nimport { computeValidDropTargets } from './computeValidDropTargets';\nimport { parseFolderTargetId, parseFolderTreeTargetId } from './dndIds';\nimport { DragOverlayChip } from './DragOverlayChip';\n\nimport type { DragItemData } from '../../../../types/dnd';\n\n/* -------------------------------------------------------------------------------------------------\n * Context — shared with UploadDropZoneProvider for bidirectional drag guard.\n * See UploadDropZoneContext.tsx TODO linking both providers.\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsDndContextValue {\n isInternalDragActive: boolean;\n isMovePending: boolean;\n /** O(1) lookup of whether the current drag set may drop on this destination. */\n isValidDropTarget: (targetFolderId: number | null) => boolean;\n}\n\nconst AssetsDndContext = createContext<AssetsDndContextValue | null>(null);\n\nexport const useAssetsDnd = () => {\n const context = useContext(AssetsDndContext);\n\n if (!context) {\n throw new Error('useAssetsDnd must be used within AssetsDndProvider');\n }\n\n return context;\n};\n\nexport const useAssetsDndOptional = () => useContext(AssetsDndContext);\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsDndProviderProps {\n children: ReactNode;\n /**\n * Real location of every loaded row, so a multi-item drag validates against\n * each item's own parent. Defaults to a lookup that misses everything, which\n * falls back to the folder currently open.\n */\n locations?: ItemLocations;\n}\n\ninterface DragSession {\n items: DragItemData[];\n fromSelection: boolean;\n /** Location of the grabbed row — names the source in the success toast. */\n activeSourceFolderId: number | null;\n /** True when the set spans several source folders, so none can be named. */\n spansMultipleSources: boolean;\n}\n\nconst resolveDestination = (\n overId: string | number\n): { destinationFolderId: number | null } | null => {\n const inView = parseFolderTargetId(overId);\n\n if (inView != null) {\n return { destinationFolderId: inView };\n }\n\n const tree = parseFolderTreeTargetId(overId);\n\n if (tree === 'root') {\n return { destinationFolderId: null };\n }\n\n if (typeof tree === 'number') {\n return { destinationFolderId: tree };\n }\n\n return null;\n};\n\n// Activation distance no real pointer gesture will ever reach — used to keep a\n// constant-length sensor array while disabling drag for users without the move\n// permission (see the note in the provider).\nconst DRAG_DISABLED_DISTANCE = Number.MAX_SAFE_INTEGER;\n\nexport const AssetsDndProvider = ({\n children,\n locations = emptyItemLocations,\n}: AssetsDndProviderProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { toggleNotification } = useNotification();\n const selection = useAssetSelectionOptional();\n const { currentFolderId } = useFolderNavigation();\n const { data: folderStructure = [] } = useGetFolderStructureQuery();\n const rootLabel = formatMessage({\n id: getTranslationKey('plugin.name'),\n defaultMessage: 'Media Library',\n });\n const [bulkMove, { isLoading: isMovePending }] = useBulkMoveMutation();\n const [dragItems, setDragItems] = useState<DragItemData[]>([]);\n const [liveAnnouncement, setLiveAnnouncement] = useState('');\n // Sync session for drag-end — state alone can lag one render behind dragStart.\n const dragSessionRef = useRef<DragSession>({\n items: [],\n fromSelection: false,\n activeSourceFolderId: null,\n spansMultipleSources: false,\n });\n\n const announceToLiveRegion = useCallback((message: string) => {\n setLiveAnnouncement('');\n requestAnimationFrame(() => setLiveAnnouncement(message));\n }, []);\n\n // Moving is a mutation (bulk-move → `assets.update`); without the permission\n // pointer drag must never activate. Keyboard moves go through BulkMoveDialog,\n // which is itself gated.\n //\n // The gate has to keep BOTH the `useSensor`/`useSensors` calls AND the sensor\n // array's length constant across renders: `canUpdate` starts false and flips\n // true once the RBAC check resolves, and dnd-kit keys internal memos/effects\n // on the sensor list, erroring if its size changes (\"argument changed size\n // between renders\"). So adding/removing a sensor is out — instead keep one\n // PointerSensor always and push its activation distance out of reach when the\n // user can't move, which no real drag gesture will ever satisfy.\n const { canUpdate } = useMediaLibraryPermissions();\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: canUpdate ? 8 : DRAG_DISABLED_DISTANCE },\n })\n );\n\n const validDropTargets = useMemo(\n () => computeValidDropTargets(dragItems, folderStructure),\n [dragItems, folderStructure]\n );\n\n const isValidDropTarget = useCallback(\n (targetFolderId: number | null) => validDropTargets.has(targetFolderId),\n [validDropTargets]\n );\n\n const contextValue = useMemo<AssetsDndContextValue>(\n () => ({\n isInternalDragActive: dragItems.length > 0,\n isMovePending,\n isValidDropTarget,\n }),\n [dragItems.length, isMovePending, isValidDropTarget]\n );\n\n const clearDragState = useCallback(() => {\n dragSessionRef.current = {\n items: [],\n fromSelection: false,\n activeSourceFolderId: null,\n spansMultipleSources: false,\n };\n setDragItems([]);\n }, []);\n\n const handleDragStart = useCallback(\n (event: DragStartEvent) => {\n const data = event.active.data.current as DragItemData | undefined;\n\n if (!data) {\n clearDragState();\n return;\n }\n\n const dragSet = buildDragSet(data, selection?.selectedKeys, locations, currentFolderId);\n dragSessionRef.current = dragSet;\n setDragItems(dragSet.items);\n },\n [clearDragState, currentFolderId, locations, selection?.selectedKeys]\n );\n\n const handleDragEnd = useCallback(\n async (event: DragEndEvent) => {\n const { over } = event;\n const { items, fromSelection, activeSourceFolderId, spansMultipleSources } =\n dragSessionRef.current;\n clearDragState();\n\n if (isMovePending || !over || items.length === 0) {\n return;\n }\n\n const destination = resolveDestination(over.id);\n\n if (!destination) {\n return;\n }\n\n const { destinationFolderId: targetFolderId } = destination;\n\n if (\n !canDropItemOnFolder({\n items,\n targetFolderId,\n folderStructure,\n })\n ) {\n return;\n }\n\n const payload = buildBulkMovePayload(items);\n // Source is the grabbed row's own location, not the folder currently open:\n // a global search result can be dragged out of a folder the user isn't in.\n // A search-built selection can also span folders, and then no single\n // source is true for the whole set — `null` drops it from the wording\n // instead of naming one item's folder for all of them. Destination is the\n // drop target. Both use leaf names so the DnD toast reads identically to\n // the dialog's.\n const successMessage = formatMoveSuccessMessage({\n formatMessage,\n count: items.length,\n source: spansMultipleSources\n ? null\n : getFolderLabel(folderStructure, activeSourceFolderId, rootLabel),\n destination: getFolderLabel(folderStructure, targetFolderId, rootLabel),\n });\n const errorFallback = formatMessage({\n id: getTranslationKey('list.bulk-actions.move.error'),\n defaultMessage: 'An error occurred while moving the items.',\n });\n\n try {\n await bulkMove({ ...payload, destinationFolderId: targetFolderId }).unwrap();\n\n if (fromSelection) {\n selection?.clear();\n }\n\n announceToLiveRegion(successMessage);\n\n toggleNotification({\n type: 'success',\n message: successMessage,\n });\n } catch (error) {\n const errorMessage = getErrorMessage(error, errorFallback);\n\n announceToLiveRegion(\n formatMessage(\n {\n id: getTranslationKey('dnd.announce.move-failure'),\n defaultMessage: 'Move failed. {message}',\n },\n { message: errorMessage }\n )\n );\n\n toggleNotification({\n type: 'danger',\n message: errorMessage,\n });\n }\n },\n [\n announceToLiveRegion,\n bulkMove,\n clearDragState,\n folderStructure,\n formatMessage,\n getErrorMessage,\n isMovePending,\n rootLabel,\n selection,\n toggleNotification,\n ]\n );\n\n const handleDragCancel = useCallback(() => {\n clearDragState();\n }, [clearDragState]);\n\n const announcements = useMemo(\n () => ({\n onDragStart: ({ active }: DragStartEvent) => {\n const data = active.data.current as DragItemData | undefined;\n return data\n ? formatMessage(\n {\n id: getTranslationKey('dnd.announce.drag-start'),\n defaultMessage: 'Picked up {name}. Drop on a folder to move.',\n },\n { name: data.name }\n )\n : '';\n },\n onDragOver: () => '',\n onDragEnd: ({ active, over }: DragEndEvent) => {\n if (!over) {\n return formatMessage({\n id: getTranslationKey('dnd.announce.cancel'),\n defaultMessage: 'Drag cancelled.',\n });\n }\n\n const destination = resolveDestination(over.id);\n const activeData = active.data.current as DragItemData | undefined;\n\n if (!destination || !activeData) {\n return '';\n }\n\n const { items } = buildDragSet(\n activeData,\n selection?.selectedKeys,\n locations,\n currentFolderId\n );\n\n if (\n !canDropItemOnFolder({\n items,\n targetFolderId: destination.destinationFolderId,\n folderStructure,\n })\n ) {\n return formatMessage({\n id: getTranslationKey('dnd.announce.invalid-drop'),\n defaultMessage: 'Cannot move item to this folder.',\n });\n }\n\n return '';\n },\n onDragCancel: () =>\n formatMessage({\n id: getTranslationKey('dnd.announce.cancel'),\n defaultMessage: 'Drag cancelled.',\n }),\n }),\n [currentFolderId, folderStructure, formatMessage, locations, selection?.selectedKeys]\n );\n\n return (\n <AssetsDndContext.Provider value={contextValue}>\n <DndContext\n sensors={sensors}\n collisionDetection={pointerWithin}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n accessibility={{ announcements }}\n >\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {liveAnnouncement}\n </VisuallyHidden>\n <Flex position=\"relative\" alignItems=\"stretch\" direction=\"column\" height=\"100%\">\n {children}\n </Flex>\n <DragOverlay dropAnimation={null}>\n {dragItems.length > 0 ? <DragOverlayChip items={dragItems} /> : null}\n </DragOverlay>\n </DndContext>\n </AssetsDndContext.Provider>\n );\n};\n\n// Keyboard-accessible moves are handled by `BulkMoveDialog` (reachable from the\n// bulk-actions bar): pointer drag is a mouse-only enhancement, the dialog is the\n// a11y path. No `KeyboardSensor` by design.\n"],"names":["AssetsDndContext","createContext","useAssetsDndOptional","useContext","resolveDestination","overId","inView","parseFolderTargetId","destinationFolderId","tree","parseFolderTreeTargetId","DRAG_DISABLED_DISTANCE","Number","MAX_SAFE_INTEGER","AssetsDndProvider","children","locations","emptyItemLocations","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","toggleNotification","useNotification","selection","useAssetSelectionOptional","currentFolderId","useFolderNavigation","data","folderStructure","useGetFolderStructureQuery","rootLabel","id","getTranslationKey","defaultMessage","bulkMove","isLoading","isMovePending","useBulkMoveMutation","dragItems","setDragItems","useState","liveAnnouncement","setLiveAnnouncement","dragSessionRef","useRef","items","fromSelection","activeSourceFolderId","spansMultipleSources","announceToLiveRegion","useCallback","message","requestAnimationFrame","canUpdate","useMediaLibraryPermissions","sensors","useSensors","useSensor","PointerSensor","activationConstraint","distance","validDropTargets","useMemo","computeValidDropTargets","isValidDropTarget","targetFolderId","has","contextValue","isInternalDragActive","length","clearDragState","current","handleDragStart","event","active","dragSet","buildDragSet","selectedKeys","handleDragEnd","over","destination","canDropItemOnFolder","payload","buildBulkMovePayload","successMessage","formatMoveSuccessMessage","count","source","getFolderLabel","errorFallback","unwrap","clear","type","error","errorMessage","handleDragCancel","announcements","onDragStart","name","onDragOver","onDragEnd","activeData","onDragCancel","_jsx","Provider","value","_jsxs","DndContext","collisionDetection","pointerWithin","accessibility","VisuallyHidden","aria-live","aria-atomic","Flex","position","alignItems","direction","height","DragOverlay","dropAnimation","DragOverlayChip"],"mappings":"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"}
1
+ {"version":3,"file":"AssetsDndProvider.mjs","sources":["../../../../../../../admin/src/future/pages/Assets/components/Dnd/AssetsDndProvider.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport {\n DndContext,\n DragOverlay,\n PointerSensor,\n pointerWithin,\n useSensor,\n useSensors,\n type DragEndEvent,\n type DragStartEvent,\n} from '@dnd-kit/core';\nimport { snapCenterToCursor } from '@dnd-kit/modifiers';\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Flex, VisuallyHidden } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { useApiErrorMessage } from '../../../../hooks/useApiErrorMessage';\nimport { useMediaLibraryPermissions } from '../../../../hooks/useMediaLibraryPermissions';\nimport { useBulkMoveMutation, useGetFolderStructureQuery } from '../../../../services/folders';\nimport { buildBulkMovePayload } from '../../../../utils/buildBulkMovePayload';\nimport { canDropItemOnFolder } from '../../../../utils/canDropItemOnFolder';\nimport { formatMoveSuccessMessage } from '../../../../utils/formatMoveSuccessMessage';\nimport { getFolderLabel } from '../../../../utils/getFolderLabel';\nimport { emptyItemLocations, type ItemLocations } from '../../../../utils/itemLocations';\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { useAssetSelectionOptional } from '../../hooks/useAssetSelection';\nimport { useFolderNavigation } from '../../hooks/useFolderNavigation';\n\nimport { buildDragSet } from './buildDragSet';\nimport { computeValidDropTargets } from './computeValidDropTargets';\nimport { parseFolderTargetId, parseFolderTreeTargetId } from './dndIds';\nimport { DragOverlayChip } from './DragOverlayChip';\n\nimport type { DragItemData } from '../../../../types/dnd';\n\n/* -------------------------------------------------------------------------------------------------\n * Context — shared with UploadDropZoneProvider for bidirectional drag guard.\n * See UploadDropZoneContext.tsx TODO linking both providers.\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsDndContextValue {\n isInternalDragActive: boolean;\n isMovePending: boolean;\n /** O(1) lookup of whether the current drag set may drop on this destination. */\n isValidDropTarget: (targetFolderId: number | null) => boolean;\n}\n\nconst AssetsDndContext = createContext<AssetsDndContextValue | null>(null);\n\nexport const useAssetsDnd = () => {\n const context = useContext(AssetsDndContext);\n\n if (!context) {\n throw new Error('useAssetsDnd must be used within AssetsDndProvider');\n }\n\n return context;\n};\n\nexport const useAssetsDndOptional = () => useContext(AssetsDndContext);\n\n/* -------------------------------------------------------------------------------------------------\n * Provider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface AssetsDndProviderProps {\n children: ReactNode;\n /**\n * Real location of every loaded row, so a multi-item drag validates against\n * each item's own parent. Defaults to a lookup that misses everything, which\n * falls back to the folder currently open.\n */\n locations?: ItemLocations;\n}\n\ninterface DragSession {\n items: DragItemData[];\n fromSelection: boolean;\n /** Location of the grabbed row — names the source in the success toast. */\n activeSourceFolderId: number | null;\n /** True when the set spans several source folders, so none can be named. */\n spansMultipleSources: boolean;\n}\n\nconst resolveDestination = (\n overId: string | number\n): { destinationFolderId: number | null } | null => {\n const inView = parseFolderTargetId(overId);\n\n if (inView != null) {\n return { destinationFolderId: inView };\n }\n\n const tree = parseFolderTreeTargetId(overId);\n\n if (tree === 'root') {\n return { destinationFolderId: null };\n }\n\n if (typeof tree === 'number') {\n return { destinationFolderId: tree };\n }\n\n return null;\n};\n\n// Activation distance no real pointer gesture will ever reach — used to keep a\n// constant-length sensor array while disabling drag for users without the move\n// permission (see the note in the provider).\nconst DRAG_DISABLED_DISTANCE = Number.MAX_SAFE_INTEGER;\n\n// Without a modifier the overlay is anchored to the dragged node's top-left, so the\n// chip trails the cursor by however far into the card or row the grab landed.\nconst OVERLAY_MODIFIERS = [snapCenterToCursor];\n\nexport const AssetsDndProvider = ({\n children,\n locations = emptyItemLocations,\n}: AssetsDndProviderProps) => {\n const { formatMessage } = useIntl();\n const getErrorMessage = useApiErrorMessage();\n const { toggleNotification } = useNotification();\n const selection = useAssetSelectionOptional();\n const { currentFolderId } = useFolderNavigation();\n const { data: folderStructure = [] } = useGetFolderStructureQuery();\n const rootLabel = formatMessage({\n id: getTranslationKey('plugin.name'),\n defaultMessage: 'Media Library',\n });\n const [bulkMove, { isLoading: isMovePending }] = useBulkMoveMutation();\n const [dragItems, setDragItems] = useState<DragItemData[]>([]);\n const [liveAnnouncement, setLiveAnnouncement] = useState('');\n // Sync session for drag-end — state alone can lag one render behind dragStart.\n const dragSessionRef = useRef<DragSession>({\n items: [],\n fromSelection: false,\n activeSourceFolderId: null,\n spansMultipleSources: false,\n });\n\n const announceToLiveRegion = useCallback((message: string) => {\n setLiveAnnouncement('');\n requestAnimationFrame(() => setLiveAnnouncement(message));\n }, []);\n\n // Moving is a mutation (bulk-move → `assets.update`); without the permission\n // pointer drag must never activate. Keyboard moves go through BulkMoveDialog,\n // which is itself gated.\n //\n // The gate has to keep BOTH the `useSensor`/`useSensors` calls AND the sensor\n // array's length constant across renders: `canUpdate` starts false and flips\n // true once the RBAC check resolves, and dnd-kit keys internal memos/effects\n // on the sensor list, erroring if its size changes (\"argument changed size\n // between renders\"). So adding/removing a sensor is out — instead keep one\n // PointerSensor always and push its activation distance out of reach when the\n // user can't move, which no real drag gesture will ever satisfy.\n const { canUpdate } = useMediaLibraryPermissions();\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: canUpdate ? 8 : DRAG_DISABLED_DISTANCE },\n })\n );\n\n const validDropTargets = useMemo(\n () => computeValidDropTargets(dragItems, folderStructure),\n [dragItems, folderStructure]\n );\n\n const isValidDropTarget = useCallback(\n (targetFolderId: number | null) => validDropTargets.has(targetFolderId),\n [validDropTargets]\n );\n\n const contextValue = useMemo<AssetsDndContextValue>(\n () => ({\n isInternalDragActive: dragItems.length > 0,\n isMovePending,\n isValidDropTarget,\n }),\n [dragItems.length, isMovePending, isValidDropTarget]\n );\n\n const clearDragState = useCallback(() => {\n dragSessionRef.current = {\n items: [],\n fromSelection: false,\n activeSourceFolderId: null,\n spansMultipleSources: false,\n };\n setDragItems([]);\n }, []);\n\n const handleDragStart = useCallback(\n (event: DragStartEvent) => {\n const data = event.active.data.current as DragItemData | undefined;\n\n if (!data) {\n clearDragState();\n return;\n }\n\n const dragSet = buildDragSet(data, selection?.selectedKeys, locations, currentFolderId);\n dragSessionRef.current = dragSet;\n setDragItems(dragSet.items);\n },\n [clearDragState, currentFolderId, locations, selection?.selectedKeys]\n );\n\n const handleDragEnd = useCallback(\n async (event: DragEndEvent) => {\n const { over } = event;\n const { items, fromSelection, activeSourceFolderId, spansMultipleSources } =\n dragSessionRef.current;\n clearDragState();\n\n if (isMovePending || !over || items.length === 0) {\n return;\n }\n\n const destination = resolveDestination(over.id);\n\n if (!destination) {\n return;\n }\n\n const { destinationFolderId: targetFolderId } = destination;\n\n if (\n !canDropItemOnFolder({\n items,\n targetFolderId,\n folderStructure,\n })\n ) {\n return;\n }\n\n const payload = buildBulkMovePayload(items);\n // Source is the grabbed row's own location, not the folder currently open:\n // a global search result can be dragged out of a folder the user isn't in.\n // A search-built selection can also span folders, and then no single\n // source is true for the whole set — `null` drops it from the wording\n // instead of naming one item's folder for all of them. Destination is the\n // drop target. Both use leaf names so the DnD toast reads identically to\n // the dialog's.\n const successMessage = formatMoveSuccessMessage({\n formatMessage,\n count: items.length,\n source: spansMultipleSources\n ? null\n : getFolderLabel(folderStructure, activeSourceFolderId, rootLabel),\n destination: getFolderLabel(folderStructure, targetFolderId, rootLabel),\n });\n const errorFallback = formatMessage({\n id: getTranslationKey('list.bulk-actions.move.error'),\n defaultMessage: 'An error occurred while moving the items.',\n });\n\n try {\n await bulkMove({ ...payload, destinationFolderId: targetFolderId }).unwrap();\n\n if (fromSelection) {\n selection?.clear();\n }\n\n announceToLiveRegion(successMessage);\n\n toggleNotification({\n type: 'success',\n message: successMessage,\n });\n } catch (error) {\n const errorMessage = getErrorMessage(error, errorFallback);\n\n announceToLiveRegion(\n formatMessage(\n {\n id: getTranslationKey('dnd.announce.move-failure'),\n defaultMessage: 'Move failed. {message}',\n },\n { message: errorMessage }\n )\n );\n\n toggleNotification({\n type: 'danger',\n message: errorMessage,\n });\n }\n },\n [\n announceToLiveRegion,\n bulkMove,\n clearDragState,\n folderStructure,\n formatMessage,\n getErrorMessage,\n isMovePending,\n rootLabel,\n selection,\n toggleNotification,\n ]\n );\n\n const handleDragCancel = useCallback(() => {\n clearDragState();\n }, [clearDragState]);\n\n const announcements = useMemo(\n () => ({\n onDragStart: ({ active }: DragStartEvent) => {\n const data = active.data.current as DragItemData | undefined;\n return data\n ? formatMessage(\n {\n id: getTranslationKey('dnd.announce.drag-start'),\n defaultMessage: 'Picked up {name}. Drop on a folder to move.',\n },\n { name: data.name }\n )\n : '';\n },\n onDragOver: () => '',\n onDragEnd: ({ active, over }: DragEndEvent) => {\n if (!over) {\n return formatMessage({\n id: getTranslationKey('dnd.announce.cancel'),\n defaultMessage: 'Drag cancelled.',\n });\n }\n\n const destination = resolveDestination(over.id);\n const activeData = active.data.current as DragItemData | undefined;\n\n if (!destination || !activeData) {\n return '';\n }\n\n const { items } = buildDragSet(\n activeData,\n selection?.selectedKeys,\n locations,\n currentFolderId\n );\n\n if (\n !canDropItemOnFolder({\n items,\n targetFolderId: destination.destinationFolderId,\n folderStructure,\n })\n ) {\n return formatMessage({\n id: getTranslationKey('dnd.announce.invalid-drop'),\n defaultMessage: 'Cannot move item to this folder.',\n });\n }\n\n return '';\n },\n onDragCancel: () =>\n formatMessage({\n id: getTranslationKey('dnd.announce.cancel'),\n defaultMessage: 'Drag cancelled.',\n }),\n }),\n [currentFolderId, folderStructure, formatMessage, locations, selection?.selectedKeys]\n );\n\n return (\n <AssetsDndContext.Provider value={contextValue}>\n <DndContext\n sensors={sensors}\n collisionDetection={pointerWithin}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n accessibility={{ announcements }}\n >\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {liveAnnouncement}\n </VisuallyHidden>\n <Flex position=\"relative\" alignItems=\"stretch\" direction=\"column\" height=\"100%\">\n {children}\n </Flex>\n <DragOverlay dropAnimation={null} modifiers={OVERLAY_MODIFIERS}>\n {dragItems.length > 0 ? <DragOverlayChip items={dragItems} /> : null}\n </DragOverlay>\n </DndContext>\n </AssetsDndContext.Provider>\n );\n};\n\n// Keyboard-accessible moves are handled by `BulkMoveDialog` (reachable from the\n// bulk-actions bar): pointer drag is a mouse-only enhancement, the dialog is the\n// a11y path. No `KeyboardSensor` by design.\n"],"names":["AssetsDndContext","createContext","useAssetsDndOptional","useContext","resolveDestination","overId","inView","parseFolderTargetId","destinationFolderId","tree","parseFolderTreeTargetId","DRAG_DISABLED_DISTANCE","Number","MAX_SAFE_INTEGER","OVERLAY_MODIFIERS","snapCenterToCursor","AssetsDndProvider","children","locations","emptyItemLocations","formatMessage","useIntl","getErrorMessage","useApiErrorMessage","toggleNotification","useNotification","selection","useAssetSelectionOptional","currentFolderId","useFolderNavigation","data","folderStructure","useGetFolderStructureQuery","rootLabel","id","getTranslationKey","defaultMessage","bulkMove","isLoading","isMovePending","useBulkMoveMutation","dragItems","setDragItems","useState","liveAnnouncement","setLiveAnnouncement","dragSessionRef","useRef","items","fromSelection","activeSourceFolderId","spansMultipleSources","announceToLiveRegion","useCallback","message","requestAnimationFrame","canUpdate","useMediaLibraryPermissions","sensors","useSensors","useSensor","PointerSensor","activationConstraint","distance","validDropTargets","useMemo","computeValidDropTargets","isValidDropTarget","targetFolderId","has","contextValue","isInternalDragActive","length","clearDragState","current","handleDragStart","event","active","dragSet","buildDragSet","selectedKeys","handleDragEnd","over","destination","canDropItemOnFolder","payload","buildBulkMovePayload","successMessage","formatMoveSuccessMessage","count","source","getFolderLabel","errorFallback","unwrap","clear","type","error","errorMessage","handleDragCancel","announcements","onDragStart","name","onDragOver","onDragEnd","activeData","onDragCancel","_jsx","Provider","value","_jsxs","DndContext","collisionDetection","pointerWithin","accessibility","VisuallyHidden","aria-live","aria-atomic","Flex","position","alignItems","direction","height","DragOverlay","dropAnimation","modifiers","DragOverlayChip"],"mappings":"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"}
@@ -13,7 +13,10 @@ var translations = require('../../../../utils/translations.js');
13
13
  const FOLDER_ICON_SIZE = 20;
14
14
  const FILE_ICON_SIZE = 24;
15
15
  const ICON_BOX = 24;
16
- const Chip = styledComponents.styled(designSystem.Flex)`
16
+ // `CompositeChip` is `styled(Chip)`, so it inherits the testid.
17
+ const Chip = styledComponents.styled(designSystem.Flex).attrs({
18
+ 'data-testid': 'drag-overlay-chip'
19
+ })`
17
20
  position: relative;
18
21
  align-items: center;
19
22
  gap: ${({ theme })=>theme.spaces[2]};
@@ -1 +1 @@
1
- {"version":3,"file":"DragOverlayChip.js","sources":["../../../../../../../admin/src/future/pages/Assets/components/Dnd/DragOverlayChip.tsx"],"sourcesContent":["import { Flex, Typography } from '@strapi/design-system';\nimport { File as FileIcon, Folder as FolderIcon } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../../utils/translations';\n\nimport type { DragItemData } from '../../../../types/dnd';\n\n// Folder & File (@strapi/icons) share viewBox 0 0 32 32 but File's glyph is\n// narrower/lighter. Rendering File a few px larger inside a fixed square box makes\n// the two previews read at the same visual size without shifting the chip layout.\nconst FOLDER_ICON_SIZE = 20;\nconst FILE_ICON_SIZE = 24;\nconst ICON_BOX = 24;\n\nconst Chip = styled(Flex)`\n position: relative;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary100};\n box-shadow: ${({ theme }) => theme.shadows.tableShadow};\n cursor: grabbing;\n max-width: 24rem;\n`;\n\nconst CompositeChip = styled(Chip)`\n box-shadow:\n ${({ theme }) => theme.shadows.tableShadow},\n 0 4px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 4px 0 0 ${({ theme }) => theme.colors.primary200},\n 0 7px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 7px 0 0 ${({ theme }) => theme.colors.primary200};\n`;\n\nconst CountGroup = styled(Flex)`\n align-items: center;\n gap: ${({ theme }) => theme.spaces[1]};\n`;\n\nconst IconBox = styled(Flex)`\n flex-shrink: 0;\n width: ${ICON_BOX}px;\n height: ${ICON_BOX}px;\n align-items: center;\n justify-content: center;\n`;\n\nconst TotalBadge = styled(Flex)`\n position: absolute;\n top: -${({ theme }) => theme.spaces[2]};\n right: -${({ theme }) => theme.spaces[2]};\n align-items: center;\n justify-content: center;\n min-width: ${({ theme }) => theme.spaces[5]};\n height: ${({ theme }) => theme.spaces[5]};\n padding: 0 ${({ theme }) => theme.spaces[1]};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary600};\n`;\n\ninterface DragOverlayChipProps {\n items: DragItemData[];\n}\n\nexport const DragOverlayChip = ({ items }: DragOverlayChipProps) => {\n const { formatMessage } = useIntl();\n\n if (items.length === 0) {\n return null;\n }\n\n if (items.length === 1) {\n const item = items[0];\n const isFolder = item.kind === 'folder';\n const Icon = isFolder ? FolderIcon : FileIcon;\n const size = isFolder ? FOLDER_ICON_SIZE : FILE_ICON_SIZE;\n\n return (\n <Chip>\n <IconBox>\n <Icon width={size} height={size} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\" ellipsis>\n {item.name}\n </Typography>\n </Chip>\n );\n }\n\n const folderCount = items.filter((item) => item.kind === 'folder').length;\n const fileCount = items.filter((item) => item.kind === 'file').length;\n const total = folderCount + fileCount;\n\n return (\n <CompositeChip gap={3}>\n {folderCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FolderIcon width={FOLDER_ICON_SIZE} height={FOLDER_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.folders'),\n defaultMessage: '{count, plural, one {# folder} other {# folders}}',\n },\n { count: folderCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n {fileCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FileIcon width={FILE_ICON_SIZE} height={FILE_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.files'),\n defaultMessage: '{count, plural, one {# file} other {# files}}',\n },\n { count: fileCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n <TotalBadge>\n <Typography textColor=\"neutral0\" fontWeight=\"bold\" variant=\"pi\">\n {total}\n </Typography>\n </TotalBadge>\n </CompositeChip>\n );\n};\n"],"names":["FOLDER_ICON_SIZE","FILE_ICON_SIZE","ICON_BOX","Chip","styled","Flex","theme","spaces","borderRadius","colors","primary100","shadows","tableShadow","CompositeChip","primary200","CountGroup","IconBox","TotalBadge","primary600","DragOverlayChip","items","formatMessage","useIntl","length","item","isFolder","kind","Icon","FolderIcon","FileIcon","size","_jsxs","_jsx","width","height","Typography","textColor","fontWeight","ellipsis","name","folderCount","filter","fileCount","total","gap","id","getTranslationKey","defaultMessage","count","variant"],"mappings":"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"}
1
+ {"version":3,"file":"DragOverlayChip.js","sources":["../../../../../../../admin/src/future/pages/Assets/components/Dnd/DragOverlayChip.tsx"],"sourcesContent":["import { Flex, Typography } from '@strapi/design-system';\nimport { File as FileIcon, Folder as FolderIcon } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../../utils/translations';\n\nimport type { DragItemData } from '../../../../types/dnd';\n\n// Folder & File (@strapi/icons) share viewBox 0 0 32 32 but File's glyph is\n// narrower/lighter. Rendering File a few px larger inside a fixed square box makes\n// the two previews read at the same visual size without shifting the chip layout.\nconst FOLDER_ICON_SIZE = 20;\nconst FILE_ICON_SIZE = 24;\nconst ICON_BOX = 24;\n\n// `CompositeChip` is `styled(Chip)`, so it inherits the testid.\nconst Chip = styled(Flex).attrs({ 'data-testid': 'drag-overlay-chip' })`\n position: relative;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary100};\n box-shadow: ${({ theme }) => theme.shadows.tableShadow};\n cursor: grabbing;\n max-width: 24rem;\n`;\n\nconst CompositeChip = styled(Chip)`\n box-shadow:\n ${({ theme }) => theme.shadows.tableShadow},\n 0 4px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 4px 0 0 ${({ theme }) => theme.colors.primary200},\n 0 7px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 7px 0 0 ${({ theme }) => theme.colors.primary200};\n`;\n\nconst CountGroup = styled(Flex)`\n align-items: center;\n gap: ${({ theme }) => theme.spaces[1]};\n`;\n\nconst IconBox = styled(Flex)`\n flex-shrink: 0;\n width: ${ICON_BOX}px;\n height: ${ICON_BOX}px;\n align-items: center;\n justify-content: center;\n`;\n\nconst TotalBadge = styled(Flex)`\n position: absolute;\n top: -${({ theme }) => theme.spaces[2]};\n right: -${({ theme }) => theme.spaces[2]};\n align-items: center;\n justify-content: center;\n min-width: ${({ theme }) => theme.spaces[5]};\n height: ${({ theme }) => theme.spaces[5]};\n padding: 0 ${({ theme }) => theme.spaces[1]};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary600};\n`;\n\ninterface DragOverlayChipProps {\n items: DragItemData[];\n}\n\nexport const DragOverlayChip = ({ items }: DragOverlayChipProps) => {\n const { formatMessage } = useIntl();\n\n if (items.length === 0) {\n return null;\n }\n\n if (items.length === 1) {\n const item = items[0];\n const isFolder = item.kind === 'folder';\n const Icon = isFolder ? FolderIcon : FileIcon;\n const size = isFolder ? FOLDER_ICON_SIZE : FILE_ICON_SIZE;\n\n return (\n <Chip>\n <IconBox>\n <Icon width={size} height={size} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\" ellipsis>\n {item.name}\n </Typography>\n </Chip>\n );\n }\n\n const folderCount = items.filter((item) => item.kind === 'folder').length;\n const fileCount = items.filter((item) => item.kind === 'file').length;\n const total = folderCount + fileCount;\n\n return (\n <CompositeChip gap={3}>\n {folderCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FolderIcon width={FOLDER_ICON_SIZE} height={FOLDER_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.folders'),\n defaultMessage: '{count, plural, one {# folder} other {# folders}}',\n },\n { count: folderCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n {fileCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FileIcon width={FILE_ICON_SIZE} height={FILE_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.files'),\n defaultMessage: '{count, plural, one {# file} other {# files}}',\n },\n { count: fileCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n <TotalBadge>\n <Typography textColor=\"neutral0\" fontWeight=\"bold\" variant=\"pi\">\n {total}\n </Typography>\n </TotalBadge>\n </CompositeChip>\n );\n};\n"],"names":["FOLDER_ICON_SIZE","FILE_ICON_SIZE","ICON_BOX","Chip","styled","Flex","attrs","theme","spaces","borderRadius","colors","primary100","shadows","tableShadow","CompositeChip","primary200","CountGroup","IconBox","TotalBadge","primary600","DragOverlayChip","items","formatMessage","useIntl","length","item","isFolder","kind","Icon","FolderIcon","FileIcon","size","_jsxs","_jsx","width","height","Typography","textColor","fontWeight","ellipsis","name","folderCount","filter","fileCount","total","gap","id","getTranslationKey","defaultMessage","count","variant"],"mappings":"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"}
@@ -11,7 +11,10 @@ import { getTranslationKey } from '../../../../utils/translations.mjs';
11
11
  const FOLDER_ICON_SIZE = 20;
12
12
  const FILE_ICON_SIZE = 24;
13
13
  const ICON_BOX = 24;
14
- const Chip = styled(Flex)`
14
+ // `CompositeChip` is `styled(Chip)`, so it inherits the testid.
15
+ const Chip = styled(Flex).attrs({
16
+ 'data-testid': 'drag-overlay-chip'
17
+ })`
15
18
  position: relative;
16
19
  align-items: center;
17
20
  gap: ${({ theme })=>theme.spaces[2]};
@@ -1 +1 @@
1
- {"version":3,"file":"DragOverlayChip.mjs","sources":["../../../../../../../admin/src/future/pages/Assets/components/Dnd/DragOverlayChip.tsx"],"sourcesContent":["import { Flex, Typography } from '@strapi/design-system';\nimport { File as FileIcon, Folder as FolderIcon } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../../utils/translations';\n\nimport type { DragItemData } from '../../../../types/dnd';\n\n// Folder & File (@strapi/icons) share viewBox 0 0 32 32 but File's glyph is\n// narrower/lighter. Rendering File a few px larger inside a fixed square box makes\n// the two previews read at the same visual size without shifting the chip layout.\nconst FOLDER_ICON_SIZE = 20;\nconst FILE_ICON_SIZE = 24;\nconst ICON_BOX = 24;\n\nconst Chip = styled(Flex)`\n position: relative;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary100};\n box-shadow: ${({ theme }) => theme.shadows.tableShadow};\n cursor: grabbing;\n max-width: 24rem;\n`;\n\nconst CompositeChip = styled(Chip)`\n box-shadow:\n ${({ theme }) => theme.shadows.tableShadow},\n 0 4px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 4px 0 0 ${({ theme }) => theme.colors.primary200},\n 0 7px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 7px 0 0 ${({ theme }) => theme.colors.primary200};\n`;\n\nconst CountGroup = styled(Flex)`\n align-items: center;\n gap: ${({ theme }) => theme.spaces[1]};\n`;\n\nconst IconBox = styled(Flex)`\n flex-shrink: 0;\n width: ${ICON_BOX}px;\n height: ${ICON_BOX}px;\n align-items: center;\n justify-content: center;\n`;\n\nconst TotalBadge = styled(Flex)`\n position: absolute;\n top: -${({ theme }) => theme.spaces[2]};\n right: -${({ theme }) => theme.spaces[2]};\n align-items: center;\n justify-content: center;\n min-width: ${({ theme }) => theme.spaces[5]};\n height: ${({ theme }) => theme.spaces[5]};\n padding: 0 ${({ theme }) => theme.spaces[1]};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary600};\n`;\n\ninterface DragOverlayChipProps {\n items: DragItemData[];\n}\n\nexport const DragOverlayChip = ({ items }: DragOverlayChipProps) => {\n const { formatMessage } = useIntl();\n\n if (items.length === 0) {\n return null;\n }\n\n if (items.length === 1) {\n const item = items[0];\n const isFolder = item.kind === 'folder';\n const Icon = isFolder ? FolderIcon : FileIcon;\n const size = isFolder ? FOLDER_ICON_SIZE : FILE_ICON_SIZE;\n\n return (\n <Chip>\n <IconBox>\n <Icon width={size} height={size} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\" ellipsis>\n {item.name}\n </Typography>\n </Chip>\n );\n }\n\n const folderCount = items.filter((item) => item.kind === 'folder').length;\n const fileCount = items.filter((item) => item.kind === 'file').length;\n const total = folderCount + fileCount;\n\n return (\n <CompositeChip gap={3}>\n {folderCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FolderIcon width={FOLDER_ICON_SIZE} height={FOLDER_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.folders'),\n defaultMessage: '{count, plural, one {# folder} other {# folders}}',\n },\n { count: folderCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n {fileCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FileIcon width={FILE_ICON_SIZE} height={FILE_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.files'),\n defaultMessage: '{count, plural, one {# file} other {# files}}',\n },\n { count: fileCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n <TotalBadge>\n <Typography textColor=\"neutral0\" fontWeight=\"bold\" variant=\"pi\">\n {total}\n </Typography>\n </TotalBadge>\n </CompositeChip>\n );\n};\n"],"names":["FOLDER_ICON_SIZE","FILE_ICON_SIZE","ICON_BOX","Chip","styled","Flex","theme","spaces","borderRadius","colors","primary100","shadows","tableShadow","CompositeChip","primary200","CountGroup","IconBox","TotalBadge","primary600","DragOverlayChip","items","formatMessage","useIntl","length","item","isFolder","kind","Icon","FolderIcon","FileIcon","size","_jsxs","_jsx","width","height","Typography","textColor","fontWeight","ellipsis","name","folderCount","filter","fileCount","total","gap","id","getTranslationKey","defaultMessage","count","variant"],"mappings":"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"}
1
+ {"version":3,"file":"DragOverlayChip.mjs","sources":["../../../../../../../admin/src/future/pages/Assets/components/Dnd/DragOverlayChip.tsx"],"sourcesContent":["import { Flex, Typography } from '@strapi/design-system';\nimport { File as FileIcon, Folder as FolderIcon } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../../utils/translations';\n\nimport type { DragItemData } from '../../../../types/dnd';\n\n// Folder & File (@strapi/icons) share viewBox 0 0 32 32 but File's glyph is\n// narrower/lighter. Rendering File a few px larger inside a fixed square box makes\n// the two previews read at the same visual size without shifting the chip layout.\nconst FOLDER_ICON_SIZE = 20;\nconst FILE_ICON_SIZE = 24;\nconst ICON_BOX = 24;\n\n// `CompositeChip` is `styled(Chip)`, so it inherits the testid.\nconst Chip = styled(Flex).attrs({ 'data-testid': 'drag-overlay-chip' })`\n position: relative;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary100};\n box-shadow: ${({ theme }) => theme.shadows.tableShadow};\n cursor: grabbing;\n max-width: 24rem;\n`;\n\nconst CompositeChip = styled(Chip)`\n box-shadow:\n ${({ theme }) => theme.shadows.tableShadow},\n 0 4px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 4px 0 0 ${({ theme }) => theme.colors.primary200},\n 0 7px 0 -1px ${({ theme }) => theme.colors.primary100},\n 0 7px 0 0 ${({ theme }) => theme.colors.primary200};\n`;\n\nconst CountGroup = styled(Flex)`\n align-items: center;\n gap: ${({ theme }) => theme.spaces[1]};\n`;\n\nconst IconBox = styled(Flex)`\n flex-shrink: 0;\n width: ${ICON_BOX}px;\n height: ${ICON_BOX}px;\n align-items: center;\n justify-content: center;\n`;\n\nconst TotalBadge = styled(Flex)`\n position: absolute;\n top: -${({ theme }) => theme.spaces[2]};\n right: -${({ theme }) => theme.spaces[2]};\n align-items: center;\n justify-content: center;\n min-width: ${({ theme }) => theme.spaces[5]};\n height: ${({ theme }) => theme.spaces[5]};\n padding: 0 ${({ theme }) => theme.spaces[1]};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.primary600};\n`;\n\ninterface DragOverlayChipProps {\n items: DragItemData[];\n}\n\nexport const DragOverlayChip = ({ items }: DragOverlayChipProps) => {\n const { formatMessage } = useIntl();\n\n if (items.length === 0) {\n return null;\n }\n\n if (items.length === 1) {\n const item = items[0];\n const isFolder = item.kind === 'folder';\n const Icon = isFolder ? FolderIcon : FileIcon;\n const size = isFolder ? FOLDER_ICON_SIZE : FILE_ICON_SIZE;\n\n return (\n <Chip>\n <IconBox>\n <Icon width={size} height={size} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\" ellipsis>\n {item.name}\n </Typography>\n </Chip>\n );\n }\n\n const folderCount = items.filter((item) => item.kind === 'folder').length;\n const fileCount = items.filter((item) => item.kind === 'file').length;\n const total = folderCount + fileCount;\n\n return (\n <CompositeChip gap={3}>\n {folderCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FolderIcon width={FOLDER_ICON_SIZE} height={FOLDER_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.folders'),\n defaultMessage: '{count, plural, one {# folder} other {# folders}}',\n },\n { count: folderCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n {fileCount > 0 ? (\n <CountGroup>\n <IconBox>\n <FileIcon width={FILE_ICON_SIZE} height={FILE_ICON_SIZE} />\n </IconBox>\n <Typography textColor=\"neutral800\" fontWeight=\"semiBold\">\n {formatMessage(\n {\n id: getTranslationKey('dnd.overlay.files'),\n defaultMessage: '{count, plural, one {# file} other {# files}}',\n },\n { count: fileCount }\n )}\n </Typography>\n </CountGroup>\n ) : null}\n <TotalBadge>\n <Typography textColor=\"neutral0\" fontWeight=\"bold\" variant=\"pi\">\n {total}\n </Typography>\n </TotalBadge>\n </CompositeChip>\n );\n};\n"],"names":["FOLDER_ICON_SIZE","FILE_ICON_SIZE","ICON_BOX","Chip","styled","Flex","attrs","theme","spaces","borderRadius","colors","primary100","shadows","tableShadow","CompositeChip","primary200","CountGroup","IconBox","TotalBadge","primary600","DragOverlayChip","items","formatMessage","useIntl","length","item","isFolder","kind","Icon","FolderIcon","FileIcon","size","_jsxs","_jsx","width","height","Typography","textColor","fontWeight","ellipsis","name","folderCount","filter","fileCount","total","gap","id","getTranslationKey","defaultMessage","count","variant"],"mappings":"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"}
@@ -0,0 +1,181 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var designSystem = require('@strapi/design-system');
6
+ var icons = require('@strapi/icons');
7
+ var reactIntl = require('react-intl');
8
+ var translations = require('../../../utils/translations.js');
9
+ var ActionsMenuContent = require('./ActionsMenuContent.js');
10
+
11
+ /**
12
+ * The admin layout marks the element that scrolls the main column. Listening on
13
+ * it rather than a wrapper of our own is what makes the whole column part of the
14
+ * hit area: it carries a responsive `padding-bottom` (16 / 24 / 40px) that no
15
+ * descendant can cover, and that strip is exactly where a right-click "below the
16
+ * list" lands.
17
+ */ const SCROLL_ROOT_SELECTOR = '[data-strapi-main-content]';
18
+ /**
19
+ * Subtrees that keep the browser's own context menu instead of opening the
20
+ * create menu.
21
+ *
22
+ * `data-native-context-menu` is the explicit opt-out carried by the list items
23
+ * themselves (asset cards, folder cards, table rows) and by the bulk actions
24
+ * bar — right-clicking one of those must behave exactly as it does today. The
25
+ * rest are the generic cases where the native menu is the useful one: links,
26
+ * buttons and anything the user can type into or select text in.
27
+ *
28
+ * `thead` covers the table's header row, which is chrome rather than empty
29
+ * background even though it carries no `data-native-context-menu` item.
30
+ */ const NATIVE_CONTEXT_MENU_SELECTOR = [
31
+ '[data-native-context-menu]',
32
+ 'thead',
33
+ 'a',
34
+ 'button',
35
+ 'input',
36
+ 'textarea',
37
+ 'select',
38
+ '[contenteditable="true"]'
39
+ ].join(', ');
40
+ /**
41
+ * The menu is anchored to a zero-sized element parked at the cursor, because
42
+ * the design system's `Menu` is a dropdown: it positions its content against a
43
+ * trigger, and there is no real trigger for a right-click on empty space.
44
+ *
45
+ * Inline styles rather than a `styled` wrapper — the trigger renders a design
46
+ * system `Button`, and losing the specificity race with its own class would put
47
+ * a stray button on the page.
48
+ */ const CURSOR_ANCHOR_STYLE = {
49
+ position: 'fixed',
50
+ width: 0,
51
+ height: 0,
52
+ minWidth: 0,
53
+ minHeight: 0,
54
+ padding: 0,
55
+ border: 0,
56
+ opacity: 0,
57
+ overflow: 'hidden',
58
+ pointerEvents: 'none'
59
+ };
60
+ const LOCATOR_STYLE = {
61
+ height: 0
62
+ };
63
+ /**
64
+ * Drive/Dropbox-style right-click on the empty parts of the assets area: the
65
+ * same creation actions the header "New" menu offers, acting on the folder
66
+ * currently open.
67
+ *
68
+ * Renders no wrapper — it finds the scrolling column and listens there, so the
69
+ * hit area is the whole column including the padding below the list.
70
+ *
71
+ * Deliberately background-only. Right-clicking an asset, a folder or a table
72
+ * row is left alone — those carry `data-native-context-menu` and keep the
73
+ * browser's menu (which is what you want over a thumbnail or a filename).
74
+ */ const MainAreaContextMenu = ({ onCreateFolder, onImportFiles, onImportFromUrl, disabled })=>{
75
+ const { formatMessage } = reactIntl.useIntl();
76
+ const [position, setPosition] = React.useState(null);
77
+ const [locator, setLocator] = React.useState(null);
78
+ const anchorRef = React.useCallback((node)=>setLocator(node), []);
79
+ React.useEffect(()=>{
80
+ const container = locator?.closest(SCROLL_ROOT_SELECTOR);
81
+ if (!container || disabled) {
82
+ return;
83
+ }
84
+ const handleContextMenu = (event)=>{
85
+ if (!(event.target instanceof Element)) {
86
+ return;
87
+ }
88
+ if (event.target.closest(NATIVE_CONTEXT_MENU_SELECTOR)) {
89
+ return;
90
+ }
91
+ event.preventDefault();
92
+ // A right-click while the menu is open reaches Radix's dismiss listener
93
+ // first, which closes it; re-anchoring here reopens it under the new
94
+ // cursor rather than leaving the user with a menu that just vanished.
95
+ setPosition({
96
+ x: event.clientX,
97
+ y: event.clientY
98
+ });
99
+ };
100
+ container.addEventListener('contextmenu', handleContextMenu);
101
+ return ()=>container.removeEventListener('contextmenu', handleContextMenu);
102
+ }, [
103
+ locator,
104
+ disabled
105
+ ]);
106
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
107
+ children: [
108
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
109
+ ref: anchorRef,
110
+ style: LOCATOR_STYLE,
111
+ "aria-hidden": true
112
+ }),
113
+ !disabled && /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Menu.Root, {
114
+ modal: false,
115
+ open: position !== null,
116
+ onOpenChange: (open)=>{
117
+ if (!open) {
118
+ setPosition(null);
119
+ }
120
+ },
121
+ children: [
122
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Trigger, {
123
+ tabIndex: -1,
124
+ // No visible content, so the name has to come from `aria-label` —
125
+ // the trigger's `label` prop renders as button text, which would
126
+ // defeat the point of an invisible anchor. Radix points the menu's
127
+ // `aria-labelledby` at this element, so it names the menu too.
128
+ endIcon: null,
129
+ "aria-label": formatMessage({
130
+ id: translations.getTranslationKey('list.context-menu.label'),
131
+ defaultMessage: 'Media library actions'
132
+ }),
133
+ style: {
134
+ ...CURSOR_ANCHOR_STYLE,
135
+ top: position?.y ?? 0,
136
+ left: position?.x ?? 0
137
+ }
138
+ }),
139
+ /*#__PURE__*/ jsxRuntime.jsxs(ActionsMenuContent.ActionsMenuContent, {
140
+ popoverPlacement: "bottom-start",
141
+ zIndex: 2,
142
+ minWidth: "22rem",
143
+ // The anchor is invisible and sits wherever the cursor was, so
144
+ // handing focus back to it on close would be a focus ring nobody can
145
+ // see. Let it fall to the body instead.
146
+ onCloseAutoFocus: (event)=>event.preventDefault(),
147
+ children: [
148
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
149
+ onSelect: onCreateFolder,
150
+ startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Folder, {}),
151
+ children: formatMessage({
152
+ id: translations.getTranslationKey('folder.create.title'),
153
+ defaultMessage: 'New folder'
154
+ })
155
+ }),
156
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
157
+ onSelect: onImportFiles,
158
+ startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Files, {}),
159
+ children: formatMessage({
160
+ id: translations.getTranslationKey('import-files'),
161
+ defaultMessage: 'File upload'
162
+ })
163
+ }),
164
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
165
+ onSelect: onImportFromUrl,
166
+ startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Link, {}),
167
+ children: formatMessage({
168
+ id: translations.getTranslationKey('import-from-url'),
169
+ defaultMessage: 'File upload from URL'
170
+ })
171
+ })
172
+ ]
173
+ })
174
+ ]
175
+ })
176
+ ]
177
+ });
178
+ };
179
+
180
+ exports.MainAreaContextMenu = MainAreaContextMenu;
181
+ //# sourceMappingURL=MainAreaContextMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MainAreaContextMenu.js","sources":["../../../../../../admin/src/future/pages/Assets/components/MainAreaContextMenu.tsx"],"sourcesContent":["import { useCallback, useEffect, useState, type CSSProperties } from 'react';\n\nimport { Menu } from '@strapi/design-system';\nimport { Files, Folder as FolderIcon, Link } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\n\n/**\n * The admin layout marks the element that scrolls the main column. Listening on\n * it rather than a wrapper of our own is what makes the whole column part of the\n * hit area: it carries a responsive `padding-bottom` (16 / 24 / 40px) that no\n * descendant can cover, and that strip is exactly where a right-click \"below the\n * list\" lands.\n */\nconst SCROLL_ROOT_SELECTOR = '[data-strapi-main-content]';\n\n/**\n * Subtrees that keep the browser's own context menu instead of opening the\n * create menu.\n *\n * `data-native-context-menu` is the explicit opt-out carried by the list items\n * themselves (asset cards, folder cards, table rows) and by the bulk actions\n * bar — right-clicking one of those must behave exactly as it does today. The\n * rest are the generic cases where the native menu is the useful one: links,\n * buttons and anything the user can type into or select text in.\n *\n * `thead` covers the table's header row, which is chrome rather than empty\n * background even though it carries no `data-native-context-menu` item.\n */\nconst NATIVE_CONTEXT_MENU_SELECTOR = [\n '[data-native-context-menu]',\n 'thead',\n 'a',\n 'button',\n 'input',\n 'textarea',\n 'select',\n '[contenteditable=\"true\"]',\n].join(', ');\n\n/**\n * The menu is anchored to a zero-sized element parked at the cursor, because\n * the design system's `Menu` is a dropdown: it positions its content against a\n * trigger, and there is no real trigger for a right-click on empty space.\n *\n * Inline styles rather than a `styled` wrapper — the trigger renders a design\n * system `Button`, and losing the specificity race with its own class would put\n * a stray button on the page.\n */\nconst CURSOR_ANCHOR_STYLE: CSSProperties = {\n position: 'fixed',\n width: 0,\n height: 0,\n minWidth: 0,\n minHeight: 0,\n padding: 0,\n border: 0,\n opacity: 0,\n overflow: 'hidden',\n pointerEvents: 'none',\n};\n\nconst LOCATOR_STYLE: CSSProperties = { height: 0 };\n\ninterface CursorPosition {\n x: number;\n y: number;\n}\n\ninterface MainAreaContextMenuProps {\n /** Opens the \"new folder\" dialog in the folder currently on screen. */\n onCreateFolder: () => void;\n /** Opens the native file picker — same entry point as the header \"New\" menu. */\n onImportFiles: () => void;\n /** Opens the \"import from URL\" dialog. */\n onImportFromUrl: () => void;\n /**\n * RBAC gate — without `assets.create` there is nothing to offer, so the\n * right-click falls through to the browser. Required (not defaulted) so a\n * permission gate can't silently regress to permissive.\n */\n disabled: boolean;\n}\n\n/**\n * Drive/Dropbox-style right-click on the empty parts of the assets area: the\n * same creation actions the header \"New\" menu offers, acting on the folder\n * currently open.\n *\n * Renders no wrapper — it finds the scrolling column and listens there, so the\n * hit area is the whole column including the padding below the list.\n *\n * Deliberately background-only. Right-clicking an asset, a folder or a table\n * row is left alone — those carry `data-native-context-menu` and keep the\n * browser's menu (which is what you want over a thumbnail or a filename).\n */\nexport const MainAreaContextMenu = ({\n onCreateFolder,\n onImportFiles,\n onImportFromUrl,\n disabled,\n}: MainAreaContextMenuProps) => {\n const { formatMessage } = useIntl();\n const [position, setPosition] = useState<CursorPosition | null>(null);\n const [locator, setLocator] = useState<HTMLElement | null>(null);\n\n const anchorRef = useCallback((node: HTMLElement | null) => setLocator(node), []);\n\n useEffect(() => {\n const container = locator?.closest<HTMLElement>(SCROLL_ROOT_SELECTOR);\n\n if (!container || disabled) {\n return;\n }\n\n const handleContextMenu = (event: MouseEvent) => {\n if (!(event.target instanceof Element)) {\n return;\n }\n\n if (event.target.closest(NATIVE_CONTEXT_MENU_SELECTOR)) {\n return;\n }\n\n event.preventDefault();\n // A right-click while the menu is open reaches Radix's dismiss listener\n // first, which closes it; re-anchoring here reopens it under the new\n // cursor rather than leaving the user with a menu that just vanished.\n setPosition({ x: event.clientX, y: event.clientY });\n };\n\n container.addEventListener('contextmenu', handleContextMenu);\n\n return () => container.removeEventListener('contextmenu', handleContextMenu);\n }, [locator, disabled]);\n\n return (\n <>\n <div ref={anchorRef} style={LOCATOR_STYLE} aria-hidden />\n {/* Non-modal, like the row-level menus: a right-click elsewhere is both\n \"close this\" and \"open that\", which a modal layer would swallow.\n Skipped entirely without the permission — the anchor is a real\n (if invisible) button, and one that can never open is noise in the\n accessibility tree. */}\n {!disabled && (\n <Menu.Root\n modal={false}\n open={position !== null}\n onOpenChange={(open) => {\n if (!open) {\n setPosition(null);\n }\n }}\n >\n <Menu.Trigger\n tabIndex={-1}\n // No visible content, so the name has to come from `aria-label` —\n // the trigger's `label` prop renders as button text, which would\n // defeat the point of an invisible anchor. Radix points the menu's\n // `aria-labelledby` at this element, so it names the menu too.\n endIcon={null}\n aria-label={formatMessage({\n id: getTranslationKey('list.context-menu.label'),\n defaultMessage: 'Media library actions',\n })}\n style={{ ...CURSOR_ANCHOR_STYLE, top: position?.y ?? 0, left: position?.x ?? 0 }}\n />\n <ActionsMenuContent\n popoverPlacement=\"bottom-start\"\n zIndex={2}\n minWidth=\"22rem\"\n // The anchor is invisible and sits wherever the cursor was, so\n // handing focus back to it on close would be a focus ring nobody can\n // see. Let it fall to the body instead.\n onCloseAutoFocus={(event) => event.preventDefault()}\n >\n <Menu.Item onSelect={onCreateFolder} startIcon={<FolderIcon />}>\n {formatMessage({\n id: getTranslationKey('folder.create.title'),\n defaultMessage: 'New folder',\n })}\n </Menu.Item>\n <Menu.Item onSelect={onImportFiles} startIcon={<Files />}>\n {formatMessage({\n id: getTranslationKey('import-files'),\n defaultMessage: 'File upload',\n })}\n </Menu.Item>\n <Menu.Item onSelect={onImportFromUrl} startIcon={<Link />}>\n {formatMessage({\n id: getTranslationKey('import-from-url'),\n defaultMessage: 'File upload from URL',\n })}\n </Menu.Item>\n </ActionsMenuContent>\n </Menu.Root>\n )}\n </>\n );\n};\n"],"names":["SCROLL_ROOT_SELECTOR","NATIVE_CONTEXT_MENU_SELECTOR","join","CURSOR_ANCHOR_STYLE","position","width","height","minWidth","minHeight","padding","border","opacity","overflow","pointerEvents","LOCATOR_STYLE","MainAreaContextMenu","onCreateFolder","onImportFiles","onImportFromUrl","disabled","formatMessage","useIntl","setPosition","useState","locator","setLocator","anchorRef","useCallback","node","useEffect","container","closest","handleContextMenu","event","target","Element","preventDefault","x","clientX","y","clientY","addEventListener","removeEventListener","_jsxs","_Fragment","_jsx","div","ref","style","aria-hidden","Menu","Root","modal","open","onOpenChange","Trigger","tabIndex","endIcon","aria-label","id","getTranslationKey","defaultMessage","top","left","ActionsMenuContent","popoverPlacement","zIndex","onCloseAutoFocus","Item","onSelect","startIcon","FolderIcon","Files","Link"],"mappings":"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"}