@ndla/ui 4.3.2 → 5.0.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/README.md +11 -11
- package/es/Article/Article.js +3 -7
- package/es/Article/ArticleByline.js +4 -4
- package/es/Article/ArticleNotions.js +37 -92
- package/es/ContentTypeBadge/ContentTypeBadge.js +10 -1
- package/es/FactBox/FactBox.js +36 -11
- package/es/Filter/FilterButtons.js +18 -17
- package/es/Filter/FilterCarousel.js +198 -0
- package/es/Masthead/Masthead.js +24 -2
- package/es/Notion/ConceptNotion.js +57 -0
- package/es/Notion/FigureNotion.js +82 -0
- package/es/Notion/Notion.js +122 -48
- package/es/Notion/NotionImage.js +47 -0
- package/es/Notion/NotionVisualElement.js +38 -0
- package/es/Notion/index.js +2 -1
- package/es/SearchTypeResult/ActiveFilterContent.js +17 -2
- package/es/SearchTypeResult/ActiveFilters.js +64 -50
- package/es/SearchTypeResult/PopupFilter.js +28 -125
- package/es/SearchTypeResult/ResultNavigation.js +41 -14
- package/es/SearchTypeResult/SearchFieldHeader.js +20 -41
- package/es/SearchTypeResult/SearchFilterContent.js +61 -0
- package/es/SearchTypeResult/SearchHeader.js +51 -28
- package/es/SearchTypeResult/SearchItem.js +64 -190
- package/es/SearchTypeResult/SearchItemList.js +132 -0
- package/es/SearchTypeResult/SearchItems.js +17 -13
- package/es/SearchTypeResult/SearchNotionItem.js +13 -13
- package/es/SearchTypeResult/SearchNotionsResult.js +16 -21
- package/es/SearchTypeResult/SearchTypeHeader.js +43 -26
- package/es/SearchTypeResult/SearchTypeResult.js +7 -5
- package/es/SearchTypeResult/SearchViewType.js +93 -0
- package/es/SearchTypeResult/components/ItemContexts.js +125 -0
- package/es/SearchTypeResult/components/ItemResourceHeader.js +87 -0
- package/es/SearchTypeResult/components/ItemTopicHeader.js +56 -0
- package/es/SearchTypeResult/components/SubjectFilters.js +177 -0
- package/es/SearchTypeResult/index.js +2 -1
- package/es/all.css +1 -1
- package/es/index.js +3 -2
- package/es/locale/messages-en.js +20 -5
- package/es/locale/messages-nb.js +21 -6
- package/es/locale/messages-nn.js +21 -6
- package/es/model/ContentType.js +2 -1
- package/es/shapes.js +1 -1
- package/lib/Article/Article.d.ts +4 -5
- package/lib/Article/Article.js +3 -7
- package/lib/Article/ArticleByline.js +4 -4
- package/lib/Article/ArticleNotions.d.ts +3 -8
- package/lib/Article/ArticleNotions.js +41 -90
- package/lib/ContentTypeBadge/ContentTypeBadge.d.ts +1 -0
- package/lib/ContentTypeBadge/ContentTypeBadge.js +14 -2
- package/lib/FactBox/FactBox.js +41 -8
- package/lib/Filter/FilterButtons.d.ts +3 -10
- package/lib/Filter/FilterButtons.js +19 -17
- package/lib/Filter/FilterCarousel.d.ts +13 -0
- package/lib/Filter/FilterCarousel.js +207 -0
- package/lib/Masthead/Masthead.js +30 -2
- package/lib/Notion/ConceptNotion.d.ts +25 -0
- package/lib/Notion/ConceptNotion.js +79 -0
- package/lib/Notion/FigureNotion.d.ts +23 -0
- package/lib/Notion/FigureNotion.js +97 -0
- package/lib/Notion/Notion.d.ts +24 -11
- package/lib/Notion/Notion.js +120 -48
- package/lib/Notion/NotionImage.d.ts +15 -0
- package/lib/Notion/NotionImage.js +63 -0
- package/lib/Notion/NotionVisualElement.d.ts +22 -0
- package/lib/Notion/NotionVisualElement.js +51 -0
- package/lib/Notion/index.d.ts +1 -0
- package/lib/Notion/index.js +8 -0
- package/lib/SearchTypeResult/ActiveFilterContent.js +16 -9
- package/lib/SearchTypeResult/ActiveFilters.d.ts +2 -1
- package/lib/SearchTypeResult/ActiveFilters.js +65 -50
- package/lib/SearchTypeResult/PopupFilter.d.ts +13 -19
- package/lib/SearchTypeResult/PopupFilter.js +27 -123
- package/lib/SearchTypeResult/ResultNavigation.d.ts +2 -2
- package/lib/SearchTypeResult/ResultNavigation.js +38 -14
- package/lib/SearchTypeResult/SearchFieldHeader.d.ts +3 -8
- package/lib/SearchTypeResult/SearchFieldHeader.js +18 -39
- package/lib/SearchTypeResult/SearchFilterContent.d.ts +16 -0
- package/lib/SearchTypeResult/SearchFilterContent.js +67 -0
- package/lib/SearchTypeResult/SearchHeader.d.ts +3 -7
- package/lib/SearchTypeResult/SearchHeader.js +59 -30
- package/lib/SearchTypeResult/SearchItem.d.ts +8 -12
- package/lib/SearchTypeResult/SearchItem.js +64 -187
- package/lib/SearchTypeResult/SearchItemList.d.ts +10 -0
- package/lib/SearchTypeResult/SearchItemList.js +139 -0
- package/lib/SearchTypeResult/SearchItems.d.ts +4 -3
- package/lib/SearchTypeResult/SearchItems.js +18 -13
- package/lib/SearchTypeResult/SearchNotionItem.js +13 -13
- package/lib/SearchTypeResult/SearchNotionsResult.d.ts +2 -4
- package/lib/SearchTypeResult/SearchNotionsResult.js +23 -23
- package/lib/SearchTypeResult/SearchTypeHeader.d.ts +2 -2
- package/lib/SearchTypeResult/SearchTypeHeader.js +40 -25
- package/lib/SearchTypeResult/SearchTypeResult.d.ts +7 -6
- package/lib/SearchTypeResult/SearchTypeResult.js +7 -5
- package/lib/SearchTypeResult/SearchViewType.d.ts +13 -0
- package/lib/SearchTypeResult/SearchViewType.js +99 -0
- package/lib/SearchTypeResult/components/ItemContexts.d.ts +19 -0
- package/lib/SearchTypeResult/components/ItemContexts.js +134 -0
- package/lib/SearchTypeResult/components/ItemResourceHeader.d.ts +16 -0
- package/lib/SearchTypeResult/components/ItemResourceHeader.js +98 -0
- package/lib/SearchTypeResult/components/ItemTopicHeader.d.ts +17 -0
- package/lib/SearchTypeResult/components/ItemTopicHeader.js +67 -0
- package/lib/SearchTypeResult/components/SubjectFilters.d.ts +32 -0
- package/lib/SearchTypeResult/components/SubjectFilters.js +192 -0
- package/lib/SearchTypeResult/index.d.ts +2 -1
- package/lib/SearchTypeResult/index.js +8 -0
- package/lib/all.css +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +24 -1
- package/lib/locale/messages-en.d.ts +16 -1
- package/lib/locale/messages-en.js +20 -5
- package/lib/locale/messages-nb.d.ts +15 -0
- package/lib/locale/messages-nb.js +21 -6
- package/lib/locale/messages-nn.d.ts +16 -1
- package/lib/locale/messages-nn.js +21 -6
- package/lib/model/ContentType.d.ts +1 -0
- package/lib/model/ContentType.js +4 -2
- package/lib/shapes.js +1 -1
- package/lib/types.d.ts +1 -0
- package/package.json +14 -14
- package/src/Article/Article.tsx +8 -15
- package/src/Article/ArticleByline.tsx +1 -1
- package/src/Article/ArticleNotions.tsx +13 -33
- package/src/ContentTypeBadge/ContentTypeBadge.tsx +8 -0
- package/src/ContentTypeBadge/component.content-type-badge.scss +5 -0
- package/src/FactBox/FactBox.tsx +22 -15
- package/src/Figure/component.figure.scss +1 -1
- package/src/Filter/FilterButtons.tsx +14 -15
- package/src/Filter/FilterCarousel.tsx +166 -0
- package/src/Masthead/Masthead.tsx +42 -18
- package/src/Notion/ConceptNotion.tsx +80 -0
- package/src/Notion/FigureNotion.tsx +86 -0
- package/src/Notion/Notion.tsx +205 -75
- package/src/Notion/NotionImage.tsx +51 -0
- package/src/Notion/NotionVisualElement.tsx +50 -0
- package/src/Notion/index.ts +1 -0
- package/src/SearchTypeResult/ActiveFilterContent.tsx +7 -2
- package/src/SearchTypeResult/ActiveFilters.tsx +72 -38
- package/src/SearchTypeResult/PopupFilter.tsx +73 -146
- package/src/SearchTypeResult/ResultNavigation.tsx +54 -16
- package/src/SearchTypeResult/SearchFieldHeader.tsx +15 -40
- package/src/SearchTypeResult/SearchFilterContent.tsx +63 -0
- package/src/SearchTypeResult/SearchHeader.tsx +31 -31
- package/src/SearchTypeResult/SearchItem.tsx +145 -233
- package/src/SearchTypeResult/SearchItemList.tsx +167 -0
- package/src/SearchTypeResult/SearchItems.tsx +26 -19
- package/src/SearchTypeResult/SearchNotionItem.tsx +5 -12
- package/src/SearchTypeResult/SearchNotionsResult.tsx +29 -22
- package/src/SearchTypeResult/SearchTypeHeader.tsx +51 -33
- package/src/SearchTypeResult/SearchTypeResult.tsx +13 -12
- package/src/SearchTypeResult/SearchViewType.tsx +109 -0
- package/src/SearchTypeResult/components/ItemContexts.tsx +138 -0
- package/src/SearchTypeResult/components/ItemResourceHeader.tsx +133 -0
- package/src/SearchTypeResult/components/ItemTopicHeader.tsx +95 -0
- package/src/SearchTypeResult/components/SubjectFilters.tsx +152 -0
- package/src/SearchTypeResult/index.ts +9 -1
- package/src/index.ts +3 -0
- package/src/locale/messages-en.ts +18 -3
- package/src/locale/messages-nb.ts +19 -4
- package/src/locale/messages-nn.ts +19 -4
- package/src/model/ContentType.ts +1 -0
- package/src/shapes.js +1 -0
- package/src/types.ts +1 -0
|
@@ -0,0 +1,86 @@
|
|
|
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
|
+
import Button from '@ndla/button';
|
|
9
|
+
import { getGroupedContributorDescriptionList, getLicenseByAbbreviation } from '@ndla/licenses';
|
|
10
|
+
import React, { ReactNode } from 'react';
|
|
11
|
+
import { useTranslation } from 'react-i18next';
|
|
12
|
+
import { Figure, FigureCaption, FigureLicenseDialog } from '..';
|
|
13
|
+
import { Copyright } from '../types';
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
resizeIframe?: boolean;
|
|
17
|
+
figureId: string;
|
|
18
|
+
children: ReactNode | ((params: { typeClass: string }) => ReactNode);
|
|
19
|
+
id: string;
|
|
20
|
+
title: string;
|
|
21
|
+
copyright?: Partial<Copyright>;
|
|
22
|
+
licenseString: string;
|
|
23
|
+
type: 'video' | 'h5p' | 'image' | 'concept';
|
|
24
|
+
hideFigCaption?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const FigureNotion = ({
|
|
28
|
+
resizeIframe,
|
|
29
|
+
figureId,
|
|
30
|
+
children,
|
|
31
|
+
id,
|
|
32
|
+
copyright,
|
|
33
|
+
licenseString,
|
|
34
|
+
title,
|
|
35
|
+
type,
|
|
36
|
+
hideFigCaption,
|
|
37
|
+
}: Props) => {
|
|
38
|
+
const { t, i18n } = useTranslation();
|
|
39
|
+
const license = getLicenseByAbbreviation(licenseString, i18n.language);
|
|
40
|
+
const { creators, processors, rightsholders } = copyright ?? {};
|
|
41
|
+
const contributors = getGroupedContributorDescriptionList(
|
|
42
|
+
{
|
|
43
|
+
creators: creators ?? [],
|
|
44
|
+
processors: processors ?? [],
|
|
45
|
+
rightsholders: rightsholders ?? [],
|
|
46
|
+
},
|
|
47
|
+
i18n.language,
|
|
48
|
+
).map((i) => ({ name: i.description, type: i.label }));
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Figure resizeIframe={resizeIframe} id={figureId} type={'full-column'}>
|
|
52
|
+
{({ typeClass }) => (
|
|
53
|
+
<>
|
|
54
|
+
{typeof children === 'function' ? children({ typeClass }) : children}
|
|
55
|
+
<FigureCaption
|
|
56
|
+
hideFigcaption={hideFigCaption}
|
|
57
|
+
figureId={figureId}
|
|
58
|
+
id={id}
|
|
59
|
+
caption={title}
|
|
60
|
+
reuseLabel={t(`${type}.reuse`)}
|
|
61
|
+
authors={contributors}
|
|
62
|
+
licenseRights={license.rights}>
|
|
63
|
+
<FigureLicenseDialog
|
|
64
|
+
id={id}
|
|
65
|
+
authors={contributors}
|
|
66
|
+
locale={i18n.language}
|
|
67
|
+
title={title}
|
|
68
|
+
origin={copyright?.origin}
|
|
69
|
+
license={license}
|
|
70
|
+
messages={{
|
|
71
|
+
close: t('close'),
|
|
72
|
+
rulesForUse: t('license.concept.rules'),
|
|
73
|
+
source: t('source'),
|
|
74
|
+
learnAboutLicenses: t('license.learnMore'),
|
|
75
|
+
title: t('title'),
|
|
76
|
+
}}>
|
|
77
|
+
{type === 'image' && <Button outline>{t('license.copyTitle')}</Button>}
|
|
78
|
+
</FigureLicenseDialog>
|
|
79
|
+
</FigureCaption>
|
|
80
|
+
</>
|
|
81
|
+
)}
|
|
82
|
+
</Figure>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default FigureNotion;
|
package/src/Notion/Notion.tsx
CHANGED
|
@@ -1,118 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2021-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
|
+
|
|
1
9
|
import styled from '@emotion/styled';
|
|
2
10
|
import { useTranslation } from 'react-i18next';
|
|
3
11
|
import HTMLReactParser from 'html-react-parser';
|
|
4
|
-
import React, {
|
|
12
|
+
import React, { Fragment, ReactNode } from 'react';
|
|
13
|
+
import { keyframes } from '@emotion/core';
|
|
5
14
|
import Button from '@ndla/button';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
const NotionContainer = styled.div`
|
|
12
|
-
border-bottom: 1px solid ${colors.brand.greyLighter};
|
|
13
|
-
margin-bottom: 3.5rem;
|
|
14
|
-
`;
|
|
15
|
+
import { animations, breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
16
|
+
import { CursorClick } from '@ndla/icons/action';
|
|
17
|
+
import { Play, ArrowCollapse } from '@ndla/icons/common';
|
|
18
|
+
import { ImageCrop, ImageFocalPoint, makeSrcQueryString } from '../Image';
|
|
15
19
|
|
|
16
|
-
const
|
|
17
|
-
display: flex;
|
|
18
|
-
flex-wrap: wrap;
|
|
19
|
-
margin: 0 0 1.5rem;
|
|
20
|
-
font-size: 0.875rem;
|
|
20
|
+
const NotionContainer = styled.div``;
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
const ContentWrapper = styled.div`
|
|
23
|
+
${mq.range({ until: breakpoints.tabletWide })} {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column-reverse;
|
|
26
|
+
}
|
|
27
|
+
.c-figure {
|
|
23
28
|
margin: 0;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
position: relative !important;
|
|
30
|
+
left: 0 !important;
|
|
31
|
+
width: 25% !important;
|
|
32
|
+
padding: 0 0 0 20px;
|
|
33
|
+
float: right;
|
|
34
|
+
&.expanded {
|
|
35
|
+
width: 100% !important;
|
|
36
|
+
padding: 0;
|
|
37
|
+
margin-bottom: ${spacing.normal};
|
|
38
|
+
}
|
|
39
|
+
${mq.range({ until: breakpoints.tabletWide })} {
|
|
40
|
+
width: 100% !important;
|
|
41
|
+
padding: 0;
|
|
27
42
|
}
|
|
28
43
|
}
|
|
29
44
|
`;
|
|
45
|
+
const TextWrapper = styled.div`
|
|
46
|
+
width: 75%;
|
|
47
|
+
${mq.range({ until: breakpoints.tabletWide })} {
|
|
48
|
+
width: 100%;
|
|
49
|
+
}
|
|
50
|
+
font-family: ${fonts.serif};
|
|
51
|
+
${fonts.sizes('18px', '28px')};
|
|
52
|
+
${ContentWrapper} .c-figure.expanded + & {
|
|
53
|
+
width: 100%;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
30
56
|
|
|
31
|
-
const
|
|
32
|
-
|
|
57
|
+
const ImageElement = styled.img``;
|
|
58
|
+
|
|
59
|
+
const fadeInMediaKeyframe = keyframes`
|
|
60
|
+
0% {
|
|
61
|
+
opacity: 0;
|
|
62
|
+
height: auto;
|
|
63
|
+
}
|
|
64
|
+
100% {
|
|
65
|
+
opacity: 1;
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
const fadeOutMediaKeyframe = keyframes`
|
|
69
|
+
0% {
|
|
70
|
+
opacity: 1;
|
|
71
|
+
height: auto;
|
|
72
|
+
}
|
|
73
|
+
100% {
|
|
74
|
+
opacity: 0;
|
|
75
|
+
height:0;
|
|
76
|
+
overflow: hidden;
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
const ImageWrapper = styled.div`
|
|
81
|
+
float: right;
|
|
82
|
+
width: 25%;
|
|
83
|
+
padding-left: ${spacing.normal};
|
|
84
|
+
position: relative;
|
|
85
|
+
|
|
86
|
+
${mq.range({ until: breakpoints.tabletWide })} {
|
|
87
|
+
width: 100%;
|
|
88
|
+
padding-left: 0;
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
const ExpandVisualElementButton = styled(Button)`
|
|
93
|
+
position: absolute;
|
|
94
|
+
right: 8px;
|
|
95
|
+
bottom: 8px;
|
|
96
|
+
transition: all ${animations.durations.normal};
|
|
97
|
+
&,
|
|
98
|
+
&:focus,
|
|
99
|
+
&:active {
|
|
100
|
+
background-color: rgba(255, 255, 255, 0.65);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
color: ${colors.brand.primary};
|
|
104
|
+
border-radius: 50%;
|
|
105
|
+
border: 0;
|
|
106
|
+
width: 40px;
|
|
107
|
+
height: 40px;
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
justify-content: center;
|
|
33
110
|
align-items: center;
|
|
34
|
-
font-size: 0.875rem;
|
|
35
|
-
margin-bottom: 1rem;
|
|
36
111
|
|
|
37
|
-
|
|
38
|
-
|
|
112
|
+
svg {
|
|
113
|
+
transition: transform ${animations.durations.normal} ease-out;
|
|
114
|
+
}
|
|
115
|
+
${ContentWrapper}:hover & {
|
|
116
|
+
background-color: #fff;
|
|
117
|
+
svg {
|
|
118
|
+
transform: scale(1.2);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const ExpandIcon = styled.span`
|
|
124
|
+
${ExpandVisualElementButton}.expanded & {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
const CollapseIcon = styled.span`
|
|
129
|
+
display: none;
|
|
130
|
+
${ExpandVisualElementButton}.expanded & {
|
|
131
|
+
display: inline-block;
|
|
39
132
|
}
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
const ClearWrapper = styled.div`
|
|
136
|
+
clear: both;
|
|
137
|
+
`;
|
|
40
138
|
|
|
41
|
-
|
|
42
|
-
|
|
139
|
+
const MediaContainer = styled.div`
|
|
140
|
+
opacity: 0;
|
|
141
|
+
height: 0;
|
|
142
|
+
overflow: hidden;
|
|
143
|
+
&.expanded {
|
|
144
|
+
animation-name: ${fadeInMediaKeyframe};
|
|
145
|
+
animation-duration: 2.8s;
|
|
146
|
+
opacity: 1;
|
|
147
|
+
height: auto;
|
|
148
|
+
}
|
|
149
|
+
&.fadeOut {
|
|
150
|
+
animation-name: ${fadeOutMediaKeyframe};
|
|
151
|
+
animation-duration: 2.8s;
|
|
43
152
|
}
|
|
44
153
|
`;
|
|
45
154
|
|
|
46
|
-
const
|
|
155
|
+
const LabelsContainer = styled.div`
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
47
158
|
${fonts.sizes('14px', '24px')};
|
|
48
|
-
font-
|
|
49
|
-
|
|
50
|
-
background-color: ${colors.brand.greyLightest};
|
|
51
|
-
vertical-align: center;
|
|
159
|
+
font-family: ${fonts.sans};
|
|
160
|
+
margin: ${spacing.small} 0;
|
|
52
161
|
`;
|
|
53
162
|
|
|
163
|
+
type VisualElementProps = {
|
|
164
|
+
type: 'video' | 'other';
|
|
165
|
+
element: ReactNode;
|
|
166
|
+
metaImage?: {
|
|
167
|
+
url: string;
|
|
168
|
+
alt: string;
|
|
169
|
+
crop?: ImageCrop;
|
|
170
|
+
focalPoint?: ImageFocalPoint;
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
|
|
54
174
|
export type NotionProps = {
|
|
55
|
-
|
|
56
|
-
id: string;
|
|
175
|
+
id: string | number;
|
|
57
176
|
labels?: string[];
|
|
58
|
-
license?: string;
|
|
59
|
-
locale?: Locale;
|
|
60
|
-
media?: ReactNode;
|
|
61
|
-
onReferenceClick?: MouseEventHandler<HTMLButtonElement>;
|
|
62
177
|
renderMarkdown?: (text: string) => string;
|
|
63
178
|
text: ReactNode;
|
|
64
179
|
title: string;
|
|
180
|
+
visualElement?: VisualElementProps;
|
|
181
|
+
imageElement?: ReactNode;
|
|
182
|
+
children?: ReactNode;
|
|
65
183
|
};
|
|
66
184
|
|
|
67
185
|
const Notion = ({
|
|
68
|
-
authors = [],
|
|
69
186
|
id,
|
|
70
187
|
labels = [],
|
|
71
|
-
license,
|
|
72
|
-
locale,
|
|
73
|
-
media,
|
|
74
|
-
onReferenceClick,
|
|
75
188
|
renderMarkdown,
|
|
76
189
|
text,
|
|
77
190
|
title,
|
|
191
|
+
visualElement,
|
|
192
|
+
imageElement,
|
|
193
|
+
children,
|
|
78
194
|
}: NotionProps) => {
|
|
79
195
|
const { t } = useTranslation();
|
|
196
|
+
|
|
80
197
|
return (
|
|
81
198
|
<NotionContainer>
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
199
|
+
{visualElement && <MediaContainer id={`notion-media-${id}`}>{visualElement.element}</MediaContainer>}
|
|
200
|
+
<ContentWrapper>
|
|
201
|
+
{imageElement}
|
|
202
|
+
{visualElement && visualElement.metaImage && (
|
|
203
|
+
<ImageWrapper>
|
|
204
|
+
<ImageElement
|
|
205
|
+
src={`${visualElement.metaImage.url}?${makeSrcQueryString(
|
|
206
|
+
400,
|
|
207
|
+
visualElement.metaImage.crop,
|
|
208
|
+
visualElement.metaImage.focalPoint,
|
|
209
|
+
)}`}
|
|
210
|
+
alt={visualElement.metaImage.alt}
|
|
211
|
+
/>
|
|
212
|
+
<ExpandVisualElementButton
|
|
213
|
+
stripped
|
|
214
|
+
data-notion-expand-media={true}
|
|
215
|
+
data-notion-media-id={`notion-media-${id}`}>
|
|
216
|
+
<ExpandIcon>
|
|
217
|
+
{visualElement.type === 'video' && <Play style={{ width: '24px', height: '24px' }} />}
|
|
218
|
+
{visualElement.type === 'other' && <CursorClick style={{ width: '24px', height: '24px' }} />}
|
|
219
|
+
</ExpandIcon>
|
|
220
|
+
<CollapseIcon>
|
|
221
|
+
<ArrowCollapse style={{ width: '24px', height: '24px' }} />
|
|
222
|
+
</CollapseIcon>
|
|
223
|
+
</ExpandVisualElementButton>
|
|
224
|
+
</ImageWrapper>
|
|
85
225
|
)}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
{onReferenceClick && (
|
|
102
|
-
<Button link onClick={onReferenceClick}>
|
|
103
|
-
{t('article.citeNotion')}
|
|
104
|
-
</Button>
|
|
226
|
+
<TextWrapper>
|
|
227
|
+
{HTMLReactParser(
|
|
228
|
+
renderMarkdown ? renderMarkdown(`**${title}** \u2013 ${text}`) : `<b>${title}</b> \u2013 ${text}`,
|
|
229
|
+
)}
|
|
230
|
+
{!!labels.length && (
|
|
231
|
+
<LabelsContainer>
|
|
232
|
+
{t('searchPage.resultType.notionLabels')}
|
|
233
|
+
{labels.map((label, i) => (
|
|
234
|
+
<Fragment key={`notion-${id}-label-${i + 1}`}>
|
|
235
|
+
{' '}
|
|
236
|
+
{label}
|
|
237
|
+
{i < labels?.length - 1 && <> •</>}
|
|
238
|
+
</Fragment>
|
|
239
|
+
))}
|
|
240
|
+
</LabelsContainer>
|
|
105
241
|
)}
|
|
106
|
-
</
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<p>{t('searchPage.resultType.notionLabels')}</p>
|
|
111
|
-
{labels.map((label, i) => (
|
|
112
|
-
<Label key={`notion-${id}-label-${i + 1}`}>{label}</Label>
|
|
113
|
-
))}
|
|
114
|
-
</LabelsContainer>
|
|
115
|
-
)}
|
|
242
|
+
</TextWrapper>
|
|
243
|
+
<ClearWrapper />
|
|
244
|
+
</ContentWrapper>
|
|
245
|
+
{children}
|
|
116
246
|
</NotionContainer>
|
|
117
247
|
);
|
|
118
248
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
import React from 'react';
|
|
9
|
+
import { useTranslation } from 'react-i18next';
|
|
10
|
+
import { Image, FigureExpandButton } from '..';
|
|
11
|
+
import { Copyright } from '../types';
|
|
12
|
+
import FigureNotion from './FigureNotion';
|
|
13
|
+
interface Props {
|
|
14
|
+
id: string;
|
|
15
|
+
src: string;
|
|
16
|
+
alt: string;
|
|
17
|
+
imageCopyright?: Partial<Copyright>;
|
|
18
|
+
}
|
|
19
|
+
export const NotionImage = ({ id, src, alt, imageCopyright }: Props) => {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
|
|
22
|
+
const imageId = `image-${id}`;
|
|
23
|
+
const imageFigureId = `image-figure-${id}`;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<FigureNotion
|
|
27
|
+
hideFigCaption
|
|
28
|
+
figureId={imageFigureId}
|
|
29
|
+
id={imageId}
|
|
30
|
+
title={alt}
|
|
31
|
+
copyright={imageCopyright}
|
|
32
|
+
licenseString={imageCopyright?.license?.license ?? ''}
|
|
33
|
+
type={'image'}>
|
|
34
|
+
{({ typeClass }) => (
|
|
35
|
+
<Image
|
|
36
|
+
alt={alt}
|
|
37
|
+
src={src}
|
|
38
|
+
expandButton={
|
|
39
|
+
<FigureExpandButton
|
|
40
|
+
typeClass={typeClass}
|
|
41
|
+
messages={{
|
|
42
|
+
zoomImageButtonLabel: t('license.images.itemImage.zoomImageButtonLabel'),
|
|
43
|
+
zoomOutImageButtonLabel: t('license.image.itemImage.zoomOutImageButtonLabel'),
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
}
|
|
47
|
+
/>
|
|
48
|
+
)}
|
|
49
|
+
</FigureNotion>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
import React from 'react';
|
|
9
|
+
import { Copyright } from '../types';
|
|
10
|
+
import FigureNotion from './FigureNotion';
|
|
11
|
+
|
|
12
|
+
export type NotionVisualElementType = {
|
|
13
|
+
resource?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
copyright?: Partial<Copyright>;
|
|
17
|
+
image?: {
|
|
18
|
+
src: string;
|
|
19
|
+
alt?: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
interface Props {
|
|
24
|
+
visualElement: NotionVisualElementType;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const supportedEmbedTypes = ['brightcove', 'h5p'];
|
|
28
|
+
const NotionVisualElement = ({ visualElement }: Props) => {
|
|
29
|
+
const id = '1';
|
|
30
|
+
const figureId = 'figure-1';
|
|
31
|
+
if (!visualElement.resource || !supportedEmbedTypes.includes(visualElement.resource)) {
|
|
32
|
+
return <p>Embed type is not supported!</p>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const type = visualElement.resource === 'brightcove' ? 'video' : 'h5p';
|
|
36
|
+
return (
|
|
37
|
+
<FigureNotion
|
|
38
|
+
resizeIframe
|
|
39
|
+
id={id}
|
|
40
|
+
figureId={figureId}
|
|
41
|
+
title={visualElement.title ?? ''}
|
|
42
|
+
copyright={visualElement.copyright}
|
|
43
|
+
licenseString={visualElement.copyright?.license?.license ?? ''}
|
|
44
|
+
type={type}>
|
|
45
|
+
<iframe title={visualElement.title} src={visualElement.url} />
|
|
46
|
+
</FigureNotion>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default NotionVisualElement;
|
package/src/Notion/index.ts
CHANGED
|
@@ -19,6 +19,11 @@ export const StyledActiveFilterTitle = styled.span`
|
|
|
19
19
|
font-weight: ${fonts.weight.semibold};
|
|
20
20
|
`;
|
|
21
21
|
|
|
22
|
+
const StyledButton = styled(Button)`
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-template-columns: 1fr auto;
|
|
25
|
+
`;
|
|
26
|
+
|
|
22
27
|
export type FilterProps = {
|
|
23
28
|
value: string;
|
|
24
29
|
title: string;
|
|
@@ -31,7 +36,7 @@ type Props = {
|
|
|
31
36
|
};
|
|
32
37
|
|
|
33
38
|
const ActiveFilterContent = ({ filter, onFilterRemove, t }: Props & WithTranslation) => (
|
|
34
|
-
<
|
|
39
|
+
<StyledButton
|
|
35
40
|
aria-label={t('searchPage.searchFilterMessages.removeFilter', {
|
|
36
41
|
filterName: filter.title,
|
|
37
42
|
})}
|
|
@@ -41,7 +46,7 @@ const ActiveFilterContent = ({ filter, onFilterRemove, t }: Props & WithTranslat
|
|
|
41
46
|
onClick={() => onFilterRemove(filter.value, filter.name)}>
|
|
42
47
|
<StyledActiveFilterTitle>{filter.title}</StyledActiveFilterTitle>
|
|
43
48
|
<Cross />
|
|
44
|
-
</
|
|
49
|
+
</StyledButton>
|
|
45
50
|
);
|
|
46
51
|
|
|
47
52
|
export default withTranslation()(ActiveFilterContent);
|
|
@@ -7,31 +7,39 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import React, { ReactElement } from 'react';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
10
11
|
import styled from '@emotion/styled';
|
|
11
12
|
import css from '@emotion/css';
|
|
12
13
|
import { spacing, mq, breakpoints } from '@ndla/core';
|
|
13
14
|
import Tooltip from '@ndla/tooltip';
|
|
14
|
-
import
|
|
15
|
+
import Button from '@ndla/button';
|
|
15
16
|
import ActiveFilterContent, { FilterProps, StyledActiveFilterTitle } from './ActiveFilterContent';
|
|
16
17
|
|
|
17
18
|
type StyledActiveFiltersProps = {
|
|
18
19
|
showOnSmallScreen?: boolean;
|
|
19
20
|
filterLength?: number;
|
|
20
21
|
};
|
|
22
|
+
|
|
21
23
|
const StyledActiveFilters = styled.ul<StyledActiveFiltersProps>`
|
|
22
24
|
margin: 0;
|
|
23
25
|
padding: 0;
|
|
24
26
|
display: none;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
${(props: StyledActiveFiltersProps) =>
|
|
28
|
+
props.showOnSmallScreen &&
|
|
29
|
+
css`
|
|
30
|
+
${StyledActiveFilterTitle} {
|
|
31
|
+
text-overflow: ellipsis;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
padding-right: ${spacing.small};
|
|
34
|
+
display: block;
|
|
35
|
+
/* max-width: 200px; */
|
|
36
|
+
}
|
|
37
|
+
${mq.range({ until: breakpoints.desktop })} {
|
|
30
38
|
display: flex;
|
|
31
39
|
flex-direction: row;
|
|
32
40
|
flex-wrap: wrap;
|
|
33
41
|
}
|
|
34
|
-
|
|
42
|
+
${mq.range({ until: breakpoints.tablet })} {
|
|
35
43
|
display: flex;
|
|
36
44
|
flex-direction: column;
|
|
37
45
|
align-items: stretch;
|
|
@@ -88,46 +96,72 @@ type Props = {
|
|
|
88
96
|
onFilterRemove: (value: string, name: string) => void;
|
|
89
97
|
showOnSmallScreen?: boolean;
|
|
90
98
|
customElements?: ReactElement[];
|
|
99
|
+
onClickShowHiddenSubjects: () => void;
|
|
91
100
|
};
|
|
92
101
|
|
|
93
|
-
const ActiveFilters = ({
|
|
102
|
+
const ActiveFilters = ({
|
|
103
|
+
filters,
|
|
104
|
+
onFilterRemove,
|
|
105
|
+
showOnSmallScreen,
|
|
106
|
+
customElements,
|
|
107
|
+
onClickShowHiddenSubjects,
|
|
108
|
+
}: Props) => {
|
|
94
109
|
const { t } = useTranslation();
|
|
95
|
-
if (filters
|
|
96
|
-
|
|
110
|
+
if (!filters) return null;
|
|
111
|
+
const showFilterCount = 3;
|
|
112
|
+
const filterLength = filters.length;
|
|
97
113
|
|
|
98
|
-
|
|
99
|
-
const filterKey = filter.name ? `${filter.name}${filter.value}` : filter.value;
|
|
114
|
+
const visibleFilters = filterLength > showFilterCount ? filters.slice(0, showFilterCount - 1) : filters;
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{filterLength > 1 ? (
|
|
104
|
-
<Tooltip
|
|
105
|
-
delay={2000}
|
|
106
|
-
align="bottom"
|
|
107
|
-
tooltip={t('searchPage.searchFilterMessages.removeFilter', {
|
|
108
|
-
filterName: filter.title,
|
|
109
|
-
})}>
|
|
110
|
-
<ActiveFilterContent filter={filter} onFilterRemove={onFilterRemove} />
|
|
111
|
-
</Tooltip>
|
|
112
|
-
) : (
|
|
113
|
-
<ActiveFilterContent filter={filter} onFilterRemove={onFilterRemove} />
|
|
114
|
-
)}
|
|
115
|
-
</StyledActiveFilterWrapper>
|
|
116
|
-
);
|
|
117
|
-
});
|
|
116
|
+
const filterItems = visibleFilters.map((filter) => {
|
|
117
|
+
const filterKey = filter.name ? `${filter.name}${filter.value}` : filter.value;
|
|
118
118
|
|
|
119
119
|
return (
|
|
120
|
-
<
|
|
121
|
-
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
<StyledActiveFilterWrapper key={filterKey}>
|
|
121
|
+
{filterLength > 1 ? (
|
|
122
|
+
<Tooltip
|
|
123
|
+
delay={2000}
|
|
124
|
+
align="bottom"
|
|
125
|
+
tooltip={t('searchPage.searchFilterMessages.removeFilter', {
|
|
126
|
+
filterName: filter.title,
|
|
127
|
+
})}>
|
|
128
|
+
<ActiveFilterContent filter={filter} onFilterRemove={onFilterRemove} />
|
|
129
|
+
</Tooltip>
|
|
130
|
+
) : (
|
|
131
|
+
<ActiveFilterContent filter={filter} onFilterRemove={onFilterRemove} />
|
|
132
|
+
)}
|
|
133
|
+
</StyledActiveFilterWrapper>
|
|
127
134
|
);
|
|
128
|
-
}
|
|
135
|
+
});
|
|
129
136
|
|
|
130
|
-
return
|
|
137
|
+
return (
|
|
138
|
+
<StyledActiveFilters showOnSmallScreen={showOnSmallScreen} filterLength={filterLength}>
|
|
139
|
+
{filterItems}
|
|
140
|
+
{filterLength > showFilterCount && (
|
|
141
|
+
<StyledActiveFilterWrapper>
|
|
142
|
+
<Tooltip delay={2000} align="bottom" tooltip={t('searchPage.searchFilterMessages.noValuesButtonText')}>
|
|
143
|
+
<Button
|
|
144
|
+
aria-label={t('searchPage.searchFilterMessages.additionalSubjectFilters', {
|
|
145
|
+
count: filterLength - showFilterCount + 1,
|
|
146
|
+
})}
|
|
147
|
+
type="button"
|
|
148
|
+
size="normal"
|
|
149
|
+
borderShape="rounded"
|
|
150
|
+
onClick={onClickShowHiddenSubjects}>
|
|
151
|
+
<StyledActiveFilterTitle>
|
|
152
|
+
{t('searchPage.searchFilterMessages.additionalSubjectFilters', {
|
|
153
|
+
count: filterLength - showFilterCount + 1,
|
|
154
|
+
})}
|
|
155
|
+
</StyledActiveFilterTitle>
|
|
156
|
+
</Button>
|
|
157
|
+
</Tooltip>
|
|
158
|
+
</StyledActiveFilterWrapper>
|
|
159
|
+
)}
|
|
160
|
+
{customElements?.map((item, index) => (
|
|
161
|
+
<StyledActiveFilterWrapper key={index}>{item}</StyledActiveFilterWrapper>
|
|
162
|
+
))}
|
|
163
|
+
</StyledActiveFilters>
|
|
164
|
+
);
|
|
131
165
|
};
|
|
132
166
|
|
|
133
167
|
export default ActiveFilters;
|