@strapi/upload 5.56.0 → 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 (208) hide show
  1. package/dist/admin/hooks/useTracking.js +2 -8
  2. package/dist/admin/hooks/useTracking.js.map +1 -1
  3. package/dist/admin/hooks/useTracking.mjs +3 -8
  4. package/dist/admin/hooks/useTracking.mjs.map +1 -1
  5. package/dist/admin/legacy/hooks/useTracking.js +3 -1
  6. package/dist/admin/legacy/hooks/useTracking.js.map +1 -1
  7. package/dist/admin/legacy/hooks/useTracking.mjs +3 -1
  8. package/dist/admin/legacy/hooks/useTracking.mjs.map +1 -1
  9. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js +2 -1
  10. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -1
  11. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs +2 -1
  12. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -1
  13. package/dist/admin/legacy/pages/App/MediaLibrary.js +2 -1
  14. package/dist/admin/legacy/pages/App/MediaLibrary.js.map +1 -1
  15. package/dist/admin/legacy/pages/App/MediaLibrary.mjs +2 -1
  16. package/dist/admin/legacy/pages/App/MediaLibrary.mjs.map +1 -1
  17. package/dist/admin/pages/Assets/AssetsPage.js +24 -12
  18. package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
  19. package/dist/admin/pages/Assets/AssetsPage.mjs +25 -13
  20. package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
  21. package/dist/admin/pages/Assets/components/AssetActions.js +326 -0
  22. package/dist/admin/pages/Assets/components/AssetActions.js.map +1 -0
  23. package/dist/admin/pages/Assets/components/AssetActions.mjs +324 -0
  24. package/dist/admin/pages/Assets/components/AssetActions.mjs.map +1 -0
  25. package/dist/admin/pages/Assets/components/AssetActionsMenu.js +28 -309
  26. package/dist/admin/pages/Assets/components/AssetActionsMenu.js.map +1 -1
  27. package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs +31 -312
  28. package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
  29. package/dist/admin/pages/Assets/components/AssetContextMenu.js +79 -0
  30. package/dist/admin/pages/Assets/components/AssetContextMenu.js.map +1 -0
  31. package/dist/admin/pages/Assets/components/AssetContextMenu.mjs +77 -0
  32. package/dist/admin/pages/Assets/components/AssetContextMenu.mjs.map +1 -0
  33. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js +87 -5
  34. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  35. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +89 -7
  36. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  37. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +3 -3
  38. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  39. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +3 -3
  40. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  41. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js +62 -5
  42. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js.map +1 -1
  43. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs +60 -6
  44. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs.map +1 -1
  45. package/dist/admin/pages/Assets/components/AssetsGrid.js +27 -4
  46. package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
  47. package/dist/admin/pages/Assets/components/AssetsGrid.mjs +27 -4
  48. package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  49. package/dist/admin/pages/Assets/components/AssetsTable.js +27 -4
  50. package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
  51. package/dist/admin/pages/Assets/components/AssetsTable.mjs +27 -4
  52. package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
  53. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js +77 -0
  54. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js.map +1 -0
  55. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs +75 -0
  56. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs.map +1 -0
  57. package/dist/admin/pages/Assets/components/FolderActions.js +139 -0
  58. package/dist/admin/pages/Assets/components/FolderActions.js.map +1 -0
  59. package/dist/admin/pages/Assets/components/FolderActions.mjs +137 -0
  60. package/dist/admin/pages/Assets/components/FolderActions.mjs.map +1 -0
  61. package/dist/admin/pages/Assets/components/FolderActionsMenu.js +25 -119
  62. package/dist/admin/pages/Assets/components/FolderActionsMenu.js.map +1 -1
  63. package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs +27 -121
  64. package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs.map +1 -1
  65. package/dist/admin/pages/Assets/components/FolderContextMenu.js +67 -0
  66. package/dist/admin/pages/Assets/components/FolderContextMenu.js.map +1 -0
  67. package/dist/admin/pages/Assets/components/FolderContextMenu.mjs +65 -0
  68. package/dist/admin/pages/Assets/components/FolderContextMenu.mjs.map +1 -0
  69. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js +139 -45
  70. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  71. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs +140 -47
  72. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  73. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js +115 -0
  74. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js.map +1 -0
  75. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs +113 -0
  76. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs.map +1 -0
  77. package/dist/admin/pages/Assets/components/ItemContextMenu.js +125 -0
  78. package/dist/admin/pages/Assets/components/ItemContextMenu.js.map +1 -0
  79. package/dist/admin/pages/Assets/components/ItemContextMenu.mjs +122 -0
  80. package/dist/admin/pages/Assets/components/ItemContextMenu.mjs.map +1 -0
  81. package/dist/admin/pages/Assets/components/MainAreaContextMenu.js +88 -63
  82. package/dist/admin/pages/Assets/components/MainAreaContextMenu.js.map +1 -1
  83. package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs +88 -63
  84. package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -1
  85. package/dist/admin/pages/Assets/components/SelectionActions.js +111 -0
  86. package/dist/admin/pages/Assets/components/SelectionActions.js.map +1 -0
  87. package/dist/admin/pages/Assets/components/SelectionActions.mjs +109 -0
  88. package/dist/admin/pages/Assets/components/SelectionActions.mjs.map +1 -0
  89. package/dist/admin/pages/Assets/components/SelectionContextMenu.js +82 -0
  90. package/dist/admin/pages/Assets/components/SelectionContextMenu.js.map +1 -0
  91. package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs +80 -0
  92. package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs.map +1 -0
  93. package/dist/admin/pages/Assets/hooks/useAssetSelection.js +10 -0
  94. package/dist/admin/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  95. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs +10 -0
  96. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  97. package/dist/admin/pages/SettingsPage/SettingsPage.js +8 -1
  98. package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
  99. package/dist/admin/pages/SettingsPage/SettingsPage.mjs +8 -1
  100. package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
  101. package/dist/admin/src/hooks/useTracking.d.ts +0 -7
  102. package/dist/admin/src/pages/Assets/components/AssetActions.d.ts +70 -0
  103. package/dist/admin/src/pages/Assets/components/AssetActionsMenu.d.ts +5 -14
  104. package/dist/admin/src/pages/Assets/components/AssetContextMenu.d.ts +27 -0
  105. package/dist/admin/src/pages/Assets/components/AssetDetails/useCropImg.d.ts +16 -0
  106. package/dist/admin/src/pages/Assets/components/CursorAnchoredMenu.d.ts +32 -0
  107. package/dist/admin/src/pages/Assets/components/FolderActions.d.ts +48 -0
  108. package/dist/admin/src/pages/Assets/components/FolderActionsMenu.d.ts +4 -8
  109. package/dist/admin/src/pages/Assets/components/FolderContextMenu.d.ts +21 -0
  110. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTree.d.ts +5 -1
  111. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTreeRowMenu.d.ts +25 -0
  112. package/dist/admin/src/pages/Assets/components/ItemContextMenu.d.ts +53 -0
  113. package/dist/admin/src/pages/Assets/components/MainAreaContextMenu.d.ts +15 -1
  114. package/dist/admin/src/pages/Assets/components/SelectionActions.d.ts +40 -0
  115. package/dist/admin/src/pages/Assets/components/SelectionContextMenu.d.ts +25 -0
  116. package/dist/admin/src/pages/Assets/hooks/useAssetSelection.d.ts +5 -0
  117. package/dist/admin/src/utils/mediaLibraryVersion.d.ts +18 -0
  118. package/dist/admin/translations/en.json.js +8 -3
  119. package/dist/admin/translations/en.json.js.map +1 -1
  120. package/dist/admin/translations/en.json.mjs +8 -3
  121. package/dist/admin/translations/en.json.mjs.map +1 -1
  122. package/dist/admin/utils/mediaLibraryVersion.js +24 -0
  123. package/dist/admin/utils/mediaLibraryVersion.js.map +1 -0
  124. package/dist/admin/utils/mediaLibraryVersion.mjs +20 -0
  125. package/dist/admin/utils/mediaLibraryVersion.mjs.map +1 -0
  126. package/dist/server/controllers/admin-file.js +2 -2
  127. package/dist/server/controllers/admin-file.js.map +1 -1
  128. package/dist/server/controllers/admin-file.mjs +2 -2
  129. package/dist/server/controllers/admin-file.mjs.map +1 -1
  130. package/dist/server/controllers/admin-folder.js +5 -5
  131. package/dist/server/controllers/admin-folder.js.map +1 -1
  132. package/dist/server/controllers/admin-folder.mjs +5 -5
  133. package/dist/server/controllers/admin-folder.mjs.map +1 -1
  134. package/dist/server/controllers/content-api.js +30 -7
  135. package/dist/server/controllers/content-api.js.map +1 -1
  136. package/dist/server/controllers/content-api.mjs +30 -7
  137. package/dist/server/controllers/content-api.mjs.map +1 -1
  138. package/dist/server/controllers/validation/admin/folder-file.js +4 -4
  139. package/dist/server/controllers/validation/admin/folder-file.js.map +1 -1
  140. package/dist/server/controllers/validation/admin/folder-file.mjs +2 -2
  141. package/dist/server/controllers/validation/admin/folder-file.mjs.map +1 -1
  142. package/dist/server/controllers/validation/admin/folder.js +3 -4
  143. package/dist/server/controllers/validation/admin/folder.js.map +1 -1
  144. package/dist/server/controllers/validation/admin/folder.mjs +3 -4
  145. package/dist/server/controllers/validation/admin/folder.mjs.map +1 -1
  146. package/dist/server/controllers/validation/admin/upload.js +1 -2
  147. package/dist/server/controllers/validation/admin/upload.js.map +1 -1
  148. package/dist/server/controllers/validation/admin/upload.mjs +1 -2
  149. package/dist/server/controllers/validation/admin/upload.mjs.map +1 -1
  150. package/dist/server/controllers/validation/admin/utils.js +1 -2
  151. package/dist/server/controllers/validation/admin/utils.js.map +1 -1
  152. package/dist/server/controllers/validation/admin/utils.mjs +1 -2
  153. package/dist/server/controllers/validation/admin/utils.mjs.map +1 -1
  154. package/dist/server/migrations/unsign-richtext-and-blocks-urls.js +2 -2
  155. package/dist/server/migrations/unsign-richtext-and-blocks-urls.js.map +1 -1
  156. package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs +1 -1
  157. package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs.map +1 -1
  158. package/dist/server/routes/content-api.js +3 -3
  159. package/dist/server/routes/content-api.js.map +1 -1
  160. package/dist/server/routes/content-api.mjs +3 -3
  161. package/dist/server/routes/content-api.mjs.map +1 -1
  162. package/dist/server/routes/validation/upload.js +8 -0
  163. package/dist/server/routes/validation/upload.js.map +1 -1
  164. package/dist/server/routes/validation/upload.mjs +8 -0
  165. package/dist/server/routes/validation/upload.mjs.map +1 -1
  166. package/dist/server/services/api-upload-folder.js +3 -3
  167. package/dist/server/services/api-upload-folder.js.map +1 -1
  168. package/dist/server/services/api-upload-folder.mjs +3 -3
  169. package/dist/server/services/api-upload-folder.mjs.map +1 -1
  170. package/dist/server/services/extensions/utils.js +19 -15
  171. package/dist/server/services/extensions/utils.js.map +1 -1
  172. package/dist/server/services/extensions/utils.mjs +19 -15
  173. package/dist/server/services/extensions/utils.mjs.map +1 -1
  174. package/dist/server/services/file.js +2 -2
  175. package/dist/server/services/file.js.map +1 -1
  176. package/dist/server/services/file.mjs +1 -1
  177. package/dist/server/services/file.mjs.map +1 -1
  178. package/dist/server/services/folder.js +5 -5
  179. package/dist/server/services/folder.js.map +1 -1
  180. package/dist/server/services/folder.mjs +5 -5
  181. package/dist/server/services/folder.mjs.map +1 -1
  182. package/dist/server/services/provider.js +3 -4
  183. package/dist/server/services/provider.js.map +1 -1
  184. package/dist/server/services/provider.mjs +3 -4
  185. package/dist/server/services/provider.mjs.map +1 -1
  186. package/dist/server/services/upload.js +5 -6
  187. package/dist/server/services/upload.js.map +1 -1
  188. package/dist/server/services/upload.mjs +4 -5
  189. package/dist/server/services/upload.mjs.map +1 -1
  190. package/dist/server/services/weekly-metrics.js +2 -2
  191. package/dist/server/services/weekly-metrics.js.map +1 -1
  192. package/dist/server/services/weekly-metrics.mjs +2 -2
  193. package/dist/server/services/weekly-metrics.mjs.map +1 -1
  194. package/dist/server/src/controllers/admin-folder.d.ts.map +1 -1
  195. package/dist/server/src/controllers/content-api.d.ts.map +1 -1
  196. package/dist/server/src/controllers/validation/admin/folder.d.ts.map +1 -1
  197. package/dist/server/src/controllers/validation/admin/upload.d.ts.map +1 -1
  198. package/dist/server/src/controllers/validation/admin/utils.d.ts.map +1 -1
  199. package/dist/server/src/index.d.ts.map +1 -1
  200. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
  201. package/dist/server/src/routes/validation/upload.d.ts +4 -0
  202. package/dist/server/src/routes/validation/upload.d.ts.map +1 -1
  203. package/dist/server/src/services/extensions/utils.d.ts +33 -1
  204. package/dist/server/src/services/extensions/utils.d.ts.map +1 -1
  205. package/dist/server/src/services/index.d.ts.map +1 -1
  206. package/dist/server/src/services/provider.d.ts.map +1 -1
  207. package/dist/server/src/services/upload.d.ts.map +1 -1
  208. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"FolderTree.mjs","sources":["../../../../../../admin/src/pages/Assets/components/FolderTree/FolderTree.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\n\nimport { SubNav } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, IconButton, Loader, Typography } from '@strapi/design-system';\nimport { ChevronDown, Folder as FolderIcon, House } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { css, styled } from 'styled-components';\n\nimport { TruncatedText } from '../../../../components/TruncatedText';\nimport { useGetFolderStructureQuery } from '../../../../services/folders';\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { useAssetsDndOptional } from '../Dnd/AssetsDndProvider';\nimport { useFolderTreeDroppable } from '../Dnd/useFolderTreeDroppable';\n\nimport { useSpringLoadedExpand } from './useSpringLoadedExpand';\n\nimport type { FolderNode } from '../../../../../../shared/contracts/folders';\n\n/* -------------------------------------------------------------------------------------------------\n * RowButton — shared row styling aligned with admin SubNav.Link\n * -----------------------------------------------------------------------------------------------*/\n\nconst RowButton = styled.button<{\n $isActive: boolean;\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n width: 100%;\n min-height: 3.2rem;\n padding: ${({ theme }) => `${theme.spaces[1]} ${theme.spaces[2]}`};\n border: 0;\n background: ${({ $isActive, $isValidDropTarget, theme }) => {\n if ($isValidDropTarget) {\n return theme.colors.primary100;\n }\n\n return $isActive ? theme.colors.primary100 : 'transparent';\n }};\n color: ${({ $isActive, theme }) =>\n $isActive ? theme.colors.primary700 : theme.colors.neutral800};\n border-radius: ${({ theme }) => theme.borderRadius};\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'pointer';\n }};\n text-align: left;\n font: inherit;\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n\n &:hover {\n background: ${({ $isActive, $isValidDropTarget, theme }) => {\n if ($isValidDropTarget) {\n return theme.colors.primary100;\n }\n\n return $isActive ? theme.colors.primary100 : theme.colors.neutral100;\n }};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n`;\n\nconst TreeRow = styled(Flex)<{\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'default';\n }};\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n border-radius: ${({ theme }) => theme.borderRadius};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n background: ${theme.colors.primary100};\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * useExpandedFolders — local expand/collapse state\n * -----------------------------------------------------------------------------------------------*/\n\nconst findAncestorIds = (\n nodes: FolderNode[],\n targetId: number,\n trail: number[] = []\n): number[] | null => {\n for (const node of nodes) {\n if (node.id === targetId) {\n return trail;\n }\n\n if (node.children?.length) {\n const nextTrail = node.id != null ? [...trail, node.id] : trail;\n const found = findAncestorIds(node.children, targetId, nextTrail);\n if (found !== null) {\n return found;\n }\n }\n }\n\n return null;\n};\n\nconst useExpandedFolders = (folderStructure: FolderNode[], currentFolderId: number | null) => {\n const [expandedIds, setExpandedIds] = useState<Set<number>>(() => new Set());\n\n useEffect(() => {\n if (currentFolderId == null) {\n return;\n }\n\n const ancestors = findAncestorIds(folderStructure, currentFolderId);\n if (!ancestors || ancestors.length === 0) {\n return;\n }\n\n setExpandedIds((prev) => {\n const next = new Set(prev);\n let changed = false;\n for (const id of ancestors) {\n if (!next.has(id)) {\n next.add(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [folderStructure, currentFolderId]);\n\n const toggleExpanded = useCallback((id: number) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n return next;\n });\n }, []);\n\n const expandFolder = useCallback((id: number) => {\n setExpandedIds((prev) => {\n if (prev.has(id)) {\n return prev;\n }\n\n const next = new Set(prev);\n next.add(id);\n return next;\n });\n }, []);\n\n const isExpanded = useCallback((id: number) => expandedIds.has(id), [expandedIds]);\n\n return { isExpanded, toggleExpanded, expandFolder };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NavList — unstyled list for tree rows\n * -----------------------------------------------------------------------------------------------*/\n\nconst NavList = styled.ul`\n list-style: none;\n margin: 0;\n padding: 0;\n\n /* Grid rather than block, and load-bearing despite rendering a single column:\n a minmax(0, 1fr) track contributes a minimum of 0, which is what stops each\n row propagating the min-content width of its own label.\n\n Folder names ellipsize, and text-overflow needs white-space: nowrap — so a\n label's min-content width is the entire name, and no box lays out narrower\n than its min-content. In block flow that floor travels up to the SubNav\n ScrollArea, which widens the rail and shows a horizontal scrollbar instead of\n truncating the name. Nesting makes it worse: the indent is spent before the\n label is measured, so shorter names trigger it the deeper you go.\n\n Measured in Chromium — dropping either declaration brings the scrollbar\n back, and neither min-width nor overflow on the row is a substitute. */\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTreeItem — single tree row (internal)\n * -----------------------------------------------------------------------------------------------*/\n\nconst INDENT_PER_LEVEL_REM = 1.6;\n\n/**\n * A leaf's chevron is present only to keep the folder names aligned, so it\n * should read as absent. The design system's disabled state is built for real\n * controls — a filled, bordered pill — which draws more attention than the\n * enabled chevron next to it. Doubled selector to outrank that rule.\n */\nconst ChevronButton = styled(IconButton)`\n &&[aria-disabled='true'] {\n background: transparent;\n border-color: transparent;\n opacity: 0.3;\n }\n`;\n\nconst RotatingChevron = styled(ChevronDown)<{ $expanded: boolean }>`\n transform: rotate(${({ $expanded }) => ($expanded ? '0deg' : '-90deg')});\n transition: transform 0.2s ease;\n`;\n\ninterface FolderTreeItemProps {\n node: FolderNode;\n level: number;\n currentFolderId: number | null;\n showActiveFolder: boolean;\n isExpanded: (id: number) => boolean;\n onToggle: (id: number) => void;\n onExpand: (id: number) => void;\n onSelect: (folderId: number) => void;\n isMovePending: boolean;\n}\n\ninterface FolderTreeItemInnerProps extends Omit<FolderTreeItemProps, 'node'> {\n id: number;\n name: string;\n folderChildren: FolderNode[];\n}\n\nconst FolderTreeItemInner = ({\n id,\n name,\n folderChildren,\n level,\n currentFolderId,\n showActiveFolder,\n isExpanded,\n onToggle,\n onExpand,\n onSelect,\n isMovePending,\n}: FolderTreeItemInnerProps) => {\n const { formatMessage } = useIntl();\n const hasChildren = folderChildren.length > 0;\n const isFolderExpanded = isExpanded(id);\n const isActive = showActiveFolder && currentFolderId === id;\n\n const {\n droppable: { setNodeRef },\n isOver,\n showValidDropHighlight,\n showInvalidDropCursor,\n } = useFolderTreeDroppable({ id, name });\n\n const handleExpand = useCallback(() => onExpand(id), [id, onExpand]);\n\n useSpringLoadedExpand({\n isOver,\n canExpand: hasChildren && !isFolderExpanded,\n onExpand: handleExpand,\n });\n\n // TODO: full `role=\"tree\"` + arrow-key treeview navigation before revamp GA\n // if an accessibility audit requires it (v1 is button rows only).\n return (\n <li>\n <TreeRow\n ref={setNodeRef}\n alignItems=\"center\"\n paddingLeft={`${level * INDENT_PER_LEVEL_REM}rem`}\n gap={1}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n >\n <ChevronButton\n label={\n hasChildren\n ? formatMessage(\n {\n id: getTranslationKey(\n isFolderExpanded ? 'sidebar.tree.collapse' : 'sidebar.tree.expand'\n ),\n defaultMessage: isFolderExpanded ? 'Collapse {name}' : 'Expand {name}',\n },\n { name }\n )\n : formatMessage(\n {\n id: getTranslationKey('sidebar.tree.no-subfolders'),\n defaultMessage: 'The folder {name} has no subfolders',\n },\n { name }\n )\n }\n disabled={!hasChildren}\n onClick={(event: React.MouseEvent) => {\n event.stopPropagation();\n onToggle(id);\n }}\n variant=\"ghost\"\n withTooltip={false}\n aria-expanded={hasChildren ? isFolderExpanded : undefined}\n >\n <RotatingChevron $expanded={isFolderExpanded} fill=\"neutral500\" />\n </ChevronButton>\n\n <Box flex=\"1\" minWidth={0}>\n <RowButton\n type=\"button\"\n $isActive={isActive}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isActive ? 'page' : undefined}\n onClick={() => onSelect(id)}\n data-testid={`folder-tree-node-${id}`}\n data-folder-id={id}\n >\n <TruncatedText variant=\"omega\" fontWeight={isActive ? 'semiBold' : 'regular'}>\n {name}\n </TruncatedText>\n </RowButton>\n </Box>\n </TreeRow>\n\n {hasChildren && isFolderExpanded && (\n <NavList>\n {folderChildren.map((child) => (\n <FolderTreeItem\n key={child.id ?? child.name}\n node={child}\n level={level + 1}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={onToggle}\n onExpand={onExpand}\n onSelect={onSelect}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </li>\n );\n};\n\nconst FolderTreeItem = ({ node, ...props }: FolderTreeItemProps) => {\n if (node.id == null) {\n return null;\n }\n\n return (\n <FolderTreeItemInner\n {...props}\n id={node.id}\n name={node.name ?? ''}\n folderChildren={node.children ?? []}\n />\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTree — public sidebar component\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FolderTreeProps {\n currentFolderId: number | null;\n /**\n * Set to `false` while a global asset search is active: the results span the\n * whole library, so highlighting one folder would misrepresent them.\n * */\n showActiveFolder?: boolean;\n onSelectFolder: (folderId: number | null) => void;\n}\n\n/**\n * Left-rail navigation for the Media Library. Fetches folder structure internally\n * and renders:\n *\n * 1. A \"Media library\" title\n * 2. A filter input that prunes the tree to matching destinations\n * 3. A \"Home\" entry that clears the folder query param\n * 4. A \"FOLDERS\" section header\n * 5. The folder tree itself\n *\n * The filter is purely local: it never touches the URL and never affects the\n * asset list, which has its own independent search in the content toolbar.\n *\n * Presentational with respect to routing — navigation is delegated to the parent\n * via `onSelectFolder` so the URL stays the single source of truth (see\n * `useFolderNavigation`).\n */\nexport const FolderTree = ({\n currentFolderId,\n showActiveFolder = true,\n onSelectFolder,\n}: FolderTreeProps) => {\n const { formatMessage } = useIntl();\n const { data: folderStructure = [], isLoading, isError } = useGetFolderStructureQuery();\n const { isExpanded, toggleExpanded, expandFolder } = useExpandedFolders(\n folderStructure,\n currentFolderId\n );\n const { isMovePending } = useAssetsDndOptional() ?? { isMovePending: false };\n\n const isHomeActive = showActiveFolder && currentFolderId == null;\n const homeLabel = formatMessage({\n id: getTranslationKey('sidebar.home'),\n defaultMessage: 'Home',\n });\n\n const {\n droppable: { setNodeRef: setHomeDropRef },\n showValidDropHighlight: showHomeValidDropHighlight,\n showInvalidDropCursor: showHomeInvalidDropCursor,\n } = useFolderTreeDroppable({ id: null, name: homeLabel });\n\n return (\n <SubNav.Main\n aria-label={formatMessage({\n id: getTranslationKey('sidebar.tree.aria-label'),\n defaultMessage: 'Media library folders',\n })}\n >\n <SubNav.Header\n label={formatMessage({\n id: getTranslationKey('sidebar.title'),\n defaultMessage: 'Media library',\n })}\n />\n\n <SubNav.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={1} padding={3}>\n <RowButton\n ref={setHomeDropRef}\n type=\"button\"\n $isActive={isHomeActive}\n $isValidDropTarget={showHomeValidDropHighlight}\n $isInvalidDropCursor={showHomeInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isHomeActive ? 'page' : undefined}\n onClick={() => onSelectFolder(null)}\n data-testid=\"folder-tree-home\"\n >\n <House aria-hidden width=\"1.6rem\" height=\"1.6rem\" />\n <Typography variant=\"omega\" fontWeight={isHomeActive ? 'semiBold' : 'regular'}>\n {homeLabel}\n </Typography>\n </RowButton>\n\n <Box marginTop={4}>\n <Flex\n alignItems=\"center\"\n gap={1}\n paddingTop={1}\n paddingBottom={1}\n paddingLeft={2}\n paddingRight={2}\n marginBottom={2}\n >\n <FolderIcon aria-hidden width=\"1.6rem\" height=\"1.6rem\" fill=\"neutral500\" />\n <Typography\n variant=\"sigma\"\n textColor=\"neutral600\"\n style={{ textTransform: 'uppercase' }}\n >\n {formatMessage({\n id: getTranslationKey('sidebar.folders'),\n defaultMessage: 'Folders',\n })}\n </Typography>\n </Flex>\n\n {isLoading ? (\n // TODO: revisit loading state before revamp GA\n <Flex justifyContent=\"center\" padding={1} paddingTop={2}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('sidebar.tree.loading'),\n defaultMessage: 'Loading folders...',\n })}\n </Loader>\n </Flex>\n ) : isError ? (\n // TODO: revisit error state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.error'),\n defaultMessage: 'Could not load folders.',\n })}\n </Typography>\n </Box>\n ) : folderStructure.length === 0 ? (\n // TODO: revisit empty state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.empty'),\n defaultMessage: 'No folders yet',\n })}\n </Typography>\n </Box>\n ) : (\n <NavList>\n {folderStructure.map((node) => (\n <FolderTreeItem\n key={node.id ?? node.name}\n node={node}\n level={0}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={toggleExpanded}\n onExpand={expandFolder}\n onSelect={onSelectFolder}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </Box>\n </Flex>\n </SubNav.Content>\n </SubNav.Main>\n );\n};\n"],"names":["RowButton","styled","button","theme","spaces","$isActive","$isValidDropTarget","colors","primary100","primary700","neutral800","borderRadius","$isMovePending","$isInvalidDropCursor","css","primary600","neutral100","TreeRow","Flex","findAncestorIds","nodes","targetId","trail","node","id","children","length","nextTrail","found","useExpandedFolders","folderStructure","currentFolderId","expandedIds","setExpandedIds","useState","Set","useEffect","ancestors","prev","next","changed","has","add","toggleExpanded","useCallback","delete","expandFolder","isExpanded","NavList","ul","INDENT_PER_LEVEL_REM","ChevronButton","IconButton","RotatingChevron","ChevronDown","$expanded","FolderTreeItemInner","name","folderChildren","level","showActiveFolder","onToggle","onExpand","onSelect","isMovePending","formatMessage","useIntl","hasChildren","isFolderExpanded","isActive","droppable","setNodeRef","isOver","showValidDropHighlight","showInvalidDropCursor","useFolderTreeDroppable","handleExpand","useSpringLoadedExpand","canExpand","_jsxs","li","ref","alignItems","paddingLeft","gap","_jsx","label","getTranslationKey","defaultMessage","disabled","onClick","event","stopPropagation","variant","withTooltip","aria-expanded","undefined","fill","Box","flex","minWidth","type","aria-current","data-testid","data-folder-id","TruncatedText","fontWeight","map","child","FolderTreeItem","props","FolderTree","onSelectFolder","data","isLoading","isError","useGetFolderStructureQuery","useAssetsDndOptional","isHomeActive","homeLabel","setHomeDropRef","showHomeValidDropHighlight","showHomeInvalidDropCursor","SubNav","Main","aria-label","Header","Content","direction","padding","House","aria-hidden","width","height","Typography","marginTop","paddingTop","paddingBottom","paddingRight","marginBottom","FolderIcon","textColor","style","textTransform","justifyContent","Loader"],"mappings":"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"}
1
+ {"version":3,"file":"FolderTree.mjs","sources":["../../../../../../admin/src/pages/Assets/components/FolderTree/FolderTree.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState, type ReactNode } from 'react';\n\nimport { SubNav } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, IconButton, Loader, Typography } from '@strapi/design-system';\nimport { ChevronDown, Folder as FolderIcon, House } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { css, styled } from 'styled-components';\n\nimport { TruncatedText } from '../../../../components/TruncatedText';\nimport { useGetFolderStructureQuery } from '../../../../services/folders';\nimport { isEventFromWithin } from '../../../../utils/isEventFromWithin';\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { useAssetsDndOptional } from '../Dnd/AssetsDndProvider';\nimport { useFolderTreeDroppable } from '../Dnd/useFolderTreeDroppable';\n\nimport { FolderTreeRowMenu } from './FolderTreeRowMenu';\nimport { useSpringLoadedExpand } from './useSpringLoadedExpand';\n\nimport type { FolderNode } from '../../../../../../shared/contracts/folders';\n\n/* -------------------------------------------------------------------------------------------------\n * RowButton — shared row styling aligned with admin SubNav.Link\n * -----------------------------------------------------------------------------------------------*/\n\nconst RowButton = styled.button<{\n $isActive: boolean;\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n display: flex;\n align-items: center;\n // Matches the row's own gap, so Home — the one row whose icon sits inside\n // this button rather than beside it — puts its label on the same line as a\n // folder's.\n gap: ${({ theme }) => theme.spaces[1]};\n width: 100%;\n min-height: 3.2rem;\n // No padding of its own: the row owns the inset, so the label lines up with\n // the icon boxes instead of being pushed in by a second layer of spacing.\n padding: 0;\n border: 0;\n // The surface — hover, active, drop target — is painted by the row behind\n // this, so it spans the chevron and the actions menu too, not just the label.\n background: transparent;\n color: ${({ $isActive, theme }) =>\n $isActive ? theme.colors.primary700 : theme.colors.neutral800};\n border-radius: ${({ theme }) => theme.borderRadius};\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'pointer';\n }};\n text-align: left;\n font: inherit;\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n`;\n\nconst TreeRow = styled(Flex)<{\n $isActive?: boolean;\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'default';\n }};\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ $isActive, theme }) => ($isActive ? theme.colors.primary100 : 'transparent')};\n\n // The whole row lights up, so pointing anywhere along it — chevron, label or\n // the actions trigger — reads as one target.\n &:hover {\n background: ${({ $isActive, theme }) =>\n $isActive ? theme.colors.primary100 : theme.colors.neutral100};\n }\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n background: ${theme.colors.primary100};\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n\n &:hover {\n background: ${theme.colors.primary100};\n }\n `}\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * useExpandedFolders — local expand/collapse state\n * -----------------------------------------------------------------------------------------------*/\n\nconst findAncestorIds = (\n nodes: FolderNode[],\n targetId: number,\n trail: number[] = []\n): number[] | null => {\n for (const node of nodes) {\n if (node.id === targetId) {\n return trail;\n }\n\n if (node.children?.length) {\n const nextTrail = node.id != null ? [...trail, node.id] : trail;\n const found = findAncestorIds(node.children, targetId, nextTrail);\n if (found !== null) {\n return found;\n }\n }\n }\n\n return null;\n};\n\nconst useExpandedFolders = (folderStructure: FolderNode[], currentFolderId: number | null) => {\n const [expandedIds, setExpandedIds] = useState<Set<number>>(() => new Set());\n\n useEffect(() => {\n if (currentFolderId == null) {\n return;\n }\n\n const ancestors = findAncestorIds(folderStructure, currentFolderId);\n if (!ancestors || ancestors.length === 0) {\n return;\n }\n\n setExpandedIds((prev) => {\n const next = new Set(prev);\n let changed = false;\n for (const id of ancestors) {\n if (!next.has(id)) {\n next.add(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [folderStructure, currentFolderId]);\n\n const toggleExpanded = useCallback((id: number) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n return next;\n });\n }, []);\n\n const expandFolder = useCallback((id: number) => {\n setExpandedIds((prev) => {\n if (prev.has(id)) {\n return prev;\n }\n\n const next = new Set(prev);\n next.add(id);\n return next;\n });\n }, []);\n\n const isExpanded = useCallback((id: number) => expandedIds.has(id), [expandedIds]);\n\n return { isExpanded, toggleExpanded, expandFolder };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NavList — unstyled list for tree rows\n * -----------------------------------------------------------------------------------------------*/\n\nconst NavList = styled.ul`\n list-style: none;\n margin: 0;\n padding: 0;\n\n /* Grid rather than block, and load-bearing despite rendering a single column:\n a minmax(0, 1fr) track contributes a minimum of 0, which is what stops each\n row propagating the min-content width of its own label.\n\n Folder names ellipsize, and text-overflow needs white-space: nowrap — so a\n label's min-content width is the entire name, and no box lays out narrower\n than its min-content. In block flow that floor travels up to the SubNav\n ScrollArea, which widens the rail and shows a horizontal scrollbar instead of\n truncating the name. Nesting makes it worse: the indent is spent before the\n label is measured, so shorter names trigger it the deeper you go.\n\n Measured in Chromium — dropping either declaration brings the scrollbar\n back, and neither min-width nor overflow on the row is a substitute. */\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTreeItem — single tree row (internal)\n * -----------------------------------------------------------------------------------------------*/\n\nconst INDENT_PER_LEVEL_REM = 1.6;\n\n/**\n * Breathing room between the row's highlight and the controls at either end.\n * Asymmetric on purpose: the chevron reads as part of the indent, while the\n * actions trigger sits closer to the edge so it stays out of the name's way.\n */\nconst ROW_INSET_LEFT_REM = 0.8;\nconst ROW_INSET_RIGHT_REM = 0.4;\n\n/**\n * Every icon in the rail occupies the same 24px box, whether or not it is a\n * control: the chevron and the actions trigger are buttons, the home and folder\n * marks are not. Sizing the box rather than the glyph is what keeps the labels\n * on one vertical line across rows that mix the two.\n */\nconst IconSlot = styled(Flex)`\n width: 2.4rem;\n height: 2.4rem;\n min-width: 2.4rem;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n`;\n\n/**\n * A leaf's chevron is present only to keep the folder names aligned, so it\n * should read as absent. The design system's disabled state is built for real\n * controls — a filled, bordered pill — which draws more attention than the\n * enabled chevron next to it. Doubled selector to outrank that rule.\n */\nconst ChevronButton = styled(IconButton)`\n // Square, so it and the actions trigger read as one pair of controls.\n && {\n width: 2.4rem;\n height: 2.4rem;\n min-width: 2.4rem;\n min-height: 2.4rem;\n padding: 0.4rem;\n }\n\n // The row paints its own hover, so the control needs a stronger one of its own\n // to read as a separate target sitting on top of it.\n &&:hover:not([aria-disabled='true']) {\n background: ${({ theme }) => theme.colors.primary200};\n }\n\n &&[aria-disabled='true'] {\n background: transparent;\n border-color: transparent;\n opacity: 0.3;\n }\n`;\n\nconst RotatingChevron = styled(ChevronDown)<{ $expanded: boolean }>`\n transform: rotate(${({ $expanded }) => ($expanded ? '0deg' : '-90deg')});\n transition: transform 0.2s ease;\n`;\n\ninterface FolderTreeItemProps {\n node: FolderNode;\n /** Its parent's id, so the actions can validate a move against the real parent. */\n parentId: number | null;\n level: number;\n currentFolderId: number | null;\n showActiveFolder: boolean;\n isExpanded: (id: number) => boolean;\n onToggle: (id: number) => void;\n onExpand: (id: number) => void;\n onSelect: (folderId: number) => void;\n isMovePending: boolean;\n}\n\ninterface FolderTreeItemInnerProps extends Omit<FolderTreeItemProps, 'node'> {\n id: number;\n name: string;\n folderChildren: FolderNode[];\n}\n\nconst FolderTreeItemInner = ({\n id,\n name,\n parentId,\n folderChildren,\n level,\n currentFolderId,\n showActiveFolder,\n isExpanded,\n onToggle,\n onExpand,\n onSelect,\n isMovePending,\n}: FolderTreeItemInnerProps) => {\n const { formatMessage } = useIntl();\n const hasChildren = folderChildren.length > 0;\n // A folder keeps its entry in the expanded set after its last subfolder is\n // moved away, so \"expanded\" has to mean \"expanded *and* still has something to\n // show\" — otherwise the chevron stays rotated on what is now a leaf.\n const isFolderExpanded = isExpanded(id) && hasChildren;\n const isActive = showActiveFolder && currentFolderId === id;\n\n const {\n droppable: { setNodeRef },\n isOver,\n showValidDropHighlight,\n showInvalidDropCursor,\n } = useFolderTreeDroppable({ id, name });\n\n const handleExpand = useCallback(() => onExpand(id), [id, onExpand]);\n\n // Tree rows carry no selection, so a right-click always means \"this folder\" —\n // none of the list's selection rules apply here.\n const [menuPosition, setMenuPosition] = useState<{ x: number; y: number } | null>(null);\n const rowButtonRef = useRef<HTMLButtonElement>(null);\n\n useSpringLoadedExpand({\n isOver,\n canExpand: hasChildren && !isFolderExpanded,\n onExpand: handleExpand,\n });\n\n // TODO: full `role=\"tree\"` + arrow-key treeview navigation before revamp GA\n // if an accessibility audit requires it (v1 is button rows only).\n return (\n <li>\n <TreeRow\n ref={setNodeRef}\n data-native-context-menu\n alignItems=\"center\"\n // Indent plus the row's own inset, so the chevron never sits flush\n // against the edge of the highlight at any depth.\n paddingLeft={`${level * INDENT_PER_LEVEL_REM + ROW_INSET_LEFT_REM}rem`}\n paddingRight={`${ROW_INSET_RIGHT_REM}rem`}\n gap={1}\n $isActive={isActive}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n onContextMenu={(event: React.MouseEvent) => {\n if (!isEventFromWithin(event)) {\n return;\n }\n\n event.preventDefault();\n setMenuPosition({ x: event.clientX, y: event.clientY });\n }}\n >\n <ChevronButton\n label={\n hasChildren\n ? formatMessage(\n {\n id: getTranslationKey(\n isFolderExpanded ? 'sidebar.tree.collapse' : 'sidebar.tree.expand'\n ),\n defaultMessage: isFolderExpanded ? 'Collapse {name}' : 'Expand {name}',\n },\n { name }\n )\n : formatMessage(\n {\n id: getTranslationKey('sidebar.tree.no-subfolders'),\n defaultMessage: 'The folder {name} has no subfolders',\n },\n { name }\n )\n }\n disabled={!hasChildren}\n onClick={(event: React.MouseEvent) => {\n event.stopPropagation();\n onToggle(id);\n }}\n variant=\"ghost\"\n withTooltip={false}\n aria-expanded={hasChildren ? isFolderExpanded : undefined}\n >\n <RotatingChevron $expanded={isFolderExpanded} fill=\"neutral500\" />\n </ChevronButton>\n\n <Box flex=\"1\" minWidth={0}>\n <RowButton\n ref={rowButtonRef}\n type=\"button\"\n $isActive={isActive}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isActive ? 'page' : undefined}\n onClick={() => onSelect(id)}\n data-testid={`folder-tree-node-${id}`}\n data-folder-id={id}\n >\n <TruncatedText variant=\"omega\" fontWeight={isActive ? 'semiBold' : 'regular'}>\n {name}\n </TruncatedText>\n </RowButton>\n </Box>\n\n <FolderTreeRowMenu\n folder={{ id, name }}\n parentId={parentId}\n menuPosition={menuPosition}\n returnFocusTo={rowButtonRef.current}\n onCloseMenu={() => setMenuPosition(null)}\n />\n </TreeRow>\n\n {hasChildren && isFolderExpanded && (\n <NavList>\n {folderChildren.map((child) => (\n <FolderTreeItem\n key={child.id ?? child.name}\n node={child}\n parentId={id}\n level={level + 1}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={onToggle}\n onExpand={onExpand}\n onSelect={onSelect}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </li>\n );\n};\n\nconst FolderTreeItem = ({ node, ...props }: FolderTreeItemProps) => {\n if (node.id == null) {\n return null;\n }\n\n return (\n <FolderTreeItemInner\n {...props}\n id={node.id}\n name={node.name ?? ''}\n folderChildren={node.children ?? []}\n />\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTree — public sidebar component\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FolderTreeProps {\n currentFolderId: number | null;\n /**\n * Set to `false` while a global asset search is active: the results span the\n * whole library, so highlighting one folder would misrepresent them.\n * */\n showActiveFolder?: boolean;\n onSelectFolder: (folderId: number | null) => void;\n /** Rendered inside the sidebar, which it can listen on through `FOLDER_TREE_ROOT_SELECTOR`. */\n backgroundContextMenu?: ReactNode;\n}\n\nexport const FOLDER_TREE_ROOT_SELECTOR = '[data-folder-tree-root]';\n\n/**\n * Left-rail navigation for the Media Library. Fetches folder structure internally\n * and renders:\n *\n * 1. A \"Media library\" title\n * 2. A filter input that prunes the tree to matching destinations\n * 3. A \"Home\" entry that clears the folder query param\n * 4. A \"FOLDERS\" section header\n * 5. The folder tree itself\n *\n * The filter is purely local: it never touches the URL and never affects the\n * asset list, which has its own independent search in the content toolbar.\n *\n * Presentational with respect to routing — navigation is delegated to the parent\n * via `onSelectFolder` so the URL stays the single source of truth (see\n * `useFolderNavigation`).\n */\nexport const FolderTree = ({\n currentFolderId,\n showActiveFolder = true,\n onSelectFolder,\n backgroundContextMenu,\n}: FolderTreeProps) => {\n const { formatMessage } = useIntl();\n const { data: folderStructure = [], isLoading, isError } = useGetFolderStructureQuery();\n const { isExpanded, toggleExpanded, expandFolder } = useExpandedFolders(\n folderStructure,\n currentFolderId\n );\n const { isMovePending } = useAssetsDndOptional() ?? { isMovePending: false };\n\n const isHomeActive = showActiveFolder && currentFolderId == null;\n const homeLabel = formatMessage({\n id: getTranslationKey('sidebar.home'),\n defaultMessage: 'Home',\n });\n\n const {\n droppable: { setNodeRef: setHomeDropRef },\n showValidDropHighlight: showHomeValidDropHighlight,\n showInvalidDropCursor: showHomeInvalidDropCursor,\n } = useFolderTreeDroppable({ id: null, name: homeLabel });\n\n return (\n <SubNav.Main\n data-folder-tree-root\n aria-label={formatMessage({\n id: getTranslationKey('sidebar.tree.aria-label'),\n defaultMessage: 'Media library folders',\n })}\n >\n {backgroundContextMenu}\n <SubNav.Header\n label={formatMessage({\n id: getTranslationKey('sidebar.title'),\n defaultMessage: 'Media library',\n })}\n />\n\n <SubNav.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" padding={3}>\n {/* Same row wrapper as a folder, so Home highlights across its whole\n width rather than only behind the label. */}\n <TreeRow\n ref={setHomeDropRef}\n data-native-context-menu\n alignItems=\"center\"\n // Level 0, so the indent contributes nothing — but the row's own\n // inset still applies, exactly as it does for a top-level folder.\n paddingLeft={`${ROW_INSET_LEFT_REM}rem`}\n paddingRight={`${ROW_INSET_RIGHT_REM}rem`}\n $isActive={isHomeActive}\n $isValidDropTarget={showHomeValidDropHighlight}\n $isInvalidDropCursor={showHomeInvalidDropCursor}\n $isMovePending={isMovePending}\n >\n <RowButton\n type=\"button\"\n $isActive={isHomeActive}\n $isValidDropTarget={showHomeValidDropHighlight}\n $isInvalidDropCursor={showHomeInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isHomeActive ? 'page' : undefined}\n onClick={() => onSelectFolder(null)}\n data-testid=\"folder-tree-home\"\n >\n <IconSlot>\n <House aria-hidden width=\"1.6rem\" height=\"1.6rem\" />\n </IconSlot>\n <Typography variant=\"omega\" fontWeight={isHomeActive ? 'semiBold' : 'regular'}>\n {homeLabel}\n </Typography>\n </RowButton>\n </TreeRow>\n\n <Box marginTop={4}>\n <Flex\n alignItems=\"center\"\n gap={1}\n paddingTop={1}\n paddingBottom={1}\n paddingLeft={2}\n paddingRight={2}\n >\n <IconSlot>\n <FolderIcon aria-hidden width=\"1.6rem\" height=\"1.6rem\" fill=\"neutral500\" />\n </IconSlot>\n <Typography\n variant=\"sigma\"\n textColor=\"neutral600\"\n style={{ textTransform: 'uppercase' }}\n >\n {formatMessage({\n id: getTranslationKey('sidebar.folders'),\n defaultMessage: 'Folders',\n })}\n </Typography>\n </Flex>\n\n {isLoading ? (\n // TODO: revisit loading state before revamp GA\n <Flex justifyContent=\"center\" padding={1} paddingTop={2}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('sidebar.tree.loading'),\n defaultMessage: 'Loading folders...',\n })}\n </Loader>\n </Flex>\n ) : isError ? (\n // TODO: revisit error state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.error'),\n defaultMessage: 'Could not load folders.',\n })}\n </Typography>\n </Box>\n ) : folderStructure.length === 0 ? (\n // TODO: revisit empty state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.empty'),\n defaultMessage: 'No folders yet',\n })}\n </Typography>\n </Box>\n ) : (\n <NavList>\n {folderStructure.map((node) => (\n <FolderTreeItem\n key={node.id ?? node.name}\n node={node}\n // Top of the tree — these sit at the library root.\n parentId={null}\n level={0}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={toggleExpanded}\n onExpand={expandFolder}\n onSelect={onSelectFolder}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </Box>\n </Flex>\n </SubNav.Content>\n </SubNav.Main>\n );\n};\n"],"names":["RowButton","styled","button","theme","spaces","$isActive","colors","primary700","neutral800","borderRadius","$isMovePending","$isInvalidDropCursor","$isValidDropTarget","css","primary600","TreeRow","Flex","primary100","neutral100","findAncestorIds","nodes","targetId","trail","node","id","children","length","nextTrail","found","useExpandedFolders","folderStructure","currentFolderId","expandedIds","setExpandedIds","useState","Set","useEffect","ancestors","prev","next","changed","has","add","toggleExpanded","useCallback","delete","expandFolder","isExpanded","NavList","ul","INDENT_PER_LEVEL_REM","ROW_INSET_LEFT_REM","ROW_INSET_RIGHT_REM","IconSlot","ChevronButton","IconButton","primary200","RotatingChevron","ChevronDown","$expanded","FolderTreeItemInner","name","parentId","folderChildren","level","showActiveFolder","onToggle","onExpand","onSelect","isMovePending","formatMessage","useIntl","hasChildren","isFolderExpanded","isActive","droppable","setNodeRef","isOver","showValidDropHighlight","showInvalidDropCursor","useFolderTreeDroppable","handleExpand","menuPosition","setMenuPosition","rowButtonRef","useRef","useSpringLoadedExpand","canExpand","_jsxs","li","ref","data-native-context-menu","alignItems","paddingLeft","paddingRight","gap","onContextMenu","event","isEventFromWithin","preventDefault","x","clientX","y","clientY","_jsx","label","getTranslationKey","defaultMessage","disabled","onClick","stopPropagation","variant","withTooltip","aria-expanded","undefined","fill","Box","flex","minWidth","type","aria-current","data-testid","data-folder-id","TruncatedText","fontWeight","FolderTreeRowMenu","folder","returnFocusTo","current","onCloseMenu","map","child","FolderTreeItem","props","FOLDER_TREE_ROOT_SELECTOR","FolderTree","onSelectFolder","backgroundContextMenu","data","isLoading","isError","useGetFolderStructureQuery","useAssetsDndOptional","isHomeActive","homeLabel","setHomeDropRef","showHomeValidDropHighlight","showHomeInvalidDropCursor","SubNav","Main","data-folder-tree-root","aria-label","Header","Content","direction","padding","House","aria-hidden","width","height","Typography","marginTop","paddingTop","paddingBottom","FolderIcon","textColor","style","textTransform","justifyContent","Loader"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var designSystem = require('@strapi/design-system');
5
+ var icons = require('@strapi/icons');
6
+ var reactIntl = require('react-intl');
7
+ var styledComponents = require('styled-components');
8
+ var translations = require('../../../../utils/translations.js');
9
+ var ActionsMenuContent = require('../ActionsMenuContent.js');
10
+ var CursorAnchoredMenu = require('../CursorAnchoredMenu.js');
11
+ var FolderActions = require('../FolderActions.js');
12
+
13
+ /**
14
+ * Hidden until the row is hovered or something inside it has focus, so the tree
15
+ * stays quiet at rest. Wraps the trigger rather than styling it: `Menu.Trigger`
16
+ * types its `tag` against the design system's own component, which a styled
17
+ * wrapper of it no longer satisfies.
18
+ *
19
+ * `:focus-within` keeps it on screen while its own menu is open, since the
20
+ * trigger holds focus for as long as the menu does.
21
+ */ const MenuSlot = styledComponents.styled.div`
22
+ opacity: 0;
23
+
24
+ li:hover > div > &,
25
+ &:focus-within,
26
+ &:has([data-state='open']) {
27
+ opacity: 1;
28
+ }
29
+
30
+ // Square, matching the chevron at the other end of the row. Descendant rather
31
+ // than child: Menu.Root renders no element today, but that is Radix's
32
+ // business, not something to depend on.
33
+ && button {
34
+ width: 2.4rem;
35
+ height: 2.4rem;
36
+ min-width: 2.4rem;
37
+ min-height: 2.4rem;
38
+ padding: 0.4rem;
39
+ }
40
+
41
+ // The row paints its own hover, so the trigger needs a stronger one of its own
42
+ // to read as a separate target sitting on top of it.
43
+ && button:hover,
44
+ && button[data-state='open'] {
45
+ background: ${({ theme })=>theme.colors.primary200};
46
+ }
47
+ `;
48
+ /**
49
+ * Folder actions on a tree row, from either the `•••` or a right-click.
50
+ *
51
+ * Both render the same `FolderActions`, minus Rename — renaming is a list
52
+ * affordance and the tree does not offer it. Unlike the list, a tree row has no
53
+ * selection, so a right-click always means the row it landed on.
54
+ *
55
+ * One `FolderActions` serves both triggers here rather than two instances, so
56
+ * the dialogs it owns are not duplicated per row.
57
+ */ const FolderTreeRowMenu = ({ folder, parentId, menuPosition, returnFocusTo, onCloseMenu })=>{
58
+ const { formatMessage } = reactIntl.useIntl();
59
+ return /*#__PURE__*/ jsxRuntime.jsx(FolderActions.FolderActions, {
60
+ folder: folder,
61
+ dragData: {
62
+ kind: 'folder',
63
+ id: folder.id,
64
+ name: folder.name,
65
+ parentId
66
+ },
67
+ showRename: false,
68
+ children: ({ items, dialogs })=>/*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
69
+ children: [
70
+ /*#__PURE__*/ jsxRuntime.jsx(MenuSlot, {
71
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Menu.Root, {
72
+ modal: false,
73
+ children: [
74
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Trigger, {
75
+ tag: designSystem.IconButton,
76
+ icon: /*#__PURE__*/ jsxRuntime.jsx(icons.More, {}),
77
+ variant: "ghost",
78
+ size: "S",
79
+ // The row itself is a button; keep the trigger's click off it.
80
+ onClick: (event)=>event.stopPropagation(),
81
+ label: formatMessage({
82
+ id: translations.getTranslationKey('sidebar.tree.actions'),
83
+ defaultMessage: 'Actions for {name}'
84
+ }, {
85
+ name: folder.name
86
+ })
87
+ }),
88
+ /*#__PURE__*/ jsxRuntime.jsx(ActionsMenuContent.ActionsMenuContent, {
89
+ popoverPlacement: "bottom-end",
90
+ zIndex: 2,
91
+ minWidth: "22rem",
92
+ children: items
93
+ })
94
+ ]
95
+ })
96
+ }),
97
+ menuPosition !== null && /*#__PURE__*/ jsxRuntime.jsx(CursorAnchoredMenu.CursorAnchoredMenu, {
98
+ position: menuPosition,
99
+ open: true,
100
+ label: formatMessage({
101
+ id: translations.getTranslationKey('list.folder.context-menu.label'),
102
+ defaultMessage: 'Folder actions'
103
+ }),
104
+ returnFocusTo: returnFocusTo,
105
+ onClose: onCloseMenu,
106
+ children: items
107
+ }),
108
+ dialogs
109
+ ]
110
+ })
111
+ });
112
+ };
113
+
114
+ exports.FolderTreeRowMenu = FolderTreeRowMenu;
115
+ //# sourceMappingURL=FolderTreeRowMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FolderTreeRowMenu.js","sources":["../../../../../../admin/src/pages/Assets/components/FolderTree/FolderTreeRowMenu.tsx"],"sourcesContent":["import { IconButton, Menu } from '@strapi/design-system';\nimport { More } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { ActionsMenuContent } from '../ActionsMenuContent';\nimport { CursorAnchoredMenu } from '../CursorAnchoredMenu';\nimport { FolderActions } from '../FolderActions';\n\nimport type { CursorPosition } from '../CursorAnchoredMenu';\n\n/**\n * Hidden until the row is hovered or something inside it has focus, so the tree\n * stays quiet at rest. Wraps the trigger rather than styling it: `Menu.Trigger`\n * types its `tag` against the design system's own component, which a styled\n * wrapper of it no longer satisfies.\n *\n * `:focus-within` keeps it on screen while its own menu is open, since the\n * trigger holds focus for as long as the menu does.\n */\nconst MenuSlot = styled.div`\n opacity: 0;\n\n li:hover > div > &,\n &:focus-within,\n &:has([data-state='open']) {\n opacity: 1;\n }\n\n // Square, matching the chevron at the other end of the row. Descendant rather\n // than child: Menu.Root renders no element today, but that is Radix's\n // business, not something to depend on.\n && button {\n width: 2.4rem;\n height: 2.4rem;\n min-width: 2.4rem;\n min-height: 2.4rem;\n padding: 0.4rem;\n }\n\n // The row paints its own hover, so the trigger needs a stronger one of its own\n // to read as a separate target sitting on top of it.\n && button:hover,\n && button[data-state='open'] {\n background: ${({ theme }) => theme.colors.primary200};\n }\n`;\n\ninterface FolderTreeRowMenuProps {\n folder: { id: number; name: string };\n /** Its parent's id, so a move validates against where it actually lives. */\n parentId: number | null;\n /** Set by the row's right-click; null when the menu is closed. */\n menuPosition: CursorPosition | null;\n returnFocusTo: HTMLElement | null;\n onCloseMenu: () => void;\n}\n\n/**\n * Folder actions on a tree row, from either the `•••` or a right-click.\n *\n * Both render the same `FolderActions`, minus Rename — renaming is a list\n * affordance and the tree does not offer it. Unlike the list, a tree row has no\n * selection, so a right-click always means the row it landed on.\n *\n * One `FolderActions` serves both triggers here rather than two instances, so\n * the dialogs it owns are not duplicated per row.\n */\nexport const FolderTreeRowMenu = ({\n folder,\n parentId,\n menuPosition,\n returnFocusTo,\n onCloseMenu,\n}: FolderTreeRowMenuProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <FolderActions\n folder={folder}\n dragData={{ kind: 'folder', id: folder.id, name: folder.name, parentId }}\n showRename={false}\n >\n {({ items, dialogs }) => (\n <>\n <MenuSlot>\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n size=\"S\"\n // The row itself is a button; keep the trigger's click off it.\n onClick={(event: React.MouseEvent) => event.stopPropagation()}\n label={formatMessage(\n {\n id: getTranslationKey('sidebar.tree.actions'),\n defaultMessage: 'Actions for {name}',\n },\n { name: folder.name }\n )}\n />\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {items}\n </ActionsMenuContent>\n </Menu.Root>\n </MenuSlot>\n\n {menuPosition !== null && (\n <CursorAnchoredMenu\n position={menuPosition}\n open\n label={formatMessage({\n id: getTranslationKey('list.folder.context-menu.label'),\n defaultMessage: 'Folder actions',\n })}\n returnFocusTo={returnFocusTo}\n onClose={onCloseMenu}\n >\n {items}\n </CursorAnchoredMenu>\n )}\n\n {dialogs}\n </>\n )}\n </FolderActions>\n );\n};\n"],"names":["MenuSlot","styled","div","theme","colors","primary200","FolderTreeRowMenu","folder","parentId","menuPosition","returnFocusTo","onCloseMenu","formatMessage","useIntl","_jsx","FolderActions","dragData","kind","id","name","showRename","items","dialogs","_jsxs","_Fragment","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","size","onClick","event","stopPropagation","label","getTranslationKey","defaultMessage","ActionsMenuContent","popoverPlacement","zIndex","minWidth","CursorAnchoredMenu","position","open","onClose"],"mappings":";;;;;;;;;;;;AAYA;;;;;;;;AAQC,IACD,MAAMA,QAAAA,GAAWC,uBAAAA,CAAOC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;gBAwBX,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC;;AAEzD,CAAC;AAYD;;;;;;;;;AASC,IACM,MAAMC,iBAAAA,GAAoB,CAAC,EAChCC,MAAM,EACNC,QAAQ,EACRC,YAAY,EACZC,aAAa,EACbC,WAAW,EACY,GAAA;IACvB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,qBACEC,cAAA,CAACC,2BAAAA,EAAAA;QACCR,MAAAA,EAAQA,MAAAA;QACRS,QAAAA,EAAU;YAAEC,IAAAA,EAAM,QAAA;AAAUC,YAAAA,EAAAA,EAAIX,OAAOW,EAAE;AAAEC,YAAAA,IAAAA,EAAMZ,OAAOY,IAAI;AAAEX,YAAAA;AAAS,SAAA;QACvEY,UAAAA,EAAY,KAAA;AAEX,QAAA,QAAA,EAAA,CAAC,EAAEC,KAAK,EAAEC,OAAO,EAAE,iBAClBC,eAAA,CAAAC,mBAAA,EAAA;;kCACEV,cAAA,CAACd,QAAAA,EAAAA;gDACCuB,eAAA,CAACE,kBAAKC,IAAI,EAAA;4BAACC,KAAAA,EAAO,KAAA;;AAChB,8CAAAb,cAAA,CAACW,kBAAKG,OAAO,EAAA;oCACXC,GAAAA,EAAKC,uBAAAA;AACLC,oCAAAA,IAAAA,gBAAMjB,cAAA,CAACkB,UAAAA,EAAAA,EAAAA,CAAAA;oCACPC,OAAAA,EAAQ,OAAA;oCACRC,IAAAA,EAAK,GAAA;;oCAELC,OAAAA,EAAS,CAACC,KAAAA,GAA4BA,KAAAA,CAAMC,eAAe,EAAA;AAC3DC,oCAAAA,KAAAA,EAAO1B,aAAAA,CACL;AACEM,wCAAAA,EAAAA,EAAIqB,8BAAAA,CAAkB,sBAAA,CAAA;wCACtBC,cAAAA,EAAgB;qCAClB,EACA;AAAErB,wCAAAA,IAAAA,EAAMZ,OAAOY;AAAK,qCAAA;;8CAGxBL,cAAA,CAAC2B,qCAAAA,EAAAA;oCAAmBC,gBAAAA,EAAiB,YAAA;oCAAaC,MAAAA,EAAQ,CAAA;oCAAGC,QAAAA,EAAS,OAAA;AACnEvB,oCAAAA,QAAAA,EAAAA;;;;;AAKNZ,oBAAAA,YAAAA,KAAiB,sBAChBK,cAAA,CAAC+B,qCAAAA,EAAAA;wBACCC,QAAAA,EAAUrC,YAAAA;wBACVsC,IAAI,EAAA,IAAA;AACJT,wBAAAA,KAAAA,EAAO1B,aAAAA,CAAc;AACnBM,4BAAAA,EAAAA,EAAIqB,8BAAAA,CAAkB,gCAAA,CAAA;4BACtBC,cAAAA,EAAgB;AAClB,yBAAA,CAAA;wBACA9B,aAAAA,EAAeA,aAAAA;wBACfsC,OAAAA,EAASrC,WAAAA;AAERU,wBAAAA,QAAAA,EAAAA;;AAIJC,oBAAAA;;;;AAKX;;;;"}
@@ -0,0 +1,113 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { Menu, IconButton } from '@strapi/design-system';
3
+ import { More } from '@strapi/icons';
4
+ import { useIntl } from 'react-intl';
5
+ import { styled } from 'styled-components';
6
+ import { getTranslationKey } from '../../../../utils/translations.mjs';
7
+ import { ActionsMenuContent } from '../ActionsMenuContent.mjs';
8
+ import { CursorAnchoredMenu } from '../CursorAnchoredMenu.mjs';
9
+ import { FolderActions } from '../FolderActions.mjs';
10
+
11
+ /**
12
+ * Hidden until the row is hovered or something inside it has focus, so the tree
13
+ * stays quiet at rest. Wraps the trigger rather than styling it: `Menu.Trigger`
14
+ * types its `tag` against the design system's own component, which a styled
15
+ * wrapper of it no longer satisfies.
16
+ *
17
+ * `:focus-within` keeps it on screen while its own menu is open, since the
18
+ * trigger holds focus for as long as the menu does.
19
+ */ const MenuSlot = styled.div`
20
+ opacity: 0;
21
+
22
+ li:hover > div > &,
23
+ &:focus-within,
24
+ &:has([data-state='open']) {
25
+ opacity: 1;
26
+ }
27
+
28
+ // Square, matching the chevron at the other end of the row. Descendant rather
29
+ // than child: Menu.Root renders no element today, but that is Radix's
30
+ // business, not something to depend on.
31
+ && button {
32
+ width: 2.4rem;
33
+ height: 2.4rem;
34
+ min-width: 2.4rem;
35
+ min-height: 2.4rem;
36
+ padding: 0.4rem;
37
+ }
38
+
39
+ // The row paints its own hover, so the trigger needs a stronger one of its own
40
+ // to read as a separate target sitting on top of it.
41
+ && button:hover,
42
+ && button[data-state='open'] {
43
+ background: ${({ theme })=>theme.colors.primary200};
44
+ }
45
+ `;
46
+ /**
47
+ * Folder actions on a tree row, from either the `•••` or a right-click.
48
+ *
49
+ * Both render the same `FolderActions`, minus Rename — renaming is a list
50
+ * affordance and the tree does not offer it. Unlike the list, a tree row has no
51
+ * selection, so a right-click always means the row it landed on.
52
+ *
53
+ * One `FolderActions` serves both triggers here rather than two instances, so
54
+ * the dialogs it owns are not duplicated per row.
55
+ */ const FolderTreeRowMenu = ({ folder, parentId, menuPosition, returnFocusTo, onCloseMenu })=>{
56
+ const { formatMessage } = useIntl();
57
+ return /*#__PURE__*/ jsx(FolderActions, {
58
+ folder: folder,
59
+ dragData: {
60
+ kind: 'folder',
61
+ id: folder.id,
62
+ name: folder.name,
63
+ parentId
64
+ },
65
+ showRename: false,
66
+ children: ({ items, dialogs })=>/*#__PURE__*/ jsxs(Fragment, {
67
+ children: [
68
+ /*#__PURE__*/ jsx(MenuSlot, {
69
+ children: /*#__PURE__*/ jsxs(Menu.Root, {
70
+ modal: false,
71
+ children: [
72
+ /*#__PURE__*/ jsx(Menu.Trigger, {
73
+ tag: IconButton,
74
+ icon: /*#__PURE__*/ jsx(More, {}),
75
+ variant: "ghost",
76
+ size: "S",
77
+ // The row itself is a button; keep the trigger's click off it.
78
+ onClick: (event)=>event.stopPropagation(),
79
+ label: formatMessage({
80
+ id: getTranslationKey('sidebar.tree.actions'),
81
+ defaultMessage: 'Actions for {name}'
82
+ }, {
83
+ name: folder.name
84
+ })
85
+ }),
86
+ /*#__PURE__*/ jsx(ActionsMenuContent, {
87
+ popoverPlacement: "bottom-end",
88
+ zIndex: 2,
89
+ minWidth: "22rem",
90
+ children: items
91
+ })
92
+ ]
93
+ })
94
+ }),
95
+ menuPosition !== null && /*#__PURE__*/ jsx(CursorAnchoredMenu, {
96
+ position: menuPosition,
97
+ open: true,
98
+ label: formatMessage({
99
+ id: getTranslationKey('list.folder.context-menu.label'),
100
+ defaultMessage: 'Folder actions'
101
+ }),
102
+ returnFocusTo: returnFocusTo,
103
+ onClose: onCloseMenu,
104
+ children: items
105
+ }),
106
+ dialogs
107
+ ]
108
+ })
109
+ });
110
+ };
111
+
112
+ export { FolderTreeRowMenu };
113
+ //# sourceMappingURL=FolderTreeRowMenu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FolderTreeRowMenu.mjs","sources":["../../../../../../admin/src/pages/Assets/components/FolderTree/FolderTreeRowMenu.tsx"],"sourcesContent":["import { IconButton, Menu } from '@strapi/design-system';\nimport { More } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { ActionsMenuContent } from '../ActionsMenuContent';\nimport { CursorAnchoredMenu } from '../CursorAnchoredMenu';\nimport { FolderActions } from '../FolderActions';\n\nimport type { CursorPosition } from '../CursorAnchoredMenu';\n\n/**\n * Hidden until the row is hovered or something inside it has focus, so the tree\n * stays quiet at rest. Wraps the trigger rather than styling it: `Menu.Trigger`\n * types its `tag` against the design system's own component, which a styled\n * wrapper of it no longer satisfies.\n *\n * `:focus-within` keeps it on screen while its own menu is open, since the\n * trigger holds focus for as long as the menu does.\n */\nconst MenuSlot = styled.div`\n opacity: 0;\n\n li:hover > div > &,\n &:focus-within,\n &:has([data-state='open']) {\n opacity: 1;\n }\n\n // Square, matching the chevron at the other end of the row. Descendant rather\n // than child: Menu.Root renders no element today, but that is Radix's\n // business, not something to depend on.\n && button {\n width: 2.4rem;\n height: 2.4rem;\n min-width: 2.4rem;\n min-height: 2.4rem;\n padding: 0.4rem;\n }\n\n // The row paints its own hover, so the trigger needs a stronger one of its own\n // to read as a separate target sitting on top of it.\n && button:hover,\n && button[data-state='open'] {\n background: ${({ theme }) => theme.colors.primary200};\n }\n`;\n\ninterface FolderTreeRowMenuProps {\n folder: { id: number; name: string };\n /** Its parent's id, so a move validates against where it actually lives. */\n parentId: number | null;\n /** Set by the row's right-click; null when the menu is closed. */\n menuPosition: CursorPosition | null;\n returnFocusTo: HTMLElement | null;\n onCloseMenu: () => void;\n}\n\n/**\n * Folder actions on a tree row, from either the `•••` or a right-click.\n *\n * Both render the same `FolderActions`, minus Rename — renaming is a list\n * affordance and the tree does not offer it. Unlike the list, a tree row has no\n * selection, so a right-click always means the row it landed on.\n *\n * One `FolderActions` serves both triggers here rather than two instances, so\n * the dialogs it owns are not duplicated per row.\n */\nexport const FolderTreeRowMenu = ({\n folder,\n parentId,\n menuPosition,\n returnFocusTo,\n onCloseMenu,\n}: FolderTreeRowMenuProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <FolderActions\n folder={folder}\n dragData={{ kind: 'folder', id: folder.id, name: folder.name, parentId }}\n showRename={false}\n >\n {({ items, dialogs }) => (\n <>\n <MenuSlot>\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n size=\"S\"\n // The row itself is a button; keep the trigger's click off it.\n onClick={(event: React.MouseEvent) => event.stopPropagation()}\n label={formatMessage(\n {\n id: getTranslationKey('sidebar.tree.actions'),\n defaultMessage: 'Actions for {name}',\n },\n { name: folder.name }\n )}\n />\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {items}\n </ActionsMenuContent>\n </Menu.Root>\n </MenuSlot>\n\n {menuPosition !== null && (\n <CursorAnchoredMenu\n position={menuPosition}\n open\n label={formatMessage({\n id: getTranslationKey('list.folder.context-menu.label'),\n defaultMessage: 'Folder actions',\n })}\n returnFocusTo={returnFocusTo}\n onClose={onCloseMenu}\n >\n {items}\n </CursorAnchoredMenu>\n )}\n\n {dialogs}\n </>\n )}\n </FolderActions>\n );\n};\n"],"names":["MenuSlot","styled","div","theme","colors","primary200","FolderTreeRowMenu","folder","parentId","menuPosition","returnFocusTo","onCloseMenu","formatMessage","useIntl","_jsx","FolderActions","dragData","kind","id","name","showRename","items","dialogs","_jsxs","_Fragment","Menu","Root","modal","Trigger","tag","IconButton","icon","More","variant","size","onClick","event","stopPropagation","label","getTranslationKey","defaultMessage","ActionsMenuContent","popoverPlacement","zIndex","minWidth","CursorAnchoredMenu","position","open","onClose"],"mappings":";;;;;;;;;;AAYA;;;;;;;;AAQC,IACD,MAAMA,QAAAA,GAAWC,MAAAA,CAAOC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;gBAwBX,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC;;AAEzD,CAAC;AAYD;;;;;;;;;AASC,IACM,MAAMC,iBAAAA,GAAoB,CAAC,EAChCC,MAAM,EACNC,QAAQ,EACRC,YAAY,EACZC,aAAa,EACbC,WAAW,EACY,GAAA;IACvB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,qBACEC,GAAA,CAACC,aAAAA,EAAAA;QACCR,MAAAA,EAAQA,MAAAA;QACRS,QAAAA,EAAU;YAAEC,IAAAA,EAAM,QAAA;AAAUC,YAAAA,EAAAA,EAAIX,OAAOW,EAAE;AAAEC,YAAAA,IAAAA,EAAMZ,OAAOY,IAAI;AAAEX,YAAAA;AAAS,SAAA;QACvEY,UAAAA,EAAY,KAAA;AAEX,QAAA,QAAA,EAAA,CAAC,EAAEC,KAAK,EAAEC,OAAO,EAAE,iBAClBC,IAAA,CAAAC,QAAA,EAAA;;kCACEV,GAAA,CAACd,QAAAA,EAAAA;gDACCuB,IAAA,CAACE,KAAKC,IAAI,EAAA;4BAACC,KAAAA,EAAO,KAAA;;AAChB,8CAAAb,GAAA,CAACW,KAAKG,OAAO,EAAA;oCACXC,GAAAA,EAAKC,UAAAA;AACLC,oCAAAA,IAAAA,gBAAMjB,GAAA,CAACkB,IAAAA,EAAAA,EAAAA,CAAAA;oCACPC,OAAAA,EAAQ,OAAA;oCACRC,IAAAA,EAAK,GAAA;;oCAELC,OAAAA,EAAS,CAACC,KAAAA,GAA4BA,KAAAA,CAAMC,eAAe,EAAA;AAC3DC,oCAAAA,KAAAA,EAAO1B,aAAAA,CACL;AACEM,wCAAAA,EAAAA,EAAIqB,iBAAAA,CAAkB,sBAAA,CAAA;wCACtBC,cAAAA,EAAgB;qCAClB,EACA;AAAErB,wCAAAA,IAAAA,EAAMZ,OAAOY;AAAK,qCAAA;;8CAGxBL,GAAA,CAAC2B,kBAAAA,EAAAA;oCAAmBC,gBAAAA,EAAiB,YAAA;oCAAaC,MAAAA,EAAQ,CAAA;oCAAGC,QAAAA,EAAS,OAAA;AACnEvB,oCAAAA,QAAAA,EAAAA;;;;;AAKNZ,oBAAAA,YAAAA,KAAiB,sBAChBK,GAAA,CAAC+B,kBAAAA,EAAAA;wBACCC,QAAAA,EAAUrC,YAAAA;wBACVsC,IAAI,EAAA,IAAA;AACJT,wBAAAA,KAAAA,EAAO1B,aAAAA,CAAc;AACnBM,4BAAAA,EAAAA,EAAIqB,iBAAAA,CAAkB,gCAAA,CAAA;4BACtBC,cAAAA,EAAgB;AAClB,yBAAA,CAAA;wBACA9B,aAAAA,EAAeA,aAAAA;wBACfsC,OAAAA,EAASrC,WAAAA;AAERU,wBAAAA,QAAAA,EAAAA;;AAIJC,oBAAAA;;;;AAKX;;;;"}
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var useMediaLibraryPermissions = require('../../../hooks/useMediaLibraryPermissions.js');
6
+ var useAssetSelection = require('../hooks/useAssetSelection.js');
7
+ var AssetContextMenu = require('./AssetContextMenu.js');
8
+ var FolderContextMenu = require('./FolderContextMenu.js');
9
+ var SelectionContextMenu = require('./SelectionContextMenu.js');
10
+
11
+ const ItemContextMenuContext = /*#__PURE__*/ React.createContext(null);
12
+ /**
13
+ * Called by the list items. Returns `null` outside the provider — the asset
14
+ * picker renders the same cards without a context menu, and a missing provider
15
+ * there should be a no-op rather than a crash.
16
+ */ const useItemContextMenuTrigger = ()=>React.useContext(ItemContextMenuContext);
17
+ /**
18
+ * Mirrors what each menu would render once open. Folders have no gated actions
19
+ * yet, so they always have a menu.
20
+ */ const hasItemActions = (permissions, isForSelection, payload)=>{
21
+ if (isForSelection) {
22
+ return permissions.canUpdate;
23
+ }
24
+ if (payload.kind === 'asset') {
25
+ return permissions.canUpdate || permissions.canCopyLink || permissions.canDownload;
26
+ }
27
+ return true;
28
+ };
29
+ /**
30
+ * Owns the right-click menu for the list, above both the grid and the table so
31
+ * one instance serves either view and the selection case has the `locations` it
32
+ * needs.
33
+ *
34
+ * The rule, in one place:
35
+ *
36
+ * - right-clicking an item **inside a multi-selection** opens the selection
37
+ * menu, acting on all of it — the file-manager behaviour, and the menu leads
38
+ * with the count so what it acts on is stated before the actions are
39
+ * - **anything else** replaces the selection with the clicked item and opens
40
+ * that item's own menu. That includes right-clicking an unselected item while
41
+ * others are selected: every file manager drops the old selection there, and
42
+ * the visible deselection is what stops the menu looking like it applies to
43
+ * items it doesn't
44
+ */ const ItemContextMenuProvider = ({ locations, children })=>{
45
+ const { isSelected, selectOnly, selectedKeys } = useAssetSelection.useAssetSelection();
46
+ // Resolved here, once, and handed to each menu as it opens. Mounted with the
47
+ // list, so by the time anyone right-clicks the answer is in — a menu that
48
+ // asked for itself would render empty for a tick.
49
+ const permissions = useMediaLibraryPermissions.useMediaLibraryPermissions();
50
+ const [state, setState] = React.useState(null);
51
+ const nextId = React.useRef(0);
52
+ const openForItem = React.useCallback((event, key, payload)=>{
53
+ const isForSelection = isSelected(key) && selectedKeys.size > 1;
54
+ if (!permissions.isLoading && !hasItemActions(permissions, isForSelection, payload)) {
55
+ return;
56
+ }
57
+ // Only once we know we're handling it — declining would otherwise cost the
58
+ // browser's own menu too.
59
+ event.preventDefault();
60
+ const position = {
61
+ x: event.clientX,
62
+ y: event.clientY
63
+ };
64
+ const returnFocusTo = event.currentTarget instanceof HTMLElement ? event.currentTarget : null;
65
+ nextId.current += 1;
66
+ const id = nextId.current;
67
+ if (isForSelection) {
68
+ setState({
69
+ id,
70
+ position,
71
+ returnFocusTo,
72
+ payload: null
73
+ });
74
+ return;
75
+ }
76
+ // Replace the selection *before* the menu renders, so the highlight has
77
+ // already moved by the time the user reads the menu.
78
+ selectOnly(key);
79
+ setState({
80
+ id,
81
+ position,
82
+ returnFocusTo,
83
+ payload
84
+ });
85
+ }, [
86
+ isSelected,
87
+ selectOnly,
88
+ selectedKeys,
89
+ permissions
90
+ ]);
91
+ // Only the menu that is still on screen may close it.
92
+ const close = React.useCallback((id)=>setState((prev)=>prev?.id === id ? null : prev), []);
93
+ const value = React.useMemo(()=>openForItem, [
94
+ openForItem
95
+ ]);
96
+ return /*#__PURE__*/ jsxRuntime.jsxs(ItemContextMenuContext.Provider, {
97
+ value: value,
98
+ children: [
99
+ children,
100
+ state !== null && (state.payload === null ? /*#__PURE__*/ jsxRuntime.jsx(SelectionContextMenu.SelectionContextMenu, {
101
+ position: state.position,
102
+ returnFocusTo: state.returnFocusTo,
103
+ locations: locations,
104
+ onClose: ()=>close(state.id)
105
+ }, state.id) : state.payload.kind === 'asset' ? /*#__PURE__*/ jsxRuntime.jsx(AssetContextMenu.AssetContextMenu, {
106
+ asset: state.payload.asset,
107
+ dragData: state.payload.dragData,
108
+ permissions: permissions,
109
+ position: state.position,
110
+ returnFocusTo: state.returnFocusTo,
111
+ onClose: ()=>close(state.id)
112
+ }, state.id) : /*#__PURE__*/ jsxRuntime.jsx(FolderContextMenu.FolderContextMenu, {
113
+ folder: state.payload.folder,
114
+ dragData: state.payload.dragData,
115
+ position: state.position,
116
+ returnFocusTo: state.returnFocusTo,
117
+ onClose: ()=>close(state.id)
118
+ }, state.id))
119
+ ]
120
+ });
121
+ };
122
+
123
+ exports.ItemContextMenuProvider = ItemContextMenuProvider;
124
+ exports.useItemContextMenuTrigger = useItemContextMenuTrigger;
125
+ //# sourceMappingURL=ItemContextMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ItemContextMenu.js","sources":["../../../../../admin/src/pages/Assets/components/ItemContextMenu.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\n\nimport { AssetContextMenu } from './AssetContextMenu';\nimport { FolderContextMenu } from './FolderContextMenu';\nimport { SelectionContextMenu } from './SelectionContextMenu';\n\nimport type { AssetActionPermissions } from './AssetActions';\nimport type { CursorPosition } from './CursorAnchoredMenu';\nimport type { File } from '../../../../../shared/contracts/files';\nimport type { Folder } from '../../../../../shared/contracts/folders';\nimport type { DragFileData, DragFolderData } from '../../../types/dnd';\nimport type { ItemLocations } from '../../../utils/itemLocations';\nimport type { ItemKey } from '../utils/selection';\n\n/**\n * What a card or row hands over when it is right-clicked. It passes its own\n * asset rather than a key alone, so nothing here has to resolve keys back to\n * items — the item is already in scope where the gesture happens.\n */\nexport type ContextMenuPayload =\n | { kind: 'asset'; asset: File; dragData: DragFileData }\n | { kind: 'folder'; folder: Folder; dragData: DragFolderData };\n\ntype OpenForItem = (event: React.MouseEvent, key: ItemKey, payload: ContextMenuPayload) => void;\n\nconst ItemContextMenuContext = createContext<OpenForItem | null>(null);\n\n/**\n * Called by the list items. Returns `null` outside the provider — the asset\n * picker renders the same cards without a context menu, and a missing provider\n * there should be a no-op rather than a crash.\n */\nexport const useItemContextMenuTrigger = (): OpenForItem | null =>\n useContext(ItemContextMenuContext);\n\ninterface OpenState {\n /**\n * Distinguishes one opening from the next.\n *\n * A right-click while a menu is open is two events: `pointerdown`, which\n * Radix treats as \"dismiss\", then `contextmenu`, which opens the next menu.\n * The dismissed menu's own effect runs *after* the new one has mounted, so a\n * plain `close()` would clear state that no longer belongs to it — and the\n * second right-click would appear to do nothing.\n */\n id: number;\n position: CursorPosition;\n /** The card or row that was right-clicked. */\n returnFocusTo: HTMLElement | null;\n payload: ContextMenuPayload | null;\n}\n\n/**\n * Mirrors what each menu would render once open. Folders have no gated actions\n * yet, so they always have a menu.\n */\nconst hasItemActions = (\n permissions: AssetActionPermissions,\n isForSelection: boolean,\n payload: ContextMenuPayload\n) => {\n if (isForSelection) {\n return permissions.canUpdate;\n }\n\n if (payload.kind === 'asset') {\n return permissions.canUpdate || permissions.canCopyLink || permissions.canDownload;\n }\n\n return true;\n};\n\ninterface ItemContextMenuProviderProps {\n /**\n * Real location of every loaded row, so a selection move validates each item\n * against its own parent — same input the bulk bar takes.\n */\n locations: ItemLocations;\n children: ReactNode;\n}\n\n/**\n * Owns the right-click menu for the list, above both the grid and the table so\n * one instance serves either view and the selection case has the `locations` it\n * needs.\n *\n * The rule, in one place:\n *\n * - right-clicking an item **inside a multi-selection** opens the selection\n * menu, acting on all of it — the file-manager behaviour, and the menu leads\n * with the count so what it acts on is stated before the actions are\n * - **anything else** replaces the selection with the clicked item and opens\n * that item's own menu. That includes right-clicking an unselected item while\n * others are selected: every file manager drops the old selection there, and\n * the visible deselection is what stops the menu looking like it applies to\n * items it doesn't\n */\nexport const ItemContextMenuProvider = ({ locations, children }: ItemContextMenuProviderProps) => {\n const { isSelected, selectOnly, selectedKeys } = useAssetSelection();\n // Resolved here, once, and handed to each menu as it opens. Mounted with the\n // list, so by the time anyone right-clicks the answer is in — a menu that\n // asked for itself would render empty for a tick.\n const permissions = useMediaLibraryPermissions();\n const [state, setState] = useState<OpenState | null>(null);\n const nextId = useRef(0);\n\n const openForItem = useCallback<OpenForItem>(\n (event, key, payload) => {\n const isForSelection = isSelected(key) && selectedKeys.size > 1;\n\n if (!permissions.isLoading && !hasItemActions(permissions, isForSelection, payload)) {\n return;\n }\n\n // Only once we know we're handling it — declining would otherwise cost the\n // browser's own menu too.\n event.preventDefault();\n\n const position = { x: event.clientX, y: event.clientY };\n const returnFocusTo = event.currentTarget instanceof HTMLElement ? event.currentTarget : null;\n nextId.current += 1;\n const id = nextId.current;\n\n if (isForSelection) {\n setState({ id, position, returnFocusTo, payload: null });\n return;\n }\n\n // Replace the selection *before* the menu renders, so the highlight has\n // already moved by the time the user reads the menu.\n selectOnly(key);\n setState({ id, position, returnFocusTo, payload });\n },\n [isSelected, selectOnly, selectedKeys, permissions]\n );\n\n // Only the menu that is still on screen may close it.\n const close = useCallback(\n (id: number) => setState((prev) => (prev?.id === id ? null : prev)),\n []\n );\n\n const value = useMemo(() => openForItem, [openForItem]);\n\n return (\n <ItemContextMenuContext.Provider value={value}>\n {children}\n {state !== null &&\n (state.payload === null ? (\n <SelectionContextMenu\n key={state.id}\n position={state.position}\n returnFocusTo={state.returnFocusTo}\n locations={locations}\n onClose={() => close(state.id)}\n />\n ) : state.payload.kind === 'asset' ? (\n <AssetContextMenu\n // A fresh menu per gesture: the actions carry dialog state, and\n // reusing the instance across two right-clicks would carry it over.\n // Keyed on the opening rather than the item, so right-clicking the\n // same card twice still remounts.\n key={state.id}\n asset={state.payload.asset}\n dragData={state.payload.dragData}\n permissions={permissions}\n position={state.position}\n returnFocusTo={state.returnFocusTo}\n onClose={() => close(state.id)}\n />\n ) : (\n <FolderContextMenu\n key={state.id}\n folder={state.payload.folder}\n dragData={state.payload.dragData}\n position={state.position}\n returnFocusTo={state.returnFocusTo}\n onClose={() => close(state.id)}\n />\n ))}\n </ItemContextMenuContext.Provider>\n );\n};\n"],"names":["ItemContextMenuContext","createContext","useItemContextMenuTrigger","useContext","hasItemActions","permissions","isForSelection","payload","canUpdate","kind","canCopyLink","canDownload","ItemContextMenuProvider","locations","children","isSelected","selectOnly","selectedKeys","useAssetSelection","useMediaLibraryPermissions","state","setState","useState","nextId","useRef","openForItem","useCallback","event","key","size","isLoading","preventDefault","position","x","clientX","y","clientY","returnFocusTo","currentTarget","HTMLElement","current","id","close","prev","value","useMemo","_jsxs","Provider","_jsx","SelectionContextMenu","onClose","AssetContextMenu","asset","dragData","FolderContextMenu","folder"],"mappings":"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"}