@ndla/ui 34.6.2 → 34.6.4

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 (153) hide show
  1. package/es/Article/Article.js +11 -6
  2. package/es/Aside/Aside.js +5 -2
  3. package/es/CopyParagraphButton/CopyParagraphButtonV2.js +85 -0
  4. package/es/CopyParagraphButton/index.js +2 -1
  5. package/es/Embed/AudioEmbed.js +254 -0
  6. package/es/Embed/BrightcoveEmbed.js +250 -0
  7. package/es/Embed/ConceptEmbed.js +359 -0
  8. package/es/Embed/ConceptListEmbed.js +71 -0
  9. package/es/Embed/ContentLinkEmbed.js +42 -0
  10. package/es/Embed/ExternalEmbed.js +91 -0
  11. package/es/Embed/FootnoteEmbed.js +32 -0
  12. package/es/Embed/H5pEmbed.js +87 -0
  13. package/es/Embed/IframeEmbed.js +83 -0
  14. package/es/Embed/ImageEmbed.js +322 -0
  15. package/es/Embed/RelatedContentEmbed.js +58 -0
  16. package/es/Embed/UnknownEmbed.js +27 -0
  17. package/es/Embed/conceptComponents.js +282 -0
  18. package/es/Embed/index.js +21 -0
  19. package/es/FactBox/FactBoxV2.js +90 -0
  20. package/es/FactBox/index.js +1 -0
  21. package/es/Figure/Figure.js +8 -5
  22. package/es/Figure/FigureLicenseDialogContent.js +72 -0
  23. package/es/FileList/FileListV2.js +47 -0
  24. package/es/FileList/FileV2.js +34 -0
  25. package/es/FileList/PdfFile.js +25 -0
  26. package/es/FileList/index.js +3 -0
  27. package/es/Notion/Notion.js +5 -5
  28. package/es/Notion/NotionVisualElement.js +2 -2
  29. package/es/RelatedArticleList/RelatedArticleV2.js +101 -0
  30. package/es/RelatedArticleList/index.js +2 -1
  31. package/es/Table/Table.js +95 -8
  32. package/es/all.css +1 -1
  33. package/es/index.js +5 -4
  34. package/es/locale/messages-en.js +32 -2
  35. package/es/locale/messages-nb.js +32 -2
  36. package/es/locale/messages-nn.js +32 -2
  37. package/es/locale/messages-se.js +32 -2
  38. package/es/locale/messages-sma.js +32 -2
  39. package/lib/Article/Article.d.ts +2 -1
  40. package/lib/Article/Article.js +11 -6
  41. package/lib/Aside/Aside.d.ts +2 -1
  42. package/lib/Aside/Aside.js +5 -2
  43. package/lib/CopyParagraphButton/CopyParagraphButtonV2.d.ts +14 -0
  44. package/lib/CopyParagraphButton/CopyParagraphButtonV2.js +84 -0
  45. package/lib/CopyParagraphButton/index.d.ts +2 -1
  46. package/lib/CopyParagraphButton/index.js +7 -0
  47. package/lib/Embed/AudioEmbed.d.ts +20 -0
  48. package/lib/Embed/AudioEmbed.js +252 -0
  49. package/lib/Embed/BrightcoveEmbed.d.ts +16 -0
  50. package/lib/Embed/BrightcoveEmbed.js +250 -0
  51. package/lib/Embed/ConceptEmbed.d.ts +19 -0
  52. package/lib/Embed/ConceptEmbed.js +359 -0
  53. package/lib/Embed/ConceptListEmbed.d.ts +13 -0
  54. package/lib/Embed/ConceptListEmbed.js +70 -0
  55. package/lib/Embed/ContentLinkEmbed.d.ts +14 -0
  56. package/lib/Embed/ContentLinkEmbed.js +50 -0
  57. package/lib/Embed/ExternalEmbed.d.ts +14 -0
  58. package/lib/Embed/ExternalEmbed.js +90 -0
  59. package/lib/Embed/FootnoteEmbed.d.ts +13 -0
  60. package/lib/Embed/FootnoteEmbed.js +39 -0
  61. package/lib/Embed/H5pEmbed.d.ts +14 -0
  62. package/lib/Embed/H5pEmbed.js +86 -0
  63. package/lib/Embed/IframeEmbed.d.ts +14 -0
  64. package/lib/Embed/IframeEmbed.js +91 -0
  65. package/lib/Embed/ImageEmbed.d.ts +37 -0
  66. package/lib/Embed/ImageEmbed.js +326 -0
  67. package/lib/Embed/RelatedContentEmbed.d.ts +16 -0
  68. package/lib/Embed/RelatedContentEmbed.js +64 -0
  69. package/lib/Embed/UnknownEmbed.d.ts +13 -0
  70. package/lib/Embed/UnknownEmbed.js +35 -0
  71. package/lib/Embed/conceptComponents.d.ts +32 -0
  72. package/lib/Embed/conceptComponents.js +280 -0
  73. package/lib/Embed/index.d.ts +20 -0
  74. package/lib/Embed/index.js +97 -0
  75. package/lib/FactBox/FactBoxV2.d.ts +13 -0
  76. package/lib/FactBox/FactBoxV2.js +92 -0
  77. package/lib/FactBox/index.d.ts +1 -0
  78. package/lib/FactBox/index.js +7 -0
  79. package/lib/Figure/Figure.d.ts +5 -2
  80. package/lib/Figure/Figure.js +8 -5
  81. package/lib/Figure/FigureLicenseDialogContent.d.ts +22 -0
  82. package/lib/Figure/FigureLicenseDialogContent.js +71 -0
  83. package/lib/FileList/FileListV2.d.ts +13 -0
  84. package/lib/FileList/FileListV2.js +46 -0
  85. package/lib/FileList/FileV2.d.ts +16 -0
  86. package/lib/FileList/FileV2.js +42 -0
  87. package/lib/FileList/PdfFile.d.ts +13 -0
  88. package/lib/FileList/PdfFile.js +31 -0
  89. package/lib/FileList/index.d.ts +3 -0
  90. package/lib/FileList/index.js +21 -0
  91. package/lib/Notion/Notion.js +5 -5
  92. package/lib/Notion/NotionVisualElement.d.ts +1 -1
  93. package/lib/Notion/NotionVisualElement.js +2 -2
  94. package/lib/RelatedArticleList/RelatedArticleV2.d.ts +25 -0
  95. package/lib/RelatedArticleList/RelatedArticleV2.js +101 -0
  96. package/lib/RelatedArticleList/index.d.ts +2 -1
  97. package/lib/RelatedArticleList/index.js +7 -0
  98. package/lib/Table/Table.js +98 -8
  99. package/lib/all.css +1 -1
  100. package/lib/index.d.ts +5 -4
  101. package/lib/index.js +117 -2
  102. package/lib/locale/messages-en.d.ts +30 -0
  103. package/lib/locale/messages-en.js +32 -2
  104. package/lib/locale/messages-nb.d.ts +30 -0
  105. package/lib/locale/messages-nb.js +32 -2
  106. package/lib/locale/messages-nn.d.ts +30 -0
  107. package/lib/locale/messages-nn.js +32 -2
  108. package/lib/locale/messages-se.d.ts +30 -0
  109. package/lib/locale/messages-se.js +32 -2
  110. package/lib/locale/messages-sma.d.ts +30 -0
  111. package/lib/locale/messages-sma.js +32 -2
  112. package/lib/types.d.ts +1 -1
  113. package/package.json +16 -12
  114. package/src/Article/Article.tsx +8 -3
  115. package/src/Aside/Aside.tsx +9 -1
  116. package/src/Aside/component.aside.scss +3 -0
  117. package/src/CopyParagraphButton/CopyParagraphButtonV2.tsx +84 -0
  118. package/src/CopyParagraphButton/index.tsx +2 -1
  119. package/src/Embed/AudioEmbed.tsx +249 -0
  120. package/src/Embed/BrightcoveEmbed.tsx +203 -0
  121. package/src/Embed/ConceptEmbed.tsx +403 -0
  122. package/src/Embed/ConceptListEmbed.tsx +64 -0
  123. package/src/Embed/ContentLinkEmbed.tsx +41 -0
  124. package/src/Embed/ExternalEmbed.tsx +80 -0
  125. package/src/Embed/FootnoteEmbed.tsx +30 -0
  126. package/src/Embed/H5pEmbed.tsx +74 -0
  127. package/src/Embed/IframeEmbed.tsx +84 -0
  128. package/src/Embed/ImageEmbed.tsx +314 -0
  129. package/src/Embed/RelatedContentEmbed.tsx +62 -0
  130. package/src/Embed/UnknownEmbed.tsx +27 -0
  131. package/src/Embed/conceptComponents.tsx +393 -0
  132. package/src/Embed/index.ts +21 -0
  133. package/src/FactBox/FactBoxV2.tsx +56 -0
  134. package/src/FactBox/index.ts +2 -0
  135. package/src/Figure/Figure.tsx +28 -15
  136. package/src/Figure/FigureLicenseDialogContent.tsx +80 -0
  137. package/src/Figure/component.figure.scss +0 -1
  138. package/src/FileList/FileListV2.tsx +58 -0
  139. package/src/FileList/FileV2.tsx +35 -0
  140. package/src/FileList/PdfFile.tsx +25 -0
  141. package/src/FileList/index.ts +3 -0
  142. package/src/Notion/Notion.tsx +0 -1
  143. package/src/Notion/NotionVisualElement.tsx +1 -1
  144. package/src/RelatedArticleList/RelatedArticleV2.tsx +84 -0
  145. package/src/RelatedArticleList/index.ts +2 -1
  146. package/src/Table/Table.tsx +77 -4
  147. package/src/index.ts +19 -4
  148. package/src/locale/messages-en.ts +33 -0
  149. package/src/locale/messages-nb.ts +33 -0
  150. package/src/locale/messages-nn.ts +33 -0
  151. package/src/locale/messages-se.ts +33 -0
  152. package/src/locale/messages-sma.ts +33 -0
  153. package/src/types.ts +1 -1
@@ -587,7 +587,8 @@ var messages = _objectSpread(_objectSpread({
587
587
  originator: 'Ásaheaddji',
588
588
  published: 'Almmuhanbeaivi',
589
589
  rightsholder: 'Vuoigatvuođaguoddi',
590
- source: 'Gáldu'
590
+ source: 'Gáldu',
591
+ info: 'Lisensinformasjon'
591
592
  },
592
593
  errorMessage: {
593
594
  title: 'Ops, juoga manai boastut',
@@ -722,6 +723,7 @@ var messages = _objectSpread(_objectSpread({
722
723
  hits: '{{count}} deaivama'
723
724
  },
724
725
  notions: {
726
+ tags: 'Liste og filter',
725
727
  usedIn: 'Adnojuvvo dás',
726
728
  closeNotion: 'Govčča'
727
729
  },
@@ -1062,7 +1064,30 @@ var messages = _objectSpread(_objectSpread({
1062
1064
  onDragEnd: 'Máhppa {{name}} luitojuvvui {{index}} posišuvdnii {{length}} posišuvnnas',
1063
1065
  onDragEndMissingOver: 'Máhppa {{name}} lea luitojuvvon',
1064
1066
  onDragCancel: 'Sirdin botkejuvvui. Máhppa {{name}} lea luitojuvvon.',
1065
- dragHandle: 'Ordne máhpa {{name}}'
1067
+ dragHandle: 'Ordne máhpa {{name}}',
1068
+ sharing: {
1069
+ share: 'Del mappe',
1070
+ shared: 'Delt',
1071
+ unShare: 'Delingen er avsluttet. Mappen er ikke lenger delt.',
1072
+ link: 'Lenken er kopiert',
1073
+ header: {
1074
+ "private": 'Vil du dele denne mappen?',
1075
+ shared: 'Denne mappen er delt.',
1076
+ unShare: 'Vil du avslutte deling av denne mappen?'
1077
+ },
1078
+ description: {
1079
+ copy: 'Kopier og del denne lenken:',
1080
+ "private": 'Når du deler en mappe lager du en lenke som er åpen for alle som har lenken. Du kan endre innholdet eller avslutte delingen når du ønsker.',
1081
+ shared: 'Nå kan du dele denne lenken med elever eller andre lærere. Hvis du gjør endringer i mappen vil de bli synlige for alle du har delt lenken med.',
1082
+ unShare: 'Når du avslutter deling vil lenken til den delte mappen slutte å virke. Dersom du har delt lenken med noen vil de ikke lengre kunne se innholdet i mappen.'
1083
+ },
1084
+ button: {
1085
+ share: 'Del mappen',
1086
+ preview: 'Forhåndsvis delt mappe',
1087
+ unShare: 'Avslutt deling',
1088
+ shareLink: 'Kopier lenke'
1089
+ }
1090
+ }
1066
1091
  },
1067
1092
  tagList: 'Fáddágilkor',
1068
1093
  tags: '{{count}} fáddágilkor',
@@ -1182,6 +1207,11 @@ var messages = _objectSpread(_objectSpread({
1182
1207
  },
1183
1208
  programme: {
1184
1209
  grades: 'Trinn'
1210
+ },
1211
+ embed: {
1212
+ conceptListError: 'Klarte ikkje å vise forklaringsliste',
1213
+ linkError: 'Klarte ikkje å vise lenke.',
1214
+ unsupported: "Embed {{type}} er ikkje st\xF8tta."
1185
1215
  }
1186
1216
  });
1187
1217
  var _default = messages;
@@ -88,6 +88,29 @@ declare const messages: {
88
88
  onDragEndMissingOver: string;
89
89
  onDragCancel: string;
90
90
  dragHandle: string;
91
+ sharing: {
92
+ share: string;
93
+ shared: string;
94
+ unShare: string;
95
+ link: string;
96
+ header: {
97
+ private: string;
98
+ shared: string;
99
+ unShare: string;
100
+ };
101
+ description: {
102
+ copy: string;
103
+ private: string;
104
+ shared: string;
105
+ unShare: string;
106
+ };
107
+ button: {
108
+ share: string;
109
+ preview: string;
110
+ unShare: string;
111
+ shareLink: string;
112
+ };
113
+ };
91
114
  };
92
115
  tagList: string;
93
116
  tags: string;
@@ -208,6 +231,11 @@ declare const messages: {
208
231
  programme: {
209
232
  grades: string;
210
233
  };
234
+ embed: {
235
+ conceptListError: string;
236
+ linkError: string;
237
+ unsupported: string;
238
+ };
211
239
  common: {
212
240
  subject: string;
213
241
  subject_plural: string;
@@ -796,6 +824,7 @@ declare const messages: {
796
824
  published: string;
797
825
  rightsholder: string;
798
826
  source: string;
827
+ info: string;
799
828
  };
800
829
  errorMessage: {
801
830
  title: string;
@@ -930,6 +959,7 @@ declare const messages: {
930
959
  hits: string;
931
960
  };
932
961
  notions: {
962
+ tags: string;
933
963
  usedIn: string;
934
964
  closeNotion: string;
935
965
  };
@@ -587,7 +587,8 @@ var messages = _objectSpread(_objectSpread({
587
587
  originator: 'Opphaver',
588
588
  published: 'Publiseringsdato',
589
589
  rightsholder: 'Rettighetshaver',
590
- source: 'Gaaltije'
590
+ source: 'Gaaltije',
591
+ info: 'Lisensinformasjon'
591
592
  },
592
593
  errorMessage: {
593
594
  title: 'Ovva, mij akt båajhtede sjïdtit',
@@ -722,6 +723,7 @@ var messages = _objectSpread(_objectSpread({
722
723
  hits: '{{count}} gaavnedimmieh'
723
724
  },
724
725
  notions: {
726
+ tags: 'Liste og filter',
725
727
  usedIn: 'Brukes i',
726
728
  closeNotion: 'Dahph'
727
729
  },
@@ -1062,7 +1064,30 @@ var messages = _objectSpread(_objectSpread({
1062
1064
  onDragEnd: 'Mappa {{name}} blei sloppe på posisjon {{index}} av {{length}}',
1063
1065
  onDragEndMissingOver: 'Mappa blei sloppe',
1064
1066
  onDragCancel: 'Flytting avbrutt. Mappa {{name}} blei sloppe',
1065
- dragHandle: 'Sorter mappen {{name}}'
1067
+ dragHandle: 'Sorter mappen {{name}}',
1068
+ sharing: {
1069
+ share: 'Del mappe',
1070
+ shared: 'Delt',
1071
+ unShare: 'Delingen er avsluttet. Mappen er ikke lenger delt.',
1072
+ link: 'Lenken er kopiert',
1073
+ header: {
1074
+ "private": 'Vil du dele denne mappen?',
1075
+ shared: 'Denne mappen er delt.',
1076
+ unShare: 'Vil du avslutte deling av denne mappen?'
1077
+ },
1078
+ description: {
1079
+ copy: 'Kopier og del denne lenken:',
1080
+ "private": 'Når du deler en mappe lager du en lenke som er åpen for alle som har lenken. Du kan endre innholdet eller avslutte delingen når du ønsker.',
1081
+ shared: 'Nå kan du dele denne lenken med elever eller andre lærere. Hvis du gjør endringer i mappen vil de bli synlige for alle du har delt lenken med.',
1082
+ unShare: 'Når du avslutter deling vil lenken til den delte mappen slutte å virke. Dersom du har delt lenken med noen vil de ikke lengre kunne se innholdet i mappen.'
1083
+ },
1084
+ button: {
1085
+ share: 'Del mappen',
1086
+ preview: 'Forhåndsvis delt mappe',
1087
+ unShare: 'Avslutt deling',
1088
+ shareLink: 'Kopier lenke'
1089
+ }
1090
+ }
1066
1091
  },
1067
1092
  tagList: 'Emneknagg',
1068
1093
  tags: '{{count}} emneknagg',
@@ -1182,6 +1207,11 @@ var messages = _objectSpread(_objectSpread({
1182
1207
  },
1183
1208
  programme: {
1184
1209
  grades: 'Trinn'
1210
+ },
1211
+ embed: {
1212
+ conceptListError: 'Klarte ikkje å vise forklaringsliste',
1213
+ linkError: 'Klarte ikkje å vise lenke.',
1214
+ unsupported: "Embed {{type}} er ikkje st\xF8tta."
1185
1215
  }
1186
1216
  });
1187
1217
  var _default = messages;
package/lib/types.d.ts CHANGED
@@ -39,7 +39,7 @@ export interface License {
39
39
  license: string;
40
40
  }
41
41
  export interface Copyright {
42
- license: License;
42
+ license?: License;
43
43
  creators: Array<Contributor>;
44
44
  rightsholders: Array<Contributor>;
45
45
  processors: Array<Contributor>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "34.6.2",
3
+ "version": "34.6.4",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -31,28 +31,30 @@
31
31
  "types"
32
32
  ],
33
33
  "dependencies": {
34
- "@ndla/article-scripts": "^3.0.14",
35
- "@ndla/button": "^9.1.3",
34
+ "@ndla/article-scripts": "^3.0.15",
35
+ "@ndla/button": "^9.1.4",
36
36
  "@ndla/carousel": "^3.0.3",
37
37
  "@ndla/core": "^3.1.2",
38
- "@ndla/forms": "^4.2.6",
39
- "@ndla/hooks": "^2.0.1",
38
+ "@ndla/forms": "^4.2.7",
39
+ "@ndla/hooks": "^2.0.2",
40
40
  "@ndla/icons": "^2.2.3",
41
41
  "@ndla/licenses": "^7.0.1",
42
42
  "@ndla/modal": "^2.2.7",
43
- "@ndla/notion": "^4.2.3",
44
- "@ndla/safelink": "^4.0.8",
43
+ "@ndla/notion": "^4.2.4",
44
+ "@ndla/safelink": "^4.0.9",
45
45
  "@ndla/switch": "^1.0.7",
46
- "@ndla/tabs": "^2.1.6",
47
- "@ndla/tooltip": "^4.0.9",
46
+ "@ndla/tabs": "^2.1.8",
47
+ "@ndla/tooltip": "^4.0.10",
48
48
  "@ndla/types-learningpath-api": "^0.0.17",
49
- "@ndla/util": "^3.1.9",
49
+ "@ndla/util": "^3.1.10",
50
+ "@radix-ui/react-accordion": "1.1.0",
50
51
  "@radix-ui/react-dropdown-menu": "2.0.2",
52
+ "@radix-ui/react-popover": "^1.0.3",
51
53
  "@reach/menu-button": "^0.16.2",
52
54
  "@reach/slider": "^0.16.0",
53
55
  "focus-trap-react": "^8.9.2",
54
56
  "framer-motion": "^6.5.1",
55
- "html-react-parser": "^0.14.1",
57
+ "html-react-parser": "^3.0.8",
56
58
  "i18next-browser-languagedetector": "^6.1.1",
57
59
  "invariant": "^2.2.3",
58
60
  "react-bem-helper": "1.4.1",
@@ -73,6 +75,8 @@
73
75
  },
74
76
  "devDependencies": {
75
77
  "@babel/plugin-proposal-optional-chaining": "^7.11.0",
78
+ "@ndla/types-embed": "^1.0.1",
79
+ "@ndla/types-image-api": "0.0.10",
76
80
  "@types/reach__dialog": "^0.1.0",
77
81
  "css-loader": "^6.7.3",
78
82
  "mini-css-extract-plugin": "^2.7.2",
@@ -83,5 +87,5 @@
83
87
  "publishConfig": {
84
88
  "access": "public"
85
89
  },
86
- "gitHead": "3ee77008faadb18e2316c564971b19d4ca0fc2c4"
90
+ "gitHead": "22850ec146bbc6fe00fe4e29801109edc0acc975"
87
91
  }
@@ -123,6 +123,7 @@ type Props = {
123
123
  modifier?: string;
124
124
  children?: ReactNode;
125
125
  messages: Messages;
126
+ contentTransformed?: boolean;
126
127
  locale: Locale;
127
128
  messageBoxLinks?: [];
128
129
  copyText?: string;
@@ -137,7 +138,10 @@ type Props = {
137
138
  accessMessage?: string;
138
139
  };
139
140
 
140
- const getArticleContent = (content: any, locale: Locale) => {
141
+ const getArticleContent = (content: any, locale: Locale, contentTransformed?: boolean) => {
142
+ if (contentTransformed) {
143
+ return content;
144
+ }
141
145
  switch (typeof content) {
142
146
  case 'string':
143
147
  return <ArticleContent content={content} locale={locale} />;
@@ -166,6 +170,7 @@ export const Article = ({
166
170
  accessMessage,
167
171
  heartButton,
168
172
  copyText,
173
+ contentTransformed,
169
174
  }: Props) => {
170
175
  const articleRef = useRef<HTMLDivElement>(null);
171
176
  const wrapperRef = useRef<HTMLDivElement>(null);
@@ -232,7 +237,7 @@ export const Article = ({
232
237
  buttonOffsetRight={articlePositionRight}
233
238
  />
234
239
  )}
235
- {getArticleContent(content, locale)}
240
+ {getArticleContent(content, locale, contentTransformed)}
236
241
  </LayoutItem>
237
242
 
238
243
  <LayoutItem layout="center">
@@ -242,7 +247,7 @@ export const Article = ({
242
247
  authors={authors}
243
248
  suppliers={rightsholders}
244
249
  published={published}
245
- license={licenseObj.license}
250
+ license={licenseObj?.license ?? ''}
246
251
  licenseBox={licenseBox}
247
252
  printUrl={printUrl}
248
253
  />
@@ -21,12 +21,20 @@ interface Props {
21
21
  children?: ReactNode;
22
22
  narrowScreen?: boolean;
23
23
  wideScreen?: boolean;
24
+ alwaysShow?: boolean;
24
25
  }
25
26
 
26
- const Aside = ({ children, narrowScreen = false, dangerouslySetInnerHTML, wideScreen = false }: Props) => {
27
+ const Aside = ({
28
+ children,
29
+ narrowScreen = false,
30
+ dangerouslySetInnerHTML,
31
+ wideScreen = false,
32
+ alwaysShow = false,
33
+ }: Props) => {
27
34
  const modifiers = {
28
35
  narrowScreen,
29
36
  wideScreen,
37
+ alwaysShow,
30
38
  };
31
39
  return (
32
40
  <aside {...classes('', modifiers)}>
@@ -28,6 +28,9 @@
28
28
  display: none;
29
29
  }
30
30
  }
31
+ &--alwaysShow {
32
+ display: block !important;
33
+ }
31
34
  }
32
35
 
33
36
  .c-aside__content {
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Copyright (c) 2021-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 { MouseEvent, ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
10
+ import { useTranslation } from 'react-i18next';
11
+ import styled from '@emotion/styled';
12
+ import { colors } from '@ndla/core';
13
+ import Tooltip from '@ndla/tooltip';
14
+ import { Link } from '@ndla/icons/common';
15
+ import { copyTextToClipboard } from '@ndla/util';
16
+
17
+ const ContainerDiv = styled.div`
18
+ position: relative;
19
+ `;
20
+ const IconButton = styled.button`
21
+ position: absolute;
22
+ left: -3em;
23
+ top: 0.1em;
24
+ background: none;
25
+ border: 0;
26
+ z-index: 1;
27
+ transition: 0.2s;
28
+ opacity: 0;
29
+ color: ${colors.brand.grey};
30
+
31
+ & svg {
32
+ width: 30px;
33
+ height: 30px;
34
+ }
35
+
36
+ ${ContainerDiv}:hover &,
37
+ &:focus, &:focus-visible, &:active {
38
+ cursor: pointer;
39
+ opacity: 1;
40
+ }
41
+ `;
42
+
43
+ interface Props {
44
+ // What to render within the h2
45
+ children: ReactNode;
46
+ copyText: string;
47
+ }
48
+ const CopyParagraphButtonV2 = ({ children, copyText }: Props) => {
49
+ const [hasCopied, setHasCopied] = useState(false);
50
+ const { t } = useTranslation();
51
+ const sanitizedTitle = useMemo(() => encodeURIComponent(copyText.replace(/ /g, '-')), [copyText]);
52
+
53
+ useEffect(() => {
54
+ if (hasCopied) {
55
+ setTimeout(() => setHasCopied(false), 3000);
56
+ }
57
+ }, [hasCopied]);
58
+
59
+ const onCopyClick = useCallback(() => {
60
+ setHasCopied(true);
61
+ const { location } = window;
62
+ const newHash = `#${sanitizedTitle}`;
63
+ const port = location.port ? `:${location.port}` : '';
64
+ const urlToCopy = `${location.protocol}//${location.hostname}${port}${location.pathname}${location.search}${newHash}`;
65
+
66
+ copyTextToClipboard(urlToCopy);
67
+ }, [sanitizedTitle]);
68
+
69
+ const tooltip = hasCopied ? t('article.copyPageLinkCopied') : t('article.copyHeaderLink');
70
+ return (
71
+ <ContainerDiv>
72
+ <Tooltip tooltip={tooltip}>
73
+ <IconButton onClick={onCopyClick} aria-label={`${tooltip}: ${copyText}`}>
74
+ <Link />
75
+ </IconButton>
76
+ </Tooltip>
77
+ <h2 id={sanitizedTitle} tabIndex={-1}>
78
+ {children}
79
+ </h2>
80
+ </ContainerDiv>
81
+ );
82
+ };
83
+
84
+ export default CopyParagraphButtonV2;
@@ -7,7 +7,8 @@
7
7
  */
8
8
 
9
9
  import CopyParagraphButton from './CopyParagraphButton';
10
+ import CopyParagraphButtonV2 from './CopyParagraphButtonV2';
10
11
  import initCopyParagraphButtons from './initCopyParagraphButtons';
11
12
 
12
- export { CopyParagraphButton, initCopyParagraphButtons };
13
+ export { CopyParagraphButton, initCopyParagraphButtons, CopyParagraphButtonV2 };
13
14
  export default CopyParagraphButton;
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Copyright (c) 2023-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { AudioMetaData } from '@ndla/types-embed';
10
+ import { ICopyright } from '@ndla/types-image-api';
11
+ import {
12
+ figureApa7CopyString,
13
+ getGroupedContributorDescriptionList,
14
+ getLicenseByAbbreviation,
15
+ getLicenseCredits,
16
+ } from '@ndla/licenses';
17
+ import { ModalV2 } from '@ndla/modal';
18
+ import { useState } from 'react';
19
+ import { useTranslation } from 'react-i18next';
20
+ //@ts-ignore
21
+ import { Remarkable } from 'remarkable';
22
+ import { ButtonV2, CopyButton } from '@ndla/button';
23
+ import { SafeLinkButton } from '@ndla/safelink';
24
+ import AudioPlayer from '../AudioPlayer';
25
+ import { Figure, FigureCaption } from '../Figure';
26
+ import { FigureLicenseDialogContent } from '../Figure/FigureLicenseDialogContent';
27
+ import { Author } from './ImageEmbed';
28
+
29
+ interface Props {
30
+ embed: AudioMetaData;
31
+ articlePath?: string;
32
+ }
33
+ export const getFirstNonEmptyLicenseCredits = (authors: {
34
+ creators: Author[];
35
+ rightsholders: Author[];
36
+ processors: Author[];
37
+ }) => Object.values(authors).find((i) => i.length > 0) ?? [];
38
+
39
+ const renderMarkdown = (text: string) => {
40
+ const md = new Remarkable();
41
+ const rendered = md.render(text);
42
+ return <span dangerouslySetInnerHTML={{ __html: rendered }} />;
43
+ };
44
+
45
+ const AudioEmbed = ({ embed, articlePath }: Props) => {
46
+ const { t, i18n } = useTranslation();
47
+ const [isOpen, setIsOpen] = useState(false);
48
+ if (embed.status === 'error') {
49
+ return (
50
+ <Figure>
51
+ <svg
52
+ fill="#8A8888"
53
+ height="50"
54
+ viewBox="0 0 24 12"
55
+ width="100%"
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ style={{ backgroundColor: '#EFF0F2' }}>
58
+ <path d="M0 0h24v24H0V0z" fill="none" />
59
+ <path
60
+ transform="scale(0.3) translate(28, 8.5)"
61
+ d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
62
+ />
63
+ </svg>
64
+ <figcaption>{t('audio.error.caption')}</figcaption>
65
+ </Figure>
66
+ );
67
+ }
68
+
69
+ const { data, embedData, seq } = embed;
70
+
71
+ if (embedData.type === 'minimal') {
72
+ return <AudioPlayer speech src={data.audioFile.url} title={data.title.title} />;
73
+ }
74
+
75
+ const subtitle = data.series ? { title: data.series.title.title, url: `/podkast/${data.series.id}` } : undefined;
76
+
77
+ const textVersion = data.manuscript && renderMarkdown(data.manuscript.manuscript);
78
+ const description = renderMarkdown(data.podcastMeta?.introduction ?? '');
79
+
80
+ const coverPhoto = data.podcastMeta?.coverPhoto;
81
+
82
+ const img = coverPhoto && { url: coverPhoto.url, alt: coverPhoto.altText };
83
+
84
+ const authors = getLicenseCredits(data.copyright);
85
+
86
+ const license = getLicenseByAbbreviation(data.copyright.license.license, i18n.language);
87
+
88
+ const contributors = getGroupedContributorDescriptionList(data.copyright, i18n.language).map((item) => ({
89
+ name: item.description,
90
+ type: item.label,
91
+ }));
92
+
93
+ const figureId = `figure-${seq}-${data.id}`;
94
+
95
+ const copyString =
96
+ data.audioType === 'podcast'
97
+ ? figureApa7CopyString(
98
+ data.title.title,
99
+ undefined,
100
+ data.audioFile.url,
101
+ articlePath,
102
+ data.copyright,
103
+ data.copyright.license.license,
104
+ '',
105
+ (id: string) => t(id),
106
+ i18n.language,
107
+ )
108
+ : undefined;
109
+ const captionAuthors = getFirstNonEmptyLicenseCredits(authors);
110
+ return (
111
+ <Figure id={figureId} type="full">
112
+ <AudioPlayer
113
+ description={description}
114
+ img={img}
115
+ src={data.audioFile.url}
116
+ textVersion={textVersion}
117
+ title={data.title.title}
118
+ subtitle={subtitle}
119
+ />
120
+ <FigureCaption
121
+ id=""
122
+ figureId=""
123
+ modalButton={
124
+ <ButtonV2 variant="outline" shape="pill" size="small" onClick={() => setIsOpen(true)}>
125
+ {t('audio.reuse')}
126
+ </ButtonV2>
127
+ }
128
+ licenseRights={license.rights}
129
+ authors={captionAuthors}
130
+ locale={i18n.language}
131
+ />
132
+ <ModalV2 controlled isOpen={isOpen} onClose={() => setIsOpen(false)} labelledBy="license-dialog-rules-heading">
133
+ {(close) => (
134
+ <FigureLicenseDialogContent
135
+ onClose={close}
136
+ title={data.title.title}
137
+ license={license}
138
+ authors={contributors}
139
+ origin={data.copyright.origin}
140
+ locale={i18n.language}
141
+ type="audio">
142
+ {data.copyright.license.license !== 'COPYRIGHT' && (
143
+ <>
144
+ {copyString && (
145
+ <CopyButton
146
+ variant="outline"
147
+ copyNode={t('license.hasCopiedTitle')}
148
+ onClick={() => navigator.clipboard.writeText(copyString)}>
149
+ {t('license.copyTitle')}
150
+ </CopyButton>
151
+ )}
152
+ <SafeLinkButton download to={data.audioFile.url} variant="outline">
153
+ {t('audio.download')}
154
+ </SafeLinkButton>
155
+ </>
156
+ )}
157
+ </FigureLicenseDialogContent>
158
+ )}
159
+ </ModalV2>
160
+ {data.imageMeta && (
161
+ <ImageLicense
162
+ title={data.imageMeta.title.title}
163
+ imageUrl={data.imageMeta.imageUrl}
164
+ copyright={data.imageMeta.copyright}
165
+ articlePath={articlePath}
166
+ />
167
+ )}
168
+ </Figure>
169
+ );
170
+ };
171
+
172
+ interface ImageLicenseProps {
173
+ title: string;
174
+ imageUrl: string;
175
+ copyright: ICopyright;
176
+ articlePath?: string;
177
+ }
178
+
179
+ const ImageLicense = ({ articlePath, title, imageUrl, copyright }: ImageLicenseProps) => {
180
+ const { t, i18n } = useTranslation();
181
+ const [isOpen, setIsOpen] = useState(false);
182
+ const copyString = figureApa7CopyString(
183
+ title,
184
+ undefined,
185
+ imageUrl,
186
+ articlePath,
187
+ copyright,
188
+ copyright.license.license,
189
+ undefined,
190
+ (id: string) => t(id),
191
+ i18n.language,
192
+ );
193
+ const license = getLicenseByAbbreviation(copyright.license.license, i18n.language);
194
+ const authors = getLicenseCredits(copyright);
195
+
196
+ const contributors = getGroupedContributorDescriptionList(copyright, i18n.language).map((item) => ({
197
+ name: item.description,
198
+ type: item.label,
199
+ }));
200
+
201
+ const captionAuthors = getFirstNonEmptyLicenseCredits(authors);
202
+
203
+ return (
204
+ <>
205
+ <FigureCaption
206
+ figureId=""
207
+ id=""
208
+ licenseRights={license.rights}
209
+ modalButton={
210
+ <ButtonV2 variant="outline" shape="pill" size="small" onClick={() => setIsOpen(true)}>
211
+ {t('image.reuse')}
212
+ </ButtonV2>
213
+ }
214
+ authors={captionAuthors}
215
+ locale={i18n.language}>
216
+ <ModalV2 controlled isOpen={isOpen} onClose={() => setIsOpen(false)}>
217
+ {(close) => (
218
+ <FigureLicenseDialogContent
219
+ onClose={close}
220
+ title={title}
221
+ license={license}
222
+ authors={contributors}
223
+ origin={copyright.origin}
224
+ locale={i18n.language}
225
+ type="image">
226
+ {copyright.license.license !== 'COPYRIGHTED' && (
227
+ <>
228
+ {copyString && (
229
+ <CopyButton
230
+ variant="outline"
231
+ copyNode={t('license.hasCopiedTitle')}
232
+ onClick={() => navigator.clipboard.writeText(copyString)}>
233
+ {t('license.copyTitle')}
234
+ </CopyButton>
235
+ )}
236
+ <SafeLinkButton download to={imageUrl} variant="outline">
237
+ {t('image.download')}
238
+ </SafeLinkButton>
239
+ </>
240
+ )}
241
+ </FigureLicenseDialogContent>
242
+ )}
243
+ </ModalV2>
244
+ </FigureCaption>
245
+ </>
246
+ );
247
+ };
248
+
249
+ export default AudioEmbed;