@ndla/ui 27.1.0 → 27.1.2
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/MyNdla/Resource/FolderInput.js +65 -77
- package/es/Resource/resourceComponents.js +13 -13
- package/es/TreeStructure/AddFolderButton.js +87 -0
- package/es/TreeStructure/ComboboxButton.js +13 -64
- package/es/TreeStructure/FolderItem.js +12 -12
- package/es/TreeStructure/FolderItems.js +12 -14
- package/es/TreeStructure/TreeStructure.js +55 -41
- package/es/i18n/i18n.js +1 -0
- package/es/locale/messages-en.js +1 -1
- package/es/locale/messages-nb.js +1 -1
- package/es/locale/messages-nn.js +1 -1
- package/es/locale/messages-se.js +2 -2
- package/es/locale/messages-sma.js +1 -1
- package/lib/MyNdla/Resource/FolderInput.d.ts +7 -6
- package/lib/MyNdla/Resource/FolderInput.js +65 -73
- package/lib/Resource/resourceComponents.js +13 -13
- package/lib/TreeStructure/AddFolderButton.d.ts +16 -0
- package/lib/TreeStructure/AddFolderButton.js +100 -0
- package/lib/TreeStructure/ComboboxButton.d.ts +0 -4
- package/lib/TreeStructure/ComboboxButton.js +19 -64
- package/lib/TreeStructure/FolderItem.js +12 -12
- package/lib/TreeStructure/FolderItems.d.ts +4 -3
- package/lib/TreeStructure/FolderItems.js +12 -15
- package/lib/TreeStructure/TreeStructure.d.ts +3 -4
- package/lib/TreeStructure/TreeStructure.js +55 -41
- package/lib/TreeStructure/types.d.ts +7 -1
- package/lib/i18n/i18n.js +1 -0
- package/lib/locale/messages-en.js +1 -1
- package/lib/locale/messages-nb.js +1 -1
- package/lib/locale/messages-nn.js +1 -1
- package/lib/locale/messages-se.js +2 -2
- package/lib/locale/messages-sma.js +1 -1
- package/package.json +6 -6
- package/src/MyNdla/Resource/FolderInput.tsx +69 -73
- package/src/Resource/resourceComponents.tsx +4 -6
- package/src/TreeStructure/AddFolderButton.tsx +79 -0
- package/src/TreeStructure/ComboboxButton.tsx +8 -53
- package/src/TreeStructure/FolderItem.tsx +5 -4
- package/src/TreeStructure/FolderItems.tsx +8 -15
- package/src/TreeStructure/TreeStructure.tsx +42 -33
- package/src/TreeStructure/types.ts +13 -1
- package/src/i18n/i18n.ts +1 -0
- package/src/locale/messages-en.ts +1 -1
- package/src/locale/messages-nb.ts +1 -1
- package/src/locale/messages-nn.ts +1 -1
- package/src/locale/messages-se.ts +2 -2
- package/src/locale/messages-sma.ts +1 -1
- package/es/TreeStructure/FolderNameInput.js +0 -143
- package/lib/TreeStructure/FolderNameInput.d.ts +0 -19
- package/lib/TreeStructure/FolderNameInput.js +0 -159
- package/src/TreeStructure/FolderNameInput.tsx +0 -167
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ndla/ui",
|
|
3
|
-
"version": "27.1.
|
|
3
|
+
"version": "27.1.2",
|
|
4
4
|
"description": "UI component library for NDLA.",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -32,16 +32,16 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@ndla/article-scripts": "^3.0.2",
|
|
35
|
-
"@ndla/button": "^3.5.
|
|
35
|
+
"@ndla/button": "^3.5.3",
|
|
36
36
|
"@ndla/carousel": "^1.2.23",
|
|
37
37
|
"@ndla/core": "^2.3.5",
|
|
38
|
-
"@ndla/forms": "^3.3.
|
|
38
|
+
"@ndla/forms": "^3.3.3",
|
|
39
39
|
"@ndla/hooks": "^1.1.6",
|
|
40
40
|
"@ndla/icons": "^1.13.0",
|
|
41
41
|
"@ndla/licenses": "^5.0.17",
|
|
42
42
|
"@ndla/modal": "^1.4.0",
|
|
43
|
-
"@ndla/notion": "^3.1.
|
|
44
|
-
"@ndla/safelink": "^2.2.
|
|
43
|
+
"@ndla/notion": "^3.1.44",
|
|
44
|
+
"@ndla/safelink": "^2.2.17",
|
|
45
45
|
"@ndla/switch": "^0.1.13",
|
|
46
46
|
"@ndla/tabs": "^1.1.22",
|
|
47
47
|
"@ndla/tooltip": "^2.2.1",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "bba524f1971adfe12c6b5e6ac8d2a532f828f790"
|
|
89
89
|
}
|
|
@@ -7,110 +7,106 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import styled from '@emotion/styled';
|
|
10
|
-
import { IconButton } from '@ndla/button';
|
|
11
|
-
import { FolderOutlined } from '@ndla/icons/contentType';
|
|
10
|
+
import { IconButton, IconButtonV2 } from '@ndla/button';
|
|
12
11
|
import { Cross } from '@ndla/icons/action';
|
|
13
|
-
import React, {
|
|
12
|
+
import React, { ComponentProps, forwardRef, useEffect } from 'react';
|
|
13
|
+
import { isMobile } from 'react-device-detect';
|
|
14
14
|
import { useTranslation } from 'react-i18next';
|
|
15
15
|
import { colors, spacing } from '@ndla/core';
|
|
16
|
-
import {
|
|
17
|
-
import { css } from '@emotion/core';
|
|
16
|
+
import { InputV2 } from '@ndla/forms';
|
|
18
17
|
import { Done } from '@ndla/icons/editor';
|
|
18
|
+
import { Spinner } from '@ndla/icons';
|
|
19
|
+
import { useForwardedRef } from '@ndla/util';
|
|
20
|
+
|
|
21
|
+
interface Props extends ComponentProps<typeof InputV2> {
|
|
22
|
+
loading?: boolean;
|
|
23
|
+
onClose?: () => void;
|
|
24
|
+
onSave: () => void;
|
|
25
|
+
}
|
|
19
26
|
|
|
20
27
|
// Source: https://kovart.github.io/dashed-border-generator/
|
|
21
|
-
const borderStyle =
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
const borderStyle = (error?: boolean) =>
|
|
29
|
+
`url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' stroke='${encodeURIComponent(
|
|
30
|
+
error ? colors.support.red : colors.brand.tertiary,
|
|
31
|
+
)}' stroke-width='2' stroke-dasharray='8%2c8' stroke-dashoffset='4' stroke-linecap='square'/%3e%3c/svg%3e")`;
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
svg {
|
|
29
|
-
color: ${colors.brand.primary};
|
|
30
|
-
height: 20px;
|
|
31
|
-
width: 20px;
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
33
|
+
interface StyledInputProps {
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
34
36
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
background:
|
|
38
|
-
background-image: ${borderStyle};
|
|
37
|
+
const StyledInput = styled(InputV2)<StyledInputProps>`
|
|
38
|
+
background-color: white;
|
|
39
|
+
background-image: ${({ error }) => borderStyle(!!error)};
|
|
39
40
|
border: none;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
&& {
|
|
44
|
-
flex-grow: 1;
|
|
45
|
-
flex-basis: 0;
|
|
46
|
-
min-width: 0;
|
|
41
|
+
border-radius: 0;
|
|
42
|
+
flex-wrap: nowrap;
|
|
43
|
+
input {
|
|
47
44
|
line-height: 1.75em;
|
|
48
45
|
color: ${colors.brand.primary};
|
|
46
|
+
caret-color: ${colors.brand.tertiary};
|
|
49
47
|
::selection {
|
|
50
48
|
background: ${colors.brand.lighter};
|
|
51
49
|
}
|
|
50
|
+
::placeholder {
|
|
51
|
+
color: ${colors.brand.tertiary};
|
|
52
|
+
}
|
|
52
53
|
}
|
|
53
54
|
`;
|
|
54
55
|
|
|
55
56
|
const Row = styled.div`
|
|
56
57
|
display: flex;
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
align-items: center;
|
|
59
|
+
gap: ${spacing.xxsmall};
|
|
60
|
+
padding-right: ${spacing.xsmall};
|
|
59
61
|
`;
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
onAddFolder: (name: string) => void;
|
|
63
|
-
onClose: () => void;
|
|
64
|
-
autoSelect?: boolean;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const FolderInput = ({ onAddFolder, onClose, autoSelect }: Props) => {
|
|
63
|
+
const FolderInput = forwardRef<HTMLInputElement, Props>(({ loading, error, onClose, onSave, ...rest }, ref) => {
|
|
68
64
|
const { t } = useTranslation();
|
|
69
|
-
const
|
|
70
|
-
const [input, setInput] = useState<string>(newFolderText);
|
|
71
|
-
const inputRef = useRef<HTMLInputElement>(null);
|
|
72
|
-
|
|
73
|
-
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
74
|
-
setInput(e.target.value);
|
|
75
|
-
};
|
|
65
|
+
const inputRef = useForwardedRef(ref);
|
|
76
66
|
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
onAddFolder(input);
|
|
81
|
-
} else if (e.key === 'Escape') {
|
|
82
|
-
e.preventDefault();
|
|
83
|
-
onClose();
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (isMobile) {
|
|
69
|
+
inputRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
84
70
|
}
|
|
85
|
-
|
|
71
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
|
+
}, []);
|
|
86
73
|
|
|
87
74
|
return (
|
|
88
75
|
<StyledInput
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
onKeyDown={onKeydown}
|
|
96
|
-
aria-label={newFolderText}
|
|
97
|
-
iconLeft={
|
|
98
|
-
<StyledFolderIcon>
|
|
99
|
-
<FolderOutlined />
|
|
100
|
-
</StyledFolderIcon>
|
|
101
|
-
}
|
|
102
|
-
iconRight={
|
|
76
|
+
white
|
|
77
|
+
error={error}
|
|
78
|
+
aria-disabled={loading ? true : undefined}
|
|
79
|
+
aria-describedby={'folder-input-spinner'}
|
|
80
|
+
ref={ref}
|
|
81
|
+
after={
|
|
103
82
|
<Row>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
83
|
+
{!loading && (
|
|
84
|
+
<>
|
|
85
|
+
{!error && (
|
|
86
|
+
<IconButtonV2
|
|
87
|
+
variant={'ghost'}
|
|
88
|
+
colorTheme="light"
|
|
89
|
+
tabIndex={0}
|
|
90
|
+
aria-label={t('save')}
|
|
91
|
+
title={t('save')}
|
|
92
|
+
size="small"
|
|
93
|
+
onClick={onSave}>
|
|
94
|
+
<Done />
|
|
95
|
+
</IconButtonV2>
|
|
96
|
+
)}
|
|
97
|
+
<IconButton aria-label={t('close')} title={t('close')} size="small" ghostPill onClick={onClose}>
|
|
98
|
+
<Cross />
|
|
99
|
+
</IconButton>
|
|
100
|
+
</>
|
|
101
|
+
)}
|
|
102
|
+
<div aria-live="assertive">
|
|
103
|
+
{loading && <Spinner size="normal" margin={spacing.small} id="folder-spinner" aria-label={t('loading')} />}
|
|
104
|
+
</div>
|
|
110
105
|
</Row>
|
|
111
106
|
}
|
|
107
|
+
{...rest}
|
|
112
108
|
/>
|
|
113
109
|
);
|
|
114
|
-
};
|
|
110
|
+
});
|
|
115
111
|
|
|
116
112
|
export default FolderInput;
|
|
@@ -185,12 +185,10 @@ export const TopicList = ({ topics }: TopicListProps) => {
|
|
|
185
185
|
return (
|
|
186
186
|
<StyledTopicList aria-label={t('navigation.topics')}>
|
|
187
187
|
{topics.map((topic, i) => (
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
</StyledTopicListElement>
|
|
193
|
-
</>
|
|
188
|
+
<StyledTopicListElement key={topic}>
|
|
189
|
+
{topic}
|
|
190
|
+
{i !== topics.length - 1 && <StyledTopicDivider aria-hidden="true">•</StyledTopicDivider>}
|
|
191
|
+
</StyledTopicListElement>
|
|
194
192
|
))}
|
|
195
193
|
</StyledTopicList>
|
|
196
194
|
);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022-present, NDLA.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { useRef } from 'react';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
11
|
+
import Tooltip from '@ndla/tooltip';
|
|
12
|
+
import styled from '@emotion/styled';
|
|
13
|
+
import { ButtonV2 as Button } from '@ndla/button';
|
|
14
|
+
import { Plus } from '@ndla/icons/action';
|
|
15
|
+
import { FolderType } from './types';
|
|
16
|
+
|
|
17
|
+
interface AddFolderButtonProps {
|
|
18
|
+
canAddFolder: boolean;
|
|
19
|
+
focusedFolder?: FolderType;
|
|
20
|
+
setNewFolderParentId: (id?: string) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const StyledAddFolderButton = styled(Button)`
|
|
24
|
+
&,
|
|
25
|
+
&:disabled {
|
|
26
|
+
border-color: transparent;
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const StyledPlus = styled(Plus)`
|
|
31
|
+
height: 24px;
|
|
32
|
+
width: 24px;
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const AddFolderButton = ({ canAddFolder, setNewFolderParentId, focusedFolder }: AddFolderButtonProps) => {
|
|
36
|
+
const { t } = useTranslation();
|
|
37
|
+
const ref = useRef<HTMLButtonElement>(null);
|
|
38
|
+
return (
|
|
39
|
+
<Tooltip
|
|
40
|
+
tooltip={
|
|
41
|
+
canAddFolder
|
|
42
|
+
? t('myNdla.newFolderUnder', {
|
|
43
|
+
folderName: focusedFolder?.name,
|
|
44
|
+
})
|
|
45
|
+
: t('treeStructure.maxFoldersAlreadyAdded')
|
|
46
|
+
}>
|
|
47
|
+
<StyledAddFolderButton
|
|
48
|
+
ref={ref}
|
|
49
|
+
variant="outline"
|
|
50
|
+
shape="pill"
|
|
51
|
+
disabled={!canAddFolder}
|
|
52
|
+
aria-label={
|
|
53
|
+
canAddFolder
|
|
54
|
+
? t('myNdla.newFolderUnder', {
|
|
55
|
+
folderName: focusedFolder?.name,
|
|
56
|
+
})
|
|
57
|
+
: t('treeStructure.maxFoldersAlreadyAdded')
|
|
58
|
+
}
|
|
59
|
+
onMouseDown={(e) => {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
e.stopPropagation();
|
|
62
|
+
ref.current?.focus();
|
|
63
|
+
}}
|
|
64
|
+
onMouseUp={(e) => {
|
|
65
|
+
e.preventDefault();
|
|
66
|
+
e.stopPropagation();
|
|
67
|
+
ref.current?.focus();
|
|
68
|
+
}}
|
|
69
|
+
onClick={(e) => {
|
|
70
|
+
e.currentTarget.focus();
|
|
71
|
+
setNewFolderParentId(focusedFolder?.id);
|
|
72
|
+
}}>
|
|
73
|
+
<StyledPlus /> {t('myNdla.newFolder')}
|
|
74
|
+
</StyledAddFolderButton>
|
|
75
|
+
</Tooltip>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default AddFolderButton;
|
|
@@ -7,13 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import React, { KeyboardEvent } from 'react';
|
|
10
|
-
import { useTranslation } from 'react-i18next';
|
|
11
10
|
import styled from '@emotion/styled';
|
|
12
11
|
import { useForwardedRef } from '@ndla/util';
|
|
13
|
-
import
|
|
14
|
-
import { colors, spacing } from '@ndla/core';
|
|
15
|
-
import { IFolder } from '@ndla/types-learningpath-api';
|
|
16
|
-
import { Plus } from '@ndla/icons/action';
|
|
12
|
+
import { breakpoints, colors, mq, spacing } from '@ndla/core';
|
|
17
13
|
import { ChevronUp, ChevronDown } from '@ndla/icons/common';
|
|
18
14
|
import { forwardRef } from 'react';
|
|
19
15
|
import { ButtonV2 as Button, IconButtonV2 as IconButton } from '@ndla/button';
|
|
@@ -27,8 +23,8 @@ interface StyledRowProps {
|
|
|
27
23
|
|
|
28
24
|
const StyledRow = styled.div<StyledRowProps>`
|
|
29
25
|
display: flex;
|
|
30
|
-
justify-content: space-between;
|
|
31
26
|
padding: ${spacing.xxsmall};
|
|
27
|
+
align-items: center;
|
|
32
28
|
border-bottom: ${({ isOpen }) => isOpen && `1px solid ${colors.brand.tertiary}`};
|
|
33
29
|
`;
|
|
34
30
|
const StyledSelectedFolder = styled(Button)`
|
|
@@ -44,20 +40,13 @@ const StyledSelectedFolder = styled(Button)`
|
|
|
44
40
|
:focus-visible {
|
|
45
41
|
outline: none;
|
|
46
42
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
&:disabled {
|
|
52
|
-
border-color: transparent;
|
|
43
|
+
${mq.range({ until: breakpoints.tablet })} {
|
|
44
|
+
min-height: 4rem;
|
|
45
|
+
max-height: 4rem;
|
|
46
|
+
text-align: start;
|
|
53
47
|
}
|
|
54
48
|
`;
|
|
55
49
|
|
|
56
|
-
const StyledPlus = styled(Plus)`
|
|
57
|
-
height: 24px;
|
|
58
|
-
width: 24px;
|
|
59
|
-
`;
|
|
60
|
-
|
|
61
50
|
interface Props {
|
|
62
51
|
showTree: boolean;
|
|
63
52
|
type: TreeStructureType;
|
|
@@ -70,9 +59,6 @@ interface Props {
|
|
|
70
59
|
onOpenFolder: (id: string) => void;
|
|
71
60
|
onCloseFolder: (id: string) => void;
|
|
72
61
|
setFocusedFolder: (folder?: FolderType) => void;
|
|
73
|
-
onNewFolder?: (name: string, parentId: string) => Promise<IFolder>;
|
|
74
|
-
maxLevel: number;
|
|
75
|
-
setNewFolderParentId: (id?: string) => void;
|
|
76
62
|
}
|
|
77
63
|
|
|
78
64
|
const ComboboxButton = forwardRef<HTMLButtonElement, Props>(
|
|
@@ -89,13 +75,9 @@ const ComboboxButton = forwardRef<HTMLButtonElement, Props>(
|
|
|
89
75
|
setFocusedFolder,
|
|
90
76
|
onOpenFolder,
|
|
91
77
|
onCloseFolder,
|
|
92
|
-
onNewFolder,
|
|
93
|
-
maxLevel,
|
|
94
|
-
setNewFolderParentId,
|
|
95
78
|
},
|
|
96
79
|
ref,
|
|
97
80
|
) => {
|
|
98
|
-
const { t } = useTranslation();
|
|
99
81
|
const innerRef = useForwardedRef(ref);
|
|
100
82
|
|
|
101
83
|
const onKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {
|
|
@@ -118,7 +100,6 @@ const ComboboxButton = forwardRef<HTMLButtonElement, Props>(
|
|
|
118
100
|
}
|
|
119
101
|
};
|
|
120
102
|
|
|
121
|
-
const canAddFolder = selectedFolder && selectedFolder?.breadcrumbs.length < (maxLevel || 1);
|
|
122
103
|
return (
|
|
123
104
|
<StyledRow isOpen={showTree}>
|
|
124
105
|
<StyledSelectedFolder
|
|
@@ -137,35 +118,11 @@ const ComboboxButton = forwardRef<HTMLButtonElement, Props>(
|
|
|
137
118
|
shape="sharp"
|
|
138
119
|
onKeyDown={onKeyDown}
|
|
139
120
|
onClick={() => {
|
|
121
|
+
innerRef.current?.focus();
|
|
140
122
|
onToggleTree(!showTree);
|
|
141
123
|
}}>
|
|
142
124
|
{selectedFolder?.name}
|
|
143
125
|
</StyledSelectedFolder>
|
|
144
|
-
{onNewFolder && showTree && (
|
|
145
|
-
<Tooltip
|
|
146
|
-
tooltip={
|
|
147
|
-
canAddFolder
|
|
148
|
-
? t('myNdla.newFolderUnder', {
|
|
149
|
-
folderName: selectedFolder?.name,
|
|
150
|
-
})
|
|
151
|
-
: t('treeStructure.maxFoldersAlreadyAdded')
|
|
152
|
-
}>
|
|
153
|
-
<StyledAddFolderButton
|
|
154
|
-
variant="outline"
|
|
155
|
-
shape="pill"
|
|
156
|
-
disabled={!canAddFolder}
|
|
157
|
-
aria-label={
|
|
158
|
-
canAddFolder
|
|
159
|
-
? t('myNdla.newFolderUnder', {
|
|
160
|
-
folderName: selectedFolder?.name,
|
|
161
|
-
})
|
|
162
|
-
: t('treeStructure.maxFoldersAlreadyAdded')
|
|
163
|
-
}
|
|
164
|
-
onClick={() => setNewFolderParentId(focusedFolder?.id)}>
|
|
165
|
-
<StyledPlus /> {t('myNdla.newFolder')}
|
|
166
|
-
</StyledAddFolderButton>
|
|
167
|
-
</Tooltip>
|
|
168
|
-
)}
|
|
169
126
|
<IconButton
|
|
170
127
|
aria-hidden
|
|
171
128
|
aria-label=""
|
|
@@ -174,9 +131,7 @@ const ComboboxButton = forwardRef<HTMLButtonElement, Props>(
|
|
|
174
131
|
colorTheme="greyLighter"
|
|
175
132
|
size="small"
|
|
176
133
|
onClick={() => {
|
|
177
|
-
|
|
178
|
-
innerRef.current?.focus();
|
|
179
|
-
}
|
|
134
|
+
innerRef.current?.focus();
|
|
180
135
|
onToggleTree(!showTree);
|
|
181
136
|
}}>
|
|
182
137
|
{showTree ? <ChevronUp /> : <ChevronDown />}
|
|
@@ -37,6 +37,9 @@ const OpenButton = styled.span<{ isOpen: boolean }>`
|
|
|
37
37
|
`;
|
|
38
38
|
|
|
39
39
|
const StyledName = styled.span`
|
|
40
|
+
white-space: nowrap;
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
text-overflow: ellipsis;
|
|
40
43
|
grid-column-start: 2;
|
|
41
44
|
text-align: left;
|
|
42
45
|
`;
|
|
@@ -63,7 +66,6 @@ const FolderName = styled(Button, { shouldForwardProp })<FolderNameProps>`
|
|
|
63
66
|
color: ${({ isCreatingFolder, focused }) =>
|
|
64
67
|
isCreatingFolder && focused ? colors.brand.primary : colors.text.primary};
|
|
65
68
|
transition: ${animations.durations.superFast};
|
|
66
|
-
line-height: 1;
|
|
67
69
|
word-break: break-word;
|
|
68
70
|
|
|
69
71
|
&:hover {
|
|
@@ -93,7 +95,6 @@ const FolderNameLink = styled(SafeLink, { shouldForwardProp })<FolderNameProps>`
|
|
|
93
95
|
font-weight: ${({ selected }) => selected && fonts.weight.semibold};
|
|
94
96
|
font-size: ${fonts.sizes('16px')};
|
|
95
97
|
transition: ${animations.durations.superFast};
|
|
96
|
-
line-height: 1;
|
|
97
98
|
word-break: break-word;
|
|
98
99
|
&:hover,
|
|
99
100
|
&:focus {
|
|
@@ -230,7 +231,7 @@ const FolderItem = ({
|
|
|
230
231
|
selected={selected}
|
|
231
232
|
disabled={loading}
|
|
232
233
|
onFocus={(e) => {
|
|
233
|
-
setFocusedFolder(focusedFolder || folder
|
|
234
|
+
setFocusedFolder(focusedFolder || folder);
|
|
234
235
|
}}
|
|
235
236
|
onClick={handleClickFolder}
|
|
236
237
|
isCreatingFolder={isCreatingFolder}>
|
|
@@ -241,7 +242,7 @@ const FolderItem = ({
|
|
|
241
242
|
isOpen={isOpen}
|
|
242
243
|
onClick={(e) => {
|
|
243
244
|
e.stopPropagation();
|
|
244
|
-
setFocusedFolder(folder
|
|
245
|
+
setFocusedFolder(folder);
|
|
245
246
|
if (isOpen) {
|
|
246
247
|
onCloseFolder(id);
|
|
247
248
|
} else {
|
|
@@ -10,8 +10,7 @@ import React, { ReactNode } from 'react';
|
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
11
|
import { animations } from '@ndla/core';
|
|
12
12
|
import FolderItem from './FolderItem';
|
|
13
|
-
import
|
|
14
|
-
import { CommonFolderItemsProps, FolderType, TreeStructureType } from './types';
|
|
13
|
+
import { CommonFolderItemsProps, FolderType, NewFolderInputFunc, OnCreatedFunc, TreeStructureType } from './types';
|
|
15
14
|
import NavigationLink from './NavigationLink';
|
|
16
15
|
import { treestructureId } from './helperFunctions';
|
|
17
16
|
|
|
@@ -42,10 +41,11 @@ export interface FolderItemsProps extends CommonFolderItemsProps {
|
|
|
42
41
|
folders: FolderType[];
|
|
43
42
|
newFolderParentId: string | undefined;
|
|
44
43
|
onCancelNewFolder: () => void;
|
|
45
|
-
onSaveNewFolder: (name: string, parentId: string) => void;
|
|
46
44
|
openFolders: string[];
|
|
47
45
|
parentFolder?: FolderType;
|
|
48
46
|
children?: ReactNode;
|
|
47
|
+
onCreate: OnCreatedFunc;
|
|
48
|
+
newFolderInput?: NewFolderInputFunc;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const FolderItems = ({
|
|
@@ -54,11 +54,12 @@ const FolderItems = ({
|
|
|
54
54
|
loading,
|
|
55
55
|
newFolderParentId,
|
|
56
56
|
onCancelNewFolder,
|
|
57
|
-
onSaveNewFolder,
|
|
58
57
|
openFolders,
|
|
59
58
|
type,
|
|
60
59
|
parentFolder,
|
|
61
60
|
children,
|
|
61
|
+
onCreate,
|
|
62
|
+
newFolderInput,
|
|
62
63
|
...rest
|
|
63
64
|
}: FolderItemsProps) => (
|
|
64
65
|
<StyledUL
|
|
@@ -101,20 +102,12 @@ const FolderItems = ({
|
|
|
101
102
|
type={type}
|
|
102
103
|
newFolderParentId={newFolderParentId}
|
|
103
104
|
onCancelNewFolder={onCancelNewFolder}
|
|
104
|
-
onSaveNewFolder={onSaveNewFolder}
|
|
105
105
|
openFolders={openFolders}
|
|
106
|
+
newFolderInput={newFolderInput}
|
|
107
|
+
onCreate={onCreate}
|
|
106
108
|
{...rest}>
|
|
107
109
|
{newFolderParentId === id && (
|
|
108
|
-
<li role="none">
|
|
109
|
-
<FolderNameInput
|
|
110
|
-
loading={loading}
|
|
111
|
-
level={level}
|
|
112
|
-
onCancelNewFolder={onCancelNewFolder}
|
|
113
|
-
onSaveNewFolder={onSaveNewFolder}
|
|
114
|
-
parentId={newFolderParentId}
|
|
115
|
-
type={type}
|
|
116
|
-
/>
|
|
117
|
-
</li>
|
|
110
|
+
<li role="none">{newFolderInput?.({ parentId: id, onClose: onCancelNewFolder, onCreate })}</li>
|
|
118
111
|
)}
|
|
119
112
|
</FolderItems>
|
|
120
113
|
)}
|