@ndla/ui 36.0.1 → 37.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/es/Article/Article.js +7 -13
- package/es/Article/ArticleByline.js +79 -123
- package/es/Article/ArticleFootNotes.js +16 -11
- package/es/AudioPlayer/AudioPlayer.js +33 -35
- package/es/AudioPlayer/initAudioPlayers.js +6 -1
- package/es/BlogPost/BlogPost.js +4 -4
- package/es/CampaignBlock/CampaignBlock.js +77 -0
- package/es/CampaignBlock/index.js +9 -0
- package/es/ContactBlock/ContactBlock.js +63 -39
- package/es/Embed/AudioEmbed.js +44 -188
- package/es/Embed/BrightcoveEmbed.js +27 -123
- package/es/Embed/ConceptEmbed.js +53 -75
- package/es/Embed/EmbedErrorPlaceholder.js +41 -0
- package/es/Embed/ExternalEmbed.js +5 -12
- package/es/Embed/H5pEmbed.js +4 -14
- package/es/Embed/IframeEmbed.js +4 -4
- package/es/Embed/ImageEmbed.js +41 -153
- package/es/Embed/conceptComponents.js +62 -228
- package/es/Embed/types.js +1 -0
- package/es/KeyFigure/KeyFigure.js +57 -0
- package/es/{KeyPerformanceIndicator → KeyFigure}/index.js +1 -1
- package/es/LicenseByline/EmbedByline.js +115 -0
- package/es/LicenseByline/LicenseDescription.js +39 -0
- package/es/LicenseByline/LicenseLink.js +36 -0
- package/es/LicenseByline/index.js +1 -0
- package/es/List/OrderedList.js +48 -0
- package/es/List/UnOrderedList.js +36 -0
- package/es/List/index.js +10 -0
- package/es/Navigation/NavigationBox.js +41 -48
- package/es/Navigation/NavigationHeading.js +18 -29
- package/es/Notion/Notion.js +5 -5
- package/es/Resource/resourceComponents.js +12 -11
- package/es/Typography/Heading.js +38 -0
- package/es/Typography/index.js +9 -0
- package/es/all.css +1 -1
- package/es/index.js +4 -2
- package/es/locale/messages-en.js +13 -2
- package/es/locale/messages-nb.js +13 -2
- package/es/locale/messages-nn.js +13 -2
- package/es/locale/messages-se.js +13 -2
- package/es/locale/messages-sma.js +13 -2
- package/es/model/ContentType.js +7 -1
- package/lib/Article/Article.d.ts +1 -3
- package/lib/Article/Article.js +7 -13
- package/lib/Article/ArticleByline.d.ts +3 -5
- package/lib/Article/ArticleByline.js +83 -126
- package/lib/Article/ArticleFootNotes.js +16 -11
- package/lib/AudioPlayer/AudioPlayer.d.ts +1 -2
- package/lib/AudioPlayer/AudioPlayer.js +33 -36
- package/lib/AudioPlayer/initAudioPlayers.d.ts +1 -0
- package/lib/AudioPlayer/initAudioPlayers.js +9 -3
- package/lib/BlogPost/BlogPost.js +4 -4
- package/lib/CampaignBlock/CampaignBlock.d.ts +31 -0
- package/lib/CampaignBlock/CampaignBlock.js +82 -0
- package/lib/CampaignBlock/index.d.ts +8 -0
- package/lib/CampaignBlock/index.js +13 -0
- package/lib/ContactBlock/ContactBlock.js +63 -39
- package/lib/Embed/AudioEmbed.d.ts +3 -2
- package/lib/Embed/AudioEmbed.js +53 -192
- package/lib/Embed/BrightcoveEmbed.d.ts +3 -1
- package/lib/Embed/BrightcoveEmbed.js +27 -122
- package/lib/Embed/ConceptEmbed.d.ts +7 -2
- package/lib/Embed/ConceptEmbed.js +51 -73
- package/lib/Embed/EmbedErrorPlaceholder.d.ts +17 -0
- package/lib/Embed/EmbedErrorPlaceholder.js +48 -0
- package/lib/Embed/ExternalEmbed.js +5 -11
- package/lib/Embed/H5pEmbed.js +4 -13
- package/lib/Embed/IframeEmbed.d.ts +2 -2
- package/lib/Embed/IframeEmbed.js +4 -4
- package/lib/Embed/ImageEmbed.d.ts +3 -10
- package/lib/Embed/ImageEmbed.js +48 -161
- package/lib/Embed/conceptComponents.d.ts +4 -2
- package/lib/Embed/conceptComponents.js +67 -231
- package/lib/Embed/index.d.ts +1 -0
- package/lib/Embed/types.d.ts +14 -0
- package/lib/Embed/types.js +5 -0
- package/lib/KeyFigure/KeyFigure.d.ts +10 -0
- package/lib/KeyFigure/KeyFigure.js +62 -0
- package/lib/KeyFigure/index.d.ts +1 -0
- package/lib/KeyFigure/index.js +13 -0
- package/lib/LicenseByline/EmbedByline.d.ts +51 -0
- package/lib/LicenseByline/EmbedByline.js +120 -0
- package/lib/LicenseByline/LicenseDescription.d.ts +14 -0
- package/lib/LicenseByline/LicenseDescription.js +44 -0
- package/lib/LicenseByline/LicenseLink.d.ts +14 -0
- package/lib/LicenseByline/LicenseLink.js +44 -0
- package/lib/LicenseByline/index.d.ts +1 -0
- package/lib/LicenseByline/index.js +13 -0
- package/lib/List/OrderedList.d.ts +15 -0
- package/lib/List/OrderedList.js +56 -0
- package/lib/List/UnOrderedList.d.ts +10 -0
- package/lib/List/UnOrderedList.js +43 -0
- package/lib/List/index.d.ts +9 -0
- package/lib/List/index.js +20 -0
- package/lib/Navigation/NavigationBox.js +40 -47
- package/lib/Navigation/NavigationHeading.js +17 -28
- package/lib/Notion/Notion.js +5 -5
- package/lib/Resource/resourceComponents.js +12 -11
- package/lib/Typography/Heading.d.ts +26 -0
- package/lib/Typography/Heading.js +45 -0
- package/lib/Typography/index.d.ts +8 -0
- package/lib/Typography/index.js +13 -0
- package/lib/all.css +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +23 -3
- package/lib/locale/messages-en.d.ts +11 -0
- package/lib/locale/messages-en.js +13 -2
- package/lib/locale/messages-nb.d.ts +11 -0
- package/lib/locale/messages-nb.js +13 -2
- package/lib/locale/messages-nn.d.ts +11 -0
- package/lib/locale/messages-nn.js +13 -2
- package/lib/locale/messages-se.d.ts +11 -0
- package/lib/locale/messages-se.js +13 -2
- package/lib/locale/messages-sma.d.ts +11 -0
- package/lib/locale/messages-sma.js +13 -2
- package/lib/model/ContentType.d.ts +1 -0
- package/lib/model/ContentType.js +9 -2
- package/package.json +15 -15
- package/src/Article/Article.tsx +1 -8
- package/src/Article/ArticleByline.tsx +78 -127
- package/src/Article/ArticleFootNotes.tsx +33 -10
- package/src/Article/component.article.scss +1 -52
- package/src/Article/component.footnotes.scss +2 -2
- package/src/Aside/component.aside.scss +3 -3
- package/src/AudioPlayer/AudioPlayer.tsx +11 -24
- package/src/AudioPlayer/initAudioPlayers.tsx +7 -2
- package/src/BlogPost/BlogPost.tsx +0 -4
- package/src/CampaignBlock/CampaignBlock.stories.tsx +63 -0
- package/src/CampaignBlock/CampaignBlock.tsx +99 -0
- package/src/CampaignBlock/index.ts +9 -0
- package/src/ContactBlock/ContactBlock.tsx +27 -19
- package/src/ContactBlock/Contactblock.stories.tsx +0 -1
- package/src/Dialog/component.dialog.scss +4 -5
- package/src/Embed/AudioEmbed.stories.tsx +5 -3
- package/src/Embed/AudioEmbed.tsx +45 -192
- package/src/Embed/BrightcoveEmbed.stories.tsx +5 -1
- package/src/Embed/BrightcoveEmbed.tsx +20 -95
- package/src/Embed/ConceptEmbed.stories.tsx +5 -0
- package/src/Embed/ConceptEmbed.tsx +43 -54
- package/src/Embed/EmbedErrorPlaceholder.tsx +59 -0
- package/src/Embed/ExternalEmbed.stories.tsx +86 -0
- package/src/Embed/ExternalEmbed.tsx +3 -8
- package/src/Embed/H5pEmbed.stories.tsx +92 -0
- package/src/Embed/H5pEmbed.tsx +2 -10
- package/src/Embed/IframeEmbed.stories.tsx +130 -0
- package/src/Embed/IframeEmbed.tsx +3 -3
- package/src/Embed/ImageEmbed.stories.tsx +3 -1
- package/src/Embed/ImageEmbed.tsx +21 -116
- package/src/Embed/conceptComponents.tsx +67 -257
- package/src/Embed/index.ts +1 -0
- package/src/Embed/types.ts +12 -0
- package/src/FactBox/component.factbox.scss +3 -3
- package/src/Figure/component.figure-license.scss +4 -4
- package/src/Figure/component.figure.scss +1 -1
- package/src/KeyFigure/KeyFigure.stories.tsx +36 -0
- package/src/{KeyPerformanceIndicator/KeyPerformanceIndicator.tsx → KeyFigure/KeyFigure.tsx} +9 -7
- package/src/{KeyPerformanceIndicator → KeyFigure}/index.ts +1 -1
- package/src/LicenseByline/EmbedByline.stories.tsx +83 -0
- package/src/LicenseByline/EmbedByline.tsx +165 -0
- package/src/LicenseByline/LicenseDescription.tsx +43 -0
- package/src/LicenseByline/LicenseLink.tsx +42 -0
- package/src/LicenseByline/index.tsx +1 -0
- package/src/List/OrderedList.tsx +115 -0
- package/src/List/UnOrderedList.tsx +49 -0
- package/src/List/index.ts +10 -0
- package/src/MediaList/component.medialist.scss +2 -2
- package/src/Navigation/NavigationBox.tsx +10 -14
- package/src/Navigation/NavigationHeading.tsx +15 -24
- package/src/Notion/Notion.tsx +1 -1
- package/src/RelatedArticleList/component.related-articles.scss +3 -13
- package/src/Resource/resourceComponents.tsx +4 -2
- package/src/Table/component.tables.scss +0 -46
- package/src/Translation/component.translation.scss +3 -5
- package/src/Typography/Heading.tsx +96 -0
- package/src/Typography/index.ts +9 -0
- package/src/index.ts +5 -1
- package/src/locale/messages-en.ts +11 -0
- package/src/locale/messages-nb.ts +11 -0
- package/src/locale/messages-nn.ts +11 -0
- package/src/locale/messages-se.ts +11 -0
- package/src/locale/messages-sma.ts +11 -0
- package/src/model/ContentType.ts +7 -0
- package/es/KeyPerformanceIndicator/KeyPerformanceIndicator.js +0 -57
- package/lib/KeyPerformanceIndicator/KeyPerformanceIndicator.d.ts +0 -8
- package/lib/KeyPerformanceIndicator/KeyPerformanceIndicator.js +0 -62
- package/lib/KeyPerformanceIndicator/index.d.ts +0 -1
- package/lib/KeyPerformanceIndicator/index.js +0 -13
- package/src/KeyPerformanceIndicator/KeyPerformanceIndicator.stories.tsx +0 -79
|
@@ -6,36 +6,36 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React, { ReactNode } from 'react';
|
|
9
|
+
import React, { ReactNode, useCallback, useEffect, useState } from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
|
-
import
|
|
12
|
-
import { CopyButton, ButtonV2 } from '@ndla/button';
|
|
13
|
-
import { colors, fonts, spacing } from '@ndla/core';
|
|
14
|
-
import { copyTextToClipboard, printPage } from '@ndla/util';
|
|
11
|
+
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
15
12
|
import { useTranslation } from 'react-i18next';
|
|
16
13
|
import { getLicenseByAbbreviation } from '@ndla/licenses';
|
|
17
|
-
import {
|
|
14
|
+
import { AccordionRoot, AccordionHeader, AccordionContent, AccordionItem } from '@ndla/accordion';
|
|
18
15
|
import { TFunction } from 'i18next';
|
|
16
|
+
import { FootNote } from '../types';
|
|
17
|
+
import ArticleFootNotes from './ArticleFootNotes';
|
|
18
|
+
import LicenseLink from '../LicenseByline/LicenseLink';
|
|
19
19
|
|
|
20
20
|
const Wrapper = styled.div`
|
|
21
21
|
margin-top: ${spacing.normal};
|
|
22
22
|
padding-top: ${spacing.normal};
|
|
23
23
|
padding-bottom: ${spacing.xsmall};
|
|
24
24
|
border-top: 1px solid ${colors.brand.greyLight};
|
|
25
|
-
${fonts.sizes('
|
|
25
|
+
${fonts.sizes('16px', '24px')};
|
|
26
26
|
font-family: ${fonts.sans};
|
|
27
27
|
color: ${colors.brand.greyDark};
|
|
28
28
|
`;
|
|
29
29
|
|
|
30
30
|
const TextWrapper = styled.div`
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
display: flex;
|
|
32
|
+
justify-content: space-between;
|
|
33
|
+
width: 100%;
|
|
34
|
+
padding-bottom: ${spacing.mediumlarge};
|
|
35
|
+
${mq.range({ until: breakpoints.tabletWide })} {
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
flex-direction: column-reverse;
|
|
38
|
+
gap: ${spacing.xsmall};
|
|
39
39
|
}
|
|
40
40
|
`;
|
|
41
41
|
|
|
@@ -57,11 +57,8 @@ type Props = {
|
|
|
57
57
|
published: string;
|
|
58
58
|
license: string;
|
|
59
59
|
licenseBox?: ReactNode;
|
|
60
|
-
copyPageUrlLink?: string;
|
|
61
|
-
printUrl?: string;
|
|
62
60
|
locale?: string;
|
|
63
|
-
|
|
64
|
-
copySourceReference?: string;
|
|
61
|
+
footnotes?: FootNote[];
|
|
65
62
|
};
|
|
66
63
|
|
|
67
64
|
const renderContributors = (contributors: SupplierProps[] | AuthorProps[], t: TFunction) => {
|
|
@@ -85,133 +82,87 @@ const getSuppliersText = (suppliers: SupplierProps[], t: TFunction) => {
|
|
|
85
82
|
: t('article.supplierLabel', { name: renderContributors(suppliers, t), interpolation: { escapeValue: false } });
|
|
86
83
|
};
|
|
87
84
|
|
|
85
|
+
const LicenseWrapper = styled.div`
|
|
86
|
+
display: flex;
|
|
87
|
+
gap: ${spacing.small};
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
const refRegexp = /note\d/;
|
|
91
|
+
const referencesAccordionId = 'references';
|
|
92
|
+
|
|
88
93
|
const ArticleByline = ({
|
|
89
94
|
authors = [],
|
|
90
95
|
suppliers = [],
|
|
91
|
-
|
|
96
|
+
footnotes,
|
|
97
|
+
license: licenseString,
|
|
92
98
|
licenseBox,
|
|
93
99
|
published,
|
|
94
|
-
copyPageUrlLink,
|
|
95
|
-
printUrl,
|
|
96
100
|
locale,
|
|
97
|
-
copyEmbedLink,
|
|
98
|
-
copySourceReference,
|
|
99
101
|
}: Props) => {
|
|
100
102
|
const { t } = useTranslation();
|
|
103
|
+
const [openAccordions, setOpenAccordions] = useState<string[]>([]);
|
|
104
|
+
|
|
105
|
+
const onHashChange = useCallback(
|
|
106
|
+
(e: HashChangeEvent) => {
|
|
107
|
+
const hash = e.newURL.split('#')[1];
|
|
108
|
+
if (hash.match(refRegexp) && !openAccordions.includes(referencesAccordionId)) {
|
|
109
|
+
setOpenAccordions([...openAccordions, referencesAccordionId]);
|
|
110
|
+
const el = document.getElementById(`#${hash}`);
|
|
111
|
+
el?.click();
|
|
112
|
+
el?.focus();
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
[openAccordions],
|
|
116
|
+
);
|
|
101
117
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
const copyLicense = () => {
|
|
110
|
-
if (copySourceReference) {
|
|
111
|
-
copyTextToClipboard(copySourceReference);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
const copyEmbededLink = () => {
|
|
115
|
-
if (copyEmbedLink) {
|
|
116
|
-
copyTextToClipboard(copyEmbedLink);
|
|
117
|
-
}
|
|
118
|
-
};
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
window.addEventListener('hashchange', onHashChange);
|
|
120
|
+
return () => window.removeEventListener('hashchange', onHashChange);
|
|
121
|
+
}, [onHashChange]);
|
|
122
|
+
|
|
123
|
+
const license = getLicenseByAbbreviation(licenseString, locale);
|
|
119
124
|
|
|
120
125
|
const showPrimaryContributors = suppliers.length > 0 || authors.length > 0;
|
|
121
126
|
const showSecondaryContributors = suppliers.length > 0 && authors.length > 0;
|
|
122
127
|
|
|
123
|
-
const buttonId = 'popupUseContent';
|
|
124
|
-
|
|
125
128
|
return (
|
|
126
129
|
<Wrapper>
|
|
127
|
-
<
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
)}
|
|
130
|
+
<TextWrapper>
|
|
131
|
+
<LicenseWrapper>
|
|
132
|
+
<LicenseLink license={license} />
|
|
133
|
+
{showPrimaryContributors && (
|
|
134
|
+
<PrimaryContributorsWrapper>
|
|
135
|
+
{authors.length > 0
|
|
136
|
+
? t('article.authorsLabel', {
|
|
137
|
+
names: renderContributors(authors, t),
|
|
138
|
+
interpolation: { escapeValue: false },
|
|
139
|
+
})
|
|
140
|
+
: getSuppliersText(suppliers, t)}
|
|
141
|
+
</PrimaryContributorsWrapper>
|
|
142
|
+
)}
|
|
143
|
+
</LicenseWrapper>
|
|
144
|
+
<div>
|
|
145
|
+
{t('article.lastUpdated')} {published}
|
|
146
|
+
</div>
|
|
147
|
+
</TextWrapper>
|
|
146
148
|
{showSecondaryContributors && <TextWrapper>{getSuppliersText(suppliers, t)}</TextWrapper>}
|
|
147
|
-
<
|
|
149
|
+
<AccordionRoot type="multiple" onValueChange={setOpenAccordions} value={openAccordions}>
|
|
148
150
|
{licenseBox && (
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
{t('article.useContent')}
|
|
154
|
-
</ButtonV2>
|
|
155
|
-
}
|
|
156
|
-
backgroundColor="white"
|
|
157
|
-
position="top"
|
|
158
|
-
size="medium"
|
|
159
|
-
>
|
|
160
|
-
{(onClose: () => void) => (
|
|
161
|
-
<>
|
|
162
|
-
<ModalHeader modifier="no-bottom-padding">
|
|
163
|
-
<ModalCloseButton onClick={onClose} title="Lukk" />
|
|
164
|
-
</ModalHeader>
|
|
165
|
-
<ModalBody>{licenseBox}</ModalBody>
|
|
166
|
-
</>
|
|
167
|
-
)}
|
|
168
|
-
</Modal>
|
|
169
|
-
)}
|
|
170
|
-
{copySourceReference && (
|
|
171
|
-
<CopyButton
|
|
172
|
-
size="small"
|
|
173
|
-
shape="pill"
|
|
174
|
-
variant="outline"
|
|
175
|
-
aria-live="assertive"
|
|
176
|
-
copyNode={t('license.hasCopiedTitle')}
|
|
177
|
-
data-copy-string={copySourceReference}
|
|
178
|
-
onClick={copyLicense}
|
|
179
|
-
>
|
|
180
|
-
{`${t('license.copy')} ${t('license.copyTitle').toLowerCase()}`}
|
|
181
|
-
</CopyButton>
|
|
151
|
+
<AccordionItem value="rulesForUse">
|
|
152
|
+
<AccordionHeader>{t('article.useContent')}</AccordionHeader>
|
|
153
|
+
<AccordionContent>{licenseBox}</AccordionContent>
|
|
154
|
+
</AccordionItem>
|
|
182
155
|
)}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
copyNode={t('article.copyPageLinkCopied')}
|
|
192
|
-
>
|
|
193
|
-
{t('article.copyPageLink')}
|
|
194
|
-
</CopyButton>
|
|
195
|
-
)}
|
|
196
|
-
{copyEmbedLink && (
|
|
197
|
-
<CopyButton
|
|
198
|
-
size="small"
|
|
199
|
-
shape="pill"
|
|
200
|
-
variant="outline"
|
|
201
|
-
aria-live="assertive"
|
|
202
|
-
copyNode={t('license.hasCopiedTitle')}
|
|
203
|
-
data-copy-string={copyEmbedLink}
|
|
204
|
-
onClick={copyEmbededLink}
|
|
205
|
-
>
|
|
206
|
-
{`${t('license.copy')} ${t('license.tabs.embedlink').toLowerCase()}`}
|
|
207
|
-
</CopyButton>
|
|
208
|
-
)}
|
|
209
|
-
{printUrl && (
|
|
210
|
-
<ButtonV2 size="small" shape="pill" variant="outline" onClick={() => printPage(printUrl)}>
|
|
211
|
-
{t('article.printPage')}
|
|
212
|
-
</ButtonV2>
|
|
156
|
+
|
|
157
|
+
{!!footnotes?.length && (
|
|
158
|
+
<AccordionItem value={referencesAccordionId}>
|
|
159
|
+
<AccordionHeader>Referanser</AccordionHeader>
|
|
160
|
+
<AccordionContent forceMount>
|
|
161
|
+
<ArticleFootNotes footNotes={footnotes} />
|
|
162
|
+
</AccordionContent>
|
|
163
|
+
</AccordionItem>
|
|
213
164
|
)}
|
|
214
|
-
</
|
|
165
|
+
</AccordionRoot>
|
|
215
166
|
</Wrapper>
|
|
216
167
|
);
|
|
217
168
|
};
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import React from 'react';
|
|
10
|
+
import styled from '@emotion/styled';
|
|
11
|
+
import { colors, spacing } from '@ndla/core';
|
|
10
12
|
import { FootNote as FootNoteType } from '../types';
|
|
11
13
|
|
|
12
14
|
const citeDetailString = (description: string | undefined) => (description ? `${description}. ` : '');
|
|
@@ -15,14 +17,26 @@ type FootNoteProps = {
|
|
|
15
17
|
footNote: FootNoteType;
|
|
16
18
|
};
|
|
17
19
|
|
|
20
|
+
const Cite = styled.cite`
|
|
21
|
+
display: flex;
|
|
22
|
+
gap: ${spacing.small};
|
|
23
|
+
a {
|
|
24
|
+
box-shadow: none;
|
|
25
|
+
text-decoration: underline;
|
|
26
|
+
text-underline-offset: ${spacing.xxsmall};
|
|
27
|
+
&:hover,
|
|
28
|
+
&:focus-visible {
|
|
29
|
+
text-decoration: none;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
|
|
18
34
|
const FootNote = ({ footNote }: FootNoteProps) => (
|
|
19
|
-
<li
|
|
20
|
-
<
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</a>
|
|
25
|
-
</sup>
|
|
35
|
+
<li>
|
|
36
|
+
<Cite id={`note${footNote.ref}`}>
|
|
37
|
+
<a href={`#ref${footNote.ref}`} target="_self">
|
|
38
|
+
{footNote.ref}
|
|
39
|
+
</a>
|
|
26
40
|
{`«${footNote.title}». ${footNote.authors.join(' ')}. ${citeDetailString(footNote.edition)}${citeDetailString(
|
|
27
41
|
footNote.publisher,
|
|
28
42
|
)}${footNote.year}. `}
|
|
@@ -32,7 +46,7 @@ const FootNote = ({ footNote }: FootNoteProps) => (
|
|
|
32
46
|
{'.'}
|
|
33
47
|
</a>
|
|
34
48
|
) : null}
|
|
35
|
-
</
|
|
49
|
+
</Cite>
|
|
36
50
|
</li>
|
|
37
51
|
);
|
|
38
52
|
|
|
@@ -40,12 +54,21 @@ type ArticleFootNotesProps = {
|
|
|
40
54
|
footNotes: Array<FootNoteType>;
|
|
41
55
|
};
|
|
42
56
|
|
|
57
|
+
const FootnoteList = styled.ol`
|
|
58
|
+
margin: 0;
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
list-style: none;
|
|
62
|
+
padding: ${spacing.small};
|
|
63
|
+
color: ${colors.text.light};
|
|
64
|
+
`;
|
|
65
|
+
|
|
43
66
|
const ArticleFootNotes = ({ footNotes }: ArticleFootNotesProps) => (
|
|
44
|
-
<
|
|
67
|
+
<FootnoteList>
|
|
45
68
|
{footNotes.map((footNote) => (
|
|
46
69
|
<FootNote key={footNote.ref} footNote={footNote} />
|
|
47
70
|
))}
|
|
48
|
-
</
|
|
71
|
+
</FootnoteList>
|
|
49
72
|
);
|
|
50
73
|
|
|
51
74
|
export default ArticleFootNotes;
|
|
@@ -4,15 +4,6 @@
|
|
|
4
4
|
** Title has icon when article is a resource type
|
|
5
5
|
**/
|
|
6
6
|
|
|
7
|
-
@mixin contentList() {
|
|
8
|
-
ul:not([class]),
|
|
9
|
-
ul.o-list--two-columns,
|
|
10
|
-
ul.o-list--bullets,
|
|
11
|
-
ol {
|
|
12
|
-
@content;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
7
|
.c-article {
|
|
17
8
|
font-family: $font-serif;
|
|
18
9
|
background: $white;
|
|
@@ -33,58 +24,16 @@
|
|
|
33
24
|
margin-bottom: 29px;
|
|
34
25
|
}
|
|
35
26
|
}
|
|
36
|
-
p {
|
|
37
|
-
@include chinese() {
|
|
38
|
-
@include font-size(20px, 35px);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@include contentList() {
|
|
43
|
-
@include chinese() {
|
|
44
|
-
@include font-size(20px, 35px);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
@include chinese() {
|
|
49
|
-
@include contentList() {
|
|
50
|
-
@include font-size(22px, 35px);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
p {
|
|
54
|
-
@include font-size(22px, 35px);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
27
|
|
|
58
28
|
@include mq(tablet) {
|
|
59
29
|
@include font-size(20px, 35px);
|
|
60
30
|
|
|
61
|
-
p {
|
|
62
|
-
@include chinese() {
|
|
63
|
-
@include font-size(22px, 35px);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
31
|
> section > p {
|
|
68
32
|
&:not([class]) {
|
|
69
33
|
margin-bottom: 35px;
|
|
70
34
|
}
|
|
71
35
|
}
|
|
72
36
|
|
|
73
|
-
@include contentList() {
|
|
74
|
-
@include chinese() {
|
|
75
|
-
@include font-size(22px, 35px);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@include chinese() {
|
|
80
|
-
@include contentList() {
|
|
81
|
-
@include font-size(22px, 35px);
|
|
82
|
-
}
|
|
83
|
-
p {
|
|
84
|
-
@include font-size(22px, 35px);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
37
|
padding: 0 $spacing $spacing;
|
|
89
38
|
margin-bottom: $spacing--large;
|
|
90
39
|
margin-top: -$spacing * 6;
|
|
@@ -178,7 +127,7 @@
|
|
|
178
127
|
}
|
|
179
128
|
|
|
180
129
|
p {
|
|
181
|
-
@include
|
|
130
|
+
@include font-size(16px, 20px);
|
|
182
131
|
color: $text-light-color;
|
|
183
132
|
text-transform: uppercase;
|
|
184
133
|
margin-bottom: 0;
|
|
@@ -17,7 +17,7 @@ $highlight-color: $brand-grey--lighter;
|
|
|
17
17
|
display: block;
|
|
18
18
|
border-top: 2px solid $brand-grey--lighter;
|
|
19
19
|
color: gray;
|
|
20
|
-
@include
|
|
20
|
+
@include font-size(15px, 1.6);
|
|
21
21
|
}
|
|
22
22
|
.c-footnotes__item {
|
|
23
23
|
margin-bottom: $spacing--small;
|
|
@@ -37,7 +37,7 @@ $highlight-color: $brand-grey--lighter;
|
|
|
37
37
|
padding: 10px 15px;
|
|
38
38
|
box-shadow: none;
|
|
39
39
|
text-decoration: underline;
|
|
40
|
-
@include
|
|
40
|
+
@include font-size(15px, 1.6);
|
|
41
41
|
|
|
42
42
|
&:hover,
|
|
43
43
|
&:active,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.c-aside {
|
|
7
7
|
position: relative;
|
|
8
8
|
margin: $spacing--large 0;
|
|
9
|
-
@include
|
|
9
|
+
@include font-size(16px, 1.5);
|
|
10
10
|
z-index: 1;
|
|
11
11
|
|
|
12
12
|
@include mq(tablet) {
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
.c-aside h1 {
|
|
60
60
|
margin-top: 0;
|
|
61
61
|
margin-bottom: $spacing;
|
|
62
|
-
@include
|
|
62
|
+
@include font-size(22px, 34px);
|
|
63
63
|
font-weight: $font-weight-bold;
|
|
64
64
|
position: relative;
|
|
65
65
|
z-index: 2;
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
.c-aside h4,
|
|
71
71
|
.c-aside h5 {
|
|
72
72
|
display: block;
|
|
73
|
-
@include
|
|
73
|
+
@include font-size(16px, 1.5);
|
|
74
74
|
letter-spacing: 0.1em;
|
|
75
75
|
margin-top: $spacing;
|
|
76
76
|
margin-bottom: $spacing--small;
|
|
@@ -6,14 +6,13 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React, { ReactNode,
|
|
9
|
+
import React, { ReactNode, useMemo, useState } from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
11
|
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
12
12
|
import { ButtonV2 } from '@ndla/button';
|
|
13
13
|
import { Cross as CrossIcon } from '@ndla/icons/action';
|
|
14
14
|
import { useTranslation } from 'react-i18next';
|
|
15
15
|
import SafeLink from '@ndla/safelink';
|
|
16
|
-
import shave from 'shave';
|
|
17
16
|
import Controls from './Controls';
|
|
18
17
|
import SpeechControl from './SpeechControl';
|
|
19
18
|
|
|
@@ -163,11 +162,7 @@ const TextVersionText = styled.div`
|
|
|
163
162
|
max-width: 670px;
|
|
164
163
|
`;
|
|
165
164
|
|
|
166
|
-
|
|
167
|
-
shave(el, 90, {
|
|
168
|
-
character: `... <a href="#" onclick="(function(e){e.preventDefault(); const parentNode = e.target.parentNode; parentNode.nextSibling.style.display = 'inline'; parentNode.remove();return false;})(arguments[0]);return false;">${readMoreLabel}</a>`,
|
|
169
|
-
});
|
|
170
|
-
};
|
|
165
|
+
const DESCRIPTION_MAX_LENGTH = 200;
|
|
171
166
|
|
|
172
167
|
type Props = {
|
|
173
168
|
src: string;
|
|
@@ -177,7 +172,7 @@ type Props = {
|
|
|
177
172
|
url?: string;
|
|
178
173
|
};
|
|
179
174
|
speech?: boolean;
|
|
180
|
-
description?:
|
|
175
|
+
description?: string;
|
|
181
176
|
textVersion?: ReactNode;
|
|
182
177
|
img?: {
|
|
183
178
|
url: string;
|
|
@@ -189,15 +184,8 @@ type Props = {
|
|
|
189
184
|
const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersion, staticRenderId }: Props) => {
|
|
190
185
|
const { t } = useTranslation();
|
|
191
186
|
const [showTextVersion, setShowTextVersion] = useState(false);
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
const readMoreDescriptionLabel = t('audio.readMoreDescriptionLabel');
|
|
195
|
-
|
|
196
|
-
useEffect(() => {
|
|
197
|
-
if (descriptionRef?.current) {
|
|
198
|
-
truncateDescription(descriptionRef.current, readMoreDescriptionLabel);
|
|
199
|
-
}
|
|
200
|
-
}, [readMoreDescriptionLabel]);
|
|
187
|
+
const [showFullDescription, setShowFullDescription] = useState(false);
|
|
188
|
+
const truncatedDescription = useMemo(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);
|
|
201
189
|
|
|
202
190
|
if (speech) {
|
|
203
191
|
return (
|
|
@@ -244,13 +232,12 @@ const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersi
|
|
|
244
232
|
</TitleWrapper>
|
|
245
233
|
{description && (
|
|
246
234
|
<StyledDescription>
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
</div>
|
|
235
|
+
{showFullDescription || description.length < DESCRIPTION_MAX_LENGTH
|
|
236
|
+
? description
|
|
237
|
+
: `${truncatedDescription}...`}
|
|
238
|
+
<ButtonV2 variant="link" onClick={() => setShowFullDescription((p) => !p)}>
|
|
239
|
+
{t(`audio.${showFullDescription ? 'readLessDescriptionLabel' : 'readMoreDescriptionLabel'}`)}
|
|
240
|
+
</ButtonV2>
|
|
254
241
|
</StyledDescription>
|
|
255
242
|
)}
|
|
256
243
|
{textVersion && img && <TextVersionComponent />}
|
|
@@ -7,11 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import ReactDOM from 'react-dom';
|
|
10
|
-
|
|
10
|
+
import shave from 'shave';
|
|
11
11
|
import Controls from './Controls';
|
|
12
12
|
import SpeechControl from './SpeechControl';
|
|
13
13
|
import { Locale } from '../types';
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
export const truncateDescription = (el: HTMLElement, readMoreLabel: string | null) => {
|
|
16
|
+
shave(el, 90, {
|
|
17
|
+
character: `... <a href="#" onclick="(function(e){e.preventDefault(); const parentNode = e.target.parentNode; parentNode.nextSibling.style.display = 'inline'; parentNode.remove();return false;})(arguments[0]);return false;">${readMoreLabel}</a>`,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
15
20
|
|
|
16
21
|
const forEachElement = (selector: string, callback: Function) => {
|
|
17
22
|
const nodeList = document.querySelectorAll(selector);
|
|
@@ -33,18 +33,14 @@ const Container = styled(SafeLink)`
|
|
|
33
33
|
flex-direction: column;
|
|
34
34
|
color: ${colors.text.primary};
|
|
35
35
|
max-width: 350px;
|
|
36
|
-
min-width: 350px;
|
|
37
36
|
max-height: 415px;
|
|
38
|
-
min-height: 415px;
|
|
39
37
|
gap: ${spacing.nsmall};
|
|
40
38
|
box-shadow: none;
|
|
41
39
|
border: 1px solid ${colors.brand.lightest};
|
|
42
40
|
border-radius: ${misc.borderRadius};
|
|
43
41
|
padding: ${spacing.normal} ${spacing.medium};
|
|
44
42
|
&[data-size='large'] {
|
|
45
|
-
min-width: 532px;
|
|
46
43
|
max-width: 532px;
|
|
47
|
-
min-height: 550px;
|
|
48
44
|
max-height: 550px;
|
|
49
45
|
}
|
|
50
46
|
&:hover,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2023-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 { Meta, StoryObj } from '@storybook/react';
|
|
11
|
+
import CampaignBlock from './CampaignBlock';
|
|
12
|
+
import { defaultParameters } from '../../../../stories/defaults';
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
title: 'Enkle komponenter/Campaign Block',
|
|
16
|
+
component: CampaignBlock,
|
|
17
|
+
tags: ['autodocs'],
|
|
18
|
+
parameters: {
|
|
19
|
+
...defaultParameters,
|
|
20
|
+
},
|
|
21
|
+
args: {},
|
|
22
|
+
} as Meta<typeof CampaignBlock>;
|
|
23
|
+
|
|
24
|
+
export const BothImages: StoryObj<typeof CampaignBlock> = {
|
|
25
|
+
args: {
|
|
26
|
+
title: { title: 'NDLA film', language: 'nb-no' },
|
|
27
|
+
description: {
|
|
28
|
+
text: 'NDLA film er en tjeneste i samarbeid med Norgesfilm. Denne tjenesten lar deg se en rekke spillefilmer, kortfilmer, dokumentarer og serier. Du kan også se undervisningsfilm og filmklipp. Velkommen inn i filmens verden!',
|
|
29
|
+
language: 'nb-no',
|
|
30
|
+
},
|
|
31
|
+
headingLevel: 'h2',
|
|
32
|
+
url: {
|
|
33
|
+
url: '#',
|
|
34
|
+
text: 'Gå til NDLA film',
|
|
35
|
+
},
|
|
36
|
+
imageBefore: {
|
|
37
|
+
alt: '',
|
|
38
|
+
src: 'https://api.test.ndla.no/image-api/raw/n2UYRxEG.png',
|
|
39
|
+
},
|
|
40
|
+
imageAfter: {
|
|
41
|
+
alt: '',
|
|
42
|
+
src: 'https://api.test.ndla.no/image-api/raw/8GOxOhjr.png',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const SingleImage: StoryObj<typeof CampaignBlock> = {
|
|
48
|
+
args: {
|
|
49
|
+
title: { title: 'FN-dagen 24. oktober!', language: 'nb-no' },
|
|
50
|
+
description: {
|
|
51
|
+
text: ' Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation quis nostrud exercitation ',
|
|
52
|
+
language: 'nb-no',
|
|
53
|
+
},
|
|
54
|
+
url: {
|
|
55
|
+
url: '#',
|
|
56
|
+
text: 'Les mer om FN-dagen',
|
|
57
|
+
},
|
|
58
|
+
imageAfter: {
|
|
59
|
+
alt: 'FN-symbol',
|
|
60
|
+
src: 'https://api.test.ndla.no/image-api/raw/LkmDGtip.png',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|