@strapi/upload 5.58.0 → 5.59.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/components/MediaLibraryInput/AddAssetMenu.js +141 -0
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs +139 -0
- package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.js +129 -0
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.mjs +127 -0
- package/dist/admin/components/MediaLibraryInput/AssetDropZone.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetRow.js +144 -0
- package/dist/admin/components/MediaLibraryInput/AssetRow.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/AssetRow.mjs +142 -0
- package/dist/admin/components/MediaLibraryInput/AssetRow.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js +397 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs +395 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.js +45 -0
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.mjs +43 -0
- package/dist/admin/components/MediaLibraryInput/NoLibraryAccessDialog.mjs.map +1 -0
- package/dist/admin/hooks/useAIMetadataAvailability.js +5 -1
- package/dist/admin/hooks/useAIMetadataAvailability.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataAvailability.mjs +5 -1
- package/dist/admin/hooks/useAIMetadataAvailability.mjs.map +1 -1
- package/dist/admin/hooks/useAIMetadataEnabled.js +7 -1
- package/dist/admin/hooks/useAIMetadataEnabled.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataEnabled.mjs +7 -1
- package/dist/admin/hooks/useAIMetadataEnabled.mjs.map +1 -1
- package/dist/admin/hooks/useMediaLibraryPermissions.js +4 -0
- package/dist/admin/hooks/useMediaLibraryPermissions.js.map +1 -1
- package/dist/admin/hooks/useMediaLibraryPermissions.mjs +4 -0
- package/dist/admin/hooks/useMediaLibraryPermissions.mjs.map +1 -1
- package/dist/admin/hooks/useTracking.js +5 -1
- package/dist/admin/hooks/useTracking.js.map +1 -1
- package/dist/admin/hooks/useTracking.mjs +5 -1
- package/dist/admin/hooks/useTracking.mjs.map +1 -1
- package/dist/admin/index.js +7 -2
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +7 -2
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/legacy/components/AssetCard/AssetCardBase.js.map +1 -1
- package/dist/admin/legacy/components/AssetCard/AssetCardBase.mjs.map +1 -1
- package/dist/admin/legacy/components/AssetCard/VideoPreview.js +2 -1
- package/dist/admin/legacy/components/AssetCard/VideoPreview.js.map +1 -1
- package/dist/admin/legacy/components/AssetCard/VideoPreview.mjs +2 -1
- package/dist/admin/legacy/components/AssetCard/VideoPreview.mjs.map +1 -1
- package/dist/admin/legacy/components/AssetDialog/AssetDialog.js +3 -1
- package/dist/admin/legacy/components/AssetDialog/AssetDialog.js.map +1 -1
- package/dist/admin/legacy/components/AssetDialog/AssetDialog.mjs +3 -1
- package/dist/admin/legacy/components/AssetDialog/AssetDialog.mjs.map +1 -1
- package/dist/admin/legacy/components/AssetDialog/BrowseStep/BrowseStep.js +3 -1
- package/dist/admin/legacy/components/AssetDialog/BrowseStep/BrowseStep.js.map +1 -1
- package/dist/admin/legacy/components/AssetDialog/BrowseStep/BrowseStep.mjs +3 -1
- package/dist/admin/legacy/components/AssetDialog/BrowseStep/BrowseStep.mjs.map +1 -1
- package/dist/admin/legacy/components/AssetDialog/BrowseStep/Filters.js.map +1 -1
- package/dist/admin/legacy/components/AssetDialog/BrowseStep/Filters.mjs.map +1 -1
- package/dist/admin/legacy/components/AssetGridList/AssetGridList.js +7 -6
- package/dist/admin/legacy/components/AssetGridList/AssetGridList.js.map +1 -1
- package/dist/admin/legacy/components/AssetGridList/AssetGridList.mjs +7 -6
- package/dist/admin/legacy/components/AssetGridList/AssetGridList.mjs.map +1 -1
- package/dist/admin/legacy/components/Breadcrumbs/CrumbSimpleMenuAsync.js +2 -1
- package/dist/admin/legacy/components/Breadcrumbs/CrumbSimpleMenuAsync.js.map +1 -1
- package/dist/admin/legacy/components/Breadcrumbs/CrumbSimpleMenuAsync.mjs +2 -1
- package/dist/admin/legacy/components/Breadcrumbs/CrumbSimpleMenuAsync.mjs.map +1 -1
- package/dist/admin/legacy/components/BulkMoveDialog/BulkMoveDialog.js +2 -1
- package/dist/admin/legacy/components/BulkMoveDialog/BulkMoveDialog.js.map +1 -1
- package/dist/admin/legacy/components/BulkMoveDialog/BulkMoveDialog.mjs +2 -1
- package/dist/admin/legacy/components/BulkMoveDialog/BulkMoveDialog.mjs.map +1 -1
- package/dist/admin/legacy/components/EditAssetDialog/EditAssetContent.js +3 -1
- package/dist/admin/legacy/components/EditAssetDialog/EditAssetContent.js.map +1 -1
- package/dist/admin/legacy/components/EditAssetDialog/EditAssetContent.mjs +3 -1
- package/dist/admin/legacy/components/EditAssetDialog/EditAssetContent.mjs.map +1 -1
- package/dist/admin/legacy/components/FilterList/FilterList.js.map +1 -1
- package/dist/admin/legacy/components/FilterList/FilterList.mjs.map +1 -1
- package/dist/admin/legacy/components/FilterPopover/FilterPopover.js.map +1 -1
- package/dist/admin/legacy/components/FilterPopover/FilterPopover.mjs.map +1 -1
- package/dist/admin/legacy/components/FilterPopover/FilterValueInput.js +2 -1
- package/dist/admin/legacy/components/FilterPopover/FilterValueInput.js.map +1 -1
- package/dist/admin/legacy/components/FilterPopover/FilterValueInput.mjs +2 -1
- package/dist/admin/legacy/components/FilterPopover/FilterValueInput.mjs.map +1 -1
- package/dist/admin/legacy/components/MediaLibraryDialog/MediaLibraryDialog.js +4 -2
- package/dist/admin/legacy/components/MediaLibraryDialog/MediaLibraryDialog.js.map +1 -1
- package/dist/admin/legacy/components/MediaLibraryDialog/MediaLibraryDialog.mjs +4 -2
- package/dist/admin/legacy/components/MediaLibraryDialog/MediaLibraryDialog.mjs.map +1 -1
- package/dist/admin/legacy/components/MediaLibraryInput/MediaLibraryInput.js +2 -1
- package/dist/admin/legacy/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -1
- package/dist/admin/legacy/components/MediaLibraryInput/MediaLibraryInput.mjs +2 -1
- package/dist/admin/legacy/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -1
- package/dist/admin/legacy/components/SelectTree/SelectTree.js +3 -1
- package/dist/admin/legacy/components/SelectTree/SelectTree.js.map +1 -1
- package/dist/admin/legacy/components/SelectTree/SelectTree.mjs +3 -1
- package/dist/admin/legacy/components/SelectTree/SelectTree.mjs.map +1 -1
- package/dist/admin/legacy/components/TableList/TableList.js +3 -1
- package/dist/admin/legacy/components/TableList/TableList.js.map +1 -1
- package/dist/admin/legacy/components/TableList/TableList.mjs +3 -1
- package/dist/admin/legacy/components/TableList/TableList.mjs.map +1 -1
- package/dist/admin/legacy/components/TableList/TableRows.js +3 -1
- package/dist/admin/legacy/components/TableList/TableRows.js.map +1 -1
- package/dist/admin/legacy/components/TableList/TableRows.mjs +3 -1
- package/dist/admin/legacy/components/TableList/TableRows.mjs.map +1 -1
- package/dist/admin/legacy/components/UploadAssetDialog/UploadAssetDialog.js +3 -1
- package/dist/admin/legacy/components/UploadAssetDialog/UploadAssetDialog.js.map +1 -1
- package/dist/admin/legacy/components/UploadAssetDialog/UploadAssetDialog.mjs +3 -1
- package/dist/admin/legacy/components/UploadAssetDialog/UploadAssetDialog.mjs.map +1 -1
- package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -1
- package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -1
- package/dist/admin/legacy/pages/App/components/BulkActions.js +2 -1
- package/dist/admin/legacy/pages/App/components/BulkActions.js.map +1 -1
- package/dist/admin/legacy/pages/App/components/BulkActions.mjs +2 -1
- package/dist/admin/legacy/pages/App/components/BulkActions.mjs.map +1 -1
- package/dist/admin/legacy/pages/App/components/BulkMoveButton.js +2 -1
- package/dist/admin/legacy/pages/App/components/BulkMoveButton.js.map +1 -1
- package/dist/admin/legacy/pages/App/components/BulkMoveButton.mjs +2 -1
- package/dist/admin/legacy/pages/App/components/BulkMoveButton.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.js +2 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.mjs +2 -1
- package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsTable.js +2 -1
- package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/pages/Assets/components/AssetsTable.mjs +2 -1
- package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/BulkActionsBar.js +3 -1
- package/dist/admin/pages/Assets/components/BulkActionsBar.js.map +1 -1
- package/dist/admin/pages/Assets/components/BulkActionsBar.mjs +3 -1
- package/dist/admin/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/DateRangeCalendar.js +10 -7
- package/dist/admin/pages/Assets/components/DateRangeCalendar.js.map +1 -1
- package/dist/admin/pages/Assets/components/DateRangeCalendar.mjs +10 -7
- package/dist/admin/pages/Assets/components/DateRangeCalendar.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/DropZone/UploadDropZoneContext.js +4 -2
- package/dist/admin/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -1
- package/dist/admin/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +5 -3
- package/dist/admin/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -1
- package/dist/admin/pages/Assets/components/FilterBadges.js +32 -3
- package/dist/admin/pages/Assets/components/FilterBadges.js.map +1 -1
- package/dist/admin/pages/Assets/components/FilterBadges.mjs +33 -4
- package/dist/admin/pages/Assets/components/FilterBadges.mjs.map +1 -1
- package/dist/admin/services/api.js +15 -5
- package/dist/admin/services/api.js.map +1 -1
- package/dist/admin/services/api.mjs +15 -5
- package/dist/admin/services/api.mjs.map +1 -1
- package/dist/admin/src/components/MediaLibraryInput/AddAssetMenu.d.ts +19 -0
- package/dist/admin/src/components/MediaLibraryInput/AssetDropZone.d.ts +13 -0
- package/dist/admin/src/components/MediaLibraryInput/AssetRow.d.ts +15 -0
- package/dist/admin/src/components/MediaLibraryInput/MediaLibraryInput.d.ts +26 -0
- package/dist/admin/src/components/MediaLibraryInput/NoLibraryAccessDialog.d.ts +10 -0
- package/dist/admin/src/hooks/useMediaLibraryPermissions.d.ts +1 -0
- package/dist/admin/src/legacy/components/BulkMoveDialog/BulkMoveDialog.d.ts +1 -1
- package/dist/admin/src/legacy/pages/App/components/BulkActions.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +6 -0
- package/dist/admin/src/utils/allowedMediaTypes.d.ts +16 -0
- package/dist/admin/translations/ca.json.js +3 -3
- package/dist/admin/translations/ca.json.mjs +3 -3
- package/dist/admin/translations/da.json.js +1 -1
- package/dist/admin/translations/da.json.mjs +1 -1
- package/dist/admin/translations/de.json.js +1 -1
- package/dist/admin/translations/de.json.mjs +1 -1
- package/dist/admin/translations/en.json.js +9 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +9 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/translations/es.json.js +1 -1
- package/dist/admin/translations/es.json.mjs +1 -1
- package/dist/admin/translations/sk.json.js +2 -2
- package/dist/admin/translations/sk.json.mjs +2 -2
- package/dist/admin/translations/tr.json.js +2 -2
- package/dist/admin/translations/tr.json.mjs +2 -2
- package/dist/admin/translations/zh-Hans.json.js +1 -1
- package/dist/admin/translations/zh-Hans.json.mjs +1 -1
- package/dist/admin/translations/zh.json.js +2 -2
- package/dist/admin/translations/zh.json.mjs +2 -2
- package/dist/admin/utils/allowedMediaTypes.js +42 -0
- package/dist/admin/utils/allowedMediaTypes.js.map +1 -0
- package/dist/admin/utils/allowedMediaTypes.mjs +39 -0
- package/dist/admin/utils/allowedMediaTypes.mjs.map +1 -0
- package/dist/server/config.js +6 -0
- package/dist/server/config.js.map +1 -1
- package/dist/server/config.mjs +6 -0
- package/dist/server/config.mjs.map +1 -1
- package/dist/server/controllers/validation/admin/upload.js.map +1 -1
- package/dist/server/controllers/validation/admin/upload.mjs.map +1 -1
- package/dist/server/controllers/validation/content-api/upload.js.map +1 -1
- package/dist/server/controllers/validation/content-api/upload.mjs.map +1 -1
- package/dist/server/mcp/ambient-instance.js +7 -5
- package/dist/server/mcp/ambient-instance.js.map +1 -1
- package/dist/server/mcp/ambient-instance.mjs +7 -5
- package/dist/server/mcp/ambient-instance.mjs.map +1 -1
- package/dist/server/mcp/handlers/folder-handlers.js +4 -16
- package/dist/server/mcp/handlers/folder-handlers.js.map +1 -1
- package/dist/server/mcp/handlers/folder-handlers.mjs +5 -17
- package/dist/server/mcp/handlers/folder-handlers.mjs.map +1 -1
- package/dist/server/mcp/handlers/read-handlers.js +6 -14
- package/dist/server/mcp/handlers/read-handlers.js.map +1 -1
- package/dist/server/mcp/handlers/read-handlers.mjs +7 -15
- package/dist/server/mcp/handlers/read-handlers.mjs.map +1 -1
- package/dist/server/mcp/handlers/write-handlers.js +3 -13
- package/dist/server/mcp/handlers/write-handlers.js.map +1 -1
- package/dist/server/mcp/handlers/write-handlers.mjs +3 -13
- package/dist/server/mcp/handlers/write-handlers.mjs.map +1 -1
- package/dist/server/mcp/register-upload-mcp-tools.js +215 -195
- package/dist/server/mcp/register-upload-mcp-tools.js.map +1 -1
- package/dist/server/mcp/register-upload-mcp-tools.mjs +215 -195
- package/dist/server/mcp/register-upload-mcp-tools.mjs.map +1 -1
- package/dist/server/services/image-manipulation.js +33 -14
- package/dist/server/services/image-manipulation.js.map +1 -1
- package/dist/server/services/image-manipulation.mjs +33 -14
- package/dist/server/services/image-manipulation.mjs.map +1 -1
- package/dist/server/src/config.d.ts +3 -0
- package/dist/server/src/config.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/admin/upload.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/content-api/upload.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +3 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/mcp/ambient-instance.d.ts +7 -5
- package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
- package/dist/server/src/mcp/handlers/folder-handlers.d.ts.map +1 -1
- package/dist/server/src/mcp/handlers/read-handlers.d.ts +3 -2
- package/dist/server/src/mcp/handlers/read-handlers.d.ts.map +1 -1
- package/dist/server/src/mcp/handlers/write-handlers.d.ts.map +1 -1
- package/dist/server/src/mcp/register-upload-mcp-tools.d.ts +9 -14
- package/dist/server/src/mcp/register-upload-mcp-tools.d.ts.map +1 -1
- package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
- package/dist/server/src/types.d.ts +1 -0
- package/dist/server/src/types.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,141 @@
|
|
|
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 useMediaLibraryPermissions = require('../../hooks/useMediaLibraryPermissions.js');
|
|
9
|
+
var ActionsMenuContent = require('../../pages/Assets/components/ActionsMenuContent.js');
|
|
10
|
+
var translations = require('../../utils/translations.js');
|
|
11
|
+
|
|
12
|
+
// The trigger reads as a link on the label row, not as a button: no padding, no
|
|
13
|
+
// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the
|
|
14
|
+
// colour is set here and forced past the design system's own span rule.
|
|
15
|
+
const AddAssetTrigger = styledComponents.styled(designSystem.Menu.Trigger)`
|
|
16
|
+
padding: 0;
|
|
17
|
+
|
|
18
|
+
// No hover treatment at all: this reads as a link on the label row, and the
|
|
19
|
+
// design system's ghost button paints a primary100 plate behind it (also while
|
|
20
|
+
// the menu is open, via data-state).
|
|
21
|
+
&,
|
|
22
|
+
&:hover,
|
|
23
|
+
&[data-state='open'] {
|
|
24
|
+
background: transparent;
|
|
25
|
+
background-color: transparent;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&,
|
|
29
|
+
& span,
|
|
30
|
+
&:hover span {
|
|
31
|
+
color: ${({ theme })=>theme.colors.primary600};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
& span {
|
|
35
|
+
font-weight: ${({ theme })=>theme.fontWeights.regular};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// The chevron needs the fill, not the colour: the design system paints button
|
|
39
|
+
// icons with its own "svg path { fill }" rule per variant, and repaints them
|
|
40
|
+
// again on hover — both beat an inherited color and the icon's own
|
|
41
|
+
// fill="currentColor". Doubled specificity so these land after those rules
|
|
42
|
+
// whatever order they are injected in.
|
|
43
|
+
&& svg path,
|
|
44
|
+
&&:hover svg path {
|
|
45
|
+
fill: ${({ theme })=>theme.colors.primary600};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// The design system's disabled button is a bordered grey plate; this stays a
|
|
49
|
+
// greyed-out link instead.
|
|
50
|
+
&&[aria-disabled='true'] {
|
|
51
|
+
border-color: transparent;
|
|
52
|
+
background: transparent;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&[aria-disabled='true'],
|
|
56
|
+
&[aria-disabled='true'] span {
|
|
57
|
+
color: ${({ theme })=>theme.colors.neutral500};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&&[aria-disabled='true'] svg path {
|
|
61
|
+
fill: ${({ theme })=>theme.colors.neutral500};
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
/**
|
|
65
|
+
* The field's "Add asset" menu, on the label row.
|
|
66
|
+
*
|
|
67
|
+
* Browsing needs the Media Library's read permission, the two upload entries
|
|
68
|
+
* `assets.create`; each entry disappears without its permission, and the
|
|
69
|
+
* trigger itself goes when nothing is left to offer, rather than opening an
|
|
70
|
+
* empty menu.
|
|
71
|
+
*
|
|
72
|
+
* The drop zone below keeps working whatever this shows — it is a second way
|
|
73
|
+
* in, not the only one.
|
|
74
|
+
*/ const AddAssetMenu = ({ disabled = false, onBrowseLibrary, onUploadFromDevice, onUploadFromUrl })=>{
|
|
75
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
76
|
+
const { canRead, canCreate, isLoading } = useMediaLibraryPermissions.useMediaLibraryPermissions();
|
|
77
|
+
// `useRBAC` starts every instance at `isLoading: true` with the flags false.
|
|
78
|
+
// Until it settles, every entry shows but none can be picked: hiding them
|
|
79
|
+
// would flash a smaller menu, enabling them would lead to a 403.
|
|
80
|
+
const canBrowse = isLoading || canRead;
|
|
81
|
+
const canUpload = isLoading || canCreate;
|
|
82
|
+
if (!canBrowse && !canUpload) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Menu.Root, {
|
|
86
|
+
children: [
|
|
87
|
+
/*#__PURE__*/ jsxRuntime.jsx(AddAssetTrigger, {
|
|
88
|
+
variant: "ghost",
|
|
89
|
+
disabled: disabled,
|
|
90
|
+
endIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.ChevronDown, {
|
|
91
|
+
"aria-hidden": true
|
|
92
|
+
}),
|
|
93
|
+
children: formatMessage({
|
|
94
|
+
id: translations.getTranslationKey('content-manager.input.add-asset'),
|
|
95
|
+
defaultMessage: 'Add asset'
|
|
96
|
+
})
|
|
97
|
+
}),
|
|
98
|
+
/*#__PURE__*/ jsxRuntime.jsxs(ActionsMenuContent.ActionsMenuContent, {
|
|
99
|
+
popoverPlacement: "bottom-end",
|
|
100
|
+
zIndex: 2,
|
|
101
|
+
minWidth: "22rem",
|
|
102
|
+
children: [
|
|
103
|
+
canBrowse && /*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
|
|
104
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Images, {}),
|
|
105
|
+
disabled: isLoading,
|
|
106
|
+
onSelect: onBrowseLibrary,
|
|
107
|
+
children: formatMessage({
|
|
108
|
+
id: translations.getTranslationKey('content-manager.input.add-asset.browse'),
|
|
109
|
+
defaultMessage: 'Browse library'
|
|
110
|
+
})
|
|
111
|
+
}),
|
|
112
|
+
canUpload && /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
113
|
+
children: [
|
|
114
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
|
|
115
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Upload, {}),
|
|
116
|
+
disabled: isLoading,
|
|
117
|
+
onSelect: onUploadFromDevice,
|
|
118
|
+
children: formatMessage({
|
|
119
|
+
id: translations.getTranslationKey('content-manager.input.add-asset.device'),
|
|
120
|
+
defaultMessage: 'Upload from device'
|
|
121
|
+
})
|
|
122
|
+
}),
|
|
123
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Menu.Item, {
|
|
124
|
+
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Link, {}),
|
|
125
|
+
disabled: isLoading,
|
|
126
|
+
onSelect: onUploadFromUrl,
|
|
127
|
+
children: formatMessage({
|
|
128
|
+
id: translations.getTranslationKey('content-manager.input.add-asset.url'),
|
|
129
|
+
defaultMessage: 'Upload from URL'
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
})
|
|
134
|
+
]
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
exports.AddAssetMenu = AddAssetMenu;
|
|
141
|
+
//# sourceMappingURL=AddAssetMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddAssetMenu.js","sources":["../../../../admin/src/components/MediaLibraryInput/AddAssetMenu.tsx"],"sourcesContent":["import { Menu } from '@strapi/design-system';\nimport { ChevronDown, Images, Link, Upload } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { ActionsMenuContent } from '../../pages/Assets/components/ActionsMenuContent';\nimport { getTranslationKey } from '../../utils/translations';\n\n// The trigger reads as a link on the label row, not as a button: no padding, no\n// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the\n// colour is set here and forced past the design system's own span rule.\nconst AddAssetTrigger = styled(Menu.Trigger)`\n padding: 0;\n\n // No hover treatment at all: this reads as a link on the label row, and the\n // design system's ghost button paints a primary100 plate behind it (also while\n // the menu is open, via data-state).\n &,\n &:hover,\n &[data-state='open'] {\n background: transparent;\n background-color: transparent;\n }\n\n &,\n & span,\n &:hover span {\n color: ${({ theme }) => theme.colors.primary600};\n }\n\n & span {\n font-weight: ${({ theme }) => theme.fontWeights.regular};\n }\n\n // The chevron needs the fill, not the colour: the design system paints button\n // icons with its own \"svg path { fill }\" rule per variant, and repaints them\n // again on hover — both beat an inherited color and the icon's own\n // fill=\"currentColor\". Doubled specificity so these land after those rules\n // whatever order they are injected in.\n && svg path,\n &&:hover svg path {\n fill: ${({ theme }) => theme.colors.primary600};\n }\n\n // The design system's disabled button is a bordered grey plate; this stays a\n // greyed-out link instead.\n &&[aria-disabled='true'] {\n border-color: transparent;\n background: transparent;\n }\n\n &[aria-disabled='true'],\n &[aria-disabled='true'] span {\n color: ${({ theme }) => theme.colors.neutral500};\n }\n\n &&[aria-disabled='true'] svg path {\n fill: ${({ theme }) => theme.colors.neutral500};\n }\n`;\n\ninterface AddAssetMenuProps {\n disabled?: boolean;\n onBrowseLibrary: () => void;\n onUploadFromDevice: () => void;\n onUploadFromUrl: () => void;\n}\n\n/**\n * The field's \"Add asset\" menu, on the label row.\n *\n * Browsing needs the Media Library's read permission, the two upload entries\n * `assets.create`; each entry disappears without its permission, and the\n * trigger itself goes when nothing is left to offer, rather than opening an\n * empty menu.\n *\n * The drop zone below keeps working whatever this shows — it is a second way\n * in, not the only one.\n */\nexport const AddAssetMenu = ({\n disabled = false,\n onBrowseLibrary,\n onUploadFromDevice,\n onUploadFromUrl,\n}: AddAssetMenuProps) => {\n const { formatMessage } = useIntl();\n const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();\n\n // `useRBAC` starts every instance at `isLoading: true` with the flags false.\n // Until it settles, every entry shows but none can be picked: hiding them\n // would flash a smaller menu, enabling them would lead to a 403.\n const canBrowse = isLoading || canRead;\n const canUpload = isLoading || canCreate;\n\n if (!canBrowse && !canUpload) {\n return null;\n }\n\n return (\n <Menu.Root>\n <AddAssetTrigger variant=\"ghost\" disabled={disabled} endIcon={<ChevronDown aria-hidden />}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset'),\n defaultMessage: 'Add asset',\n })}\n </AddAssetTrigger>\n\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canBrowse && (\n <Menu.Item startIcon={<Images />} disabled={isLoading} onSelect={onBrowseLibrary}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.browse'),\n defaultMessage: 'Browse library',\n })}\n </Menu.Item>\n )}\n\n {canUpload && (\n <>\n <Menu.Item startIcon={<Upload />} disabled={isLoading} onSelect={onUploadFromDevice}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.device'),\n defaultMessage: 'Upload from device',\n })}\n </Menu.Item>\n\n <Menu.Item startIcon={<Link />} disabled={isLoading} onSelect={onUploadFromUrl}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.url'),\n defaultMessage: 'Upload from URL',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n );\n};\n"],"names":["AddAssetTrigger","styled","Menu","Trigger","theme","colors","primary600","fontWeights","regular","neutral500","AddAssetMenu","disabled","onBrowseLibrary","onUploadFromDevice","onUploadFromUrl","formatMessage","useIntl","canRead","canCreate","isLoading","useMediaLibraryPermissions","canBrowse","canUpload","_jsxs","Root","_jsx","variant","endIcon","ChevronDown","aria-hidden","id","getTranslationKey","defaultMessage","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","Images","onSelect","_Fragment","Upload","Link"],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { Menu } from '@strapi/design-system';
|
|
3
|
+
import { ChevronDown, Images, Upload, Link } from '@strapi/icons';
|
|
4
|
+
import { useIntl } from 'react-intl';
|
|
5
|
+
import { styled } from 'styled-components';
|
|
6
|
+
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions.mjs';
|
|
7
|
+
import { ActionsMenuContent } from '../../pages/Assets/components/ActionsMenuContent.mjs';
|
|
8
|
+
import { getTranslationKey } from '../../utils/translations.mjs';
|
|
9
|
+
|
|
10
|
+
// The trigger reads as a link on the label row, not as a button: no padding, no
|
|
11
|
+
// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the
|
|
12
|
+
// colour is set here and forced past the design system's own span rule.
|
|
13
|
+
const AddAssetTrigger = styled(Menu.Trigger)`
|
|
14
|
+
padding: 0;
|
|
15
|
+
|
|
16
|
+
// No hover treatment at all: this reads as a link on the label row, and the
|
|
17
|
+
// design system's ghost button paints a primary100 plate behind it (also while
|
|
18
|
+
// the menu is open, via data-state).
|
|
19
|
+
&,
|
|
20
|
+
&:hover,
|
|
21
|
+
&[data-state='open'] {
|
|
22
|
+
background: transparent;
|
|
23
|
+
background-color: transparent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&,
|
|
27
|
+
& span,
|
|
28
|
+
&:hover span {
|
|
29
|
+
color: ${({ theme })=>theme.colors.primary600};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
& span {
|
|
33
|
+
font-weight: ${({ theme })=>theme.fontWeights.regular};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The chevron needs the fill, not the colour: the design system paints button
|
|
37
|
+
// icons with its own "svg path { fill }" rule per variant, and repaints them
|
|
38
|
+
// again on hover — both beat an inherited color and the icon's own
|
|
39
|
+
// fill="currentColor". Doubled specificity so these land after those rules
|
|
40
|
+
// whatever order they are injected in.
|
|
41
|
+
&& svg path,
|
|
42
|
+
&&:hover svg path {
|
|
43
|
+
fill: ${({ theme })=>theme.colors.primary600};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// The design system's disabled button is a bordered grey plate; this stays a
|
|
47
|
+
// greyed-out link instead.
|
|
48
|
+
&&[aria-disabled='true'] {
|
|
49
|
+
border-color: transparent;
|
|
50
|
+
background: transparent;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&[aria-disabled='true'],
|
|
54
|
+
&[aria-disabled='true'] span {
|
|
55
|
+
color: ${({ theme })=>theme.colors.neutral500};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&&[aria-disabled='true'] svg path {
|
|
59
|
+
fill: ${({ theme })=>theme.colors.neutral500};
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
/**
|
|
63
|
+
* The field's "Add asset" menu, on the label row.
|
|
64
|
+
*
|
|
65
|
+
* Browsing needs the Media Library's read permission, the two upload entries
|
|
66
|
+
* `assets.create`; each entry disappears without its permission, and the
|
|
67
|
+
* trigger itself goes when nothing is left to offer, rather than opening an
|
|
68
|
+
* empty menu.
|
|
69
|
+
*
|
|
70
|
+
* The drop zone below keeps working whatever this shows — it is a second way
|
|
71
|
+
* in, not the only one.
|
|
72
|
+
*/ const AddAssetMenu = ({ disabled = false, onBrowseLibrary, onUploadFromDevice, onUploadFromUrl })=>{
|
|
73
|
+
const { formatMessage } = useIntl();
|
|
74
|
+
const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();
|
|
75
|
+
// `useRBAC` starts every instance at `isLoading: true` with the flags false.
|
|
76
|
+
// Until it settles, every entry shows but none can be picked: hiding them
|
|
77
|
+
// would flash a smaller menu, enabling them would lead to a 403.
|
|
78
|
+
const canBrowse = isLoading || canRead;
|
|
79
|
+
const canUpload = isLoading || canCreate;
|
|
80
|
+
if (!canBrowse && !canUpload) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return /*#__PURE__*/ jsxs(Menu.Root, {
|
|
84
|
+
children: [
|
|
85
|
+
/*#__PURE__*/ jsx(AddAssetTrigger, {
|
|
86
|
+
variant: "ghost",
|
|
87
|
+
disabled: disabled,
|
|
88
|
+
endIcon: /*#__PURE__*/ jsx(ChevronDown, {
|
|
89
|
+
"aria-hidden": true
|
|
90
|
+
}),
|
|
91
|
+
children: formatMessage({
|
|
92
|
+
id: getTranslationKey('content-manager.input.add-asset'),
|
|
93
|
+
defaultMessage: 'Add asset'
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
/*#__PURE__*/ jsxs(ActionsMenuContent, {
|
|
97
|
+
popoverPlacement: "bottom-end",
|
|
98
|
+
zIndex: 2,
|
|
99
|
+
minWidth: "22rem",
|
|
100
|
+
children: [
|
|
101
|
+
canBrowse && /*#__PURE__*/ jsx(Menu.Item, {
|
|
102
|
+
startIcon: /*#__PURE__*/ jsx(Images, {}),
|
|
103
|
+
disabled: isLoading,
|
|
104
|
+
onSelect: onBrowseLibrary,
|
|
105
|
+
children: formatMessage({
|
|
106
|
+
id: getTranslationKey('content-manager.input.add-asset.browse'),
|
|
107
|
+
defaultMessage: 'Browse library'
|
|
108
|
+
})
|
|
109
|
+
}),
|
|
110
|
+
canUpload && /*#__PURE__*/ jsxs(Fragment, {
|
|
111
|
+
children: [
|
|
112
|
+
/*#__PURE__*/ jsx(Menu.Item, {
|
|
113
|
+
startIcon: /*#__PURE__*/ jsx(Upload, {}),
|
|
114
|
+
disabled: isLoading,
|
|
115
|
+
onSelect: onUploadFromDevice,
|
|
116
|
+
children: formatMessage({
|
|
117
|
+
id: getTranslationKey('content-manager.input.add-asset.device'),
|
|
118
|
+
defaultMessage: 'Upload from device'
|
|
119
|
+
})
|
|
120
|
+
}),
|
|
121
|
+
/*#__PURE__*/ jsx(Menu.Item, {
|
|
122
|
+
startIcon: /*#__PURE__*/ jsx(Link, {}),
|
|
123
|
+
disabled: isLoading,
|
|
124
|
+
onSelect: onUploadFromUrl,
|
|
125
|
+
children: formatMessage({
|
|
126
|
+
id: getTranslationKey('content-manager.input.add-asset.url'),
|
|
127
|
+
defaultMessage: 'Upload from URL'
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
})
|
|
134
|
+
]
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export { AddAssetMenu };
|
|
139
|
+
//# sourceMappingURL=AddAssetMenu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddAssetMenu.mjs","sources":["../../../../admin/src/components/MediaLibraryInput/AddAssetMenu.tsx"],"sourcesContent":["import { Menu } from '@strapi/design-system';\nimport { ChevronDown, Images, Link, Upload } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';\nimport { ActionsMenuContent } from '../../pages/Assets/components/ActionsMenuContent';\nimport { getTranslationKey } from '../../utils/translations';\n\n// The trigger reads as a link on the label row, not as a button: no padding, no\n// ghost background, primary text. `Menu.Trigger` takes no `textColor`, so the\n// colour is set here and forced past the design system's own span rule.\nconst AddAssetTrigger = styled(Menu.Trigger)`\n padding: 0;\n\n // No hover treatment at all: this reads as a link on the label row, and the\n // design system's ghost button paints a primary100 plate behind it (also while\n // the menu is open, via data-state).\n &,\n &:hover,\n &[data-state='open'] {\n background: transparent;\n background-color: transparent;\n }\n\n &,\n & span,\n &:hover span {\n color: ${({ theme }) => theme.colors.primary600};\n }\n\n & span {\n font-weight: ${({ theme }) => theme.fontWeights.regular};\n }\n\n // The chevron needs the fill, not the colour: the design system paints button\n // icons with its own \"svg path { fill }\" rule per variant, and repaints them\n // again on hover — both beat an inherited color and the icon's own\n // fill=\"currentColor\". Doubled specificity so these land after those rules\n // whatever order they are injected in.\n && svg path,\n &&:hover svg path {\n fill: ${({ theme }) => theme.colors.primary600};\n }\n\n // The design system's disabled button is a bordered grey plate; this stays a\n // greyed-out link instead.\n &&[aria-disabled='true'] {\n border-color: transparent;\n background: transparent;\n }\n\n &[aria-disabled='true'],\n &[aria-disabled='true'] span {\n color: ${({ theme }) => theme.colors.neutral500};\n }\n\n &&[aria-disabled='true'] svg path {\n fill: ${({ theme }) => theme.colors.neutral500};\n }\n`;\n\ninterface AddAssetMenuProps {\n disabled?: boolean;\n onBrowseLibrary: () => void;\n onUploadFromDevice: () => void;\n onUploadFromUrl: () => void;\n}\n\n/**\n * The field's \"Add asset\" menu, on the label row.\n *\n * Browsing needs the Media Library's read permission, the two upload entries\n * `assets.create`; each entry disappears without its permission, and the\n * trigger itself goes when nothing is left to offer, rather than opening an\n * empty menu.\n *\n * The drop zone below keeps working whatever this shows — it is a second way\n * in, not the only one.\n */\nexport const AddAssetMenu = ({\n disabled = false,\n onBrowseLibrary,\n onUploadFromDevice,\n onUploadFromUrl,\n}: AddAssetMenuProps) => {\n const { formatMessage } = useIntl();\n const { canRead, canCreate, isLoading } = useMediaLibraryPermissions();\n\n // `useRBAC` starts every instance at `isLoading: true` with the flags false.\n // Until it settles, every entry shows but none can be picked: hiding them\n // would flash a smaller menu, enabling them would lead to a 403.\n const canBrowse = isLoading || canRead;\n const canUpload = isLoading || canCreate;\n\n if (!canBrowse && !canUpload) {\n return null;\n }\n\n return (\n <Menu.Root>\n <AddAssetTrigger variant=\"ghost\" disabled={disabled} endIcon={<ChevronDown aria-hidden />}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset'),\n defaultMessage: 'Add asset',\n })}\n </AddAssetTrigger>\n\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n {canBrowse && (\n <Menu.Item startIcon={<Images />} disabled={isLoading} onSelect={onBrowseLibrary}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.browse'),\n defaultMessage: 'Browse library',\n })}\n </Menu.Item>\n )}\n\n {canUpload && (\n <>\n <Menu.Item startIcon={<Upload />} disabled={isLoading} onSelect={onUploadFromDevice}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.device'),\n defaultMessage: 'Upload from device',\n })}\n </Menu.Item>\n\n <Menu.Item startIcon={<Link />} disabled={isLoading} onSelect={onUploadFromUrl}>\n {formatMessage({\n id: getTranslationKey('content-manager.input.add-asset.url'),\n defaultMessage: 'Upload from URL',\n })}\n </Menu.Item>\n </>\n )}\n </ActionsMenuContent>\n </Menu.Root>\n );\n};\n"],"names":["AddAssetTrigger","styled","Menu","Trigger","theme","colors","primary600","fontWeights","regular","neutral500","AddAssetMenu","disabled","onBrowseLibrary","onUploadFromDevice","onUploadFromUrl","formatMessage","useIntl","canRead","canCreate","isLoading","useMediaLibraryPermissions","canBrowse","canUpload","_jsxs","Root","_jsx","variant","endIcon","ChevronDown","aria-hidden","id","getTranslationKey","defaultMessage","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","Images","onSelect","_Fragment","Upload","Link"],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var designSystem = require('@strapi/design-system');
|
|
6
|
+
var icons = require('@strapi/icons');
|
|
7
|
+
var reactIntl = require('react-intl');
|
|
8
|
+
var styledComponents = require('styled-components');
|
|
9
|
+
var translations = require('../../utils/translations.js');
|
|
10
|
+
|
|
11
|
+
const Zone = styledComponents.styled.button`
|
|
12
|
+
position: relative;
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
gap: ${({ theme })=>theme.spaces[2]};
|
|
18
|
+
width: 100%;
|
|
19
|
+
min-height: 12rem;
|
|
20
|
+
padding: ${({ theme })=>theme.spaces[6]};
|
|
21
|
+
border: 1px solid ${({ theme })=>theme.colors.neutral200};
|
|
22
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
23
|
+
background: ${({ theme })=>theme.colors.neutral100};
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
|
|
26
|
+
// Only while a file is dragged over the zone: it marks where the file will
|
|
27
|
+
// land, so it has nothing to say to a pointer that is merely passing through.
|
|
28
|
+
// Drawn inside rather than on the box itself, so the field keeps its own
|
|
29
|
+
// outline and the invitation reads as an area to drop into.
|
|
30
|
+
&::after {
|
|
31
|
+
content: '';
|
|
32
|
+
position: absolute;
|
|
33
|
+
inset: ${({ theme })=>theme.spaces[2]} ${({ theme })=>theme.spaces[4]};
|
|
34
|
+
border: 1px dashed ${({ theme })=>theme.colors.primary600};
|
|
35
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
36
|
+
opacity: ${({ $isDragging })=>$isDragging ? 1 : 0};
|
|
37
|
+
pointer-events: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&[aria-disabled='true'] {
|
|
41
|
+
cursor: not-allowed;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&:focus-visible {
|
|
45
|
+
outline: 2px solid ${({ theme })=>theme.colors.primary600};
|
|
46
|
+
outline-offset: 2px;
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
/**
|
|
50
|
+
* The field's own drop target. Deliberately not the Media Library page's
|
|
51
|
+
* `UploadDropZoneProvider`: that one covers a whole route and paints a
|
|
52
|
+
* full-surface overlay, where this has to stay inside one field on a form that
|
|
53
|
+
* may hold several of them.
|
|
54
|
+
*/ const AssetDropZone = ({ disabled = false, onClick, onDropFiles })=>{
|
|
55
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
56
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
57
|
+
// Drag events fire on descendants too, so a plain boolean flickers as the
|
|
58
|
+
// pointer crosses the icon or the label. Counting enter/leave pairs doesn't.
|
|
59
|
+
const dragDepth = React.useRef(0);
|
|
60
|
+
const handleDragEnter = React.useCallback((event)=>{
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
if (disabled || !event.dataTransfer.types.includes('Files')) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
dragDepth.current += 1;
|
|
66
|
+
setIsDragging(true);
|
|
67
|
+
}, [
|
|
68
|
+
disabled
|
|
69
|
+
]);
|
|
70
|
+
const handleDragLeave = React.useCallback((event)=>{
|
|
71
|
+
event.preventDefault();
|
|
72
|
+
dragDepth.current -= 1;
|
|
73
|
+
if (dragDepth.current <= 0) {
|
|
74
|
+
dragDepth.current = 0;
|
|
75
|
+
setIsDragging(false);
|
|
76
|
+
}
|
|
77
|
+
}, []);
|
|
78
|
+
const handleDragOver = React.useCallback((event)=>{
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
event.dataTransfer.dropEffect = 'copy';
|
|
81
|
+
}, []);
|
|
82
|
+
const handleDrop = React.useCallback((event)=>{
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
dragDepth.current = 0;
|
|
85
|
+
setIsDragging(false);
|
|
86
|
+
if (disabled) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const files = Array.from(event.dataTransfer.files ?? []);
|
|
90
|
+
if (files.length > 0) {
|
|
91
|
+
onDropFiles(files);
|
|
92
|
+
}
|
|
93
|
+
}, [
|
|
94
|
+
disabled,
|
|
95
|
+
onDropFiles
|
|
96
|
+
]);
|
|
97
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(Zone, {
|
|
98
|
+
type: "button",
|
|
99
|
+
$isDragging: isDragging,
|
|
100
|
+
"aria-disabled": disabled,
|
|
101
|
+
onClick: ()=>!disabled && onClick(),
|
|
102
|
+
onDragEnter: handleDragEnter,
|
|
103
|
+
onDragLeave: handleDragLeave,
|
|
104
|
+
onDragOver: handleDragOver,
|
|
105
|
+
onDrop: handleDrop,
|
|
106
|
+
children: [
|
|
107
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
108
|
+
justifyContent: "center",
|
|
109
|
+
color: disabled ? 'neutral500' : 'primary600',
|
|
110
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(icons.PlusCircle, {
|
|
111
|
+
width: "3.2rem",
|
|
112
|
+
height: "3.2rem"
|
|
113
|
+
})
|
|
114
|
+
}),
|
|
115
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
116
|
+
textColor: "neutral600",
|
|
117
|
+
fontWeight: "bold",
|
|
118
|
+
variant: "pi",
|
|
119
|
+
children: formatMessage({
|
|
120
|
+
id: translations.getTranslationKey('mediaLibraryInput.placeholder'),
|
|
121
|
+
defaultMessage: 'Click to add an asset or drag and drop one in this area'
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
exports.AssetDropZone = AssetDropZone;
|
|
129
|
+
//# sourceMappingURL=AssetDropZone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetDropZone.js","sources":["../../../../admin/src/components/MediaLibraryInput/AssetDropZone.tsx"],"sourcesContent":["import { useCallback, useRef, useState, type DragEvent } from 'react';\n\nimport { Flex, Typography } from '@strapi/design-system';\nimport { PlusCircle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../utils/translations';\n\nconst Zone = styled.button<{ $isDragging: boolean }>`\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: ${({ theme }) => theme.spaces[2]};\n width: 100%;\n min-height: 12rem;\n padding: ${({ theme }) => theme.spaces[6]};\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.neutral100};\n cursor: pointer;\n\n // Only while a file is dragged over the zone: it marks where the file will\n // land, so it has nothing to say to a pointer that is merely passing through.\n // Drawn inside rather than on the box itself, so the field keeps its own\n // outline and the invitation reads as an area to drop into.\n &::after {\n content: '';\n position: absolute;\n inset: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[4]};\n border: 1px dashed ${({ theme }) => theme.colors.primary600};\n border-radius: ${({ theme }) => theme.borderRadius};\n opacity: ${({ $isDragging }) => ($isDragging ? 1 : 0)};\n pointer-events: none;\n }\n\n &[aria-disabled='true'] {\n cursor: not-allowed;\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: 2px;\n }\n`;\n\ninterface AssetDropZoneProps {\n disabled?: boolean;\n onClick: () => void;\n onDropFiles: (files: globalThis.File[]) => void;\n}\n\n/**\n * The field's own drop target. Deliberately not the Media Library page's\n * `UploadDropZoneProvider`: that one covers a whole route and paints a\n * full-surface overlay, where this has to stay inside one field on a form that\n * may hold several of them.\n */\nexport const AssetDropZone = ({ disabled = false, onClick, onDropFiles }: AssetDropZoneProps) => {\n const { formatMessage } = useIntl();\n const [isDragging, setIsDragging] = useState(false);\n // Drag events fire on descendants too, so a plain boolean flickers as the\n // pointer crosses the icon or the label. Counting enter/leave pairs doesn't.\n const dragDepth = useRef(0);\n\n const handleDragEnter = useCallback(\n (event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n if (disabled || !event.dataTransfer.types.includes('Files')) {\n return;\n }\n dragDepth.current += 1;\n setIsDragging(true);\n },\n [disabled]\n );\n\n const handleDragLeave = useCallback((event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n dragDepth.current -= 1;\n if (dragDepth.current <= 0) {\n dragDepth.current = 0;\n setIsDragging(false);\n }\n }, []);\n\n const handleDragOver = useCallback((event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n event.dataTransfer.dropEffect = 'copy';\n }, []);\n\n const handleDrop = useCallback(\n (event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n dragDepth.current = 0;\n setIsDragging(false);\n\n if (disabled) {\n return;\n }\n\n const files = Array.from(event.dataTransfer.files ?? []);\n if (files.length > 0) {\n onDropFiles(files);\n }\n },\n [disabled, onDropFiles]\n );\n\n return (\n <Zone\n type=\"button\"\n $isDragging={isDragging}\n aria-disabled={disabled}\n onClick={() => !disabled && onClick()}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {/* Same treatment as the repeatable-component initializer, so the two\n empty states in a form read as one affordance. */}\n <Flex justifyContent=\"center\" color={disabled ? 'neutral500' : 'primary600'}>\n <PlusCircle width=\"3.2rem\" height=\"3.2rem\" />\n </Flex>\n <Typography textColor=\"neutral600\" fontWeight=\"bold\" variant=\"pi\">\n {/* The legacy field's own key: identical wording, already translated in\n every locale, where a new key would ship English to all of them. */}\n {formatMessage({\n id: getTranslationKey('mediaLibraryInput.placeholder'),\n defaultMessage: 'Click to add an asset or drag and drop one in this area',\n })}\n </Typography>\n </Zone>\n );\n};\n"],"names":["Zone","styled","button","theme","spaces","colors","neutral200","borderRadius","neutral100","primary600","$isDragging","AssetDropZone","disabled","onClick","onDropFiles","formatMessage","useIntl","isDragging","setIsDragging","useState","dragDepth","useRef","handleDragEnter","useCallback","event","preventDefault","dataTransfer","types","includes","current","handleDragLeave","handleDragOver","dropEffect","handleDrop","files","Array","from","length","_jsxs","type","aria-disabled","onDragEnter","onDragLeave","onDragOver","onDrop","_jsx","Flex","justifyContent","color","PlusCircle","width","height","Typography","textColor","fontWeight","variant","id","getTranslationKey","defaultMessage"],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef, useCallback } from 'react';
|
|
3
|
+
import { Flex, Typography } from '@strapi/design-system';
|
|
4
|
+
import { PlusCircle } from '@strapi/icons';
|
|
5
|
+
import { useIntl } from 'react-intl';
|
|
6
|
+
import { styled } from 'styled-components';
|
|
7
|
+
import { getTranslationKey } from '../../utils/translations.mjs';
|
|
8
|
+
|
|
9
|
+
const Zone = styled.button`
|
|
10
|
+
position: relative;
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
gap: ${({ theme })=>theme.spaces[2]};
|
|
16
|
+
width: 100%;
|
|
17
|
+
min-height: 12rem;
|
|
18
|
+
padding: ${({ theme })=>theme.spaces[6]};
|
|
19
|
+
border: 1px solid ${({ theme })=>theme.colors.neutral200};
|
|
20
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
21
|
+
background: ${({ theme })=>theme.colors.neutral100};
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
|
|
24
|
+
// Only while a file is dragged over the zone: it marks where the file will
|
|
25
|
+
// land, so it has nothing to say to a pointer that is merely passing through.
|
|
26
|
+
// Drawn inside rather than on the box itself, so the field keeps its own
|
|
27
|
+
// outline and the invitation reads as an area to drop into.
|
|
28
|
+
&::after {
|
|
29
|
+
content: '';
|
|
30
|
+
position: absolute;
|
|
31
|
+
inset: ${({ theme })=>theme.spaces[2]} ${({ theme })=>theme.spaces[4]};
|
|
32
|
+
border: 1px dashed ${({ theme })=>theme.colors.primary600};
|
|
33
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
34
|
+
opacity: ${({ $isDragging })=>$isDragging ? 1 : 0};
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&[aria-disabled='true'] {
|
|
39
|
+
cursor: not-allowed;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&:focus-visible {
|
|
43
|
+
outline: 2px solid ${({ theme })=>theme.colors.primary600};
|
|
44
|
+
outline-offset: 2px;
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
/**
|
|
48
|
+
* The field's own drop target. Deliberately not the Media Library page's
|
|
49
|
+
* `UploadDropZoneProvider`: that one covers a whole route and paints a
|
|
50
|
+
* full-surface overlay, where this has to stay inside one field on a form that
|
|
51
|
+
* may hold several of them.
|
|
52
|
+
*/ const AssetDropZone = ({ disabled = false, onClick, onDropFiles })=>{
|
|
53
|
+
const { formatMessage } = useIntl();
|
|
54
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
55
|
+
// Drag events fire on descendants too, so a plain boolean flickers as the
|
|
56
|
+
// pointer crosses the icon or the label. Counting enter/leave pairs doesn't.
|
|
57
|
+
const dragDepth = useRef(0);
|
|
58
|
+
const handleDragEnter = useCallback((event)=>{
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
if (disabled || !event.dataTransfer.types.includes('Files')) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
dragDepth.current += 1;
|
|
64
|
+
setIsDragging(true);
|
|
65
|
+
}, [
|
|
66
|
+
disabled
|
|
67
|
+
]);
|
|
68
|
+
const handleDragLeave = useCallback((event)=>{
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
dragDepth.current -= 1;
|
|
71
|
+
if (dragDepth.current <= 0) {
|
|
72
|
+
dragDepth.current = 0;
|
|
73
|
+
setIsDragging(false);
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
76
|
+
const handleDragOver = useCallback((event)=>{
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
event.dataTransfer.dropEffect = 'copy';
|
|
79
|
+
}, []);
|
|
80
|
+
const handleDrop = useCallback((event)=>{
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
dragDepth.current = 0;
|
|
83
|
+
setIsDragging(false);
|
|
84
|
+
if (disabled) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const files = Array.from(event.dataTransfer.files ?? []);
|
|
88
|
+
if (files.length > 0) {
|
|
89
|
+
onDropFiles(files);
|
|
90
|
+
}
|
|
91
|
+
}, [
|
|
92
|
+
disabled,
|
|
93
|
+
onDropFiles
|
|
94
|
+
]);
|
|
95
|
+
return /*#__PURE__*/ jsxs(Zone, {
|
|
96
|
+
type: "button",
|
|
97
|
+
$isDragging: isDragging,
|
|
98
|
+
"aria-disabled": disabled,
|
|
99
|
+
onClick: ()=>!disabled && onClick(),
|
|
100
|
+
onDragEnter: handleDragEnter,
|
|
101
|
+
onDragLeave: handleDragLeave,
|
|
102
|
+
onDragOver: handleDragOver,
|
|
103
|
+
onDrop: handleDrop,
|
|
104
|
+
children: [
|
|
105
|
+
/*#__PURE__*/ jsx(Flex, {
|
|
106
|
+
justifyContent: "center",
|
|
107
|
+
color: disabled ? 'neutral500' : 'primary600',
|
|
108
|
+
children: /*#__PURE__*/ jsx(PlusCircle, {
|
|
109
|
+
width: "3.2rem",
|
|
110
|
+
height: "3.2rem"
|
|
111
|
+
})
|
|
112
|
+
}),
|
|
113
|
+
/*#__PURE__*/ jsx(Typography, {
|
|
114
|
+
textColor: "neutral600",
|
|
115
|
+
fontWeight: "bold",
|
|
116
|
+
variant: "pi",
|
|
117
|
+
children: formatMessage({
|
|
118
|
+
id: getTranslationKey('mediaLibraryInput.placeholder'),
|
|
119
|
+
defaultMessage: 'Click to add an asset or drag and drop one in this area'
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
]
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export { AssetDropZone };
|
|
127
|
+
//# sourceMappingURL=AssetDropZone.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetDropZone.mjs","sources":["../../../../admin/src/components/MediaLibraryInput/AssetDropZone.tsx"],"sourcesContent":["import { useCallback, useRef, useState, type DragEvent } from 'react';\n\nimport { Flex, Typography } from '@strapi/design-system';\nimport { PlusCircle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../utils/translations';\n\nconst Zone = styled.button<{ $isDragging: boolean }>`\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: ${({ theme }) => theme.spaces[2]};\n width: 100%;\n min-height: 12rem;\n padding: ${({ theme }) => theme.spaces[6]};\n border: 1px solid ${({ theme }) => theme.colors.neutral200};\n border-radius: ${({ theme }) => theme.borderRadius};\n background: ${({ theme }) => theme.colors.neutral100};\n cursor: pointer;\n\n // Only while a file is dragged over the zone: it marks where the file will\n // land, so it has nothing to say to a pointer that is merely passing through.\n // Drawn inside rather than on the box itself, so the field keeps its own\n // outline and the invitation reads as an area to drop into.\n &::after {\n content: '';\n position: absolute;\n inset: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[4]};\n border: 1px dashed ${({ theme }) => theme.colors.primary600};\n border-radius: ${({ theme }) => theme.borderRadius};\n opacity: ${({ $isDragging }) => ($isDragging ? 1 : 0)};\n pointer-events: none;\n }\n\n &[aria-disabled='true'] {\n cursor: not-allowed;\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: 2px;\n }\n`;\n\ninterface AssetDropZoneProps {\n disabled?: boolean;\n onClick: () => void;\n onDropFiles: (files: globalThis.File[]) => void;\n}\n\n/**\n * The field's own drop target. Deliberately not the Media Library page's\n * `UploadDropZoneProvider`: that one covers a whole route and paints a\n * full-surface overlay, where this has to stay inside one field on a form that\n * may hold several of them.\n */\nexport const AssetDropZone = ({ disabled = false, onClick, onDropFiles }: AssetDropZoneProps) => {\n const { formatMessage } = useIntl();\n const [isDragging, setIsDragging] = useState(false);\n // Drag events fire on descendants too, so a plain boolean flickers as the\n // pointer crosses the icon or the label. Counting enter/leave pairs doesn't.\n const dragDepth = useRef(0);\n\n const handleDragEnter = useCallback(\n (event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n if (disabled || !event.dataTransfer.types.includes('Files')) {\n return;\n }\n dragDepth.current += 1;\n setIsDragging(true);\n },\n [disabled]\n );\n\n const handleDragLeave = useCallback((event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n dragDepth.current -= 1;\n if (dragDepth.current <= 0) {\n dragDepth.current = 0;\n setIsDragging(false);\n }\n }, []);\n\n const handleDragOver = useCallback((event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n event.dataTransfer.dropEffect = 'copy';\n }, []);\n\n const handleDrop = useCallback(\n (event: DragEvent<HTMLElement>) => {\n event.preventDefault();\n dragDepth.current = 0;\n setIsDragging(false);\n\n if (disabled) {\n return;\n }\n\n const files = Array.from(event.dataTransfer.files ?? []);\n if (files.length > 0) {\n onDropFiles(files);\n }\n },\n [disabled, onDropFiles]\n );\n\n return (\n <Zone\n type=\"button\"\n $isDragging={isDragging}\n aria-disabled={disabled}\n onClick={() => !disabled && onClick()}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {/* Same treatment as the repeatable-component initializer, so the two\n empty states in a form read as one affordance. */}\n <Flex justifyContent=\"center\" color={disabled ? 'neutral500' : 'primary600'}>\n <PlusCircle width=\"3.2rem\" height=\"3.2rem\" />\n </Flex>\n <Typography textColor=\"neutral600\" fontWeight=\"bold\" variant=\"pi\">\n {/* The legacy field's own key: identical wording, already translated in\n every locale, where a new key would ship English to all of them. */}\n {formatMessage({\n id: getTranslationKey('mediaLibraryInput.placeholder'),\n defaultMessage: 'Click to add an asset or drag and drop one in this area',\n })}\n </Typography>\n </Zone>\n );\n};\n"],"names":["Zone","styled","button","theme","spaces","colors","neutral200","borderRadius","neutral100","primary600","$isDragging","AssetDropZone","disabled","onClick","onDropFiles","formatMessage","useIntl","isDragging","setIsDragging","useState","dragDepth","useRef","handleDragEnter","useCallback","event","preventDefault","dataTransfer","types","includes","current","handleDragLeave","handleDragOver","dropEffect","handleDrop","files","Array","from","length","_jsxs","type","aria-disabled","onDragEnter","onDragLeave","onDragOver","onDrop","_jsx","Flex","justifyContent","color","PlusCircle","width","height","Typography","textColor","fontWeight","variant","id","getTranslationKey","defaultMessage"],"mappings":"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"}
|