@ndla/ui 19.0.1 → 19.2.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/es/Breadcrumb/ActionBreadcrumb.js +9 -3
- package/es/MyNdla/Resource/Folder.js +7 -7
- package/es/Resource/ListResource.js +7 -7
- package/es/TreeStructure/FolderItem.js +54 -38
- package/es/TreeStructure/FolderItems.js +29 -35
- package/es/TreeStructure/FolderNameInput.js +11 -15
- package/es/TreeStructure/TreeStructure.js +64 -91
- package/es/TreeStructure/arrowNavigation.js +44 -0
- package/es/TreeStructure/helperFunctions.js +41 -35
- package/es/locale/messages-en.js +10 -1
- package/es/locale/messages-nb.js +10 -1
- package/es/locale/messages-nn.js +10 -1
- package/es/locale/messages-se.js +10 -1
- package/es/locale/messages-sma.js +10 -1
- package/lib/Breadcrumb/ActionBreadcrumb.js +9 -3
- package/lib/MyNdla/Resource/Folder.js +7 -7
- package/lib/Resource/ListResource.js +7 -7
- package/lib/TreeStructure/FolderItem.d.ts +6 -3
- package/lib/TreeStructure/FolderItem.js +55 -38
- package/lib/TreeStructure/FolderItems.d.ts +1 -1
- package/lib/TreeStructure/FolderItems.js +29 -35
- package/lib/TreeStructure/FolderNameInput.d.ts +3 -2
- package/lib/TreeStructure/FolderNameInput.js +11 -15
- package/lib/TreeStructure/TreeStructure.d.ts +1 -6
- package/lib/TreeStructure/TreeStructure.js +63 -92
- package/lib/TreeStructure/TreeStructure.types.d.ts +13 -20
- package/lib/TreeStructure/arrowNavigation.d.ts +9 -0
- package/lib/TreeStructure/arrowNavigation.js +54 -0
- package/lib/TreeStructure/helperFunctions.d.ts +3 -4
- package/lib/TreeStructure/helperFunctions.js +45 -35
- package/lib/locale/messages-en.d.ts +10 -1
- package/lib/locale/messages-en.js +10 -1
- package/lib/locale/messages-nb.d.ts +10 -1
- package/lib/locale/messages-nb.js +10 -1
- package/lib/locale/messages-nn.d.ts +10 -1
- package/lib/locale/messages-nn.js +10 -1
- package/lib/locale/messages-se.d.ts +10 -1
- package/lib/locale/messages-se.js +10 -1
- package/lib/locale/messages-sma.d.ts +10 -1
- package/lib/locale/messages-sma.js +10 -1
- package/package.json +5 -5
- package/src/Breadcrumb/ActionBreadcrumb.tsx +3 -0
- package/src/MyNdla/Resource/Folder.tsx +1 -1
- package/src/Resource/ListResource.tsx +4 -2
- package/src/TreeStructure/FolderItem.tsx +63 -40
- package/src/TreeStructure/FolderItems.tsx +26 -19
- package/src/TreeStructure/FolderNameInput.tsx +9 -11
- package/src/TreeStructure/TreeStructure.tsx +56 -71
- package/src/TreeStructure/TreeStructure.types.ts +13 -17
- package/src/TreeStructure/arrowNavigation.ts +53 -0
- package/src/TreeStructure/helperFunctions.ts +17 -25
- package/src/locale/messages-en.ts +10 -1
- package/src/locale/messages-nb.ts +10 -1
- package/src/locale/messages-nn.ts +10 -1
- package/src/locale/messages-se.ts +10 -1
- package/src/locale/messages-sma.ts +10 -1
- package/es/TreeStructure/keyboardNavigation/keyboardNavigation.js +0 -194
- package/es/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +0 -0
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.d.ts +0 -11
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.js +0 -198
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.d.ts +0 -26
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +0 -1
- package/src/TreeStructure/keyboardNavigation/keyboardNavigation.ts +0 -161
- package/src/TreeStructure/keyboardNavigation/keyboardNavigation.types.ts +0 -28
|
@@ -951,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
|
|
|
951
951
|
resources_plural: '{{count}} Resources',
|
|
952
952
|
folders: '{{count}} Folder',
|
|
953
953
|
folders_plural: '{{count}} Folders',
|
|
954
|
-
folder:
|
|
954
|
+
folder: {
|
|
955
|
+
folder: 'Folder',
|
|
956
|
+
"delete": 'Delete',
|
|
957
|
+
edit: 'Edit'
|
|
958
|
+
},
|
|
959
|
+
confirmDeleteFolder: 'Are you sure you want to delete this folder? This process cannot be undone.',
|
|
960
|
+
confirmDeleteTag: 'Are you sure you want to delete this tag? This process cannot be undone.',
|
|
955
961
|
myFolders: 'My folders',
|
|
956
962
|
myTags: 'My tags',
|
|
957
963
|
newFolder: 'New folder',
|
|
@@ -997,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
|
|
|
997
1003
|
}
|
|
998
1004
|
},
|
|
999
1005
|
resource: {
|
|
1006
|
+
add: 'Add folder/tag',
|
|
1007
|
+
remove: 'Remove',
|
|
1008
|
+
copyLink: 'Copy link to this page',
|
|
1000
1009
|
addToMyNdla: 'Add to My NDLA',
|
|
1001
1010
|
addedToMyNdla: 'Added to My NDLA'
|
|
1002
1011
|
}
|
|
@@ -58,7 +58,13 @@ declare const messages: {
|
|
|
58
58
|
resources_plural: string;
|
|
59
59
|
folders: string;
|
|
60
60
|
folders_plural: string;
|
|
61
|
-
folder:
|
|
61
|
+
folder: {
|
|
62
|
+
folder: string;
|
|
63
|
+
delete: string;
|
|
64
|
+
edit: string;
|
|
65
|
+
};
|
|
66
|
+
confirmDeleteFolder: string;
|
|
67
|
+
confirmDeleteTag: string;
|
|
62
68
|
myFolders: string;
|
|
63
69
|
myTags: string;
|
|
64
70
|
newFolder: string;
|
|
@@ -104,6 +110,9 @@ declare const messages: {
|
|
|
104
110
|
};
|
|
105
111
|
};
|
|
106
112
|
resource: {
|
|
113
|
+
add: string;
|
|
114
|
+
remove: string;
|
|
115
|
+
copyLink: string;
|
|
107
116
|
addToMyNdla: string;
|
|
108
117
|
addedToMyNdla: string;
|
|
109
118
|
};
|
|
@@ -951,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
|
|
|
951
951
|
resources_plural: '{{count}} ressurser',
|
|
952
952
|
folders: '{{count}} mappe',
|
|
953
953
|
folders_plural: '{{count}} mapper',
|
|
954
|
-
folder:
|
|
954
|
+
folder: {
|
|
955
|
+
folder: 'Mappe',
|
|
956
|
+
"delete": 'Slett',
|
|
957
|
+
edit: 'Rediger'
|
|
958
|
+
},
|
|
959
|
+
confirmDeleteFolder: 'Er du sikker på at du vil slette mappen? Denne handlingen kan ikke angres.',
|
|
960
|
+
confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlingen kan ikke angres.',
|
|
955
961
|
myFolders: 'Mine mapper',
|
|
956
962
|
myTags: 'Mine tags',
|
|
957
963
|
newFolder: 'Ny mappe',
|
|
@@ -997,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
|
|
|
997
1003
|
}
|
|
998
1004
|
},
|
|
999
1005
|
resource: {
|
|
1006
|
+
add: 'Legg til mappe/tag',
|
|
1007
|
+
remove: 'Fjern',
|
|
1008
|
+
copyLink: 'Kopier lenke til siden',
|
|
1000
1009
|
addToMyNdla: 'Legg i Min NDLA',
|
|
1001
1010
|
addedToMyNdla: 'Lagt i Min NDLA'
|
|
1002
1011
|
}
|
|
@@ -58,7 +58,13 @@ declare const messages: {
|
|
|
58
58
|
resources_plural: string;
|
|
59
59
|
folders: string;
|
|
60
60
|
folders_plural: string;
|
|
61
|
-
folder:
|
|
61
|
+
folder: {
|
|
62
|
+
folder: string;
|
|
63
|
+
delete: string;
|
|
64
|
+
edit: string;
|
|
65
|
+
};
|
|
66
|
+
confirmDeleteFolder: string;
|
|
67
|
+
confirmDeleteTag: string;
|
|
62
68
|
myFolders: string;
|
|
63
69
|
myTags: string;
|
|
64
70
|
newFolder: string;
|
|
@@ -104,6 +110,9 @@ declare const messages: {
|
|
|
104
110
|
};
|
|
105
111
|
};
|
|
106
112
|
resource: {
|
|
113
|
+
add: string;
|
|
114
|
+
remove: string;
|
|
115
|
+
copyLink: string;
|
|
107
116
|
addToMyNdla: string;
|
|
108
117
|
addedToMyNdla: string;
|
|
109
118
|
};
|
|
@@ -951,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
|
|
|
951
951
|
resources_plural: '{{count}} ressursar',
|
|
952
952
|
folders: '{{count}} mappe',
|
|
953
953
|
folders_plural: '{{count}} mapper',
|
|
954
|
-
folder:
|
|
954
|
+
folder: {
|
|
955
|
+
folder: 'Mappe',
|
|
956
|
+
"delete": 'Slett',
|
|
957
|
+
edit: 'Rediger'
|
|
958
|
+
},
|
|
959
|
+
confirmDeleteFolder: 'Er du sikker på at du vil slette mappa? Denne handlinga kan ikkje angres.',
|
|
960
|
+
confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlinga kan ikkje angres.',
|
|
955
961
|
myFolders: 'Mine mapper',
|
|
956
962
|
myTags: 'Mine tags',
|
|
957
963
|
newFolder: 'Ny mappe',
|
|
@@ -997,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
|
|
|
997
1003
|
}
|
|
998
1004
|
},
|
|
999
1005
|
resource: {
|
|
1006
|
+
add: 'Legg til mappe/tag',
|
|
1007
|
+
remove: 'Fjern',
|
|
1008
|
+
copyLink: 'Kopier lenke til sida',
|
|
1000
1009
|
addToMyNdla: 'Legg i Min NDLA',
|
|
1001
1010
|
addedToMyNdla: 'Lagt i Min NDLA'
|
|
1002
1011
|
}
|
|
@@ -58,7 +58,13 @@ declare const messages: {
|
|
|
58
58
|
resources_plural: string;
|
|
59
59
|
folders: string;
|
|
60
60
|
folders_plural: string;
|
|
61
|
-
folder:
|
|
61
|
+
folder: {
|
|
62
|
+
folder: string;
|
|
63
|
+
delete: string;
|
|
64
|
+
edit: string;
|
|
65
|
+
};
|
|
66
|
+
confirmDeleteFolder: string;
|
|
67
|
+
confirmDeleteTag: string;
|
|
62
68
|
myFolders: string;
|
|
63
69
|
myTags: string;
|
|
64
70
|
newFolder: string;
|
|
@@ -104,6 +110,9 @@ declare const messages: {
|
|
|
104
110
|
};
|
|
105
111
|
};
|
|
106
112
|
resource: {
|
|
113
|
+
add: string;
|
|
114
|
+
remove: string;
|
|
115
|
+
copyLink: string;
|
|
107
116
|
addToMyNdla: string;
|
|
108
117
|
addedToMyNdla: string;
|
|
109
118
|
};
|
|
@@ -951,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
|
|
|
951
951
|
resources_plural: '{{count}} ressurser',
|
|
952
952
|
folders: '{{count}} mappe',
|
|
953
953
|
folders_plural: '{{count}} mapper',
|
|
954
|
-
folder:
|
|
954
|
+
folder: {
|
|
955
|
+
folder: 'Mappe',
|
|
956
|
+
"delete": 'Slett',
|
|
957
|
+
edit: 'Rediger'
|
|
958
|
+
},
|
|
959
|
+
confirmDeleteFolder: 'Er du sikker på at du vil slette mappen? Denne handlingen kan ikke angres.',
|
|
960
|
+
confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlingen kan ikke angres.',
|
|
955
961
|
myFolders: 'Mine mapper',
|
|
956
962
|
myTags: 'Mine tags',
|
|
957
963
|
newFolder: 'Ny mappe',
|
|
@@ -997,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
|
|
|
997
1003
|
}
|
|
998
1004
|
},
|
|
999
1005
|
resource: {
|
|
1006
|
+
add: 'Legg til mappe/tag',
|
|
1007
|
+
remove: 'Fjern',
|
|
1008
|
+
copyLink: 'Kopier lenke til siden',
|
|
1000
1009
|
addToMyNdla: 'Legg i Min NDLA',
|
|
1001
1010
|
addedToMyNdla: 'Lagt i Min NDLA'
|
|
1002
1011
|
}
|
|
@@ -58,7 +58,13 @@ declare const messages: {
|
|
|
58
58
|
resources_plural: string;
|
|
59
59
|
folders: string;
|
|
60
60
|
folders_plural: string;
|
|
61
|
-
folder:
|
|
61
|
+
folder: {
|
|
62
|
+
folder: string;
|
|
63
|
+
delete: string;
|
|
64
|
+
edit: string;
|
|
65
|
+
};
|
|
66
|
+
confirmDeleteFolder: string;
|
|
67
|
+
confirmDeleteTag: string;
|
|
62
68
|
myFolders: string;
|
|
63
69
|
myTags: string;
|
|
64
70
|
newFolder: string;
|
|
@@ -104,6 +110,9 @@ declare const messages: {
|
|
|
104
110
|
};
|
|
105
111
|
};
|
|
106
112
|
resource: {
|
|
113
|
+
add: string;
|
|
114
|
+
remove: string;
|
|
115
|
+
copyLink: string;
|
|
107
116
|
addToMyNdla: string;
|
|
108
117
|
addedToMyNdla: string;
|
|
109
118
|
};
|
|
@@ -951,7 +951,13 @@ var messages = _objectSpread(_objectSpread({
|
|
|
951
951
|
resources_plural: '{{count}} ressurser',
|
|
952
952
|
folders: '{{count}} mappe',
|
|
953
953
|
folders_plural: '{{count}} mapper',
|
|
954
|
-
folder:
|
|
954
|
+
folder: {
|
|
955
|
+
folder: 'Mappe',
|
|
956
|
+
"delete": 'Slett',
|
|
957
|
+
edit: 'Rediger'
|
|
958
|
+
},
|
|
959
|
+
confirmDeleteFolder: 'Er du sikker på at du vil slette mappen? Denne handlingen kan ikke angres.',
|
|
960
|
+
confirmDeleteTag: 'Er du sikker på at du vil slette tag? Denne handlingen kan ikke angres.',
|
|
955
961
|
myFolders: 'Mine mapper',
|
|
956
962
|
myTags: 'Mine tags',
|
|
957
963
|
newFolder: 'Ny mappe',
|
|
@@ -997,6 +1003,9 @@ var messages = _objectSpread(_objectSpread({
|
|
|
997
1003
|
}
|
|
998
1004
|
},
|
|
999
1005
|
resource: {
|
|
1006
|
+
add: 'Legg til mappe/tag',
|
|
1007
|
+
remove: 'Fjern',
|
|
1008
|
+
copyLink: 'Kopier lenke til siden',
|
|
1000
1009
|
addToMyNdla: 'Legg i Min NDLA',
|
|
1001
1010
|
addedToMyNdla: 'Lagt i Min NDLA'
|
|
1002
1011
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ndla/ui",
|
|
3
|
-
"version": "19.0
|
|
3
|
+
"version": "19.2.0",
|
|
4
4
|
"description": "UI component library for NDLA.",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"types"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ndla/button": "^3.
|
|
34
|
+
"@ndla/button": "^3.1.2",
|
|
35
35
|
"@ndla/carousel": "^1.2.11",
|
|
36
36
|
"@ndla/core": "^2.3.0",
|
|
37
37
|
"@ndla/hooks": "^1.1.4",
|
|
38
38
|
"@ndla/icons": "^1.10.0",
|
|
39
39
|
"@ndla/licenses": "^5.0.2",
|
|
40
40
|
"@ndla/modal": "^1.2.12",
|
|
41
|
-
"@ndla/notion": "^3.1.
|
|
42
|
-
"@ndla/safelink": "^2.
|
|
41
|
+
"@ndla/notion": "^3.1.22",
|
|
42
|
+
"@ndla/safelink": "^2.2.0",
|
|
43
43
|
"@ndla/switch": "^0.1.7",
|
|
44
44
|
"@ndla/tabs": "^1.1.10",
|
|
45
45
|
"@ndla/tooltip": "^2.1.2",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"publishConfig": {
|
|
82
82
|
"access": "public"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "5f018a6a78778970d0d448896de96bb16e970fab"
|
|
85
85
|
}
|
|
@@ -44,6 +44,9 @@ interface Props {
|
|
|
44
44
|
|
|
45
45
|
const ActionBreadcrumb = ({ items, actionItems }: Props) => {
|
|
46
46
|
const renderItem = (item: IndexedBreadcrumbItem, totalCount: number) => {
|
|
47
|
+
if (totalCount === 1) {
|
|
48
|
+
return <StyledSpan title={item.name}>{item.name}</StyledSpan>;
|
|
49
|
+
}
|
|
47
50
|
if (item.index === totalCount - 1) {
|
|
48
51
|
return (
|
|
49
52
|
<MenuButton menuItems={actionItems} size="small">
|
|
@@ -136,7 +136,7 @@ const Folder = ({ link, title, subFolders, subResources, type = 'list', menuItem
|
|
|
136
136
|
return (
|
|
137
137
|
<FolderWrapper to={link}>
|
|
138
138
|
<FolderIconWrapper type={type}>
|
|
139
|
-
<FolderOutlined aria-label={t('myNdla.folder')} />
|
|
139
|
+
<FolderOutlined aria-label={t('myNdla.folder.folder')} />
|
|
140
140
|
</FolderIconWrapper>
|
|
141
141
|
<FolderTitle>{title}</FolderTitle>
|
|
142
142
|
<IconCount layoutType={type} type={'folder'} count={subFolders} />
|
|
@@ -31,12 +31,13 @@ const ResourceDescription = styled.p`
|
|
|
31
31
|
`;
|
|
32
32
|
|
|
33
33
|
const ResourceWrapper = styled(SafeLink)`
|
|
34
|
-
display: grid;
|
|
35
34
|
flex: 1;
|
|
35
|
+
display: grid;
|
|
36
|
+
grid-template-columns: auto 1fr auto;
|
|
36
37
|
grid-template-areas:
|
|
37
38
|
'image topicAndTitle tags'
|
|
38
39
|
'image description description';
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
${mq.range({ until: breakpoints.mobileWide })} {
|
|
41
42
|
grid-template-columns: auto 1fr;
|
|
42
43
|
grid-template-areas:
|
|
@@ -52,6 +53,7 @@ const ResourceWrapper = styled(SafeLink)`
|
|
|
52
53
|
border-radius: 2px;
|
|
53
54
|
color: ${colors.brand.greyDark};
|
|
54
55
|
gap: 0 ${spacing.small};
|
|
56
|
+
|
|
55
57
|
&:hover {
|
|
56
58
|
box-shadow: 1px 1px 6px 2px rgba(9, 55, 101, 0.08);
|
|
57
59
|
transition-duration: 0.2s;
|
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React, { useEffect, useRef } from 'react';
|
|
9
|
+
import React, { KeyboardEvent, useEffect, useRef } from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
11
|
import { ArrowDropDown } from '@ndla/icons/common';
|
|
12
12
|
import { FolderOutlined } from '@ndla/icons/contentType';
|
|
13
13
|
import { colors, spacing, misc, animations } from '@ndla/core';
|
|
14
14
|
import SafeLink from '@ndla/safelink';
|
|
15
15
|
import { SetFocusedFolderId, FolderChildFuncType } from './TreeStructure.types';
|
|
16
|
+
import { arrowNavigation } from './arrowNavigation';
|
|
16
17
|
|
|
17
18
|
const OpenButton = styled.button<{ isOpen: boolean }>`
|
|
18
19
|
background: transparent;
|
|
@@ -49,7 +50,10 @@ const WrapperForFolderChild = styled.div<{ marked: boolean }>`
|
|
|
49
50
|
}
|
|
50
51
|
`;
|
|
51
52
|
|
|
52
|
-
const FolderName = styled
|
|
53
|
+
const FolderName = styled('button', { shouldForwardProp: (name) => !['marked', 'noArrow'].includes(name) })<{
|
|
54
|
+
marked: boolean;
|
|
55
|
+
noArrow?: boolean;
|
|
56
|
+
}>`
|
|
53
57
|
line-height: 1;
|
|
54
58
|
background: ${({ marked }) => (marked ? colors.brand.lighter : 'transparent')};
|
|
55
59
|
color: ${colors.text.primary};
|
|
@@ -81,16 +85,19 @@ const FolderNameLink = FolderName.withComponent(SafeLink);
|
|
|
81
85
|
interface Props {
|
|
82
86
|
name: string;
|
|
83
87
|
id: string;
|
|
84
|
-
|
|
88
|
+
level: number;
|
|
89
|
+
onCloseFolder: (id: string) => void;
|
|
90
|
+
onOpenFolder: (id: string) => void;
|
|
85
91
|
onMarkFolder: (id: string) => void;
|
|
92
|
+
onSelectFolder?: (id: string) => void;
|
|
86
93
|
isOpen: boolean;
|
|
87
94
|
markedFolderId?: string;
|
|
88
95
|
focusedFolderId?: string;
|
|
96
|
+
visibleFolders: string[];
|
|
89
97
|
loading?: boolean;
|
|
90
98
|
openOnFolderClick?: boolean;
|
|
91
99
|
hideArrow?: boolean;
|
|
92
100
|
setFocusedFolderId: SetFocusedFolderId;
|
|
93
|
-
url?: string;
|
|
94
101
|
icon?: React.ReactNode;
|
|
95
102
|
noPaddingWhenArrowIsHidden?: boolean;
|
|
96
103
|
folderChild?: FolderChildFuncType;
|
|
@@ -99,62 +106,61 @@ interface Props {
|
|
|
99
106
|
const FolderItem = ({
|
|
100
107
|
hideArrow,
|
|
101
108
|
loading,
|
|
109
|
+
level,
|
|
102
110
|
name,
|
|
103
111
|
id,
|
|
104
|
-
|
|
112
|
+
visibleFolders,
|
|
113
|
+
onCloseFolder,
|
|
114
|
+
onOpenFolder,
|
|
105
115
|
onMarkFolder,
|
|
116
|
+
onSelectFolder,
|
|
106
117
|
isOpen,
|
|
107
118
|
markedFolderId,
|
|
108
119
|
focusedFolderId,
|
|
109
120
|
openOnFolderClick,
|
|
110
121
|
setFocusedFolderId,
|
|
111
122
|
icon,
|
|
112
|
-
url,
|
|
113
123
|
noPaddingWhenArrowIsHidden,
|
|
114
124
|
folderChild,
|
|
115
125
|
}: Props) => {
|
|
116
|
-
const
|
|
117
|
-
const
|
|
126
|
+
const ref = useRef<HTMLButtonElement & HTMLAnchorElement>(null);
|
|
127
|
+
const marked = markedFolderId === id;
|
|
128
|
+
|
|
129
|
+
const handleMarkFolder = () => {
|
|
130
|
+
onMarkFolder(id);
|
|
131
|
+
if (openOnFolderClick) {
|
|
132
|
+
if (isOpen) {
|
|
133
|
+
onCloseFolder(id);
|
|
134
|
+
} else {
|
|
135
|
+
onOpenFolder(id);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
118
140
|
useEffect(() => {
|
|
119
141
|
if (focusedFolderId === id) {
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
} else if (folderNameButtonRef.current) {
|
|
123
|
-
folderNameButtonRef.current.focus();
|
|
142
|
+
if (ref.current) {
|
|
143
|
+
ref.current.focus();
|
|
124
144
|
}
|
|
125
145
|
}
|
|
126
|
-
}, [focusedFolderId,
|
|
127
|
-
|
|
146
|
+
}, [focusedFolderId, ref, id]);
|
|
147
|
+
|
|
128
148
|
return (
|
|
129
149
|
<FolderItemWrapper>
|
|
130
150
|
{!hideArrow && (
|
|
131
|
-
<OpenButton
|
|
151
|
+
<OpenButton
|
|
152
|
+
tabIndex={-1}
|
|
153
|
+
isOpen={isOpen}
|
|
154
|
+
disabled={loading}
|
|
155
|
+
onClick={() => (isOpen ? onCloseFolder(id) : onOpenFolder(id))}>
|
|
132
156
|
<ArrowDropDown />
|
|
133
157
|
</OpenButton>
|
|
134
158
|
)}
|
|
135
|
-
{
|
|
136
|
-
<FolderNameLink
|
|
137
|
-
ref={folderNameLinkRef}
|
|
138
|
-
noArrow={hideArrow}
|
|
139
|
-
to={loading ? '' : url}
|
|
140
|
-
tabIndex={marked ? 0 : -1}
|
|
141
|
-
marked={marked}
|
|
142
|
-
onFocus={() => {
|
|
143
|
-
setFocusedFolderId(id);
|
|
144
|
-
}}
|
|
145
|
-
onClick={() => {
|
|
146
|
-
onMarkFolder(id);
|
|
147
|
-
if (openOnFolderClick) {
|
|
148
|
-
onToggleOpen(id);
|
|
149
|
-
}
|
|
150
|
-
}}>
|
|
151
|
-
{icon || <FolderOutlined />}
|
|
152
|
-
{name}
|
|
153
|
-
</FolderNameLink>
|
|
154
|
-
) : (
|
|
159
|
+
{onSelectFolder ? (
|
|
155
160
|
<>
|
|
156
161
|
<FolderName
|
|
157
|
-
ref={
|
|
162
|
+
ref={ref}
|
|
163
|
+
onKeyDown={(e) => arrowNavigation(e, id, visibleFolders, setFocusedFolderId, onOpenFolder, onCloseFolder)}
|
|
158
164
|
noArrow={hideArrow && !noPaddingWhenArrowIsHidden}
|
|
159
165
|
tabIndex={marked ? 0 : -1}
|
|
160
166
|
marked={marked}
|
|
@@ -163,10 +169,8 @@ const FolderItem = ({
|
|
|
163
169
|
setFocusedFolderId(id);
|
|
164
170
|
}}
|
|
165
171
|
onClick={() => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
onToggleOpen(id);
|
|
169
|
-
}
|
|
172
|
+
handleMarkFolder();
|
|
173
|
+
onSelectFolder(id);
|
|
170
174
|
}}>
|
|
171
175
|
{icon || <FolderOutlined />}
|
|
172
176
|
{name}
|
|
@@ -177,6 +181,25 @@ const FolderItem = ({
|
|
|
177
181
|
</WrapperForFolderChild>
|
|
178
182
|
)}
|
|
179
183
|
</>
|
|
184
|
+
) : (
|
|
185
|
+
<FolderNameLink
|
|
186
|
+
ref={ref}
|
|
187
|
+
onKeyDown={(e: KeyboardEvent<HTMLElement>) =>
|
|
188
|
+
arrowNavigation(e, id, visibleFolders, setFocusedFolderId, onOpenFolder, onCloseFolder)
|
|
189
|
+
}
|
|
190
|
+
noArrow={hideArrow}
|
|
191
|
+
to={loading ? '' : `/minndla/${level > 1 ? 'folders/' : ''}${id}`}
|
|
192
|
+
tabIndex={marked || level === 1 ? 0 : -1}
|
|
193
|
+
marked={marked}
|
|
194
|
+
onFocus={() => {
|
|
195
|
+
setFocusedFolderId(id);
|
|
196
|
+
}}
|
|
197
|
+
onClick={() => {
|
|
198
|
+
handleMarkFolder();
|
|
199
|
+
}}>
|
|
200
|
+
{icon || <FolderOutlined />}
|
|
201
|
+
{name}
|
|
202
|
+
</FolderNameLink>
|
|
180
203
|
)}
|
|
181
204
|
</FolderItemWrapper>
|
|
182
205
|
);
|
|
@@ -32,65 +32,73 @@ const StyledLI = styled.li`
|
|
|
32
32
|
|
|
33
33
|
const FolderItems = ({
|
|
34
34
|
loading,
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
folders,
|
|
36
|
+
level,
|
|
37
37
|
editable,
|
|
38
|
-
|
|
38
|
+
onSelectFolder,
|
|
39
|
+
onCloseFolder,
|
|
40
|
+
onOpenFolder,
|
|
39
41
|
onCreateNewFolder,
|
|
40
42
|
onCancelNewFolder,
|
|
41
43
|
onSaveNewFolder,
|
|
42
|
-
|
|
44
|
+
newFolderParentId,
|
|
45
|
+
visibleFolders,
|
|
43
46
|
openFolders,
|
|
44
47
|
markedFolderId,
|
|
45
48
|
onMarkFolder,
|
|
46
49
|
openOnFolderClick,
|
|
47
50
|
focusedFolderId,
|
|
48
51
|
setFocusedFolderId,
|
|
49
|
-
firstLevel,
|
|
50
52
|
folderChild,
|
|
51
53
|
maximumLevelsOfFoldersAllowed,
|
|
52
54
|
}: FolderItemsProps) => (
|
|
53
|
-
<StyledUL role="group" firstLevel={
|
|
54
|
-
{
|
|
55
|
-
const newIdPaths = [...idPaths, _index];
|
|
55
|
+
<StyledUL role="group" firstLevel={level === 1}>
|
|
56
|
+
{folders.map(({ name, subfolders, id, icon }, _index) => {
|
|
56
57
|
const isOpen = openFolders?.includes(id);
|
|
57
58
|
return (
|
|
58
59
|
<StyledLI key={id} role="treeitem">
|
|
59
60
|
<div>
|
|
60
61
|
<FolderItem
|
|
62
|
+
level={level}
|
|
61
63
|
icon={icon}
|
|
62
|
-
|
|
64
|
+
onSelectFolder={onSelectFolder}
|
|
63
65
|
openOnFolderClick={openOnFolderClick}
|
|
64
66
|
loading={loading}
|
|
65
67
|
isOpen={isOpen}
|
|
66
68
|
id={id}
|
|
69
|
+
visibleFolders={visibleFolders}
|
|
67
70
|
name={name}
|
|
68
71
|
markedFolderId={markedFolderId}
|
|
69
72
|
focusedFolderId={focusedFolderId}
|
|
70
|
-
onToggleOpen={onToggleOpen}
|
|
71
73
|
onMarkFolder={onMarkFolder}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
onCloseFolder={onCloseFolder}
|
|
75
|
+
onOpenFolder={onOpenFolder}
|
|
76
|
+
hideArrow={subfolders?.length === 0 || level > maximumLevelsOfFoldersAllowed}
|
|
77
|
+
noPaddingWhenArrowIsHidden={editable && level === 1 && subfolders?.length === 0}
|
|
74
78
|
setFocusedFolderId={setFocusedFolderId}
|
|
75
79
|
folderChild={folderChild}
|
|
76
80
|
/>
|
|
77
81
|
</div>
|
|
78
|
-
{
|
|
82
|
+
{newFolderParentId === id && (
|
|
79
83
|
<FolderNameInput
|
|
84
|
+
parentId={newFolderParentId}
|
|
80
85
|
loading={loading}
|
|
81
86
|
onCancelNewFolder={onCancelNewFolder}
|
|
82
87
|
onSaveNewFolder={onSaveNewFolder}
|
|
83
88
|
/>
|
|
84
89
|
)}
|
|
85
|
-
{
|
|
90
|
+
{subfolders && isOpen && (
|
|
86
91
|
<FolderItems
|
|
92
|
+
onSelectFolder={onSelectFolder}
|
|
87
93
|
loading={loading}
|
|
88
|
-
|
|
94
|
+
newFolderParentId={newFolderParentId}
|
|
95
|
+
visibleFolders={visibleFolders}
|
|
89
96
|
openFolders={openFolders}
|
|
90
|
-
|
|
97
|
+
level={level + 1}
|
|
91
98
|
editable={editable}
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
folders={subfolders}
|
|
100
|
+
onCloseFolder={onCloseFolder}
|
|
101
|
+
onOpenFolder={onOpenFolder}
|
|
94
102
|
onCreateNewFolder={onCreateNewFolder}
|
|
95
103
|
onSaveNewFolder={onSaveNewFolder}
|
|
96
104
|
onCancelNewFolder={onCancelNewFolder}
|
|
@@ -99,7 +107,6 @@ const FolderItems = ({
|
|
|
99
107
|
openOnFolderClick={openOnFolderClick}
|
|
100
108
|
focusedFolderId={focusedFolderId}
|
|
101
109
|
setFocusedFolderId={setFocusedFolderId}
|
|
102
|
-
firstLevel={false}
|
|
103
110
|
folderChild={folderChild}
|
|
104
111
|
maximumLevelsOfFoldersAllowed={maximumLevelsOfFoldersAllowed}
|
|
105
112
|
/>
|
|
@@ -53,14 +53,15 @@ const StyledInput = styled.input`
|
|
|
53
53
|
`;
|
|
54
54
|
|
|
55
55
|
interface FolderNameInputProps {
|
|
56
|
-
onSaveNewFolder: (
|
|
56
|
+
onSaveNewFolder: (name: string, parentId: string) => void;
|
|
57
|
+
parentId: string;
|
|
57
58
|
onCancelNewFolder: () => void;
|
|
58
59
|
loading?: boolean;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
const FolderNameInput = ({ onSaveNewFolder, onCancelNewFolder, loading }: FolderNameInputProps) => {
|
|
62
|
+
const FolderNameInput = ({ onSaveNewFolder, parentId, onCancelNewFolder, loading }: FolderNameInputProps) => {
|
|
62
63
|
const { t } = useTranslation();
|
|
63
|
-
const [
|
|
64
|
+
const [name, setName] = useState<string>(t('treeStructure.newFolder.defaultName'));
|
|
64
65
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
65
66
|
|
|
66
67
|
useEffect(() => {
|
|
@@ -82,22 +83,19 @@ const FolderNameInput = ({ onSaveNewFolder, onCancelNewFolder, loading }: Folder
|
|
|
82
83
|
autoFocus
|
|
83
84
|
placeholder={t('treeStructure.newFolder.placeholder')}
|
|
84
85
|
disabled={loading}
|
|
85
|
-
value={
|
|
86
|
+
value={name}
|
|
86
87
|
onBlur={() => onCancelNewFolder()}
|
|
87
88
|
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
88
89
|
if (e.key === 'Escape') {
|
|
89
90
|
onCancelNewFolder();
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
if (e.key === 'Enter' || e.key === 'Tab') {
|
|
93
|
-
onSaveNewFolder(value);
|
|
91
|
+
} else if (e.key === 'Enter' || e.key === 'Tab') {
|
|
94
92
|
e.preventDefault();
|
|
93
|
+
onSaveNewFolder(name, parentId);
|
|
95
94
|
}
|
|
96
|
-
return;
|
|
97
95
|
}}
|
|
98
96
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
99
|
-
const target = e.target
|
|
100
|
-
|
|
97
|
+
const target = e.target;
|
|
98
|
+
setName(target.value);
|
|
101
99
|
}}
|
|
102
100
|
/>
|
|
103
101
|
{loading && <Spinner size="small" />}
|