@ndla/ui 43.0.3 → 44.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/Article/Article.js +6 -14
- package/es/Article/ArticleNotions.js +24 -48
- package/es/Article/index.js +1 -2
- package/es/ContactBlock/ContactBlock.js +13 -13
- package/es/Embed/ImageEmbed.js +2 -2
- package/es/Grid/Grid.js +15 -2
- package/es/Grid/index.js +1 -1
- package/es/LinkBlock/LinkBlock.js +16 -6
- package/es/{Article/ArticleContent.js → LinkBlock/LinkBlockSection.js} +22 -30
- package/es/LinkBlock/index.js +2 -1
- package/es/Topic/Topic.js +60 -42
- package/es/index.js +4 -3
- package/lib/Article/Article.d.ts +3 -9
- package/lib/Article/Article.js +6 -14
- package/lib/Article/ArticleNotions.d.ts +3 -9
- package/lib/Article/ArticleNotions.js +30 -56
- package/lib/Article/index.d.ts +1 -2
- package/lib/Article/index.js +0 -7
- package/lib/ContactBlock/ContactBlock.js +13 -13
- package/lib/Embed/ImageEmbed.d.ts +11 -1
- package/lib/Embed/ImageEmbed.js +3 -1
- package/lib/Grid/Grid.d.ts +4 -0
- package/lib/Grid/Grid.js +23 -10
- package/lib/Grid/index.d.ts +1 -1
- package/lib/Grid/index.js +10 -2
- package/lib/LinkBlock/LinkBlock.d.ts +2 -7
- package/lib/LinkBlock/LinkBlock.js +16 -6
- package/lib/LinkBlock/LinkBlockSection.d.ts +13 -0
- package/lib/{Article/ArticleContent.js → LinkBlock/LinkBlockSection.js} +22 -27
- package/lib/LinkBlock/index.d.ts +1 -0
- package/lib/LinkBlock/index.js +7 -0
- package/lib/Topic/Topic.d.ts +10 -17
- package/lib/Topic/Topic.js +62 -44
- package/lib/index.d.ts +3 -2
- package/lib/index.js +19 -6
- package/lib/types.d.ts +1 -1
- package/package.json +6 -5
- package/src/Article/Article.tsx +6 -16
- package/src/Article/ArticleNotions.tsx +9 -78
- package/src/Article/index.ts +1 -10
- package/src/ContactBlock/ContactBlock.tsx +3 -0
- package/src/Embed/ImageEmbed.tsx +2 -2
- package/src/Grid/Grid.tsx +9 -1
- package/src/Grid/index.ts +1 -1
- package/src/LinkBlock/LinkBlock.stories.tsx +18 -8
- package/src/LinkBlock/LinkBlock.tsx +12 -9
- package/src/LinkBlock/LinkBlockSection.tsx +42 -0
- package/src/LinkBlock/index.ts +1 -0
- package/src/Topic/Topic.tsx +58 -39
- package/src/index.ts +3 -2
- package/src/types.ts +1 -1
- package/lib/Article/ArticleContent.d.ts +0 -7
- package/src/Article/ArticleContent.tsx +0 -40
package/lib/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { default as SectionHeading } from './SectionHeading';
|
|
9
9
|
export { ConceptNotionV2, ImageEmbed, AudioEmbed, H5pEmbed, ExternalEmbed, IframeEmbed, FootnoteEmbed, BrightcoveEmbed, ContentLinkEmbed, RelatedContentEmbed, ConceptEmbed, ConceptListEmbed, UnknownEmbed, } from './Embed';
|
|
10
|
-
export { ArticleByline,
|
|
10
|
+
export { ArticleByline, ArticleFootNotes, ArticleIntroduction, ArticleTitle, ArticleWrapper, ArticleHeaderWrapper, default as Article, } from './Article';
|
|
11
11
|
export { default as Table } from './Table';
|
|
12
12
|
export { default as ResourcesWrapper, ResourcesTopicTitle } from './ResourcesWrapper';
|
|
13
13
|
export { createUniversalPortal } from './utils/createUniversalPortal';
|
|
@@ -94,7 +94,7 @@ export { KeyFigure } from './KeyFigure';
|
|
|
94
94
|
export { default as ContactBlock } from './ContactBlock';
|
|
95
95
|
export type { HeartButtonType } from './Embed';
|
|
96
96
|
export { CampaignBlock } from './CampaignBlock';
|
|
97
|
-
export { Grid } from './Grid';
|
|
97
|
+
export { Grid, GridParallaxItem } from './Grid';
|
|
98
98
|
export type { GridType } from './Grid';
|
|
99
99
|
export { Heading } from './Typography';
|
|
100
100
|
export type { HeadingLevel } from './types';
|
|
@@ -102,3 +102,4 @@ export { default as FrontpageArticle } from './FrontpageArticle';
|
|
|
102
102
|
export { DefinitionTerm, DefinitionDescription } from './DefinitionList';
|
|
103
103
|
export type { ProgrammeV2 } from './ProgrammeCard';
|
|
104
104
|
export { Gloss } from './Gloss';
|
|
105
|
+
export { LinkBlock, LinkBlockSection } from './LinkBlock';
|
package/lib/index.js
CHANGED
|
@@ -34,12 +34,6 @@ Object.defineProperty(exports, "ArticleByline", {
|
|
|
34
34
|
return _Article.ArticleByline;
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
-
Object.defineProperty(exports, "ArticleContent", {
|
|
38
|
-
enumerable: true,
|
|
39
|
-
get: function get() {
|
|
40
|
-
return _Article.ArticleContent;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
37
|
Object.defineProperty(exports, "ArticleFootNotes", {
|
|
44
38
|
enumerable: true,
|
|
45
39
|
get: function get() {
|
|
@@ -502,6 +496,12 @@ Object.defineProperty(exports, "Grid", {
|
|
|
502
496
|
return _Grid.Grid;
|
|
503
497
|
}
|
|
504
498
|
});
|
|
499
|
+
Object.defineProperty(exports, "GridParallaxItem", {
|
|
500
|
+
enumerable: true,
|
|
501
|
+
get: function get() {
|
|
502
|
+
return _Grid.GridParallaxItem;
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
505
|
Object.defineProperty(exports, "H5pEmbed", {
|
|
506
506
|
enumerable: true,
|
|
507
507
|
get: function get() {
|
|
@@ -670,6 +670,18 @@ Object.defineProperty(exports, "LetterFilter", {
|
|
|
670
670
|
return _LetterFilter.default;
|
|
671
671
|
}
|
|
672
672
|
});
|
|
673
|
+
Object.defineProperty(exports, "LinkBlock", {
|
|
674
|
+
enumerable: true,
|
|
675
|
+
get: function get() {
|
|
676
|
+
return _LinkBlock.LinkBlock;
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
Object.defineProperty(exports, "LinkBlockSection", {
|
|
680
|
+
enumerable: true,
|
|
681
|
+
get: function get() {
|
|
682
|
+
return _LinkBlock.LinkBlockSection;
|
|
683
|
+
}
|
|
684
|
+
});
|
|
673
685
|
Object.defineProperty(exports, "ListResource", {
|
|
674
686
|
enumerable: true,
|
|
675
687
|
get: function get() {
|
|
@@ -1334,6 +1346,7 @@ var _Typography = require("./Typography");
|
|
|
1334
1346
|
var _FrontpageArticle = _interopRequireDefault(require("./FrontpageArticle"));
|
|
1335
1347
|
var _DefinitionList = require("./DefinitionList");
|
|
1336
1348
|
var _Gloss = require("./Gloss");
|
|
1349
|
+
var _LinkBlock = require("./LinkBlock");
|
|
1337
1350
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
1338
1351
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
1339
1352
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
package/lib/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ndla/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "44.0.1",
|
|
4
4
|
"description": "UI component library for NDLA.",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"@ndla/forms": "^4.3.17",
|
|
41
41
|
"@ndla/hooks": "^2.0.9",
|
|
42
42
|
"@ndla/icons": "^4.0.2",
|
|
43
|
-
"@ndla/licenses": "^7.1.
|
|
43
|
+
"@ndla/licenses": "^7.1.3",
|
|
44
44
|
"@ndla/modal": "^4.0.1",
|
|
45
|
-
"@ndla/notion": "^5.0.
|
|
45
|
+
"@ndla/notion": "^5.0.16",
|
|
46
46
|
"@ndla/safelink": "^4.1.16",
|
|
47
47
|
"@ndla/select": "^2.4.8",
|
|
48
48
|
"@ndla/switch": "^1.1.9",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@ndla/util": "^3.1.15",
|
|
52
52
|
"@radix-ui/react-popover": "^1.0.6",
|
|
53
53
|
"@radix-ui/react-slider": "^1.1.2",
|
|
54
|
+
"date-fns": "^2.30.0",
|
|
54
55
|
"framer-motion": "^6.5.1",
|
|
55
56
|
"html-react-parser": "^3.0.8",
|
|
56
57
|
"i18next-browser-languagedetector": "^6.1.1",
|
|
@@ -72,7 +73,7 @@
|
|
|
72
73
|
"devDependencies": {
|
|
73
74
|
"@babel/plugin-proposal-optional-chaining": "^7.11.0",
|
|
74
75
|
"@ndla/types-backend": "^0.2.5",
|
|
75
|
-
"@ndla/types-embed": "^2.0.
|
|
76
|
+
"@ndla/types-embed": "^2.0.7",
|
|
76
77
|
"css-loader": "^6.7.3",
|
|
77
78
|
"mini-css-extract-plugin": "^2.7.5",
|
|
78
79
|
"sass-loader": "^13.2.2",
|
|
@@ -82,5 +83,5 @@
|
|
|
82
83
|
"publishConfig": {
|
|
83
84
|
"access": "public"
|
|
84
85
|
},
|
|
85
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "494677b86370dc86e7642c6c3934435339f87e18"
|
|
86
87
|
}
|
package/src/Article/Article.tsx
CHANGED
|
@@ -14,15 +14,13 @@ import styled from '@emotion/styled';
|
|
|
14
14
|
import { useIntersectionObserver } from '@ndla/hooks';
|
|
15
15
|
import { resizeObserver } from '@ndla/util';
|
|
16
16
|
import { spacing, spacingUnit, mq, breakpoints } from '@ndla/core';
|
|
17
|
-
import { Article as ArticleType
|
|
18
|
-
import ArticleContent from './ArticleContent';
|
|
17
|
+
import { Article as ArticleType } from '../types';
|
|
19
18
|
import ArticleByline from './ArticleByline';
|
|
20
19
|
import LayoutItem from '../Layout';
|
|
21
20
|
import ArticleHeaderWrapper from './ArticleHeaderWrapper';
|
|
22
|
-
import ArticleNotions
|
|
21
|
+
import ArticleNotions from './ArticleNotions';
|
|
23
22
|
import ArticleAccessMessage from './ArticleAccessMessage';
|
|
24
23
|
import MessageBox from '../Messages/MessageBox';
|
|
25
|
-
import { ConceptNotionType } from '../Notion/ConceptNotion';
|
|
26
24
|
import { Heading } from '../Typography';
|
|
27
25
|
|
|
28
26
|
const classes = new BEMHelper({
|
|
@@ -124,22 +122,19 @@ type Props = {
|
|
|
124
122
|
children?: ReactNode;
|
|
125
123
|
messages: Messages;
|
|
126
124
|
contentTransformed?: boolean;
|
|
127
|
-
locale: Locale;
|
|
128
125
|
messageBoxLinks?: [];
|
|
129
126
|
competenceGoals?: ReactNode;
|
|
130
127
|
id: string;
|
|
131
128
|
renderMarkdown: (text: string) => string;
|
|
132
|
-
notions?:
|
|
129
|
+
notions?: ReactNode;
|
|
133
130
|
accessMessage?: string;
|
|
134
131
|
};
|
|
135
132
|
|
|
136
|
-
const getArticleContent = (content: any,
|
|
133
|
+
const getArticleContent = (content: any, contentTransformed?: boolean) => {
|
|
137
134
|
if (contentTransformed) {
|
|
138
135
|
return content;
|
|
139
136
|
}
|
|
140
137
|
switch (typeof content) {
|
|
141
|
-
case 'string':
|
|
142
|
-
return <ArticleContent content={content} locale={locale} />;
|
|
143
138
|
case 'function':
|
|
144
139
|
return content();
|
|
145
140
|
default:
|
|
@@ -157,7 +152,6 @@ export const Article = ({
|
|
|
157
152
|
children,
|
|
158
153
|
competenceGoals,
|
|
159
154
|
id,
|
|
160
|
-
locale,
|
|
161
155
|
notions,
|
|
162
156
|
renderMarkdown,
|
|
163
157
|
accessMessage,
|
|
@@ -223,13 +217,9 @@ export const Article = ({
|
|
|
223
217
|
</LayoutItem>
|
|
224
218
|
<LayoutItem layout="center">
|
|
225
219
|
{notions && showExplainNotions && (
|
|
226
|
-
<ArticleNotions
|
|
227
|
-
notions={notions.list}
|
|
228
|
-
relatedContent={notions.related}
|
|
229
|
-
buttonOffsetRight={articlePositionRight}
|
|
230
|
-
/>
|
|
220
|
+
<ArticleNotions buttonOffsetRight={articlePositionRight}>{notions}</ArticleNotions>
|
|
231
221
|
)}
|
|
232
|
-
{getArticleContent(content,
|
|
222
|
+
{getArticleContent(content, contentTransformed)}
|
|
233
223
|
</LayoutItem>
|
|
234
224
|
|
|
235
225
|
<LayoutItem layout="center">
|
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { ReactNode } from 'react';
|
|
9
10
|
import styled from '@emotion/styled';
|
|
10
11
|
import { useTranslation } from 'react-i18next';
|
|
11
12
|
import { ModalHeader, ModalCloseButton, ModalBody, Modal, ModalTitle, ModalTrigger, ModalContent } from '@ndla/modal';
|
|
12
13
|
import { mq, breakpoints, fonts, colors } from '@ndla/core';
|
|
13
14
|
import { Explanation, NotionFlip } from '@ndla/icons/common';
|
|
14
|
-
import { ConceptNotion } from '../Notion';
|
|
15
|
-
import { ConceptNotionType } from '../Notion/ConceptNotion';
|
|
16
15
|
|
|
17
16
|
const ArticleNotionsContainer = styled.div`
|
|
18
17
|
margin-bottom: 26px;
|
|
@@ -81,14 +80,6 @@ const NotionsTrigger = styled.div`
|
|
|
81
80
|
const ModalHeadingContainer = styled.div`
|
|
82
81
|
display: flex;
|
|
83
82
|
align-items: center;
|
|
84
|
-
padding-left: 1rem;
|
|
85
|
-
padding-right: 1rem;
|
|
86
|
-
margin-bottom: 2rem;
|
|
87
|
-
|
|
88
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
89
|
-
padding-left: 3.5rem;
|
|
90
|
-
padding-right: 3.5rem;
|
|
91
|
-
}
|
|
92
83
|
|
|
93
84
|
svg {
|
|
94
85
|
display: block;
|
|
@@ -103,65 +94,20 @@ const ModalHeadingContainer = styled.div`
|
|
|
103
94
|
margin: 0 1.5rem 0 -0.5rem;
|
|
104
95
|
}
|
|
105
96
|
}
|
|
106
|
-
|
|
107
|
-
h1 {
|
|
108
|
-
margin: 0;
|
|
109
|
-
}
|
|
110
|
-
`;
|
|
111
|
-
|
|
112
|
-
const NotionsContainer = styled.div`
|
|
113
|
-
padding: 0 20px;
|
|
114
|
-
|
|
115
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
116
|
-
padding: 0 3.5rem;
|
|
117
|
-
}
|
|
118
97
|
`;
|
|
119
98
|
|
|
120
|
-
const
|
|
99
|
+
const StyledModalHeader = styled(ModalHeader)`
|
|
121
100
|
display: flex;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
margin: 0 0 2rem;
|
|
125
|
-
padding: 0 20px;
|
|
126
|
-
|
|
127
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
128
|
-
padding: 0 3.5rem;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
&:not(:last-child) {
|
|
132
|
-
margin-bottom: 1.5rem;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
> li {
|
|
136
|
-
width: 100%;
|
|
137
|
-
|
|
138
|
-
&:not(:nth-child(2n)) {
|
|
139
|
-
margin-right: 0;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
143
|
-
width: calc(100% * (1 / 3));
|
|
144
|
-
|
|
145
|
-
&:not(:nth-child(2n)) {
|
|
146
|
-
margin-right: 0.5rem;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
101
|
+
justify-content: space-between;
|
|
102
|
+
align-items: center;
|
|
150
103
|
`;
|
|
151
104
|
|
|
152
|
-
export type NotionRelatedContent = {
|
|
153
|
-
url: string;
|
|
154
|
-
label: string;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
105
|
type ArticleNotionsProps = {
|
|
158
|
-
|
|
159
|
-
relatedContent?: NotionRelatedContent[];
|
|
106
|
+
children?: ReactNode;
|
|
160
107
|
buttonOffsetRight: number;
|
|
161
|
-
type?: 'image' | 'video' | 'h5p' | 'iframe' | 'external';
|
|
162
108
|
};
|
|
163
109
|
|
|
164
|
-
export const ArticleNotions = ({
|
|
110
|
+
export const ArticleNotions = ({ buttonOffsetRight, children }: ArticleNotionsProps) => {
|
|
165
111
|
const { t } = useTranslation();
|
|
166
112
|
const leftOffset = `${buttonOffsetRight - 32}px`;
|
|
167
113
|
|
|
@@ -176,29 +122,14 @@ export const ArticleNotions = ({ notions, relatedContent = [], buttonOffsetRight
|
|
|
176
122
|
</NotionsTrigger>
|
|
177
123
|
</ModalTrigger>
|
|
178
124
|
<ModalContent size="large">
|
|
179
|
-
<
|
|
125
|
+
<StyledModalHeader>
|
|
180
126
|
<ModalHeadingContainer>
|
|
181
127
|
<Explanation />
|
|
182
128
|
<ModalTitle>{t('article.notionsPrompt')}</ModalTitle>
|
|
183
129
|
</ModalHeadingContainer>
|
|
184
130
|
<ModalCloseButton />
|
|
185
|
-
</
|
|
186
|
-
<ModalBody modifier="notions-modal-body no-padding">
|
|
187
|
-
<NotionsContainer>
|
|
188
|
-
{notions.map((notion) => (
|
|
189
|
-
<ConceptNotion key={notion.id} concept={notion} type={type} />
|
|
190
|
-
))}
|
|
191
|
-
</NotionsContainer>
|
|
192
|
-
{relatedContent.length > 0 && (
|
|
193
|
-
<RelatedContentContainer>
|
|
194
|
-
{relatedContent.map((content, i) => (
|
|
195
|
-
<li key={`notion-related-item-${i + 1}`}>
|
|
196
|
-
<a href={content.url}>{content.label}</a>
|
|
197
|
-
</li>
|
|
198
|
-
))}
|
|
199
|
-
</RelatedContentContainer>
|
|
200
|
-
)}
|
|
201
|
-
</ModalBody>
|
|
131
|
+
</StyledModalHeader>
|
|
132
|
+
<ModalBody modifier="notions-modal-body no-padding">{children}</ModalBody>
|
|
202
133
|
</ModalContent>
|
|
203
134
|
</Modal>
|
|
204
135
|
</ArticleNotionsContainer>
|
package/src/Article/index.ts
CHANGED
|
@@ -8,17 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import Article, { ArticleTitle, ArticleIntroduction, ArticleWrapper } from './Article';
|
|
10
10
|
import ArticleByline from './ArticleByline';
|
|
11
|
-
import ArticleContent from './ArticleContent';
|
|
12
11
|
import ArticleFootNotes from './ArticleFootNotes';
|
|
13
12
|
import ArticleHeaderWrapper from './ArticleHeaderWrapper';
|
|
14
13
|
|
|
15
|
-
export {
|
|
16
|
-
ArticleByline,
|
|
17
|
-
ArticleContent,
|
|
18
|
-
ArticleFootNotes,
|
|
19
|
-
ArticleHeaderWrapper,
|
|
20
|
-
ArticleTitle,
|
|
21
|
-
ArticleIntroduction,
|
|
22
|
-
ArticleWrapper,
|
|
23
|
-
};
|
|
14
|
+
export { ArticleByline, ArticleFootNotes, ArticleHeaderWrapper, ArticleTitle, ArticleIntroduction, ArticleWrapper };
|
|
24
15
|
export default Article;
|
|
@@ -33,6 +33,9 @@ const BlockWrapper = styled.div`
|
|
|
33
33
|
border-radius: ${misc.borderRadius};
|
|
34
34
|
border: 1px solid ${colors.brand.lighter};
|
|
35
35
|
max-width: 348px;
|
|
36
|
+
& ~ & {
|
|
37
|
+
margin-top: ${spacing.medium};
|
|
38
|
+
}
|
|
36
39
|
${mq.range({ from: breakpoints.tabletWide })} {
|
|
37
40
|
max-width: 773px;
|
|
38
41
|
flex-direction: row;
|
package/src/Embed/ImageEmbed.tsx
CHANGED
|
@@ -73,14 +73,14 @@ const getSizes = (size?: string, align?: string) => {
|
|
|
73
73
|
return '(min-width: 1024px) 1024px, 100vw';
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
const getFocalPoint = (data: ImageEmbedData) => {
|
|
76
|
+
export const getFocalPoint = (data: ImageEmbedData) => {
|
|
77
77
|
if (typeof data.focalX === 'number' && typeof data.focalY === 'number') {
|
|
78
78
|
return { x: data.focalX, y: data.focalY };
|
|
79
79
|
}
|
|
80
80
|
return undefined;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
const getCrop = (data: ImageEmbedData) => {
|
|
83
|
+
export const getCrop = (data: ImageEmbedData) => {
|
|
84
84
|
if (
|
|
85
85
|
typeof data.lowerRightX === 'number' &&
|
|
86
86
|
typeof data.lowerRightY === 'number' &&
|
package/src/Grid/Grid.tsx
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import styled from '@emotion/styled';
|
|
10
10
|
import { breakpoints, colors, misc, mq, spacing } from '@ndla/core';
|
|
11
|
-
import { ReactNode } from 'react';
|
|
11
|
+
import { Children, ReactNode } from 'react';
|
|
12
12
|
|
|
13
13
|
export interface GridProps {
|
|
14
14
|
columns: '2' | '4' | '2x2';
|
|
@@ -87,4 +87,12 @@ const Grid = ({ columns, border, children, background, size, ...rest }: GridProp
|
|
|
87
87
|
);
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
+
export const GridParallaxItem = styled.div`
|
|
91
|
+
position: relative;
|
|
92
|
+
> div {
|
|
93
|
+
top: 0px;
|
|
94
|
+
position: sticky;
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
|
|
90
98
|
export default Grid;
|
package/src/Grid/index.ts
CHANGED
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { Meta, StoryObj } from '@storybook/react';
|
|
9
|
+
import { Meta, StoryObj, StoryFn } from '@storybook/react';
|
|
10
10
|
import LinkBlock from './LinkBlock';
|
|
11
11
|
import { defaultParameters } from '../../../../stories/defaults';
|
|
12
|
+
import { LinkBlockSection } from '.';
|
|
12
13
|
|
|
13
14
|
export default {
|
|
14
15
|
title: 'Components/Link Block',
|
|
@@ -20,11 +21,20 @@ export default {
|
|
|
20
21
|
args: {},
|
|
21
22
|
} as Meta<typeof LinkBlock>;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
url: '',
|
|
29
|
-
},
|
|
24
|
+
const args = {
|
|
25
|
+
title: 'Redaksjonell medarbeider i faget spansk 2',
|
|
26
|
+
language: 'nb',
|
|
27
|
+
date: '05. mars 2023',
|
|
28
|
+
url: '',
|
|
30
29
|
};
|
|
30
|
+
|
|
31
|
+
export const AnnouncementExample: StoryObj<typeof LinkBlock> = { args };
|
|
32
|
+
|
|
33
|
+
export const LinkList: StoryFn<typeof LinkBlock> = () => (
|
|
34
|
+
<LinkBlockSection>
|
|
35
|
+
<LinkBlock {...args} />
|
|
36
|
+
<LinkBlock {...args} />
|
|
37
|
+
<LinkBlock {...args} />
|
|
38
|
+
<LinkBlock {...args} />
|
|
39
|
+
</LinkBlockSection>
|
|
40
|
+
);
|
|
@@ -6,19 +6,16 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { format } from 'date-fns';
|
|
10
|
+
import { enGB, nb, nn } from 'date-fns/locale';
|
|
9
11
|
import styled from '@emotion/styled';
|
|
10
12
|
import SafeLink from '@ndla/safelink';
|
|
11
13
|
import { Forward, CalendarEd } from '@ndla/icons/common';
|
|
12
14
|
import { breakpoints, colors, spacing, mq } from '@ndla/core';
|
|
15
|
+
import { LinkBlockEmbedData } from '@ndla/types-embed';
|
|
16
|
+
import { useMemo } from 'react';
|
|
13
17
|
import Heading from '../Typography/Heading';
|
|
14
18
|
|
|
15
|
-
interface Props {
|
|
16
|
-
title: string;
|
|
17
|
-
language: string;
|
|
18
|
-
date: string;
|
|
19
|
-
url: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
19
|
const StyledForward = styled(Forward)`
|
|
23
20
|
margin: 0 ${spacing.nsmall};
|
|
24
21
|
min-width: ${spacing.normal};
|
|
@@ -74,7 +71,13 @@ const StyledCalenderEd = styled(CalendarEd)`
|
|
|
74
71
|
color: ${colors.icon.iconBlue};
|
|
75
72
|
`;
|
|
76
73
|
|
|
77
|
-
const LinkBlock = ({ title, language, date, url }:
|
|
74
|
+
const LinkBlock = ({ title, language, date, url }: Omit<LinkBlockEmbedData, 'resource'>) => {
|
|
75
|
+
const formattedDate = useMemo(() => {
|
|
76
|
+
if (!date) return null;
|
|
77
|
+
const locale = language === 'nb' ? nb : language === 'nn' ? nn : enGB;
|
|
78
|
+
return format(new Date(date), 'dd. LLLL. yyyy', { locale });
|
|
79
|
+
}, [date, language]);
|
|
80
|
+
|
|
78
81
|
return (
|
|
79
82
|
<StyledSafeLink to={url}>
|
|
80
83
|
<InfoWrapper>
|
|
@@ -84,7 +87,7 @@ const LinkBlock = ({ title, language, date, url }: Props) => {
|
|
|
84
87
|
{date && (
|
|
85
88
|
<StyledDateContainer>
|
|
86
89
|
<StyledCalenderEd />
|
|
87
|
-
{
|
|
90
|
+
{formattedDate}
|
|
88
91
|
</StyledDateContainer>
|
|
89
92
|
)}
|
|
90
93
|
</InfoWrapper>
|
|
@@ -0,0 +1,42 @@
|
|
|
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 styled from '@emotion/styled';
|
|
10
|
+
import { spacing } from '@ndla/core';
|
|
11
|
+
import { Children, HTMLAttributes, ReactNode } from 'react';
|
|
12
|
+
|
|
13
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const StyledList = styled.ul`
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: ${spacing.small};
|
|
21
|
+
list-style: none;
|
|
22
|
+
padding: 0px;
|
|
23
|
+
margin: 0px;
|
|
24
|
+
li {
|
|
25
|
+
padding: 0px;
|
|
26
|
+
margin: 0px;
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const LinkBlockSection = ({ children, ...rest }: Props) => {
|
|
31
|
+
return (
|
|
32
|
+
<nav {...rest}>
|
|
33
|
+
<StyledList>
|
|
34
|
+
{Children.map(children, (child) => (
|
|
35
|
+
<li>{child}</li>
|
|
36
|
+
))}
|
|
37
|
+
</StyledList>
|
|
38
|
+
</nav>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default LinkBlockSection;
|
package/src/LinkBlock/index.ts
CHANGED