@ndla/ui 55.0.12-alpha.0 → 55.0.13-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 (192) hide show
  1. package/dist/all-aout.js +0 -0
  2. package/dist/all.css +1 -0
  3. package/dist/panda.buildinfo.json +170 -0
  4. package/dist/styles.css +686 -0
  5. package/es/Article/Article.js +3 -4
  6. package/es/Article/ArticleByline.js +9 -9
  7. package/es/Article/ArticleFootNotes.js +4 -4
  8. package/es/AudioPlayer/AudioPlayer.js +142 -163
  9. package/es/AudioPlayer/Controls.js +187 -203
  10. package/es/AudioPlayer/SpeechControl.js +13 -11
  11. package/es/BlogPost/BlogPost.js +85 -23
  12. package/es/CampaignBlock/CampaignBlock.js +3 -4
  13. package/es/CodeBlock/CodeBlock.js +88 -96
  14. package/es/ContactBlock/ContactBlock.js +54 -40
  15. package/es/ContentLoader/index.js +7 -7
  16. package/es/CopyParagraphButton/CopyParagraphButton.js +4 -4
  17. package/es/Embed/AudioEmbed.js +5 -9
  18. package/es/Embed/BrightcoveEmbed.js +12 -15
  19. package/es/Embed/CodeEmbed.js +58 -10
  20. package/es/Embed/ConceptEmbed.js +15 -20
  21. package/es/Embed/ContentLinkEmbed.js +1 -1
  22. package/es/Embed/EmbedErrorPlaceholder.js +32 -17
  23. package/es/Embed/ExternalEmbed.js +7 -10
  24. package/es/Embed/FootnoteEmbed.js +3 -3
  25. package/es/Embed/H5pEmbed.js +1 -2
  26. package/es/Embed/IframeEmbed.js +8 -9
  27. package/es/Embed/ImageEmbed.js +167 -122
  28. package/es/Embed/RelatedContentEmbed.js +8 -10
  29. package/es/Embed/UuDisclaimerEmbed.js +2 -2
  30. package/es/Embed/conceptComponents.js +9 -9
  31. package/es/ErrorMessage/ErrorMessage.js +1 -1
  32. package/es/FactBox/FactBox.js +2 -2
  33. package/es/FileList/File.js +1 -1
  34. package/es/FileList/Format.js +3 -3
  35. package/es/FrontpageArticle/FrontpageArticle.js +1 -1
  36. package/es/Gloss/Gloss.js +9 -11
  37. package/es/Gloss/GlossExample.js +3 -4
  38. package/es/Grid/Grid.js +1 -1
  39. package/es/Image/Image.js +7 -8
  40. package/es/Image/ImageLink.js +1 -1
  41. package/es/KeyFigure/KeyFigure.js +2 -2
  42. package/es/LanguageSelector/LanguageSelector.js +2 -2
  43. package/es/LetterFilter/LetterFilter.js +1 -1
  44. package/es/LicenseByline/EmbedByline.js +5 -6
  45. package/es/LicenseByline/LicenseDescription.js +1 -1
  46. package/es/LicenseByline/LicenseLink.js +1 -2
  47. package/es/Messages/MessageBox.js +1 -1
  48. package/es/Notion/Notion.js +2 -2
  49. package/es/Notion/NotionImage.js +12 -57
  50. package/es/RelatedArticleList/RelatedArticleList.js +3 -3
  51. package/es/ResourceBox/ResourceBox.js +12 -17
  52. package/es/Search/ActiveFilters.js +1 -1
  53. package/es/Search/ContentTypeResult.js +9 -6
  54. package/es/Search/ContentTypeResultStyles.js +1 -1
  55. package/es/Search/IsPathToHighlight.js +1 -1
  56. package/es/Search/SearchField.js +6 -8
  57. package/es/Search/SearchResult.js +14 -19
  58. package/es/Search/SearchResultSleeve.js +14 -16
  59. package/es/SnackBar/SnackbarProvider.js +8 -11
  60. package/es/TagSelector/TagSelector.js +1 -1
  61. package/es/TagSelector/ariaMessages.js +6 -6
  62. package/es/TreeStructure/AddFolderButton.js +4 -6
  63. package/es/TreeStructure/ComboboxButton.js +4 -7
  64. package/es/TreeStructure/FolderItem.js +12 -15
  65. package/es/TreeStructure/FolderItems.js +3 -3
  66. package/es/TreeStructure/TreeStructure.js +9 -12
  67. package/es/TreeStructure/helperFunctions.js +1 -1
  68. package/es/ZendeskButton/ZendeskButton.js +55 -0
  69. package/es/i18n/formatNestedMessages.js +1 -1
  70. package/es/index.js +2 -1
  71. package/es/locale/messages-en.js +9 -8
  72. package/es/locale/messages-nb.js +9 -8
  73. package/es/locale/messages-nn.js +9 -8
  74. package/es/locale/messages-se.js +9 -8
  75. package/es/locale/messages-sma.js +9 -8
  76. package/es/styles.css +686 -0
  77. package/es/utils/relativeUrl.js +3 -3
  78. package/lib/Article/Article.js +3 -4
  79. package/lib/Article/ArticleByline.js +9 -9
  80. package/lib/Article/ArticleFootNotes.js +4 -4
  81. package/lib/AudioPlayer/AudioPlayer.d.ts +1 -2
  82. package/lib/AudioPlayer/AudioPlayer.js +142 -162
  83. package/lib/AudioPlayer/Controls.js +190 -205
  84. package/lib/AudioPlayer/SpeechControl.js +13 -11
  85. package/lib/BlogPost/BlogPost.d.ts +2 -2
  86. package/lib/BlogPost/BlogPost.js +85 -24
  87. package/lib/CampaignBlock/CampaignBlock.js +3 -4
  88. package/lib/CodeBlock/CodeBlock.d.ts +5 -8
  89. package/lib/CodeBlock/CodeBlock.js +88 -96
  90. package/lib/ContactBlock/ContactBlock.js +55 -43
  91. package/lib/ContentLoader/index.js +7 -7
  92. package/lib/CopyParagraphButton/CopyParagraphButton.js +4 -4
  93. package/lib/Embed/AudioEmbed.js +5 -9
  94. package/lib/Embed/BrightcoveEmbed.js +12 -15
  95. package/lib/Embed/CodeEmbed.js +56 -8
  96. package/lib/Embed/ConceptEmbed.js +15 -20
  97. package/lib/Embed/ContentLinkEmbed.js +1 -1
  98. package/lib/Embed/EmbedErrorPlaceholder.d.ts +4 -3
  99. package/lib/Embed/EmbedErrorPlaceholder.js +32 -18
  100. package/lib/Embed/ExternalEmbed.js +7 -10
  101. package/lib/Embed/FootnoteEmbed.js +3 -3
  102. package/lib/Embed/H5pEmbed.js +1 -2
  103. package/lib/Embed/IframeEmbed.js +8 -9
  104. package/lib/Embed/ImageEmbed.d.ts +1 -2
  105. package/lib/Embed/ImageEmbed.js +167 -123
  106. package/lib/Embed/RelatedContentEmbed.js +8 -10
  107. package/lib/Embed/UuDisclaimerEmbed.js +2 -2
  108. package/lib/Embed/conceptComponents.js +9 -9
  109. package/lib/ErrorMessage/ErrorMessage.js +1 -1
  110. package/lib/FactBox/FactBox.js +2 -2
  111. package/lib/FileList/File.js +1 -1
  112. package/lib/FileList/Format.js +3 -3
  113. package/lib/FrontpageArticle/FrontpageArticle.js +1 -1
  114. package/lib/Gloss/Gloss.js +9 -11
  115. package/lib/Gloss/GlossExample.js +3 -4
  116. package/lib/Grid/Grid.js +1 -1
  117. package/lib/Image/Image.js +7 -8
  118. package/lib/Image/ImageLink.js +1 -1
  119. package/lib/KeyFigure/KeyFigure.js +2 -2
  120. package/lib/LanguageSelector/LanguageSelector.js +2 -2
  121. package/lib/LetterFilter/LetterFilter.js +1 -1
  122. package/lib/LicenseByline/EmbedByline.js +5 -6
  123. package/lib/LicenseByline/LicenseDescription.js +1 -1
  124. package/lib/LicenseByline/LicenseLink.js +1 -2
  125. package/lib/Messages/MessageBox.js +1 -1
  126. package/lib/Notion/Notion.js +2 -2
  127. package/lib/Notion/NotionImage.d.ts +1 -11
  128. package/lib/Notion/NotionImage.js +12 -59
  129. package/lib/RelatedArticleList/RelatedArticleList.js +3 -3
  130. package/lib/ResourceBox/ResourceBox.js +13 -18
  131. package/lib/Search/ActiveFilters.js +1 -1
  132. package/lib/Search/ContentTypeResult.js +9 -6
  133. package/lib/Search/ContentTypeResultStyles.js +1 -1
  134. package/lib/Search/IsPathToHighlight.js +1 -1
  135. package/lib/Search/SearchField.js +6 -8
  136. package/lib/Search/SearchResult.js +14 -19
  137. package/lib/Search/SearchResultSleeve.js +14 -16
  138. package/lib/SnackBar/SnackbarProvider.js +8 -11
  139. package/lib/TagSelector/TagSelector.js +1 -1
  140. package/lib/TagSelector/ariaMessages.js +6 -6
  141. package/lib/TreeStructure/AddFolderButton.js +4 -6
  142. package/lib/TreeStructure/ComboboxButton.js +4 -7
  143. package/lib/TreeStructure/FolderItem.js +12 -15
  144. package/lib/TreeStructure/FolderItems.js +3 -3
  145. package/lib/TreeStructure/TreeStructure.js +9 -12
  146. package/lib/TreeStructure/helperFunctions.js +1 -1
  147. package/lib/ZendeskButton/ZendeskButton.d.ts +19 -0
  148. package/lib/ZendeskButton/ZendeskButton.js +61 -0
  149. package/lib/i18n/formatNestedMessages.js +1 -1
  150. package/lib/index.d.ts +2 -0
  151. package/lib/index.js +7 -0
  152. package/lib/locale/messages-en.d.ts +1 -0
  153. package/lib/locale/messages-en.js +9 -8
  154. package/lib/locale/messages-nb.d.ts +1 -0
  155. package/lib/locale/messages-nb.js +9 -8
  156. package/lib/locale/messages-nn.d.ts +1 -0
  157. package/lib/locale/messages-nn.js +9 -8
  158. package/lib/locale/messages-se.d.ts +1 -0
  159. package/lib/locale/messages-se.js +9 -8
  160. package/lib/locale/messages-sma.d.ts +1 -0
  161. package/lib/locale/messages-sma.js +9 -8
  162. package/lib/styles.css +686 -0
  163. package/lib/types.d.ts +1 -0
  164. package/lib/utils/relativeUrl.js +3 -3
  165. package/package.json +17 -12
  166. package/src/AudioPlayer/AudioPlayer.tsx +139 -176
  167. package/src/AudioPlayer/Controls.tsx +210 -250
  168. package/src/AudioPlayer/SpeechControl.tsx +9 -7
  169. package/src/BlogPost/BlogPost.tsx +82 -58
  170. package/src/CodeBlock/CodeBlock.stories.tsx +0 -43
  171. package/src/CodeBlock/CodeBlock.tsx +91 -202
  172. package/src/ContactBlock/ContactBlock.tsx +10 -2
  173. package/src/Embed/CodeEmbed.stories.tsx +95 -0
  174. package/src/Embed/CodeEmbed.tsx +62 -7
  175. package/src/Embed/ConceptEmbed.tsx +1 -9
  176. package/src/Embed/EmbedErrorPlaceholder.tsx +31 -28
  177. package/src/Embed/ImageEmbed.stories.tsx +53 -11
  178. package/src/Embed/ImageEmbed.tsx +162 -166
  179. package/src/Notion/NotionImage.tsx +4 -54
  180. package/src/ResourceBox/ResourceBox.tsx +3 -15
  181. package/src/Search/ContentTypeResult.tsx +9 -3
  182. package/src/Search/SearchResultSleeve.tsx +5 -2
  183. package/src/ZendeskButton/ZendeskButton.tsx +58 -0
  184. package/src/index.ts +4 -0
  185. package/src/locale/messages-en.ts +1 -0
  186. package/src/locale/messages-nb.ts +1 -0
  187. package/src/locale/messages-nn.ts +1 -0
  188. package/src/locale/messages-se.ts +1 -0
  189. package/src/locale/messages-sma.ts +1 -0
  190. package/src/types.ts +2 -0
  191. package/src/Image/__tests__/Image-test.tsx +0 -66
  192. package/src/Image/__tests__/__snapshots__/Image-test.tsx.snap +0 -194
@@ -23,9 +23,9 @@ const ContentLoader = _ref => {
23
23
  } = _ref;
24
24
  const idClip = uuid();
25
25
  const idGradient = uuid();
26
- const viewBox = viewBoxProp === undefined ? "0 0 ".concat(width, " ").concat(height) : viewBoxProp;
26
+ const viewBox = viewBoxProp === undefined ? `0 0 ${width} ${height}` : viewBoxProp;
27
27
  return _jsxs("svg", {
28
- viewBox: viewBox !== null && viewBox !== void 0 ? viewBox : undefined,
28
+ viewBox: viewBox ?? undefined,
29
29
  version: "1.1",
30
30
  preserveAspectRatio: preserveAspectRatio,
31
31
  className: className,
@@ -34,9 +34,9 @@ const ContentLoader = _ref => {
34
34
  width: typeof width === "string" ? width : undefined,
35
35
  children: [_jsx("rect", {
36
36
  style: {
37
- fill: "url(#".concat(idGradient, ")")
37
+ fill: `url(#${idGradient})`
38
38
  },
39
- clipPath: "url(#".concat(idClip, ")"),
39
+ clipPath: `url(#${idClip})`,
40
40
  x: "0",
41
41
  y: "0",
42
42
  width: width,
@@ -53,7 +53,7 @@ const ContentLoader = _ref => {
53
53
  children: _jsx("animate", {
54
54
  attributeName: "offset",
55
55
  values: "-2; 1",
56
- dur: "".concat(speed, "s"),
56
+ dur: `${speed}s`,
57
57
  repeatCount: "indefinite"
58
58
  })
59
59
  }), _jsx("stop", {
@@ -62,7 +62,7 @@ const ContentLoader = _ref => {
62
62
  children: _jsx("animate", {
63
63
  attributeName: "offset",
64
64
  values: "-1.5; 1.5",
65
- dur: "".concat(speed, "s"),
65
+ dur: `${speed}s`,
66
66
  repeatCount: "indefinite"
67
67
  })
68
68
  }), _jsx("stop", {
@@ -71,7 +71,7 @@ const ContentLoader = _ref => {
71
71
  children: _jsx("animate", {
72
72
  attributeName: "offset",
73
73
  values: "-1; 2",
74
- dur: "".concat(speed, "s"),
74
+ dur: `${speed}s`,
75
75
  repeatCount: "indefinite"
76
76
  })
77
77
  })]
@@ -52,9 +52,9 @@ const CopyParagraphButton = _ref => {
52
52
  const {
53
53
  location
54
54
  } = window;
55
- const newHash = "#".concat(sanitizedTitle);
56
- const port = location.port ? ":".concat(location.port) : "";
57
- const urlToCopy = "".concat(location.protocol, "//").concat(location.hostname).concat(port).concat(location.pathname).concat(location.search).concat(newHash);
55
+ const newHash = `#${sanitizedTitle}`;
56
+ const port = location.port ? `:${location.port}` : "";
57
+ const urlToCopy = `${location.protocol}//${location.hostname}${port}${location.pathname}${location.search}${newHash}`;
58
58
  copyTextToClipboard(urlToCopy);
59
59
  }, [sanitizedTitle]);
60
60
  const tooltip = hasCopied ? t("article.copyPageLinkCopied") : t("article.copyHeaderLink");
@@ -63,7 +63,7 @@ const CopyParagraphButton = _ref => {
63
63
  tooltip: tooltip,
64
64
  children: _jsx(IconButton, {
65
65
  onClick: onCopyClick,
66
- "aria-label": "".concat(tooltip, ": ").concat(copyText),
66
+ "aria-label": `${tooltip}: ${copyText}`,
67
67
  children: _jsx(Link, {})
68
68
  })
69
69
  }), _jsx("h2", {
@@ -11,12 +11,8 @@ import AudioPlayer from "../AudioPlayer";
11
11
  import { Figure } from "../Figure";
12
12
  import { EmbedByline } from "../LicenseByline";
13
13
  import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
14
- export const getFirstNonEmptyLicenseCredits = authors => {
15
- var _Object$values$find;
16
- return (_Object$values$find = Object.values(authors).find(i => i.length > 0)) !== null && _Object$values$find !== void 0 ? _Object$values$find : [];
17
- };
14
+ export const getFirstNonEmptyLicenseCredits = authors => Object.values(authors).find(i => i.length > 0) ?? [];
18
15
  const AudioEmbed = _ref => {
19
- var _data$podcastMeta, _data$podcastMeta$int, _data$podcastMeta2, _data$manuscript;
20
16
  let {
21
17
  embed,
22
18
  lang
@@ -39,9 +35,9 @@ const AudioEmbed = _ref => {
39
35
  }
40
36
  const subtitle = data.series ? {
41
37
  title: data.series.title.title,
42
- url: "/podkast/".concat(data.series.id)
38
+ url: `/podkast/${data.series.id}`
43
39
  } : undefined;
44
- const coverPhoto = (_data$podcastMeta = data.podcastMeta) === null || _data$podcastMeta === void 0 ? void 0 : _data$podcastMeta.coverPhoto;
40
+ const coverPhoto = data.podcastMeta?.coverPhoto;
45
41
  const img = coverPhoto && {
46
42
  url: coverPhoto.url,
47
43
  alt: coverPhoto.altText
@@ -50,10 +46,10 @@ const AudioEmbed = _ref => {
50
46
  type: "full",
51
47
  lang: lang,
52
48
  children: [_jsx(AudioPlayer, {
53
- description: (_data$podcastMeta$int = (_data$podcastMeta2 = data.podcastMeta) === null || _data$podcastMeta2 === void 0 ? void 0 : _data$podcastMeta2.introduction) !== null && _data$podcastMeta$int !== void 0 ? _data$podcastMeta$int : "",
49
+ description: data.podcastMeta?.introduction ?? "",
54
50
  img: img,
55
51
  src: data.audioFile.url,
56
- textVersion: (_data$manuscript = data.manuscript) !== null && _data$manuscript !== void 0 && _data$manuscript.manuscript.length ? _jsx("span", {
52
+ textVersion: data.manuscript?.manuscript.length ? _jsx("span", {
57
53
  dangerouslySetInnerHTML: {
58
54
  __html: data.manuscript.manuscript
59
55
  }
@@ -38,11 +38,10 @@ export const makeIframeString = function (url, width, height) {
38
38
  const strippedWidth = typeof width === "number" ? width : width.replace(/\s*px/, "");
39
39
  const strippedHeight = typeof height === "number" ? height : height.replace(/\s*px/, "");
40
40
  const urlOrTitle = title || url;
41
- return "<iframe title=\"".concat(urlOrTitle, "\" aria-label=\"").concat(urlOrTitle, "\" src=\"").concat(url, "\" width=\"").concat(strippedWidth, "\" height=\"").concat(strippedHeight, "\" allowfullscreen scrolling=\"no\" frameborder=\"0\" loading=\"lazy\"></iframe>");
41
+ return `<iframe title="${urlOrTitle}" aria-label="${urlOrTitle}" src="${url}" width="${strippedWidth}" height="${strippedHeight}" allowfullscreen scrolling="no" frameborder="0" loading="lazy"></iframe>`;
42
42
  };
43
43
  export const isNumeric = value => !Number.isNaN(value - Number.parseFloat(value));
44
44
  const getIframeProps = (data, sources) => {
45
- var _source$height, _source$width;
46
45
  const {
47
46
  account,
48
47
  videoid,
@@ -50,13 +49,12 @@ const getIframeProps = (data, sources) => {
50
49
  } = data;
51
50
  const source = sources.filter(s => s.width && s.height).toSorted((a, b) => a.height - b.height)[0];
52
51
  return {
53
- src: "https://players.brightcove.net/".concat(account, "/").concat(player, "_default/index.html?videoId=").concat(videoid),
54
- height: (_source$height = source === null || source === void 0 ? void 0 : source.height) !== null && _source$height !== void 0 ? _source$height : "480",
55
- width: (_source$width = source === null || source === void 0 ? void 0 : source.width) !== null && _source$width !== void 0 ? _source$width : "640"
52
+ src: `https://players.brightcove.net/${account}/${player}_default/index.html?videoId=${videoid}`,
53
+ height: source?.height ?? "480",
54
+ width: source?.width ?? "640"
56
55
  };
57
56
  };
58
57
  const BrightcoveEmbed = _ref => {
59
- var _data$link, _data$link2, _ref2, _embedData$alt3, _ref3, _embedData$alt4;
60
58
  let {
61
59
  embed,
62
60
  isConcept,
@@ -70,7 +68,7 @@ const BrightcoveEmbed = _ref => {
70
68
  const {
71
69
  embedData
72
70
  } = embed;
73
- const fallbackTitle = "".concat(t("embed.type.video"), ": ").concat(embedData.videoid);
71
+ const fallbackTitle = `${t("embed.type.video")}: ${embedData.videoid}`;
74
72
  const parsedDescription = useMemo(() => {
75
73
  if (embed.embedData.caption || renderContext === "article") {
76
74
  return embed.embedData.caption ? parse(embed.embedData.caption) : undefined;
@@ -82,19 +80,18 @@ const BrightcoveEmbed = _ref => {
82
80
  const iframe = iframeRef.current;
83
81
  if (iframe) {
84
82
  const [width, height] = [parseInt(iframe.width), parseInt(iframe.height)];
85
- iframe.style.aspectRatio = "".concat(width, "/").concat(height);
83
+ iframe.style.aspectRatio = `${width}/${height}`;
86
84
  iframe.width = "";
87
85
  iframe.height = "";
88
86
  }
89
87
  }, []);
90
88
  if (embed.status === "error") {
91
- var _embedData$alt, _embedData$alt2;
92
89
  return _jsx(EmbedErrorPlaceholder, {
93
90
  type: "video",
94
91
  children: _jsx(BrightcoveIframe, {
95
92
  ref: iframeRef,
96
- title: (_embedData$alt = embedData.alt) !== null && _embedData$alt !== void 0 ? _embedData$alt : fallbackTitle,
97
- "aria-label": (_embedData$alt2 = embedData.alt) !== null && _embedData$alt2 !== void 0 ? _embedData$alt2 : fallbackTitle,
93
+ title: embedData.alt ?? fallbackTitle,
94
+ "aria-label": embedData.alt ?? fallbackTitle,
98
95
  frameBorder: "0",
99
96
  ...getIframeProps(embedData, []),
100
97
  allowFullScreen: true
@@ -104,7 +101,7 @@ const BrightcoveEmbed = _ref => {
104
101
  const {
105
102
  data
106
103
  } = embed;
107
- const linkedVideoId = isNumeric((_data$link = data.link) === null || _data$link === void 0 ? void 0 : _data$link.text) ? (_data$link2 = data.link) === null || _data$link2 === void 0 ? void 0 : _data$link2.text : undefined;
104
+ const linkedVideoId = isNumeric(data.link?.text) ? data.link?.text : undefined;
108
105
  const originalVideoProps = getIframeProps(embedData, data.sources);
109
106
  const alternativeVideoProps = linkedVideoId ? getIframeProps({
110
107
  ...embedData,
@@ -117,8 +114,8 @@ const BrightcoveEmbed = _ref => {
117
114
  children: _jsx(BrightcoveIframe, {
118
115
  ref: iframeRef,
119
116
  className: "original",
120
- title: (_ref2 = (_embedData$alt3 = embedData.alt) !== null && _embedData$alt3 !== void 0 ? _embedData$alt3 : data.name) !== null && _ref2 !== void 0 ? _ref2 : fallbackTitle,
121
- "aria-label": (_ref3 = (_embedData$alt4 = embedData.alt) !== null && _embedData$alt4 !== void 0 ? _embedData$alt4 : data.name) !== null && _ref3 !== void 0 ? _ref3 : fallbackTitle,
117
+ title: embedData.alt ?? data.name ?? fallbackTitle,
118
+ "aria-label": embedData.alt ?? data.name ?? fallbackTitle,
122
119
  frameBorder: "0",
123
120
  ...(alternativeVideoProps && !showOriginalVideo ? alternativeVideoProps : originalVideoProps),
124
121
  allowFullScreen: true
@@ -133,7 +130,7 @@ const BrightcoveEmbed = _ref => {
133
130
  shape: "pill",
134
131
  size: "small",
135
132
  onClick: () => setShowOriginalVideo(p => !p),
136
- children: t("figure.button.".concat(!showOriginalVideo ? "original" : "alternative"))
133
+ children: t(`figure.button.${!showOriginalVideo ? "original" : "alternative"}`)
137
134
  })
138
135
  })]
139
136
  });
@@ -6,21 +6,69 @@
6
6
  *
7
7
  */
8
8
 
9
- import { CodeBlock } from "../CodeBlock";
10
- import { Figure } from "../Figure";
11
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
9
+ import { useEffect, useState } from "react";
10
+ import { useTranslation } from "react-i18next";
11
+ import { Copy } from "@ndla/icons/action";
12
+ import { Done } from "@ndla/icons/editor";
13
+ import { Button, Figure } from "@ndla/primitives";
14
+ import { styled } from "@ndla/styled-system/jsx";
15
+ import { copyTextToClipboard } from "@ndla/util";
16
+ import { CodeBlock, codeLanguageOptions } from "../CodeBlock";
17
+
18
+ // TODO: We need an error state for this
19
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
20
+ const StyledFigCaption = styled("figcaption", {
21
+ base: {
22
+ textStyle: "label.large",
23
+ fontWeight: "bold"
24
+ }
25
+ });
26
+ const StyledFigure = styled(Figure, {
27
+ base: {
28
+ // We apply margin here to allow for the float and size props on figure to work as intended.
29
+ "& > *:not(:where(:first-child))": {
30
+ marginBlockStart: "xsmall"
31
+ }
32
+ }
33
+ });
34
+ const getTitleFromFormat = format => {
35
+ const selectedLanguage = codeLanguageOptions.find(item => item.format === format);
36
+ if (selectedLanguage) {
37
+ return selectedLanguage.title;
38
+ }
39
+ return;
40
+ };
12
41
  const CodeEmbed = _ref => {
13
42
  let {
14
43
  embed
15
44
  } = _ref;
16
- return _jsx(Figure, {
17
- children: _jsx(CodeBlock, {
18
- title: embed.embedData.title,
19
- code: embed.status === "success" ? embed.data.decodedContent : "",
45
+ const [isCopied, setIsCopied] = useState(false);
46
+ const {
47
+ t
48
+ } = useTranslation();
49
+ useEffect(() => {
50
+ if (isCopied) {
51
+ const timer = setInterval(() => setIsCopied(false), 3000);
52
+ // ensure interval is cleared - also if unmounted
53
+ return () => {
54
+ clearTimeout(timer);
55
+ };
56
+ }
57
+ }, [isCopied]);
58
+ return _jsxs(StyledFigure, {
59
+ children: [_jsx(StyledFigCaption, {
60
+ children: embed.embedData.title || getTitleFromFormat(embed.embedData.codeFormat)
61
+ }), _jsx(CodeBlock, {
20
62
  highlightedCode: embed.status === "success" ? embed.data.highlightedCode : "",
21
- format: embed.embedData.codeFormat,
22
- showCopy: true
23
- })
63
+ format: embed.embedData.codeFormat
64
+ }), _jsxs(Button, {
65
+ variant: "secondary",
66
+ onClick: () => {
67
+ copyTextToClipboard(embed.status === "success" ? embed.data.decodedContent : "");
68
+ setIsCopied(true);
69
+ },
70
+ children: [isCopied ? _jsx(Done, {}) : _jsx(Copy, {}), isCopied ? t("codeBlock.copiedCode") : t("codeBlock.copyCode")]
71
+ })]
24
72
  });
25
73
  };
26
74
  export default CodeEmbed;