@ndla/ui 48.0.0 → 49.0.1
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/BlogPost/BlogPost.js +6 -6
- package/es/CampaignBlock/CampaignBlock.js +8 -8
- package/es/ContactBlock/ContactBlock.js +29 -20
- package/es/CopyParagraphButton/CopyParagraphButton.js +30 -58
- package/es/CopyParagraphButton/index.js +1 -3
- package/es/Embed/BrightcoveEmbed.js +8 -6
- package/es/Embed/ImageEmbed.js +7 -5
- package/es/Embed/RelatedContentEmbed.js +3 -3
- package/es/FactBox/FactBox.js +64 -19
- package/es/FactBox/index.js +0 -1
- package/es/Figure/index.js +0 -2
- package/es/FileList/File.js +46 -24
- package/es/FileList/FileList.js +18 -14
- package/es/FileList/index.js +0 -2
- package/es/LinkBlock/LinkBlock.js +7 -7
- package/es/Messages/index.js +1 -2
- package/es/Navigation/index.js +1 -2
- package/es/RelatedArticleList/RelatedArticleList.js +80 -35
- package/es/RelatedArticleList/index.js +2 -3
- package/es/Search/index.js +0 -1
- package/es/all.css +1 -1
- package/es/i18n/i18n.js +2 -1
- package/es/index.js +9 -11
- package/es/utils/relativeUrl.js +17 -2
- package/lib/BlogPost/BlogPost.js +5 -5
- package/lib/CampaignBlock/CampaignBlock.js +7 -7
- package/lib/ContactBlock/ContactBlock.js +28 -19
- package/lib/CopyParagraphButton/CopyParagraphButton.d.ts +5 -4
- package/lib/CopyParagraphButton/CopyParagraphButton.js +29 -57
- package/lib/CopyParagraphButton/index.d.ts +1 -3
- package/lib/CopyParagraphButton/index.js +0 -14
- package/lib/Embed/BrightcoveEmbed.d.ts +3 -2
- package/lib/Embed/BrightcoveEmbed.js +8 -6
- package/lib/Embed/ImageEmbed.d.ts +3 -2
- package/lib/Embed/ImageEmbed.js +7 -5
- package/lib/Embed/RelatedContentEmbed.js +3 -3
- package/lib/Embed/index.d.ts +1 -1
- package/lib/Embed/types.d.ts +1 -0
- package/lib/FactBox/FactBox.d.ts +1 -4
- package/lib/FactBox/FactBox.js +72 -27
- package/lib/FactBox/index.d.ts +0 -1
- package/lib/FactBox/index.js +0 -7
- package/lib/Figure/index.d.ts +0 -2
- package/lib/Figure/index.js +0 -14
- package/lib/FileList/File.d.ts +22 -3
- package/lib/FileList/File.js +45 -25
- package/lib/FileList/FileList.d.ts +10 -14
- package/lib/FileList/FileList.js +17 -15
- package/lib/FileList/index.d.ts +0 -2
- package/lib/FileList/index.js +0 -14
- package/lib/LinkBlock/LinkBlock.js +6 -6
- package/lib/Messages/index.d.ts +1 -2
- package/lib/Messages/index.js +0 -7
- package/lib/Navigation/index.d.ts +1 -2
- package/lib/Navigation/index.js +0 -7
- package/lib/RelatedArticleList/RelatedArticleList.d.ts +16 -17
- package/lib/RelatedArticleList/RelatedArticleList.js +78 -35
- package/lib/RelatedArticleList/index.d.ts +2 -3
- package/lib/RelatedArticleList/index.js +2 -12
- package/lib/Search/index.d.ts +0 -1
- package/lib/Search/index.js +0 -7
- package/lib/all.css +1 -1
- package/lib/i18n/i18n.d.ts +1 -0
- package/lib/i18n/i18n.js +4 -2
- package/lib/index.d.ts +10 -12
- package/lib/index.js +9 -89
- package/lib/utils/relativeUrl.d.ts +1 -1
- package/lib/utils/relativeUrl.js +19 -4
- package/package.json +17 -17
- package/src/BlogPost/BlogPost.tsx +2 -2
- package/src/CampaignBlock/CampaignBlock.tsx +2 -2
- package/src/ContactBlock/ContactBlock.tsx +12 -6
- package/src/CopyParagraphButton/CopyParagraphButton.tsx +24 -46
- package/src/CopyParagraphButton/index.tsx +1 -3
- package/src/Embed/BrightcoveEmbed.tsx +6 -5
- package/src/Embed/ImageEmbed.tsx +14 -5
- package/src/Embed/RelatedContentEmbed.stories.tsx +9 -9
- package/src/Embed/RelatedContentEmbed.tsx +3 -3
- package/src/Embed/index.ts +1 -1
- package/src/Embed/types.ts +2 -0
- package/src/FactBox/FactBox.tsx +29 -16
- package/src/FactBox/Factbox.stories.tsx +4 -4
- package/src/FactBox/index.ts +0 -2
- package/src/Figure/index.ts +0 -2
- package/src/FileList/File.tsx +62 -32
- package/src/FileList/FileList.stories.tsx +15 -15
- package/src/FileList/FileList.tsx +21 -27
- package/src/FileList/index.ts +0 -2
- package/src/LinkBlock/LinkBlock.tsx +2 -2
- package/src/Messages/index.ts +1 -2
- package/src/Navigation/index.ts +1 -2
- package/src/RelatedArticleList/RelatedArticleList.tsx +53 -47
- package/src/RelatedArticleList/index.ts +2 -3
- package/src/Search/index.ts +0 -1
- package/src/i18n/i18n.ts +2 -1
- package/src/index.ts +11 -14
- package/src/main.scss +0 -1
- package/src/utils/__tests__/relativeUrl-test.tsx +72 -0
- package/src/utils/relativeUrl.ts +19 -2
- package/es/CopyParagraphButton/CopyParagraphButtonV2.js +0 -87
- package/es/CopyParagraphButton/initCopyParagraphButtons.js +0 -29
- package/es/FactBox/FactBoxV2.js +0 -93
- package/es/Figure/FigureBylineExpandButton.js +0 -29
- package/es/Figure/FigureExpandButton.js +0 -30
- package/es/FileList/FileListV2.js +0 -47
- package/es/FileList/FileV2.js +0 -32
- package/es/Masthead/MastheadSearchModal.js +0 -82
- package/es/Messages/MessageBoxTag.js +0 -33
- package/es/MultidisciplinarySubject/List.js +0 -52
- package/es/MultidisciplinarySubject/ListItem.js +0 -90
- package/es/MultidisciplinarySubject/MultidisciplinarySubject.js +0 -125
- package/es/MultidisciplinarySubject/index.js +0 -10
- package/es/Navigation/NavigationTopicAbout.js +0 -164
- package/es/RelatedArticleList/RelatedArticleV2.js +0 -125
- package/es/Search/ToggleSearchButton.js +0 -51
- package/es/Translation/Translation.js +0 -33
- package/es/Translation/TranslationLine.js +0 -47
- package/es/Translation/index.js +0 -2
- package/lib/CopyParagraphButton/CopyParagraphButtonV2.d.ts +0 -15
- package/lib/CopyParagraphButton/CopyParagraphButtonV2.js +0 -92
- package/lib/CopyParagraphButton/initCopyParagraphButtons.d.ts +0 -2
- package/lib/CopyParagraphButton/initCopyParagraphButtons.js +0 -38
- package/lib/FactBox/FactBoxV2.d.ts +0 -13
- package/lib/FactBox/FactBoxV2.js +0 -98
- package/lib/Figure/FigureBylineExpandButton.d.ts +0 -16
- package/lib/Figure/FigureBylineExpandButton.js +0 -35
- package/lib/Figure/FigureExpandButton.d.ts +0 -16
- package/lib/Figure/FigureExpandButton.js +0 -35
- package/lib/FileList/FileListV2.d.ts +0 -13
- package/lib/FileList/FileListV2.js +0 -52
- package/lib/FileList/FileV2.d.ts +0 -15
- package/lib/FileList/FileV2.js +0 -40
- package/lib/Masthead/MastheadSearchModal.d.ts +0 -8
- package/lib/Masthead/MastheadSearchModal.js +0 -89
- package/lib/Messages/MessageBoxTag.d.ts +0 -12
- package/lib/Messages/MessageBoxTag.js +0 -40
- package/lib/MultidisciplinarySubject/List.d.ts +0 -7
- package/lib/MultidisciplinarySubject/List.js +0 -59
- package/lib/MultidisciplinarySubject/ListItem.d.ts +0 -10
- package/lib/MultidisciplinarySubject/ListItem.js +0 -97
- package/lib/MultidisciplinarySubject/MultidisciplinarySubject.d.ts +0 -13
- package/lib/MultidisciplinarySubject/MultidisciplinarySubject.js +0 -135
- package/lib/MultidisciplinarySubject/index.d.ts +0 -9
- package/lib/MultidisciplinarySubject/index.js +0 -17
- package/lib/Navigation/NavigationTopicAbout.d.ts +0 -13
- package/lib/Navigation/NavigationTopicAbout.js +0 -171
- package/lib/RelatedArticleList/RelatedArticleV2.d.ts +0 -26
- package/lib/RelatedArticleList/RelatedArticleV2.js +0 -131
- package/lib/Search/ToggleSearchButton.d.ts +0 -14
- package/lib/Search/ToggleSearchButton.js +0 -57
- package/lib/Translation/Translation.d.ts +0 -14
- package/lib/Translation/Translation.js +0 -38
- package/lib/Translation/TranslationLine.d.ts +0 -16
- package/lib/Translation/TranslationLine.js +0 -51
- package/lib/Translation/index.d.ts +0 -2
- package/lib/Translation/index.js +0 -20
- package/src/CopyParagraphButton/CopyParagraphButtonV2.tsx +0 -85
- package/src/CopyParagraphButton/initCopyParagraphButtons.tsx +0 -27
- package/src/FactBox/FactBoxV2.tsx +0 -56
- package/src/Figure/FigureBylineExpandButton.tsx +0 -34
- package/src/Figure/FigureExpandButton.tsx +0 -35
- package/src/FileList/FileListV2.tsx +0 -58
- package/src/FileList/FileV2.tsx +0 -33
- package/src/Masthead/MastheadSearchModal.tsx +0 -101
- package/src/Messages/MessageBoxTag.tsx +0 -34
- package/src/MultidisciplinarySubject/List.tsx +0 -49
- package/src/MultidisciplinarySubject/ListItem.tsx +0 -74
- package/src/MultidisciplinarySubject/MultidisciplinarySubject.tsx +0 -117
- package/src/MultidisciplinarySubject/index.ts +0 -11
- package/src/Navigation/NavigationTopicAbout.tsx +0 -171
- package/src/RelatedArticleList/RelatedArticleV2.tsx +0 -101
- package/src/Search/ToggleSearchButton.tsx +0 -64
- package/src/Translation/Translation.tsx +0 -29
- package/src/Translation/TranslationLine.tsx +0 -42
- package/src/Translation/component.translation.scss +0 -53
- package/src/Translation/index.ts +0 -2
|
@@ -18,12 +18,13 @@ import { ButtonV2 } from '@ndla/button';
|
|
|
18
18
|
import { Figure } from '../Figure';
|
|
19
19
|
import { EmbedByline } from '../LicenseByline';
|
|
20
20
|
import EmbedErrorPlaceholder from './EmbedErrorPlaceholder';
|
|
21
|
-
import { HeartButtonType } from './types';
|
|
21
|
+
import { HeartButtonType, RenderContext } from './types';
|
|
22
22
|
|
|
23
23
|
interface Props {
|
|
24
24
|
embed: BrightcoveMetaData;
|
|
25
25
|
isConcept?: boolean;
|
|
26
26
|
heartButton?: HeartButtonType;
|
|
27
|
+
renderContext?: RenderContext;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const LinkedVideoButton = styled(ButtonV2)`
|
|
@@ -57,19 +58,19 @@ const getIframeProps = (data: BrightcoveEmbedData, sources: BrightcoveVideoSourc
|
|
|
57
58
|
width: source?.width ?? '640',
|
|
58
59
|
};
|
|
59
60
|
};
|
|
60
|
-
const BrightcoveEmbed = ({ embed, isConcept, heartButton: HeartButton }: Props) => {
|
|
61
|
+
const BrightcoveEmbed = ({ embed, isConcept, heartButton: HeartButton, renderContext = 'article' }: Props) => {
|
|
61
62
|
const [showOriginalVideo, setShowOriginalVideo] = useState(true);
|
|
62
63
|
const { t } = useTranslation();
|
|
63
64
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
64
65
|
const { embedData } = embed;
|
|
65
66
|
const fallbackTitle = `${t('embed.type.video')}: ${embedData.videoid}`;
|
|
66
67
|
const parsedDescription = useMemo(() => {
|
|
67
|
-
if (embed.embedData.caption) {
|
|
68
|
-
return parse(embed.embedData.caption);
|
|
68
|
+
if (embed.embedData.caption || renderContext === 'article') {
|
|
69
|
+
return embed.embedData.caption ? parse(embed.embedData.caption) : undefined;
|
|
69
70
|
} else if (embed.status === 'success' && embed.data.description) {
|
|
70
71
|
return parse(embed.data.description);
|
|
71
72
|
}
|
|
72
|
-
}, [embed]);
|
|
73
|
+
}, [embed, renderContext]);
|
|
73
74
|
|
|
74
75
|
useEffect(() => {
|
|
75
76
|
const iframe = iframeRef.current;
|
package/src/Embed/ImageEmbed.tsx
CHANGED
|
@@ -19,7 +19,7 @@ import { Figure, FigureType } from '../Figure';
|
|
|
19
19
|
import Image, { ImageLink } from '../Image';
|
|
20
20
|
import { EmbedByline } from '../LicenseByline';
|
|
21
21
|
import EmbedErrorPlaceholder from './EmbedErrorPlaceholder';
|
|
22
|
-
import { HeartButtonType } from './types';
|
|
22
|
+
import { HeartButtonType, RenderContext } from './types';
|
|
23
23
|
|
|
24
24
|
interface Props {
|
|
25
25
|
embed: ImageMetaData;
|
|
@@ -28,6 +28,7 @@ interface Props {
|
|
|
28
28
|
heartButton?: HeartButtonType;
|
|
29
29
|
inGrid?: boolean;
|
|
30
30
|
lang?: string;
|
|
31
|
+
renderContext?: RenderContext;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export interface Author {
|
|
@@ -105,17 +106,25 @@ export const getCrop = (data: ImageEmbedData) => {
|
|
|
105
106
|
|
|
106
107
|
const expandedSizes = '(min-width: 1024px) 1024px, 100vw';
|
|
107
108
|
|
|
108
|
-
const ImageEmbed = ({
|
|
109
|
+
const ImageEmbed = ({
|
|
110
|
+
embed,
|
|
111
|
+
previewAlt,
|
|
112
|
+
heartButton: HeartButton,
|
|
113
|
+
inGrid,
|
|
114
|
+
path,
|
|
115
|
+
lang,
|
|
116
|
+
renderContext = 'article',
|
|
117
|
+
}: Props) => {
|
|
109
118
|
const [isBylineHidden, setIsBylineHidden] = useState(hideByline(embed.embedData.size));
|
|
110
119
|
const [imageSizes, setImageSizes] = useState<string | undefined>(undefined);
|
|
111
120
|
|
|
112
121
|
const parsedDescription = useMemo(() => {
|
|
113
|
-
if (embed.embedData.caption) {
|
|
114
|
-
return parse(embed.embedData.caption);
|
|
122
|
+
if (embed.embedData.caption || renderContext === 'article') {
|
|
123
|
+
return embed.embedData.caption ? parse(embed.embedData.caption) : undefined;
|
|
115
124
|
} else if (embed.status === 'success' && embed.data.caption.caption) {
|
|
116
125
|
return parse(embed.data.caption.caption);
|
|
117
126
|
}
|
|
118
|
-
}, [embed]);
|
|
127
|
+
}, [embed, renderContext]);
|
|
119
128
|
|
|
120
129
|
if (embed.status === 'error') {
|
|
121
130
|
const { align, size } = embed.embedData;
|
|
@@ -10,7 +10,7 @@ import { Meta, StoryObj } from '@storybook/react';
|
|
|
10
10
|
import { RelatedContentMetaData } from '@ndla/types-embed';
|
|
11
11
|
import { defaultParameters } from '../../../../stories/defaults';
|
|
12
12
|
import RelatedContentEmbed from './RelatedContentEmbed';
|
|
13
|
-
import
|
|
13
|
+
import RelatedArticleList from '../RelatedArticleList';
|
|
14
14
|
|
|
15
15
|
const filmResourceMeta: RelatedContentMetaData = {
|
|
16
16
|
resource: 'related-content',
|
|
@@ -397,41 +397,41 @@ const linkEmbed2: RelatedContentMetaData = {
|
|
|
397
397
|
|
|
398
398
|
export const RelatedContentStory: StoryObj<typeof RelatedContentEmbed> = {
|
|
399
399
|
render: () => (
|
|
400
|
-
<
|
|
400
|
+
<RelatedArticleList>
|
|
401
401
|
<RelatedContentEmbed embed={learningResourceMeta} />
|
|
402
402
|
<RelatedContentEmbed embed={learningResourceMeta} />
|
|
403
|
-
</
|
|
403
|
+
</RelatedArticleList>
|
|
404
404
|
),
|
|
405
405
|
};
|
|
406
406
|
|
|
407
407
|
export const HideAllAboveTwo: StoryObj<typeof RelatedContentEmbed> = {
|
|
408
408
|
render: () => (
|
|
409
|
-
<
|
|
409
|
+
<RelatedArticleList>
|
|
410
410
|
<RelatedContentEmbed embed={learningResourceMeta} />
|
|
411
411
|
<RelatedContentEmbed embed={filmResourceMeta} />
|
|
412
412
|
<RelatedContentEmbed embed={learningResourceMeta} />
|
|
413
413
|
<RelatedContentEmbed embed={filmResourceMeta} />
|
|
414
|
-
</
|
|
414
|
+
</RelatedArticleList>
|
|
415
415
|
),
|
|
416
416
|
};
|
|
417
417
|
|
|
418
418
|
export const WithLinks: StoryObj<typeof RelatedContentEmbed> = {
|
|
419
419
|
render: () => (
|
|
420
|
-
<
|
|
420
|
+
<RelatedArticleList>
|
|
421
421
|
<RelatedContentEmbed embed={linkEmbed1} />
|
|
422
422
|
<RelatedContentEmbed embed={linkEmbed2} />
|
|
423
|
-
</
|
|
423
|
+
</RelatedArticleList>
|
|
424
424
|
),
|
|
425
425
|
};
|
|
426
426
|
|
|
427
427
|
export const Mixed: StoryObj<typeof RelatedContentEmbed> = {
|
|
428
428
|
render: () => (
|
|
429
|
-
<
|
|
429
|
+
<RelatedArticleList>
|
|
430
430
|
<RelatedContentEmbed embed={linkEmbed1} />
|
|
431
431
|
<RelatedContentEmbed embed={learningResourceMeta} />
|
|
432
432
|
<RelatedContentEmbed embed={filmResourceMeta} />
|
|
433
433
|
<RelatedContentEmbed embed={linkEmbed2} />
|
|
434
|
-
</
|
|
434
|
+
</RelatedArticleList>
|
|
435
435
|
),
|
|
436
436
|
};
|
|
437
437
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { RelatedContentMetaData } from '@ndla/types-embed';
|
|
10
10
|
import { useTranslation } from 'react-i18next';
|
|
11
11
|
import { contentTypeMapping } from '../model/ContentType';
|
|
12
|
-
import {
|
|
12
|
+
import { RelatedArticle } from '../RelatedArticleList/RelatedArticleList';
|
|
13
13
|
|
|
14
14
|
interface Props {
|
|
15
15
|
embed: RelatedContentMetaData;
|
|
@@ -34,7 +34,7 @@ const RelatedContentEmbed = ({ embed, isOembed, subject, ndlaFrontendDomain }: P
|
|
|
34
34
|
data.resource?.path ??
|
|
35
35
|
`/article/${embedData.articleId}`;
|
|
36
36
|
return (
|
|
37
|
-
<
|
|
37
|
+
<RelatedArticle
|
|
38
38
|
title={data.article.title?.title ?? ''}
|
|
39
39
|
introduction={data.article.metaDescription?.metaDescription ?? ''}
|
|
40
40
|
target={isOembed ? '_blank' : undefined}
|
|
@@ -44,7 +44,7 @@ const RelatedContentEmbed = ({ embed, isOembed, subject, ndlaFrontendDomain }: P
|
|
|
44
44
|
);
|
|
45
45
|
} else if (typeof embedData.url === 'string') {
|
|
46
46
|
return (
|
|
47
|
-
<
|
|
47
|
+
<RelatedArticle
|
|
48
48
|
title={embedData.title ?? ''}
|
|
49
49
|
introduction=""
|
|
50
50
|
to={embedData.url}
|
package/src/Embed/index.ts
CHANGED
|
@@ -20,4 +20,4 @@ export { ConceptNotionV2 } from './conceptComponents';
|
|
|
20
20
|
export { default as ConceptListEmbed } from './ConceptListEmbed';
|
|
21
21
|
export { default as UnknownEmbed } from './UnknownEmbed';
|
|
22
22
|
export { InlineConcept, BlockConcept } from './ConceptEmbed';
|
|
23
|
-
export type { HeartButtonType } from './types';
|
|
23
|
+
export type { HeartButtonType, RenderContext } from './types';
|
package/src/Embed/types.ts
CHANGED
package/src/FactBox/FactBox.tsx
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { ReactNode,
|
|
9
|
+
import { ReactNode, useState } from 'react';
|
|
10
10
|
import BEMHelper from 'react-bem-helper';
|
|
11
|
-
import { ButtonV2 } from '@ndla/button';
|
|
12
11
|
import { useTranslation } from 'react-i18next';
|
|
12
|
+
import styled from '@emotion/styled';
|
|
13
|
+
import { IconButtonV2 } from '@ndla/button';
|
|
14
|
+
import { ChevronDown, ChevronUp } from '@ndla/icons/common';
|
|
13
15
|
|
|
14
16
|
const classes = new BEMHelper({
|
|
15
17
|
name: 'factbox',
|
|
@@ -17,26 +19,37 @@ const classes = new BEMHelper({
|
|
|
17
19
|
});
|
|
18
20
|
|
|
19
21
|
interface Props {
|
|
20
|
-
dangerouslySetInnerHTML?: { __html: string };
|
|
21
22
|
children?: ReactNode;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
const StyledAside = styled.aside`
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
align-items: center;
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const StyledDiv = styled.div`
|
|
32
|
+
width: 100%;
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const StyledIconButton = styled(IconButtonV2)`
|
|
36
|
+
margin-top: -20px;
|
|
37
|
+
z-index: 1;
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const FactBox = ({ children }: Props) => {
|
|
30
41
|
const { t } = useTranslation();
|
|
42
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
43
|
+
|
|
44
|
+
const additional = isOpen ? 'expanded' : '';
|
|
31
45
|
|
|
32
46
|
return (
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</aside>
|
|
47
|
+
<StyledAside {...classes(undefined, undefined, additional)}>
|
|
48
|
+
<StyledDiv {...classes('content')}>{children}</StyledDiv>
|
|
49
|
+
<StyledIconButton onClick={() => setIsOpen((p) => !p)} aria-label={t(`factbox.${isOpen ? 'close' : 'open'}`)}>
|
|
50
|
+
{isOpen ? <ChevronUp /> : <ChevronDown />}
|
|
51
|
+
</StyledIconButton>
|
|
52
|
+
</StyledAside>
|
|
40
53
|
);
|
|
41
54
|
};
|
|
42
55
|
|
|
@@ -10,7 +10,7 @@ import styled from '@emotion/styled';
|
|
|
10
10
|
import { Meta, StoryObj } from '@storybook/react';
|
|
11
11
|
import { spacing } from '@ndla/core';
|
|
12
12
|
import { Heading, Text } from '@ndla/typography';
|
|
13
|
-
import
|
|
13
|
+
import FactBox from './FactBox';
|
|
14
14
|
import { defaultParameters } from '../../../../stories/defaults';
|
|
15
15
|
|
|
16
16
|
const Wrapper = styled.div`
|
|
@@ -22,7 +22,7 @@ const Wrapper = styled.div`
|
|
|
22
22
|
*/
|
|
23
23
|
export default {
|
|
24
24
|
title: 'Components/FactBox',
|
|
25
|
-
component:
|
|
25
|
+
component: FactBox,
|
|
26
26
|
tags: ['autodocs'],
|
|
27
27
|
paramemeters: {
|
|
28
28
|
inlineStories: true,
|
|
@@ -57,6 +57,6 @@ export default {
|
|
|
57
57
|
</>
|
|
58
58
|
),
|
|
59
59
|
},
|
|
60
|
-
} as Meta<typeof
|
|
60
|
+
} as Meta<typeof FactBox>;
|
|
61
61
|
|
|
62
|
-
export const Default: StoryObj<typeof
|
|
62
|
+
export const Default: StoryObj<typeof FactBox> = {};
|
package/src/FactBox/index.ts
CHANGED
package/src/Figure/index.ts
CHANGED
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export { default as Figure } from './Figure';
|
|
10
|
-
export { FigureExpandButton } from './FigureExpandButton';
|
|
11
|
-
export { FigureBylineExpandButton } from './FigureBylineExpandButton';
|
|
12
10
|
export { FigureOpenDialogButton } from './FigureOpenDialogButton';
|
|
13
11
|
|
|
14
12
|
export type { FigureType } from './Figure';
|
package/src/FileList/File.tsx
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
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
|
+
|
|
1
9
|
import styled from '@emotion/styled';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
11
|
+
import SafeLink from '@ndla/safelink';
|
|
2
12
|
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
3
13
|
import { Download } from '@ndla/icons/common';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
title: string;
|
|
17
|
+
url: string;
|
|
18
|
+
fileExists: boolean;
|
|
19
|
+
fileType: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FileType {
|
|
23
|
+
title: string;
|
|
24
|
+
formats: FileFormat[];
|
|
25
|
+
fileExists?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface FileFormat {
|
|
29
|
+
url: string;
|
|
30
|
+
fileType: string;
|
|
31
|
+
tooltip: string;
|
|
32
|
+
}
|
|
7
33
|
|
|
8
34
|
const LinkTextWrapper = styled.div`
|
|
9
35
|
& > span {
|
|
@@ -31,7 +57,29 @@ const FileLink = styled(SafeLink)`
|
|
|
31
57
|
}
|
|
32
58
|
`;
|
|
33
59
|
|
|
34
|
-
const
|
|
60
|
+
const FileListItem = styled.li`
|
|
61
|
+
${fonts.sizes('18px', '26px')};
|
|
62
|
+
font-weight: ${fonts.weight.semibold};
|
|
63
|
+
min-height: 60px;
|
|
64
|
+
background: ${colors.brand.greyLighter};
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
flex-wrap: wrap;
|
|
68
|
+
margin-bottom: ${spacing.xsmall};
|
|
69
|
+
padding: ${spacing.small};
|
|
70
|
+
${mq.range({ from: breakpoints.tablet })} {
|
|
71
|
+
padding: ${spacing.small} ${spacing.normal};
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
interface FormatProps {
|
|
76
|
+
format: FileFormat;
|
|
77
|
+
title: string;
|
|
78
|
+
isPrimary: boolean;
|
|
79
|
+
isDeadLink: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const Format = ({ format, title, isPrimary, isDeadLink }: FormatProps) => {
|
|
35
83
|
const titleWithFormat = `${title} (${format.fileType.toUpperCase()})`;
|
|
36
84
|
|
|
37
85
|
if (isDeadLink) {
|
|
@@ -46,40 +94,22 @@ const renderFormat = (format: FileFormat, title: string, isPrimary: boolean, isD
|
|
|
46
94
|
return (
|
|
47
95
|
<FileLink key={format.url} to={format.url} target="_blank" aria-label={titleWithFormat}>
|
|
48
96
|
<Download />
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
</LinkTextWrapper>
|
|
53
|
-
</Tooltip>
|
|
97
|
+
<LinkTextWrapper aria-label={format.tooltip}>
|
|
98
|
+
<span>{isPrimary ? titleWithFormat : `(${format.fileType.toUpperCase()})`}</span>
|
|
99
|
+
</LinkTextWrapper>
|
|
54
100
|
</FileLink>
|
|
55
101
|
);
|
|
56
102
|
};
|
|
57
103
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
104
|
+
const File = ({ title, url, fileExists, fileType }: Props) => {
|
|
105
|
+
const { t } = useTranslation();
|
|
106
|
+
const tooltip = `${t('download')} ${url.split('/').pop()}`;
|
|
61
107
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
background: ${colors.brand.greyLighter};
|
|
67
|
-
display: flex;
|
|
68
|
-
align-items: center;
|
|
69
|
-
flex-wrap: wrap;
|
|
70
|
-
margin-bottom: ${spacing.xsmall};
|
|
71
|
-
padding: ${spacing.small};
|
|
72
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
73
|
-
padding: ${spacing.small} ${spacing.normal};
|
|
74
|
-
}
|
|
75
|
-
`;
|
|
76
|
-
|
|
77
|
-
const File = ({ file }: Props) => {
|
|
78
|
-
const formatLinks = file.formats.map((format, index) =>
|
|
79
|
-
renderFormat(format, file.title, index === 0, !file.fileExists),
|
|
108
|
+
return (
|
|
109
|
+
<FileListItem>
|
|
110
|
+
<Format format={{ url, fileType, tooltip }} isPrimary title={title} isDeadLink={!fileExists} />
|
|
111
|
+
</FileListItem>
|
|
80
112
|
);
|
|
81
|
-
|
|
82
|
-
return <FileListItem key={file.title}>{formatLinks}</FileListItem>;
|
|
83
113
|
};
|
|
84
114
|
|
|
85
115
|
export default File;
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { Meta, StoryObj } from '@storybook/react';
|
|
10
|
-
import
|
|
10
|
+
import File from './File';
|
|
11
11
|
import { defaultParameters } from '../../../../stories/defaults';
|
|
12
|
-
import
|
|
12
|
+
import FileList from './FileList';
|
|
13
13
|
|
|
14
14
|
export default {
|
|
15
15
|
title: 'Components/FileList',
|
|
16
16
|
tags: ['autodocs'],
|
|
17
|
-
component:
|
|
17
|
+
component: File,
|
|
18
18
|
parameters: {
|
|
19
19
|
inlineStories: true,
|
|
20
20
|
...defaultParameters,
|
|
@@ -26,23 +26,23 @@ export default {
|
|
|
26
26
|
fileType: 'pdf',
|
|
27
27
|
},
|
|
28
28
|
render: (args) => (
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
</
|
|
29
|
+
<FileList>
|
|
30
|
+
<File {...args} />
|
|
31
|
+
</FileList>
|
|
32
32
|
),
|
|
33
|
-
} as Meta<typeof
|
|
33
|
+
} as Meta<typeof File>;
|
|
34
34
|
|
|
35
|
-
export const FileNotFound: StoryObj<typeof
|
|
35
|
+
export const FileNotFound: StoryObj<typeof File> = {
|
|
36
36
|
args: { fileExists: false },
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
export const SeveralFiles: StoryObj<typeof
|
|
39
|
+
export const SeveralFiles: StoryObj<typeof File> = {
|
|
40
40
|
render: () => (
|
|
41
|
-
<
|
|
42
|
-
<
|
|
43
|
-
<
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
</
|
|
41
|
+
<FileList>
|
|
42
|
+
<File title="Fil 1" url="https://ndla.no/1" fileExists fileType="mp4" />
|
|
43
|
+
<File title="Fil 2" url="https://ndla.no/2" fileExists={false} fileType="pdf" />
|
|
44
|
+
<File title="Fil 3" url="https://ndla.no/3" fileExists fileType="docx" />
|
|
45
|
+
<File title="Fil 4" url="https://ndla.no/4" fileExists fileType="docx" />
|
|
46
|
+
</FileList>
|
|
47
47
|
),
|
|
48
48
|
};
|
|
@@ -1,23 +1,18 @@
|
|
|
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
|
+
|
|
1
9
|
import styled from '@emotion/styled';
|
|
2
10
|
import { colors, fonts, spacing } from '@ndla/core';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
export interface FileType {
|
|
6
|
-
title: string;
|
|
7
|
-
formats: FileFormat[];
|
|
8
|
-
fileExists?: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface FileFormat {
|
|
12
|
-
url: string;
|
|
13
|
-
fileType: string;
|
|
14
|
-
tooltip: string;
|
|
15
|
-
}
|
|
11
|
+
import { ReactNode } from 'react';
|
|
12
|
+
import { useTranslation } from 'react-i18next';
|
|
16
13
|
|
|
17
14
|
interface Props {
|
|
18
|
-
|
|
19
|
-
heading: string;
|
|
20
|
-
files: FileType[];
|
|
15
|
+
children: ReactNode;
|
|
21
16
|
}
|
|
22
17
|
|
|
23
18
|
const FileListSection = styled.section`
|
|
@@ -35,7 +30,7 @@ const FileListSection = styled.section`
|
|
|
35
30
|
}
|
|
36
31
|
`;
|
|
37
32
|
|
|
38
|
-
const FileListHeading = styled.
|
|
33
|
+
const FileListHeading = styled.h3`
|
|
39
34
|
${fonts.sizes('16px', '18px')};
|
|
40
35
|
letter-spacing: 0.05em;
|
|
41
36
|
margin: 0 0 ${spacing.xsmall} 0;
|
|
@@ -50,15 +45,14 @@ const FilesList = styled.ul`
|
|
|
50
45
|
padding: 0;
|
|
51
46
|
`;
|
|
52
47
|
|
|
53
|
-
const FileList = ({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
{files
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
);
|
|
48
|
+
const FileList = ({ children }: Props) => {
|
|
49
|
+
const { t } = useTranslation();
|
|
50
|
+
return (
|
|
51
|
+
<FileListSection>
|
|
52
|
+
<FileListHeading>{t('files')}</FileListHeading>
|
|
53
|
+
<FilesList>{children}</FilesList>
|
|
54
|
+
</FileListSection>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
63
57
|
|
|
64
58
|
export default FileList;
|
package/src/FileList/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { breakpoints, colors, spacing, mq } from '@ndla/core';
|
|
|
15
15
|
import { LinkBlockEmbedData } from '@ndla/types-embed';
|
|
16
16
|
import { useMemo } from 'react';
|
|
17
17
|
import { Heading } from '@ndla/typography';
|
|
18
|
-
import {
|
|
18
|
+
import { getPossiblyRelativeUrl } from '../utils/relativeUrl';
|
|
19
19
|
|
|
20
20
|
const StyledForward = styled(Forward)`
|
|
21
21
|
margin: 0 ${spacing.nsmall};
|
|
@@ -78,7 +78,7 @@ interface Props extends Omit<LinkBlockEmbedData, 'resource'> {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
const LinkBlock = ({ title, language, date, url, path }: Props) => {
|
|
81
|
-
const href =
|
|
81
|
+
const href = getPossiblyRelativeUrl(url, path);
|
|
82
82
|
const formattedDate = useMemo(() => {
|
|
83
83
|
if (!date) return null;
|
|
84
84
|
const locale = language === 'nb' ? nb : language === 'nn' ? nn : enGB;
|
package/src/Messages/index.ts
CHANGED