@ndla/ui 48.0.0 → 49.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/BlogPost/BlogPost.js +6 -6
- package/es/CampaignBlock/CampaignBlock.js +8 -8
- package/es/CopyParagraphButton/CopyParagraphButton.js +30 -58
- package/es/CopyParagraphButton/index.js +1 -3
- 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/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/RelatedContentEmbed.js +3 -3
- 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 +9 -11
- package/lib/index.js +9 -89
- package/lib/utils/relativeUrl.d.ts +1 -1
- package/lib/utils/relativeUrl.js +19 -4
- package/package.json +8 -8
- package/src/BlogPost/BlogPost.tsx +2 -2
- package/src/CampaignBlock/CampaignBlock.tsx +2 -2
- package/src/CopyParagraphButton/CopyParagraphButton.tsx +24 -46
- package/src/CopyParagraphButton/index.tsx +1 -3
- package/src/Embed/RelatedContentEmbed.stories.tsx +9 -9
- package/src/Embed/RelatedContentEmbed.tsx +3 -3
- 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 +10 -13
- 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
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
package/src/Navigation/index.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
|
|
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 { Children, HTMLProps, ReactNode, useMemo, useState } from 'react';
|
|
2
10
|
import BEMHelper from 'react-bem-helper';
|
|
11
|
+
import { useTranslation } from 'react-i18next';
|
|
12
|
+
import styled from '@emotion/styled';
|
|
3
13
|
import { ButtonV2 } from '@ndla/button';
|
|
4
14
|
import SafeLink from '@ndla/safelink';
|
|
5
15
|
import { HeadingLevel } from '@ndla/typography';
|
|
6
16
|
import SectionHeading from '../SectionHeading';
|
|
17
|
+
import ContentTypeBadge from '../ContentTypeBadge';
|
|
18
|
+
import { contentTypes } from '../model/ContentType';
|
|
7
19
|
|
|
8
20
|
const classes = new BEMHelper({
|
|
9
21
|
name: 'related-articles',
|
|
@@ -11,29 +23,26 @@ const classes = new BEMHelper({
|
|
|
11
23
|
});
|
|
12
24
|
|
|
13
25
|
interface RelatedArticleProps {
|
|
14
|
-
icon: ReactElement;
|
|
15
26
|
title: string;
|
|
16
|
-
modifier?: string;
|
|
17
27
|
introduction: string;
|
|
18
28
|
to: string;
|
|
19
29
|
linkInfo?: string;
|
|
20
30
|
target?: string;
|
|
31
|
+
type?: string;
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
export const RelatedArticle = ({
|
|
24
35
|
title,
|
|
25
36
|
introduction,
|
|
26
|
-
icon,
|
|
27
|
-
modifier,
|
|
28
37
|
to,
|
|
29
38
|
linkInfo = '',
|
|
30
39
|
target = '',
|
|
40
|
+
type = contentTypes.SUBJECT_MATERIAL,
|
|
31
41
|
}: RelatedArticleProps) => {
|
|
32
|
-
const iconWithClass = cloneElement(icon, { className: 'c-icon--medium' });
|
|
33
42
|
return (
|
|
34
|
-
<article {...classes('item',
|
|
43
|
+
<article {...classes('item', type)}>
|
|
35
44
|
<h3 {...classes('title')}>
|
|
36
|
-
{
|
|
45
|
+
<ContentTypeBadge type={type} background size="small" />
|
|
37
46
|
<span {...classes('link-wrapper')}>
|
|
38
47
|
<SafeLink to={to} {...classes('link')} target={target} rel={linkInfo ? 'noopener noreferrer' : undefined}>
|
|
39
48
|
{title}
|
|
@@ -46,50 +55,47 @@ export const RelatedArticle = ({
|
|
|
46
55
|
);
|
|
47
56
|
};
|
|
48
57
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
children?:
|
|
57
|
-
dangerouslySetInnerHTML?: {
|
|
58
|
-
__html: string;
|
|
59
|
-
};
|
|
58
|
+
const HeadingWrapper = styled.div`
|
|
59
|
+
display: flex;
|
|
60
|
+
justify-content: space-between;
|
|
61
|
+
align-items: center;
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
interface Props extends HTMLProps<HTMLElement> {
|
|
65
|
+
children?: JSX.Element[];
|
|
60
66
|
articleCount?: number;
|
|
67
|
+
headingLevel?: HeadingLevel;
|
|
68
|
+
headingButtons?: ReactNode;
|
|
61
69
|
}
|
|
62
|
-
const RelatedArticleList = ({
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
70
|
+
export const RelatedArticleList = ({
|
|
71
|
+
children = [],
|
|
72
|
+
articleCount,
|
|
73
|
+
headingLevel = 'h3',
|
|
74
|
+
headingButtons,
|
|
75
|
+
...rest
|
|
76
|
+
}: Props) => {
|
|
77
|
+
const [expanded, setExpanded] = useState(false);
|
|
78
|
+
const { t } = useTranslation();
|
|
79
|
+
const childCount = useMemo(() => articleCount ?? Children.count(children), [children, articleCount]);
|
|
80
|
+
const childrenToShow = useMemo(
|
|
81
|
+
() => (childCount > 2 && !expanded ? children?.slice(0, 2) : children),
|
|
82
|
+
[childCount, children, expanded],
|
|
83
|
+
);
|
|
72
84
|
|
|
73
85
|
return (
|
|
74
|
-
<section {...classes('')}>
|
|
75
|
-
<
|
|
76
|
-
{
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
</
|
|
81
|
-
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
data-showless={messages.showLess}
|
|
86
|
-
variant="outline"
|
|
87
|
-
>
|
|
88
|
-
{messages.showMore}
|
|
86
|
+
<section {...classes('')} {...rest}>
|
|
87
|
+
<HeadingWrapper>
|
|
88
|
+
<SectionHeading headingLevel={headingLevel} className={classes('component-title').className}>
|
|
89
|
+
{t('related.title')}
|
|
90
|
+
</SectionHeading>
|
|
91
|
+
{headingButtons}
|
|
92
|
+
</HeadingWrapper>
|
|
93
|
+
<div {...classes('articles')}>{childrenToShow}</div>
|
|
94
|
+
{childCount > 2 ? (
|
|
95
|
+
<ButtonV2 onClick={() => setExpanded((p) => !p)} variant="outline">
|
|
96
|
+
{t(`related.show${expanded ? 'Less' : 'More'}`)}
|
|
89
97
|
</ButtonV2>
|
|
90
|
-
)}
|
|
98
|
+
) : null}
|
|
91
99
|
</section>
|
|
92
100
|
);
|
|
93
101
|
};
|
|
94
|
-
|
|
95
|
-
export default RelatedArticleList;
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
import { RelatedArticleListV2 } from './RelatedArticleV2';
|
|
9
|
+
import { RelatedArticle, RelatedArticleList } from './RelatedArticleList';
|
|
11
10
|
|
|
12
|
-
export { RelatedArticle
|
|
11
|
+
export { RelatedArticle };
|
|
13
12
|
|
|
14
13
|
export default RelatedArticleList;
|
package/src/Search/index.ts
CHANGED
|
@@ -11,6 +11,5 @@ import SearchField from './SearchField';
|
|
|
11
11
|
import { SearchResultList, SearchResultItem } from './SearchResult';
|
|
12
12
|
|
|
13
13
|
import ActiveFilters from './ActiveFilters';
|
|
14
|
-
export { default as ToggleSearchButton } from './ToggleSearchButton';
|
|
15
14
|
|
|
16
15
|
export { SearchField, SearchResultItem, SearchResultList, ActiveFilters };
|
package/src/i18n/i18n.ts
CHANGED
|
@@ -21,13 +21,14 @@ const DETECTION_OPTIONS = {
|
|
|
21
21
|
lookupLocalStorage: 'i18nextLng',
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
export const supportedTranslationLanguages = ['nb', 'nn', 'en', 'se', 'sma'] as const;
|
|
24
25
|
const i18nInstance = i18n.use(initReactI18next).use(LanguageDetector);
|
|
25
26
|
|
|
26
27
|
i18nInstance.init({
|
|
27
28
|
compatibilityJSON: 'v3',
|
|
28
29
|
detection: DETECTION_OPTIONS,
|
|
29
30
|
fallbackLng: 'nb',
|
|
30
|
-
supportedLngs:
|
|
31
|
+
supportedLngs: supportedTranslationLanguages,
|
|
31
32
|
resources: {
|
|
32
33
|
en: {
|
|
33
34
|
translation: messagesEN,
|