@ndla/ui 56.0.18-alpha.0 → 56.0.20-alpha.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/dist/panda.buildinfo.json +10 -8
- package/dist/styles.css +35 -29
- package/es/Article/Article.js +3 -3
- package/es/Article/ArticleByline.js +5 -4
- package/es/Article/index.js +1 -2
- package/es/AudioPlayer/AudioPlayer.js +1 -1
- package/es/CampaignBlock/CampaignBlock.js +25 -13
- package/es/Concept/Concept.js +7 -1
- package/es/ContactBlock/ContactBlock.js +0 -1
- package/es/ContentTypeBadge/ContentTypeBadgeNew.js +0 -3
- package/es/ContentTypeHero/ContentTypeHero.js +2 -8
- package/es/Embed/AudioEmbed.js +3 -0
- package/es/Embed/BrightcoveEmbed.js +5 -1
- package/es/Embed/ConceptEmbed.js +23 -11
- package/es/Embed/ConceptListEmbed.js +2 -1
- package/es/Embed/ImageEmbed.js +3 -0
- package/es/Embed/index.js +1 -0
- package/es/FileList/FileList.js +5 -1
- package/es/FileList/PdfFile.js +6 -1
- package/es/FileList/index.js +1 -1
- package/es/Grid/Grid.js +0 -1
- package/es/LicenseByline/EmbedByline.js +4 -1
- package/es/TreeStructure/TreeStructure.js +0 -2
- package/es/i18n/index.js +1 -1
- package/es/i18n/useComponentTranslations.js +62 -0
- package/es/index.js +7 -5
- package/es/locale/messages-en.js +31 -5
- package/es/locale/messages-nb.js +31 -5
- package/es/locale/messages-nn.js +79 -53
- package/es/locale/messages-se.js +31 -5
- package/es/locale/messages-sma.js +31 -5
- package/es/styles.css +35 -29
- package/es/utils/licenseAttributes.js +18 -0
- package/lib/Article/Article.js +3 -3
- package/lib/Article/ArticleByline.js +5 -4
- package/lib/Article/index.d.ts +0 -1
- package/lib/Article/index.js +1 -8
- package/lib/AudioPlayer/AudioPlayer.js +1 -1
- package/lib/CampaignBlock/CampaignBlock.js +25 -13
- package/lib/Concept/Concept.d.ts +2 -0
- package/lib/Concept/Concept.js +7 -1
- package/lib/ContactBlock/ContactBlock.js +0 -1
- package/lib/ContentTypeBadge/ContentTypeBadgeNew.js +0 -3
- package/lib/ContentTypeHero/ContentTypeHero.js +2 -7
- package/lib/Embed/AudioEmbed.js +3 -0
- package/lib/Embed/BrightcoveEmbed.d.ts +2 -1
- package/lib/Embed/BrightcoveEmbed.js +5 -1
- package/lib/Embed/ConceptEmbed.d.ts +3 -1
- package/lib/Embed/ConceptEmbed.js +23 -11
- package/lib/Embed/ConceptListEmbed.js +2 -1
- package/lib/Embed/ImageEmbed.js +3 -0
- package/lib/Embed/index.d.ts +1 -0
- package/lib/Embed/index.js +7 -0
- package/lib/FileList/FileList.d.ts +3 -1
- package/lib/FileList/FileList.js +5 -1
- package/lib/FileList/PdfFile.js +6 -1
- package/lib/FileList/index.d.ts +1 -1
- package/lib/FileList/index.js +6 -0
- package/lib/Grid/Grid.js +0 -1
- package/lib/LicenseByline/EmbedByline.js +4 -1
- package/lib/TreeStructure/TreeStructure.js +0 -2
- package/lib/i18n/index.d.ts +1 -1
- package/lib/i18n/index.js +12 -0
- package/lib/i18n/useComponentTranslations.d.ts +31 -0
- package/lib/i18n/useComponentTranslations.js +65 -2
- package/lib/index.d.ts +6 -4
- package/lib/index.js +38 -6
- package/lib/locale/messages-en.d.ts +26 -0
- package/lib/locale/messages-en.js +31 -5
- package/lib/locale/messages-nb.d.ts +26 -0
- package/lib/locale/messages-nb.js +31 -5
- package/lib/locale/messages-nn.d.ts +26 -0
- package/lib/locale/messages-nn.js +79 -53
- package/lib/locale/messages-se.d.ts +26 -0
- package/lib/locale/messages-se.js +31 -5
- package/lib/locale/messages-sma.d.ts +26 -0
- package/lib/locale/messages-sma.js +31 -5
- package/lib/styles.css +35 -29
- package/lib/utils/licenseAttributes.d.ts +16 -0
- package/lib/utils/licenseAttributes.js +25 -0
- package/package.json +8 -8
- package/src/Article/Article.tsx +7 -6
- package/src/Article/ArticleByline.tsx +2 -3
- package/src/Article/index.ts +0 -2
- package/src/AudioPlayer/AudioPlayer.tsx +5 -3
- package/src/CampaignBlock/CampaignBlock.tsx +23 -12
- package/src/Concept/Concept.tsx +8 -3
- package/src/ContactBlock/ContactBlock.tsx +0 -1
- package/src/ContentTypeBadge/ContentTypeBadgeNew.tsx +0 -3
- package/src/ContentTypeHero/ContentTypeHero.tsx +2 -7
- package/src/Embed/AudioEmbed.tsx +4 -1
- package/src/Embed/BrightcoveEmbed.tsx +6 -3
- package/src/Embed/ConceptEmbed.tsx +21 -11
- package/src/Embed/ConceptListEmbed.tsx +1 -0
- package/src/Embed/ImageEmbed.tsx +4 -0
- package/src/Embed/index.ts +1 -0
- package/src/FileList/FileList.tsx +16 -10
- package/src/FileList/PdfFile.tsx +8 -2
- package/src/FileList/index.ts +1 -1
- package/src/Grid/Grid.tsx +0 -1
- package/src/LicenseByline/EmbedByline.tsx +2 -1
- package/src/TreeStructure/TreeStructure.tsx +0 -1
- package/src/i18n/index.ts +2 -0
- package/src/i18n/useComponentTranslations.ts +79 -0
- package/src/index.ts +8 -2
- package/src/locale/messages-en.ts +30 -3
- package/src/locale/messages-nb.ts +30 -3
- package/src/locale/messages-nn.ts +78 -51
- package/src/locale/messages-se.ts +30 -3
- package/src/locale/messages-sma.ts +30 -3
- package/src/utils/licenseAttributes.ts +23 -0
- package/es/Article/ArticleParagraph.js +0 -23
- package/lib/Article/ArticleParagraph.d.ts +0 -13
- package/lib/Article/ArticleParagraph.js +0 -30
- package/src/Article/ArticleParagraph.tsx +0 -27
package/lib/styles.css
CHANGED
|
@@ -93,10 +93,6 @@
|
|
|
93
93
|
display: flex;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
.gap_xxlarge {
|
|
97
|
-
gap: var(--spacing-xxlarge);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
96
|
.c_text\.default {
|
|
101
97
|
color: var(--colors-text-default);
|
|
102
98
|
}
|
|
@@ -121,6 +117,10 @@
|
|
|
121
117
|
padding-block-start: var(--spacing-xxlarge);
|
|
122
118
|
}
|
|
123
119
|
|
|
120
|
+
.gap_xxlarge {
|
|
121
|
+
gap: var(--spacing-xxlarge);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
124
|
.min-h_xxlarge {
|
|
125
125
|
min-height: var(--sizes-xxlarge);
|
|
126
126
|
}
|
|
@@ -326,10 +326,18 @@
|
|
|
326
326
|
text-decoration: underline;
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
.d_grid {
|
|
330
|
+
display: grid;
|
|
331
|
+
}
|
|
332
|
+
|
|
329
333
|
.h_215px {
|
|
330
334
|
height: 215px;
|
|
331
335
|
}
|
|
332
336
|
|
|
337
|
+
.min-w_270px {
|
|
338
|
+
min-width: 270px;
|
|
339
|
+
}
|
|
340
|
+
|
|
333
341
|
.bd-l_4px_solid {
|
|
334
342
|
border-left: 4px solid;
|
|
335
343
|
}
|
|
@@ -438,6 +446,10 @@
|
|
|
438
446
|
width: var(--sizes-surface-xlarge);
|
|
439
447
|
}
|
|
440
448
|
|
|
449
|
+
.max-h_50vh {
|
|
450
|
+
max-height: 50vh;
|
|
451
|
+
}
|
|
452
|
+
|
|
441
453
|
.c_text\.error {
|
|
442
454
|
color: var(--colors-text-error);
|
|
443
455
|
}
|
|
@@ -539,14 +551,6 @@
|
|
|
539
551
|
margin-block-start: var(--spacing-3xsmall);
|
|
540
552
|
}
|
|
541
553
|
|
|
542
|
-
.d_grid {
|
|
543
|
-
display: grid;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
.max-w_surface\.4xlarge {
|
|
547
|
-
max-width: var(--sizes-surface-4xlarge);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
554
|
.w_surface\.3xsmall {
|
|
551
555
|
width: var(--sizes-surface-3xsmall);
|
|
552
556
|
}
|
|
@@ -678,12 +682,12 @@
|
|
|
678
682
|
align-items: flex-end;
|
|
679
683
|
}
|
|
680
684
|
|
|
681
|
-
.
|
|
682
|
-
|
|
685
|
+
.grid-tc_1fr {
|
|
686
|
+
grid-template-columns: 1fr;
|
|
683
687
|
}
|
|
684
688
|
|
|
685
|
-
.
|
|
686
|
-
|
|
689
|
+
.fw_bold {
|
|
690
|
+
font-weight: var(--font-weights-bold);
|
|
687
691
|
}
|
|
688
692
|
|
|
689
693
|
.bd-l-c_stroke\.default {
|
|
@@ -722,6 +726,10 @@
|
|
|
722
726
|
top: calc(var(--spacing-4xsmall) * -1);
|
|
723
727
|
}
|
|
724
728
|
|
|
729
|
+
.ov-y_auto {
|
|
730
|
+
overflow-y: auto;
|
|
731
|
+
}
|
|
732
|
+
|
|
725
733
|
.bg-c_surface\.disabled {
|
|
726
734
|
background-color: var(--colors-surface-disabled);
|
|
727
735
|
}
|
|
@@ -900,14 +908,6 @@
|
|
|
900
908
|
padding-block-end: var(--spacing-5xlarge);
|
|
901
909
|
}
|
|
902
910
|
|
|
903
|
-
.\[\&\[data-align\=\"center\"\]\]\:ta_center[data-align="center"] {
|
|
904
|
-
text-align: center;
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
.\[\&\:has\(span\[dir\=\"rtl\"\]\)\]\:direction_rtl:has(span[dir="rtl"]) {
|
|
908
|
-
direction: rtl;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
911
|
.\[\&_img\]\:w_100\% img {
|
|
912
912
|
width: 100%;
|
|
913
913
|
}
|
|
@@ -1448,9 +1448,6 @@
|
|
|
1448
1448
|
}
|
|
1449
1449
|
|
|
1450
1450
|
@media screen and (min-width: 29.75rem) {
|
|
1451
|
-
.mobileWide\:h_340px {
|
|
1452
|
-
height: 340px;
|
|
1453
|
-
}
|
|
1454
1451
|
.mobileWide\:d_none {
|
|
1455
1452
|
display: none;
|
|
1456
1453
|
}
|
|
@@ -1465,6 +1462,9 @@
|
|
|
1465
1462
|
@media screen and (min-width: 37.5625rem) {
|
|
1466
1463
|
.tablet\:px_medium {
|
|
1467
1464
|
padding-inline: var(--spacing-medium);
|
|
1465
|
+
}
|
|
1466
|
+
.tablet\:h_265px {
|
|
1467
|
+
height: 265px;
|
|
1468
1468
|
}
|
|
1469
1469
|
.tablet\:h_26px {
|
|
1470
1470
|
height: 26px;
|
|
@@ -1544,8 +1544,8 @@
|
|
|
1544
1544
|
.tabletWide\:max-w_532px {
|
|
1545
1545
|
max-width: 532px;
|
|
1546
1546
|
}
|
|
1547
|
-
.tabletWide\:
|
|
1548
|
-
|
|
1547
|
+
.tabletWide\:h_340px {
|
|
1548
|
+
height: 340px;
|
|
1549
1549
|
}
|
|
1550
1550
|
.tabletWide\:d_block {
|
|
1551
1551
|
display: block;
|
|
@@ -1570,6 +1570,12 @@
|
|
|
1570
1570
|
}
|
|
1571
1571
|
.tabletWide\:jc_space-between {
|
|
1572
1572
|
justify-content: space-between;
|
|
1573
|
+
}
|
|
1574
|
+
.tabletWide\:grid-tc_minmax\(230px\,_455px\)_auto {
|
|
1575
|
+
grid-template-columns: minmax(230px, 455px) auto;
|
|
1576
|
+
}
|
|
1577
|
+
.tabletWide\:grid-tc_auto_minmax\(230px\,_455px\) {
|
|
1578
|
+
grid-template-columns: auto minmax(230px, 455px);
|
|
1573
1579
|
}
|
|
1574
1580
|
}
|
|
1575
1581
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2024-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
|
+
export declare const licenseAttributes: (license: string | undefined, lang: string | undefined, url: string | undefined) => {
|
|
9
|
+
"xmlns:cc": string;
|
|
10
|
+
"xmlns:dct": string;
|
|
11
|
+
about: string | undefined;
|
|
12
|
+
} | {
|
|
13
|
+
"xmlns:cc"?: undefined;
|
|
14
|
+
"xmlns:dct"?: undefined;
|
|
15
|
+
about?: undefined;
|
|
16
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.licenseAttributes = void 0;
|
|
7
|
+
var _licenses = require("@ndla/licenses");
|
|
8
|
+
/**
|
|
9
|
+
* Copyright (c) 2024-present, NDLA.
|
|
10
|
+
*
|
|
11
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
12
|
+
* LICENSE file in the root directory of this source tree.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const licenseAttributes = (license, lang, url) => {
|
|
17
|
+
const licenseAbbr = (0, _licenses.getLicenseByAbbreviation)(license ? license : "", lang);
|
|
18
|
+
const licenseProps = (0, _licenses.isCreativeCommonsLicense)(licenseAbbr.rights) ? {
|
|
19
|
+
"xmlns:cc": "https://creativecommons.org/ns#",
|
|
20
|
+
"xmlns:dct": "http://purl.org/dc/terms/",
|
|
21
|
+
about: url ?? undefined
|
|
22
|
+
} : {};
|
|
23
|
+
return licenseProps;
|
|
24
|
+
};
|
|
25
|
+
exports.licenseAttributes = licenseAttributes;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ndla/ui",
|
|
3
|
-
"version": "56.0.
|
|
3
|
+
"version": "56.0.20-alpha.0",
|
|
4
4
|
"description": "UI component library for NDLA",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@ndla/core": "^5.0.2",
|
|
37
|
-
"@ndla/icons": "^8.0.
|
|
38
|
-
"@ndla/licenses": "^8.0.
|
|
39
|
-
"@ndla/primitives": "^1.0.
|
|
40
|
-
"@ndla/safelink": "^7.0.
|
|
41
|
-
"@ndla/styled-system": "^0.0.
|
|
37
|
+
"@ndla/icons": "^8.0.14-alpha.0",
|
|
38
|
+
"@ndla/licenses": "^8.0.2-alpha.0",
|
|
39
|
+
"@ndla/primitives": "^1.0.18-alpha.0",
|
|
40
|
+
"@ndla/safelink": "^7.0.18-alpha.0",
|
|
41
|
+
"@ndla/styled-system": "^0.0.16",
|
|
42
42
|
"@ndla/util": "^4.1.0",
|
|
43
43
|
"html-react-parser": "^5.1.8",
|
|
44
44
|
"i18next-browser-languagedetector": "^7.1.0"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"react-router-dom": "> 6.0.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@ndla/preset-panda": "^0.0.
|
|
56
|
+
"@ndla/preset-panda": "^0.0.24",
|
|
57
57
|
"@ndla/types-backend": "^0.2.86",
|
|
58
58
|
"@ndla/types-embed": "^5.0.1-alpha.0",
|
|
59
59
|
"@pandacss/dev": "^0.45.2",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"publishConfig": {
|
|
67
67
|
"access": "public"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "66b3b382188ec1730fa409d4adb3672942f00670"
|
|
70
70
|
}
|
package/src/Article/Article.tsx
CHANGED
|
@@ -32,7 +32,6 @@ const StyledArticleWrapper = styled(
|
|
|
32
32
|
background: "background.default",
|
|
33
33
|
display: "flex",
|
|
34
34
|
flexDirection: "column",
|
|
35
|
-
gap: "xxlarge",
|
|
36
35
|
color: "text.default",
|
|
37
36
|
alignItems: "center",
|
|
38
37
|
width: "100%",
|
|
@@ -131,11 +130,13 @@ export const ArticleTitle = ({
|
|
|
131
130
|
return (
|
|
132
131
|
<ArticleHeader>
|
|
133
132
|
<ArticleHGroup>
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
{(!!contentType || !!heartButton) && (
|
|
134
|
+
<StyledStack justify="space-between" align="center" direction="row" gap="small">
|
|
135
|
+
{!!contentType && <ContentTypeBadgeNew contentType={contentType} />}
|
|
136
|
+
{heartButton}
|
|
137
|
+
</StyledStack>
|
|
138
|
+
)}
|
|
139
|
+
<Heading textStyle="heading.medium" id={id} lang={lang} property="dct:title">
|
|
139
140
|
{title}
|
|
140
141
|
</Heading>
|
|
141
142
|
</ArticleHGroup>
|
|
@@ -36,8 +36,6 @@ const Wrapper = styled("div", {
|
|
|
36
36
|
},
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
// TODO: This is designed with 24px of inline padding. If you do this, most bylines will break into two lines.
|
|
40
|
-
// Should reconsider.
|
|
41
39
|
const TextWrapper = styled("div", {
|
|
42
40
|
base: {
|
|
43
41
|
display: "flex",
|
|
@@ -169,7 +167,8 @@ export const ArticleByline = ({
|
|
|
169
167
|
<LicenseWrapper>
|
|
170
168
|
{license && <LicenseLink license={license} />}
|
|
171
169
|
{showPrimaryContributors && (
|
|
172
|
-
|
|
170
|
+
//eslint-disable-next-line react/no-unknown-property
|
|
171
|
+
<span property="cc:attributionName">
|
|
173
172
|
{authors.length > 0 &&
|
|
174
173
|
`${t("article.authorsLabel", {
|
|
175
174
|
names: renderContributors(authors, t),
|
package/src/Article/index.ts
CHANGED
|
@@ -190,9 +190,11 @@ const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersi
|
|
|
190
190
|
{showFullDescription || description.length < DESCRIPTION_MAX_LENGTH
|
|
191
191
|
? description
|
|
192
192
|
: `${truncatedDescription}...`}
|
|
193
|
-
|
|
194
|
-
{
|
|
195
|
-
|
|
193
|
+
{description.length > DESCRIPTION_MAX_LENGTH && (
|
|
194
|
+
<Button variant="link" onClick={() => setShowFullDescription((p) => !p)}>
|
|
195
|
+
{t(`audio.${showFullDescription ? "readLessDescriptionLabel" : "readMoreDescriptionLabel"}`)}
|
|
196
|
+
</Button>
|
|
197
|
+
)}
|
|
196
198
|
</Text>
|
|
197
199
|
)}
|
|
198
200
|
{!!textVersion && !!img && textVersionButton}
|
|
@@ -36,21 +36,33 @@ interface Props {
|
|
|
36
36
|
|
|
37
37
|
const Container = styled("div", {
|
|
38
38
|
base: {
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
display: "grid",
|
|
40
|
+
gridTemplateColumns: "1fr",
|
|
41
41
|
gap: "medium",
|
|
42
|
-
flexDirection: "column",
|
|
43
42
|
border: "1px solid",
|
|
44
43
|
borderColor: "stroke.default",
|
|
45
44
|
backgroundColor: "background.default",
|
|
46
45
|
borderRadius: "xsmall",
|
|
47
46
|
boxShadow: "full",
|
|
48
|
-
marginBlockEnd: "4xsmall",
|
|
49
47
|
overflow: "hidden",
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
},
|
|
49
|
+
variants: {
|
|
50
|
+
imageSide: {
|
|
51
|
+
left: {
|
|
52
|
+
tabletWide: {
|
|
53
|
+
gridTemplateColumns: "minmax(230px, 455px) auto", //required for campaign block in myNdla
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
right: {
|
|
57
|
+
tabletWide: {
|
|
58
|
+
gridTemplateColumns: "auto minmax(230px, 455px)", //required for campaign block in myNdla
|
|
59
|
+
},
|
|
60
|
+
},
|
|
52
61
|
},
|
|
53
62
|
},
|
|
63
|
+
defaultVariants: {
|
|
64
|
+
imageSide: "left",
|
|
65
|
+
},
|
|
54
66
|
});
|
|
55
67
|
|
|
56
68
|
const LinkText = styled(Text, {
|
|
@@ -78,15 +90,14 @@ const LinkHeader = styled(Text, {
|
|
|
78
90
|
|
|
79
91
|
const StyledImg = styled("img", {
|
|
80
92
|
base: {
|
|
81
|
-
alignSelf: "center",
|
|
82
93
|
objectFit: "cover",
|
|
83
94
|
width: "100%",
|
|
84
95
|
height: "215px",
|
|
85
|
-
|
|
86
|
-
height: "
|
|
96
|
+
tablet: {
|
|
97
|
+
height: "265px",
|
|
87
98
|
},
|
|
88
99
|
tabletWide: {
|
|
89
|
-
|
|
100
|
+
height: "340px",
|
|
90
101
|
},
|
|
91
102
|
},
|
|
92
103
|
});
|
|
@@ -94,7 +105,6 @@ const StyledImg = styled("img", {
|
|
|
94
105
|
const ContentWrapper = styled("div", {
|
|
95
106
|
base: {
|
|
96
107
|
width: "100%",
|
|
97
|
-
position: "relative",
|
|
98
108
|
display: "flex",
|
|
99
109
|
flexDirection: "column",
|
|
100
110
|
gap: "medium",
|
|
@@ -102,6 +112,7 @@ const ContentWrapper = styled("div", {
|
|
|
102
112
|
justifyContent: "center",
|
|
103
113
|
paddingBlock: "medium",
|
|
104
114
|
paddingInline: "medium",
|
|
115
|
+
minWidth: "270px", //required for campaign block in myNdla
|
|
105
116
|
},
|
|
106
117
|
});
|
|
107
118
|
|
|
@@ -147,7 +158,7 @@ const CampaignBlock = ({
|
|
|
147
158
|
const imageComponent = image && <StyledImg src={`${image.src}?width=455`} height={340} width={455} alt={image.alt} />;
|
|
148
159
|
const HeaderComponent = url?.url ? LinkHeader : Text;
|
|
149
160
|
return (
|
|
150
|
-
<Container className={className} data-embed-type="campaign-block">
|
|
161
|
+
<Container className={className} data-embed-type="campaign-block" imageSide={imageSide}>
|
|
151
162
|
{imageSide === "left" && imageComponent}
|
|
152
163
|
<ContentWrapper>
|
|
153
164
|
<MaybeLinkText url={url?.url} path={path}>
|
package/src/Concept/Concept.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import { IDraftCopyright as ConceptCopyright } from "@ndla/types-backend/concept
|
|
|
13
13
|
import { ConceptVisualElementMeta } from "@ndla/types-embed";
|
|
14
14
|
import { BrightcoveEmbed, ExternalEmbed, H5pEmbed, IframeEmbed, ImageEmbed } from "../Embed";
|
|
15
15
|
import { EmbedByline } from "../LicenseByline/EmbedByline";
|
|
16
|
+
import { licenseAttributes } from "../utils/licenseAttributes";
|
|
16
17
|
|
|
17
18
|
export interface ConceptProps extends ComponentPropsWithRef<"figure"> {
|
|
18
19
|
copyright?: ConceptCopyright;
|
|
@@ -20,6 +21,8 @@ export interface ConceptProps extends ComponentPropsWithRef<"figure"> {
|
|
|
20
21
|
lang?: string;
|
|
21
22
|
title?: string;
|
|
22
23
|
children?: ReactNode;
|
|
24
|
+
source?: string;
|
|
25
|
+
previewAlt?: boolean;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
const StyledFigure = styled(Figure, {
|
|
@@ -43,9 +46,11 @@ const ContentWrapper = styled("div", {
|
|
|
43
46
|
// TODO: Figure out if we need to support headerButtons.
|
|
44
47
|
|
|
45
48
|
export const Concept = forwardRef<HTMLElement, ConceptProps>(
|
|
46
|
-
({ copyright, visualElement, lang, children, title, ...rest }, ref) => {
|
|
49
|
+
({ copyright, visualElement, lang, children, title, source, previewAlt, ...rest }, ref) => {
|
|
50
|
+
const licenseProps = licenseAttributes(copyright?.license?.license, lang, source);
|
|
51
|
+
|
|
47
52
|
return (
|
|
48
|
-
<StyledFigure ref={ref} {...rest}>
|
|
53
|
+
<StyledFigure ref={ref} {...rest} {...licenseProps}>
|
|
49
54
|
<ContentWrapper lang={lang}>
|
|
50
55
|
{!!title && (
|
|
51
56
|
<>
|
|
@@ -56,7 +61,7 @@ export const Concept = forwardRef<HTMLElement, ConceptProps>(
|
|
|
56
61
|
{children}
|
|
57
62
|
</ContentWrapper>
|
|
58
63
|
{visualElement?.resource === "image" ? (
|
|
59
|
-
<ImageEmbed embed={visualElement} lang={lang} />
|
|
64
|
+
<ImageEmbed embed={visualElement} lang={lang} previewAlt={previewAlt} />
|
|
60
65
|
) : visualElement?.resource === "brightcove" ? (
|
|
61
66
|
<BrightcoveEmbed embed={visualElement} />
|
|
62
67
|
) : visualElement?.resource === "h5p" ? (
|
|
@@ -42,12 +42,9 @@ export const contentTypeToBadgeVariantMap: Record<ContentType, BadgeVariant> = {
|
|
|
42
42
|
[contentTypes.SOURCE_MATERIAL]: "brand1",
|
|
43
43
|
[contentTypes.LEARNING_PATH]: "brand3",
|
|
44
44
|
[contentTypes.TOPIC]: "neutral",
|
|
45
|
-
// TODO: Verify this color
|
|
46
45
|
[contentTypes.MULTIDISCIPLINARY]: "neutral",
|
|
47
46
|
[contentTypes.CONCEPT]: "brand1",
|
|
48
|
-
// TODO: Verify this color
|
|
49
47
|
[contentTypes.EXTERNAL]: "brand2",
|
|
50
|
-
// TODO: Verify resourceEmbedTypeMapping colors
|
|
51
48
|
[contentTypes.IMAGE]: "brand1",
|
|
52
49
|
[contentTypes.AUDIO]: "brand1",
|
|
53
50
|
[contentTypes.PODCAST]: "brand1",
|
|
@@ -11,23 +11,18 @@ import { Hero, HeroProps, HeroVariant } from "@ndla/primitives";
|
|
|
11
11
|
import { ContentType } from "../ContentTypeBadge/ContentTypeBadgeNew";
|
|
12
12
|
import * as contentTypes from "../model/ContentType";
|
|
13
13
|
|
|
14
|
-
// TODO: Figure out what to do with frontpage articles. If anything...
|
|
15
|
-
// Also, verify all of these colors.
|
|
16
14
|
export const contentTypeToHeroMap: Record<ContentType, HeroVariant> = {
|
|
17
15
|
[contentTypes.SUBJECT_MATERIAL]: "primary",
|
|
18
|
-
[contentTypes.TASKS_AND_ACTIVITIES]: "
|
|
16
|
+
[contentTypes.TASKS_AND_ACTIVITIES]: "brand2Bold",
|
|
19
17
|
[contentTypes.ASSESSMENT_RESOURCES]: "brand2",
|
|
20
18
|
// This will never happen
|
|
21
19
|
[contentTypes.SUBJECT]: "primary",
|
|
22
20
|
[contentTypes.SOURCE_MATERIAL]: "brand1",
|
|
23
21
|
// This will never happen
|
|
24
22
|
[contentTypes.LEARNING_PATH]: "primary",
|
|
25
|
-
// TODO: This needs a color
|
|
26
23
|
[contentTypes.TOPIC]: "neutral",
|
|
27
|
-
|
|
28
|
-
[contentTypes.MULTIDISCIPLINARY]: "brand4",
|
|
24
|
+
[contentTypes.MULTIDISCIPLINARY]: "primary",
|
|
29
25
|
[contentTypes.CONCEPT]: "brand1Subtle",
|
|
30
|
-
// TODO: No clue what this'll be. Maybe unused?
|
|
31
26
|
[contentTypes.EXTERNAL]: "primary",
|
|
32
27
|
[contentTypes.IMAGE]: "primary",
|
|
33
28
|
[contentTypes.AUDIO]: "primary",
|
package/src/Embed/AudioEmbed.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import EmbedErrorPlaceholder from "./EmbedErrorPlaceholder";
|
|
|
12
12
|
import { Author } from "./ImageEmbed";
|
|
13
13
|
import AudioPlayer from "../AudioPlayer";
|
|
14
14
|
import { EmbedByline } from "../LicenseByline";
|
|
15
|
+
import { licenseAttributes } from "../utils/licenseAttributes";
|
|
15
16
|
|
|
16
17
|
interface Props {
|
|
17
18
|
embed: AudioMetaData;
|
|
@@ -42,8 +43,10 @@ const AudioEmbed = ({ embed, lang }: Props) => {
|
|
|
42
43
|
|
|
43
44
|
const img = coverPhoto && { url: coverPhoto.url, alt: coverPhoto.altText };
|
|
44
45
|
|
|
46
|
+
const licenseProps = licenseAttributes(data.copyright.license.license, lang, embedData.url);
|
|
47
|
+
|
|
45
48
|
return (
|
|
46
|
-
<Figure lang={lang} data-embed-type={type}>
|
|
49
|
+
<Figure lang={lang} data-embed-type={type} {...licenseProps}>
|
|
47
50
|
<AudioPlayer
|
|
48
51
|
description={data.podcastMeta?.introduction ?? ""}
|
|
49
52
|
img={img}
|
|
@@ -15,10 +15,12 @@ import { BrightcoveEmbedData, BrightcoveMetaData, BrightcoveVideoSource } from "
|
|
|
15
15
|
import EmbedErrorPlaceholder from "./EmbedErrorPlaceholder";
|
|
16
16
|
import { RenderContext } from "./types";
|
|
17
17
|
import { EmbedByline } from "../LicenseByline";
|
|
18
|
+
import { licenseAttributes } from "../utils/licenseAttributes";
|
|
18
19
|
|
|
19
20
|
interface Props {
|
|
20
21
|
embed: BrightcoveMetaData;
|
|
21
22
|
renderContext?: RenderContext;
|
|
23
|
+
lang?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const LinkedVideoButton = styled(Button, {
|
|
@@ -54,7 +56,7 @@ const getIframeProps = (data: BrightcoveEmbedData, sources: BrightcoveVideoSourc
|
|
|
54
56
|
width: source?.width ?? "640",
|
|
55
57
|
};
|
|
56
58
|
};
|
|
57
|
-
const BrightcoveEmbed = ({ embed, renderContext = "article" }: Props) => {
|
|
59
|
+
const BrightcoveEmbed = ({ embed, renderContext = "article", lang }: Props) => {
|
|
58
60
|
const [showOriginalVideo, setShowOriginalVideo] = useState(true);
|
|
59
61
|
const { t } = useTranslation();
|
|
60
62
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
@@ -100,8 +102,10 @@ const BrightcoveEmbed = ({ embed, renderContext = "article" }: Props) => {
|
|
|
100
102
|
? getIframeProps({ ...embedData, videoid: linkedVideoId }, data.sources)
|
|
101
103
|
: undefined;
|
|
102
104
|
|
|
105
|
+
const licenseProps = licenseAttributes(data?.copyright?.license.license, lang, embedData.pageUrl);
|
|
106
|
+
|
|
103
107
|
return (
|
|
104
|
-
<Figure data-embed-type="brightcove">
|
|
108
|
+
<Figure data-embed-type="brightcove" {...licenseProps}>
|
|
105
109
|
<div className="brightcove-video">
|
|
106
110
|
<BrightcoveIframe
|
|
107
111
|
ref={iframeRef}
|
|
@@ -114,7 +118,6 @@ const BrightcoveEmbed = ({ embed, renderContext = "article" }: Props) => {
|
|
|
114
118
|
/>
|
|
115
119
|
</div>
|
|
116
120
|
<EmbedByline type="video" copyright={data.copyright!} description={parsedDescription}>
|
|
117
|
-
{/* TODO: Figure out if this button should still be here. If yes, figure out what it should look like. */}
|
|
118
121
|
{!!linkedVideoId && (
|
|
119
122
|
<LinkedVideoButton size="small" variant="secondary" onClick={() => setShowOriginalVideo((p) => !p)}>
|
|
120
123
|
{t(`figure.button.${!showOriginalVideo ? "original" : "alternative"}`)}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import parse from "html-react-parser";
|
|
10
10
|
import { forwardRef, useMemo } from "react";
|
|
11
|
+
import { Portal } from "@ark-ui/react";
|
|
11
12
|
import { PopoverContent, PopoverRoot, PopoverTrigger } from "@ndla/primitives";
|
|
12
13
|
import { styled } from "@ndla/styled-system/jsx";
|
|
13
14
|
import { ConceptMetaData } from "@ndla/types-embed";
|
|
@@ -20,6 +21,7 @@ import { Concept, ConceptProps } from "../Concept/Concept";
|
|
|
20
21
|
interface BaseProps {
|
|
21
22
|
renderContext?: RenderContext;
|
|
22
23
|
lang?: string;
|
|
24
|
+
previewAlt?: boolean;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
interface Props extends BaseProps {
|
|
@@ -29,10 +31,12 @@ interface Props extends BaseProps {
|
|
|
29
31
|
const StyledPopoverContent = styled(PopoverContent, {
|
|
30
32
|
base: {
|
|
31
33
|
width: "surface.xlarge",
|
|
34
|
+
maxHeight: "50vh",
|
|
35
|
+
overflowY: "auto",
|
|
32
36
|
},
|
|
33
37
|
});
|
|
34
38
|
|
|
35
|
-
export const ConceptEmbed = ({ embed, renderContext, lang }: Props) => {
|
|
39
|
+
export const ConceptEmbed = ({ embed, renderContext, lang, previewAlt }: Props) => {
|
|
36
40
|
const parsedContent = useMemo(() => {
|
|
37
41
|
if (embed.status === "error" || !embed.data.concept.content) return undefined;
|
|
38
42
|
return parse(embed.data.concept.content.htmlContent);
|
|
@@ -55,11 +59,13 @@ export const ConceptEmbed = ({ embed, renderContext, lang }: Props) => {
|
|
|
55
59
|
if (embed.embedData.type === "inline") {
|
|
56
60
|
return (
|
|
57
61
|
<InlineConcept
|
|
62
|
+
previewAlt={previewAlt}
|
|
58
63
|
linkText={embed.embedData.linkText}
|
|
59
64
|
copyright={concept.copyright}
|
|
60
65
|
visualElement={visualElement}
|
|
61
66
|
lang={lang}
|
|
62
67
|
title={concept.title.title}
|
|
68
|
+
source={concept.source}
|
|
63
69
|
>
|
|
64
70
|
{parsedContent}
|
|
65
71
|
</InlineConcept>
|
|
@@ -68,10 +74,12 @@ export const ConceptEmbed = ({ embed, renderContext, lang }: Props) => {
|
|
|
68
74
|
|
|
69
75
|
return (
|
|
70
76
|
<BlockConcept
|
|
77
|
+
previewAlt={previewAlt}
|
|
71
78
|
copyright={concept.copyright}
|
|
72
79
|
visualElement={visualElement}
|
|
73
80
|
lang={lang}
|
|
74
81
|
title={renderContext === "embed" ? undefined : concept.title.title}
|
|
82
|
+
source={concept.source}
|
|
75
83
|
>
|
|
76
84
|
{parsedContent}
|
|
77
85
|
</BlockConcept>
|
|
@@ -80,21 +88,23 @@ export const ConceptEmbed = ({ embed, renderContext, lang }: Props) => {
|
|
|
80
88
|
|
|
81
89
|
export interface InlineConceptProps extends ConceptProps, BaseProps {
|
|
82
90
|
linkText?: string;
|
|
91
|
+
source?: string;
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
export const InlineConcept = forwardRef<HTMLSpanElement, InlineConceptProps>(
|
|
86
|
-
({ linkText, copyright, visualElement, lang, children, title, ...rest }, ref) => (
|
|
95
|
+
({ linkText, copyright, visualElement, lang, children, title, source, ...rest }, ref) => (
|
|
87
96
|
<PopoverRoot>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
</InlineTriggerButton>
|
|
97
|
+
{/* @ts-expect-error placing ref and rest on popover trigger somehow removes a bug where the popover target becomes a bit bigger */}
|
|
98
|
+
<PopoverTrigger asChild ref={ref} {...rest}>
|
|
99
|
+
<InlineTriggerButton>{linkText}</InlineTriggerButton>
|
|
92
100
|
</PopoverTrigger>
|
|
93
|
-
<
|
|
94
|
-
<
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
<Portal>
|
|
102
|
+
<StyledPopoverContent>
|
|
103
|
+
<Concept copyright={copyright} visualElement={visualElement} lang={lang} title={title} source={source}>
|
|
104
|
+
{children}
|
|
105
|
+
</Concept>
|
|
106
|
+
</StyledPopoverContent>
|
|
107
|
+
</Portal>
|
|
98
108
|
</PopoverRoot>
|
|
99
109
|
),
|
|
100
110
|
);
|
package/src/Embed/ImageEmbed.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import { ImageEmbedData, ImageMetaData } from "@ndla/types-embed";
|
|
|
17
17
|
import EmbedErrorPlaceholder from "./EmbedErrorPlaceholder";
|
|
18
18
|
import { RenderContext } from "./types";
|
|
19
19
|
import { EmbedByline } from "../LicenseByline";
|
|
20
|
+
import { licenseAttributes } from "../utils/licenseAttributes";
|
|
20
21
|
|
|
21
22
|
interface Props {
|
|
22
23
|
embed: ImageMetaData;
|
|
@@ -247,12 +248,15 @@ const ImageEmbed = ({ embed, previewAlt, lang, renderContext = "article", childr
|
|
|
247
248
|
setImageSizes((sizes) => (!sizes ? expandedSizes : undefined));
|
|
248
249
|
};
|
|
249
250
|
|
|
251
|
+
const licenseProps = licenseAttributes(data.copyright.license.license, lang, embedData.url);
|
|
252
|
+
|
|
250
253
|
// TODO: Check how this works with `children`. Will only be important for ED
|
|
251
254
|
return (
|
|
252
255
|
<StyledFigure
|
|
253
256
|
float={figureProps?.float}
|
|
254
257
|
size={imageSizes ? "full" : figureProps?.size ?? "medium"}
|
|
255
258
|
data-embed-type="image"
|
|
259
|
+
{...licenseProps}
|
|
256
260
|
>
|
|
257
261
|
{children}
|
|
258
262
|
<ImageWrapper border={embedData.border === "true"} expandable={!!figureProps?.float}>
|
package/src/Embed/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export { default as ImageEmbed, getCrop, getFocalPoint } from "./ImageEmbed";
|
|
10
|
+
export { InlineTriggerButton } from "./InlineTriggerButton";
|
|
10
11
|
export { default as AudioEmbed } from "./AudioEmbed";
|
|
11
12
|
export { default as H5pEmbed } from "./H5pEmbed";
|
|
12
13
|
export { default as ExternalEmbed } from "./ExternalEmbed";
|