@ndla/ui 12.0.2 → 13.1.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/Breadcrumb/Breadcrumb.js +101 -24
- package/es/Breadcrumb/BreadcrumbItem.js +70 -18
- package/es/Breadcrumb/HeaderBreadcrumb.js +82 -0
- package/es/Breadcrumb/HomeBreadcrumb.js +117 -0
- package/es/Breadcrumb/index.js +2 -1
- package/es/Breadcrumblist/index.js +1 -2
- package/es/all.css +1 -1
- package/es/index.js +1 -1
- package/es/locale/messages-en.js +55 -16
- package/es/locale/messages-nb.js +54 -15
- package/es/locale/messages-nn.js +55 -16
- package/es/locale/messages-se.js +52 -13
- package/es/locale/messages-sma.js +52 -13
- package/lib/Breadcrumb/Breadcrumb.d.ts +10 -12
- package/lib/Breadcrumb/Breadcrumb.js +104 -32
- package/lib/Breadcrumb/BreadcrumbItem.d.ts +15 -7
- package/lib/Breadcrumb/BreadcrumbItem.js +68 -20
- package/lib/Breadcrumb/HeaderBreadcrumb.d.ts +15 -0
- package/lib/Breadcrumb/HeaderBreadcrumb.js +95 -0
- package/lib/Breadcrumb/HomeBreadcrumb.d.ts +15 -0
- package/lib/Breadcrumb/HomeBreadcrumb.js +127 -0
- package/lib/Breadcrumb/index.d.ts +3 -1
- package/lib/Breadcrumb/index.js +11 -3
- package/lib/Breadcrumblist/index.js +0 -1
- package/lib/all.css +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +10 -3
- package/lib/locale/messages-en.d.ts +39 -0
- package/lib/locale/messages-en.js +55 -16
- package/lib/locale/messages-nb.d.ts +39 -0
- package/lib/locale/messages-nb.js +54 -15
- package/lib/locale/messages-nn.d.ts +39 -0
- package/lib/locale/messages-nn.js +55 -16
- package/lib/locale/messages-se.d.ts +39 -0
- package/lib/locale/messages-se.js +52 -13
- package/lib/locale/messages-sma.d.ts +40 -1
- package/lib/locale/messages-sma.js +52 -13
- package/package.json +4 -4
- package/src/Breadcrumb/Breadcrumb.tsx +76 -40
- package/src/Breadcrumb/BreadcrumbItem.tsx +82 -18
- package/src/Breadcrumb/HeaderBreadcrumb.tsx +78 -0
- package/src/Breadcrumb/HomeBreadcrumb.tsx +88 -0
- package/src/Breadcrumb/index.ts +5 -1
- package/src/Breadcrumblist/index.tsx +0 -1
- package/src/index.ts +2 -1
- package/src/locale/__tests__/translations-test.ts +10 -0
- package/src/locale/messages-en.ts +51 -12
- package/src/locale/messages-nb.ts +50 -11
- package/src/locale/messages-nn.ts +52 -13
- package/src/locale/messages-se.ts +48 -9
- package/src/locale/messages-sma.ts +49 -10
- package/src/main.scss +0 -2
- package/es/Breadcrumb/BreadcrumbBlock.js +0 -90
- package/lib/Breadcrumb/BreadcrumbBlock.d.ts +0 -15
- package/lib/Breadcrumb/BreadcrumbBlock.js +0 -105
- package/src/Breadcrumb/BreadcrumbBlock.tsx +0 -80
- package/src/Breadcrumb/component.breadcrumb-block.scss +0 -98
- package/src/Breadcrumb/component.breadcrumb.scss +0 -104
|
@@ -6,47 +6,83 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React, { ReactNode } from 'react';
|
|
10
|
-
import
|
|
9
|
+
import React, { ReactNode, useRef } from 'react';
|
|
10
|
+
import { useComponentSize, useIsomorphicLayoutEffect } from '@ndla/hooks';
|
|
11
11
|
import { uuid } from '@ndla/util';
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import BreadcrumbItem from './BreadcrumbItem';
|
|
15
|
-
|
|
16
|
-
const classes: BEMHelper<ReturnObject> = BEMHelper({
|
|
17
|
-
name: 'breadcrumb',
|
|
18
|
-
prefix: 'c-',
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
export interface BreadcrumbItemI {
|
|
22
|
-
to: string;
|
|
23
|
-
name: string;
|
|
24
|
-
}
|
|
12
|
+
import styled from '@emotion/styled';
|
|
13
|
+
import { useTranslation } from 'react-i18next';
|
|
14
|
+
import BreadcrumbItem, { IndexedBreadcrumbItem, SimpleBreadcrumbItem } from './BreadcrumbItem';
|
|
25
15
|
|
|
26
|
-
interface Props
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
16
|
+
interface Props {
|
|
17
|
+
items: SimpleBreadcrumbItem[];
|
|
18
|
+
autoCollapse?: boolean;
|
|
19
|
+
collapseFirst?: boolean;
|
|
20
|
+
renderItem?: (item: IndexedBreadcrumbItem, totalCount: number) => ReactNode;
|
|
21
|
+
renderSeparator?: (item: IndexedBreadcrumbItem, totalCount: number) => ReactNode;
|
|
30
22
|
}
|
|
31
23
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
24
|
+
const BreadcrumbNav = styled.nav``;
|
|
25
|
+
|
|
26
|
+
const StyledList = styled.ol`
|
|
27
|
+
display: inline-block;
|
|
28
|
+
padding-left: 0;
|
|
29
|
+
margin-bottom: 0;
|
|
30
|
+
margin-top: 0;
|
|
31
|
+
list-style: none;
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
const Breadcrumb = ({ items, autoCollapse, renderItem, renderSeparator, collapseFirst }: Props) => {
|
|
35
|
+
const { t } = useTranslation();
|
|
36
|
+
const olRef = useRef<any>();
|
|
37
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
38
|
+
// No idiomatic way of dealing with sets of refs yet
|
|
39
|
+
// See: https://github.com/facebook/react/issues/14072#issuecomment-446777406
|
|
40
|
+
const breadcrumbItemRefs = useRef(new Map()).current;
|
|
41
|
+
const size = useComponentSize(containerRef);
|
|
42
|
+
|
|
43
|
+
useIsomorphicLayoutEffect(() => {
|
|
44
|
+
if (!autoCollapse) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Create an array of all breadcrumb item refs
|
|
48
|
+
const items = Array.from(breadcrumbItemRefs).map(([key, value]) => value);
|
|
49
|
+
|
|
50
|
+
// Clear max width on all items
|
|
51
|
+
items.forEach((el) => {
|
|
52
|
+
el.setMaxWidth('none');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Set maxWidth on breadcrumb text items iteratively until
|
|
56
|
+
// the ordered list fits on a single line. It's on a single line
|
|
57
|
+
// if the height of the list is less then 70.
|
|
58
|
+
items.forEach((el) => {
|
|
59
|
+
if (olRef.current.offsetHeight > 60) {
|
|
60
|
+
el.setMaxWidth('40px');
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}, [size]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<BreadcrumbNav ref={containerRef} aria-label={t('breadcrumb.breadcrumb')}>
|
|
67
|
+
<StyledList ref={olRef}>
|
|
68
|
+
{items.map((item, index) => (
|
|
69
|
+
<BreadcrumbItem
|
|
70
|
+
autoCollapse={autoCollapse}
|
|
71
|
+
renderItem={renderItem}
|
|
72
|
+
renderSeparator={renderSeparator}
|
|
73
|
+
ref={(element) =>
|
|
74
|
+
element === null || (!collapseFirst && index === 0) // skip first item which is never truncated
|
|
75
|
+
? breadcrumbItemRefs.delete(item.to)
|
|
76
|
+
: breadcrumbItemRefs.set(item.to, element)
|
|
77
|
+
}
|
|
78
|
+
key={uuid()}
|
|
79
|
+
totalCount={items.length}
|
|
80
|
+
item={{ ...item, index }}
|
|
81
|
+
/>
|
|
82
|
+
))}
|
|
83
|
+
</StyledList>
|
|
84
|
+
</BreadcrumbNav>
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default Breadcrumb;
|
|
@@ -9,37 +9,101 @@
|
|
|
9
9
|
import React, { useRef, useImperativeHandle, ReactNode, forwardRef } from 'react';
|
|
10
10
|
import { ChevronRight } from '@ndla/icons/common';
|
|
11
11
|
import SafeLink from '@ndla/safelink';
|
|
12
|
-
import
|
|
12
|
+
import styled from '@emotion/styled';
|
|
13
|
+
import { mq, spacing, breakpoints } from '@ndla/core';
|
|
14
|
+
import { css } from '@emotion/core';
|
|
13
15
|
|
|
14
|
-
interface
|
|
15
|
-
classes: BEMHelper<ReturnObject>;
|
|
16
|
-
isCurrent: boolean;
|
|
17
|
-
children: ReactNode;
|
|
16
|
+
export interface SimpleBreadcrumbItem {
|
|
18
17
|
to: string | Partial<Location>;
|
|
19
|
-
home: boolean;
|
|
20
18
|
name: string;
|
|
21
|
-
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface IndexedBreadcrumbItem extends SimpleBreadcrumbItem {
|
|
22
|
+
index: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface BreadcrumbRenderProps {
|
|
26
|
+
item: IndexedBreadcrumbItem;
|
|
27
|
+
totalCount: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface AutoCollapseProps {
|
|
31
|
+
autoCollapse?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const StyledListItem = styled.li<AutoCollapseProps>`
|
|
35
|
+
margin-bottom: 0;
|
|
36
|
+
margin-left: 0;
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
:before {
|
|
40
|
+
display: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
${({ autoCollapse }) =>
|
|
44
|
+
!autoCollapse &&
|
|
45
|
+
css`
|
|
46
|
+
${mq.range({ until: breakpoints.tablet })} {
|
|
47
|
+
display: block;
|
|
48
|
+
}
|
|
49
|
+
`}
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
const CollapseContainer = styled.div<AutoCollapseProps>`
|
|
53
|
+
display: inline-block;
|
|
54
|
+
${({ autoCollapse }) =>
|
|
55
|
+
autoCollapse &&
|
|
56
|
+
css`
|
|
57
|
+
text-overflow: ellipsis;
|
|
58
|
+
white-space: nowrap;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
display: inline-block;
|
|
61
|
+
`}
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
const StyledChevron = styled(ChevronRight)`
|
|
65
|
+
margin: ${spacing.xxsmall};
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const StyledSafeLink = styled(SafeLink)`
|
|
69
|
+
color: inherit;
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
interface Props {
|
|
73
|
+
item: IndexedBreadcrumbItem;
|
|
74
|
+
autoCollapse?: boolean;
|
|
75
|
+
totalCount: number;
|
|
76
|
+
renderItem?: (item: IndexedBreadcrumbItem, totalCount: number) => ReactNode;
|
|
77
|
+
renderSeparator?: (item: IndexedBreadcrumbItem, totalCount: number) => ReactNode;
|
|
22
78
|
}
|
|
23
79
|
|
|
24
80
|
const BreadcrumbItem = forwardRef<any, Props>(
|
|
25
|
-
({
|
|
81
|
+
({ renderItem, renderSeparator, item, totalCount, autoCollapse }, ref) => {
|
|
26
82
|
const liRef = useRef<any>();
|
|
83
|
+
|
|
27
84
|
useImperativeHandle(ref, () => ({
|
|
28
85
|
setMaxWidth: (maxWidth: number) => {
|
|
29
86
|
liRef.current.children[0].style.maxWidth = maxWidth;
|
|
30
87
|
},
|
|
31
88
|
}));
|
|
89
|
+
|
|
90
|
+
const { to, name, index } = item;
|
|
91
|
+
const isLast = index === totalCount - 1;
|
|
32
92
|
return (
|
|
33
|
-
<
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
93
|
+
<StyledListItem ref={liRef} autoCollapse={autoCollapse}>
|
|
94
|
+
<CollapseContainer autoCollapse={autoCollapse}>
|
|
95
|
+
{renderItem ? (
|
|
96
|
+
renderItem(item, totalCount)
|
|
97
|
+
) : isLast ? (
|
|
98
|
+
<span>{name}</span>
|
|
99
|
+
) : (
|
|
100
|
+
<StyledSafeLink to={to}>
|
|
101
|
+
<span>{name}</span>
|
|
102
|
+
</StyledSafeLink>
|
|
103
|
+
)}
|
|
104
|
+
</CollapseContainer>
|
|
105
|
+
{renderSeparator ? renderSeparator(item, totalCount) : !isLast && <StyledChevron />}
|
|
106
|
+
</StyledListItem>
|
|
43
107
|
);
|
|
44
108
|
},
|
|
45
109
|
);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022-present, NDLA.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import styled from '@emotion/styled';
|
|
10
|
+
import { colors, fonts, spacing } from '@ndla/core';
|
|
11
|
+
import { ChevronRight } from '@ndla/icons/common';
|
|
12
|
+
import SafeLink from '@ndla/safelink';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import Breadcrumb from './Breadcrumb';
|
|
15
|
+
import { IndexedBreadcrumbItem, SimpleBreadcrumbItem } from './BreadcrumbItem';
|
|
16
|
+
|
|
17
|
+
interface ThemeProps {
|
|
18
|
+
light: boolean | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const StyledHeaderSafeLink = styled(SafeLink)<ThemeProps>`
|
|
22
|
+
${fonts.sizes(14)};
|
|
23
|
+
font-weight: ${fonts.weight.bold};
|
|
24
|
+
color: ${({ light }) => (light ? colors.white : colors.brand.primary)};
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
const StyledRightChevron = styled(ChevronRight)<ThemeProps>`
|
|
28
|
+
color: ${({ light }) => (light ? colors.white : colors.brand.primary)};
|
|
29
|
+
margin: ${spacing.xxsmall};
|
|
30
|
+
`;
|
|
31
|
+
const StyledSpan = styled.span<ThemeProps>`
|
|
32
|
+
color: ${({ light }) => (light ? colors.white : colors.brand.primary)};
|
|
33
|
+
`;
|
|
34
|
+
const StyledSafeLink = styled(SafeLink)<ThemeProps>`
|
|
35
|
+
color: ${({ light }) => (light ? colors.white : colors.brand.primary)};
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
interface Props {
|
|
39
|
+
items: SimpleBreadcrumbItem[];
|
|
40
|
+
light?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const HeaderBreadcrumb = ({ items, light }: Props) => {
|
|
44
|
+
const renderItem = (item: IndexedBreadcrumbItem, totalCount: number) => {
|
|
45
|
+
if (item.index === totalCount - 1) {
|
|
46
|
+
return <StyledSpan light={light}>{item.name}</StyledSpan>;
|
|
47
|
+
}
|
|
48
|
+
return (
|
|
49
|
+
<StyledSafeLink light={light} to={item.to}>
|
|
50
|
+
{item.name}
|
|
51
|
+
</StyledSafeLink>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const renderSeparator = (item: IndexedBreadcrumbItem, totalCount: number) => {
|
|
56
|
+
if (item.index === totalCount - 1) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return <StyledRightChevron light={light} />;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div>
|
|
64
|
+
<StyledHeaderSafeLink light={light} to={items[0]?.to}>
|
|
65
|
+
{items[0]?.name}
|
|
66
|
+
</StyledHeaderSafeLink>
|
|
67
|
+
<Breadcrumb
|
|
68
|
+
items={items.slice(1)}
|
|
69
|
+
renderItem={renderItem}
|
|
70
|
+
renderSeparator={renderSeparator}
|
|
71
|
+
autoCollapse
|
|
72
|
+
collapseFirst
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default HeaderBreadcrumb;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022-present, NDLA.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import styled from '@emotion/styled';
|
|
10
|
+
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
11
|
+
import { ChevronRight, Home } from '@ndla/icons/common';
|
|
12
|
+
import SafeLink from '@ndla/safelink';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import Breadcrumb from './Breadcrumb';
|
|
15
|
+
import { IndexedBreadcrumbItem, SimpleBreadcrumbItem } from './BreadcrumbItem';
|
|
16
|
+
|
|
17
|
+
interface ThemeProps {
|
|
18
|
+
light: boolean | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const StyledSeparator = styled.div<ThemeProps>`
|
|
22
|
+
${fonts.sizes('14px')};
|
|
23
|
+
margin: 0 ${spacing.small};
|
|
24
|
+
user-select: none;
|
|
25
|
+
color: ${({ light }) => (light ? colors.white : colors.text.primary)};
|
|
26
|
+
${mq.range({ until: breakpoints.tablet })} {
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const StyledIconSafeLink = styled(SafeLink)`
|
|
32
|
+
box-shadow: none;
|
|
33
|
+
border-bottom: none;
|
|
34
|
+
`;
|
|
35
|
+
const StyledHome = styled(Home)<ThemeProps>`
|
|
36
|
+
width: 20px;
|
|
37
|
+
height: 20px;
|
|
38
|
+
color: ${({ light }) => (light ? colors.white : colors.text.primary)};
|
|
39
|
+
`;
|
|
40
|
+
const StyledRightChevron = styled(ChevronRight)<ThemeProps>`
|
|
41
|
+
color: ${({ light }) => (light ? colors.white : colors.text.primary)};
|
|
42
|
+
margin: ${spacing.xxsmall};
|
|
43
|
+
`;
|
|
44
|
+
const StyledSpan = styled.span<ThemeProps>`
|
|
45
|
+
color: ${({ light }) => (light ? colors.white : colors.text.primary)};
|
|
46
|
+
`;
|
|
47
|
+
const StyledSafeLink = styled(SafeLink)<ThemeProps>`
|
|
48
|
+
color: ${({ light }) => (light ? colors.white : colors.text.primary)};
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
interface Props {
|
|
52
|
+
items: SimpleBreadcrumbItem[];
|
|
53
|
+
light?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const HomeBreadcrumb = ({ items, light }: Props) => {
|
|
57
|
+
const renderItem = (item: IndexedBreadcrumbItem, totalCount: number) => {
|
|
58
|
+
if (item.index === totalCount - 1) {
|
|
59
|
+
return <StyledSpan light={light}>{item.name}</StyledSpan>;
|
|
60
|
+
}
|
|
61
|
+
if (item.index === 0) {
|
|
62
|
+
return (
|
|
63
|
+
<StyledIconSafeLink aria-label={item.name} to={item.to}>
|
|
64
|
+
<StyledHome title={item.name} light={light} />
|
|
65
|
+
</StyledIconSafeLink>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return (
|
|
69
|
+
<StyledSafeLink light={light} to={item.to}>
|
|
70
|
+
{item.name}
|
|
71
|
+
</StyledSafeLink>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const renderSeparator = (item: IndexedBreadcrumbItem, totalCount: number) => {
|
|
76
|
+
if (item.index === totalCount - 1) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (item.index === 0) {
|
|
80
|
+
return <StyledSeparator light={light}>|</StyledSeparator>;
|
|
81
|
+
}
|
|
82
|
+
return <StyledRightChevron light={light} />;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return <Breadcrumb items={items} renderItem={renderItem} renderSeparator={renderSeparator} />;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default HomeBreadcrumb;
|
package/src/Breadcrumb/index.ts
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import Breadcrumb from './Breadcrumb';
|
|
10
10
|
|
|
11
|
-
export {
|
|
11
|
+
export type { SimpleBreadcrumbItem, IndexedBreadcrumbItem } from './BreadcrumbItem';
|
|
12
|
+
|
|
13
|
+
export { default as HeaderBreadcrumb } from './HeaderBreadcrumb';
|
|
14
|
+
|
|
15
|
+
export { default as HomeBreadcrumb } from './HomeBreadcrumb';
|
|
12
16
|
|
|
13
17
|
export default Breadcrumb;
|
package/src/index.ts
CHANGED
|
@@ -151,7 +151,8 @@ export type { TopicProps } from './Topic';
|
|
|
151
151
|
export { default as Aside } from './Aside';
|
|
152
152
|
export { default as AuthorInfo } from './AuthorInfo';
|
|
153
153
|
|
|
154
|
-
export { default as Breadcrumb,
|
|
154
|
+
export { default as Breadcrumb, HeaderBreadcrumb, HomeBreadcrumb } from './Breadcrumb';
|
|
155
|
+
export type { SimpleBreadcrumbItem, IndexedBreadcrumbItem } from './Breadcrumb';
|
|
155
156
|
|
|
156
157
|
export type { BreadcrumbItemProps } from './Breadcrumblist/Breadcrumblist';
|
|
157
158
|
export { i18nInstance, formatNestedMessages, formatMessage } from './i18n';
|
|
@@ -10,6 +10,8 @@ import { validateTranslationFiles } from '@ndla/util';
|
|
|
10
10
|
import messagesNB from '../messages-nb';
|
|
11
11
|
import messagesNN from '../messages-nn';
|
|
12
12
|
import messagesEN from '../messages-en';
|
|
13
|
+
import messagesSE from '../messages-se';
|
|
14
|
+
import messagesSMA from '../messages-sma';
|
|
13
15
|
|
|
14
16
|
test('That all translations has all language keys', () => {
|
|
15
17
|
const anyMissing = validateTranslationFiles(
|
|
@@ -26,6 +28,14 @@ test('That all translations has all language keys', () => {
|
|
|
26
28
|
languageName: 'English',
|
|
27
29
|
translationObject: messagesEN,
|
|
28
30
|
},
|
|
31
|
+
{
|
|
32
|
+
languageName: 'Nordsamisk',
|
|
33
|
+
translationObject: messagesSE,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
languageName: 'Sørsamisk',
|
|
37
|
+
translationObject: messagesSMA,
|
|
38
|
+
},
|
|
29
39
|
],
|
|
30
40
|
'only-on-error',
|
|
31
41
|
);
|
|
@@ -407,13 +407,13 @@ const messages = {
|
|
|
407
407
|
openAll: 'Open all',
|
|
408
408
|
},
|
|
409
409
|
license: {
|
|
410
|
-
heading: '
|
|
410
|
+
heading: 'How to reuse content',
|
|
411
411
|
tabs: {
|
|
412
412
|
text: 'Text',
|
|
413
413
|
images: 'Images',
|
|
414
414
|
audio: 'Audio',
|
|
415
415
|
video: 'Video',
|
|
416
|
-
h5p: '
|
|
416
|
+
h5p: 'H5P',
|
|
417
417
|
files: 'Files',
|
|
418
418
|
embedlink: 'Embedded link',
|
|
419
419
|
other: 'Other content',
|
|
@@ -429,7 +429,7 @@ const messages = {
|
|
|
429
429
|
rules: 'Rules for use of image:',
|
|
430
430
|
},
|
|
431
431
|
images: {
|
|
432
|
-
heading: 'How to
|
|
432
|
+
heading: 'How to reuse images',
|
|
433
433
|
description: 'Remember to copy the text to be attached to the image where you use it.',
|
|
434
434
|
rules: 'Rules for use of image:',
|
|
435
435
|
itemImage: {
|
|
@@ -443,44 +443,50 @@ const messages = {
|
|
|
443
443
|
title: 'Title',
|
|
444
444
|
},
|
|
445
445
|
text: {
|
|
446
|
-
heading: 'How to
|
|
446
|
+
heading: 'How to reuse the text',
|
|
447
447
|
description: 'Remember to refer to the source when reusing text.',
|
|
448
448
|
rules: 'Rules for use of text:',
|
|
449
449
|
published: 'Published',
|
|
450
450
|
},
|
|
451
451
|
audio: {
|
|
452
|
-
heading: 'How to
|
|
452
|
+
heading: 'How to reuse audio files',
|
|
453
453
|
description: 'Remember to copy the text to be attached to the audio where you use it.',
|
|
454
454
|
rules: 'Rules for use of audio file:',
|
|
455
455
|
},
|
|
456
456
|
video: {
|
|
457
|
-
heading: 'How to
|
|
457
|
+
heading: 'How to reuse videos',
|
|
458
458
|
description: 'Remember to copy the text to be attached to the video where you use it.',
|
|
459
|
-
rules: 'Rules for use of
|
|
459
|
+
rules: 'Rules for use of video files:',
|
|
460
460
|
itemImage: {
|
|
461
461
|
ariaLabel: 'Open video in new window',
|
|
462
462
|
},
|
|
463
463
|
},
|
|
464
464
|
other: {
|
|
465
|
-
heading: 'How to
|
|
465
|
+
heading: 'How to reuse other content',
|
|
466
466
|
description: 'You will find guidelines for use of other content in the asset',
|
|
467
467
|
itemImage: {
|
|
468
468
|
ariaLabel: 'Open in new window',
|
|
469
469
|
},
|
|
470
470
|
},
|
|
471
471
|
h5p: {
|
|
472
|
-
heading: 'How to
|
|
472
|
+
heading: 'How to reuse H5P content',
|
|
473
473
|
description: 'You will find guidelines for use of H5P content in the asset',
|
|
474
474
|
rules: 'Rules for use of H5P:',
|
|
475
475
|
},
|
|
476
476
|
concept: {
|
|
477
|
-
heading: 'How to
|
|
477
|
+
heading: 'How to reuse concept content',
|
|
478
478
|
description: 'You will find guidelines for use of concept content in the asset',
|
|
479
479
|
rules: 'Rules for use of concept:',
|
|
480
480
|
title: 'Title',
|
|
481
|
+
embedlink: {
|
|
482
|
+
heading: 'How to show the concept in other content',
|
|
483
|
+
description: 'This url shows the concept without menu and footer',
|
|
484
|
+
copyTitle: 'Copy embed link',
|
|
485
|
+
hasCopiedTitle: 'Embed link copied',
|
|
486
|
+
},
|
|
481
487
|
},
|
|
482
488
|
files: {
|
|
483
|
-
heading: 'How to
|
|
489
|
+
heading: 'How to reuse files',
|
|
484
490
|
description: 'Remember to copy the text to be attached to the file where you use it.',
|
|
485
491
|
rules: 'Rules for use of file:',
|
|
486
492
|
itemImage: {
|
|
@@ -502,6 +508,11 @@ const messages = {
|
|
|
502
508
|
},
|
|
503
509
|
hasCopiedTitle: 'Copied!',
|
|
504
510
|
download: 'Download',
|
|
511
|
+
title: 'Title',
|
|
512
|
+
originator: 'Originator',
|
|
513
|
+
rightsholder: 'Rightsholder',
|
|
514
|
+
source: 'Source',
|
|
515
|
+
published: 'Published',
|
|
505
516
|
},
|
|
506
517
|
errorMessage: {
|
|
507
518
|
title: 'Oops, something went wrong',
|
|
@@ -598,6 +609,10 @@ const messages = {
|
|
|
598
609
|
search: {
|
|
599
610
|
placeholder: 'Search',
|
|
600
611
|
},
|
|
612
|
+
embedlink: {
|
|
613
|
+
copyTitle: 'Copy embed code',
|
|
614
|
+
hasCopiedTitle: 'Embed code copied',
|
|
615
|
+
},
|
|
601
616
|
filters: {
|
|
602
617
|
subject: {
|
|
603
618
|
useFilter: 'Use filter',
|
|
@@ -614,6 +629,7 @@ const messages = {
|
|
|
614
629
|
openFilter: 'Filter',
|
|
615
630
|
closeFilter: 'Close filter',
|
|
616
631
|
heading: 'Filter',
|
|
632
|
+
filteredBy: 'Filtered by',
|
|
617
633
|
},
|
|
618
634
|
alphabet: {
|
|
619
635
|
letterFilter: 'Filter content by the letter {{letter}}.',
|
|
@@ -769,6 +785,14 @@ const messages = {
|
|
|
769
785
|
createdBy: {
|
|
770
786
|
content: 'The resource',
|
|
771
787
|
text: 'is retrieved from',
|
|
788
|
+
concept: {
|
|
789
|
+
content: 'The concept',
|
|
790
|
+
text: 'is created by',
|
|
791
|
+
},
|
|
792
|
+
listing: {
|
|
793
|
+
content: 'The list',
|
|
794
|
+
text: 'is created by',
|
|
795
|
+
},
|
|
772
796
|
},
|
|
773
797
|
fagfornyelse: {
|
|
774
798
|
frontpage: {
|
|
@@ -801,7 +825,7 @@ const messages = {
|
|
|
801
825
|
frontpageMenu: {
|
|
802
826
|
program: 'Education programme',
|
|
803
827
|
allsubjects: 'All subjects',
|
|
804
|
-
cursorText: 'Have a look at some new learning resources from our
|
|
828
|
+
cursorText: 'Have a look at some new learning resources from our new subjects!',
|
|
805
829
|
},
|
|
806
830
|
navigation: {
|
|
807
831
|
showLongerDescription: 'Show topic description',
|
|
@@ -942,6 +966,21 @@ const messages = {
|
|
|
942
966
|
favourites: 'Favourites',
|
|
943
967
|
help: 'Help',
|
|
944
968
|
},
|
|
969
|
+
labels: {
|
|
970
|
+
category: 'Category',
|
|
971
|
+
subject: 'Subject',
|
|
972
|
+
other: 'Other',
|
|
973
|
+
},
|
|
974
|
+
listingPage: {
|
|
975
|
+
or: 'or',
|
|
976
|
+
noFilters: 'Have nothing to filter',
|
|
977
|
+
loadMore: 'Load more',
|
|
978
|
+
},
|
|
979
|
+
siteNav: {
|
|
980
|
+
search: 'Search',
|
|
981
|
+
contact: 'Contact',
|
|
982
|
+
help: 'Help',
|
|
983
|
+
},
|
|
945
984
|
};
|
|
946
985
|
|
|
947
986
|
export default messages;
|