@strapi/upload 5.52.0 → 5.52.1
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/future/components/TruncatedText.js +76 -0
- package/dist/admin/future/components/TruncatedText.js.map +1 -0
- package/dist/admin/future/components/TruncatedText.mjs +74 -0
- package/dist/admin/future/components/TruncatedText.mjs.map +1 -0
- package/dist/admin/future/hooks/useTracking.js +57 -0
- package/dist/admin/future/hooks/useTracking.js.map +1 -0
- package/dist/admin/future/hooks/useTracking.mjs +53 -0
- package/dist/admin/future/hooks/useTracking.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +31 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +31 -0
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +9 -6
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +9 -6
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +21 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +21 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +3 -4
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +4 -5
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +11 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +11 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +6 -4
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +6 -4
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.js +18 -2
- package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +18 -2
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js +9 -7
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs +9 -7
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js +12 -0
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs +12 -0
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +21 -38
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +23 -40
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.js +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +5 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +6 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/utils/selection.js +17 -0
- package/dist/admin/future/pages/Assets/utils/selection.js.map +1 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs +17 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs.map +1 -1
- package/dist/admin/future/services/api.js +7 -8
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +7 -8
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +11 -23
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +11 -23
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/hooks/useAIMetadataJob.js +1 -1
- package/dist/admin/hooks/useAIMetadataJob.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.js +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
- package/dist/admin/src/future/components/TruncatedText.d.ts +32 -0
- package/dist/admin/src/future/hooks/useTracking.d.ts +29 -0
- package/dist/admin/src/future/pages/Assets/components/AssetActionsMenu.d.ts +5 -3
- package/dist/admin/src/future/pages/Assets/components/FolderActionsMenu.d.ts +5 -4
- package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +2 -0
- package/dist/admin/src/future/pages/Assets/utils/selection.d.ts +10 -0
- package/dist/admin/src/future/services/api.d.ts +6 -7
- package/dist/server/controllers/admin-file.js +27 -9
- package/dist/server/controllers/admin-file.js.map +1 -1
- package/dist/server/controllers/admin-file.mjs +27 -9
- package/dist/server/controllers/admin-file.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +24 -8
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +24 -8
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/routes/admin.js +41 -21
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +41 -21
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/services/ai-metadata.js.map +1 -1
- package/dist/server/services/ai-metadata.mjs.map +1 -1
- package/dist/server/src/controllers/admin-file.d.ts +29 -8
- package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +20 -4
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +4 -4
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata.d.ts +2 -2
- package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
- package/dist/shared/contracts/ai-metadata-jobs.d.ts +10 -32
- package/dist/shared/contracts/ai-metadata-jobs.d.ts.map +1 -1
- package/dist/shared/contracts/files.d.ts +10 -10
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -6,6 +6,7 @@ var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
|
6
6
|
var designSystem = require('@strapi/design-system');
|
|
7
7
|
var reactIntl = require('react-intl');
|
|
8
8
|
var styledComponents = require('styled-components');
|
|
9
|
+
var useTracking = require('../../../hooks/useTracking.js');
|
|
9
10
|
var folders = require('../../../services/folders.js');
|
|
10
11
|
var translations = require('../../../utils/translations.js');
|
|
11
12
|
|
|
@@ -17,6 +18,7 @@ const FolderFormDialog = (props)=>{
|
|
|
17
18
|
const initialName = props.mode === 'rename' ? props.initialName : '';
|
|
18
19
|
const { formatMessage } = reactIntl.useIntl();
|
|
19
20
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
21
|
+
const { trackUsage } = useTracking.useTracking();
|
|
20
22
|
const [name, setName] = React.useState(initialName);
|
|
21
23
|
const [fieldError, setFieldError] = React.useState();
|
|
22
24
|
const inputRef = React.useRef(null);
|
|
@@ -55,11 +57,21 @@ const FolderFormDialog = (props)=>{
|
|
|
55
57
|
name: trimmedName,
|
|
56
58
|
parent: parentFolderId
|
|
57
59
|
}).unwrap();
|
|
60
|
+
// Matches the legacy folder-edit payload. This dialog only renames
|
|
61
|
+
// (parent is fixed), so the location never changes here.
|
|
62
|
+
trackUsage('didEditMediaLibraryElements', {
|
|
63
|
+
location: useTracking.MEDIA_LIBRARY_LOCATION,
|
|
64
|
+
type: 'folder',
|
|
65
|
+
changeLocation: false
|
|
66
|
+
});
|
|
58
67
|
} else {
|
|
59
68
|
await createFolder({
|
|
60
69
|
name: trimmedName,
|
|
61
70
|
parent: parentFolderId
|
|
62
71
|
}).unwrap();
|
|
72
|
+
trackUsage('didAddMediaLibraryFolders', {
|
|
73
|
+
location: useTracking.MEDIA_LIBRARY_LOCATION
|
|
74
|
+
});
|
|
63
75
|
}
|
|
64
76
|
toggleNotification({
|
|
65
77
|
type: 'success',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderFormDialog.js","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","type","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderFormDialog.js","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking';\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { trackUsage } = useTracking();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n // Matches the legacy folder-edit payload. This dialog only renames\n // (parent is fixed), so the location never changes here.\n trackUsage('didEditMediaLibraryElements', {\n location: MEDIA_LIBRARY_LOCATION,\n type: 'folder',\n changeLocation: false,\n });\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n trackUsage('didAddMediaLibraryFolders', { location: MEDIA_LIBRARY_LOCATION });\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","trackUsage","useTracking","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","location","MEDIA_LIBRARY_LOCATION","type","changeLocation","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { useNotification } from '@strapi/admin/strapi-admin';
|
|
|
4
4
|
import { Modal, Field, TextInput, Flex, Button } from '@strapi/design-system';
|
|
5
5
|
import { useIntl } from 'react-intl';
|
|
6
6
|
import { styled } from 'styled-components';
|
|
7
|
+
import { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking.mjs';
|
|
7
8
|
import { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders.mjs';
|
|
8
9
|
import { getTranslationKey } from '../../../utils/translations.mjs';
|
|
9
10
|
|
|
@@ -15,6 +16,7 @@ const FolderFormDialog = (props)=>{
|
|
|
15
16
|
const initialName = props.mode === 'rename' ? props.initialName : '';
|
|
16
17
|
const { formatMessage } = useIntl();
|
|
17
18
|
const { toggleNotification } = useNotification();
|
|
19
|
+
const { trackUsage } = useTracking();
|
|
18
20
|
const [name, setName] = useState(initialName);
|
|
19
21
|
const [fieldError, setFieldError] = useState();
|
|
20
22
|
const inputRef = useRef(null);
|
|
@@ -53,11 +55,21 @@ const FolderFormDialog = (props)=>{
|
|
|
53
55
|
name: trimmedName,
|
|
54
56
|
parent: parentFolderId
|
|
55
57
|
}).unwrap();
|
|
58
|
+
// Matches the legacy folder-edit payload. This dialog only renames
|
|
59
|
+
// (parent is fixed), so the location never changes here.
|
|
60
|
+
trackUsage('didEditMediaLibraryElements', {
|
|
61
|
+
location: MEDIA_LIBRARY_LOCATION,
|
|
62
|
+
type: 'folder',
|
|
63
|
+
changeLocation: false
|
|
64
|
+
});
|
|
56
65
|
} else {
|
|
57
66
|
await createFolder({
|
|
58
67
|
name: trimmedName,
|
|
59
68
|
parent: parentFolderId
|
|
60
69
|
}).unwrap();
|
|
70
|
+
trackUsage('didAddMediaLibraryFolders', {
|
|
71
|
+
location: MEDIA_LIBRARY_LOCATION
|
|
72
|
+
});
|
|
61
73
|
}
|
|
62
74
|
toggleNotification({
|
|
63
75
|
type: 'success',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderFormDialog.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","type","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderFormDialog.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking';\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { trackUsage } = useTracking();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n // Matches the legacy folder-edit payload. This dialog only renames\n // (parent is fixed), so the location never changes here.\n trackUsage('didEditMediaLibraryElements', {\n location: MEDIA_LIBRARY_LOCATION,\n type: 'folder',\n changeLocation: false,\n });\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n trackUsage('didAddMediaLibraryFolders', { location: MEDIA_LIBRARY_LOCATION });\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","trackUsage","useTracking","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","location","MEDIA_LIBRARY_LOCATION","type","changeLocation","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ var designSystem = require('@strapi/design-system');
|
|
|
7
7
|
var icons = require('@strapi/icons');
|
|
8
8
|
var reactIntl = require('react-intl');
|
|
9
9
|
var styledComponents = require('styled-components');
|
|
10
|
+
var TruncatedText = require('../../../../components/TruncatedText.js');
|
|
10
11
|
var folders = require('../../../../services/folders.js');
|
|
11
12
|
var translations = require('../../../../utils/translations.js');
|
|
12
13
|
var AssetsDndProvider = require('../Dnd/AssetsDndProvider.js');
|
|
@@ -151,47 +152,28 @@ const useExpandedFolders = (folderStructure, currentFolderId)=>{
|
|
|
151
152
|
expandFolder
|
|
152
153
|
};
|
|
153
154
|
};
|
|
154
|
-
/* -------------------------------------------------------------------------------------------------
|
|
155
|
-
* TruncatedFolderName — tooltip when the label is ellipsized
|
|
156
|
-
* -----------------------------------------------------------------------------------------------*/ const TruncatedFolderName = ({ name, isActive })=>{
|
|
157
|
-
const textRef = React.useRef(null);
|
|
158
|
-
const [isTruncated, setIsTruncated] = React.useState(false);
|
|
159
|
-
React.useLayoutEffect(()=>{
|
|
160
|
-
const el = textRef.current;
|
|
161
|
-
if (!el) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const checkTruncation = ()=>{
|
|
165
|
-
setIsTruncated(el.scrollWidth > el.clientWidth);
|
|
166
|
-
};
|
|
167
|
-
checkTruncation();
|
|
168
|
-
const observer = new ResizeObserver(checkTruncation);
|
|
169
|
-
observer.observe(el);
|
|
170
|
-
return ()=>observer.disconnect();
|
|
171
|
-
}, [
|
|
172
|
-
name
|
|
173
|
-
]);
|
|
174
|
-
const label = /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
175
|
-
ref: textRef,
|
|
176
|
-
variant: "omega",
|
|
177
|
-
fontWeight: isActive ? 'semiBold' : 'regular',
|
|
178
|
-
ellipsis: true,
|
|
179
|
-
children: name
|
|
180
|
-
});
|
|
181
|
-
if (isTruncated) {
|
|
182
|
-
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
|
|
183
|
-
label: name,
|
|
184
|
-
children: label
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
return label;
|
|
188
|
-
};
|
|
189
155
|
/* -------------------------------------------------------------------------------------------------
|
|
190
156
|
* NavList — unstyled list for tree rows
|
|
191
157
|
* -----------------------------------------------------------------------------------------------*/ const NavList = styledComponents.styled.ul`
|
|
192
158
|
list-style: none;
|
|
193
159
|
margin: 0;
|
|
194
160
|
padding: 0;
|
|
161
|
+
|
|
162
|
+
/* Grid rather than block, and load-bearing despite rendering a single column:
|
|
163
|
+
a minmax(0, 1fr) track contributes a minimum of 0, which is what stops each
|
|
164
|
+
row propagating the min-content width of its own label.
|
|
165
|
+
|
|
166
|
+
Folder names ellipsize, and text-overflow needs white-space: nowrap — so a
|
|
167
|
+
label's min-content width is the entire name, and no box lays out narrower
|
|
168
|
+
than its min-content. In block flow that floor travels up to the SubNav
|
|
169
|
+
ScrollArea, which widens the rail and shows a horizontal scrollbar instead of
|
|
170
|
+
truncating the name. Nesting makes it worse: the indent is spent before the
|
|
171
|
+
label is measured, so shorter names trigger it the deeper you go.
|
|
172
|
+
|
|
173
|
+
Measured in Chromium — dropping either declaration brings the scrollbar
|
|
174
|
+
back, and neither min-width nor overflow on the row is a substitute. */
|
|
175
|
+
display: grid;
|
|
176
|
+
grid-template-columns: minmax(0, 1fr);
|
|
195
177
|
`;
|
|
196
178
|
/* -------------------------------------------------------------------------------------------------
|
|
197
179
|
* FolderTreeItem — single tree row (internal)
|
|
@@ -263,9 +245,10 @@ const FolderTreeItemInner = ({ id, name, folderChildren, level, currentFolderId,
|
|
|
263
245
|
onClick: ()=>onSelect(id),
|
|
264
246
|
"data-testid": `folder-tree-node-${id}`,
|
|
265
247
|
"data-folder-id": id,
|
|
266
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(
|
|
267
|
-
|
|
268
|
-
isActive:
|
|
248
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(TruncatedText.TruncatedText, {
|
|
249
|
+
variant: "omega",
|
|
250
|
+
fontWeight: isActive ? 'semiBold' : 'regular',
|
|
251
|
+
children: name
|
|
269
252
|
})
|
|
270
253
|
})
|
|
271
254
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderTree.js","sources":["../../../../../../../admin/src/future/pages/Assets/components/FolderTree/FolderTree.tsx"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport { SubNav } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, IconButton, Loader, Tooltip, Typography } from '@strapi/design-system';\nimport { ChevronDown, Folder as FolderIcon, House } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { css, styled } from 'styled-components';\n\nimport { useGetFolderStructureQuery } from '../../../../services/folders';\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { useAssetsDndOptional } from '../Dnd/AssetsDndProvider';\nimport { useFolderTreeDroppable } from '../Dnd/useFolderTreeDroppable';\n\nimport { useSpringLoadedExpand } from './useSpringLoadedExpand';\n\nimport type { FolderNode } from '../../../../../../../shared/contracts/folders';\n\n/* -------------------------------------------------------------------------------------------------\n * RowButton — shared row styling aligned with admin SubNav.Link\n * -----------------------------------------------------------------------------------------------*/\n\nconst RowButton = styled.button<{\n $isActive: boolean;\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n width: 100%;\n min-height: 3.2rem;\n padding: ${({ theme }) => `${theme.spaces[1]} ${theme.spaces[2]}`};\n border: 0;\n background: ${({ $isActive, $isValidDropTarget, theme }) => {\n if ($isValidDropTarget) {\n return theme.colors.primary100;\n }\n\n return $isActive ? theme.colors.primary100 : 'transparent';\n }};\n color: ${({ $isActive, theme }) =>\n $isActive ? theme.colors.primary700 : theme.colors.neutral800};\n border-radius: ${({ theme }) => theme.borderRadius};\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'pointer';\n }};\n text-align: left;\n font: inherit;\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n\n &:hover {\n background: ${({ $isActive, $isValidDropTarget, theme }) => {\n if ($isValidDropTarget) {\n return theme.colors.primary100;\n }\n\n return $isActive ? theme.colors.primary100 : theme.colors.neutral100;\n }};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n`;\n\nconst TreeRow = styled(Flex)<{\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'default';\n }};\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n border-radius: ${({ theme }) => theme.borderRadius};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n background: ${theme.colors.primary100};\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * useExpandedFolders — local expand/collapse state\n * -----------------------------------------------------------------------------------------------*/\n\nconst findAncestorIds = (\n nodes: FolderNode[],\n targetId: number,\n trail: number[] = []\n): number[] | null => {\n for (const node of nodes) {\n if (node.id === targetId) {\n return trail;\n }\n\n if (node.children?.length) {\n const nextTrail = node.id != null ? [...trail, node.id] : trail;\n const found = findAncestorIds(node.children, targetId, nextTrail);\n if (found !== null) {\n return found;\n }\n }\n }\n\n return null;\n};\n\nconst useExpandedFolders = (folderStructure: FolderNode[], currentFolderId: number | null) => {\n const [expandedIds, setExpandedIds] = useState<Set<number>>(() => new Set());\n\n useEffect(() => {\n if (currentFolderId == null) {\n return;\n }\n\n const ancestors = findAncestorIds(folderStructure, currentFolderId);\n if (!ancestors || ancestors.length === 0) {\n return;\n }\n\n setExpandedIds((prev) => {\n const next = new Set(prev);\n let changed = false;\n for (const id of ancestors) {\n if (!next.has(id)) {\n next.add(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [folderStructure, currentFolderId]);\n\n const toggleExpanded = useCallback((id: number) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n return next;\n });\n }, []);\n\n const expandFolder = useCallback((id: number) => {\n setExpandedIds((prev) => {\n if (prev.has(id)) {\n return prev;\n }\n\n const next = new Set(prev);\n next.add(id);\n return next;\n });\n }, []);\n\n const isExpanded = useCallback((id: number) => expandedIds.has(id), [expandedIds]);\n\n return { isExpanded, toggleExpanded, expandFolder };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * TruncatedFolderName — tooltip when the label is ellipsized\n * -----------------------------------------------------------------------------------------------*/\n\nconst TruncatedFolderName = ({ name, isActive }: { name: string; isActive: boolean }) => {\n const textRef = useRef<HTMLSpanElement>(null);\n const [isTruncated, setIsTruncated] = useState(false);\n\n useLayoutEffect(() => {\n const el = textRef.current;\n if (!el) {\n return;\n }\n\n const checkTruncation = () => {\n setIsTruncated(el.scrollWidth > el.clientWidth);\n };\n\n checkTruncation();\n\n const observer = new ResizeObserver(checkTruncation);\n observer.observe(el);\n\n return () => observer.disconnect();\n }, [name]);\n\n const label = (\n <Typography\n ref={textRef}\n variant=\"omega\"\n fontWeight={isActive ? 'semiBold' : 'regular'}\n ellipsis\n >\n {name}\n </Typography>\n );\n\n if (isTruncated) {\n return <Tooltip label={name}>{label}</Tooltip>;\n }\n\n return label;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NavList — unstyled list for tree rows\n * -----------------------------------------------------------------------------------------------*/\n\nconst NavList = styled.ul`\n list-style: none;\n margin: 0;\n padding: 0;\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTreeItem — single tree row (internal)\n * -----------------------------------------------------------------------------------------------*/\n\nconst INDENT_PER_LEVEL_REM = 1.6;\n\nconst RotatingChevron = styled(ChevronDown)<{ $expanded: boolean }>`\n transform: rotate(${({ $expanded }) => ($expanded ? '0deg' : '-90deg')});\n transition: transform 0.2s ease;\n`;\n\ninterface FolderTreeItemProps {\n node: FolderNode;\n level: number;\n currentFolderId: number | null;\n showActiveFolder: boolean;\n isExpanded: (id: number) => boolean;\n onToggle: (id: number) => void;\n onExpand: (id: number) => void;\n onSelect: (folderId: number) => void;\n isMovePending: boolean;\n}\n\ninterface FolderTreeItemInnerProps extends Omit<FolderTreeItemProps, 'node'> {\n id: number;\n name: string;\n folderChildren: FolderNode[];\n}\n\nconst FolderTreeItemInner = ({\n id,\n name,\n folderChildren,\n level,\n currentFolderId,\n showActiveFolder,\n isExpanded,\n onToggle,\n onExpand,\n onSelect,\n isMovePending,\n}: FolderTreeItemInnerProps) => {\n const { formatMessage } = useIntl();\n const hasChildren = folderChildren.length > 0;\n const isFolderExpanded = isExpanded(id);\n const isActive = showActiveFolder && currentFolderId === id;\n\n const {\n droppable: { setNodeRef },\n isOver,\n showValidDropHighlight,\n showInvalidDropCursor,\n } = useFolderTreeDroppable({ id, name });\n\n const handleExpand = useCallback(() => onExpand(id), [id, onExpand]);\n\n useSpringLoadedExpand({\n isOver,\n canExpand: hasChildren && !isFolderExpanded,\n onExpand: handleExpand,\n });\n\n // TODO: full `role=\"tree\"` + arrow-key treeview navigation before revamp GA\n // if an accessibility audit requires it (v1 is button rows only).\n return (\n <li>\n <TreeRow\n ref={setNodeRef}\n alignItems=\"center\"\n paddingLeft={`${level * INDENT_PER_LEVEL_REM}rem`}\n gap={1}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n >\n <IconButton\n label={formatMessage(\n {\n id: getTranslationKey(\n isFolderExpanded ? 'sidebar.tree.collapse' : 'sidebar.tree.expand'\n ),\n defaultMessage: isFolderExpanded ? 'Collapse {name}' : 'Expand {name}',\n },\n { name }\n )}\n onClick={(event: React.MouseEvent) => {\n event.stopPropagation();\n onToggle(id);\n }}\n variant=\"ghost\"\n withTooltip={false}\n aria-expanded={isFolderExpanded}\n >\n <RotatingChevron $expanded={isFolderExpanded} fill=\"neutral500\" />\n </IconButton>\n\n <Box flex=\"1\" minWidth={0}>\n <RowButton\n type=\"button\"\n $isActive={isActive}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isActive ? 'page' : undefined}\n onClick={() => onSelect(id)}\n data-testid={`folder-tree-node-${id}`}\n data-folder-id={id}\n >\n <TruncatedFolderName name={name} isActive={isActive} />\n </RowButton>\n </Box>\n </TreeRow>\n\n {hasChildren && isFolderExpanded && (\n <NavList>\n {folderChildren.map((child) => (\n <FolderTreeItem\n key={child.id ?? child.name}\n node={child}\n level={level + 1}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={onToggle}\n onExpand={onExpand}\n onSelect={onSelect}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </li>\n );\n};\n\nconst FolderTreeItem = ({ node, ...props }: FolderTreeItemProps) => {\n if (node.id == null) {\n return null;\n }\n\n return (\n <FolderTreeItemInner\n {...props}\n id={node.id}\n name={node.name ?? ''}\n folderChildren={node.children ?? []}\n />\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTree — public sidebar component\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FolderTreeProps {\n currentFolderId: number | null;\n /**\n * Set to `false` while a global asset search is active: the results span the\n * whole library, so highlighting one folder would misrepresent them.\n * */\n showActiveFolder?: boolean;\n onSelectFolder: (folderId: number | null) => void;\n}\n\n/**\n * Left-rail navigation for the Media Library. Fetches folder structure internally\n * and renders:\n *\n * 1. A \"Media library\" title\n * 2. A filter input that prunes the tree to matching destinations\n * 3. A \"Home\" entry that clears the folder query param\n * 4. A \"FOLDERS\" section header\n * 5. The folder tree itself\n *\n * The filter is purely local: it never touches the URL and never affects the\n * asset list, which has its own independent search in the content toolbar.\n *\n * Presentational with respect to routing — navigation is delegated to the parent\n * via `onSelectFolder` so the URL stays the single source of truth (see\n * `useFolderNavigation`).\n */\nexport const FolderTree = ({\n currentFolderId,\n showActiveFolder = true,\n onSelectFolder,\n}: FolderTreeProps) => {\n const { formatMessage } = useIntl();\n const { data: folderStructure = [], isLoading, isError } = useGetFolderStructureQuery();\n const { isExpanded, toggleExpanded, expandFolder } = useExpandedFolders(\n folderStructure,\n currentFolderId\n );\n const { isMovePending } = useAssetsDndOptional() ?? { isMovePending: false };\n\n const isHomeActive = showActiveFolder && currentFolderId == null;\n const homeLabel = formatMessage({\n id: getTranslationKey('sidebar.home'),\n defaultMessage: 'Home',\n });\n\n const {\n droppable: { setNodeRef: setHomeDropRef },\n showValidDropHighlight: showHomeValidDropHighlight,\n showInvalidDropCursor: showHomeInvalidDropCursor,\n } = useFolderTreeDroppable({ id: null, name: homeLabel });\n\n return (\n <SubNav.Main\n aria-label={formatMessage({\n id: getTranslationKey('sidebar.tree.aria-label'),\n defaultMessage: 'Media library folders',\n })}\n >\n <SubNav.Header\n label={formatMessage({\n id: getTranslationKey('sidebar.title'),\n defaultMessage: 'Media library',\n })}\n />\n\n <SubNav.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={1} padding={3}>\n <RowButton\n ref={setHomeDropRef}\n type=\"button\"\n $isActive={isHomeActive}\n $isValidDropTarget={showHomeValidDropHighlight}\n $isInvalidDropCursor={showHomeInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isHomeActive ? 'page' : undefined}\n onClick={() => onSelectFolder(null)}\n data-testid=\"folder-tree-home\"\n >\n <House aria-hidden width=\"1.6rem\" height=\"1.6rem\" />\n <Typography variant=\"omega\" fontWeight={isHomeActive ? 'semiBold' : 'regular'}>\n {homeLabel}\n </Typography>\n </RowButton>\n\n <Box marginTop={4}>\n <Flex\n alignItems=\"center\"\n gap={1}\n paddingTop={1}\n paddingBottom={1}\n paddingLeft={2}\n paddingRight={2}\n marginBottom={2}\n >\n <FolderIcon aria-hidden width=\"1.6rem\" height=\"1.6rem\" fill=\"neutral500\" />\n <Typography\n variant=\"sigma\"\n textColor=\"neutral600\"\n style={{ textTransform: 'uppercase' }}\n >\n {formatMessage({\n id: getTranslationKey('sidebar.folders'),\n defaultMessage: 'Folders',\n })}\n </Typography>\n </Flex>\n\n {isLoading ? (\n // TODO: revisit loading state before revamp GA\n <Flex justifyContent=\"center\" padding={1} paddingTop={2}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('sidebar.tree.loading'),\n defaultMessage: 'Loading folders...',\n })}\n </Loader>\n </Flex>\n ) : isError ? (\n // TODO: revisit error state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.error'),\n defaultMessage: 'Could not load folders.',\n })}\n </Typography>\n </Box>\n ) : folderStructure.length === 0 ? (\n // TODO: revisit empty state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.empty'),\n defaultMessage: 'No folders yet',\n })}\n </Typography>\n </Box>\n ) : (\n <NavList>\n {folderStructure.map((node) => (\n <FolderTreeItem\n key={node.id ?? node.name}\n node={node}\n level={0}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={toggleExpanded}\n onExpand={expandFolder}\n onSelect={onSelectFolder}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </Box>\n </Flex>\n </SubNav.Content>\n </SubNav.Main>\n );\n};\n"],"names":["RowButton","styled","button","theme","spaces","$isActive","$isValidDropTarget","colors","primary100","primary700","neutral800","borderRadius","$isMovePending","$isInvalidDropCursor","css","primary600","neutral100","TreeRow","Flex","findAncestorIds","nodes","targetId","trail","node","id","children","length","nextTrail","found","useExpandedFolders","folderStructure","currentFolderId","expandedIds","setExpandedIds","useState","Set","useEffect","ancestors","prev","next","changed","has","add","toggleExpanded","useCallback","delete","expandFolder","isExpanded","TruncatedFolderName","name","isActive","textRef","useRef","isTruncated","setIsTruncated","useLayoutEffect","el","current","checkTruncation","scrollWidth","clientWidth","observer","ResizeObserver","observe","disconnect","label","_jsx","Typography","ref","variant","fontWeight","ellipsis","Tooltip","NavList","ul","INDENT_PER_LEVEL_REM","RotatingChevron","ChevronDown","$expanded","FolderTreeItemInner","folderChildren","level","showActiveFolder","onToggle","onExpand","onSelect","isMovePending","formatMessage","useIntl","hasChildren","isFolderExpanded","droppable","setNodeRef","isOver","showValidDropHighlight","showInvalidDropCursor","useFolderTreeDroppable","handleExpand","useSpringLoadedExpand","canExpand","_jsxs","li","alignItems","paddingLeft","gap","IconButton","getTranslationKey","defaultMessage","onClick","event","stopPropagation","withTooltip","aria-expanded","fill","Box","flex","minWidth","type","aria-current","undefined","data-testid","data-folder-id","map","child","FolderTreeItem","props","FolderTree","onSelectFolder","data","isLoading","isError","useGetFolderStructureQuery","useAssetsDndOptional","isHomeActive","homeLabel","setHomeDropRef","showHomeValidDropHighlight","showHomeInvalidDropCursor","SubNav","Main","aria-label","Header","Content","direction","padding","House","aria-hidden","width","height","marginTop","paddingTop","paddingBottom","paddingRight","marginBottom","FolderIcon","textColor","style","textTransform","justifyContent","Loader"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderTree.js","sources":["../../../../../../../admin/src/future/pages/Assets/components/FolderTree/FolderTree.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\n\nimport { SubNav } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, IconButton, Loader, Typography } from '@strapi/design-system';\nimport { ChevronDown, Folder as FolderIcon, House } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { css, styled } from 'styled-components';\n\nimport { TruncatedText } from '../../../../components/TruncatedText';\nimport { useGetFolderStructureQuery } from '../../../../services/folders';\nimport { getTranslationKey } from '../../../../utils/translations';\nimport { useAssetsDndOptional } from '../Dnd/AssetsDndProvider';\nimport { useFolderTreeDroppable } from '../Dnd/useFolderTreeDroppable';\n\nimport { useSpringLoadedExpand } from './useSpringLoadedExpand';\n\nimport type { FolderNode } from '../../../../../../../shared/contracts/folders';\n\n/* -------------------------------------------------------------------------------------------------\n * RowButton — shared row styling aligned with admin SubNav.Link\n * -----------------------------------------------------------------------------------------------*/\n\nconst RowButton = styled.button<{\n $isActive: boolean;\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.spaces[2]};\n width: 100%;\n min-height: 3.2rem;\n padding: ${({ theme }) => `${theme.spaces[1]} ${theme.spaces[2]}`};\n border: 0;\n background: ${({ $isActive, $isValidDropTarget, theme }) => {\n if ($isValidDropTarget) {\n return theme.colors.primary100;\n }\n\n return $isActive ? theme.colors.primary100 : 'transparent';\n }};\n color: ${({ $isActive, theme }) =>\n $isActive ? theme.colors.primary700 : theme.colors.neutral800};\n border-radius: ${({ theme }) => theme.borderRadius};\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'pointer';\n }};\n text-align: left;\n font: inherit;\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n\n &:hover {\n background: ${({ $isActive, $isValidDropTarget, theme }) => {\n if ($isValidDropTarget) {\n return theme.colors.primary100;\n }\n\n return $isActive ? theme.colors.primary100 : theme.colors.neutral100;\n }};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => theme.colors.primary600};\n outline-offset: -2px;\n }\n`;\n\nconst TreeRow = styled(Flex)<{\n $isValidDropTarget?: boolean;\n $isInvalidDropCursor?: boolean;\n $isMovePending?: boolean;\n}>`\n cursor: ${({ $isMovePending, $isInvalidDropCursor }) => {\n if ($isMovePending) {\n return 'wait';\n }\n\n return $isInvalidDropCursor ? 'not-allowed' : 'default';\n }};\n pointer-events: ${({ $isMovePending }) => ($isMovePending ? 'none' : 'auto')};\n border-radius: ${({ theme }) => theme.borderRadius};\n\n ${({ $isValidDropTarget, theme }) =>\n $isValidDropTarget &&\n css`\n background: ${theme.colors.primary100};\n outline: 1px dashed ${theme.colors.primary600};\n outline-offset: -1px;\n `}\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * useExpandedFolders — local expand/collapse state\n * -----------------------------------------------------------------------------------------------*/\n\nconst findAncestorIds = (\n nodes: FolderNode[],\n targetId: number,\n trail: number[] = []\n): number[] | null => {\n for (const node of nodes) {\n if (node.id === targetId) {\n return trail;\n }\n\n if (node.children?.length) {\n const nextTrail = node.id != null ? [...trail, node.id] : trail;\n const found = findAncestorIds(node.children, targetId, nextTrail);\n if (found !== null) {\n return found;\n }\n }\n }\n\n return null;\n};\n\nconst useExpandedFolders = (folderStructure: FolderNode[], currentFolderId: number | null) => {\n const [expandedIds, setExpandedIds] = useState<Set<number>>(() => new Set());\n\n useEffect(() => {\n if (currentFolderId == null) {\n return;\n }\n\n const ancestors = findAncestorIds(folderStructure, currentFolderId);\n if (!ancestors || ancestors.length === 0) {\n return;\n }\n\n setExpandedIds((prev) => {\n const next = new Set(prev);\n let changed = false;\n for (const id of ancestors) {\n if (!next.has(id)) {\n next.add(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [folderStructure, currentFolderId]);\n\n const toggleExpanded = useCallback((id: number) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n return next;\n });\n }, []);\n\n const expandFolder = useCallback((id: number) => {\n setExpandedIds((prev) => {\n if (prev.has(id)) {\n return prev;\n }\n\n const next = new Set(prev);\n next.add(id);\n return next;\n });\n }, []);\n\n const isExpanded = useCallback((id: number) => expandedIds.has(id), [expandedIds]);\n\n return { isExpanded, toggleExpanded, expandFolder };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * NavList — unstyled list for tree rows\n * -----------------------------------------------------------------------------------------------*/\n\nconst NavList = styled.ul`\n list-style: none;\n margin: 0;\n padding: 0;\n\n /* Grid rather than block, and load-bearing despite rendering a single column:\n a minmax(0, 1fr) track contributes a minimum of 0, which is what stops each\n row propagating the min-content width of its own label.\n\n Folder names ellipsize, and text-overflow needs white-space: nowrap — so a\n label's min-content width is the entire name, and no box lays out narrower\n than its min-content. In block flow that floor travels up to the SubNav\n ScrollArea, which widens the rail and shows a horizontal scrollbar instead of\n truncating the name. Nesting makes it worse: the indent is spent before the\n label is measured, so shorter names trigger it the deeper you go.\n\n Measured in Chromium — dropping either declaration brings the scrollbar\n back, and neither min-width nor overflow on the row is a substitute. */\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTreeItem — single tree row (internal)\n * -----------------------------------------------------------------------------------------------*/\n\nconst INDENT_PER_LEVEL_REM = 1.6;\n\nconst RotatingChevron = styled(ChevronDown)<{ $expanded: boolean }>`\n transform: rotate(${({ $expanded }) => ($expanded ? '0deg' : '-90deg')});\n transition: transform 0.2s ease;\n`;\n\ninterface FolderTreeItemProps {\n node: FolderNode;\n level: number;\n currentFolderId: number | null;\n showActiveFolder: boolean;\n isExpanded: (id: number) => boolean;\n onToggle: (id: number) => void;\n onExpand: (id: number) => void;\n onSelect: (folderId: number) => void;\n isMovePending: boolean;\n}\n\ninterface FolderTreeItemInnerProps extends Omit<FolderTreeItemProps, 'node'> {\n id: number;\n name: string;\n folderChildren: FolderNode[];\n}\n\nconst FolderTreeItemInner = ({\n id,\n name,\n folderChildren,\n level,\n currentFolderId,\n showActiveFolder,\n isExpanded,\n onToggle,\n onExpand,\n onSelect,\n isMovePending,\n}: FolderTreeItemInnerProps) => {\n const { formatMessage } = useIntl();\n const hasChildren = folderChildren.length > 0;\n const isFolderExpanded = isExpanded(id);\n const isActive = showActiveFolder && currentFolderId === id;\n\n const {\n droppable: { setNodeRef },\n isOver,\n showValidDropHighlight,\n showInvalidDropCursor,\n } = useFolderTreeDroppable({ id, name });\n\n const handleExpand = useCallback(() => onExpand(id), [id, onExpand]);\n\n useSpringLoadedExpand({\n isOver,\n canExpand: hasChildren && !isFolderExpanded,\n onExpand: handleExpand,\n });\n\n // TODO: full `role=\"tree\"` + arrow-key treeview navigation before revamp GA\n // if an accessibility audit requires it (v1 is button rows only).\n return (\n <li>\n <TreeRow\n ref={setNodeRef}\n alignItems=\"center\"\n paddingLeft={`${level * INDENT_PER_LEVEL_REM}rem`}\n gap={1}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n >\n <IconButton\n label={formatMessage(\n {\n id: getTranslationKey(\n isFolderExpanded ? 'sidebar.tree.collapse' : 'sidebar.tree.expand'\n ),\n defaultMessage: isFolderExpanded ? 'Collapse {name}' : 'Expand {name}',\n },\n { name }\n )}\n onClick={(event: React.MouseEvent) => {\n event.stopPropagation();\n onToggle(id);\n }}\n variant=\"ghost\"\n withTooltip={false}\n aria-expanded={isFolderExpanded}\n >\n <RotatingChevron $expanded={isFolderExpanded} fill=\"neutral500\" />\n </IconButton>\n\n <Box flex=\"1\" minWidth={0}>\n <RowButton\n type=\"button\"\n $isActive={isActive}\n $isValidDropTarget={showValidDropHighlight}\n $isInvalidDropCursor={showInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isActive ? 'page' : undefined}\n onClick={() => onSelect(id)}\n data-testid={`folder-tree-node-${id}`}\n data-folder-id={id}\n >\n <TruncatedText variant=\"omega\" fontWeight={isActive ? 'semiBold' : 'regular'}>\n {name}\n </TruncatedText>\n </RowButton>\n </Box>\n </TreeRow>\n\n {hasChildren && isFolderExpanded && (\n <NavList>\n {folderChildren.map((child) => (\n <FolderTreeItem\n key={child.id ?? child.name}\n node={child}\n level={level + 1}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={onToggle}\n onExpand={onExpand}\n onSelect={onSelect}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </li>\n );\n};\n\nconst FolderTreeItem = ({ node, ...props }: FolderTreeItemProps) => {\n if (node.id == null) {\n return null;\n }\n\n return (\n <FolderTreeItemInner\n {...props}\n id={node.id}\n name={node.name ?? ''}\n folderChildren={node.children ?? []}\n />\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * FolderTree — public sidebar component\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FolderTreeProps {\n currentFolderId: number | null;\n /**\n * Set to `false` while a global asset search is active: the results span the\n * whole library, so highlighting one folder would misrepresent them.\n * */\n showActiveFolder?: boolean;\n onSelectFolder: (folderId: number | null) => void;\n}\n\n/**\n * Left-rail navigation for the Media Library. Fetches folder structure internally\n * and renders:\n *\n * 1. A \"Media library\" title\n * 2. A filter input that prunes the tree to matching destinations\n * 3. A \"Home\" entry that clears the folder query param\n * 4. A \"FOLDERS\" section header\n * 5. The folder tree itself\n *\n * The filter is purely local: it never touches the URL and never affects the\n * asset list, which has its own independent search in the content toolbar.\n *\n * Presentational with respect to routing — navigation is delegated to the parent\n * via `onSelectFolder` so the URL stays the single source of truth (see\n * `useFolderNavigation`).\n */\nexport const FolderTree = ({\n currentFolderId,\n showActiveFolder = true,\n onSelectFolder,\n}: FolderTreeProps) => {\n const { formatMessage } = useIntl();\n const { data: folderStructure = [], isLoading, isError } = useGetFolderStructureQuery();\n const { isExpanded, toggleExpanded, expandFolder } = useExpandedFolders(\n folderStructure,\n currentFolderId\n );\n const { isMovePending } = useAssetsDndOptional() ?? { isMovePending: false };\n\n const isHomeActive = showActiveFolder && currentFolderId == null;\n const homeLabel = formatMessage({\n id: getTranslationKey('sidebar.home'),\n defaultMessage: 'Home',\n });\n\n const {\n droppable: { setNodeRef: setHomeDropRef },\n showValidDropHighlight: showHomeValidDropHighlight,\n showInvalidDropCursor: showHomeInvalidDropCursor,\n } = useFolderTreeDroppable({ id: null, name: homeLabel });\n\n return (\n <SubNav.Main\n aria-label={formatMessage({\n id: getTranslationKey('sidebar.tree.aria-label'),\n defaultMessage: 'Media library folders',\n })}\n >\n <SubNav.Header\n label={formatMessage({\n id: getTranslationKey('sidebar.title'),\n defaultMessage: 'Media library',\n })}\n />\n\n <SubNav.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={1} padding={3}>\n <RowButton\n ref={setHomeDropRef}\n type=\"button\"\n $isActive={isHomeActive}\n $isValidDropTarget={showHomeValidDropHighlight}\n $isInvalidDropCursor={showHomeInvalidDropCursor}\n $isMovePending={isMovePending}\n aria-current={isHomeActive ? 'page' : undefined}\n onClick={() => onSelectFolder(null)}\n data-testid=\"folder-tree-home\"\n >\n <House aria-hidden width=\"1.6rem\" height=\"1.6rem\" />\n <Typography variant=\"omega\" fontWeight={isHomeActive ? 'semiBold' : 'regular'}>\n {homeLabel}\n </Typography>\n </RowButton>\n\n <Box marginTop={4}>\n <Flex\n alignItems=\"center\"\n gap={1}\n paddingTop={1}\n paddingBottom={1}\n paddingLeft={2}\n paddingRight={2}\n marginBottom={2}\n >\n <FolderIcon aria-hidden width=\"1.6rem\" height=\"1.6rem\" fill=\"neutral500\" />\n <Typography\n variant=\"sigma\"\n textColor=\"neutral600\"\n style={{ textTransform: 'uppercase' }}\n >\n {formatMessage({\n id: getTranslationKey('sidebar.folders'),\n defaultMessage: 'Folders',\n })}\n </Typography>\n </Flex>\n\n {isLoading ? (\n // TODO: revisit loading state before revamp GA\n <Flex justifyContent=\"center\" padding={1} paddingTop={2}>\n <Loader>\n {formatMessage({\n id: getTranslationKey('sidebar.tree.loading'),\n defaultMessage: 'Loading folders...',\n })}\n </Loader>\n </Flex>\n ) : isError ? (\n // TODO: revisit error state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"danger600\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.error'),\n defaultMessage: 'Could not load folders.',\n })}\n </Typography>\n </Box>\n ) : folderStructure.length === 0 ? (\n // TODO: revisit empty state before revamp GA\n <Box padding={1} paddingTop={2}>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {formatMessage({\n id: getTranslationKey('sidebar.tree.empty'),\n defaultMessage: 'No folders yet',\n })}\n </Typography>\n </Box>\n ) : (\n <NavList>\n {folderStructure.map((node) => (\n <FolderTreeItem\n key={node.id ?? node.name}\n node={node}\n level={0}\n currentFolderId={currentFolderId}\n showActiveFolder={showActiveFolder}\n isExpanded={isExpanded}\n onToggle={toggleExpanded}\n onExpand={expandFolder}\n onSelect={onSelectFolder}\n isMovePending={isMovePending}\n />\n ))}\n </NavList>\n )}\n </Box>\n </Flex>\n </SubNav.Content>\n </SubNav.Main>\n );\n};\n"],"names":["RowButton","styled","button","theme","spaces","$isActive","$isValidDropTarget","colors","primary100","primary700","neutral800","borderRadius","$isMovePending","$isInvalidDropCursor","css","primary600","neutral100","TreeRow","Flex","findAncestorIds","nodes","targetId","trail","node","id","children","length","nextTrail","found","useExpandedFolders","folderStructure","currentFolderId","expandedIds","setExpandedIds","useState","Set","useEffect","ancestors","prev","next","changed","has","add","toggleExpanded","useCallback","delete","expandFolder","isExpanded","NavList","ul","INDENT_PER_LEVEL_REM","RotatingChevron","ChevronDown","$expanded","FolderTreeItemInner","name","folderChildren","level","showActiveFolder","onToggle","onExpand","onSelect","isMovePending","formatMessage","useIntl","hasChildren","isFolderExpanded","isActive","droppable","setNodeRef","isOver","showValidDropHighlight","showInvalidDropCursor","useFolderTreeDroppable","handleExpand","useSpringLoadedExpand","canExpand","_jsxs","li","ref","alignItems","paddingLeft","gap","_jsx","IconButton","label","getTranslationKey","defaultMessage","onClick","event","stopPropagation","variant","withTooltip","aria-expanded","fill","Box","flex","minWidth","type","aria-current","undefined","data-testid","data-folder-id","TruncatedText","fontWeight","map","child","FolderTreeItem","props","FolderTree","onSelectFolder","data","isLoading","isError","useGetFolderStructureQuery","useAssetsDndOptional","isHomeActive","homeLabel","setHomeDropRef","showHomeValidDropHighlight","showHomeInvalidDropCursor","SubNav","Main","aria-label","Header","Content","direction","padding","House","aria-hidden","width","height","Typography","marginTop","paddingTop","paddingBottom","paddingRight","marginBottom","FolderIcon","textColor","style","textTransform","justifyContent","Loader"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useEffect, useCallback
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
3
|
import { SubNav } from '@strapi/admin/strapi-admin';
|
|
4
|
-
import { Flex, Typography, Box, Loader, IconButton
|
|
4
|
+
import { Flex, Typography, Box, Loader, IconButton } from '@strapi/design-system';
|
|
5
5
|
import { House, Folder, ChevronDown } from '@strapi/icons';
|
|
6
6
|
import { useIntl } from 'react-intl';
|
|
7
7
|
import { css, styled } from 'styled-components';
|
|
8
|
+
import { TruncatedText } from '../../../../components/TruncatedText.mjs';
|
|
8
9
|
import { useGetFolderStructureQuery } from '../../../../services/folders.mjs';
|
|
9
10
|
import { getTranslationKey } from '../../../../utils/translations.mjs';
|
|
10
11
|
import { useAssetsDndOptional } from '../Dnd/AssetsDndProvider.mjs';
|
|
@@ -149,47 +150,28 @@ const useExpandedFolders = (folderStructure, currentFolderId)=>{
|
|
|
149
150
|
expandFolder
|
|
150
151
|
};
|
|
151
152
|
};
|
|
152
|
-
/* -------------------------------------------------------------------------------------------------
|
|
153
|
-
* TruncatedFolderName — tooltip when the label is ellipsized
|
|
154
|
-
* -----------------------------------------------------------------------------------------------*/ const TruncatedFolderName = ({ name, isActive })=>{
|
|
155
|
-
const textRef = useRef(null);
|
|
156
|
-
const [isTruncated, setIsTruncated] = useState(false);
|
|
157
|
-
useLayoutEffect(()=>{
|
|
158
|
-
const el = textRef.current;
|
|
159
|
-
if (!el) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const checkTruncation = ()=>{
|
|
163
|
-
setIsTruncated(el.scrollWidth > el.clientWidth);
|
|
164
|
-
};
|
|
165
|
-
checkTruncation();
|
|
166
|
-
const observer = new ResizeObserver(checkTruncation);
|
|
167
|
-
observer.observe(el);
|
|
168
|
-
return ()=>observer.disconnect();
|
|
169
|
-
}, [
|
|
170
|
-
name
|
|
171
|
-
]);
|
|
172
|
-
const label = /*#__PURE__*/ jsx(Typography, {
|
|
173
|
-
ref: textRef,
|
|
174
|
-
variant: "omega",
|
|
175
|
-
fontWeight: isActive ? 'semiBold' : 'regular',
|
|
176
|
-
ellipsis: true,
|
|
177
|
-
children: name
|
|
178
|
-
});
|
|
179
|
-
if (isTruncated) {
|
|
180
|
-
return /*#__PURE__*/ jsx(Tooltip, {
|
|
181
|
-
label: name,
|
|
182
|
-
children: label
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
return label;
|
|
186
|
-
};
|
|
187
153
|
/* -------------------------------------------------------------------------------------------------
|
|
188
154
|
* NavList — unstyled list for tree rows
|
|
189
155
|
* -----------------------------------------------------------------------------------------------*/ const NavList = styled.ul`
|
|
190
156
|
list-style: none;
|
|
191
157
|
margin: 0;
|
|
192
158
|
padding: 0;
|
|
159
|
+
|
|
160
|
+
/* Grid rather than block, and load-bearing despite rendering a single column:
|
|
161
|
+
a minmax(0, 1fr) track contributes a minimum of 0, which is what stops each
|
|
162
|
+
row propagating the min-content width of its own label.
|
|
163
|
+
|
|
164
|
+
Folder names ellipsize, and text-overflow needs white-space: nowrap — so a
|
|
165
|
+
label's min-content width is the entire name, and no box lays out narrower
|
|
166
|
+
than its min-content. In block flow that floor travels up to the SubNav
|
|
167
|
+
ScrollArea, which widens the rail and shows a horizontal scrollbar instead of
|
|
168
|
+
truncating the name. Nesting makes it worse: the indent is spent before the
|
|
169
|
+
label is measured, so shorter names trigger it the deeper you go.
|
|
170
|
+
|
|
171
|
+
Measured in Chromium — dropping either declaration brings the scrollbar
|
|
172
|
+
back, and neither min-width nor overflow on the row is a substitute. */
|
|
173
|
+
display: grid;
|
|
174
|
+
grid-template-columns: minmax(0, 1fr);
|
|
193
175
|
`;
|
|
194
176
|
/* -------------------------------------------------------------------------------------------------
|
|
195
177
|
* FolderTreeItem — single tree row (internal)
|
|
@@ -261,9 +243,10 @@ const FolderTreeItemInner = ({ id, name, folderChildren, level, currentFolderId,
|
|
|
261
243
|
onClick: ()=>onSelect(id),
|
|
262
244
|
"data-testid": `folder-tree-node-${id}`,
|
|
263
245
|
"data-folder-id": id,
|
|
264
|
-
children: /*#__PURE__*/ jsx(
|
|
265
|
-
|
|
266
|
-
isActive:
|
|
246
|
+
children: /*#__PURE__*/ jsx(TruncatedText, {
|
|
247
|
+
variant: "omega",
|
|
248
|
+
fontWeight: isActive ? 'semiBold' : 'regular',
|
|
249
|
+
children: name
|
|
267
250
|
})
|
|
268
251
|
})
|
|
269
252
|
})
|