@ndla/ui 55.0.13-alpha.0 → 55.0.14-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/dist/panda.buildinfo.json +120 -1
  2. package/dist/styles.css +511 -0
  3. package/es/Article/ArticleParagraph.js +11 -13
  4. package/es/CampaignBlock/CampaignBlock.js +103 -68
  5. package/es/Concept/Concept.js +69 -0
  6. package/es/ContentTypeBadge/ContentTypeBadgeNew.js +48 -0
  7. package/es/Embed/AudioEmbed.js +1 -2
  8. package/es/Embed/BrightcoveEmbed.js +13 -24
  9. package/es/Embed/ConceptEmbed.js +57 -301
  10. package/es/Embed/ConceptListEmbed.js +18 -24
  11. package/es/Embed/ContentLinkEmbed.js +10 -10
  12. package/es/Embed/CopyrightEmbed.js +4 -21
  13. package/es/Embed/ExternalEmbed.js +10 -18
  14. package/es/Embed/FootnoteEmbed.js +11 -8
  15. package/es/Embed/GlossEmbed.js +68 -0
  16. package/es/Embed/H5pEmbed.js +19 -19
  17. package/es/Embed/IframeEmbed.js +9 -6
  18. package/es/Embed/InlineTriggerButton.js +70 -0
  19. package/es/Embed/UnknownEmbed.js +9 -9
  20. package/es/Embed/UuDisclaimerEmbed.js +14 -25
  21. package/es/Embed/index.js +1 -3
  22. package/es/ErrorMessage/ErrorMessage.js +41 -22
  23. package/es/ErrorMessage/ErrorResourceAccessDenied.js +8 -6
  24. package/es/FactBox/FactBox.js +118 -47
  25. package/es/FileList/PdfFile.js +23 -5
  26. package/es/Gloss/Gloss.js +116 -86
  27. package/es/Gloss/GlossExample.js +49 -51
  28. package/es/LinkBlock/LinkBlock.js +61 -33
  29. package/es/LinkBlock/LinkBlockSection.js +9 -6
  30. package/es/Logo/Logo.js +1 -30
  31. package/es/RelatedArticleList/RelatedArticleList.js +70 -87
  32. package/es/ResourceBox/ResourceBox.js +65 -37
  33. package/es/TagSelector/TagSelector.js +124 -131
  34. package/es/i18n/index.js +2 -1
  35. package/es/i18n/useComponentTranslations.js +83 -0
  36. package/es/index.js +4 -11
  37. package/es/locale/messages-en.js +30 -4
  38. package/es/locale/messages-nb.js +30 -4
  39. package/es/locale/messages-nn.js +30 -4
  40. package/es/locale/messages-se.js +30 -4
  41. package/es/locale/messages-sma.js +30 -4
  42. package/es/model/ContentType.js +3 -0
  43. package/es/styles.css +511 -0
  44. package/lib/Article/ArticleParagraph.js +12 -14
  45. package/lib/CampaignBlock/CampaignBlock.d.ts +2 -2
  46. package/lib/CampaignBlock/CampaignBlock.js +106 -68
  47. package/lib/Concept/Concept.d.ts +18 -0
  48. package/lib/Concept/Concept.js +75 -0
  49. package/lib/ContentTypeBadge/ContentTypeBadgeNew.d.ts +17 -0
  50. package/lib/ContentTypeBadge/ContentTypeBadgeNew.js +56 -0
  51. package/lib/Embed/AudioEmbed.js +2 -3
  52. package/lib/Embed/BrightcoveEmbed.d.ts +1 -2
  53. package/lib/Embed/BrightcoveEmbed.js +16 -25
  54. package/lib/Embed/ConceptEmbed.d.ts +15 -21
  55. package/lib/Embed/ConceptEmbed.js +58 -301
  56. package/lib/Embed/ConceptListEmbed.js +21 -26
  57. package/lib/Embed/ContentLinkEmbed.js +10 -11
  58. package/lib/Embed/CopyrightEmbed.js +6 -22
  59. package/lib/Embed/ExternalEmbed.d.ts +1 -2
  60. package/lib/Embed/ExternalEmbed.js +13 -19
  61. package/lib/Embed/FootnoteEmbed.js +11 -9
  62. package/lib/Embed/GlossEmbed.d.ts +13 -0
  63. package/lib/Embed/GlossEmbed.js +76 -0
  64. package/lib/Embed/H5pEmbed.d.ts +1 -2
  65. package/lib/Embed/H5pEmbed.js +21 -19
  66. package/lib/Embed/IframeEmbed.d.ts +1 -2
  67. package/lib/Embed/IframeEmbed.js +11 -8
  68. package/lib/Embed/InlineTriggerButton.d.ts +11 -0
  69. package/lib/Embed/InlineTriggerButton.js +76 -0
  70. package/lib/Embed/UnknownEmbed.js +9 -10
  71. package/lib/Embed/UuDisclaimerEmbed.js +16 -26
  72. package/lib/Embed/index.d.ts +2 -3
  73. package/lib/Embed/index.js +2 -9
  74. package/lib/ErrorMessage/ErrorMessage.js +40 -23
  75. package/lib/ErrorMessage/ErrorResourceAccessDenied.js +7 -6
  76. package/lib/FactBox/FactBox.d.ts +0 -1
  77. package/lib/FactBox/FactBox.js +119 -46
  78. package/lib/FileList/PdfFile.js +23 -5
  79. package/lib/Gloss/Gloss.d.ts +10 -2
  80. package/lib/Gloss/Gloss.js +116 -85
  81. package/lib/Gloss/GlossExample.d.ts +3 -5
  82. package/lib/Gloss/GlossExample.js +49 -52
  83. package/lib/LinkBlock/LinkBlock.js +62 -34
  84. package/lib/LinkBlock/LinkBlockSection.js +9 -7
  85. package/lib/Logo/Logo.d.ts +1 -3
  86. package/lib/Logo/Logo.js +2 -30
  87. package/lib/RelatedArticleList/RelatedArticleList.d.ts +4 -4
  88. package/lib/RelatedArticleList/RelatedArticleList.js +74 -90
  89. package/lib/ResourceBox/ResourceBox.js +64 -37
  90. package/lib/TagSelector/TagSelector.d.ts +27 -12
  91. package/lib/TagSelector/TagSelector.js +126 -131
  92. package/lib/i18n/index.d.ts +1 -0
  93. package/lib/i18n/index.js +20 -1
  94. package/lib/i18n/useComponentTranslations.d.ts +14 -0
  95. package/lib/i18n/useComponentTranslations.js +93 -0
  96. package/lib/index.d.ts +5 -14
  97. package/lib/index.js +70 -89
  98. package/lib/locale/messages-en.d.ts +26 -0
  99. package/lib/locale/messages-en.js +30 -4
  100. package/lib/locale/messages-nb.d.ts +26 -0
  101. package/lib/locale/messages-nb.js +30 -4
  102. package/lib/locale/messages-nn.d.ts +26 -0
  103. package/lib/locale/messages-nn.js +30 -4
  104. package/lib/locale/messages-se.d.ts +26 -0
  105. package/lib/locale/messages-se.js +30 -4
  106. package/lib/locale/messages-sma.d.ts +26 -0
  107. package/lib/locale/messages-sma.js +30 -4
  108. package/lib/model/ContentType.d.ts +3 -0
  109. package/lib/model/ContentType.js +4 -1
  110. package/lib/styles.css +511 -0
  111. package/package.json +11 -13
  112. package/src/Article/ArticleParagraph.tsx +11 -9
  113. package/src/CampaignBlock/CampaignBlock.tsx +92 -55
  114. package/src/Concept/Concept.stories.tsx +142 -0
  115. package/src/Concept/Concept.tsx +73 -0
  116. package/src/ContentTypeBadge/ContentTypeBadgeNew.stories.tsx +70 -0
  117. package/src/ContentTypeBadge/ContentTypeBadgeNew.tsx +69 -0
  118. package/src/Embed/AudioEmbed.tsx +2 -2
  119. package/src/Embed/BrightcoveEmbed.stories.tsx +0 -3
  120. package/src/Embed/BrightcoveEmbed.tsx +17 -19
  121. package/src/Embed/ConceptEmbed.stories.tsx +1 -105
  122. package/src/Embed/ConceptEmbed.tsx +60 -385
  123. package/src/Embed/ConceptListEmbed.tsx +20 -19
  124. package/src/Embed/ContentLinkEmbed.tsx +8 -10
  125. package/src/Embed/CopyrightEmbed.tsx +1 -11
  126. package/src/Embed/ExternalEmbed.tsx +14 -17
  127. package/src/Embed/FootnoteEmbed.stories.tsx +2 -5
  128. package/src/Embed/FootnoteEmbed.tsx +13 -16
  129. package/src/Embed/GlossEmbed.stories.tsx +140 -0
  130. package/src/Embed/GlossEmbed.tsx +64 -0
  131. package/src/Embed/H5pEmbed.tsx +22 -16
  132. package/src/Embed/IframeEmbed.tsx +12 -6
  133. package/src/Embed/InlineTriggerButton.tsx +72 -0
  134. package/src/Embed/UnknownEmbed.tsx +6 -7
  135. package/src/Embed/UuDisclaimerEmbed.stories.tsx +4 -4
  136. package/src/Embed/UuDisclaimerEmbed.tsx +17 -25
  137. package/src/Embed/index.ts +2 -3
  138. package/src/ErrorMessage/ErrorMessage.tsx +40 -29
  139. package/src/ErrorMessage/ErrorResourceAccessDenied.tsx +8 -6
  140. package/src/FactBox/FactBox.tsx +115 -115
  141. package/src/FactBox/Factbox.stories.tsx +43 -27
  142. package/src/FileList/FileList.stories.tsx +6 -1
  143. package/src/FileList/PdfFile.tsx +22 -5
  144. package/src/Gloss/Gloss.stories.tsx +107 -1
  145. package/src/Gloss/Gloss.tsx +143 -156
  146. package/src/Gloss/GlossExample.tsx +51 -77
  147. package/src/LinkBlock/LinkBlock.stories.tsx +8 -10
  148. package/src/LinkBlock/LinkBlock.tsx +54 -59
  149. package/src/LinkBlock/LinkBlockSection.tsx +9 -12
  150. package/src/Logo/Logo.stories.tsx +0 -1
  151. package/src/Logo/Logo.tsx +2 -30
  152. package/src/RelatedArticleList/RelatedArticleList.tsx +69 -88
  153. package/src/ResourceBox/ResourceBox.tsx +63 -59
  154. package/src/TagSelector/TagSelector.stories.tsx +92 -68
  155. package/src/TagSelector/TagSelector.tsx +161 -126
  156. package/src/i18n/index.ts +5 -0
  157. package/src/i18n/useComponentTranslations.ts +72 -0
  158. package/src/index.ts +23 -18
  159. package/src/locale/messages-en.ts +28 -2
  160. package/src/locale/messages-nb.ts +28 -2
  161. package/src/locale/messages-nn.ts +28 -2
  162. package/src/locale/messages-se.ts +28 -2
  163. package/src/locale/messages-sma.ts +28 -2
  164. package/src/model/ContentType.ts +3 -0
  165. package/es/DefinitionList/DefinitionDescription.js +0 -28
  166. package/es/DefinitionList/DefinitionTerm.js +0 -28
  167. package/es/DefinitionList/index.js +0 -10
  168. package/es/Embed/conceptComponents.js +0 -155
  169. package/es/ExpandableBox/ExpandableBox.js +0 -29
  170. package/es/ExpandableBox/index.js +0 -9
  171. package/es/Figure/Figure.js +0 -73
  172. package/es/Figure/index.js +0 -9
  173. package/es/FramedContent/FramedContent.js +0 -28
  174. package/es/FramedContent/index.js +0 -10
  175. package/es/Image/Image.js +0 -99
  176. package/es/Image/ImageLink.js +0 -39
  177. package/es/Image/index.js +0 -12
  178. package/es/LetterFilter/LetterFilter.js +0 -54
  179. package/es/LetterFilter/alphabet.js +0 -9
  180. package/es/LetterFilter/index.js +0 -10
  181. package/es/Notion/Notion.js +0 -76
  182. package/es/Notion/NotionImage.js +0 -46
  183. package/es/Notion/index.js +0 -9
  184. package/es/Table/Table.js +0 -141
  185. package/es/Table/index.js +0 -11
  186. package/es/TagSelector/Control.js +0 -28
  187. package/es/TagSelector/DropdownIndicator.js +0 -60
  188. package/es/TagSelector/Input.js +0 -22
  189. package/es/TagSelector/Menu.js +0 -27
  190. package/es/TagSelector/MenuList.js +0 -28
  191. package/es/TagSelector/Option.js +0 -60
  192. package/es/TagSelector/SelectContainer.js +0 -27
  193. package/es/TagSelector/ValueButton.js +0 -53
  194. package/es/TagSelector/ariaMessages.js +0 -94
  195. package/es/TagSelector/index.js +0 -10
  196. package/es/TagSelector/types.js +0 -1
  197. package/lib/DefinitionList/DefinitionDescription.d.ts +0 -10
  198. package/lib/DefinitionList/DefinitionDescription.js +0 -35
  199. package/lib/DefinitionList/DefinitionTerm.d.ts +0 -10
  200. package/lib/DefinitionList/DefinitionTerm.js +0 -35
  201. package/lib/DefinitionList/index.d.ts +0 -9
  202. package/lib/DefinitionList/index.js +0 -20
  203. package/lib/Embed/conceptComponents.d.ts +0 -40
  204. package/lib/Embed/conceptComponents.js +0 -163
  205. package/lib/ExpandableBox/ExpandableBox.d.ts +0 -15
  206. package/lib/ExpandableBox/ExpandableBox.js +0 -37
  207. package/lib/ExpandableBox/index.d.ts +0 -8
  208. package/lib/ExpandableBox/index.js +0 -18
  209. package/lib/Figure/Figure.d.ts +0 -16
  210. package/lib/Figure/Figure.js +0 -81
  211. package/lib/Figure/index.d.ts +0 -9
  212. package/lib/Figure/index.js +0 -13
  213. package/lib/FramedContent/FramedContent.d.ts +0 -12
  214. package/lib/FramedContent/FramedContent.js +0 -35
  215. package/lib/FramedContent/index.d.ts +0 -9
  216. package/lib/FramedContent/index.js +0 -16
  217. package/lib/Image/Image.d.ts +0 -38
  218. package/lib/Image/Image.js +0 -105
  219. package/lib/Image/ImageLink.d.ts +0 -18
  220. package/lib/Image/ImageLink.js +0 -44
  221. package/lib/Image/index.d.ts +0 -12
  222. package/lib/Image/index.js +0 -30
  223. package/lib/LetterFilter/LetterFilter.d.ts +0 -14
  224. package/lib/LetterFilter/LetterFilter.js +0 -61
  225. package/lib/LetterFilter/alphabet.d.ts +0 -8
  226. package/lib/LetterFilter/alphabet.js +0 -15
  227. package/lib/LetterFilter/index.d.ts +0 -9
  228. package/lib/LetterFilter/index.js +0 -16
  229. package/lib/Notion/Notion.d.ts +0 -20
  230. package/lib/Notion/Notion.js +0 -82
  231. package/lib/Notion/NotionImage.d.ts +0 -13
  232. package/lib/Notion/NotionImage.js +0 -54
  233. package/lib/Notion/index.d.ts +0 -8
  234. package/lib/Notion/index.js +0 -13
  235. package/lib/Table/Table.d.ts +0 -19
  236. package/lib/Table/Table.js +0 -145
  237. package/lib/Table/index.d.ts +0 -10
  238. package/lib/Table/index.js +0 -23
  239. package/lib/TagSelector/Control.d.ts +0 -11
  240. package/lib/TagSelector/Control.js +0 -35
  241. package/lib/TagSelector/DropdownIndicator.d.ts +0 -11
  242. package/lib/TagSelector/DropdownIndicator.js +0 -64
  243. package/lib/TagSelector/Input.d.ts +0 -12
  244. package/lib/TagSelector/Input.js +0 -29
  245. package/lib/TagSelector/Menu.d.ts +0 -12
  246. package/lib/TagSelector/Menu.js +0 -34
  247. package/lib/TagSelector/MenuList.d.ts +0 -16
  248. package/lib/TagSelector/MenuList.js +0 -35
  249. package/lib/TagSelector/Option.d.ts +0 -12
  250. package/lib/TagSelector/Option.js +0 -67
  251. package/lib/TagSelector/SelectContainer.d.ts +0 -11
  252. package/lib/TagSelector/SelectContainer.js +0 -34
  253. package/lib/TagSelector/ValueButton.d.ts +0 -20
  254. package/lib/TagSelector/ValueButton.js +0 -60
  255. package/lib/TagSelector/ariaMessages.d.ts +0 -16
  256. package/lib/TagSelector/ariaMessages.js +0 -101
  257. package/lib/TagSelector/index.d.ts +0 -11
  258. package/lib/TagSelector/index.js +0 -13
  259. package/lib/TagSelector/types.d.ts +0 -11
  260. package/lib/TagSelector/types.js +0 -5
  261. package/src/DefinitionList/DefinitionDescription.tsx +0 -26
  262. package/src/DefinitionList/DefinitionTerm.tsx +0 -26
  263. package/src/DefinitionList/index.tsx +0 -10
  264. package/src/Embed/conceptComponents.tsx +0 -293
  265. package/src/ExpandableBox/ExpandableBox.stories.tsx +0 -41
  266. package/src/ExpandableBox/ExpandableBox.tsx +0 -23
  267. package/src/ExpandableBox/index.ts +0 -9
  268. package/src/Figure/Figure.tsx +0 -167
  269. package/src/Figure/index.ts +0 -11
  270. package/src/FramedContent/FramedContent.stories.tsx +0 -152
  271. package/src/FramedContent/FramedContent.tsx +0 -26
  272. package/src/FramedContent/index.ts +0 -10
  273. package/src/Image/Image.stories.tsx +0 -61
  274. package/src/Image/Image.tsx +0 -147
  275. package/src/Image/ImageLink.tsx +0 -37
  276. package/src/Image/index.ts +0 -14
  277. package/src/LetterFilter/LetterFilter.stories.tsx +0 -29
  278. package/src/LetterFilter/LetterFilter.tsx +0 -78
  279. package/src/LetterFilter/alphabet.ts +0 -39
  280. package/src/LetterFilter/index.ts +0 -11
  281. package/src/Notion/Notion.tsx +0 -96
  282. package/src/Notion/NotionImage.tsx +0 -64
  283. package/src/Notion/index.ts +0 -9
  284. package/src/Table/Table.stories.tsx +0 -738
  285. package/src/Table/Table.tsx +0 -284
  286. package/src/Table/index.ts +0 -12
  287. package/src/TagSelector/Control.tsx +0 -34
  288. package/src/TagSelector/DropdownIndicator.tsx +0 -55
  289. package/src/TagSelector/Input.tsx +0 -31
  290. package/src/TagSelector/Menu.tsx +0 -38
  291. package/src/TagSelector/MenuList.tsx +0 -30
  292. package/src/TagSelector/Option.tsx +0 -58
  293. package/src/TagSelector/SelectContainer.tsx +0 -31
  294. package/src/TagSelector/ValueButton.tsx +0 -47
  295. package/src/TagSelector/ariaMessages.ts +0 -96
  296. package/src/TagSelector/index.ts +0 -14
  297. package/src/TagSelector/types.ts +0 -12
@@ -6,14 +6,13 @@
6
6
  *
7
7
  */
8
8
 
9
- /** @jsxImportSource @emotion/react */
10
9
  import parse from "html-react-parser";
11
- import { css } from "@emotion/react";
12
- import styled from "@emotion/styled";
13
- import { breakpoints, colors, fonts, spacing, mq, misc } from "@ndla/core";
10
+ import { ReactNode } from "react";
14
11
  import { Forward } from "@ndla/icons/common";
12
+ import { Text } from "@ndla/primitives";
15
13
  import { SafeLink } from "@ndla/safelink";
16
- import { HeadingLevel } from "@ndla/typography";
14
+ import { styled } from "@ndla/styled-system/jsx";
15
+ import { HeadingLevel } from "../types";
17
16
  import { getPossiblyRelativeUrl } from "../utils/relativeUrl";
18
17
 
19
18
  interface Image {
@@ -35,74 +34,112 @@ interface Props {
35
34
  path?: string;
36
35
  }
37
36
 
38
- const Container = styled.div`
39
- display: flex;
40
- flex-direction: column;
41
- gap: ${spacing.normal};
42
- border: 1px ${colors.brand.lighter} solid;
43
- border-radius: ${misc.borderRadius};
44
- padding: ${spacing.normal};
45
- background-color: ${colors.white};
46
- &[data-image-side="right"] {
47
- flex-direction: column-reverse;
48
- }
49
- ${mq.range({ from: breakpoints.tabletWide })} {
50
- max-width: 1100px;
51
- flex-direction: row;
52
- &[data-image-side="right"] {
53
- flex-direction: row-reverse;
54
- }
55
- }
56
- `;
37
+ const Container = styled("div", {
38
+ base: {
39
+ display: "flex",
40
+ flexDirection: "column",
41
+ border: "1px solid",
42
+ borderColor: "stroke.default",
43
+ backgroundColor: "background.default",
44
+ borderRadius: "xsmall",
45
+ boxShadow: "full",
46
+ maxWidth: "surface.xsmall",
47
+ overflow: "hidden",
48
+ mobileWide: {
49
+ maxWidth: "surface.medium",
50
+ },
51
+ tabletWide: {
52
+ // TODO: This is probably not the correct max-width. And it should be a token
53
+ maxWidth: "1100px",
54
+ flexDirection: "row",
55
+ },
56
+ },
57
+ });
57
58
 
58
- const headingStyle = css`
59
- margin: 0;
60
- `;
59
+ const LinkText = styled(Text, {
60
+ base: {
61
+ display: "flex",
62
+ gap: "xxsmall",
63
+ textDecoration: "underline",
64
+ _hover: {
65
+ textDecoration: "none",
66
+ },
67
+ },
68
+ });
69
+ const StyledImg = styled("img", {
70
+ base: {
71
+ alignSelf: "center",
72
+ objectFit: "cover",
73
+ width: "100%",
74
+ height: "215px",
75
+ desktop: {
76
+ height: "340px",
77
+ },
78
+ },
79
+ });
61
80
 
62
- const StyledDescription = styled.p`
63
- font-family: ${fonts.serif};
64
- margin: ${spacing.normal} 0 ${spacing.medium};
65
- `;
81
+ const ContentWrapper = styled("div", {
82
+ base: {
83
+ width: "100%",
84
+ position: "relative",
85
+ display: "flex",
86
+ flexDirection: "column",
87
+ gap: "xsmall",
88
+ alignItems: "flex-start",
89
+ paddingBlock: "medium",
90
+ paddingInline: "medium",
91
+ },
92
+ });
66
93
 
67
- const StyledImg = styled.img`
68
- align-self: center;
69
- object-fit: contain;
70
- `;
94
+ interface MaybeLinkTextProps {
95
+ url?: string;
96
+ path?: string;
97
+ children: ReactNode;
98
+ }
71
99
 
72
- const StyledLink = styled(SafeLink)`
73
- display: inline-flex;
74
- align-items: center;
75
- gap: ${spacing.xxsmall};
76
- color: ${colors.brand.primary};
77
- `;
100
+ const StyledSafeLink = styled(SafeLink, {
101
+ base: {
102
+ color: "inherit",
103
+ },
104
+ });
78
105
 
79
- const TextWrapper = styled.div`
80
- flex-grow: 1;
81
- `;
106
+ const MaybeLinkText = ({ url, children, path }: MaybeLinkTextProps) => {
107
+ if (url) return <StyledSafeLink to={getPossiblyRelativeUrl(url, path)}>{children}</StyledSafeLink>;
108
+ return children;
109
+ };
82
110
 
83
111
  const CampaignBlock = ({
84
112
  title,
85
113
  image,
86
114
  imageSide = "left",
87
115
  description,
88
- headingLevel: Heading = "h2",
116
+ headingLevel: InternalHeading = "h2",
89
117
  url,
90
118
  path,
91
119
  className,
92
120
  }: Props) => {
121
+ const imageComponent = image && <StyledImg src={`${image.src}?width=455`} height={340} width={455} alt={image.alt} />;
122
+ const HeaderComponent = url?.url ? LinkText : Text;
93
123
  return (
94
- <Container className={className} data-type="campaign-block" data-image-side={imageSide}>
95
- {image && <StyledImg src={`${image.src}?width=240`} height={200} width={240} alt={image.alt} />}
96
- <TextWrapper>
97
- <Heading css={headingStyle}>{parse(title)}</Heading>
98
- <StyledDescription>{parse(description)}</StyledDescription>
124
+ <Container className={className} data-type="campaign-block">
125
+ {imageSide === "left" && imageComponent}
126
+ <ContentWrapper>
127
+ <MaybeLinkText url={url?.url} path={path}>
128
+ <HeaderComponent asChild consumeCss textStyle="heading.small">
129
+ <InternalHeading>{parse(title)}</InternalHeading>
130
+ </HeaderComponent>
131
+ </MaybeLinkText>
132
+ <Text textStyle="body.large">{parse(description)}</Text>
99
133
  {!!url?.url && (
100
- <StyledLink to={getPossiblyRelativeUrl(url.url, path)}>
101
- {parse(url.text ?? "")}
102
- <Forward />
103
- </StyledLink>
134
+ <MaybeLinkText url={url.url} path={path}>
135
+ <LinkText textStyle="body.medium">
136
+ {parse(url.text ?? "")}
137
+ <Forward />
138
+ </LinkText>
139
+ </MaybeLinkText>
104
140
  )}
105
- </TextWrapper>
141
+ </ContentWrapper>
142
+ {imageSide !== "left" && imageComponent}
106
143
  </Container>
107
144
  );
108
145
  };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Copyright (c) 2024-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { Meta, StoryObj } from "@storybook/react";
10
+ import { ConceptData } from "@ndla/types-embed";
11
+ import { Concept } from "./Concept";
12
+
13
+ const visualElementData: ConceptData["visualElement"] = {
14
+ resource: "image",
15
+ status: "success",
16
+ embedData: {
17
+ resource: "image",
18
+ resourceId: "61181",
19
+ size: "full",
20
+ align: "",
21
+ alt: "Tenåringsjente med lyse fletter slenger på håret. Foto. ",
22
+ caption:
23
+ "Den østerrikske tronfølgeren Franz Ferdinand og hans hustru Sophie var på besøk i Sarajevo i 1914. Begge ble skutt og drept av nasjonalisten Gavrilo Princip i det som er kjent som <em>skuddene i Sarajevo</em>. Denne hendelsen var den utløsende årsaken til første verdenskrig.",
24
+ url: "https://api.test.ndla.no/image-api/v2/images/61181",
25
+ },
26
+ data: {
27
+ id: "61181",
28
+ metaUrl: "https://api.test.ndla.no/image-api/v3/images/61181",
29
+ title: {
30
+ title: "\nHigh angle view of teenage girl with tousled dyed hair dancing at skateboard park\n",
31
+ language: "nb",
32
+ },
33
+ alttext: {
34
+ alttext: "Tenåringsjente med lyse fletter slenger på håret. Foto. ",
35
+ language: "nb",
36
+ },
37
+ copyright: {
38
+ license: {
39
+ license: "CC-BY-NC-4.0",
40
+ description: "Creative Commons Attribution-NonCommercial 4.0 International",
41
+ url: "https://creativecommons.org/licenses/by-nc/4.0/",
42
+ },
43
+ origin: "https://bilder.ntb.no/r/preview/creative/EXuziiZGWno",
44
+ creators: [
45
+ {
46
+ type: "photographer",
47
+ name: "Maskot",
48
+ },
49
+ ],
50
+ processors: [],
51
+ rightsholders: [
52
+ {
53
+ type: "rightsholder",
54
+ name: "NTB",
55
+ },
56
+ ],
57
+ processed: false,
58
+ },
59
+ tags: {
60
+ tags: ["danser", "kultur", "identitet"],
61
+ language: "nb",
62
+ },
63
+ caption: {
64
+ caption: "Modellklarert.",
65
+ language: "nb",
66
+ },
67
+ supportedLanguages: ["nb"],
68
+ created: "2022-01-07T08:26:01Z",
69
+ createdBy: "lA2KgVfhY-fpmgHCYAy5W1DX",
70
+ modelRelease: "yes",
71
+ image: {
72
+ fileName: "S81WiNgl.jpg",
73
+ size: 1685455,
74
+ contentType: "image/jpeg",
75
+ imageUrl: "https://api.test.ndla.no/image-api/raw/S81WiNgl.jpg",
76
+ dimensions: {
77
+ width: 2000,
78
+ height: 1333,
79
+ },
80
+ language: "nb",
81
+ },
82
+ },
83
+ };
84
+
85
+ export default {
86
+ title: "Components/Concept",
87
+ component: Concept,
88
+ tags: ["autodocs"],
89
+ args: {
90
+ title: "skin - formasjonsskade",
91
+ lang: "nb",
92
+ visualElement: visualElementData,
93
+ copyright: {
94
+ license: {
95
+ license: "CC-BY-SA-4.0",
96
+ description: "Creative Commons Attribution-ShareAlike 4.0 International",
97
+ url: "https://creativecommons.org/licenses/by-sa/4.0/",
98
+ },
99
+ creators: [{ type: "Writer", name: "Sissel Paaske" }],
100
+ processors: [
101
+ { type: "Processor", name: "Totaltekst" },
102
+ { type: "Correction", name: "Arbeidets art" },
103
+ ],
104
+ rightsholders: [],
105
+ processed: false,
106
+ },
107
+ children: (
108
+ <>
109
+ <p>
110
+ Ordet «skin» er engelsk og brukes om formasjonsskade som oppstår i boreprosessen i området som grenser inn til
111
+ brønnen. Skaden er størst i området nærmest hullet, men den kan bre seg utover et stykke fra brønnen. Skin
112
+ forteller om bergartens permeabilitet i reservoarsonen.
113
+ </p>
114
+ <p>Hullveggen skades både av borekronen, små partikler og væsken som brukes i brønnen.</p>
115
+ <p>
116
+ Skaden i bergarten gir dårligere forhold for oljen som skal strømme til brønnen. Gangene i bergarten plugges,
117
+ og det oppstår et trykkfall som reduserer produksjonstrykket i brønnen.
118
+ </p>
119
+ <p>
120
+ Det er viktig å redusere omfanget av skaden ved å velge væsker som passer godt til bergartsegenskapene, og å
121
+ bore med en borekrone som skader minst mulig.
122
+ </p>
123
+ <p>Skader som er dannet av borevæske, kan repareres ved å syrebehandle hullets overflate.</p>
124
+ </>
125
+ ),
126
+ },
127
+ } satisfies Meta<typeof Concept>;
128
+
129
+ export const Default: StoryObj<typeof Concept> = {};
130
+
131
+ export const WithoutVisualElement: StoryObj<typeof Concept> = {
132
+ args: {
133
+ visualElement: undefined,
134
+ },
135
+ };
136
+
137
+ export const WithoutLicenseAndVisualElement: StoryObj<typeof Concept> = {
138
+ args: {
139
+ visualElement: undefined,
140
+ copyright: undefined,
141
+ },
142
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright (c) 2024-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { ComponentPropsWithRef, ReactNode, forwardRef } from "react";
10
+ import { Figure } from "@ndla/primitives";
11
+ import { styled } from "@ndla/styled-system/jsx";
12
+ import { IDraftCopyright as ConceptCopyright } from "@ndla/types-backend/concept-api";
13
+ import { ConceptVisualElementMeta } from "@ndla/types-embed";
14
+ import { BrightcoveEmbed, ExternalEmbed, H5pEmbed, IframeEmbed, ImageEmbed } from "../Embed";
15
+ import { LicenseContainerContent } from "../LicenseByline/EmbedByline";
16
+
17
+ export interface ConceptProps extends ComponentPropsWithRef<"figure"> {
18
+ copyright?: ConceptCopyright;
19
+ visualElement?: ConceptVisualElementMeta;
20
+ lang?: string;
21
+ title?: string;
22
+ children?: ReactNode;
23
+ }
24
+
25
+ const StyledFigure = styled(Figure, {
26
+ base: {
27
+ display: "flex",
28
+ flexDirection: "column",
29
+ gap: "medium",
30
+ },
31
+ });
32
+
33
+ const ContentWrapper = styled("div", {
34
+ base: {
35
+ textStyle: "body.large",
36
+ display: "inline",
37
+ "& p": {
38
+ display: "inline",
39
+ },
40
+ },
41
+ });
42
+
43
+ // TODO: Figure out if we need to support tags, subjects and headerButtons.
44
+
45
+ export const Concept = forwardRef<HTMLElement, ConceptProps>(
46
+ ({ copyright, visualElement, lang, children, title, ...rest }, ref) => {
47
+ return (
48
+ <StyledFigure ref={ref} {...rest}>
49
+ <ContentWrapper lang={lang}>
50
+ {!!title && (
51
+ <>
52
+ <b>{title}</b>
53
+ {` – `}
54
+ </>
55
+ )}
56
+ {children}
57
+ </ContentWrapper>
58
+ {visualElement?.resource === "image" ? (
59
+ <ImageEmbed embed={visualElement} lang={lang} />
60
+ ) : visualElement?.resource === "brightcove" ? (
61
+ <BrightcoveEmbed embed={visualElement} />
62
+ ) : visualElement?.resource === "h5p" ? (
63
+ <H5pEmbed embed={visualElement} />
64
+ ) : visualElement?.resource === "iframe" ? (
65
+ <IframeEmbed embed={visualElement} />
66
+ ) : visualElement?.resource === "external" ? (
67
+ <ExternalEmbed embed={visualElement} />
68
+ ) : null}
69
+ {copyright && <LicenseContainerContent copyright={copyright} type="concept" />}
70
+ </StyledFigure>
71
+ );
72
+ },
73
+ );
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Copyright (c) 2024-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { useTranslation } from "react-i18next";
10
+ import { Meta, StoryFn, StoryObj } from "@storybook/react";
11
+ import { Video } from "@ndla/icons/editor";
12
+ import { HStack, styled } from "@ndla/styled-system/jsx";
13
+ import { ContentTypeBadge } from "./ContentTypeBadgeNew";
14
+
15
+ export default {
16
+ title: "Components/ContentTypeBadgeNew",
17
+ component: ContentTypeBadge,
18
+ tags: ["autodocs"],
19
+ parameters: {
20
+ inlineStories: true,
21
+ },
22
+ args: {
23
+ contentType: "subject-material",
24
+ },
25
+ } satisfies Meta<typeof ContentTypeBadge>;
26
+
27
+ export const Default: StoryObj<typeof ContentTypeBadge> = {};
28
+
29
+ const StyledHStack = styled(HStack, {
30
+ base: {
31
+ flexWrap: "wrap",
32
+ },
33
+ });
34
+
35
+ export const AllBadges: StoryFn<typeof ContentTypeBadge> = () => (
36
+ <StyledHStack gap="3xsmall">
37
+ <ContentTypeBadge contentType="subject-material" />
38
+ <ContentTypeBadge contentType="tasks-and-activities" />
39
+ <ContentTypeBadge contentType="assessment-resources" />
40
+ <ContentTypeBadge contentType="subject" />
41
+ <ContentTypeBadge contentType="source-material" />
42
+ <ContentTypeBadge contentType="learning-path" />
43
+ <ContentTypeBadge contentType="topic" />
44
+ <ContentTypeBadge contentType="multidisciplinary-topic" />
45
+ <ContentTypeBadge contentType="concept" />
46
+ <ContentTypeBadge contentType="external" />
47
+ <ContentTypeBadge contentType="image" />
48
+ <ContentTypeBadge contentType="audio" />
49
+ <ContentTypeBadge contentType="video" />
50
+ <ContentTypeBadge contentType="missing" />
51
+ </StyledHStack>
52
+ );
53
+
54
+ const StyledContentTypeBadge = styled(ContentTypeBadge, {
55
+ base: {
56
+ display: "flex",
57
+ gap: "4xsmall",
58
+ alignItems: "center",
59
+ },
60
+ });
61
+
62
+ export const ContentOverride: StoryFn<typeof ContentTypeBadge> = () => {
63
+ const { t } = useTranslation();
64
+ return (
65
+ <StyledContentTypeBadge contentType="video">
66
+ <Video size="small" />
67
+ {t("contentTypes.video")}
68
+ </StyledContentTypeBadge>
69
+ );
70
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Copyright (c) 2024-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { forwardRef } from "react";
10
+ import { useTranslation } from "react-i18next";
11
+ import { Badge, BadgeProps, type BadgeVariant } from "@ndla/primitives";
12
+ import * as contentTypes from "../model/ContentType";
13
+
14
+ export interface ContentTypeBadgeProps extends Omit<BadgeProps, "colorTheme"> {
15
+ contentType: ContentType | undefined;
16
+ }
17
+
18
+ type ContentType =
19
+ | typeof contentTypes.SUBJECT_MATERIAL
20
+ | typeof contentTypes.TASKS_AND_ACTIVITIES
21
+ | typeof contentTypes.ASSESSMENT_RESOURCES
22
+ | typeof contentTypes.SUBJECT
23
+ | typeof contentTypes.SOURCE_MATERIAL
24
+ | typeof contentTypes.LEARNING_PATH
25
+ | typeof contentTypes.TOPIC
26
+ | typeof contentTypes.MULTIDISCIPLINARY_TOPIC
27
+ | typeof contentTypes.CONCEPT
28
+ | typeof contentTypes.EXTERNAL
29
+ | typeof contentTypes.IMAGE
30
+ | typeof contentTypes.AUDIO
31
+ | typeof contentTypes.VIDEO
32
+ | typeof contentTypes.MISSING
33
+ // This allows for us to fallback to string without getting a ts error, while still keeping intellisense
34
+ | (string & {});
35
+
36
+ export const contentTypeToBadgeVariantMap: Record<ContentType, BadgeVariant> = {
37
+ [contentTypes.SUBJECT_MATERIAL]: "brand1",
38
+ [contentTypes.TASKS_AND_ACTIVITIES]: "brand2",
39
+ [contentTypes.ASSESSMENT_RESOURCES]: "brand2",
40
+ [contentTypes.SUBJECT]: "neutral",
41
+ [contentTypes.SOURCE_MATERIAL]: "brand1",
42
+ [contentTypes.LEARNING_PATH]: "brand3",
43
+ [contentTypes.TOPIC]: "neutral",
44
+ // TODO: Verify this color
45
+ [contentTypes.MULTIDISCIPLINARY_TOPIC]: "neutral",
46
+ [contentTypes.CONCEPT]: "brand1",
47
+ // TODO: Verify this color
48
+ [contentTypes.EXTERNAL]: "brand2",
49
+ // TODO: Verify resourceEmbedTypeMapping colors
50
+ [contentTypes.IMAGE]: "brand1",
51
+ [contentTypes.AUDIO]: "brand1",
52
+ [contentTypes.VIDEO]: "brand1",
53
+ [contentTypes.MISSING]: "neutral",
54
+ };
55
+
56
+ export const ContentTypeBadge = forwardRef<HTMLDivElement, ContentTypeBadgeProps>(
57
+ ({ contentType, children, ...props }, ref) => {
58
+ const { t } = useTranslation();
59
+ return (
60
+ <Badge
61
+ colorTheme={contentTypeToBadgeVariantMap[contentType ?? "missing"] ?? contentTypeToBadgeVariantMap["missing"]}
62
+ {...props}
63
+ ref={ref}
64
+ >
65
+ {children ?? t(`contentTypes.${contentType}`)}
66
+ </Badge>
67
+ );
68
+ },
69
+ );
@@ -6,11 +6,11 @@
6
6
  *
7
7
  */
8
8
 
9
+ import { Figure } from "@ndla/primitives";
9
10
  import { AudioMetaData } from "@ndla/types-embed";
10
11
  import EmbedErrorPlaceholder from "./EmbedErrorPlaceholder";
11
12
  import { Author } from "./ImageEmbed";
12
13
  import AudioPlayer from "../AudioPlayer";
13
- import { Figure } from "../Figure";
14
14
  import { EmbedByline } from "../LicenseByline";
15
15
 
16
16
  interface Props {
@@ -42,7 +42,7 @@ const AudioEmbed = ({ embed, lang }: Props) => {
42
42
  const img = coverPhoto && { url: coverPhoto.url, alt: coverPhoto.altText };
43
43
 
44
44
  return (
45
- <Figure type="full" lang={lang}>
45
+ <Figure lang={lang}>
46
46
  <AudioPlayer
47
47
  description={data.podcastMeta?.introduction ?? ""}
48
48
  img={img}
@@ -155,9 +155,6 @@ const meta: Meta<typeof BrightcoveEmbed> = {
155
155
  title: "Embeds/BrightcoveEmbed",
156
156
  component: BrightcoveEmbed,
157
157
  tags: ["autodocs"],
158
- args: {
159
- isConcept: false,
160
- },
161
158
  decorators: [
162
159
  (Story) => (
163
160
  <OneColumn>
@@ -9,28 +9,30 @@
9
9
  import parse from "html-react-parser";
10
10
  import { useEffect, useMemo, useRef, useState } from "react";
11
11
  import { useTranslation } from "react-i18next";
12
- import styled from "@emotion/styled";
13
- import { ButtonV2 } from "@ndla/button";
14
- import { spacing } from "@ndla/core";
12
+ import { Button, Figure } from "@ndla/primitives";
13
+ import { styled } from "@ndla/styled-system/jsx";
15
14
  import { BrightcoveEmbedData, BrightcoveMetaData, BrightcoveVideoSource } from "@ndla/types-embed";
16
15
  import EmbedErrorPlaceholder from "./EmbedErrorPlaceholder";
17
16
  import { RenderContext } from "./types";
18
- import { Figure } from "../Figure";
19
17
  import { EmbedByline } from "../LicenseByline";
20
18
 
21
19
  interface Props {
22
20
  embed: BrightcoveMetaData;
23
- isConcept?: boolean;
24
21
  renderContext?: RenderContext;
25
22
  }
26
23
 
27
- const LinkedVideoButton = styled(ButtonV2)`
28
- margin-left: ${spacing.small};
29
- `;
24
+ const LinkedVideoButton = styled(Button, {
25
+ base: {
26
+ marginInlineStart: "xsmall",
27
+ },
28
+ });
30
29
 
31
- const BrightcoveIframe = styled.iframe`
32
- height: auto;
33
- `;
30
+ const BrightcoveIframe = styled("iframe", {
31
+ base: {
32
+ height: "auto",
33
+ width: "100%",
34
+ },
35
+ });
34
36
 
35
37
  export const makeIframeString = (url: string, width: string | number, height: string | number, title = "") => {
36
38
  const strippedWidth = typeof width === "number" ? width : width.replace(/\s*px/, "");
@@ -52,7 +54,7 @@ const getIframeProps = (data: BrightcoveEmbedData, sources: BrightcoveVideoSourc
52
54
  width: source?.width ?? "640",
53
55
  };
54
56
  };
55
- const BrightcoveEmbed = ({ embed, isConcept, renderContext = "article" }: Props) => {
57
+ const BrightcoveEmbed = ({ embed, renderContext = "article" }: Props) => {
56
58
  const [showOriginalVideo, setShowOriginalVideo] = useState(true);
57
59
  const { t } = useTranslation();
58
60
  const iframeRef = useRef<HTMLIFrameElement>(null);
@@ -99,7 +101,7 @@ const BrightcoveEmbed = ({ embed, isConcept, renderContext = "article" }: Props)
99
101
  : undefined;
100
102
 
101
103
  return (
102
- <Figure type={isConcept ? "full-column" : "full"}>
104
+ <Figure>
103
105
  <div className="brightcove-video">
104
106
  <BrightcoveIframe
105
107
  ref={iframeRef}
@@ -112,13 +114,9 @@ const BrightcoveEmbed = ({ embed, isConcept, renderContext = "article" }: Props)
112
114
  />
113
115
  </div>
114
116
  <EmbedByline type="video" copyright={data.copyright!} description={parsedDescription} bottomRounded>
117
+ {/* TODO: Figure out if this button should still be here. If yes, figure out what it should look like. */}
115
118
  {!!linkedVideoId && (
116
- <LinkedVideoButton
117
- variant="outline"
118
- shape="pill"
119
- size="small"
120
- onClick={() => setShowOriginalVideo((p) => !p)}
121
- >
119
+ <LinkedVideoButton size="small" variant="secondary" onClick={() => setShowOriginalVideo((p) => !p)}>
122
120
  {t(`figure.button.${!showOriginalVideo ? "original" : "alternative"}`)}
123
121
  </LinkedVideoButton>
124
122
  )}