@ndla/ui 56.0.185-alpha.0 → 56.0.187-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 (113) hide show
  1. package/dist/panda.buildinfo.json +20 -27
  2. package/dist/styles.css +61 -140
  3. package/es/Article/ArticleByline.mjs +2 -1
  4. package/es/Article/ArticleByline.mjs.map +1 -1
  5. package/es/AudioPlayer/AudioElement.mjs +12 -0
  6. package/es/AudioPlayer/AudioElement.mjs.map +1 -0
  7. package/es/AudioPlayer/AudioPlayer.mjs +7 -2
  8. package/es/AudioPlayer/AudioPlayer.mjs.map +1 -1
  9. package/es/AudioPlayer/AudioProgress.mjs +54 -0
  10. package/es/AudioPlayer/AudioProgress.mjs.map +1 -0
  11. package/es/AudioPlayer/CompactAudioPlayer.mjs +111 -0
  12. package/es/AudioPlayer/CompactAudioPlayer.mjs.map +1 -0
  13. package/es/AudioPlayer/Controls.mjs +25 -110
  14. package/es/AudioPlayer/Controls.mjs.map +1 -1
  15. package/es/AudioPlayer/PlayButton.mjs +24 -0
  16. package/es/AudioPlayer/PlayButton.mjs.map +1 -0
  17. package/es/AudioPlayer/SpeechControl.mjs +5 -16
  18. package/es/AudioPlayer/SpeechControl.mjs.map +1 -1
  19. package/es/AudioPlayer/VolumeSlider.mjs +31 -0
  20. package/es/AudioPlayer/VolumeSlider.mjs.map +1 -0
  21. package/es/AudioPlayer/audioUtils.mjs +17 -0
  22. package/es/AudioPlayer/audioUtils.mjs.map +1 -0
  23. package/es/AudioPlayer/useAudioControls.mjs +55 -0
  24. package/es/AudioPlayer/useAudioControls.mjs.map +1 -0
  25. package/es/Breadcrumb/BreadcrumbItem.mjs +1 -2
  26. package/es/Breadcrumb/BreadcrumbItem.mjs.map +1 -1
  27. package/es/Embed/AudioEmbed.mjs +3 -7
  28. package/es/Embed/AudioEmbed.mjs.map +1 -1
  29. package/es/Embed/ExternalEmbed.mjs +13 -16
  30. package/es/Embed/ExternalEmbed.mjs.map +1 -1
  31. package/es/Embed/IframeEmbed.mjs +4 -5
  32. package/es/Embed/IframeEmbed.mjs.map +1 -1
  33. package/es/FactBox/FactBox.mjs +14 -38
  34. package/es/FactBox/FactBox.mjs.map +1 -1
  35. package/es/Gloss/Gloss.mjs +1 -2
  36. package/es/Gloss/Gloss.mjs.map +1 -1
  37. package/es/Grid/Grid.mjs +1 -2
  38. package/es/Grid/Grid.mjs.map +1 -1
  39. package/es/LinkBlock/LinkBlock.mjs +9 -2
  40. package/es/LinkBlock/LinkBlock.mjs.map +1 -1
  41. package/es/Pitch/Pitch.mjs +1 -2
  42. package/es/Pitch/Pitch.mjs.map +1 -1
  43. package/es/index.mjs +2 -1
  44. package/lib/Article/ArticleByline.js +2 -1
  45. package/lib/Article/ArticleByline.js.map +1 -1
  46. package/lib/AudioPlayer/AudioElement.d.ts +14 -0
  47. package/lib/AudioPlayer/AudioElement.js +13 -0
  48. package/lib/AudioPlayer/AudioElement.js.map +1 -0
  49. package/lib/AudioPlayer/AudioPlayer.d.ts +5 -4
  50. package/lib/AudioPlayer/AudioPlayer.js +7 -2
  51. package/lib/AudioPlayer/AudioPlayer.js.map +1 -1
  52. package/lib/AudioPlayer/AudioProgress.d.ts +16 -0
  53. package/lib/AudioPlayer/AudioProgress.js +55 -0
  54. package/lib/AudioPlayer/AudioProgress.js.map +1 -0
  55. package/lib/AudioPlayer/CompactAudioPlayer.d.ts +13 -0
  56. package/lib/AudioPlayer/CompactAudioPlayer.js +112 -0
  57. package/lib/AudioPlayer/CompactAudioPlayer.js.map +1 -0
  58. package/lib/AudioPlayer/Controls.d.ts +1 -0
  59. package/lib/AudioPlayer/Controls.js +25 -110
  60. package/lib/AudioPlayer/Controls.js.map +1 -1
  61. package/lib/AudioPlayer/PlayButton.d.ts +13 -0
  62. package/lib/AudioPlayer/PlayButton.js +25 -0
  63. package/lib/AudioPlayer/PlayButton.js.map +1 -0
  64. package/lib/AudioPlayer/SpeechControl.d.ts +1 -2
  65. package/lib/AudioPlayer/SpeechControl.js +5 -16
  66. package/lib/AudioPlayer/SpeechControl.js.map +1 -1
  67. package/lib/AudioPlayer/VolumeSlider.d.ts +14 -0
  68. package/lib/AudioPlayer/VolumeSlider.js +32 -0
  69. package/lib/AudioPlayer/VolumeSlider.js.map +1 -0
  70. package/lib/AudioPlayer/audioUtils.d.ts +8 -0
  71. package/lib/AudioPlayer/audioUtils.js +17 -0
  72. package/lib/AudioPlayer/audioUtils.js.map +1 -0
  73. package/lib/AudioPlayer/useAudioControls.d.ts +24 -0
  74. package/lib/AudioPlayer/useAudioControls.js +56 -0
  75. package/lib/AudioPlayer/useAudioControls.js.map +1 -0
  76. package/lib/Breadcrumb/BreadcrumbItem.js +1 -2
  77. package/lib/Breadcrumb/BreadcrumbItem.js.map +1 -1
  78. package/lib/Embed/AudioEmbed.js +3 -7
  79. package/lib/Embed/AudioEmbed.js.map +1 -1
  80. package/lib/Embed/ExternalEmbed.js +13 -16
  81. package/lib/Embed/ExternalEmbed.js.map +1 -1
  82. package/lib/Embed/IframeEmbed.js +4 -5
  83. package/lib/Embed/IframeEmbed.js.map +1 -1
  84. package/lib/FactBox/FactBox.js +13 -37
  85. package/lib/FactBox/FactBox.js.map +1 -1
  86. package/lib/Gloss/Gloss.js +1 -2
  87. package/lib/Gloss/Gloss.js.map +1 -1
  88. package/lib/Grid/Grid.js +1 -2
  89. package/lib/Grid/Grid.js.map +1 -1
  90. package/lib/LinkBlock/LinkBlock.js +9 -2
  91. package/lib/LinkBlock/LinkBlock.js.map +1 -1
  92. package/lib/Pitch/Pitch.js +1 -2
  93. package/lib/Pitch/Pitch.js.map +1 -1
  94. package/lib/index.d.ts +2 -0
  95. package/lib/index.js +2 -0
  96. package/package.json +10 -10
  97. package/src/Article/ArticleByline.tsx +5 -1
  98. package/src/AudioPlayer/AudioElement.tsx +20 -0
  99. package/src/AudioPlayer/{AudiPlayer.stories.tsx → AudioPlayer.stories.tsx} +10 -1
  100. package/src/AudioPlayer/AudioPlayer.tsx +12 -5
  101. package/src/AudioPlayer/AudioProgress.tsx +92 -0
  102. package/src/AudioPlayer/CompactAudioPlayer.tsx +124 -0
  103. package/src/AudioPlayer/Controls.tsx +36 -149
  104. package/src/AudioPlayer/PlayButton.tsx +24 -0
  105. package/src/AudioPlayer/SpeechControl.tsx +6 -19
  106. package/src/AudioPlayer/VolumeSlider.tsx +56 -0
  107. package/src/AudioPlayer/audioUtils.ts +15 -0
  108. package/src/AudioPlayer/useAudioControls.ts +80 -0
  109. package/src/Embed/AudioEmbed.tsx +3 -4
  110. package/src/FactBox/FactBox.tsx +13 -43
  111. package/src/Gloss/Gloss.tsx +1 -1
  112. package/src/LinkBlock/LinkBlock.tsx +5 -2
  113. package/src/index.ts +2 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "schemaVersion": "1.7.0",
2
+ "schemaVersion": "1.10.0",
3
3
  "styles": {
4
4
  "atomic": [
5
5
  "position]___[value:absolute]___[cond:_before",
@@ -81,6 +81,20 @@
81
81
  "direction]___[value:rtl]___[cond:& p:has(span[dir=\"rtl\"])",
82
82
  "alignSelf]___[value:flex-start",
83
83
  "marginInlineStart]___[value:3xsmall",
84
+ "borderRadius]___[value:0",
85
+ "width]___[value:4xsmall",
86
+ "height]___[value:4xsmall",
87
+ "background]___[value:unset",
88
+ "height]___[value:unset",
89
+ "paddingBlockEnd]___[value:0",
90
+ "boxShadow]___[value:xsmall",
91
+ "background]___[value:surface.brand.1.subtle",
92
+ "minWidth]___[value:4xlarge",
93
+ "flexShrink]___[value:0",
94
+ "textAlign]___[value:center",
95
+ "marginInlineStart]___[value:auto",
96
+ "textOverflow]___[value:ellipsis",
97
+ "whiteSpace]___[value:nowrap",
84
98
  "borderBottomRadius]___[value:xsmall",
85
99
  "justifyContent]___[value:center",
86
100
  "paddingInline]___[value:medium",
@@ -97,8 +111,6 @@
97
111
  "gridArea]___[value:track",
98
112
  "paddingInline]___[value:xsmall]___[cond:mobileDown",
99
113
  "minWidth]___[value:xxlarge",
100
- "flexShrink]___[value:0",
101
- "textAlign]___[value:center",
102
114
  "gridArea]___[value:volume",
103
115
  "paddingBlock]___[value:auto",
104
116
  "paddingInline]___[value:auto",
@@ -106,9 +118,9 @@
106
118
  "maxHeight]___[value:xxlarge",
107
119
  "flex]___[value:1]___[cond:& span",
108
120
  "gridArea]___[value:speed",
121
+ "paddingInline]___[value:small",
109
122
  "height]___[value:surface.3xsmall",
110
123
  "minWidth]___[value:small",
111
- "paddingInline]___[value:small",
112
124
  "alignItems]___[value:flex-start]___[cond:mobileDown",
113
125
  "justifyContent]___[value:center]___[cond:mobileDown",
114
126
  "flexDirection]___[value:column]___[cond:mobileDown",
@@ -251,32 +263,15 @@
251
263
  "transitionTimingFunction]___[value:ease-in-out",
252
264
  "justifyItems]___[value:center",
253
265
  "gridTemplateRows]___[value:1fr]___[cond:_open",
254
- "overflow]___[value:visible]___[cond:_closed<___>_print",
255
- "maxHeight]___[value:500vh]___[cond:_closed<___>_print",
266
+ "gridTemplateRows]___[value:1fr]___[cond:_print",
267
+ "overflow]___[value:visible]___[cond:_print",
268
+ "maxHeight]___[value:500vh]___[cond:_print",
256
269
  "minHeight]___[value:surface.3xsmall]___[cond:& > div",
257
270
  "overflow]___[value:hidden]___[cond:& > div",
271
+ "overflow]___[value:visible]___[cond:& > div<___>_print",
258
272
  "marginBlockStart]___[value:0]___[cond:& :first-child",
259
- "content]___[value:\"\"]___[cond:_after",
260
- "textAlign]___[value:center]___[cond:_after",
261
- "position]___[value:absolute]___[cond:_after",
262
- "inset]___[value:0]___[cond:_after",
263
- "transitionProperty]___[value:opacity]___[cond:_after",
264
- "transitionDuration]___[value:slow]___[cond:_after",
265
- "transitionTimingFunction]___[value:ease-in-out]___[cond:_after",
266
- "gradientFrom]___[value:surface.default/20]___[cond:_after",
267
- "gradientTo]___[value:surface.default/95]___[cond:_after",
268
- "backgroundGradient]___[value:to-b]___[cond:_after",
269
- "opacity]___[value:1]___[cond:_after",
270
- "zIndex]___[value:base]___[cond:_after",
271
- "pointerEvents]___[value:none]___[cond:_after",
272
- "overflow]___[value:visible]___[cond:_print",
273
- "display]___[value:none]___[cond:_print<___>_after",
274
273
  "paddingBlockEnd]___[value:xsmall]___[cond:_open",
275
- "opacity]___[value:0]___[cond:_open<___>_after",
276
274
  "bottom]___[value:-medium",
277
- "transitionTimingFunction]___[value:ease-in-out]___[cond:& svg",
278
- "transitionDuration]___[value:fast]___[cond:& svg",
279
- "transform]___[value:rotate(180deg)]___[cond:_open<___>& svg",
280
275
  "textUnderlineOffset]___[value:2px",
281
276
  "paddingBlock]___[value:small",
282
277
  "paddingInlineEnd]___[value:medium",
@@ -333,7 +328,6 @@
333
328
  "maxHeight]___[value:none]___[cond:mobileWideDown<___>_open",
334
329
  "display]___[value:none]___[cond:mobileWide",
335
330
  "color]___[value:text.link",
336
- "whiteSpace]___[value:nowrap",
337
331
  "textDecoration]___[value:none]___[cond:_focusWithin",
338
332
  "display]___[value:none]___[cond:mobileWideDown<___>_disabled",
339
333
  "textDecoration]___[value:underline]___[cond:& h3",
@@ -349,7 +343,6 @@
349
343
  "outline]___[value:0px",
350
344
  "boxShadow]___[value:none",
351
345
  "aspectRatio]___[value:16/9",
352
- "height]___[value:unset",
353
346
  "gridTemplateColumns]___[value:repeat(2, 1fr)",
354
347
  "gridTemplateColumns]___[value:1fr]___[cond:tabletDown",
355
348
  "marginBlockStart]___[value:xsmall",
package/dist/styles.css CHANGED
@@ -101,9 +101,6 @@
101
101
  font-size: calc(var(--font-sizes-3xlarge) * 1.11);
102
102
  line-height: calc(var(--line-heights-3xlarge) * 1.11);
103
103
  }
104
- }
105
-
106
- @media screen and (max-width: 29.7475rem) {
107
104
  .textStyle_title\.medium {
108
105
  font-size: var(--font-sizes-medium);
109
106
  line-height: var(--line-heights-small);
@@ -125,9 +122,6 @@
125
122
  font-size: calc(var(--font-sizes-xsmall) * 1.11);
126
123
  line-height: calc(var(--line-heights-xsmall) * 1.11);
127
124
  }
128
- }
129
-
130
- @media print {
131
125
  .textStyle_label\.large {
132
126
  font-size: var(--font-sizes-small);
133
127
  line-height: var(--line-heights-small);
@@ -137,9 +131,6 @@
137
131
  font-size: calc(var(--font-sizes-small) * 1.11);
138
132
  line-height: calc(var(--line-heights-small) * 1.11);
139
133
  }
140
- }
141
-
142
- @media print {
143
134
  .textStyle_heading\.large {
144
135
  font-size: var(--font-sizes-3xlarge);
145
136
  line-height: var(--line-heights-3xlarge);
@@ -149,9 +140,6 @@
149
140
  font-size: calc(var(--font-sizes-3xlarge) * 1.11);
150
141
  line-height: calc(var(--line-heights-3xlarge) * 1.11);
151
142
  }
152
- }
153
-
154
- @media print {
155
143
  .textStyle_title\.medium {
156
144
  font-size: var(--font-sizes-medium);
157
145
  line-height: var(--line-heights-medium);
@@ -161,9 +149,6 @@
161
149
  font-size: calc(var(--font-sizes-medium) * 1.11);
162
150
  line-height: calc(var(--line-heights-medium) * 1.11);
163
151
  }
164
- }
165
-
166
- @media print {
167
152
  .textStyle_label\.medium {
168
153
  font-size: var(--font-sizes-xsmall);
169
154
  line-height: var(--line-heights-xsmall);
@@ -173,9 +158,6 @@
173
158
  font-size: calc(var(--font-sizes-xsmall) * 1.11);
174
159
  line-height: calc(var(--line-heights-xsmall) * 1.11);
175
160
  }
176
- }
177
-
178
- @media print {
179
161
  .\[\&_a\]\:textStyle_label\.xsmall a {
180
162
  font-size: var(--font-sizes-xxsmall);
181
163
  line-height: var(--line-heights-xxsmall);
@@ -200,6 +182,14 @@
200
182
  padding: var(--spacing-xsmall);
201
183
  }
202
184
 
185
+ .bg_unset {
186
+ background: unset;
187
+ }
188
+
189
+ .bg_surface\.brand\.1\.subtle {
190
+ background: var(--colors-surface-brand-1-subtle);
191
+ }
192
+
203
193
  .grid-area_play {
204
194
  grid-area: play;
205
195
  }
@@ -324,6 +314,10 @@
324
314
  padding-inline: var(--spacing-xsmall);
325
315
  }
326
316
 
317
+ .bdr_0 {
318
+ border-radius: 0;
319
+ }
320
+
327
321
  .px_medium {
328
322
  padding-inline: var(--spacing-medium);
329
323
  }
@@ -473,13 +467,12 @@
473
467
  margin-inline-start: var(--spacing-3xsmall);
474
468
  }
475
469
 
476
- .bdr-b_xsmall {
477
- border-bottom-left-radius: var(--radii-xsmall);
478
- border-bottom-right-radius: var(--radii-xsmall);
470
+ .pbe_0 {
471
+ padding-block-end: 0;
479
472
  }
480
473
 
481
- .jc_center {
482
- justify-content: center;
474
+ .bx-sh_xsmall {
475
+ box-shadow: var(--shadows-xsmall);
483
476
  }
484
477
 
485
478
  .flex-sh_0 {
@@ -490,6 +483,27 @@
490
483
  text-align: center;
491
484
  }
492
485
 
486
+ .ms_auto {
487
+ margin-inline-start: auto;
488
+ }
489
+
490
+ .tov_ellipsis {
491
+ text-overflow: ellipsis;
492
+ }
493
+
494
+ .white-space_nowrap {
495
+ white-space: nowrap;
496
+ }
497
+
498
+ .bdr-b_xsmall {
499
+ border-bottom-left-radius: var(--radii-xsmall);
500
+ border-bottom-right-radius: var(--radii-xsmall);
501
+ }
502
+
503
+ .jc_center {
504
+ justify-content: center;
505
+ }
506
+
493
507
  .c_inherit {
494
508
  color: inherit;
495
509
  }
@@ -680,10 +694,6 @@
680
694
  color: var(--colors-text-link);
681
695
  }
682
696
 
683
- .white-space_nowrap {
684
- white-space: nowrap;
685
- }
686
-
687
697
  .c_icon\.strong {
688
698
  color: var(--colors-icon-strong);
689
699
  }
@@ -740,6 +750,22 @@
740
750
  max-width: var(--sizes-surface-xlarge);
741
751
  }
742
752
 
753
+ .w_4xsmall {
754
+ width: var(--sizes-4xsmall);
755
+ }
756
+
757
+ .h_4xsmall {
758
+ height: var(--sizes-4xsmall);
759
+ }
760
+
761
+ .h_unset {
762
+ height: unset;
763
+ }
764
+
765
+ .min-w_4xlarge {
766
+ min-width: var(--sizes-4xlarge);
767
+ }
768
+
743
769
  .min-w_xxlarge {
744
770
  min-width: var(--sizes-xxlarge);
745
771
  }
@@ -828,11 +854,7 @@
828
854
  width: var(--sizes-surface-3xsmall);
829
855
  }
830
856
 
831
- .h_unset {
832
- height: unset;
833
- }
834
-
835
- .after\:inset_0::after,.before\:inset_0::before {
857
+ .before\:inset_0::before {
836
858
  inset: 0;
837
859
  }
838
860
 
@@ -1000,75 +1022,10 @@
1000
1022
  margin-block-start: 0;
1001
1023
  }
1002
1024
 
1003
- .after\:content_\"\"::after {
1004
- content: "";
1005
- }
1006
-
1007
- .after\:ta_center::after {
1008
- text-align: center;
1009
- }
1010
-
1011
- .after\:pos_absolute::after {
1012
- position: absolute;
1013
- }
1014
-
1015
- .after\:trs-prop_opacity::after {
1016
- --transition-prop: opacity;
1017
- transition-property: opacity;
1018
- }
1019
-
1020
- .after\:trs-dur_slow::after {
1021
- --transition-duration: var(--durations-slow);
1022
- transition-duration: var(--durations-slow);
1023
- }
1024
-
1025
- .after\:trs-tmf_ease-in-out::after {
1026
- --transition-easing: ease-in-out;
1027
- transition-timing-function: ease-in-out;
1028
- }
1029
-
1030
- .after\:grad-from_surface\.default\/20::after {
1031
- --mix---gradient-from: color-mix(in srgb, var(--colors-surface-default) 20%, transparent);
1032
- --gradient-from: var(--mix---gradient-from, var(--colors-surface-default));
1033
- }
1034
-
1035
- .after\:grad-to_surface\.default\/95::after {
1036
- --mix---gradient-to: color-mix(in srgb, var(--colors-surface-default) 95%, transparent);
1037
- --gradient-to: var(--mix---gradient-to, var(--colors-surface-default));
1038
- }
1039
-
1040
- .after\:bg-grad_to-b::after {
1041
- --gradient-stops: var(--gradient-via-stops, var(--gradient-position), var(--gradient-from) var(--gradient-from-position), var(--gradient-to) var(--gradient-to-position));
1042
- --gradient-position: to bottom;
1043
- background-image: linear-gradient(var(--gradient-stops));
1044
- }
1045
-
1046
- .after\:op_1::after {
1047
- opacity: 1;
1048
- }
1049
-
1050
- .after\:z_base::after {
1051
- z-index: var(--z-index-base);
1052
- }
1053
-
1054
- .after\:pointer-events_none::after {
1055
- pointer-events: none;
1056
- }
1057
-
1058
1025
  .open\:pbe_xsmall:is([open], [data-open], [data-state="open"], :popover-open) {
1059
1026
  padding-block-end: var(--spacing-xsmall);
1060
1027
  }
1061
1028
 
1062
- .\[\&_svg\]\:trs-tmf_ease-in-out svg {
1063
- --transition-easing: ease-in-out;
1064
- transition-timing-function: ease-in-out;
1065
- }
1066
-
1067
- .\[\&_svg\]\:trs-dur_fast svg {
1068
- --transition-duration: var(--durations-fast);
1069
- transition-duration: var(--durations-fast);
1070
- }
1071
-
1072
1029
  .before\:z_0::before {
1073
1030
  z-index: 0;
1074
1031
  }
@@ -1144,11 +1101,7 @@
1144
1101
  height: 100%;
1145
1102
  }
1146
1103
 
1147
- .focusWithin\:text-decoration_none:focus-within {
1148
- text-decoration: none;
1149
- }
1150
-
1151
- .focusVisible\:text-decoration_none:is(:focus-visible, [data-focus-visible]) {
1104
+ .focusWithin\:text-decoration_none:focus-within,.focusVisible\:text-decoration_none:is(:focus-visible, [data-focus-visible]) {
1152
1105
  text-decoration: none;
1153
1106
  }
1154
1107
 
@@ -1198,14 +1151,6 @@
1198
1151
  transform: rotate(-45deg);
1199
1152
  }
1200
1153
 
1201
- .open\:after\:op_0:is([open], [data-open], [data-state="open"], :popover-open)::after {
1202
- opacity: 0;
1203
- }
1204
-
1205
- .open\:\[\&_svg\]\:trf_rotate\(180deg\):is([open], [data-open], [data-state="open"], :popover-open) svg {
1206
- transform: rotate(180deg);
1207
- }
1208
-
1209
1154
  .first\:\[\&_p\]\:fw_bold:first-child p {
1210
1155
  font-weight: var(--font-weights-bold);
1211
1156
  }
@@ -1340,9 +1285,6 @@
1340
1285
  .\[\&\[data-has-image\=\'true\'\]\]\:tablet\:px_medium[data-has-image='true'] {
1341
1286
  padding-inline: var(--spacing-medium);
1342
1287
  }
1343
- }
1344
-
1345
- @media screen and (min-width: 37.5625rem) {
1346
1288
  .hover\:tablet\:before\:vis_visible:is(:hover, [data-hover])::before {
1347
1289
  visibility: visible;
1348
1290
  }
@@ -1538,27 +1480,15 @@
1538
1480
  .mobileWideDown\:max-h_large {
1539
1481
  max-height: var(--sizes-large);
1540
1482
  }
1541
- }
1542
-
1543
- @media screen and (max-width: 29.7475rem) {
1544
1483
  .mobileWideDown\:open\:d_inline:is([open], [data-open], [data-state="open"], :popover-open) {
1545
1484
  display: inline;
1546
1485
  }
1547
- }
1548
-
1549
- @media screen and (max-width: 29.7475rem) {
1550
1486
  .mobileWideDown\:open\:white-space_pre-wrap:is([open], [data-open], [data-state="open"], :popover-open) {
1551
1487
  white-space: pre-wrap;
1552
1488
  }
1553
- }
1554
-
1555
- @media screen and (max-width: 29.7475rem) {
1556
1489
  .mobileWideDown\:disabled\:d_none:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) {
1557
1490
  display: none;
1558
1491
  }
1559
- }
1560
-
1561
- @media screen and (max-width: 29.7475rem) {
1562
1492
  .mobileWideDown\:open\:max-h_none:is([open], [data-open], [data-state="open"], :popover-open) {
1563
1493
  max-height: none;
1564
1494
  }
@@ -1586,23 +1516,14 @@
1586
1516
  .print\:d_none {
1587
1517
  display: none;
1588
1518
  }
1519
+ .print\:grid-tr_1fr {
1520
+ grid-template-rows: 1fr;
1589
1521
  }
1590
-
1591
- @media print {
1592
- .closed\:print\:ov_visible:is([closed], [data-closed], [data-state="closed"]) {
1593
- overflow: visible;
1594
- }
1595
- }
1596
-
1597
- @media print {
1598
- .print\:after\:d_none::after {
1599
- display: none;
1600
- }
1601
- }
1602
-
1603
- @media print {
1604
- .closed\:print\:max-h_500vh:is([closed], [data-closed], [data-state="closed"]) {
1522
+ .print\:max-h_500vh {
1605
1523
  max-height: 500vh;
1524
+ }
1525
+ .\[\&_\>_div\]\:print\:ov_visible > div {
1526
+ overflow: visible;
1606
1527
  }
1607
1528
  }
1608
1529
  }
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next";
6
6
  import { ArrowDownShortLine } from "@ndla/icons";
7
7
  import { SafeLink } from "@ndla/safelink";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { toIntlLanguage } from "@ndla/util";
9
10
  import { useAccordionContext } from "@ark-ui/react";
10
11
  //#region src/Article/ArticleByline.tsx
11
12
  /**
@@ -50,7 +51,7 @@ const accordionItemValue = "rulesForUse";
50
51
  const ArticleByline = ({ lang, authors = [], suppliers = [], footnotes, licenseBox, published, displayByline = true, bylineType = "article", bylineSuffix, learningpathCopiedFrom }) => {
51
52
  const { t, i18n } = useTranslation();
52
53
  const showPrimaryContributors = suppliers.length > 0 || authors.length > 0;
53
- const listFormatter = new Intl.ListFormat(lang ?? i18n.language, {
54
+ const listFormatter = new Intl.ListFormat(toIntlLanguage(lang ?? i18n.language), {
54
55
  style: "long",
55
56
  type: "conjunction"
56
57
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ArticleByline.mjs","names":[],"sources":["../../src/Article/ArticleByline.tsx"],"sourcesContent":["/**\n * Copyright (c) 2020-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { useAccordionContext } from \"@ark-ui/react\";\nimport { ArrowDownShortLine } from \"@ndla/icons\";\nimport {\n AccordionItem,\n AccordionItemContent,\n AccordionItemIndicator,\n type AccordionItemProps,\n AccordionItemTrigger,\n AccordionRoot,\n Heading,\n} from \"@ndla/primitives\";\nimport { SafeLink } from \"@ndla/safelink\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { type ReactNode, forwardRef, useCallback, useEffect, useRef } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type { FootNote } from \"../types\";\nimport { ArticleFootNotes } from \"./ArticleFootNotes\";\n\nconst Wrapper = styled(\"div\", {\n base: {\n // TODO: Figure out if we want to remove this margin. It's only here to add some gap between the article content and the byline.\n marginBlockStart: \"medium\",\n paddingBlockStart: \"xsmall\",\n borderTop: \"1px solid\",\n borderColor: \"stroke.subtle\",\n },\n});\n\nconst TextWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"3xsmall\",\n width: \"100%\",\n justifyContent: \"space-between\",\n paddingBlock: \"xsmall\",\n textStyle: \"body.medium\",\n '& [data-contributors=\"false\"]': {\n marginInlineStart: \"auto\",\n },\n },\n variants: {\n learningpath: {\n true: {},\n false: {\n tabletWide: {\n flexDirection: \"row\",\n },\n },\n },\n },\n});\n\ntype AuthorProps = {\n name: string;\n};\n\ntype SupplierProps = {\n name: string;\n};\n\ntype Props = {\n lang?: string;\n authors?: AuthorProps[];\n suppliers?: SupplierProps[];\n published?: string;\n licenseBox?: ReactNode;\n footnotes?: FootNote[];\n displayByline?: boolean;\n bylineType?: \"article\" | \"learningPath\" | \"external\";\n bylineSuffix?: ReactNode;\n learningpathCopiedFrom?: string;\n};\n\nfunction formatList(list: SupplierProps[], listFormatter: Intl.ListFormat) {\n return listFormatter.format(list.map((l) => l.name));\n}\n\nconst StyledAccordionRoot = styled(AccordionRoot, {\n base: {\n paddingBlockStart: \"xxlarge\",\n _print: {\n display: \"none\",\n },\n },\n});\n\nconst refRegexp = /note\\d/;\nconst footnotesAccordionId = \"footnotes\";\nconst accordionItemValue = \"rulesForUse\";\n\nexport const ArticleByline = ({\n lang,\n authors = [],\n suppliers = [],\n footnotes,\n licenseBox,\n published,\n displayByline = true,\n bylineType = \"article\",\n bylineSuffix,\n learningpathCopiedFrom,\n}: Props) => {\n const { t, i18n } = useTranslation();\n\n const showPrimaryContributors = suppliers.length > 0 || authors.length > 0;\n const listFormatter = new Intl.ListFormat(lang ?? i18n.language, { style: \"long\", type: \"conjunction\" });\n\n return (\n <Wrapper>\n {!!displayByline && (\n <TextWrapper learningpath={bylineType === \"learningPath\"}>\n {!!showPrimaryContributors && (\n <span>\n {authors.length > 0 &&\n `${t(\"article.authorsLabel\", { context: bylineType })} ${formatList(authors, listFormatter)}. `}\n {suppliers.length > 0 &&\n `${t(\"article.supplierLabel\", { count: suppliers.length })} ${formatList(suppliers, listFormatter)}.`}\n </span>\n )}\n {learningpathCopiedFrom ? (\n <SafeLink to={learningpathCopiedFrom}>{t(`learningPath.copiedFrom`)}</SafeLink>\n ) : null}\n {published ? (\n <div data-contributors={showPrimaryContributors}>\n {t(`${bylineType}.lastUpdated`)} {published}\n </div>\n ) : null}\n {bylineSuffix}\n </TextWrapper>\n )}\n {(!!licenseBox || !!footnotes?.length) && (\n <StyledAccordionRoot multiple>\n {!!licenseBox && (\n <ArticleBylineAccordionItem value={accordionItemValue} accordionTitle={t(\"article.useContent\")}>\n {licenseBox}\n </ArticleBylineAccordionItem>\n )}\n {!!footnotes?.length && <ArticleBylineFootnotes footnotes={footnotes} />}\n </StyledAccordionRoot>\n )}\n </Wrapper>\n );\n};\n\ninterface ArticleBylineAccordionprops extends AccordionItemProps {\n accordionTitle: ReactNode;\n}\n\ninterface ArticleBylineFootnotesProps {\n footnotes: FootNote[];\n}\n\nexport const ArticleBylineFootnotes = ({ footnotes }: ArticleBylineFootnotesProps) => {\n const { t } = useTranslation();\n const { value, setValue } = useAccordionContext();\n const ref = useRef<HTMLDivElement>(null);\n\n const onHashChange = useCallback(\n (e: HashChangeEvent) => {\n const hash = e.newURL.split(\"#\")[1];\n if (hash?.match(refRegexp) && !value.includes(footnotesAccordionId)) {\n ref.current?.scrollIntoView({ behavior: \"smooth\" });\n setValue([...value, footnotesAccordionId]);\n setTimeout(() => {\n const el = document.getElementById(`${hash}`);\n el?.click();\n el?.focus();\n }, 300);\n }\n },\n [value, setValue],\n );\n\n useEffect(() => {\n window.addEventListener(\"hashchange\", onHashChange);\n return () => window.removeEventListener(\"hashchange\", onHashChange);\n }, [onHashChange]);\n\n return (\n <ArticleBylineAccordionItem ref={ref} value={footnotesAccordionId} accordionTitle={t(\"article.footnotes\")}>\n <ArticleFootNotes footNotes={footnotes} />\n </ArticleBylineAccordionItem>\n );\n};\n\nexport const ArticleBylineAccordionItem = forwardRef<HTMLDivElement, ArticleBylineAccordionprops>(\n ({ value, accordionTitle, children, ...props }, ref) => {\n return (\n <AccordionItem value={value} ref={ref} {...props}>\n <Heading asChild consumeCss textStyle=\"label.medium\" fontWeight=\"bold\">\n <h2>\n <AccordionItemTrigger>\n {accordionTitle}\n <AccordionItemIndicator asChild>\n <ArrowDownShortLine />\n </AccordionItemIndicator>\n </AccordionItemTrigger>\n </h2>\n </Heading>\n <AccordionItemContent>{children}</AccordionItemContent>\n </AccordionItem>\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ArticleByline.mjs","names":[],"sources":["../../src/Article/ArticleByline.tsx"],"sourcesContent":["/**\n * Copyright (c) 2020-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { useAccordionContext } from \"@ark-ui/react\";\nimport { ArrowDownShortLine } from \"@ndla/icons\";\nimport {\n AccordionItem,\n AccordionItemContent,\n AccordionItemIndicator,\n type AccordionItemProps,\n AccordionItemTrigger,\n AccordionRoot,\n Heading,\n} from \"@ndla/primitives\";\nimport { SafeLink } from \"@ndla/safelink\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { toIntlLanguage } from \"@ndla/util\";\nimport { type ReactNode, forwardRef, useCallback, useEffect, useRef } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type { FootNote } from \"../types\";\nimport { ArticleFootNotes } from \"./ArticleFootNotes\";\n\nconst Wrapper = styled(\"div\", {\n base: {\n // TODO: Figure out if we want to remove this margin. It's only here to add some gap between the article content and the byline.\n marginBlockStart: \"medium\",\n paddingBlockStart: \"xsmall\",\n borderTop: \"1px solid\",\n borderColor: \"stroke.subtle\",\n },\n});\n\nconst TextWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"3xsmall\",\n width: \"100%\",\n justifyContent: \"space-between\",\n paddingBlock: \"xsmall\",\n textStyle: \"body.medium\",\n '& [data-contributors=\"false\"]': {\n marginInlineStart: \"auto\",\n },\n },\n variants: {\n learningpath: {\n true: {},\n false: {\n tabletWide: {\n flexDirection: \"row\",\n },\n },\n },\n },\n});\n\ntype AuthorProps = {\n name: string;\n};\n\ntype SupplierProps = {\n name: string;\n};\n\ntype Props = {\n lang?: string;\n authors?: AuthorProps[];\n suppliers?: SupplierProps[];\n published?: string;\n licenseBox?: ReactNode;\n footnotes?: FootNote[];\n displayByline?: boolean;\n bylineType?: \"article\" | \"learningPath\" | \"external\";\n bylineSuffix?: ReactNode;\n learningpathCopiedFrom?: string;\n};\n\nfunction formatList(list: SupplierProps[], listFormatter: Intl.ListFormat) {\n return listFormatter.format(list.map((l) => l.name));\n}\n\nconst StyledAccordionRoot = styled(AccordionRoot, {\n base: {\n paddingBlockStart: \"xxlarge\",\n _print: {\n display: \"none\",\n },\n },\n});\n\nconst refRegexp = /note\\d/;\nconst footnotesAccordionId = \"footnotes\";\nconst accordionItemValue = \"rulesForUse\";\n\nexport const ArticleByline = ({\n lang,\n authors = [],\n suppliers = [],\n footnotes,\n licenseBox,\n published,\n displayByline = true,\n bylineType = \"article\",\n bylineSuffix,\n learningpathCopiedFrom,\n}: Props) => {\n const { t, i18n } = useTranslation();\n\n const showPrimaryContributors = suppliers.length > 0 || authors.length > 0;\n const listFormatter = new Intl.ListFormat(toIntlLanguage(lang ?? i18n.language), {\n style: \"long\",\n type: \"conjunction\",\n });\n\n return (\n <Wrapper>\n {!!displayByline && (\n <TextWrapper learningpath={bylineType === \"learningPath\"}>\n {!!showPrimaryContributors && (\n <span>\n {authors.length > 0 &&\n `${t(\"article.authorsLabel\", { context: bylineType })} ${formatList(authors, listFormatter)}. `}\n {suppliers.length > 0 &&\n `${t(\"article.supplierLabel\", { count: suppliers.length })} ${formatList(suppliers, listFormatter)}.`}\n </span>\n )}\n {learningpathCopiedFrom ? (\n <SafeLink to={learningpathCopiedFrom}>{t(`learningPath.copiedFrom`)}</SafeLink>\n ) : null}\n {published ? (\n <div data-contributors={showPrimaryContributors}>\n {t(`${bylineType}.lastUpdated`)} {published}\n </div>\n ) : null}\n {bylineSuffix}\n </TextWrapper>\n )}\n {(!!licenseBox || !!footnotes?.length) && (\n <StyledAccordionRoot multiple>\n {!!licenseBox && (\n <ArticleBylineAccordionItem value={accordionItemValue} accordionTitle={t(\"article.useContent\")}>\n {licenseBox}\n </ArticleBylineAccordionItem>\n )}\n {!!footnotes?.length && <ArticleBylineFootnotes footnotes={footnotes} />}\n </StyledAccordionRoot>\n )}\n </Wrapper>\n );\n};\n\ninterface ArticleBylineAccordionprops extends AccordionItemProps {\n accordionTitle: ReactNode;\n}\n\ninterface ArticleBylineFootnotesProps {\n footnotes: FootNote[];\n}\n\nexport const ArticleBylineFootnotes = ({ footnotes }: ArticleBylineFootnotesProps) => {\n const { t } = useTranslation();\n const { value, setValue } = useAccordionContext();\n const ref = useRef<HTMLDivElement>(null);\n\n const onHashChange = useCallback(\n (e: HashChangeEvent) => {\n const hash = e.newURL.split(\"#\")[1];\n if (hash?.match(refRegexp) && !value.includes(footnotesAccordionId)) {\n ref.current?.scrollIntoView({ behavior: \"smooth\" });\n setValue([...value, footnotesAccordionId]);\n setTimeout(() => {\n const el = document.getElementById(`${hash}`);\n el?.click();\n el?.focus();\n }, 300);\n }\n },\n [value, setValue],\n );\n\n useEffect(() => {\n window.addEventListener(\"hashchange\", onHashChange);\n return () => window.removeEventListener(\"hashchange\", onHashChange);\n }, [onHashChange]);\n\n return (\n <ArticleBylineAccordionItem ref={ref} value={footnotesAccordionId} accordionTitle={t(\"article.footnotes\")}>\n <ArticleFootNotes footNotes={footnotes} />\n </ArticleBylineAccordionItem>\n );\n};\n\nexport const ArticleBylineAccordionItem = forwardRef<HTMLDivElement, ArticleBylineAccordionprops>(\n ({ value, accordionTitle, children, ...props }, ref) => {\n return (\n <AccordionItem value={value} ref={ref} {...props}>\n <Heading asChild consumeCss textStyle=\"label.medium\" fontWeight=\"bold\">\n <h2>\n <AccordionItemTrigger>\n {accordionTitle}\n <AccordionItemIndicator asChild>\n <ArrowDownShortLine />\n </AccordionItemIndicator>\n </AccordionItemTrigger>\n </h2>\n </Heading>\n <AccordionItemContent>{children}</AccordionItemContent>\n </AccordionItem>\n );\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/AudioPlayer/AudioElement.tsx
3
+ const AudioElement = (props) => {
4
+ return /* @__PURE__ */ jsx("audio", {
5
+ preload: "metadata",
6
+ ...props
7
+ });
8
+ };
9
+ //#endregion
10
+ export { AudioElement };
11
+
12
+ //# sourceMappingURL=AudioElement.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioElement.mjs","names":[],"sources":["../../src/AudioPlayer/AudioElement.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ComponentProps } from \"react\";\n\ninterface Props extends ComponentProps<\"audio\"> {\n src: string;\n title: string;\n}\n\nexport const AudioElement = (props: Props) => {\n // TODO: We should tie this up to the textual description somehow\n // oxlint-disable-next-line jsx-a11y/media-has-caption\n return <audio preload=\"metadata\" {...props} />;\n};\n"],"mappings":";;AAeA,MAAa,gBAAgB,UAAiB;AAG5C,QAAO,oBAAC,SAAD;EAAO,SAAQ;EAAW,GAAI;EAAS,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { CompactAudioPlayer } from "./CompactAudioPlayer.mjs";
1
2
  import { Controls } from "./Controls.mjs";
2
3
  import { SpeechControl } from "./SpeechControl.mjs";
3
4
  import { Button, Heading, Text } from "@ndla/primitives";
@@ -92,13 +93,17 @@ const TextVersionText = styled("div", { base: {
92
93
  const TextVersionButton = styled(Button, { base: { alignSelf: "flex-start" } });
93
94
  const ShowMoreButton = styled(Button, { base: { marginInlineStart: "3xsmall" } });
94
95
  const DESCRIPTION_MAX_LENGTH = 200;
95
- const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersion }) => {
96
+ const AudioPlayer = ({ src, title, subtitle, variant = "standard", description, img, textVersion }) => {
96
97
  const { t } = useTranslation();
97
98
  const [showTextVersion, setShowTextVersion] = useState(false);
98
99
  const [showFullDescription, setShowFullDescription] = useState(false);
99
100
  const truncatedDescription = useMemo(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);
100
101
  const textDescriptionId = useId();
101
- if (speech) return /* @__PURE__ */ jsx(SpeechControl, {
102
+ if (variant === "minimal") return /* @__PURE__ */ jsx(SpeechControl, {
103
+ src,
104
+ title
105
+ });
106
+ if (variant === "compact") return /* @__PURE__ */ jsx(CompactAudioPlayer, {
102
107
  src,
103
108
  title
104
109
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AudioPlayer.mjs","names":[],"sources":["../../src/AudioPlayer/AudioPlayer.tsx"],"sourcesContent":["/**\n * Copyright (c) 2017-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { Heading, Text, Button } from \"@ndla/primitives\";\nimport { SafeLink } from \"@ndla/safelink\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { type ReactNode, useId, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Controls } from \"./Controls\";\nimport { SpeechControl } from \"./SpeechControl\";\n\n// TODO: Could the audio metadata be more tightly coupled to the audio player?\n\nconst AudioPlayerWrapper = styled(\"div\", {\n base: {\n border: \"1px solid\",\n borderColor: \"stroke.default\",\n borderRadius: \"xsmall\",\n boxShadow: \"full\",\n marginBlockEnd: \"4xsmall\",\n overflow: \"hidden\",\n },\n});\n\nconst InfoWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n tabletWideDown: {\n display: \"block\",\n },\n },\n});\n\nconst ImageWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"center\",\n flex: \"1 0 auto\",\n width: \"surface.4xsmall\",\n height: \"surface.4xsmall\",\n overflow: \"hidden\",\n \"& img\": {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n desktop: {\n width: \"260px\",\n height: \"260px\",\n },\n tabletWideDown: {\n maxHeight: \"surface.small\",\n maxWidth: \"100%\",\n width: \"100%\",\n height: \"auto\",\n },\n },\n});\n\nconst TextWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"flex-start\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n padding: \"xsmall\",\n width: \"100%\",\n \"&[data-has-image='true']\": {\n tablet: {\n paddingBlock: \"xsmall\",\n paddingInline: \"medium\",\n },\n },\n },\n});\n\nconst TitleWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n fontFamily: \"sans\",\n tabletWide: {\n width: \"100%\",\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n },\n },\n});\n\nconst TextVersionWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n borderBlockStart: \"1px solid\",\n borderColor: \"stroke.default\",\n paddingBlock: \"medium\",\n paddingInline: \"xsmall\",\n tablet: {\n paddingInline: \"medium\",\n },\n },\n});\n\nconst TextVersionText = styled(\"div\", {\n base: {\n maxWidth: \"surface.xlarge\",\n \"& span > *\": {\n whiteSpace: \"pre-wrap\",\n },\n \"& p:not(:first-child):not(:last-child)\": {\n marginBlock: \"small\",\n },\n '& p[data-align=\"center\"]': {\n textAlign: \"center\",\n },\n '& p:has(span[dir=\"rtl\"])': {\n direction: \"rtl\",\n },\n },\n});\n\nconst TextVersionButton = styled(Button, {\n base: {\n alignSelf: \"flex-start\",\n },\n});\n\nconst ShowMoreButton = styled(Button, {\n base: {\n marginInlineStart: \"3xsmall\",\n },\n});\n\nconst DESCRIPTION_MAX_LENGTH = 200;\n\ntype Props = {\n src: string;\n title: string;\n subtitle?: {\n title: string;\n url?: string;\n };\n speech?: boolean;\n description?: string;\n textVersion?: ReactNode;\n img?: {\n url: string;\n alt: string;\n };\n};\n\nexport const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersion }: Props) => {\n const { t } = useTranslation();\n const [showTextVersion, setShowTextVersion] = useState(false);\n const [showFullDescription, setShowFullDescription] = useState(false);\n const truncatedDescription = useMemo(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);\n const textDescriptionId = useId();\n\n if (speech) {\n return <SpeechControl src={src} title={title} />;\n }\n\n const toggleTextVersion = () => {\n setShowTextVersion((curr) => !curr);\n };\n\n const textVersionButton = (\n <TextVersionButton\n variant=\"secondary\"\n aria-expanded={showTextVersion}\n aria-controls={textDescriptionId}\n size=\"small\"\n onClick={toggleTextVersion}\n >\n {t(showTextVersion ? \"audio.textVersion.close\" : \"audio.textVersion.heading\")}\n </TextVersionButton>\n );\n\n return (\n <AudioPlayerWrapper>\n <InfoWrapper>\n {!!img && (\n <ImageWrapper>\n <img src={img.url} alt={img.alt} />\n </ImageWrapper>\n )}\n <TextWrapper data-has-image={!!img}>\n <TitleWrapper>\n <div>\n {subtitle?.url ? <SafeLink to={subtitle.url}>{subtitle.title}</SafeLink> : subtitle?.title}\n <Heading asChild consumeCss textStyle=\"title.large\">\n <h3>{title}</h3>\n </Heading>\n </div>\n {!!textVersion && !img && textVersionButton}\n </TitleWrapper>\n {!!description && (\n <Text textStyle=\"body.medium\">\n {showFullDescription || description.length < DESCRIPTION_MAX_LENGTH\n ? description\n : `${truncatedDescription}...`}\n {description.length > DESCRIPTION_MAX_LENGTH && (\n <ShowMoreButton variant=\"link\" onClick={() => setShowFullDescription((p) => !p)}>\n {t(`audio.${showFullDescription ? \"readLessDescriptionLabel\" : \"readMoreDescriptionLabel\"}`)}\n </ShowMoreButton>\n )}\n </Text>\n )}\n {!!textVersion && !!img && textVersionButton}\n </TextWrapper>\n </InfoWrapper>\n <Controls src={src} title={title} />\n {!!textVersion && (\n <TextVersionWrapper id={textDescriptionId} hidden={!showTextVersion}>\n <Heading asChild textStyle=\"title.medium\" consumeCss>\n <h4>{t(\"audio.textVersion.heading\")}</h4>\n </Heading>\n <TextVersionText>{textVersion}</TextVersionText>\n </TextVersionWrapper>\n )}\n </AudioPlayerWrapper>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AudioPlayer.mjs","names":[],"sources":["../../src/AudioPlayer/AudioPlayer.tsx"],"sourcesContent":["/**\n * Copyright (c) 2017-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { Heading, Text, Button } from \"@ndla/primitives\";\nimport { SafeLink } from \"@ndla/safelink\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { type ReactNode, useId, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { CompactAudioPlayer } from \"./CompactAudioPlayer\";\nimport { Controls } from \"./Controls\";\nimport { SpeechControl } from \"./SpeechControl\";\n\n// TODO: Could the audio metadata be more tightly coupled to the audio player?\n\nconst AudioPlayerWrapper = styled(\"div\", {\n base: {\n border: \"1px solid\",\n borderColor: \"stroke.default\",\n borderRadius: \"xsmall\",\n boxShadow: \"full\",\n marginBlockEnd: \"4xsmall\",\n overflow: \"hidden\",\n },\n});\n\nconst InfoWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n tabletWideDown: {\n display: \"block\",\n },\n },\n});\n\nconst ImageWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"center\",\n flex: \"1 0 auto\",\n width: \"surface.4xsmall\",\n height: \"surface.4xsmall\",\n overflow: \"hidden\",\n \"& img\": {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n desktop: {\n width: \"260px\",\n height: \"260px\",\n },\n tabletWideDown: {\n maxHeight: \"surface.small\",\n maxWidth: \"100%\",\n width: \"100%\",\n height: \"auto\",\n },\n },\n});\n\nconst TextWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"flex-start\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n padding: \"xsmall\",\n width: \"100%\",\n \"&[data-has-image='true']\": {\n tablet: {\n paddingBlock: \"xsmall\",\n paddingInline: \"medium\",\n },\n },\n },\n});\n\nconst TitleWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n fontFamily: \"sans\",\n tabletWide: {\n width: \"100%\",\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n },\n },\n});\n\nconst TextVersionWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n borderBlockStart: \"1px solid\",\n borderColor: \"stroke.default\",\n paddingBlock: \"medium\",\n paddingInline: \"xsmall\",\n tablet: {\n paddingInline: \"medium\",\n },\n },\n});\n\nconst TextVersionText = styled(\"div\", {\n base: {\n maxWidth: \"surface.xlarge\",\n \"& span > *\": {\n whiteSpace: \"pre-wrap\",\n },\n \"& p:not(:first-child):not(:last-child)\": {\n marginBlock: \"small\",\n },\n '& p[data-align=\"center\"]': {\n textAlign: \"center\",\n },\n '& p:has(span[dir=\"rtl\"])': {\n direction: \"rtl\",\n },\n },\n});\n\nconst TextVersionButton = styled(Button, {\n base: {\n alignSelf: \"flex-start\",\n },\n});\n\nconst ShowMoreButton = styled(Button, {\n base: {\n marginInlineStart: \"3xsmall\",\n },\n});\n\nconst DESCRIPTION_MAX_LENGTH = 200;\n\nexport type AudioPlayerVariant = \"standard\" | \"minimal\" | \"compact\";\n\ninterface Props {\n src: string;\n title: string;\n subtitle?: {\n title: string;\n url?: string;\n };\n variant?: AudioPlayerVariant;\n description?: string;\n textVersion?: ReactNode;\n img?: {\n url: string;\n alt: string;\n };\n}\n\nexport const AudioPlayer = ({ src, title, subtitle, variant = \"standard\", description, img, textVersion }: Props) => {\n const { t } = useTranslation();\n const [showTextVersion, setShowTextVersion] = useState(false);\n const [showFullDescription, setShowFullDescription] = useState(false);\n const truncatedDescription = useMemo(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);\n const textDescriptionId = useId();\n\n if (variant === \"minimal\") {\n return <SpeechControl src={src} title={title} />;\n }\n\n if (variant === \"compact\") {\n return <CompactAudioPlayer src={src} title={title} />;\n }\n\n const toggleTextVersion = () => {\n setShowTextVersion((curr) => !curr);\n };\n\n const textVersionButton = (\n <TextVersionButton\n variant=\"secondary\"\n aria-expanded={showTextVersion}\n aria-controls={textDescriptionId}\n size=\"small\"\n onClick={toggleTextVersion}\n >\n {t(showTextVersion ? \"audio.textVersion.close\" : \"audio.textVersion.heading\")}\n </TextVersionButton>\n );\n\n return (\n <AudioPlayerWrapper>\n <InfoWrapper>\n {!!img && (\n <ImageWrapper>\n <img src={img.url} alt={img.alt} />\n </ImageWrapper>\n )}\n <TextWrapper data-has-image={!!img}>\n <TitleWrapper>\n <div>\n {subtitle?.url ? <SafeLink to={subtitle.url}>{subtitle.title}</SafeLink> : subtitle?.title}\n <Heading asChild consumeCss textStyle=\"title.large\">\n <h3>{title}</h3>\n </Heading>\n </div>\n {!!textVersion && !img && textVersionButton}\n </TitleWrapper>\n {!!description && (\n <Text textStyle=\"body.medium\">\n {showFullDescription || description.length < DESCRIPTION_MAX_LENGTH\n ? description\n : `${truncatedDescription}...`}\n {description.length > DESCRIPTION_MAX_LENGTH && (\n <ShowMoreButton variant=\"link\" onClick={() => setShowFullDescription((p) => !p)}>\n {t(`audio.${showFullDescription ? \"readLessDescriptionLabel\" : \"readMoreDescriptionLabel\"}`)}\n </ShowMoreButton>\n )}\n </Text>\n )}\n {!!textVersion && !!img && textVersionButton}\n </TextWrapper>\n </InfoWrapper>\n <Controls src={src} title={title} />\n {!!textVersion && (\n <TextVersionWrapper id={textDescriptionId} hidden={!showTextVersion}>\n <Heading asChild textStyle=\"title.medium\" consumeCss>\n <h4>{t(\"audio.textVersion.heading\")}</h4>\n </Heading>\n <TextVersionText>{textVersion}</TextVersionText>\n </TextVersionWrapper>\n )}\n </AudioPlayerWrapper>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { formatTime } from "./audioUtils.mjs";
2
+ import { SliderControl, SliderHiddenInput, SliderLabel, SliderRange, SliderRoot, SliderThumb, SliderTrack } from "@ndla/primitives";
3
+ import { styled } from "@ndla/styled-system/jsx";
4
+ import { useTranslation } from "react-i18next";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/AudioPlayer/AudioProgress.tsx
7
+ const StyledSliderThumb = styled(SliderThumb, { variants: { variant: {
8
+ standard: {},
9
+ simple: {
10
+ borderRadius: "0",
11
+ width: "4xsmall",
12
+ height: "4xsmall"
13
+ }
14
+ } } });
15
+ const StyledSliderTrack = styled(SliderTrack, { variants: { variant: {
16
+ standard: {},
17
+ simple: { background: "unset" }
18
+ } } });
19
+ const StyledSliderControl = styled(SliderControl, { variants: { variant: {
20
+ standard: {},
21
+ simple: { height: "unset" }
22
+ } } });
23
+ const AudioProgress = ({ currentTime, duration, onValueChange, variant }) => {
24
+ const { t } = useTranslation();
25
+ return /* @__PURE__ */ jsxs(SliderRoot, {
26
+ value: [currentTime],
27
+ defaultValue: [0],
28
+ step: 1,
29
+ max: duration,
30
+ onValueChange,
31
+ getAriaValueText: (value) => t("audio.valueText", {
32
+ start: formatTime(Math.round(value.value)),
33
+ end: formatTime(Math.round(duration))
34
+ }),
35
+ children: [/* @__PURE__ */ jsx(SliderLabel, {
36
+ srOnly: true,
37
+ children: t("audio.progressBar")
38
+ }), /* @__PURE__ */ jsxs(StyledSliderControl, {
39
+ variant,
40
+ children: [/* @__PURE__ */ jsx(StyledSliderTrack, {
41
+ variant,
42
+ children: /* @__PURE__ */ jsx(SliderRange, {})
43
+ }), /* @__PURE__ */ jsx(StyledSliderThumb, {
44
+ index: 0,
45
+ variant,
46
+ children: /* @__PURE__ */ jsx(SliderHiddenInput, {})
47
+ })]
48
+ })]
49
+ });
50
+ };
51
+ //#endregion
52
+ export { AudioProgress };
53
+
54
+ //# sourceMappingURL=AudioProgress.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioProgress.mjs","names":[],"sources":["../../src/AudioPlayer/AudioProgress.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { SliderValueChangeDetails } from \"@ark-ui/react\";\nimport {\n SliderRoot,\n SliderLabel,\n SliderControl,\n SliderTrack,\n SliderRange,\n SliderThumb,\n SliderHiddenInput,\n} from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { useTranslation } from \"react-i18next\";\nimport { formatTime } from \"./audioUtils\";\n\ninterface Props {\n currentTime: number;\n duration: number;\n onValueChange: (details: SliderValueChangeDetails) => void;\n variant?: \"simple\" | \"standard\";\n}\n\nconst StyledSliderThumb = styled(SliderThumb, {\n variants: {\n variant: {\n standard: {},\n simple: {\n borderRadius: \"0\",\n width: \"4xsmall\",\n height: \"4xsmall\",\n },\n },\n },\n});\n\nconst StyledSliderTrack = styled(SliderTrack, {\n variants: {\n variant: {\n standard: {},\n simple: {\n background: \"unset\",\n },\n },\n },\n});\n\nconst StyledSliderControl = styled(SliderControl, {\n variants: {\n variant: {\n standard: {},\n simple: {\n height: \"unset\",\n },\n },\n },\n});\n\nexport const AudioProgress = ({ currentTime, duration, onValueChange, variant }: Props) => {\n const { t } = useTranslation();\n return (\n <SliderRoot\n value={[currentTime]}\n defaultValue={[0]}\n step={1}\n max={duration}\n onValueChange={onValueChange}\n getAriaValueText={(value) =>\n t(\"audio.valueText\", {\n start: formatTime(Math.round(value.value)),\n end: formatTime(Math.round(duration)),\n })\n }\n >\n <SliderLabel srOnly>{t(\"audio.progressBar\")}</SliderLabel>\n <StyledSliderControl variant={variant}>\n <StyledSliderTrack variant={variant}>\n <SliderRange />\n </StyledSliderTrack>\n <StyledSliderThumb index={0} variant={variant}>\n <SliderHiddenInput />\n </StyledSliderThumb>\n </StyledSliderControl>\n </SliderRoot>\n );\n};\n"],"mappings":";;;;;;AA6BA,MAAM,oBAAoB,OAAO,aAAa,EAC5C,UAAU,EACR,SAAS;CACP,UAAU,EAAE;CACZ,QAAQ;EACN,cAAc;EACd,OAAO;EACP,QAAQ;EACT;CACF,EACF,EACF,CAAC;AAEF,MAAM,oBAAoB,OAAO,aAAa,EAC5C,UAAU,EACR,SAAS;CACP,UAAU,EAAE;CACZ,QAAQ,EACN,YAAY,SACb;CACF,EACF,EACF,CAAC;AAEF,MAAM,sBAAsB,OAAO,eAAe,EAChD,UAAU,EACR,SAAS;CACP,UAAU,EAAE;CACZ,QAAQ,EACN,QAAQ,SACT;CACF,EACF,EACF,CAAC;AAEF,MAAa,iBAAiB,EAAE,aAAa,UAAU,eAAe,cAAqB;CACzF,MAAM,EAAE,MAAM,gBAAgB;AAC9B,QACE,qBAAC,YAAD;EACE,OAAO,CAAC,YAAY;EACpB,cAAc,CAAC,EAAE;EACjB,MAAM;EACN,KAAK;EACU;EACf,mBAAmB,UACjB,EAAE,mBAAmB;GACnB,OAAO,WAAW,KAAK,MAAM,MAAM,MAAM,CAAC;GAC1C,KAAK,WAAW,KAAK,MAAM,SAAS,CAAC;GACtC,CAAC;YAVN,CAaE,oBAAC,aAAD;GAAa,QAAA;aAAQ,EAAE,oBAAoB;GAAe,CAAA,EAC1D,qBAAC,qBAAD;GAA8B;aAA9B,CACE,oBAAC,mBAAD;IAA4B;cAC1B,oBAAC,aAAD,EAAe,CAAA;IACG,CAAA,EACpB,oBAAC,mBAAD;IAAmB,OAAO;IAAY;cACpC,oBAAC,mBAAD,EAAqB,CAAA;IACH,CAAA,CACA;KACX"}