@ndla/ui 13.2.2 → 15.1.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/Article/Article.js +22 -3
- package/es/Article/ArticleFavoritesButton.js +38 -0
- package/es/Article/index.js +2 -1
- package/es/Breadcrumb/ActionBreadcrumb.js +57 -0
- package/es/Breadcrumb/index.js +1 -0
- package/es/Footer/FooterAuth.js +15 -22
- package/es/InfoBlock/InfoBlock.js +55 -0
- package/es/InfoBlock/index.js +1 -0
- package/es/LearningPaths/LearningPathMenu.js +3 -4
- package/es/Masthead/MastheadAuthModal.js +2 -2
- package/es/MyNdla/Navigation/VerticalNavigation.js +51 -0
- package/es/MyNdla/Navigation/index.js +2 -0
- package/es/MyNdla/Resource/Folder.js +86 -0
- package/es/MyNdla/Resource/FolderInput.js +96 -0
- package/{lib/MyNdla/ResourceDash/ResourcesView.d.ts → es/MyNdla/Resource/index.js} +3 -3
- package/es/MyNdla/index.js +4 -4
- package/es/Resource/BlockResource.js +73 -0
- package/es/Resource/ListResource.js +66 -0
- package/es/Resource/index.js +10 -0
- package/es/Resource/resourceComponents.js +97 -0
- package/es/ResourceGroup/ResourceGroup.js +7 -5
- package/es/ResourceGroup/ResourceItem.js +28 -30
- package/es/ResourceGroup/ResourceList.js +18 -6
- package/es/Search/ActiveFilters.js +6 -7
- package/es/Search/ContentTypeResult.js +6 -8
- package/es/SearchTypeResult/ActiveFilters.js +6 -10
- package/es/SnackBar/SnackBar.js +117 -0
- package/es/SnackBar/index.js +9 -0
- package/es/TagSelector/SuggestionInput.js +240 -0
- package/es/TagSelector/Suggestions.js +93 -0
- package/es/TagSelector/TagSelector.js +137 -0
- package/es/TagSelector/index.js +9 -0
- package/es/TopicIntroductionList/TopicIntroduction.js +2 -4
- package/es/TopicIntroductionList/TopicShortcutItem.js +1 -3
- package/es/TreeStructure/FolderItem.js +130 -0
- package/es/TreeStructure/FolderItems.js +123 -0
- package/es/TreeStructure/FolderNameInput.js +112 -0
- package/es/TreeStructure/TreeStructure.js +254 -0
- package/es/TreeStructure/TreeStructure.types.js +0 -0
- package/es/TreeStructure/TreeStructureWrapper.js +13 -0
- package/es/TreeStructure/helperFunctions.js +92 -0
- package/es/TreeStructure/index.js +9 -0
- package/es/TreeStructure/keyboardNavigation/keyboardNavigation.js +182 -0
- package/es/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +0 -0
- package/es/User/AuthModal.js +15 -24
- package/es/User/UserInfo.js +70 -0
- package/es/User/apiTypes.js +0 -0
- package/es/User/index.js +2 -0
- package/es/User/parseUserObject.js +102 -0
- package/es/all.css +90 -0
- package/es/index.js +9 -3
- package/es/locale/messages-en.js +71 -4
- package/es/locale/messages-nb.js +70 -3
- package/es/locale/messages-nn.js +70 -3
- package/es/locale/messages-se.js +70 -3
- package/es/locale/messages-sma.js +70 -3
- package/lib/Article/Article.d.ts +3 -1
- package/lib/Article/Article.js +43 -23
- package/lib/Article/ArticleFavoritesButton.d.ts +15 -0
- package/lib/Article/ArticleFavoritesButton.js +56 -0
- package/lib/Article/index.d.ts +2 -1
- package/lib/Article/index.js +8 -0
- package/lib/Breadcrumb/ActionBreadcrumb.d.ts +16 -0
- package/lib/Breadcrumb/ActionBreadcrumb.js +72 -0
- package/lib/Breadcrumb/index.d.ts +1 -0
- package/lib/Breadcrumb/index.js +8 -0
- package/lib/Footer/FooterAuth.d.ts +1 -1
- package/lib/Footer/FooterAuth.js +17 -17
- package/lib/InfoBlock/InfoBlock.d.ts +8 -0
- package/lib/InfoBlock/InfoBlock.js +58 -0
- package/lib/InfoBlock/index.d.ts +1 -0
- package/lib/InfoBlock/index.js +13 -0
- package/lib/LearningPaths/LearningPathMenu.js +3 -4
- package/lib/Masthead/MastheadAuthModal.d.ts +3 -3
- package/lib/Masthead/MastheadAuthModal.js +3 -3
- package/lib/MyNdla/Navigation/VerticalNavigation.d.ts +10 -0
- package/lib/MyNdla/Navigation/VerticalNavigation.js +61 -0
- package/lib/MyNdla/Navigation/index.d.ts +2 -0
- package/lib/MyNdla/Navigation/index.js +15 -0
- package/lib/MyNdla/Resource/Folder.d.ts +20 -0
- package/lib/MyNdla/Resource/Folder.js +100 -0
- package/lib/MyNdla/Resource/FolderInput.d.ts +15 -0
- package/lib/MyNdla/Resource/FolderInput.js +116 -0
- package/lib/MyNdla/Resource/index.d.ts +10 -0
- package/lib/MyNdla/Resource/index.js +23 -0
- package/lib/MyNdla/index.d.ts +4 -4
- package/lib/MyNdla/index.js +13 -7
- package/lib/Resource/BlockResource.d.ts +20 -0
- package/lib/Resource/BlockResource.js +84 -0
- package/lib/Resource/ListResource.d.ts +20 -0
- package/lib/Resource/ListResource.js +78 -0
- package/lib/Resource/index.d.ts +11 -0
- package/lib/Resource/index.js +29 -0
- package/lib/Resource/resourceComponents.d.ts +24 -0
- package/lib/Resource/resourceComponents.js +106 -0
- package/lib/ResourceGroup/ResourceGroup.d.ts +2 -1
- package/lib/ResourceGroup/ResourceGroup.js +7 -5
- package/lib/ResourceGroup/ResourceItem.d.ts +5 -1
- package/lib/ResourceGroup/ResourceItem.js +29 -30
- package/lib/ResourceGroup/ResourceList.d.ts +3 -1
- package/lib/ResourceGroup/ResourceList.js +18 -6
- package/lib/Search/ActiveFilters.js +6 -7
- package/lib/Search/ContentTypeResult.js +6 -8
- package/lib/SearchTypeResult/ActiveFilters.js +6 -10
- package/lib/SnackBar/SnackBar.d.ts +23 -0
- package/lib/SnackBar/SnackBar.js +127 -0
- package/lib/SnackBar/index.d.ts +10 -0
- package/lib/SnackBar/index.js +15 -0
- package/lib/TagSelector/SuggestionInput.d.ts +19 -0
- package/lib/TagSelector/SuggestionInput.js +255 -0
- package/lib/TagSelector/Suggestions.d.ts +12 -0
- package/lib/TagSelector/Suggestions.js +96 -0
- package/lib/TagSelector/TagSelector.d.ts +16 -0
- package/lib/TagSelector/TagSelector.js +150 -0
- package/lib/TagSelector/index.d.ts +10 -0
- package/lib/TagSelector/index.js +19 -0
- package/lib/TopicIntroductionList/TopicIntroduction.js +2 -4
- package/lib/TopicIntroductionList/TopicShortcutItem.js +1 -3
- package/lib/TreeStructure/FolderItem.d.ts +27 -0
- package/lib/TreeStructure/FolderItem.js +140 -0
- package/lib/TreeStructure/FolderItems.d.ts +11 -0
- package/lib/TreeStructure/FolderItems.js +130 -0
- package/lib/TreeStructure/FolderNameInput.d.ts +15 -0
- package/lib/TreeStructure/FolderNameInput.js +125 -0
- package/lib/TreeStructure/TreeStructure.d.ts +12 -0
- package/lib/TreeStructure/TreeStructure.js +273 -0
- package/lib/TreeStructure/TreeStructure.types.d.ts +63 -0
- package/lib/TreeStructure/TreeStructure.types.js +1 -0
- package/lib/TreeStructure/TreeStructureWrapper.d.ts +12 -0
- package/lib/TreeStructure/TreeStructureWrapper.js +24 -0
- package/lib/TreeStructure/helperFunctions.d.ts +5 -0
- package/lib/TreeStructure/helperFunctions.js +103 -0
- package/lib/TreeStructure/index.d.ts +10 -0
- package/lib/TreeStructure/index.js +15 -0
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.d.ts +11 -0
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.js +186 -0
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.d.ts +26 -0
- package/lib/TreeStructure/keyboardNavigation/keyboardNavigation.types.js +1 -0
- package/lib/User/AuthModal.d.ts +3 -3
- package/lib/User/AuthModal.js +16 -23
- package/lib/User/UserInfo.d.ts +13 -0
- package/lib/User/UserInfo.js +84 -0
- package/lib/User/apiTypes.d.ts +61 -0
- package/lib/User/apiTypes.js +1 -0
- package/lib/User/index.d.ts +4 -0
- package/lib/User/index.js +8 -0
- package/lib/User/parseUserObject.d.ts +32 -0
- package/lib/User/parseUserObject.js +105 -0
- package/lib/all.css +90 -0
- package/lib/index.d.ts +14 -3
- package/lib/index.js +83 -10
- package/lib/locale/messages-en.d.ts +67 -0
- package/lib/locale/messages-en.js +71 -4
- package/lib/locale/messages-nb.d.ts +67 -0
- package/lib/locale/messages-nb.js +70 -3
- package/lib/locale/messages-nn.d.ts +67 -0
- package/lib/locale/messages-nn.js +70 -3
- package/lib/locale/messages-se.d.ts +67 -0
- package/lib/locale/messages-se.js +70 -3
- package/lib/locale/messages-sma.d.ts +67 -0
- package/lib/locale/messages-sma.js +70 -3
- package/lib/types.d.ts +1 -1
- package/package.json +11 -11
- package/src/Article/Article.tsx +31 -0
- package/src/Article/ArticleFavoritesButton.tsx +40 -0
- package/src/Article/index.ts +2 -0
- package/src/Breadcrumb/ActionBreadcrumb.tsx +68 -0
- package/src/Breadcrumb/index.ts +2 -0
- package/src/Footer/FooterAuth.tsx +7 -9
- package/src/InfoBlock/InfoBlock.tsx +61 -0
- package/src/InfoBlock/index.ts +1 -0
- package/src/LearningPaths/LearningPathMenu.tsx +1 -1
- package/src/Masthead/MastheadAuthModal.tsx +4 -5
- package/src/MyNdla/Navigation/VerticalNavigation.tsx +93 -0
- package/src/MyNdla/Navigation/index.ts +2 -0
- package/src/MyNdla/Resource/Folder.tsx +145 -0
- package/src/MyNdla/Resource/FolderInput.tsx +104 -0
- package/src/MyNdla/Resource/index.ts +11 -0
- package/src/MyNdla/index.ts +4 -5
- package/src/Resource/BlockResource.tsx +101 -0
- package/src/Resource/ListResource.tsx +111 -0
- package/src/Resource/index.ts +12 -0
- package/src/Resource/resourceComponents.tsx +143 -0
- package/src/ResourceGroup/ResourceGroup.tsx +3 -0
- package/src/ResourceGroup/ResourceItem.tsx +20 -3
- package/src/ResourceGroup/ResourceList.tsx +16 -3
- package/src/Search/ActiveFilters.jsx +0 -1
- package/src/Search/ContentTypeResult.tsx +8 -9
- package/src/SearchTypeResult/ActiveFilters.tsx +1 -3
- package/src/SnackBar/SnackBar.tsx +183 -0
- package/src/SnackBar/index.ts +13 -0
- package/src/TagSelector/SuggestionInput.tsx +230 -0
- package/src/TagSelector/Suggestions.tsx +125 -0
- package/src/TagSelector/TagSelector.tsx +111 -0
- package/src/TagSelector/index.ts +13 -0
- package/src/TopicIntroductionList/TopicIntroduction.tsx +2 -2
- package/src/TopicIntroductionList/TopicShortcutItem.tsx +1 -5
- package/src/TreeStructure/FolderItem.tsx +160 -0
- package/src/TreeStructure/FolderItems.tsx +109 -0
- package/src/TreeStructure/FolderNameInput.tsx +109 -0
- package/src/TreeStructure/TreeStructure.tsx +184 -0
- package/src/TreeStructure/TreeStructure.types.ts +69 -0
- package/src/TreeStructure/TreeStructureWrapper.tsx +34 -0
- package/src/TreeStructure/helperFunctions.ts +52 -0
- package/src/TreeStructure/index.ts +11 -0
- package/src/TreeStructure/keyboardNavigation/keyboardNavigation.ts +161 -0
- package/src/TreeStructure/keyboardNavigation/keyboardNavigation.types.ts +28 -0
- package/src/User/AuthModal.tsx +5 -26
- package/src/User/UserInfo.tsx +80 -0
- package/src/User/__tests__/parseUserObject-test.ts +315 -0
- package/src/User/apiTypes.ts +74 -0
- package/src/User/index.ts +4 -0
- package/src/User/parseUserObject.ts +83 -0
- package/src/all.scss +2 -0
- package/src/index.ts +15 -4
- package/src/locale/messages-en.ts +65 -3
- package/src/locale/messages-nb.ts +64 -2
- package/src/locale/messages-nn.ts +64 -2
- package/src/locale/messages-se.ts +64 -2
- package/src/locale/messages-sma.ts +64 -2
- package/src/types.ts +1 -1
- package/es/MyNdla/ResourceDash/Breadcrumbs.js +0 -22
- package/es/MyNdla/ResourceDash/ResourceElement.js +0 -27
- package/es/MyNdla/ResourceDash/ResourcesView.js +0 -43
- package/es/MyNdla/ResourceDash/index.js +0 -4
- package/lib/MyNdla/ResourceDash/Breadcrumbs.d.ts +0 -15
- package/lib/MyNdla/ResourceDash/Breadcrumbs.js +0 -35
- package/lib/MyNdla/ResourceDash/ResourceElement.d.ts +0 -18
- package/lib/MyNdla/ResourceDash/ResourceElement.js +0 -38
- package/lib/MyNdla/ResourceDash/ResourcesView.js +0 -57
- package/lib/MyNdla/ResourceDash/index.d.ts +0 -4
- package/lib/MyNdla/ResourceDash/index.js +0 -31
- package/src/MyNdla/ResourceDash/Breadcrumbs.tsx +0 -31
- package/src/MyNdla/ResourceDash/ResourceElement.tsx +0 -50
- package/src/MyNdla/ResourceDash/ResourcesView.tsx +0 -42
- package/src/MyNdla/ResourceDash/index.ts +0 -5
|
@@ -0,0 +1,111 @@
|
|
|
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 styled from '@emotion/styled';
|
|
10
|
+
import React, { ReactNode } from 'react';
|
|
11
|
+
import SafeLink from '@ndla/safelink';
|
|
12
|
+
import { fonts, spacing, colors } from '@ndla/core';
|
|
13
|
+
import Image from '../Image';
|
|
14
|
+
import { CompressTagsLength, ResourceImageProps, ResourceTitle, Row, TopicList } from './resourceComponents';
|
|
15
|
+
|
|
16
|
+
const ResourceDescription = styled.p`
|
|
17
|
+
line-clamp: 2;
|
|
18
|
+
line-height: 1em;
|
|
19
|
+
height: 3.1em;
|
|
20
|
+
margin: 0;
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
${fonts.sizes(16)};
|
|
23
|
+
text-overflow: ellipsis;
|
|
24
|
+
// Unfortunate css needed for multi-line text overflow ellipsis.
|
|
25
|
+
display: -webkit-box;
|
|
26
|
+
-webkit-line-clamp: 2;
|
|
27
|
+
line-clamp: 2;
|
|
28
|
+
-webkit-box-orient: vertical;
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const ResourceWrapper = styled(SafeLink)`
|
|
32
|
+
display: grid;
|
|
33
|
+
grid-template-columns: auto 1fr;
|
|
34
|
+
text-decoration: none;
|
|
35
|
+
box-shadow: none;
|
|
36
|
+
padding: ${spacing.small};
|
|
37
|
+
border: 1px solid ${colors.brand.light};
|
|
38
|
+
border-radius: 2px;
|
|
39
|
+
color: ${colors.brand.greyDark};
|
|
40
|
+
gap: ${spacing.small};
|
|
41
|
+
&:hover {
|
|
42
|
+
box-shadow: 1px 1px 6px 2px rgba(9, 55, 101, 0.08);
|
|
43
|
+
transition-duration: 0.2s;
|
|
44
|
+
${ResourceTitle} {
|
|
45
|
+
color: ${colors.brand.primary};
|
|
46
|
+
text-decoration: underline;
|
|
47
|
+
}
|
|
48
|
+
a {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const ResourceInfoWrapper = styled.div`
|
|
56
|
+
flex: 1;
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
max-width: 100%;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
interface StyledImageProps {
|
|
64
|
+
imageSize: 'normal' | 'compact';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const StyledImage = styled(Image)<StyledImageProps>`
|
|
68
|
+
display: flex;
|
|
69
|
+
border-radius: 2px;
|
|
70
|
+
object-fit: cover;
|
|
71
|
+
width: ${(p) => (p.imageSize === 'normal' ? '136px' : '56px')};
|
|
72
|
+
min-width: ${(p) => (p.imageSize === 'normal' ? '136px' : '56px')};
|
|
73
|
+
height: ${(p) => (p.imageSize === 'normal' ? '96px' : '40px')};
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
export interface ListResourceProps {
|
|
77
|
+
link: string;
|
|
78
|
+
title: string;
|
|
79
|
+
resourceImage: ResourceImageProps;
|
|
80
|
+
topics: string[];
|
|
81
|
+
tags?: string[];
|
|
82
|
+
description?: string;
|
|
83
|
+
actionMenu?: ReactNode;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const ListResource = ({ link, title, tags, resourceImage, topics, description, actionMenu }: ListResourceProps) => {
|
|
87
|
+
const showDescription = description !== undefined;
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<ResourceWrapper to={link}>
|
|
91
|
+
<StyledImage alt={resourceImage.alt} src={resourceImage.src} imageSize={showDescription ? 'normal' : 'compact'} />
|
|
92
|
+
<ResourceInfoWrapper>
|
|
93
|
+
<Row>
|
|
94
|
+
<ResourceTitle>{title}</ResourceTitle>
|
|
95
|
+
{tags && CompressTagsLength(tags)}
|
|
96
|
+
{actionMenu}
|
|
97
|
+
</Row>
|
|
98
|
+
<Row>
|
|
99
|
+
<TopicList topics={topics} />
|
|
100
|
+
</Row>
|
|
101
|
+
{showDescription && (
|
|
102
|
+
<Row>
|
|
103
|
+
<ResourceDescription>{description}</ResourceDescription>
|
|
104
|
+
</Row>
|
|
105
|
+
)}
|
|
106
|
+
</ResourceInfoWrapper>
|
|
107
|
+
</ResourceWrapper>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default ListResource;
|
|
@@ -0,0 +1,12 @@
|
|
|
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 { ListResourceProps } from './ListResource';
|
|
10
|
+
export type { ListResourceProps };
|
|
11
|
+
export { default as ListResource } from './ListResource';
|
|
12
|
+
export { default as BlockResource } from './BlockResource';
|
|
@@ -0,0 +1,143 @@
|
|
|
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 from 'react';
|
|
10
|
+
import styled from '@emotion/styled';
|
|
11
|
+
import { fonts, colors, spacing } from '@ndla/core';
|
|
12
|
+
|
|
13
|
+
import { MenuButton } from '@ndla/button';
|
|
14
|
+
|
|
15
|
+
export interface ResourceImageProps {
|
|
16
|
+
alt: string;
|
|
17
|
+
src: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const ResourceTitle = styled.h2`
|
|
21
|
+
${fonts.sizes(18)};
|
|
22
|
+
min-width: 50px;
|
|
23
|
+
font-weight: ${fonts.weight.bold};
|
|
24
|
+
margin: 0;
|
|
25
|
+
flex: 1;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
text-overflow: ellipsis;
|
|
28
|
+
// Unfortunate css needed for multi-line text overflow ellipsis.
|
|
29
|
+
line-height: 1;
|
|
30
|
+
display: -webkit-box;
|
|
31
|
+
-webkit-line-clamp: 1;
|
|
32
|
+
line-clamp: 1;
|
|
33
|
+
-webkit-box-orient: vertical;
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
const StyledTagList = styled.ul`
|
|
37
|
+
list-style: none;
|
|
38
|
+
display: flex;
|
|
39
|
+
margin: 0;
|
|
40
|
+
padding: 0;
|
|
41
|
+
gap: ${spacing.xsmall};
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
const StyledTagListElement = styled.li`
|
|
46
|
+
color: ${colors.brand.grey};
|
|
47
|
+
margin: 0;
|
|
48
|
+
${fonts.sizes(14)};
|
|
49
|
+
::before {
|
|
50
|
+
content: '#';
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
const StyledTopicList = styled.ul`
|
|
55
|
+
list-style: none;
|
|
56
|
+
display: flex;
|
|
57
|
+
margin: 0;
|
|
58
|
+
padding: 0;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
const StyledTopicListElement = styled.li`
|
|
63
|
+
${fonts.sizes(12)};
|
|
64
|
+
margin: 0;
|
|
65
|
+
line-height: 1.5;
|
|
66
|
+
padding: 0;
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const StyledTopicDivider = styled.span`
|
|
70
|
+
margin: 0;
|
|
71
|
+
padding: 0 ${spacing.xxsmall};
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
export const Row = styled.div`
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
gap: ${spacing.xsmall};
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
const TagCounterWrapper = styled.p`
|
|
81
|
+
color: ${colors.brand.primary};
|
|
82
|
+
box-shadow: none;
|
|
83
|
+
margin: 0;
|
|
84
|
+
font-weight: ${fonts.weight.semibold};
|
|
85
|
+
${fonts.sizes(16)}
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
interface TagListProps {
|
|
89
|
+
tags?: string[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const TagList = ({ tags }: TagListProps) => {
|
|
93
|
+
if (!tags) return null;
|
|
94
|
+
return (
|
|
95
|
+
<StyledTagList>
|
|
96
|
+
{tags.map((tag, i) => (
|
|
97
|
+
<StyledTagListElement key={`tag-${i}`}>{tag}</StyledTagListElement>
|
|
98
|
+
))}
|
|
99
|
+
</StyledTagList>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const CompressTagsLength = (tags: string[]) => {
|
|
104
|
+
const tagCounter = tags?.length - 3;
|
|
105
|
+
const slicedTags = tags.slice(0, 3);
|
|
106
|
+
const remainingTags = tags.slice(3, tags.length).map((tag) => {
|
|
107
|
+
return {
|
|
108
|
+
text: '#' + tag,
|
|
109
|
+
onClick: () => {},
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<>
|
|
115
|
+
<TagList tags={slicedTags} />
|
|
116
|
+
{remainingTags.length > 0 && (
|
|
117
|
+
<MenuButton hideMenuIcon={true} menuItems={remainingTags}>
|
|
118
|
+
<TagCounterWrapper>+ {tagCounter}</TagCounterWrapper>
|
|
119
|
+
</MenuButton>
|
|
120
|
+
)}
|
|
121
|
+
</>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
interface TopicListProps {
|
|
126
|
+
topics?: string[];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const TopicList = ({ topics }: TopicListProps) => {
|
|
130
|
+
if (!topics) return null;
|
|
131
|
+
return (
|
|
132
|
+
<StyledTopicList>
|
|
133
|
+
{topics.map((topic, i) => (
|
|
134
|
+
<StyledTopicListElement key={topic}>
|
|
135
|
+
<>
|
|
136
|
+
{topic}
|
|
137
|
+
{i !== topics.length - 1 && <StyledTopicDivider>•</StyledTopicDivider>}
|
|
138
|
+
</>
|
|
139
|
+
</StyledTopicListElement>
|
|
140
|
+
))}
|
|
141
|
+
</StyledTopicList>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
@@ -36,6 +36,7 @@ const StyledHeading = styled.h1`
|
|
|
36
36
|
type Props = {
|
|
37
37
|
invertedStyle?: boolean;
|
|
38
38
|
toggleAdditionalResources: () => void;
|
|
39
|
+
onToggleAddToFavorites: (id: string | number, add: string) => void;
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
const ResourceGroup = ({
|
|
@@ -45,6 +46,7 @@ const ResourceGroup = ({
|
|
|
45
46
|
toggleAdditionalResources,
|
|
46
47
|
contentType,
|
|
47
48
|
invertedStyle,
|
|
49
|
+
onToggleAddToFavorites,
|
|
48
50
|
}: Props & ResourceListProps) => (
|
|
49
51
|
<Wrapper>
|
|
50
52
|
{title && (
|
|
@@ -59,6 +61,7 @@ const ResourceGroup = ({
|
|
|
59
61
|
showAdditionalResources={showAdditionalResources}
|
|
60
62
|
contentType={contentType}
|
|
61
63
|
resources={resources}
|
|
64
|
+
onToggleAddToFavorites={onToggleAddToFavorites}
|
|
62
65
|
/>
|
|
63
66
|
) : null}
|
|
64
67
|
</Wrapper>
|
|
@@ -15,6 +15,7 @@ import SafeLink from '@ndla/safelink';
|
|
|
15
15
|
import { Additional, Core, HumanMaleBoard } from '@ndla/icons/common';
|
|
16
16
|
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
17
17
|
import Tooltip from '@ndla/tooltip';
|
|
18
|
+
import { ArticleFavoritesButton } from '../Article';
|
|
18
19
|
import { Resource } from '../types';
|
|
19
20
|
import ContentTypeBadge from '../ContentTypeBadge';
|
|
20
21
|
import * as contentTypes from '../model/ContentType';
|
|
@@ -208,6 +209,7 @@ const IconWrapper = styled.div`
|
|
|
208
209
|
const TypeWrapper = styled.div`
|
|
209
210
|
display: flex;
|
|
210
211
|
align-items: center;
|
|
212
|
+
gap: ${spacing.xsmall};
|
|
211
213
|
`;
|
|
212
214
|
|
|
213
215
|
const ContentTypeName = styled.span`
|
|
@@ -219,15 +221,20 @@ const ContentTypeName = styled.span`
|
|
|
219
221
|
`;
|
|
220
222
|
|
|
221
223
|
type Props = {
|
|
224
|
+
id: string;
|
|
222
225
|
showContentTypeDescription?: boolean;
|
|
223
226
|
contentTypeName?: string;
|
|
224
227
|
contentTypeDescription?: string;
|
|
225
228
|
extraBottomMargin?: boolean;
|
|
226
229
|
showAdditionalResources?: boolean;
|
|
227
230
|
access?: 'teacher';
|
|
231
|
+
isFavorite?: boolean;
|
|
232
|
+
onToggleAddToFavorites: (id: string, add: boolean) => void;
|
|
233
|
+
hideAddToFavoriteButton?: boolean;
|
|
228
234
|
};
|
|
229
235
|
|
|
230
236
|
const ResourceItem = ({
|
|
237
|
+
id,
|
|
231
238
|
contentTypeName,
|
|
232
239
|
contentTypeDescription,
|
|
233
240
|
name,
|
|
@@ -238,6 +245,9 @@ const ResourceItem = ({
|
|
|
238
245
|
extraBottomMargin,
|
|
239
246
|
showAdditionalResources,
|
|
240
247
|
access,
|
|
248
|
+
onToggleAddToFavorites,
|
|
249
|
+
isFavorite,
|
|
250
|
+
hideAddToFavoriteButton,
|
|
241
251
|
}: Props & Resource) => {
|
|
242
252
|
const { t } = useTranslation();
|
|
243
253
|
const hidden = additional ? !showAdditionalResources : false;
|
|
@@ -273,24 +283,31 @@ const ResourceItem = ({
|
|
|
273
283
|
<TypeWrapper>
|
|
274
284
|
{contentTypeName && <ContentTypeName>{contentTypeName}</ContentTypeName>}
|
|
275
285
|
{access && access === 'teacher' && (
|
|
276
|
-
<Tooltip tooltip={t('article.access.onlyTeacher')}
|
|
286
|
+
<Tooltip tooltip={t('article.access.onlyTeacher')}>
|
|
277
287
|
<HumanMaleBoard className="c-icon--20 u-margin-left-tiny c-topic-resource__list__additional-icons" />
|
|
278
288
|
</Tooltip>
|
|
279
289
|
)}
|
|
280
290
|
{showAdditionalResources && contentTypeDescription && (
|
|
281
291
|
<>
|
|
282
292
|
{additional && (
|
|
283
|
-
<Tooltip tooltip={contentTypeDescription}
|
|
293
|
+
<Tooltip tooltip={contentTypeDescription}>
|
|
284
294
|
<Additional className="c-icon--20 u-margin-left-tiny c-topic-resource__list__additional-icons" />
|
|
285
295
|
</Tooltip>
|
|
286
296
|
)}
|
|
287
297
|
{!additional && (
|
|
288
|
-
<Tooltip tooltip={contentTypeDescription}
|
|
298
|
+
<Tooltip tooltip={contentTypeDescription}>
|
|
289
299
|
<Core className="c-icon--20 u-margin-left-tiny c-topic-resource__list__additional-icons" />
|
|
290
300
|
</Tooltip>
|
|
291
301
|
)}
|
|
292
302
|
</>
|
|
293
303
|
)}
|
|
304
|
+
{!hideAddToFavoriteButton && (
|
|
305
|
+
<ArticleFavoritesButton
|
|
306
|
+
isFavorite={isFavorite}
|
|
307
|
+
articleId={id}
|
|
308
|
+
onToggleAddToFavorites={() => onToggleAddToFavorites(id, true)}
|
|
309
|
+
/>
|
|
310
|
+
)}
|
|
294
311
|
</TypeWrapper>
|
|
295
312
|
</ListElement>
|
|
296
313
|
);
|
|
@@ -48,9 +48,19 @@ export type ResourceListProps = {
|
|
|
48
48
|
contentType?: string;
|
|
49
49
|
title?: string;
|
|
50
50
|
showAdditionalResources?: boolean;
|
|
51
|
+
onToggleAddToFavorites: (id: string, add: boolean) => void;
|
|
52
|
+
hideAddToFavoriteButton?: boolean;
|
|
51
53
|
};
|
|
52
54
|
|
|
53
|
-
const ResourceList = ({
|
|
55
|
+
const ResourceList = ({
|
|
56
|
+
resources,
|
|
57
|
+
onClick,
|
|
58
|
+
onToggleAddToFavorites,
|
|
59
|
+
contentType,
|
|
60
|
+
title,
|
|
61
|
+
showAdditionalResources,
|
|
62
|
+
hideAddToFavoriteButton,
|
|
63
|
+
}: ResourceListProps) => {
|
|
54
64
|
const { t } = useTranslation();
|
|
55
65
|
const renderAdditionalResourceTrigger =
|
|
56
66
|
!showAdditionalResources &&
|
|
@@ -60,11 +70,14 @@ const ResourceList = ({ resources, onClick, contentType, title, showAdditionalRe
|
|
|
60
70
|
return (
|
|
61
71
|
<div>
|
|
62
72
|
<StyledResourceList showAdditionalResources={showAdditionalResources}>
|
|
63
|
-
{resources.map((resource) => (
|
|
73
|
+
{resources.map(({ id, ...resource }) => (
|
|
64
74
|
<ResourceItem
|
|
65
|
-
|
|
75
|
+
id={id}
|
|
76
|
+
key={id}
|
|
66
77
|
contentType={contentType}
|
|
67
78
|
showAdditionalResources={showAdditionalResources}
|
|
79
|
+
hideAddToFavoriteButton={hideAddToFavoriteButton}
|
|
80
|
+
onToggleAddToFavorites={onToggleAddToFavorites}
|
|
68
81
|
{...resource}
|
|
69
82
|
contentTypeDescription={
|
|
70
83
|
resource.additional ? t('resource.tooltipAdditionalTopic') : t('resource.tooltipCoreTopic')
|
|
@@ -85,7 +85,6 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
|
|
|
85
85
|
<StyledActiveFilterWrapper key={filterKey}>
|
|
86
86
|
{filterLength > 1 ? (
|
|
87
87
|
<Tooltip
|
|
88
|
-
align="top"
|
|
89
88
|
tooltip={t('searchPage.searchFilterMessages.removeFilter', {
|
|
90
89
|
filterName: filter.title,
|
|
91
90
|
})}>
|
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef, ReactElement } from 'react';
|
|
2
1
|
import Button from '@ndla/button';
|
|
3
|
-
import
|
|
4
|
-
import { Additional, ChevronUp, ChevronDown } from '@ndla/icons/common';
|
|
2
|
+
import { Additional, ChevronDown, ChevronUp } from '@ndla/icons/common';
|
|
5
3
|
import SafeLink from '@ndla/safelink';
|
|
4
|
+
import Tooltip from '@ndla/tooltip';
|
|
5
|
+
import React, { ReactElement, useEffect, useRef, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import ContentTypeBadge from '../ContentTypeBadge';
|
|
8
8
|
import { ContentTypeResultType, Resource } from '../types';
|
|
9
9
|
import {
|
|
10
10
|
highlightStyle,
|
|
11
|
+
noWidthhighlightStyle,
|
|
11
12
|
showAllButtonStyle,
|
|
12
|
-
tooltipStyle,
|
|
13
|
-
StyledNoHit,
|
|
14
|
-
StyledWrapper,
|
|
15
13
|
StyledHeader,
|
|
16
|
-
StyledListItem,
|
|
17
14
|
StyledList,
|
|
15
|
+
StyledListItem,
|
|
16
|
+
StyledNoHit,
|
|
18
17
|
StyledTag,
|
|
19
|
-
|
|
18
|
+
StyledWrapper,
|
|
20
19
|
} from './ContentTypeResultStyles';
|
|
21
20
|
import { isPathToHighlight } from './IsPathToHighlight';
|
|
22
21
|
|
|
23
22
|
const renderAdditionalIcon = (label: string, isAdditional?: boolean): ReactElement | null => {
|
|
24
23
|
if (isAdditional && label) {
|
|
25
24
|
return (
|
|
26
|
-
<Tooltip tooltip={label}
|
|
25
|
+
<Tooltip tooltip={label}>
|
|
27
26
|
<Additional className="c-icon--20" />
|
|
28
27
|
</Tooltip>
|
|
29
28
|
);
|
|
@@ -120,8 +120,6 @@ const ActiveFilters = ({
|
|
|
120
120
|
<StyledActiveFilterWrapper key={filterKey}>
|
|
121
121
|
{filterLength > 1 ? (
|
|
122
122
|
<Tooltip
|
|
123
|
-
delay={2000}
|
|
124
|
-
align="bottom"
|
|
125
123
|
tooltip={t('searchPage.searchFilterMessages.removeFilter', {
|
|
126
124
|
filterName: filter.title,
|
|
127
125
|
})}>
|
|
@@ -139,7 +137,7 @@ const ActiveFilters = ({
|
|
|
139
137
|
{filterItems}
|
|
140
138
|
{filterLength > showFilterCount && (
|
|
141
139
|
<StyledActiveFilterWrapper>
|
|
142
|
-
<Tooltip
|
|
140
|
+
<Tooltip tooltip={t('searchPage.searchFilterMessages.noValuesButtonText')}>
|
|
143
141
|
<Button
|
|
144
142
|
aria-label={t('searchPage.searchFilterMessages.additionalSubjectFilters', {
|
|
145
143
|
count: filterLength - showFilterCount + 1,
|
|
@@ -0,0 +1,183 @@
|
|
|
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, { ReactElement, useRef, useEffect, useState } from 'react';
|
|
10
|
+
import styled from '@emotion/styled';
|
|
11
|
+
import Button, { IconButton } from '@ndla/button';
|
|
12
|
+
import { spacing, spacingUnit, shadows, misc, fonts, colors, mq, breakpoints } from '@ndla/core';
|
|
13
|
+
import { Cross } from '@ndla/icons/action';
|
|
14
|
+
import { useTranslation } from 'react-i18next';
|
|
15
|
+
|
|
16
|
+
const StyledActionButton = styled(Button)`
|
|
17
|
+
color: ${colors.white};
|
|
18
|
+
padding: ${spacing.xsmall} ${spacing.small};
|
|
19
|
+
box-shadow: none;
|
|
20
|
+
&:focus,
|
|
21
|
+
&:hover {
|
|
22
|
+
color: ${colors.brand.greyLightest};
|
|
23
|
+
background: ${colors.brand.greyDark};
|
|
24
|
+
&:after {
|
|
25
|
+
opacity: 0;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
&:after {
|
|
29
|
+
content: '';
|
|
30
|
+
display: flex;
|
|
31
|
+
height: 1px;
|
|
32
|
+
width: 100%;
|
|
33
|
+
background: ${colors.white};
|
|
34
|
+
transform: translateY(-2px);
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const StyledIconButton = styled(IconButton)`
|
|
39
|
+
svg {
|
|
40
|
+
color: ${colors.brand.greyMedium};
|
|
41
|
+
}
|
|
42
|
+
&:hover,
|
|
43
|
+
&:focus {
|
|
44
|
+
background: ${colors.brand.greyDark};
|
|
45
|
+
svg {
|
|
46
|
+
color: ${colors.brand.greyLightest};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
const WrapperForButtons = styled.div`
|
|
52
|
+
display: flex;
|
|
53
|
+
${mq.range({ from: breakpoints.tablet })} {
|
|
54
|
+
gap: ${spacing.xxsmall};
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
|
|
58
|
+
interface StyledProps {
|
|
59
|
+
expired?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const Wrapper = styled.div`
|
|
63
|
+
position: fixed;
|
|
64
|
+
z-index: 99999;
|
|
65
|
+
bottom: ${spacing.small};
|
|
66
|
+
left: ${spacing.small};
|
|
67
|
+
right: ${spacing.small};
|
|
68
|
+
display: flex;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
const StyledNotification = styled.div<StyledProps>`
|
|
73
|
+
max-width: 960px;
|
|
74
|
+
${fonts.sizes(18, 1.25)};
|
|
75
|
+
background: ${colors.text.primary};
|
|
76
|
+
color: ${colors.white};
|
|
77
|
+
box-shadow: ${shadows.levitate1};
|
|
78
|
+
padding: ${spacing.small};
|
|
79
|
+
padding-right: ${spacing.xsmall};
|
|
80
|
+
gap: ${spacing.medium};
|
|
81
|
+
${mq.range({ from: breakpoints.tablet })} {
|
|
82
|
+
gap: ${spacing.large};
|
|
83
|
+
padding: ${spacing.small} ${spacing.normal} ${spacing.small} ${spacing.medium};
|
|
84
|
+
}
|
|
85
|
+
${mq.range({ from: breakpoints.desktop })} {
|
|
86
|
+
gap: ${spacingUnit * 3};
|
|
87
|
+
}
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
> div:first-of-type {
|
|
91
|
+
flex-grow: 1;
|
|
92
|
+
display: flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
}
|
|
96
|
+
&:empty {
|
|
97
|
+
display: none;
|
|
98
|
+
}
|
|
99
|
+
border-radius: ${misc.borderRadius};
|
|
100
|
+
@keyframes snackbar-animations-in {
|
|
101
|
+
0% {
|
|
102
|
+
opacity: 0;
|
|
103
|
+
transform: translateY(${spacing.medium});
|
|
104
|
+
}
|
|
105
|
+
100% {
|
|
106
|
+
opacity: 1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
@keyframes snackbar-animations-out {
|
|
110
|
+
0% {
|
|
111
|
+
opacity: 1;
|
|
112
|
+
}
|
|
113
|
+
100% {
|
|
114
|
+
opacity: 0;
|
|
115
|
+
transform: translateY(${spacing.medium});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
animation: ${(props) => (props.expired ? 'snackbar-animations-out' : 'snackbar-animations-in')} 200ms ease-in-out;
|
|
119
|
+
animation-fill-mode: forwards;
|
|
120
|
+
${fonts.sizes('18px')};
|
|
121
|
+
font-family: ${fonts.sans};
|
|
122
|
+
`;
|
|
123
|
+
|
|
124
|
+
export interface SnackBarItem {
|
|
125
|
+
children?: ReactElement;
|
|
126
|
+
snackbarItemId?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface SnackBarProps extends SnackBarItem {
|
|
130
|
+
id: string;
|
|
131
|
+
onKill?: (id: string | undefined) => void;
|
|
132
|
+
actionButtons?: {
|
|
133
|
+
text: string;
|
|
134
|
+
onClick: () => void;
|
|
135
|
+
ariaLabel: string;
|
|
136
|
+
}[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const SnackBar = ({ onKill, children, snackbarItemId, id, actionButtons }: SnackBarProps) => {
|
|
140
|
+
const { t } = useTranslation();
|
|
141
|
+
const [expired, setExpired] = useState(false);
|
|
142
|
+
const timeoutId = useRef<null | ReturnType<typeof setTimeout>>();
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
if (timeoutId.current) {
|
|
145
|
+
timeoutId && clearTimeout(timeoutId.current);
|
|
146
|
+
}
|
|
147
|
+
timeoutId.current = setTimeout(() => {
|
|
148
|
+
setExpired(true);
|
|
149
|
+
}, 8000);
|
|
150
|
+
|
|
151
|
+
return () => {
|
|
152
|
+
timeoutId.current && clearTimeout(timeoutId.current);
|
|
153
|
+
};
|
|
154
|
+
}, [snackbarItemId, timeoutId]);
|
|
155
|
+
return (
|
|
156
|
+
<Wrapper>
|
|
157
|
+
<StyledNotification
|
|
158
|
+
id={id}
|
|
159
|
+
aria-live="polite"
|
|
160
|
+
expired={expired || !children}
|
|
161
|
+
onAnimationEnd={() => expired && onKill && onKill(snackbarItemId)}>
|
|
162
|
+
{children && (
|
|
163
|
+
<>
|
|
164
|
+
<div>{children}</div>
|
|
165
|
+
<WrapperForButtons>
|
|
166
|
+
{actionButtons &&
|
|
167
|
+
actionButtons.map(({ onClick, text, ariaLabel }) => (
|
|
168
|
+
<StyledActionButton key={text} link aria-label={ariaLabel} onClick={onClick}>
|
|
169
|
+
{text}
|
|
170
|
+
</StyledActionButton>
|
|
171
|
+
))}
|
|
172
|
+
<StyledIconButton aria-label={t('snackbar.close')} size="xsmall" outline onClick={() => setExpired(true)}>
|
|
173
|
+
<Cross />
|
|
174
|
+
</StyledIconButton>
|
|
175
|
+
</WrapperForButtons>
|
|
176
|
+
</>
|
|
177
|
+
)}
|
|
178
|
+
</StyledNotification>
|
|
179
|
+
</Wrapper>
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export default SnackBar;
|
|
@@ -0,0 +1,13 @@
|
|
|
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 SnackBar from './SnackBar';
|
|
10
|
+
|
|
11
|
+
export type { SnackBarItem } from './SnackBar';
|
|
12
|
+
|
|
13
|
+
export { SnackBar };
|