@strapi/upload 5.55.1 → 5.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/hooks/useAIMetadataAvailability.js +14 -0
- package/dist/admin/hooks/useAIMetadataAvailability.js.map +1 -0
- package/dist/admin/hooks/useAIMetadataAvailability.mjs +12 -0
- package/dist/admin/hooks/useAIMetadataAvailability.mjs.map +1 -0
- package/dist/admin/hooks/useAIMetadataEnabled.js +7 -5
- package/dist/admin/hooks/useAIMetadataEnabled.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataEnabled.mjs +7 -5
- package/dist/admin/hooks/useAIMetadataEnabled.mjs.map +1 -1
- package/dist/admin/hooks/useTracking.js +4 -10
- package/dist/admin/hooks/useTracking.js.map +1 -1
- package/dist/admin/hooks/useTracking.mjs +5 -10
- package/dist/admin/hooks/useTracking.mjs.map +1 -1
- package/dist/admin/legacy/hooks/useAIMetadataAvailability.js +14 -0
- package/dist/admin/legacy/hooks/useAIMetadataAvailability.js.map +1 -0
- package/dist/admin/legacy/hooks/useAIMetadataAvailability.mjs +12 -0
- package/dist/admin/legacy/hooks/useAIMetadataAvailability.mjs.map +1 -0
- package/dist/admin/legacy/hooks/useAIMetadataEnabled.js +23 -0
- package/dist/admin/legacy/hooks/useAIMetadataEnabled.js.map +1 -0
- package/dist/admin/legacy/hooks/useAIMetadataEnabled.mjs +21 -0
- package/dist/admin/legacy/hooks/useAIMetadataEnabled.mjs.map +1 -0
- package/dist/admin/legacy/hooks/useTracking.js +5 -3
- package/dist/admin/legacy/hooks/useTracking.js.map +1 -1
- package/dist/admin/legacy/hooks/useTracking.mjs +5 -3
- package/dist/admin/legacy/hooks/useTracking.mjs.map +1 -1
- package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js +2 -1
- package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -1
- package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs +2 -1
- package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -1
- package/dist/admin/legacy/pages/App/MediaLibrary.js +6 -5
- package/dist/admin/legacy/pages/App/MediaLibrary.js.map +1 -1
- package/dist/admin/legacy/pages/App/MediaLibrary.mjs +6 -5
- package/dist/admin/legacy/pages/App/MediaLibrary.mjs.map +1 -1
- package/dist/admin/pages/Assets/AssetsPage.js +24 -12
- package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/pages/Assets/AssetsPage.mjs +25 -13
- package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetActions.js +326 -0
- package/dist/admin/pages/Assets/components/AssetActions.js.map +1 -0
- package/dist/admin/pages/Assets/components/AssetActions.mjs +324 -0
- package/dist/admin/pages/Assets/components/AssetActions.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/AssetActionsMenu.js +28 -309
- package/dist/admin/pages/Assets/components/AssetActionsMenu.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs +31 -312
- package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetContextMenu.js +79 -0
- package/dist/admin/pages/Assets/components/AssetContextMenu.js.map +1 -0
- package/dist/admin/pages/Assets/components/AssetContextMenu.mjs +77 -0
- package/dist/admin/pages/Assets/components/AssetContextMenu.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js +87 -5
- package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +89 -7
- package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +3 -3
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +3 -3
- package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js +62 -5
- package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs +60 -6
- package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.js +27 -4
- package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.mjs +27 -4
- package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsTable.js +27 -4
- package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsTable.mjs +27 -4
- package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js +77 -0
- package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js.map +1 -0
- package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs +75 -0
- package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/DeleteItemsDialog.js +4 -2
- package/dist/admin/pages/Assets/components/DeleteItemsDialog.js.map +1 -1
- package/dist/admin/pages/Assets/components/DeleteItemsDialog.mjs +4 -2
- package/dist/admin/pages/Assets/components/DeleteItemsDialog.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/FolderActions.js +139 -0
- package/dist/admin/pages/Assets/components/FolderActions.js.map +1 -0
- package/dist/admin/pages/Assets/components/FolderActions.mjs +137 -0
- package/dist/admin/pages/Assets/components/FolderActions.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/FolderActionsMenu.js +25 -119
- package/dist/admin/pages/Assets/components/FolderActionsMenu.js.map +1 -1
- package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs +27 -121
- package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/FolderContextMenu.js +67 -0
- package/dist/admin/pages/Assets/components/FolderContextMenu.js.map +1 -0
- package/dist/admin/pages/Assets/components/FolderContextMenu.mjs +65 -0
- package/dist/admin/pages/Assets/components/FolderContextMenu.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js +139 -45
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs +140 -47
- package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js +115 -0
- package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js.map +1 -0
- package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs +113 -0
- package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/ItemContextMenu.js +125 -0
- package/dist/admin/pages/Assets/components/ItemContextMenu.js.map +1 -0
- package/dist/admin/pages/Assets/components/ItemContextMenu.mjs +122 -0
- package/dist/admin/pages/Assets/components/ItemContextMenu.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/MainAreaContextMenu.js +88 -63
- package/dist/admin/pages/Assets/components/MainAreaContextMenu.js.map +1 -1
- package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs +88 -63
- package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/SelectionActions.js +111 -0
- package/dist/admin/pages/Assets/components/SelectionActions.js.map +1 -0
- package/dist/admin/pages/Assets/components/SelectionActions.mjs +109 -0
- package/dist/admin/pages/Assets/components/SelectionActions.mjs.map +1 -0
- package/dist/admin/pages/Assets/components/SelectionContextMenu.js +82 -0
- package/dist/admin/pages/Assets/components/SelectionContextMenu.js.map +1 -0
- package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs +80 -0
- package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs.map +1 -0
- package/dist/admin/pages/Assets/hooks/useAssetSelection.js +10 -0
- package/dist/admin/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs +10 -0
- package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.js +10 -3
- package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs +10 -3
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
- package/dist/admin/services/api.js.map +1 -1
- package/dist/admin/services/api.mjs.map +1 -1
- package/dist/admin/src/hooks/useAIMetadataAvailability.d.ts +5 -0
- package/dist/admin/src/hooks/useAIMetadataEnabled.d.ts +5 -3
- package/dist/admin/src/hooks/useTracking.d.ts +0 -7
- package/dist/admin/src/legacy/components/EditAssetDialog/PreviewBox/PreviewComponents.d.ts +2 -2
- package/dist/admin/src/legacy/hooks/useAIMetadataAvailability.d.ts +5 -0
- package/dist/admin/src/legacy/hooks/useAIMetadataEnabled.d.ts +12 -0
- package/dist/admin/src/legacy/hooks/useSettings.d.ts +1 -0
- package/dist/admin/src/pages/Assets/components/ActionsMenuContent.d.ts +2 -2
- package/dist/admin/src/pages/Assets/components/AssetActions.d.ts +70 -0
- package/dist/admin/src/pages/Assets/components/AssetActionsMenu.d.ts +5 -14
- package/dist/admin/src/pages/Assets/components/AssetContextMenu.d.ts +27 -0
- package/dist/admin/src/pages/Assets/components/AssetDetails/useCropImg.d.ts +16 -0
- package/dist/admin/src/pages/Assets/components/CursorAnchoredMenu.d.ts +32 -0
- package/dist/admin/src/pages/Assets/components/FolderActions.d.ts +48 -0
- package/dist/admin/src/pages/Assets/components/FolderActionsMenu.d.ts +4 -8
- package/dist/admin/src/pages/Assets/components/FolderContextMenu.d.ts +21 -0
- package/dist/admin/src/pages/Assets/components/FolderTree/FolderTree.d.ts +5 -1
- package/dist/admin/src/pages/Assets/components/FolderTree/FolderTreeRowMenu.d.ts +25 -0
- package/dist/admin/src/pages/Assets/components/ItemContextMenu.d.ts +53 -0
- package/dist/admin/src/pages/Assets/components/MainAreaContextMenu.d.ts +15 -1
- package/dist/admin/src/pages/Assets/components/SelectionActions.d.ts +40 -0
- package/dist/admin/src/pages/Assets/components/SelectionContextMenu.d.ts +25 -0
- package/dist/admin/src/pages/Assets/hooks/useAssetSelection.d.ts +5 -0
- package/dist/admin/src/utils/mediaLibraryVersion.d.ts +18 -0
- package/dist/admin/translations/en.json.js +9 -3
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +9 -3
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/utils/mediaLibraryVersion.js +24 -0
- package/dist/admin/utils/mediaLibraryVersion.js.map +1 -0
- package/dist/admin/utils/mediaLibraryVersion.mjs +20 -0
- package/dist/admin/utils/mediaLibraryVersion.mjs.map +1 -0
- package/dist/server/bootstrap.js +7 -0
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +7 -0
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/admin-file.js +2 -2
- package/dist/server/controllers/admin-file.js.map +1 -1
- package/dist/server/controllers/admin-file.mjs +2 -2
- package/dist/server/controllers/admin-file.mjs.map +1 -1
- package/dist/server/controllers/admin-folder-file.js +51 -4
- package/dist/server/controllers/admin-folder-file.js.map +1 -1
- package/dist/server/controllers/admin-folder-file.mjs +52 -5
- package/dist/server/controllers/admin-folder-file.mjs.map +1 -1
- package/dist/server/controllers/admin-folder.js +5 -5
- package/dist/server/controllers/admin-folder.js.map +1 -1
- package/dist/server/controllers/admin-folder.mjs +5 -5
- package/dist/server/controllers/admin-folder.mjs.map +1 -1
- package/dist/server/controllers/admin-settings.js +2 -1
- package/dist/server/controllers/admin-settings.js.map +1 -1
- package/dist/server/controllers/admin-settings.mjs +2 -1
- package/dist/server/controllers/admin-settings.mjs.map +1 -1
- package/dist/server/controllers/content-api.js +30 -7
- package/dist/server/controllers/content-api.js.map +1 -1
- package/dist/server/controllers/content-api.mjs +30 -7
- package/dist/server/controllers/content-api.mjs.map +1 -1
- package/dist/server/controllers/validation/admin/folder-file.js +4 -4
- package/dist/server/controllers/validation/admin/folder-file.js.map +1 -1
- package/dist/server/controllers/validation/admin/folder-file.mjs +2 -2
- package/dist/server/controllers/validation/admin/folder-file.mjs.map +1 -1
- package/dist/server/controllers/validation/admin/folder.js +3 -4
- package/dist/server/controllers/validation/admin/folder.js.map +1 -1
- package/dist/server/controllers/validation/admin/folder.mjs +3 -4
- package/dist/server/controllers/validation/admin/folder.mjs.map +1 -1
- package/dist/server/controllers/validation/admin/upload.js +1 -2
- package/dist/server/controllers/validation/admin/upload.js.map +1 -1
- package/dist/server/controllers/validation/admin/upload.mjs +1 -2
- package/dist/server/controllers/validation/admin/upload.mjs.map +1 -1
- package/dist/server/controllers/validation/admin/utils.js +1 -2
- package/dist/server/controllers/validation/admin/utils.js.map +1 -1
- package/dist/server/controllers/validation/admin/utils.mjs +1 -2
- package/dist/server/controllers/validation/admin/utils.mjs.map +1 -1
- package/dist/server/errors.js +12 -0
- package/dist/server/errors.js.map +1 -0
- package/dist/server/errors.mjs +10 -0
- package/dist/server/errors.mjs.map +1 -0
- package/dist/server/migrations/unsign-richtext-and-blocks-urls.js +2 -2
- package/dist/server/migrations/unsign-richtext-and-blocks-urls.js.map +1 -1
- package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs +1 -1
- package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs.map +1 -1
- package/dist/server/routes/content-api.js +3 -3
- package/dist/server/routes/content-api.js.map +1 -1
- package/dist/server/routes/content-api.mjs +3 -3
- package/dist/server/routes/content-api.mjs.map +1 -1
- package/dist/server/routes/validation/upload.js +8 -0
- package/dist/server/routes/validation/upload.js.map +1 -1
- package/dist/server/routes/validation/upload.mjs +8 -0
- package/dist/server/routes/validation/upload.mjs.map +1 -1
- package/dist/server/services/ai-metadata-provider.js +83 -0
- package/dist/server/services/ai-metadata-provider.js.map +1 -0
- package/dist/server/services/ai-metadata-provider.mjs +61 -0
- package/dist/server/services/ai-metadata-provider.mjs.map +1 -0
- package/dist/server/services/ai-metadata-strapi-managed.js +48 -0
- package/dist/server/services/ai-metadata-strapi-managed.js.map +1 -0
- package/dist/server/services/ai-metadata-strapi-managed.mjs +46 -0
- package/dist/server/services/ai-metadata-strapi-managed.mjs.map +1 -0
- package/dist/server/services/ai-metadata.js +5 -58
- package/dist/server/services/ai-metadata.js.map +1 -1
- package/dist/server/services/ai-metadata.mjs +6 -39
- package/dist/server/services/ai-metadata.mjs.map +1 -1
- package/dist/server/services/api-upload-folder.js +3 -3
- package/dist/server/services/api-upload-folder.js.map +1 -1
- package/dist/server/services/api-upload-folder.mjs +3 -3
- package/dist/server/services/api-upload-folder.mjs.map +1 -1
- package/dist/server/services/extensions/utils.js +19 -15
- package/dist/server/services/extensions/utils.js.map +1 -1
- package/dist/server/services/extensions/utils.mjs +19 -15
- package/dist/server/services/extensions/utils.mjs.map +1 -1
- package/dist/server/services/file.js +2 -2
- package/dist/server/services/file.js.map +1 -1
- package/dist/server/services/file.mjs +1 -1
- package/dist/server/services/file.mjs.map +1 -1
- package/dist/server/services/folder.js +9 -6
- package/dist/server/services/folder.js.map +1 -1
- package/dist/server/services/folder.mjs +9 -6
- package/dist/server/services/folder.mjs.map +1 -1
- package/dist/server/services/index.js +3 -1
- package/dist/server/services/index.js.map +1 -1
- package/dist/server/services/index.mjs +3 -1
- package/dist/server/services/index.mjs.map +1 -1
- package/dist/server/services/metrics.js +1 -1
- package/dist/server/services/metrics.js.map +1 -1
- package/dist/server/services/metrics.mjs +1 -1
- package/dist/server/services/metrics.mjs.map +1 -1
- package/dist/server/services/provider.js +3 -4
- package/dist/server/services/provider.js.map +1 -1
- package/dist/server/services/provider.mjs +3 -4
- package/dist/server/services/provider.mjs.map +1 -1
- package/dist/server/services/upload.js +5 -6
- package/dist/server/services/upload.js.map +1 -1
- package/dist/server/services/upload.mjs +4 -5
- package/dist/server/services/upload.mjs.map +1 -1
- package/dist/server/services/weekly-metrics.js +2 -2
- package/dist/server/services/weekly-metrics.js.map +1 -1
- package/dist/server/services/weekly-metrics.mjs +2 -2
- package/dist/server/services/weekly-metrics.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-folder-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-folder.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-settings.d.ts.map +1 -1
- package/dist/server/src/controllers/content-api.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/admin/folder.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/admin/upload.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/admin/utils.d.ts.map +1 -1
- package/dist/server/src/errors.d.ts +6 -0
- package/dist/server/src/errors.d.ts.map +1 -0
- package/dist/server/src/index.d.ts +6 -1
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/mcp/ambient-instance.d.ts +3 -1
- package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
- package/dist/server/src/routes/validation/upload.d.ts +4 -0
- package/dist/server/src/routes/validation/upload.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata-provider.d.ts +26 -0
- package/dist/server/src/services/ai-metadata-provider.d.ts.map +1 -0
- package/dist/server/src/services/ai-metadata-strapi-managed.d.ts +7 -0
- package/dist/server/src/services/ai-metadata-strapi-managed.d.ts.map +1 -0
- package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
- package/dist/server/src/services/extensions/utils.d.ts +33 -1
- package/dist/server/src/services/extensions/utils.d.ts.map +1 -1
- package/dist/server/src/services/folder.d.ts +5 -2
- package/dist/server/src/services/folder.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +6 -1
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/provider.d.ts.map +1 -1
- package/dist/server/src/services/upload.d.ts.map +1 -1
- package/dist/server/src/utils/images.d.ts +2 -2
- package/dist/server/src/utils/images.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/server/utils/images.js +6 -7
- package/dist/server/utils/images.js.map +1 -1
- package/dist/server/utils/images.mjs +6 -7
- package/dist/server/utils/images.mjs.map +1 -1
- package/dist/server/utils/index.js.map +1 -1
- package/dist/server/utils/index.mjs.map +1 -1
- package/dist/shared/contracts/settings.d.ts +6 -0
- package/package.json +11 -11
- package/dist/admin/legacy/hooks/useAiAvailability.js +0 -22
- package/dist/admin/legacy/hooks/useAiAvailability.js.map +0 -1
- package/dist/admin/legacy/hooks/useAiAvailability.mjs +0 -20
- package/dist/admin/legacy/hooks/useAiAvailability.mjs.map +0 -1
- package/dist/admin/src/legacy/hooks/useAiAvailability.d.ts +0 -4
|
@@ -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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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef, useCallback, useMemo, createContext, useContext } from 'react';
|
|
3
|
+
import { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions.mjs';
|
|
4
|
+
import { useAssetSelection } from '../hooks/useAssetSelection.mjs';
|
|
5
|
+
import { AssetContextMenu } from './AssetContextMenu.mjs';
|
|
6
|
+
import { FolderContextMenu } from './FolderContextMenu.mjs';
|
|
7
|
+
import { SelectionContextMenu } from './SelectionContextMenu.mjs';
|
|
8
|
+
|
|
9
|
+
const ItemContextMenuContext = /*#__PURE__*/ createContext(null);
|
|
10
|
+
/**
|
|
11
|
+
* Called by the list items. Returns `null` outside the provider — the asset
|
|
12
|
+
* picker renders the same cards without a context menu, and a missing provider
|
|
13
|
+
* there should be a no-op rather than a crash.
|
|
14
|
+
*/ const useItemContextMenuTrigger = ()=>useContext(ItemContextMenuContext);
|
|
15
|
+
/**
|
|
16
|
+
* Mirrors what each menu would render once open. Folders have no gated actions
|
|
17
|
+
* yet, so they always have a menu.
|
|
18
|
+
*/ const hasItemActions = (permissions, isForSelection, payload)=>{
|
|
19
|
+
if (isForSelection) {
|
|
20
|
+
return permissions.canUpdate;
|
|
21
|
+
}
|
|
22
|
+
if (payload.kind === 'asset') {
|
|
23
|
+
return permissions.canUpdate || permissions.canCopyLink || permissions.canDownload;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Owns the right-click menu for the list, above both the grid and the table so
|
|
29
|
+
* one instance serves either view and the selection case has the `locations` it
|
|
30
|
+
* needs.
|
|
31
|
+
*
|
|
32
|
+
* The rule, in one place:
|
|
33
|
+
*
|
|
34
|
+
* - right-clicking an item **inside a multi-selection** opens the selection
|
|
35
|
+
* menu, acting on all of it — the file-manager behaviour, and the menu leads
|
|
36
|
+
* with the count so what it acts on is stated before the actions are
|
|
37
|
+
* - **anything else** replaces the selection with the clicked item and opens
|
|
38
|
+
* that item's own menu. That includes right-clicking an unselected item while
|
|
39
|
+
* others are selected: every file manager drops the old selection there, and
|
|
40
|
+
* the visible deselection is what stops the menu looking like it applies to
|
|
41
|
+
* items it doesn't
|
|
42
|
+
*/ const ItemContextMenuProvider = ({ locations, children })=>{
|
|
43
|
+
const { isSelected, selectOnly, selectedKeys } = useAssetSelection();
|
|
44
|
+
// Resolved here, once, and handed to each menu as it opens. Mounted with the
|
|
45
|
+
// list, so by the time anyone right-clicks the answer is in — a menu that
|
|
46
|
+
// asked for itself would render empty for a tick.
|
|
47
|
+
const permissions = useMediaLibraryPermissions();
|
|
48
|
+
const [state, setState] = useState(null);
|
|
49
|
+
const nextId = useRef(0);
|
|
50
|
+
const openForItem = useCallback((event, key, payload)=>{
|
|
51
|
+
const isForSelection = isSelected(key) && selectedKeys.size > 1;
|
|
52
|
+
if (!permissions.isLoading && !hasItemActions(permissions, isForSelection, payload)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Only once we know we're handling it — declining would otherwise cost the
|
|
56
|
+
// browser's own menu too.
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
const position = {
|
|
59
|
+
x: event.clientX,
|
|
60
|
+
y: event.clientY
|
|
61
|
+
};
|
|
62
|
+
const returnFocusTo = event.currentTarget instanceof HTMLElement ? event.currentTarget : null;
|
|
63
|
+
nextId.current += 1;
|
|
64
|
+
const id = nextId.current;
|
|
65
|
+
if (isForSelection) {
|
|
66
|
+
setState({
|
|
67
|
+
id,
|
|
68
|
+
position,
|
|
69
|
+
returnFocusTo,
|
|
70
|
+
payload: null
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Replace the selection *before* the menu renders, so the highlight has
|
|
75
|
+
// already moved by the time the user reads the menu.
|
|
76
|
+
selectOnly(key);
|
|
77
|
+
setState({
|
|
78
|
+
id,
|
|
79
|
+
position,
|
|
80
|
+
returnFocusTo,
|
|
81
|
+
payload
|
|
82
|
+
});
|
|
83
|
+
}, [
|
|
84
|
+
isSelected,
|
|
85
|
+
selectOnly,
|
|
86
|
+
selectedKeys,
|
|
87
|
+
permissions
|
|
88
|
+
]);
|
|
89
|
+
// Only the menu that is still on screen may close it.
|
|
90
|
+
const close = useCallback((id)=>setState((prev)=>prev?.id === id ? null : prev), []);
|
|
91
|
+
const value = useMemo(()=>openForItem, [
|
|
92
|
+
openForItem
|
|
93
|
+
]);
|
|
94
|
+
return /*#__PURE__*/ jsxs(ItemContextMenuContext.Provider, {
|
|
95
|
+
value: value,
|
|
96
|
+
children: [
|
|
97
|
+
children,
|
|
98
|
+
state !== null && (state.payload === null ? /*#__PURE__*/ jsx(SelectionContextMenu, {
|
|
99
|
+
position: state.position,
|
|
100
|
+
returnFocusTo: state.returnFocusTo,
|
|
101
|
+
locations: locations,
|
|
102
|
+
onClose: ()=>close(state.id)
|
|
103
|
+
}, state.id) : state.payload.kind === 'asset' ? /*#__PURE__*/ jsx(AssetContextMenu, {
|
|
104
|
+
asset: state.payload.asset,
|
|
105
|
+
dragData: state.payload.dragData,
|
|
106
|
+
permissions: permissions,
|
|
107
|
+
position: state.position,
|
|
108
|
+
returnFocusTo: state.returnFocusTo,
|
|
109
|
+
onClose: ()=>close(state.id)
|
|
110
|
+
}, state.id) : /*#__PURE__*/ jsx(FolderContextMenu, {
|
|
111
|
+
folder: state.payload.folder,
|
|
112
|
+
dragData: state.payload.dragData,
|
|
113
|
+
position: state.position,
|
|
114
|
+
returnFocusTo: state.returnFocusTo,
|
|
115
|
+
onClose: ()=>close(state.id)
|
|
116
|
+
}, state.id))
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export { ItemContextMenuProvider, useItemContextMenuTrigger };
|
|
122
|
+
//# sourceMappingURL=ItemContextMenu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ItemContextMenu.mjs","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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"}
|
|
@@ -7,6 +7,7 @@ var icons = require('@strapi/icons');
|
|
|
7
7
|
var reactIntl = require('react-intl');
|
|
8
8
|
var translations = require('../../../utils/translations.js');
|
|
9
9
|
var ActionsMenuContent = require('./ActionsMenuContent.js');
|
|
10
|
+
var SelectionActions = require('./SelectionActions.js');
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* The admin layout marks the element that scrolls the main column. Listening on
|
|
@@ -71,13 +72,13 @@ const LOCATOR_STYLE = {
|
|
|
71
72
|
* Deliberately background-only. Right-clicking an asset, a folder or a table
|
|
72
73
|
* row is left alone — those carry `data-native-context-menu` and keep the
|
|
73
74
|
* browser's menu (which is what you want over a thumbnail or a filename).
|
|
74
|
-
*/ const MainAreaContextMenu = ({ onCreateFolder, onImportFiles, onImportFromUrl, disabled })=>{
|
|
75
|
+
*/ const MainAreaContextMenu = ({ onCreateFolder, onImportFiles, onImportFromUrl, disabled, containerSelector = SCROLL_ROOT_SELECTOR, locations })=>{
|
|
75
76
|
const { formatMessage } = reactIntl.useIntl();
|
|
76
77
|
const [position, setPosition] = React.useState(null);
|
|
77
78
|
const [locator, setLocator] = React.useState(null);
|
|
78
79
|
const anchorRef = React.useCallback((node)=>setLocator(node), []);
|
|
79
80
|
React.useEffect(()=>{
|
|
80
|
-
const container = locator?.closest(
|
|
81
|
+
const container = locator?.closest(containerSelector);
|
|
81
82
|
if (!container || disabled) {
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
@@ -101,8 +102,81 @@ const LOCATOR_STYLE = {
|
|
|
101
102
|
return ()=>container.removeEventListener('contextmenu', handleContextMenu);
|
|
102
103
|
}, [
|
|
103
104
|
locator,
|
|
104
|
-
disabled
|
|
105
|
+
disabled,
|
|
106
|
+
containerSelector
|
|
105
107
|
]);
|
|
108
|
+
const createItems = /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
109
|
+
children: [
|
|
110
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
|
|
111
|
+
onSelect: onCreateFolder,
|
|
112
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Folder, {}),
|
|
113
|
+
children: formatMessage({
|
|
114
|
+
id: translations.getTranslationKey('folder.create.title'),
|
|
115
|
+
defaultMessage: 'New folder'
|
|
116
|
+
})
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
|
|
119
|
+
onSelect: onImportFiles,
|
|
120
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Files, {}),
|
|
121
|
+
children: formatMessage({
|
|
122
|
+
id: translations.getTranslationKey('import-files'),
|
|
123
|
+
defaultMessage: 'File upload'
|
|
124
|
+
})
|
|
125
|
+
}),
|
|
126
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
|
|
127
|
+
onSelect: onImportFromUrl,
|
|
128
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Link, {}),
|
|
129
|
+
children: formatMessage({
|
|
130
|
+
id: translations.getTranslationKey('import-from-url'),
|
|
131
|
+
defaultMessage: 'File upload from URL'
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
]
|
|
135
|
+
});
|
|
136
|
+
/**
|
|
137
|
+
* `selectionItems` leads the menu when something is selected, so the actions
|
|
138
|
+
* that apply to the selection come before the ones that create new things.
|
|
139
|
+
*/ const renderMenu = (selectionItems)=>/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Menu.Root, {
|
|
140
|
+
modal: false,
|
|
141
|
+
open: position !== null,
|
|
142
|
+
onOpenChange: (open)=>{
|
|
143
|
+
if (!open) {
|
|
144
|
+
setPosition(null);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
children: [
|
|
148
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Trigger, {
|
|
149
|
+
tabIndex: -1,
|
|
150
|
+
// No visible content, so the name has to come from `aria-label` —
|
|
151
|
+
// the trigger's `label` prop renders as button text, which would
|
|
152
|
+
// defeat the point of an invisible anchor. Radix points the menu's
|
|
153
|
+
// `aria-labelledby` at this element, so it names the menu too.
|
|
154
|
+
endIcon: null,
|
|
155
|
+
"aria-label": formatMessage({
|
|
156
|
+
id: translations.getTranslationKey('list.context-menu.label'),
|
|
157
|
+
defaultMessage: 'Media library actions'
|
|
158
|
+
}),
|
|
159
|
+
style: {
|
|
160
|
+
...CURSOR_ANCHOR_STYLE,
|
|
161
|
+
top: position?.y ?? 0,
|
|
162
|
+
left: position?.x ?? 0
|
|
163
|
+
}
|
|
164
|
+
}),
|
|
165
|
+
/*#__PURE__*/ jsxRuntime.jsxs(ActionsMenuContent.ActionsMenuContent, {
|
|
166
|
+
popoverPlacement: "bottom-start",
|
|
167
|
+
zIndex: 2,
|
|
168
|
+
minWidth: "22rem",
|
|
169
|
+
// The anchor is invisible and sits wherever the cursor was, so
|
|
170
|
+
// handing focus back to it on close would be a focus ring nobody can
|
|
171
|
+
// see. Let it fall to the body instead.
|
|
172
|
+
onCloseAutoFocus: (event)=>event.preventDefault(),
|
|
173
|
+
children: [
|
|
174
|
+
selectionItems,
|
|
175
|
+
createItems
|
|
176
|
+
]
|
|
177
|
+
})
|
|
178
|
+
]
|
|
179
|
+
});
|
|
106
180
|
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
107
181
|
children: [
|
|
108
182
|
/*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
@@ -110,69 +184,20 @@ const LOCATOR_STYLE = {
|
|
|
110
184
|
style: LOCATOR_STYLE,
|
|
111
185
|
"aria-hidden": true
|
|
112
186
|
}),
|
|
113
|
-
!disabled && /*#__PURE__*/ jsxRuntime.
|
|
114
|
-
|
|
115
|
-
|
|
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(),
|
|
187
|
+
!disabled && (locations ? /*#__PURE__*/ jsxRuntime.jsx(SelectionActions.SelectionActions, {
|
|
188
|
+
locations: locations,
|
|
189
|
+
children: ({ count, hasActions, items, dialogs })=>/*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
147
190
|
children: [
|
|
148
|
-
/*#__PURE__*/ jsxRuntime.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
})
|
|
191
|
+
renderMenu(count > 0 && hasActions ? /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
192
|
+
children: [
|
|
193
|
+
items,
|
|
194
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Separator, {})
|
|
195
|
+
]
|
|
196
|
+
}) : null),
|
|
197
|
+
dialogs
|
|
172
198
|
]
|
|
173
199
|
})
|
|
174
|
-
|
|
175
|
-
})
|
|
200
|
+
}) : renderMenu(null))
|
|
176
201
|
]
|
|
177
202
|
});
|
|
178
203
|
};
|