@ndla/ui 56.0.186-alpha.0 → 56.0.188-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 (78) hide show
  1. package/dist/panda.buildinfo.json +15 -5
  2. package/dist/styles.css +53 -13
  3. package/es/AudioPlayer/AudioElement.mjs +12 -0
  4. package/es/AudioPlayer/AudioElement.mjs.map +1 -0
  5. package/es/AudioPlayer/AudioPlayer.mjs +7 -2
  6. package/es/AudioPlayer/AudioPlayer.mjs.map +1 -1
  7. package/es/AudioPlayer/AudioProgress.mjs +54 -0
  8. package/es/AudioPlayer/AudioProgress.mjs.map +1 -0
  9. package/es/AudioPlayer/CompactAudioPlayer.mjs +111 -0
  10. package/es/AudioPlayer/CompactAudioPlayer.mjs.map +1 -0
  11. package/es/AudioPlayer/Controls.mjs +25 -110
  12. package/es/AudioPlayer/Controls.mjs.map +1 -1
  13. package/es/AudioPlayer/PlayButton.mjs +24 -0
  14. package/es/AudioPlayer/PlayButton.mjs.map +1 -0
  15. package/es/AudioPlayer/SpeechControl.mjs +5 -16
  16. package/es/AudioPlayer/SpeechControl.mjs.map +1 -1
  17. package/es/AudioPlayer/VolumeSlider.mjs +31 -0
  18. package/es/AudioPlayer/VolumeSlider.mjs.map +1 -0
  19. package/es/AudioPlayer/audioUtils.mjs +17 -0
  20. package/es/AudioPlayer/audioUtils.mjs.map +1 -0
  21. package/es/AudioPlayer/useAudioControls.mjs +55 -0
  22. package/es/AudioPlayer/useAudioControls.mjs.map +1 -0
  23. package/es/Embed/AudioEmbed.mjs +3 -6
  24. package/es/Embed/AudioEmbed.mjs.map +1 -1
  25. package/es/Gloss/Gloss.mjs +1 -2
  26. package/es/Gloss/Gloss.mjs.map +1 -1
  27. package/es/index.mjs +2 -1
  28. package/lib/AudioPlayer/AudioElement.d.ts +14 -0
  29. package/lib/AudioPlayer/AudioElement.js +13 -0
  30. package/lib/AudioPlayer/AudioElement.js.map +1 -0
  31. package/lib/AudioPlayer/AudioPlayer.d.ts +5 -4
  32. package/lib/AudioPlayer/AudioPlayer.js +7 -2
  33. package/lib/AudioPlayer/AudioPlayer.js.map +1 -1
  34. package/lib/AudioPlayer/AudioProgress.d.ts +16 -0
  35. package/lib/AudioPlayer/AudioProgress.js +55 -0
  36. package/lib/AudioPlayer/AudioProgress.js.map +1 -0
  37. package/lib/AudioPlayer/CompactAudioPlayer.d.ts +13 -0
  38. package/lib/AudioPlayer/CompactAudioPlayer.js +112 -0
  39. package/lib/AudioPlayer/CompactAudioPlayer.js.map +1 -0
  40. package/lib/AudioPlayer/Controls.d.ts +1 -0
  41. package/lib/AudioPlayer/Controls.js +25 -110
  42. package/lib/AudioPlayer/Controls.js.map +1 -1
  43. package/lib/AudioPlayer/PlayButton.d.ts +13 -0
  44. package/lib/AudioPlayer/PlayButton.js +25 -0
  45. package/lib/AudioPlayer/PlayButton.js.map +1 -0
  46. package/lib/AudioPlayer/SpeechControl.d.ts +1 -2
  47. package/lib/AudioPlayer/SpeechControl.js +5 -16
  48. package/lib/AudioPlayer/SpeechControl.js.map +1 -1
  49. package/lib/AudioPlayer/VolumeSlider.d.ts +14 -0
  50. package/lib/AudioPlayer/VolumeSlider.js +32 -0
  51. package/lib/AudioPlayer/VolumeSlider.js.map +1 -0
  52. package/lib/AudioPlayer/audioUtils.d.ts +8 -0
  53. package/lib/AudioPlayer/audioUtils.js +17 -0
  54. package/lib/AudioPlayer/audioUtils.js.map +1 -0
  55. package/lib/AudioPlayer/useAudioControls.d.ts +24 -0
  56. package/lib/AudioPlayer/useAudioControls.js +56 -0
  57. package/lib/AudioPlayer/useAudioControls.js.map +1 -0
  58. package/lib/Embed/AudioEmbed.js +3 -6
  59. package/lib/Embed/AudioEmbed.js.map +1 -1
  60. package/lib/Gloss/Gloss.js +1 -2
  61. package/lib/Gloss/Gloss.js.map +1 -1
  62. package/lib/index.d.ts +2 -0
  63. package/lib/index.js +2 -0
  64. package/package.json +2 -2
  65. package/src/AudioPlayer/AudioElement.tsx +20 -0
  66. package/src/AudioPlayer/{AudiPlayer.stories.tsx → AudioPlayer.stories.tsx} +10 -1
  67. package/src/AudioPlayer/AudioPlayer.tsx +12 -5
  68. package/src/AudioPlayer/AudioProgress.tsx +92 -0
  69. package/src/AudioPlayer/CompactAudioPlayer.tsx +124 -0
  70. package/src/AudioPlayer/Controls.tsx +36 -149
  71. package/src/AudioPlayer/PlayButton.tsx +24 -0
  72. package/src/AudioPlayer/SpeechControl.tsx +6 -19
  73. package/src/AudioPlayer/VolumeSlider.tsx +56 -0
  74. package/src/AudioPlayer/audioUtils.ts +15 -0
  75. package/src/AudioPlayer/useAudioControls.ts +80 -0
  76. package/src/Embed/AudioEmbed.tsx +10 -9
  77. package/src/Gloss/Gloss.tsx +1 -1
  78. package/src/index.ts +2 -0
@@ -6,8 +6,8 @@
6
6
  *
7
7
  */
8
8
 
9
- import { type SliderValueChangeDetails, createListCollection } from "@ark-ui/react";
10
- import { Replay15Line, Forward15Line, PlayFill, PauseLine, VolumeUpFill, CheckLine } from "@ndla/icons";
9
+ import { createListCollection } from "@ark-ui/react";
10
+ import { Replay15Line, Forward15Line, VolumeUpFill, CheckLine } from "@ndla/icons";
11
11
  import {
12
12
  Button,
13
13
  FieldRoot,
@@ -23,18 +23,16 @@ import {
23
23
  SelectLabel,
24
24
  SelectRoot,
25
25
  SelectTrigger,
26
- SliderControl,
27
- SliderHiddenInput,
28
- SliderLabel,
29
- SliderRange,
30
- SliderRoot,
31
- SliderThumb,
32
- SliderTrack,
33
26
  Text,
34
27
  } from "@ndla/primitives";
35
28
  import { styled } from "@ndla/styled-system/jsx";
36
- import { useEffect, useRef, useState } from "react";
37
29
  import { useTranslation } from "react-i18next";
30
+ import { AudioElement } from "./AudioElement";
31
+ import { AudioProgress } from "./AudioProgress";
32
+ import { formatTime } from "./audioUtils";
33
+ import { PlayButton } from "./PlayButton";
34
+ import { useAudioControls } from "./useAudioControls";
35
+ import { VolumeSlider } from "./VolumeSlider";
38
36
 
39
37
  const ControlsWrapper = styled("div", {
40
38
  base: {
@@ -64,7 +62,7 @@ const ControlsWrapper = styled("div", {
64
62
  },
65
63
  });
66
64
 
67
- const PlayButton = styled(IconButton, {
65
+ const StyledPlayButton = styled(PlayButton, {
68
66
  base: {
69
67
  gridArea: "play",
70
68
  },
@@ -130,117 +128,48 @@ const StyledSelectRoot = styled(SelectRoot<string>, {
130
128
  },
131
129
  });
132
130
 
133
- const StyledSliderControl = styled(SliderControl, {
134
- base: {
135
- height: "surface.3xsmall",
136
- minWidth: "small",
137
- },
138
- });
139
-
140
131
  const StyledPopoverContent = styled(PopoverContent, {
141
132
  base: {
142
133
  paddingInline: "small",
143
134
  },
144
135
  });
145
136
 
146
- const formatTime = (seconds: number) => {
147
- const minutes = Math.floor(seconds / 60);
148
- const currentSeconds = seconds % 60;
149
-
150
- const formattedSeconds = currentSeconds < 10 ? `0${currentSeconds}` : currentSeconds;
151
- return `${minutes}:${formattedSeconds}`;
152
- };
153
-
154
137
  const speedValues = createListCollection({ items: ["0.5", "0.75", "1", "1.25", "1.5", "1.75", "2"] });
155
138
 
156
139
  interface Props {
157
140
  src: string;
158
141
  title: string;
142
+ variant?: "full" | "simplified";
159
143
  }
160
144
 
161
145
  export const Controls = ({ src, title }: Props) => {
162
146
  const { t } = useTranslation();
163
- const [speedValue, setSpeedValue] = useState(1);
164
- const [volumeValue, setVolumeValue] = useState(100);
165
- const [currentTime, setCurrentTime] = useState(0);
166
- const [duration, setDuration] = useState(0);
167
- const [playing, setPlaying] = useState(false);
168
- const audioRef = useRef<HTMLAudioElement>(null);
169
-
170
- useEffect(() => {
171
- if (audioRef.current) {
172
- const audioElement = audioRef.current;
173
- const handleTimeUpdate = () => {
174
- const { currentTime, duration } = audioElement;
175
- setCurrentTime(Math.round(currentTime));
176
- setDuration(Math.round(duration));
177
- };
178
-
179
- const handleLoadedMetaData = () => {
180
- const { currentTime, duration } = audioElement;
181
- setCurrentTime(Math.round(currentTime));
182
- setDuration(Math.round(duration));
183
- };
184
-
185
- const handleTimeEnded = () => {
186
- setPlaying(false);
187
- };
188
-
189
- audioElement.addEventListener("timeupdate", handleTimeUpdate);
190
- audioElement.addEventListener("loadedmetadata", handleLoadedMetaData);
191
- audioElement.addEventListener("ended", handleTimeEnded);
192
- return () => {
193
- audioElement.removeEventListener("timeupdate", handleTimeUpdate);
194
- audioElement.removeEventListener("loadedmetadata", handleLoadedMetaData);
195
- audioElement.removeEventListener("ended", handleTimeEnded);
196
- };
197
- }
198
- }, []);
199
-
200
- const togglePlay = () => {
201
- if (audioRef.current) {
202
- const audioElement = audioRef.current;
203
- if (!playing) {
204
- audioElement.play();
205
- } else {
206
- audioElement.pause();
207
- }
208
- setPlaying(!playing);
209
- }
210
- };
211
-
212
- const onPlaybackRateChange = (rate: number) => {
213
- setSpeedValue(rate);
214
- if (audioRef.current) {
215
- audioRef.current.playbackRate = rate;
216
- }
217
- };
218
-
219
- const onSeekSeconds = (seconds: number) => {
220
- if (audioRef.current) {
221
- audioRef.current.currentTime += seconds;
222
- }
223
- };
224
-
225
- const handleSliderChange = (details: SliderValueChangeDetails) => {
226
- const newValue = details.value[0];
227
- if (audioRef.current && newValue != null && !isNaN(newValue)) {
228
- audioRef.current.currentTime = details.value[0];
229
- }
230
- };
231
-
232
- const handleVolumeSliderChange = (details: SliderValueChangeDetails) => {
233
- if (audioRef.current) {
234
- audioRef.current.volume = details.value[0] / 100;
235
- setVolumeValue(details.value[0]);
236
- }
237
- };
147
+ const {
148
+ audioRef,
149
+ onEnded,
150
+ onHandleTime,
151
+ onSeekSeconds,
152
+ playing,
153
+ togglePlay,
154
+ handleSliderChange,
155
+ handleVolumeSliderChange,
156
+ currentTime,
157
+ duration,
158
+ speedValue,
159
+ onPlaybackRateChange,
160
+ volumeValue,
161
+ } = useAudioControls();
238
162
 
239
163
  return (
240
164
  <div>
241
- {/* TODO: We should tie this up to the textual description somehow */}
242
- {/* oxlint-disable-next-line jsx-a11y/media-has-caption */}
243
- <audio ref={audioRef} src={src} title={title} preload="metadata" />
165
+ <AudioElement
166
+ src={src}
167
+ title={title}
168
+ ref={audioRef}
169
+ onEnded={onEnded}
170
+ onLoadedMetadata={onHandleTime}
171
+ onTimeUpdate={onHandleTime}
172
+ />
244
173
  <ControlsWrapper>
245
174
  <Back15SecButton
246
175
  variant="tertiary"
@@ -250,9 +179,7 @@ export const Controls = ({ src, title }: Props) => {
250
179
  >
251
180
  <Replay15Line />
252
181
  </Back15SecButton>
253
- <PlayButton aria-label={t(playing ? t("audio.pause") : t("audio.play"))} variant="primary" onClick={togglePlay}>
254
- {playing ? <PauseLine /> : <PlayFill />}
255
- </PlayButton>
182
+ <StyledPlayButton playing={playing} onClick={togglePlay} />
256
183
  <Forward15SecButton
257
184
  variant="tertiary"
258
185
  title={t("audio.controls.forward15sec")}
@@ -265,29 +192,7 @@ export const Controls = ({ src, title }: Props) => {
265
192
  <StyledText textStyle="label.medium" asChild consumeCss>
266
193
  <div>{formatTime(currentTime)}</div>
267
194
  </StyledText>
268
- <SliderRoot
269
- value={[currentTime]}
270
- defaultValue={[0]}
271
- step={1}
272
- max={duration}
273
- onValueChange={handleSliderChange}
274
- getAriaValueText={(value) =>
275
- t("audio.valueText", {
276
- start: formatTime(Math.round(value.value)),
277
- end: formatTime(Math.round(duration)),
278
- })
279
- }
280
- >
281
- <SliderLabel srOnly>{t("audio.progressBar")}</SliderLabel>
282
- <SliderControl>
283
- <SliderTrack>
284
- <SliderRange />
285
- </SliderTrack>
286
- <SliderThumb index={0}>
287
- <SliderHiddenInput />
288
- </SliderThumb>
289
- </SliderControl>
290
- </SliderRoot>
195
+ <AudioProgress currentTime={currentTime} duration={duration} onValueChange={handleSliderChange} />
291
196
  <StyledText textStyle="label.medium" asChild consumeCss>
292
197
  <div>-{formatTime(Math.round(duration - currentTime))}</div>
293
198
  </StyledText>
@@ -330,25 +235,7 @@ export const Controls = ({ src, title }: Props) => {
330
235
  </VolumeButton>
331
236
  </PopoverTrigger>
332
237
  <StyledPopoverContent>
333
- <SliderRoot
334
- orientation="vertical"
335
- value={[volumeValue]}
336
- min={0}
337
- max={100}
338
- defaultValue={[100]}
339
- step={1}
340
- onValueChange={handleVolumeSliderChange}
341
- >
342
- <SliderLabel srOnly>{t("audio.controls.adjustVolume")}</SliderLabel>
343
- <StyledSliderControl>
344
- <SliderTrack>
345
- <SliderRange />
346
- </SliderTrack>
347
- <SliderThumb index={0}>
348
- <SliderHiddenInput />
349
- </SliderThumb>
350
- </StyledSliderControl>
351
- </SliderRoot>
238
+ <VolumeSlider value={volumeValue} onValueChange={handleVolumeSliderChange} />
352
239
  </StyledPopoverContent>
353
240
  </PopoverRoot>
354
241
  </ControlsWrapper>
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2026-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 { PauseLine, PlayFill } from "@ndla/icons";
10
+ import { IconButton, type IconButtonProps } from "@ndla/primitives";
11
+ import { useTranslation } from "react-i18next";
12
+
13
+ interface Props extends IconButtonProps {
14
+ playing?: boolean;
15
+ }
16
+
17
+ export const PlayButton = ({ playing, children, ...rest }: Props) => {
18
+ const { t } = useTranslation();
19
+ return (
20
+ <IconButton aria-label={playing ? t("audio.pause") : t("audio.play")} {...rest}>
21
+ {children ?? (playing ? <PauseLine /> : <PlayFill />)}
22
+ </IconButton>
23
+ );
24
+ };
@@ -7,37 +7,24 @@
7
7
  */
8
8
 
9
9
  import { VolumeUpFill } from "@ndla/icons";
10
- import { IconButton } from "@ndla/primitives";
11
- import { useRef } from "react";
12
- import { useTranslation } from "react-i18next";
10
+ import { PlayButton } from "./PlayButton";
11
+ import { useAudioControls } from "./useAudioControls";
13
12
 
14
13
  type Props = {
15
14
  src: string;
16
15
  title: string;
17
- type?: "gloss" | "audio";
18
16
  };
19
17
 
20
- export const SpeechControl = ({ src, title, type = "audio" }: Props) => {
21
- const { t } = useTranslation();
22
- const audioRef = useRef<HTMLAudioElement>(null);
18
+ export const SpeechControl = ({ src, title }: Props) => {
19
+ const { audioRef, togglePlay } = useAudioControls();
23
20
 
24
- const togglePlay = () => {
25
- if (audioRef.current) {
26
- const audioElement = audioRef.current;
27
- if (audioElement.paused) {
28
- audioElement.play();
29
- } else {
30
- audioElement.pause();
31
- }
32
- }
33
- };
34
21
  return (
35
22
  <div data-embed-type="speech">
36
23
  {/* oxlint-disable-next-line jsx-a11y/media-has-caption */}
37
24
  <audio ref={audioRef} src={src} title={title} preload="metadata" />
38
- <IconButton variant="tertiary" aria-label={t(`${type}.play`)} title={t(`${type}.play`)} onClick={togglePlay}>
25
+ <PlayButton variant="tertiary" onClick={togglePlay}>
39
26
  <VolumeUpFill />
40
- </IconButton>
27
+ </PlayButton>
41
28
  </div>
42
29
  );
43
30
  };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) 2026-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 type { SliderValueChangeDetails } from "@ark-ui/react";
10
+ import {
11
+ SliderControl,
12
+ SliderRoot,
13
+ SliderLabel,
14
+ SliderTrack,
15
+ SliderRange,
16
+ SliderHiddenInput,
17
+ SliderThumb,
18
+ } from "@ndla/primitives";
19
+ import { styled } from "@ndla/styled-system/jsx";
20
+ import { t } from "i18next";
21
+
22
+ const StyledSliderControl = styled(SliderControl, {
23
+ base: {
24
+ height: "surface.3xsmall",
25
+ minWidth: "small",
26
+ },
27
+ });
28
+
29
+ interface Props {
30
+ value: number;
31
+ onValueChange: (value: SliderValueChangeDetails) => void;
32
+ }
33
+
34
+ export const VolumeSlider = ({ value, onValueChange }: Props) => {
35
+ return (
36
+ <SliderRoot
37
+ orientation="vertical"
38
+ value={[value]}
39
+ min={0}
40
+ max={100}
41
+ defaultValue={[100]}
42
+ step={1}
43
+ onValueChange={onValueChange}
44
+ >
45
+ <SliderLabel srOnly>{t("audio.controls.adjustVolume")}</SliderLabel>
46
+ <StyledSliderControl>
47
+ <SliderTrack>
48
+ <SliderRange />
49
+ </SliderTrack>
50
+ <SliderThumb index={0}>
51
+ <SliderHiddenInput />
52
+ </SliderThumb>
53
+ </StyledSliderControl>
54
+ </SliderRoot>
55
+ );
56
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026-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
+ export const formatTime = (seconds: number) => {
10
+ const minutes = Math.floor(seconds / 60);
11
+ const currentSeconds = seconds % 60;
12
+
13
+ const formattedSeconds = currentSeconds < 10 ? `0${currentSeconds}` : currentSeconds;
14
+ return `${minutes}:${formattedSeconds}`;
15
+ };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Copyright (c) 2026-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 type { SliderValueChangeDetails } from "@ark-ui/react";
10
+ import { useCallback, useRef, useState, type ReactEventHandler } from "react";
11
+
12
+ export const useAudioControls = () => {
13
+ const [speedValue, setSpeedValue] = useState(1);
14
+ const [volumeValue, setVolumeValue] = useState(100);
15
+ const [currentTime, setCurrentTime] = useState(0);
16
+ const [duration, setDuration] = useState(0);
17
+ const [playing, setPlaying] = useState(false);
18
+ const audioRef = useRef<HTMLAudioElement>(null);
19
+
20
+ const togglePlay = useCallback(() => {
21
+ if (!audioRef.current) return;
22
+ if (audioRef.current.paused) {
23
+ audioRef.current.play();
24
+ } else {
25
+ audioRef.current.pause();
26
+ }
27
+ setPlaying((p) => !p);
28
+ }, []);
29
+
30
+ const onPlaybackRateChange = useCallback((rate: number) => {
31
+ setSpeedValue(rate);
32
+ if (audioRef.current) {
33
+ audioRef.current.playbackRate = rate;
34
+ }
35
+ }, []);
36
+
37
+ const onSeekSeconds = useCallback((seconds: number) => {
38
+ if (audioRef.current) {
39
+ audioRef.current.currentTime += seconds;
40
+ }
41
+ }, []);
42
+
43
+ const handleSliderChange = useCallback((details: SliderValueChangeDetails) => {
44
+ const newValue = details.value[0];
45
+ if (audioRef.current && newValue != null && !isNaN(newValue)) {
46
+ audioRef.current.currentTime = details.value[0];
47
+ }
48
+ }, []);
49
+
50
+ const handleVolumeSliderChange = useCallback((details: SliderValueChangeDetails) => {
51
+ if (audioRef.current) {
52
+ audioRef.current.volume = details.value[0] / 100;
53
+ setVolumeValue(details.value[0]);
54
+ }
55
+ }, []);
56
+
57
+ const onEnded = useCallback(() => setPlaying(false), []);
58
+
59
+ const onHandleTime: ReactEventHandler<HTMLAudioElement> = useCallback((meta) => {
60
+ const target = meta.currentTarget;
61
+ setCurrentTime(Math.round(target.currentTime));
62
+ setDuration(Math.round(target.duration));
63
+ }, []);
64
+
65
+ return {
66
+ togglePlay,
67
+ onPlaybackRateChange,
68
+ onSeekSeconds,
69
+ handleVolumeSliderChange,
70
+ handleSliderChange,
71
+ onEnded,
72
+ onHandleTime,
73
+ speedValue,
74
+ volumeValue,
75
+ currentTime,
76
+ duration,
77
+ playing,
78
+ audioRef,
79
+ };
80
+ };
@@ -9,7 +9,7 @@
9
9
  import { Figure } from "@ndla/primitives";
10
10
  import { styled } from "@ndla/styled-system/jsx";
11
11
  import type { AudioMetaData } from "@ndla/types-embed";
12
- import { AudioPlayer } from "../AudioPlayer/AudioPlayer";
12
+ import { AudioPlayer, type AudioPlayerVariant } from "../AudioPlayer/AudioPlayer";
13
13
  import { EmbedByline } from "../LicenseByline/EmbedByline";
14
14
  import { licenseAttributes } from "../utils/licenseAttributes";
15
15
  import { EmbedErrorPlaceholder } from "./EmbedErrorPlaceholder";
@@ -40,9 +40,7 @@ export const AudioEmbed = ({ embed, lang }: Props) => {
40
40
 
41
41
  const { data, embedData } = embed;
42
42
 
43
- if (embedData.type === "minimal") {
44
- return <AudioPlayer speech src={data.audioFile.url} title={data.title.title} />;
45
- }
43
+ const variant = embedData.type === "podcast" ? "standard" : (embedData.type as AudioPlayerVariant);
46
44
 
47
45
  const subtitle = data.series ? { title: data.series.title.title, url: `/podkast/${data.series.id}` } : undefined;
48
46
 
@@ -55,6 +53,7 @@ export const AudioEmbed = ({ embed, lang }: Props) => {
55
53
  return (
56
54
  <StyledFigure lang={lang} data-embed-type={type} {...licenseProps}>
57
55
  <AudioPlayer
56
+ variant={variant}
58
57
  description={data.podcastMeta?.introduction ?? ""}
59
58
  img={img}
60
59
  src={data.audioFile.url}
@@ -66,11 +65,13 @@ export const AudioEmbed = ({ embed, lang }: Props) => {
66
65
  title={data.title.title}
67
66
  subtitle={subtitle}
68
67
  />
69
- <EmbedByline
70
- error={false}
71
- type={data.audioType === "standard" ? "audio" : "podcast"}
72
- copyright={embed.data.copyright}
73
- />
68
+ {variant === "standard" && (
69
+ <EmbedByline
70
+ error={false}
71
+ type={data.audioType === "standard" ? "audio" : "podcast"}
72
+ copyright={embed.data.copyright}
73
+ />
74
+ )}
74
75
  </StyledFigure>
75
76
  );
76
77
  };
@@ -162,7 +162,7 @@ export const Gloss = ({ title, glossData, audio, exampleIds, exampleLangs, varia
162
162
  </Text>
163
163
  )}
164
164
  </TextWrapper>
165
- {!!audio?.src && <SpeechControl src={audio.src} title={audio.title} type="gloss" />}
165
+ {!!audio?.src && <SpeechControl src={audio.src} title={audio.title} />}
166
166
  </Container>
167
167
  <StyledContainer>
168
168
  <Text textStyle="label.medium" asChild consumeCss>
package/src/index.ts CHANGED
@@ -57,6 +57,8 @@ export { FactBox } from "./FactBox/FactBox";
57
57
  export { ResourceBox } from "./ResourceBox/ResourceBox";
58
58
 
59
59
  export { AudioPlayer } from "./AudioPlayer/AudioPlayer";
60
+ export type { AudioPlayerVariant } from "./AudioPlayer/AudioPlayer";
61
+ export { CompactAudioPlayer } from "./AudioPlayer/CompactAudioPlayer";
60
62
 
61
63
  export { constants } from "./model";
62
64
  export { contentTypes, contentTypeMapping, resourceEmbedTypeMapping } from "./model/ContentType";