@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
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { Meta, StoryObj } from "@storybook/react";
10
10
  import { ConceptData, ConceptEmbedData } from "@ndla/types-embed";
11
- import ConceptEmbed from "./ConceptEmbed";
11
+ import { ConceptEmbed } from "./ConceptEmbed";
12
12
  import { ArticleWrapper } from "../Article";
13
13
  import LayoutItem, { OneColumn } from "../Layout";
14
14
 
@@ -19,13 +19,6 @@ const blockEmbedData: ConceptEmbedData = {
19
19
  linkText: "",
20
20
  };
21
21
 
22
- const glossBlockEmbedData: ConceptEmbedData = {
23
- contentId: "4942",
24
- resource: "concept",
25
- type: "block",
26
- linkText: "",
27
- };
28
-
29
22
  const inlineEmbedData: ConceptEmbedData = {
30
23
  contentId: "2318",
31
24
  linkText: "forklaring",
@@ -33,13 +26,6 @@ const inlineEmbedData: ConceptEmbedData = {
33
26
  type: "inline",
34
27
  };
35
28
 
36
- const glossInlineEmbedData: ConceptEmbedData = {
37
- contentId: "23",
38
- linkText: "glose",
39
- resource: "concept",
40
- type: "inline",
41
- };
42
-
43
29
  const conceptMetaData: ConceptData["concept"] = {
44
30
  id: 110,
45
31
  revision: 16,
@@ -87,68 +73,6 @@ const conceptMetaData: ConceptData["concept"] = {
87
73
  conceptType: "concept",
88
74
  };
89
75
 
90
- const glossMetaData: ConceptData["concept"] = {
91
- id: 4942,
92
- revision: 6,
93
- title: {
94
- title: "Ma Hong",
95
- language: "nb",
96
- },
97
- content: {
98
- content: "Hei",
99
- htmlContent: "Hei",
100
- language: "nb",
101
- },
102
- copyright: {
103
- creators: [],
104
- processors: [],
105
- rightsholders: [],
106
- processed: false,
107
- },
108
- source: "",
109
- metaImage: {
110
- url: "",
111
- alt: "",
112
- language: "und",
113
- },
114
- created: "2023-07-19T09:30:40.000Z",
115
- updated: "2023-09-19T17:13:56.573Z",
116
- updatedBy: ["XxnkdI7rApMl58MeG3p4g4B8", "hd5ZL5Lm4kKkumWgN2gjy9wx"],
117
- supportedLanguages: ["nb"],
118
- articleIds: [],
119
- status: {
120
- current: "IN_PROGRESS",
121
- other: [],
122
- },
123
- responsible: {
124
- responsibleId: "XxnkdI7rApMl58MeG3p4g4B8",
125
- lastUpdated: "2023-07-19T09:30:40.000Z",
126
- },
127
- conceptType: "gloss",
128
- glossData: {
129
- gloss: "马红",
130
- wordClass: "personal-pronoun",
131
- originalLanguage: "zh",
132
- transcriptions: {},
133
- examples: [
134
- [
135
- {
136
- example: "我叫马红",
137
- language: "zh",
138
- transcriptions: {
139
- pinyin: "wo jiao ma hong ",
140
- },
141
- },
142
- {
143
- example: "Jeg heter ma hong",
144
- language: "nb",
145
- transcriptions: {},
146
- },
147
- ],
148
- ],
149
- },
150
- };
151
-
152
76
  const visualElementData: ConceptData["visualElement"] = {
153
77
  resource: "image",
154
78
  status: "success",
@@ -219,17 +143,10 @@ const blockMetaData: ConceptData = {
219
143
  visualElement: visualElementData,
220
144
  };
221
145
 
222
- const glossBlockData: ConceptData = {
223
- concept: glossMetaData,
224
- };
225
-
226
146
  const meta: Meta<typeof ConceptEmbed> = {
227
147
  title: "Embeds/ConceptEmbed",
228
148
  component: ConceptEmbed,
229
149
  tags: ["autodocs"],
230
- args: {
231
- fullWidth: false,
232
- },
233
150
  decorators: [
234
151
  (Story) => (
235
152
  <OneColumn>
@@ -257,16 +174,6 @@ export const Block: StoryObj<typeof ConceptEmbed> = {
257
174
  },
258
175
  },
259
176
  };
260
- export const GlossBlock: StoryObj<typeof ConceptEmbed> = {
261
- args: {
262
- embed: {
263
- resource: "concept",
264
- status: "success",
265
- embedData: glossBlockEmbedData,
266
- data: glossBlockData,
267
- },
268
- },
269
- };
270
177
 
271
178
  export const BlockFailed: StoryObj<typeof ConceptEmbed> = {
272
179
  args: {
@@ -289,17 +196,6 @@ export const Inline: StoryObj<typeof ConceptEmbed> = {
289
196
  },
290
197
  };
291
198
 
292
- export const GlossInline: StoryObj<typeof ConceptEmbed> = {
293
- args: {
294
- embed: {
295
- resource: "concept",
296
- status: "success",
297
- embedData: glossInlineEmbedData,
298
- data: glossBlockData,
299
- },
300
- },
301
- };
302
-
303
199
  export const InlineFailed: StoryObj<typeof ConceptEmbed> = {
304
200
  args: {
305
201
  embed: {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2023-present, NDLA.
2
+ * Copyright (c) 2024-present, NDLA.
3
3
  *
4
4
  * This source code is licensed under the GPLv3 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -7,431 +7,106 @@
7
7
  */
8
8
 
9
9
  import parse from "html-react-parser";
10
- import { ReactNode, forwardRef, useCallback, useMemo, useRef, useState } from "react";
11
- import { isMobile } from "react-device-detect";
12
- import { useTranslation } from "react-i18next";
13
- import styled from "@emotion/styled";
14
- import { Root, Trigger, Content, Anchor, Close, Portal } from "@radix-ui/react-popover";
15
- import { IconButtonV2 } from "@ndla/button";
16
- import { breakpoints, colors, mq, spacing, stackOrder } from "@ndla/core";
17
- import { Cross } from "@ndla/icons/action";
18
- import { Tooltip } from "@ndla/tooltip";
10
+ import { forwardRef, useMemo } from "react";
11
+ import { Figure, PopoverContent, PopoverRoot, PopoverTrigger } from "@ndla/primitives";
12
+ import { styled } from "@ndla/styled-system/jsx";
19
13
  import { ConceptMetaData } from "@ndla/types-embed";
20
- import { ConceptNotionV2, ConceptNotionData, ConceptType } from "./conceptComponents";
21
14
  import EmbedErrorPlaceholder from "./EmbedErrorPlaceholder";
15
+ import { GlossEmbed } from "./GlossEmbed";
16
+ import { InlineTriggerButton } from "./InlineTriggerButton";
22
17
  import { RenderContext } from "./types";
23
- import { Figure } from "../Figure";
24
- import { Gloss } from "../Gloss";
25
- import { EmbedByline } from "../LicenseByline";
26
- import { Notion as UINotion } from "../Notion";
27
- import { NotionImage } from "../Notion/NotionImage";
18
+ import { Concept, ConceptProps } from "../Concept/Concept";
28
19
 
29
- interface PopoverPosition {
30
- top?: number;
20
+ interface BaseProps {
21
+ renderContext?: RenderContext;
22
+ lang?: string;
31
23
  }
32
24
 
33
- const PopoverWrapper = styled.div<PopoverPosition>`
34
- div[data-radix-popper-content-wrapper] {
35
- position: absolute !important;
36
- left: 50% !important;
37
- transform: translateX(-50%) !important;
38
- top: ${({ top }) => top}px !important;
39
- z-index: ${stackOrder.popover} !important;
40
- }
41
-
42
- ${mq.range({ until: breakpoints.tablet })} {
43
- div[data-radix-popper-content-wrapper] {
44
- // Fix for popover positioning on mobile.
45
- // If we modify all popovers we break license icons.
46
- // https://github.com/radix-ui/primitives/issues/1839
47
- position: fixed !important;
48
- transform: none !important;
49
- top: 0 !important;
50
- left: 0 !important;
51
- width: 100vw;
52
- z-index: ${stackOrder.popover} !important;
53
- height: 100vh;
54
- min-width: 100vw !important;
55
- }
56
- }
57
- `;
58
-
59
- const ImageWrapper = styled.div`
60
- float: right;
61
- padding-left: ${spacing.normal};
62
- position: relative;
63
-
64
- ${mq.range({ until: breakpoints.tabletWide })} {
65
- width: 100%;
66
- padding-left: 0;
67
- }
68
- `;
69
-
70
- interface Props {
25
+ interface Props extends BaseProps {
71
26
  embed: ConceptMetaData;
72
- fullWidth?: boolean;
73
- lang?: string;
74
- renderContext?: RenderContext;
75
27
  }
76
28
 
77
- const StyledButton = styled.button`
78
- background: none;
79
- border: none;
80
- font-family: inherit;
81
- font-style: inherit;
82
- line-height: 1em;
83
- padding: 0 0 ${spacing.xxsmall} 0;
84
- margin-bottom: -${spacing.xxsmall};
85
- text-decoration: none;
86
- color: #000;
87
- position: relative;
88
- cursor: pointer;
89
- &:focus,
90
- &:hover {
91
- color: ${colors.brand.primary};
92
- outline: none;
93
- }
94
- `;
29
+ const StyledPopoverContent = styled(PopoverContent, {
30
+ base: {
31
+ width: "surface.xlarge",
32
+ },
33
+ });
95
34
 
96
- export const ConceptEmbed = ({ embed, fullWidth, lang, renderContext }: Props) => {
35
+ export const ConceptEmbed = ({ embed, renderContext, lang }: Props) => {
97
36
  const parsedContent = useMemo(() => {
98
37
  if (embed.status === "error" || !embed.data.concept.content) return undefined;
99
38
  return parse(embed.data.concept.content.htmlContent);
100
39
  }, [embed]);
40
+
101
41
  if (embed.status === "error" && embed.embedData.type === "inline") {
102
42
  return <span>{embed.embedData.linkText}</span>;
103
43
  }
104
44
  if (embed.status === "error") {
105
- return <EmbedErrorPlaceholder type="concept" />;
45
+ return <EmbedErrorPlaceholder type="gloss" />;
106
46
  }
107
47
 
108
- const {
109
- data: { concept, visualElement },
110
- } = embed;
48
+ const { concept, visualElement } = embed.data;
111
49
 
112
- if (embed.embedData.type === "block") {
113
- return (
114
- <BlockConcept
115
- fullWidth={fullWidth}
116
- title={concept.title}
117
- content={parsedContent}
118
- metaImage={concept.metaImage}
119
- copyright={concept.copyright}
120
- source={concept.source}
121
- visualElement={visualElement}
122
- conceptType={concept.conceptType}
123
- glossData={concept.glossData}
124
- lang={lang}
125
- exampleIds={embed.embedData.exampleIds}
126
- exampleLangs={embed.embedData.exampleLangs}
127
- />
128
- );
50
+ // TODO: Consider whether we should do this in article-converter instead.
51
+ if (embed.data.concept.glossData) {
52
+ return <GlossEmbed embed={embed} />;
129
53
  }
54
+
130
55
  if (embed.embedData.type === "inline") {
131
56
  return (
132
57
  <InlineConcept
133
- title={concept.title}
134
- content={parsedContent}
135
- metaImage={concept.metaImage}
58
+ linkText={embed.embedData.linkText}
136
59
  copyright={concept.copyright}
137
- source={concept.source}
138
60
  visualElement={visualElement}
139
- linkText={embed.embedData.linkText}
140
- conceptType={concept.conceptType}
141
- glossData={concept.glossData}
142
61
  lang={lang}
143
- exampleIds={embed.embedData.exampleIds}
144
- exampleLangs={embed.embedData.exampleLangs}
145
- />
62
+ title={concept.title.title}
63
+ >
64
+ {parsedContent}
65
+ </InlineConcept>
146
66
  );
147
67
  }
68
+
148
69
  return (
149
- <ConceptNotionV2
150
- title={concept.title}
151
- content={parsedContent}
70
+ <BlockConcept
152
71
  copyright={concept.copyright}
153
- source={concept.source}
154
72
  visualElement={visualElement}
155
- conceptType={concept.conceptType}
156
- glossData={concept.glossData}
157
73
  lang={lang}
158
- exampleIds={embed.embedData.exampleIds}
159
- exampleLangs={embed.embedData.exampleLangs}
160
- showTitle={renderContext !== "embed"}
161
- />
74
+ title={renderContext === "embed" ? undefined : concept.title.title}
75
+ >
76
+ {parsedContent}
77
+ </BlockConcept>
162
78
  );
163
79
  };
164
80
 
165
- interface InlineConceptProps extends ConceptNotionData {
166
- linkText: ReactNode;
167
- headerButtons?: ReactNode;
168
- exampleIds?: string;
169
- exampleLangs?: string;
170
- setSelection?: (e: MouseEvent) => void;
81
+ export interface InlineConceptProps extends ConceptProps, BaseProps {
82
+ linkText?: string;
171
83
  }
172
84
 
173
- const NotionButton = styled.span`
174
- background: none;
175
- border: none;
176
- font-family: inherit;
177
- font-style: inherit;
178
- line-height: 1em;
179
- text-decoration: none;
180
- position: relative;
181
- text-align: left;
182
- color: ${colors.concept.text};
183
- cursor: pointer;
184
- &:focus,
185
- &:hover,
186
- &:active,
187
- &[data-open="true"] {
188
- color: ${colors.concept.text};
189
- background-color: ${colors.concept.light};
190
- }
191
- display: inline;
192
- border-bottom: 5px double currentColor;
193
- `;
194
-
195
- const StyledAnchor = styled(Anchor)`
196
- ${mq.range({ until: breakpoints.tablet })} {
197
- position: fixed;
198
- top: 0;
199
- }
200
- `;
201
-
202
- const StyledAnchorSpan = styled.span`
203
- position: absolute;
204
- left: 50%;
205
- align-self: center;
206
- `;
207
-
208
- const getModalPosition = (anchor: HTMLElement) => {
209
- const article = anchor.closest("[data-ndla-article]");
210
- const articlePos = article?.getBoundingClientRect();
211
- const anchorPos = anchor.getBoundingClientRect();
212
- return anchorPos.top - (articlePos?.top || -window.scrollY) + 30; // add 30 so that position is under the word
213
- };
85
+ // TODO: Consider if we should make this act like the old concept popover.
86
+ // Should it take up the entire screen height on mobile? I don't think we need to.
87
+ // Should it always stay directly underneath the trigger?
214
88
 
215
89
  export const InlineConcept = forwardRef<HTMLSpanElement, InlineConceptProps>(
216
- (
217
- {
218
- title,
219
- content,
220
- copyright,
221
- source,
222
- visualElement,
223
- linkText,
224
- glossData,
225
- conceptType,
226
- headerButtons,
227
- lang,
228
- exampleIds,
229
- exampleLangs,
230
- setSelection,
231
- ...rest
232
- },
233
- ref,
234
- ) => {
235
- const { t } = useTranslation();
236
- const anchorRef = useRef<HTMLDivElement>(null);
237
- const [modalPos, setModalPos] = useState(-9999);
238
-
239
- const onOpenChange = useCallback((open: boolean) => {
240
- if (open) {
241
- const anchor = anchorRef.current;
242
- if (anchor) {
243
- const top = getModalPosition(anchor);
244
- setModalPos(top);
245
- }
246
- } else {
247
- setModalPos(-9999);
248
- }
249
- }, []);
250
-
251
- const preventAutoFocusInEditor = useCallback(
252
- (e: MouseEvent) => {
253
- e.preventDefault();
254
- e.stopPropagation();
255
- setSelection?.(e);
256
- },
257
- [setSelection],
258
- );
259
-
260
- return (
261
- <Root modal={isMobile} onOpenChange={onOpenChange}>
262
- <StyledAnchor ref={anchorRef} asChild>
263
- <StyledAnchorSpan contentEditable={false} />
264
- </StyledAnchor>
265
- <Trigger asChild>
266
- <NotionButton
267
- onMouseDown={(e) => (setSelection ? preventAutoFocusInEditor(e.nativeEvent) : undefined)}
268
- data-open={modalPos !== -9999}
269
- role="button"
270
- tabIndex={0}
271
- ref={ref}
272
- {...rest}
273
- >
274
- {linkText}
275
- </NotionButton>
276
- </Trigger>
277
- <Portal container={(anchorRef.current?.closest("[data-ndla-article]") as HTMLElement | null) || undefined}>
278
- <PopoverWrapper top={modalPos}>
279
- <Content avoidCollisions={false} side="bottom" asChild>
280
- <ConceptNotionV2
281
- title={title}
282
- content={content}
283
- copyright={copyright}
284
- source={source}
285
- visualElement={visualElement}
286
- inPopover
287
- headerButtons={headerButtons}
288
- lang={lang}
289
- closeButton={
290
- <Close asChild>
291
- <IconButtonV2 aria-label={t("close")} variant="ghost">
292
- <Cross />
293
- </IconButtonV2>
294
- </Close>
295
- }
296
- conceptType={conceptType}
297
- glossData={glossData}
298
- exampleIds={exampleIds}
299
- exampleLangs={exampleLangs}
300
- />
301
- </Content>
302
- </PopoverWrapper>
303
- </Portal>
304
- </Root>
305
- );
306
- },
90
+ ({ linkText, copyright, visualElement, lang, children, title, ...rest }, ref) => (
91
+ <PopoverRoot>
92
+ <PopoverTrigger asChild>
93
+ <InlineTriggerButton {...rest} ref={ref}>
94
+ {linkText}
95
+ </InlineTriggerButton>
96
+ </PopoverTrigger>
97
+ <StyledPopoverContent>
98
+ <Figure>
99
+ <Concept copyright={copyright} visualElement={visualElement} lang={lang} title={title}>
100
+ {children}
101
+ </Concept>
102
+ </Figure>
103
+ </StyledPopoverContent>
104
+ </PopoverRoot>
105
+ ),
307
106
  );
308
107
 
309
- interface ConceptProps extends ConceptNotionData {
310
- fullWidth?: boolean;
311
- exampleIds?: string;
312
- exampleLangs?: string;
313
- }
314
-
315
- export const BlockConcept = ({
316
- title,
317
- content,
318
- metaImage,
319
- copyright,
320
- source,
321
- visualElement,
322
- fullWidth,
323
- glossData,
324
- conceptType,
325
- lang,
326
- exampleIds,
327
- exampleLangs,
328
- }: ConceptProps) => {
329
- const { t } = useTranslation();
330
- const anchorRef = useRef<HTMLDivElement>(null);
331
- const [modalPos, setModalPos] = useState(-9999);
332
-
333
- const onOpenChange = useCallback((open: boolean) => {
334
- if (open) {
335
- const anchor = anchorRef.current;
336
- if (anchor) {
337
- const top = getModalPosition(anchor);
338
- setModalPos(top);
339
- }
340
- } else {
341
- setModalPos(-9999);
342
- }
343
- }, []);
344
-
345
- return (
346
- <Root modal={isMobile} onOpenChange={onOpenChange}>
347
- <StyledAnchor ref={anchorRef} />
348
- <Figure type={fullWidth ? "full" : "full-column"}>
349
- {conceptType === "concept" ? (
350
- <UINotion
351
- id=""
352
- title={title.title}
353
- text={content}
354
- lang={lang}
355
- visualElement={
356
- visualElement?.status === "success" && (
357
- <>
358
- <ImageWrapper>
359
- <Tooltip tooltip={t(`searchPage.resultType.${conceptType}`)}>
360
- <Trigger asChild>
361
- <StyledButton
362
- type="button"
363
- aria-label={t("concept.showDescription", {
364
- title: title,
365
- })}
366
- >
367
- {visualElement.resource === "image" ? (
368
- <NotionImage
369
- src={visualElement.data.image.imageUrl}
370
- alt={visualElement.data.alttext.alttext}
371
- />
372
- ) : metaImage ? (
373
- <NotionImage src={metaImage?.url ?? ""} alt={metaImage?.alt ?? ""} />
374
- ) : undefined}
375
- </StyledButton>
376
- </Trigger>
377
- </Tooltip>
378
- </ImageWrapper>
379
- <Portal
380
- container={
381
- typeof document !== "undefined"
382
- ? (document.querySelector("[data-ndla-article]") as HTMLElement | null) || undefined
383
- : undefined
384
- }
385
- >
386
- <PopoverWrapper top={modalPos}>
387
- <Content avoidCollisions={false} asChild side="bottom">
388
- <ConceptNotionV2
389
- title={title}
390
- content={content}
391
- copyright={copyright}
392
- source={source}
393
- visualElement={visualElement}
394
- inPopover
395
- lang={lang}
396
- closeButton={
397
- <Close asChild>
398
- <IconButtonV2 aria-label={t("close")} variant="ghost">
399
- <Cross />
400
- </IconButtonV2>
401
- </Close>
402
- }
403
- conceptType={conceptType}
404
- glossData={glossData}
405
- />
406
- </Content>
407
- </PopoverWrapper>
408
- </Portal>
409
- </>
410
- )
411
- }
412
- />
413
- ) : (
414
- <Gloss
415
- glossData={glossData}
416
- title={title}
417
- audio={
418
- visualElement?.status === "success" && visualElement.resource === "audio"
419
- ? {
420
- src: visualElement.data.audioFile.url,
421
- title: visualElement.data.title.title,
422
- }
423
- : undefined
424
- }
425
- exampleIds={exampleIds}
426
- exampleLangs={exampleLangs}
427
- />
428
- )}
429
- {copyright && conceptType === "concept" && (
430
- <EmbedByline copyright={copyright} type={conceptType as ConceptType} />
431
- )}
432
- </Figure>
433
- </Root>
434
- );
435
- };
108
+ export interface BlockConceptProps extends ConceptProps {}
436
109
 
437
- export default ConceptEmbed;
110
+ export const BlockConcept = forwardRef<HTMLElement, BlockConceptProps>((props, ref) => (
111
+ <Concept {...props} ref={ref} />
112
+ ));