@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,4 +1,5 @@
1
1
  require("../_virtual/_rolldown/runtime.js");
2
+ const require_CompactAudioPlayer = require("./CompactAudioPlayer.js");
2
3
  const require_Controls = require("./Controls.js");
3
4
  const require_SpeechControl = require("./SpeechControl.js");
4
5
  let _ndla_primitives = require("@ndla/primitives");
@@ -93,13 +94,17 @@ const TextVersionText = (0, _ndla_styled_system_jsx.styled)("div", { base: {
93
94
  const TextVersionButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.Button, { base: { alignSelf: "flex-start" } });
94
95
  const ShowMoreButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.Button, { base: { marginInlineStart: "3xsmall" } });
95
96
  const DESCRIPTION_MAX_LENGTH = 200;
96
- const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersion }) => {
97
+ const AudioPlayer = ({ src, title, subtitle, variant = "standard", description, img, textVersion }) => {
97
98
  const { t } = (0, react_i18next.useTranslation)();
98
99
  const [showTextVersion, setShowTextVersion] = (0, react.useState)(false);
99
100
  const [showFullDescription, setShowFullDescription] = (0, react.useState)(false);
100
101
  const truncatedDescription = (0, react.useMemo)(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);
101
102
  const textDescriptionId = (0, react.useId)();
102
- if (speech) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SpeechControl.SpeechControl, {
103
+ if (variant === "minimal") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SpeechControl.SpeechControl, {
104
+ src,
105
+ title
106
+ });
107
+ if (variant === "compact") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_CompactAudioPlayer.CompactAudioPlayer, {
103
108
  src,
104
109
  title
105
110
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AudioPlayer.js","names":["Button","SpeechControl","SafeLink","Heading","Text","Controls"],"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.js","names":["Button","SpeechControl","CompactAudioPlayer","SafeLink","Heading","Text","Controls"],"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,16 @@
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
+ import type { SliderValueChangeDetails } from "@ark-ui/react";
9
+ interface Props {
10
+ currentTime: number;
11
+ duration: number;
12
+ onValueChange: (details: SliderValueChangeDetails) => void;
13
+ variant?: "simple" | "standard";
14
+ }
15
+ export declare const AudioProgress: ({ currentTime, duration, onValueChange, variant }: Props) => import("react/jsx-runtime").JSX.Element;
16
+ export {};
@@ -0,0 +1,55 @@
1
+ require("../_virtual/_rolldown/runtime.js");
2
+ const require_audioUtils = require("./audioUtils.js");
3
+ let _ndla_primitives = require("@ndla/primitives");
4
+ let _ndla_styled_system_jsx = require("@ndla/styled-system/jsx");
5
+ let react_i18next = require("react-i18next");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ //#region src/AudioPlayer/AudioProgress.tsx
8
+ const StyledSliderThumb = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.SliderThumb, { variants: { variant: {
9
+ standard: {},
10
+ simple: {
11
+ borderRadius: "0",
12
+ width: "4xsmall",
13
+ height: "4xsmall"
14
+ }
15
+ } } });
16
+ const StyledSliderTrack = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.SliderTrack, { variants: { variant: {
17
+ standard: {},
18
+ simple: { background: "unset" }
19
+ } } });
20
+ const StyledSliderControl = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.SliderControl, { variants: { variant: {
21
+ standard: {},
22
+ simple: { height: "unset" }
23
+ } } });
24
+ const AudioProgress = ({ currentTime, duration, onValueChange, variant }) => {
25
+ const { t } = (0, react_i18next.useTranslation)();
26
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_ndla_primitives.SliderRoot, {
27
+ value: [currentTime],
28
+ defaultValue: [0],
29
+ step: 1,
30
+ max: duration,
31
+ onValueChange,
32
+ getAriaValueText: (value) => t("audio.valueText", {
33
+ start: require_audioUtils.formatTime(Math.round(value.value)),
34
+ end: require_audioUtils.formatTime(Math.round(duration))
35
+ }),
36
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderLabel, {
37
+ srOnly: true,
38
+ children: t("audio.progressBar")
39
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(StyledSliderControl, {
40
+ variant,
41
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledSliderTrack, {
42
+ variant,
43
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderRange, {})
44
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledSliderThumb, {
45
+ index: 0,
46
+ variant,
47
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderHiddenInput, {})
48
+ })]
49
+ })]
50
+ });
51
+ };
52
+ //#endregion
53
+ exports.AudioProgress = AudioProgress;
54
+
55
+ //# sourceMappingURL=AudioProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioProgress.js","names":["SliderThumb","SliderTrack","SliderControl","SliderRoot","formatTime","SliderLabel","SliderRange","SliderHiddenInput"],"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,qBAAA,GAAA,wBAAA,QAA2BA,iBAAAA,aAAa,EAC5C,UAAU,EACR,SAAS;CACP,UAAU,EAAE;CACZ,QAAQ;EACN,cAAc;EACd,OAAO;EACP,QAAQ;EACT;CACF,EACF,EACF,CAAC;AAEF,MAAM,qBAAA,GAAA,wBAAA,QAA2BC,iBAAAA,aAAa,EAC5C,UAAU,EACR,SAAS;CACP,UAAU,EAAE;CACZ,QAAQ,EACN,YAAY,SACb;CACF,EACF,EACF,CAAC;AAEF,MAAM,uBAAA,GAAA,wBAAA,QAA6BC,iBAAAA,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,OAAA,GAAA,cAAA,iBAAsB;AAC9B,QACE,iBAAA,GAAA,kBAAA,MAACC,iBAAAA,YAAD;EACE,OAAO,CAAC,YAAY;EACpB,cAAc,CAAC,EAAE;EACjB,MAAM;EACN,KAAK;EACU;EACf,mBAAmB,UACjB,EAAE,mBAAmB;GACnB,OAAOC,mBAAAA,WAAW,KAAK,MAAM,MAAM,MAAM,CAAC;GAC1C,KAAKA,mBAAAA,WAAW,KAAK,MAAM,SAAS,CAAC;GACtC,CAAC;YAVN,CAaE,iBAAA,GAAA,kBAAA,KAACC,iBAAAA,aAAD;GAAa,QAAA;aAAQ,EAAE,oBAAoB;GAAe,CAAA,EAC1D,iBAAA,GAAA,kBAAA,MAAC,qBAAD;GAA8B;aAA9B,CACE,iBAAA,GAAA,kBAAA,KAAC,mBAAD;IAA4B;cAC1B,iBAAA,GAAA,kBAAA,KAACC,iBAAAA,aAAD,EAAe,CAAA;IACG,CAAA,EACpB,iBAAA,GAAA,kBAAA,KAAC,mBAAD;IAAmB,OAAO;IAAY;cACpC,iBAAA,GAAA,kBAAA,KAACC,iBAAAA,mBAAD,EAAqB,CAAA;IACH,CAAA,CACA;KACX"}
@@ -0,0 +1,13 @@
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
+ interface Props {
9
+ src: string;
10
+ title: string;
11
+ }
12
+ export declare const CompactAudioPlayer: ({ src, title }: Props) => import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,112 @@
1
+ require("../_virtual/_rolldown/runtime.js");
2
+ const require_AudioElement = require("./AudioElement.js");
3
+ const require_audioUtils = require("./audioUtils.js");
4
+ const require_AudioProgress = require("./AudioProgress.js");
5
+ const require_PlayButton = require("./PlayButton.js");
6
+ const require_useAudioControls = require("./useAudioControls.js");
7
+ const require_VolumeSlider = require("./VolumeSlider.js");
8
+ let _ndla_primitives = require("@ndla/primitives");
9
+ let _ndla_styled_system_jsx = require("@ndla/styled-system/jsx");
10
+ let react_i18next = require("react-i18next");
11
+ let _ndla_icons = require("@ndla/icons");
12
+ let react_jsx_runtime = require("react/jsx-runtime");
13
+ //#region src/AudioPlayer/CompactAudioPlayer.tsx
14
+ /**
15
+ * Copyright (c) 2026-present, NDLA.
16
+ *
17
+ * This source code is licensed under the GPLv3 license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ *
20
+ */
21
+ const AudioContainer = (0, _ndla_styled_system_jsx.styled)("div", { base: {
22
+ display: "flex",
23
+ gap: "xxsmall",
24
+ flexDirection: "column",
25
+ padding: "xsmall",
26
+ paddingBlockEnd: "0",
27
+ borderRadius: "xsmall",
28
+ boxShadow: "xsmall",
29
+ background: "surface.brand.1.subtle"
30
+ } });
31
+ const ControlsContainer = (0, _ndla_styled_system_jsx.styled)("div", { base: {
32
+ display: "flex",
33
+ gap: "xsmall",
34
+ alignItems: "center"
35
+ } });
36
+ const StyledText = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.Text, { base: {
37
+ minWidth: "4xlarge",
38
+ flexShrink: "0",
39
+ textAlign: "center"
40
+ } });
41
+ const StyledIconButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.IconButton, { base: { marginInlineStart: "auto" } });
42
+ const EllipsedText = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.Text, { base: {
43
+ overflow: "hidden",
44
+ textOverflow: "ellipsis",
45
+ whiteSpace: "nowrap"
46
+ } });
47
+ const CompactAudioPlayer = ({ src, title }) => {
48
+ const { t } = (0, react_i18next.useTranslation)();
49
+ const { audioRef, playing, togglePlay, currentTime, duration, handleSliderChange, volumeValue, handleVolumeSliderChange, onEnded, onHandleTime } = require_useAudioControls.useAudioControls();
50
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AudioContainer, { children: [
51
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AudioElement.AudioElement, {
52
+ ref: audioRef,
53
+ src,
54
+ title,
55
+ onEnded,
56
+ onLoadedMetadata: onHandleTime,
57
+ onTimeUpdate: onHandleTime
58
+ }),
59
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ControlsContainer, { children: [
60
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PlayButton.PlayButton, {
61
+ playing,
62
+ onClick: togglePlay
63
+ }),
64
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(StyledText, { children: [
65
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.Text, {
66
+ textStyle: "label.medium",
67
+ asChild: true,
68
+ consumeCss: true,
69
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: require_audioUtils.formatTime(currentTime) })
70
+ }),
71
+ "/ ",
72
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.Text, {
73
+ textStyle: "label.medium",
74
+ color: "text.subtle",
75
+ asChild: true,
76
+ consumeCss: true,
77
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: require_audioUtils.formatTime(duration) })
78
+ })
79
+ ] }),
80
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EllipsedText, {
81
+ textStyle: "title.medium",
82
+ children: title
83
+ }),
84
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_ndla_primitives.PopoverRoot, {
85
+ positioning: { placement: "top" },
86
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.PopoverTrigger, {
87
+ asChild: true,
88
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledIconButton, {
89
+ variant: "tertiary",
90
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.VolumeUpFill, {})
91
+ })
92
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_ndla_primitives.PopoverContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.PopoverTitle, {
93
+ srOnly: true,
94
+ children: t("audio.controls.adjustVolume")
95
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_VolumeSlider.VolumeSlider, {
96
+ value: volumeValue,
97
+ onValueChange: handleVolumeSliderChange
98
+ })] })]
99
+ })
100
+ ] }),
101
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AudioProgress.AudioProgress, {
102
+ currentTime,
103
+ duration,
104
+ onValueChange: handleSliderChange,
105
+ variant: "simple"
106
+ })
107
+ ] });
108
+ };
109
+ //#endregion
110
+ exports.CompactAudioPlayer = CompactAudioPlayer;
111
+
112
+ //# sourceMappingURL=CompactAudioPlayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompactAudioPlayer.js","names":["Text","IconButton","useAudioControls","AudioElement","PlayButton","formatTime","PopoverRoot","PopoverTrigger","VolumeUpFill","PopoverContent","PopoverTitle","VolumeSlider","AudioProgress"],"sources":["../../src/AudioPlayer/CompactAudioPlayer.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 { VolumeUpFill } from \"@ndla/icons\";\nimport { PopoverRoot, PopoverTrigger, IconButton, PopoverContent, Text, PopoverTitle } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { useTranslation } from \"react-i18next\";\nimport { AudioElement } from \"./AudioElement\";\nimport { AudioProgress } from \"./AudioProgress\";\nimport { formatTime } from \"./audioUtils\";\nimport { PlayButton } from \"./PlayButton\";\nimport { useAudioControls } from \"./useAudioControls\";\nimport { VolumeSlider } from \"./VolumeSlider\";\n\nconst AudioContainer = styled(\"div\", {\n base: {\n display: \"flex\",\n gap: \"xxsmall\",\n flexDirection: \"column\",\n padding: \"xsmall\",\n paddingBlockEnd: \"0\",\n borderRadius: \"xsmall\",\n boxShadow: \"xsmall\",\n background: \"surface.brand.1.subtle\",\n },\n});\n\nconst ControlsContainer = styled(\"div\", {\n base: {\n display: \"flex\",\n gap: \"xsmall\",\n alignItems: \"center\",\n },\n});\n\ninterface Props {\n src: string;\n title: string;\n}\n\nconst StyledText = styled(Text, {\n base: {\n minWidth: \"4xlarge\",\n flexShrink: \"0\",\n textAlign: \"center\",\n },\n});\n\nconst StyledIconButton = styled(IconButton, {\n base: {\n marginInlineStart: \"auto\",\n },\n});\n\nconst EllipsedText = styled(Text, {\n base: {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n});\n\nexport const CompactAudioPlayer = ({ src, title }: Props) => {\n const { t } = useTranslation();\n const {\n audioRef,\n playing,\n togglePlay,\n currentTime,\n duration,\n handleSliderChange,\n volumeValue,\n handleVolumeSliderChange,\n onEnded,\n onHandleTime,\n } = useAudioControls();\n return (\n <AudioContainer>\n <AudioElement\n ref={audioRef}\n src={src}\n title={title}\n onEnded={onEnded}\n onLoadedMetadata={onHandleTime}\n onTimeUpdate={onHandleTime}\n />\n <ControlsContainer>\n <PlayButton playing={playing} onClick={togglePlay} />\n <StyledText>\n <Text textStyle=\"label.medium\" asChild consumeCss>\n <span>{formatTime(currentTime)}</span>\n </Text>\n {\"/ \"}\n <Text textStyle=\"label.medium\" color=\"text.subtle\" asChild consumeCss>\n <span>{formatTime(duration)}</span>\n </Text>\n </StyledText>\n <EllipsedText textStyle=\"title.medium\">{title}</EllipsedText>\n <PopoverRoot positioning={{ placement: \"top\" }}>\n <PopoverTrigger asChild>\n <StyledIconButton variant=\"tertiary\">\n <VolumeUpFill />\n </StyledIconButton>\n </PopoverTrigger>\n <PopoverContent>\n <PopoverTitle srOnly>{t(\"audio.controls.adjustVolume\")}</PopoverTitle>\n <VolumeSlider value={volumeValue} onValueChange={handleVolumeSliderChange} />\n </PopoverContent>\n </PopoverRoot>\n </ControlsContainer>\n <AudioProgress\n currentTime={currentTime}\n duration={duration}\n onValueChange={handleSliderChange}\n variant=\"simple\"\n />\n </AudioContainer>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,MAAM,kBAAA,GAAA,wBAAA,QAAwB,OAAO,EACnC,MAAM;CACJ,SAAS;CACT,KAAK;CACL,eAAe;CACf,SAAS;CACT,iBAAiB;CACjB,cAAc;CACd,WAAW;CACX,YAAY;CACb,EACF,CAAC;AAEF,MAAM,qBAAA,GAAA,wBAAA,QAA2B,OAAO,EACtC,MAAM;CACJ,SAAS;CACT,KAAK;CACL,YAAY;CACb,EACF,CAAC;AAOF,MAAM,cAAA,GAAA,wBAAA,QAAoBA,iBAAAA,MAAM,EAC9B,MAAM;CACJ,UAAU;CACV,YAAY;CACZ,WAAW;CACZ,EACF,CAAC;AAEF,MAAM,oBAAA,GAAA,wBAAA,QAA0BC,iBAAAA,YAAY,EAC1C,MAAM,EACJ,mBAAmB,QACpB,EACF,CAAC;AAEF,MAAM,gBAAA,GAAA,wBAAA,QAAsBD,iBAAAA,MAAM,EAChC,MAAM;CACJ,UAAU;CACV,cAAc;CACd,YAAY;CACb,EACF,CAAC;AAEF,MAAa,sBAAsB,EAAE,KAAK,YAAmB;CAC3D,MAAM,EAAE,OAAA,GAAA,cAAA,iBAAsB;CAC9B,MAAM,EACJ,UACA,SACA,YACA,aACA,UACA,oBACA,aACA,0BACA,SACA,iBACEE,yBAAAA,kBAAkB;AACtB,QACE,iBAAA,GAAA,kBAAA,MAAC,gBAAD,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,KAACC,qBAAAA,cAAD;GACE,KAAK;GACA;GACE;GACE;GACT,kBAAkB;GAClB,cAAc;GACd,CAAA;EACF,iBAAA,GAAA,kBAAA,MAAC,mBAAD,EAAA,UAAA;GACE,iBAAA,GAAA,kBAAA,KAACC,mBAAAA,YAAD;IAAqB;IAAS,SAAS;IAAc,CAAA;GACrD,iBAAA,GAAA,kBAAA,MAAC,YAAD,EAAA,UAAA;IACE,iBAAA,GAAA,kBAAA,KAACJ,iBAAAA,MAAD;KAAM,WAAU;KAAe,SAAA;KAAQ,YAAA;eACrC,iBAAA,GAAA,kBAAA,KAAC,QAAD,EAAA,UAAOK,mBAAAA,WAAW,YAAY,EAAQ,CAAA;KACjC,CAAA;IACN;IACD,iBAAA,GAAA,kBAAA,KAACL,iBAAAA,MAAD;KAAM,WAAU;KAAe,OAAM;KAAc,SAAA;KAAQ,YAAA;eACzD,iBAAA,GAAA,kBAAA,KAAC,QAAD,EAAA,UAAOK,mBAAAA,WAAW,SAAS,EAAQ,CAAA;KAC9B,CAAA;IACI,EAAA,CAAA;GACb,iBAAA,GAAA,kBAAA,KAAC,cAAD;IAAc,WAAU;cAAgB;IAAqB,CAAA;GAC7D,iBAAA,GAAA,kBAAA,MAACC,iBAAAA,aAAD;IAAa,aAAa,EAAE,WAAW,OAAO;cAA9C,CACE,iBAAA,GAAA,kBAAA,KAACC,iBAAAA,gBAAD;KAAgB,SAAA;eACd,iBAAA,GAAA,kBAAA,KAAC,kBAAD;MAAkB,SAAQ;gBACxB,iBAAA,GAAA,kBAAA,KAACC,YAAAA,cAAD,EAAgB,CAAA;MACC,CAAA;KACJ,CAAA,EACjB,iBAAA,GAAA,kBAAA,MAACC,iBAAAA,gBAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAACC,iBAAAA,cAAD;KAAc,QAAA;eAAQ,EAAE,8BAA8B;KAAgB,CAAA,EACtE,iBAAA,GAAA,kBAAA,KAACC,qBAAAA,cAAD;KAAc,OAAO;KAAa,eAAe;KAA4B,CAAA,CAC9D,EAAA,CAAA,CACL;;GACI,EAAA,CAAA;EACpB,iBAAA,GAAA,kBAAA,KAACC,sBAAAA,eAAD;GACe;GACH;GACV,eAAe;GACf,SAAQ;GACR,CAAA;EACa,EAAA,CAAA"}
@@ -8,6 +8,7 @@
8
8
  interface Props {
9
9
  src: string;
10
10
  title: string;
11
+ variant?: "full" | "simplified";
11
12
  }
12
13
  export declare const Controls: ({ src, title }: Props) => import("react/jsx-runtime").JSX.Element;
13
14
  export {};
@@ -1,7 +1,12 @@
1
1
  require("../_virtual/_rolldown/runtime.js");
2
+ const require_AudioElement = require("./AudioElement.js");
3
+ const require_audioUtils = require("./audioUtils.js");
4
+ const require_AudioProgress = require("./AudioProgress.js");
5
+ const require_PlayButton = require("./PlayButton.js");
6
+ const require_useAudioControls = require("./useAudioControls.js");
7
+ const require_VolumeSlider = require("./VolumeSlider.js");
2
8
  let _ndla_primitives = require("@ndla/primitives");
3
9
  let _ndla_styled_system_jsx = require("@ndla/styled-system/jsx");
4
- let react = require("react");
5
10
  let react_i18next = require("react-i18next");
6
11
  let _ndla_icons = require("@ndla/icons");
7
12
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -37,7 +42,7 @@ const ControlsWrapper = (0, _ndla_styled_system_jsx.styled)("div", { base: {
37
42
  },
38
43
  mobileWideDown: { columnGap: "3xsmall" }
39
44
  } });
40
- const PlayButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.IconButton, { base: { gridArea: "play" } });
45
+ const StyledPlayButton = (0, _ndla_styled_system_jsx.styled)(require_PlayButton.PlayButton, { base: { gridArea: "play" } });
41
46
  const Forward15SecButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.IconButton, { base: { gridArea: "forwards" } });
42
47
  const Back15SecButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.IconButton, { base: { gridArea: "backwards" } });
43
48
  const ProgressWrapper = (0, _ndla_styled_system_jsx.styled)("div", { base: {
@@ -65,16 +70,7 @@ const SpeedButton = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.Button,
65
70
  "& span": { flex: "1" }
66
71
  } });
67
72
  const StyledSelectRoot = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.SelectRoot, { base: { gridArea: "speed" } });
68
- const StyledSliderControl = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.SliderControl, { base: {
69
- height: "surface.3xsmall",
70
- minWidth: "small"
71
- } });
72
73
  const StyledPopoverContent = (0, _ndla_styled_system_jsx.styled)(_ndla_primitives.PopoverContent, { base: { paddingInline: "small" } });
73
- const formatTime = (seconds) => {
74
- const minutes = Math.floor(seconds / 60);
75
- const currentSeconds = seconds % 60;
76
- return `${minutes}:${currentSeconds < 10 ? `0${currentSeconds}` : currentSeconds}`;
77
- };
78
74
  const speedValues = (0, _ark_ui_react.createListCollection)({ items: [
79
75
  "0.5",
80
76
  "0.75",
@@ -86,68 +82,14 @@ const speedValues = (0, _ark_ui_react.createListCollection)({ items: [
86
82
  ] });
87
83
  const Controls = ({ src, title }) => {
88
84
  const { t } = (0, react_i18next.useTranslation)();
89
- const [speedValue, setSpeedValue] = (0, react.useState)(1);
90
- const [volumeValue, setVolumeValue] = (0, react.useState)(100);
91
- const [currentTime, setCurrentTime] = (0, react.useState)(0);
92
- const [duration, setDuration] = (0, react.useState)(0);
93
- const [playing, setPlaying] = (0, react.useState)(false);
94
- const audioRef = (0, react.useRef)(null);
95
- (0, react.useEffect)(() => {
96
- if (audioRef.current) {
97
- const audioElement = audioRef.current;
98
- const handleTimeUpdate = () => {
99
- const { currentTime, duration } = audioElement;
100
- setCurrentTime(Math.round(currentTime));
101
- setDuration(Math.round(duration));
102
- };
103
- const handleLoadedMetaData = () => {
104
- const { currentTime, duration } = audioElement;
105
- setCurrentTime(Math.round(currentTime));
106
- setDuration(Math.round(duration));
107
- };
108
- const handleTimeEnded = () => {
109
- setPlaying(false);
110
- };
111
- audioElement.addEventListener("timeupdate", handleTimeUpdate);
112
- audioElement.addEventListener("loadedmetadata", handleLoadedMetaData);
113
- audioElement.addEventListener("ended", handleTimeEnded);
114
- return () => {
115
- audioElement.removeEventListener("timeupdate", handleTimeUpdate);
116
- audioElement.removeEventListener("loadedmetadata", handleLoadedMetaData);
117
- audioElement.removeEventListener("ended", handleTimeEnded);
118
- };
119
- }
120
- }, []);
121
- const togglePlay = () => {
122
- if (audioRef.current) {
123
- const audioElement = audioRef.current;
124
- if (!playing) audioElement.play();
125
- else audioElement.pause();
126
- setPlaying(!playing);
127
- }
128
- };
129
- const onPlaybackRateChange = (rate) => {
130
- setSpeedValue(rate);
131
- if (audioRef.current) audioRef.current.playbackRate = rate;
132
- };
133
- const onSeekSeconds = (seconds) => {
134
- if (audioRef.current) audioRef.current.currentTime += seconds;
135
- };
136
- const handleSliderChange = (details) => {
137
- const newValue = details.value[0];
138
- if (audioRef.current && newValue != null && !isNaN(newValue)) audioRef.current.currentTime = details.value[0];
139
- };
140
- const handleVolumeSliderChange = (details) => {
141
- if (audioRef.current) {
142
- audioRef.current.volume = details.value[0] / 100;
143
- setVolumeValue(details.value[0]);
144
- }
145
- };
146
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
147
- ref: audioRef,
85
+ const { audioRef, onEnded, onHandleTime, onSeekSeconds, playing, togglePlay, handleSliderChange, handleVolumeSliderChange, currentTime, duration, speedValue, onPlaybackRateChange, volumeValue } = require_useAudioControls.useAudioControls();
86
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AudioElement.AudioElement, {
148
87
  src,
149
88
  title,
150
- preload: "metadata"
89
+ ref: audioRef,
90
+ onEnded,
91
+ onLoadedMetadata: onHandleTime,
92
+ onTimeUpdate: onHandleTime
151
93
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ControlsWrapper, { children: [
152
94
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Back15SecButton, {
153
95
  variant: "tertiary",
@@ -156,11 +98,9 @@ const Controls = ({ src, title }) => {
156
98
  onClick: () => onSeekSeconds(-15),
157
99
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.Replay15Line, {})
158
100
  }),
159
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PlayButton, {
160
- "aria-label": t(playing ? t("audio.pause") : t("audio.play")),
161
- variant: "primary",
162
- onClick: togglePlay,
163
- children: playing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.PauseLine, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.PlayFill, {})
101
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledPlayButton, {
102
+ playing,
103
+ onClick: togglePlay
164
104
  }),
165
105
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Forward15SecButton, {
166
106
  variant: "tertiary",
@@ -174,31 +114,18 @@ const Controls = ({ src, title }) => {
174
114
  textStyle: "label.medium",
175
115
  asChild: true,
176
116
  consumeCss: true,
177
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: formatTime(currentTime) })
117
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: require_audioUtils.formatTime(currentTime) })
178
118
  }),
179
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_ndla_primitives.SliderRoot, {
180
- value: [currentTime],
181
- defaultValue: [0],
182
- step: 1,
183
- max: duration,
184
- onValueChange: handleSliderChange,
185
- getAriaValueText: (value) => t("audio.valueText", {
186
- start: formatTime(Math.round(value.value)),
187
- end: formatTime(Math.round(duration))
188
- }),
189
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderLabel, {
190
- srOnly: true,
191
- children: t("audio.progressBar")
192
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_ndla_primitives.SliderControl, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderTrack, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderRange, {}) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderThumb, {
193
- index: 0,
194
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderHiddenInput, {})
195
- })] })]
119
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AudioProgress.AudioProgress, {
120
+ currentTime,
121
+ duration,
122
+ onValueChange: handleSliderChange
196
123
  }),
197
124
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledText, {
198
125
  textStyle: "label.medium",
199
126
  asChild: true,
200
127
  consumeCss: true,
201
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: ["-", formatTime(Math.round(duration - currentTime))] })
128
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: ["-", require_audioUtils.formatTime(Math.round(duration - currentTime))] })
202
129
  })
203
130
  ] }),
204
131
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.FieldRoot, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(StyledSelectRoot, {
@@ -235,21 +162,9 @@ const Controls = ({ src, title }) => {
235
162
  "aria-label": t("audio.controls.adjustVolume"),
236
163
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.VolumeUpFill, {})
237
164
  })
238
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledPopoverContent, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_ndla_primitives.SliderRoot, {
239
- orientation: "vertical",
240
- value: [volumeValue],
241
- min: 0,
242
- max: 100,
243
- defaultValue: [100],
244
- step: 1,
245
- onValueChange: handleVolumeSliderChange,
246
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderLabel, {
247
- srOnly: true,
248
- children: t("audio.controls.adjustVolume")
249
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(StyledSliderControl, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderTrack, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderRange, {}) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderThumb, {
250
- index: 0,
251
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.SliderHiddenInput, {})
252
- })] })]
165
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StyledPopoverContent, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_VolumeSlider.VolumeSlider, {
166
+ value: volumeValue,
167
+ onValueChange: handleVolumeSliderChange
253
168
  }) })]
254
169
  })
255
170
  ] })] });
@@ -1 +1 @@
1
- {"version":3,"file":"Controls.js","names":["IconButton","Text","Button","SelectRoot","SliderControl","PopoverContent","Replay15Line","PauseLine","PlayFill","Forward15Line","SliderRoot","SliderLabel","SliderTrack","SliderRange","SliderThumb","SliderHiddenInput","FieldRoot","SelectLabel","SelectControl","SelectTrigger","SelectContent","SelectItem","SelectItemText","SelectItemIndicator","CheckLine","PopoverRoot","PopoverTrigger","VolumeUpFill"],"sources":["../../src/AudioPlayer/Controls.tsx"],"sourcesContent":["/**\n * Copyright (c) 2021-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, createListCollection } from \"@ark-ui/react\";\nimport { Replay15Line, Forward15Line, PlayFill, PauseLine, VolumeUpFill, CheckLine } from \"@ndla/icons\";\nimport {\n Button,\n FieldRoot,\n IconButton,\n PopoverContent,\n PopoverRoot,\n PopoverTrigger,\n SelectContent,\n SelectControl,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectLabel,\n SelectRoot,\n SelectTrigger,\n SliderControl,\n SliderHiddenInput,\n SliderLabel,\n SliderRange,\n SliderRoot,\n SliderThumb,\n SliderTrack,\n Text,\n} from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nconst ControlsWrapper = styled(\"div\", {\n base: {\n borderBlockStart: \"1px solid\",\n borderColor: \"stroke.default\",\n borderBottomRadius: \"xsmall\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"background.default\",\n gap: \"xsmall\",\n paddingBlock: \"xsmall\",\n paddingInline: \"medium\",\n tabletWideDown: {\n display: \"grid\",\n paddingBlock: \"xsmall\",\n paddingInline: \"xsmall\",\n gridTemplateColumns: \"1fr repeat(5, auto) 1fr\",\n gridTemplateAreas: `\n \"track track track track track track track\"\n \". speed backwards play forwards volume .\"\n`,\n },\n mobileWideDown: {\n columnGap: \"3xsmall\",\n },\n },\n});\n\nconst PlayButton = styled(IconButton, {\n base: {\n gridArea: \"play\",\n },\n});\n\nconst Forward15SecButton = styled(IconButton, {\n base: {\n gridArea: \"forwards\",\n },\n});\n\nconst Back15SecButton = styled(IconButton, {\n base: {\n gridArea: \"backwards\",\n },\n});\n\nconst ProgressWrapper = styled(\"div\", {\n base: {\n flex: \"1\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"xxsmall\",\n gridArea: \"track\",\n paddingBlock: \"xsmall\",\n mobileDown: {\n paddingInline: \"xsmall\",\n },\n },\n});\n\nconst StyledText = styled(Text, {\n base: {\n minWidth: \"xxlarge\",\n flexShrink: \"0\",\n textAlign: \"center\",\n },\n});\n\nconst VolumeButton = styled(IconButton, {\n base: {\n gridArea: \"volume\",\n },\n});\n\nconst SpeedButton = styled(Button, {\n base: {\n paddingBlock: \"auto\",\n paddingInline: \"auto\",\n maxWidth: \"xxlarge\",\n maxHeight: \"xxlarge\",\n minWidth: \"xxlarge\",\n minHeight: \"xxlarge\",\n \"& span\": {\n flex: \"1\",\n },\n },\n});\n\nconst StyledSelectRoot = styled(SelectRoot<string>, {\n base: {\n gridArea: \"speed\",\n },\n});\n\nconst StyledSliderControl = styled(SliderControl, {\n base: {\n height: \"surface.3xsmall\",\n minWidth: \"small\",\n },\n});\n\nconst StyledPopoverContent = styled(PopoverContent, {\n base: {\n paddingInline: \"small\",\n },\n});\n\nconst formatTime = (seconds: number) => {\n const minutes = Math.floor(seconds / 60);\n const currentSeconds = seconds % 60;\n\n const formattedSeconds = currentSeconds < 10 ? `0${currentSeconds}` : currentSeconds;\n return `${minutes}:${formattedSeconds}`;\n};\n\nconst speedValues = createListCollection({ items: [\"0.5\", \"0.75\", \"1\", \"1.25\", \"1.5\", \"1.75\", \"2\"] });\n\ninterface Props {\n src: string;\n title: string;\n}\n\nexport const Controls = ({ src, title }: Props) => {\n const { t } = useTranslation();\n const [speedValue, setSpeedValue] = useState(1);\n const [volumeValue, setVolumeValue] = useState(100);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [playing, setPlaying] = useState(false);\n const audioRef = useRef<HTMLAudioElement>(null);\n\n useEffect(() => {\n if (audioRef.current) {\n const audioElement = audioRef.current;\n const handleTimeUpdate = () => {\n const { currentTime, duration } = audioElement;\n setCurrentTime(Math.round(currentTime));\n setDuration(Math.round(duration));\n };\n\n const handleLoadedMetaData = () => {\n const { currentTime, duration } = audioElement;\n setCurrentTime(Math.round(currentTime));\n setDuration(Math.round(duration));\n };\n\n const handleTimeEnded = () => {\n setPlaying(false);\n };\n\n audioElement.addEventListener(\"timeupdate\", handleTimeUpdate);\n audioElement.addEventListener(\"loadedmetadata\", handleLoadedMetaData);\n audioElement.addEventListener(\"ended\", handleTimeEnded);\n return () => {\n audioElement.removeEventListener(\"timeupdate\", handleTimeUpdate);\n audioElement.removeEventListener(\"loadedmetadata\", handleLoadedMetaData);\n audioElement.removeEventListener(\"ended\", handleTimeEnded);\n };\n }\n }, []);\n\n const togglePlay = () => {\n if (audioRef.current) {\n const audioElement = audioRef.current;\n if (!playing) {\n audioElement.play();\n } else {\n audioElement.pause();\n }\n setPlaying(!playing);\n }\n };\n\n const onPlaybackRateChange = (rate: number) => {\n setSpeedValue(rate);\n if (audioRef.current) {\n audioRef.current.playbackRate = rate;\n }\n };\n\n const onSeekSeconds = (seconds: number) => {\n if (audioRef.current) {\n audioRef.current.currentTime += seconds;\n }\n };\n\n const handleSliderChange = (details: SliderValueChangeDetails) => {\n const newValue = details.value[0];\n if (audioRef.current && newValue != null && !isNaN(newValue)) {\n audioRef.current.currentTime = details.value[0];\n }\n };\n\n const handleVolumeSliderChange = (details: SliderValueChangeDetails) => {\n if (audioRef.current) {\n audioRef.current.volume = details.value[0] / 100;\n setVolumeValue(details.value[0]);\n }\n };\n\n return (\n <div>\n {/* TODO: We should tie this up to the textual description somehow */}\n {/* oxlint-disable-next-line jsx-a11y/media-has-caption */}\n <audio ref={audioRef} src={src} title={title} preload=\"metadata\" />\n <ControlsWrapper>\n <Back15SecButton\n variant=\"tertiary\"\n title={t(\"audio.controls.rewind15sec\")}\n aria-label={t(\"audio.controls.rewind15sec\")}\n onClick={() => onSeekSeconds(-15)}\n >\n <Replay15Line />\n </Back15SecButton>\n <PlayButton aria-label={t(playing ? t(\"audio.pause\") : t(\"audio.play\"))} variant=\"primary\" onClick={togglePlay}>\n {playing ? <PauseLine /> : <PlayFill />}\n </PlayButton>\n <Forward15SecButton\n variant=\"tertiary\"\n title={t(\"audio.controls.forward15sec\")}\n aria-label={t(\"audio.controls.forward15sec\")}\n onClick={() => onSeekSeconds(15)}\n >\n <Forward15Line />\n </Forward15SecButton>\n <ProgressWrapper>\n <StyledText textStyle=\"label.medium\" asChild consumeCss>\n <div>{formatTime(currentTime)}</div>\n </StyledText>\n <SliderRoot\n value={[currentTime]}\n defaultValue={[0]}\n step={1}\n max={duration}\n onValueChange={handleSliderChange}\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 <SliderControl>\n <SliderTrack>\n <SliderRange />\n </SliderTrack>\n <SliderThumb index={0}>\n <SliderHiddenInput />\n </SliderThumb>\n </SliderControl>\n </SliderRoot>\n <StyledText textStyle=\"label.medium\" asChild consumeCss>\n <div>-{formatTime(Math.round(duration - currentTime))}</div>\n </StyledText>\n </ProgressWrapper>\n <FieldRoot>\n <StyledSelectRoot\n collection={speedValues}\n value={[speedValue.toString()]}\n onValueChange={(details) => onPlaybackRateChange(parseFloat(details.value[0]))}\n positioning={{ placement: \"top\" }}\n >\n <SelectLabel srOnly>{t(\"audio.controls.selectSpeed\")}</SelectLabel>\n <SelectControl>\n <SelectTrigger asChild>\n <SpeedButton\n variant=\"tertiary\"\n title={t(\"audio.controls.selectSpeed\")}\n aria-label={t(\"audio.controls.selectSpeed\")}\n >\n <span>{`${speedValue}x`}</span>\n </SpeedButton>\n </SelectTrigger>\n </SelectControl>\n <SelectContent>\n {speedValues.items.map((speed) => (\n <SelectItem key={speed} item={speed}>\n <SelectItemText>{speed}x</SelectItemText>\n <SelectItemIndicator>\n <CheckLine />\n </SelectItemIndicator>\n </SelectItem>\n ))}\n </SelectContent>\n </StyledSelectRoot>\n </FieldRoot>\n <PopoverRoot positioning={{ placement: \"top\" }}>\n <PopoverTrigger asChild>\n <VolumeButton variant=\"tertiary\" aria-label={t(\"audio.controls.adjustVolume\")}>\n <VolumeUpFill />\n </VolumeButton>\n </PopoverTrigger>\n <StyledPopoverContent>\n <SliderRoot\n orientation=\"vertical\"\n value={[volumeValue]}\n min={0}\n max={100}\n defaultValue={[100]}\n step={1}\n onValueChange={handleVolumeSliderChange}\n >\n <SliderLabel srOnly>{t(\"audio.controls.adjustVolume\")}</SliderLabel>\n <StyledSliderControl>\n <SliderTrack>\n <SliderRange />\n </SliderTrack>\n <SliderThumb index={0}>\n <SliderHiddenInput />\n </SliderThumb>\n </StyledSliderControl>\n </SliderRoot>\n </StyledPopoverContent>\n </PopoverRoot>\n </ControlsWrapper>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Controls.js","names":["PlayButton","IconButton","Text","Button","SelectRoot","PopoverContent","useAudioControls","AudioElement","Replay15Line","Forward15Line","formatTime","AudioProgress","FieldRoot","SelectLabel","SelectControl","SelectTrigger","SelectContent","SelectItem","SelectItemText","SelectItemIndicator","CheckLine","PopoverRoot","PopoverTrigger","VolumeUpFill","VolumeSlider"],"sources":["../../src/AudioPlayer/Controls.tsx"],"sourcesContent":["/**\n * Copyright (c) 2021-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 { createListCollection } from \"@ark-ui/react\";\nimport { Replay15Line, Forward15Line, VolumeUpFill, CheckLine } from \"@ndla/icons\";\nimport {\n Button,\n FieldRoot,\n IconButton,\n PopoverContent,\n PopoverRoot,\n PopoverTrigger,\n SelectContent,\n SelectControl,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectLabel,\n SelectRoot,\n SelectTrigger,\n Text,\n} from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { useTranslation } from \"react-i18next\";\nimport { AudioElement } from \"./AudioElement\";\nimport { AudioProgress } from \"./AudioProgress\";\nimport { formatTime } from \"./audioUtils\";\nimport { PlayButton } from \"./PlayButton\";\nimport { useAudioControls } from \"./useAudioControls\";\nimport { VolumeSlider } from \"./VolumeSlider\";\n\nconst ControlsWrapper = styled(\"div\", {\n base: {\n borderBlockStart: \"1px solid\",\n borderColor: \"stroke.default\",\n borderBottomRadius: \"xsmall\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"background.default\",\n gap: \"xsmall\",\n paddingBlock: \"xsmall\",\n paddingInline: \"medium\",\n tabletWideDown: {\n display: \"grid\",\n paddingBlock: \"xsmall\",\n paddingInline: \"xsmall\",\n gridTemplateColumns: \"1fr repeat(5, auto) 1fr\",\n gridTemplateAreas: `\n \"track track track track track track track\"\n \". speed backwards play forwards volume .\"\n`,\n },\n mobileWideDown: {\n columnGap: \"3xsmall\",\n },\n },\n});\n\nconst StyledPlayButton = styled(PlayButton, {\n base: {\n gridArea: \"play\",\n },\n});\n\nconst Forward15SecButton = styled(IconButton, {\n base: {\n gridArea: \"forwards\",\n },\n});\n\nconst Back15SecButton = styled(IconButton, {\n base: {\n gridArea: \"backwards\",\n },\n});\n\nconst ProgressWrapper = styled(\"div\", {\n base: {\n flex: \"1\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"xxsmall\",\n gridArea: \"track\",\n paddingBlock: \"xsmall\",\n mobileDown: {\n paddingInline: \"xsmall\",\n },\n },\n});\n\nconst StyledText = styled(Text, {\n base: {\n minWidth: \"xxlarge\",\n flexShrink: \"0\",\n textAlign: \"center\",\n },\n});\n\nconst VolumeButton = styled(IconButton, {\n base: {\n gridArea: \"volume\",\n },\n});\n\nconst SpeedButton = styled(Button, {\n base: {\n paddingBlock: \"auto\",\n paddingInline: \"auto\",\n maxWidth: \"xxlarge\",\n maxHeight: \"xxlarge\",\n minWidth: \"xxlarge\",\n minHeight: \"xxlarge\",\n \"& span\": {\n flex: \"1\",\n },\n },\n});\n\nconst StyledSelectRoot = styled(SelectRoot<string>, {\n base: {\n gridArea: \"speed\",\n },\n});\n\nconst StyledPopoverContent = styled(PopoverContent, {\n base: {\n paddingInline: \"small\",\n },\n});\n\nconst speedValues = createListCollection({ items: [\"0.5\", \"0.75\", \"1\", \"1.25\", \"1.5\", \"1.75\", \"2\"] });\n\ninterface Props {\n src: string;\n title: string;\n variant?: \"full\" | \"simplified\";\n}\n\nexport const Controls = ({ src, title }: Props) => {\n const { t } = useTranslation();\n const {\n audioRef,\n onEnded,\n onHandleTime,\n onSeekSeconds,\n playing,\n togglePlay,\n handleSliderChange,\n handleVolumeSliderChange,\n currentTime,\n duration,\n speedValue,\n onPlaybackRateChange,\n volumeValue,\n } = useAudioControls();\n\n return (\n <div>\n <AudioElement\n src={src}\n title={title}\n ref={audioRef}\n onEnded={onEnded}\n onLoadedMetadata={onHandleTime}\n onTimeUpdate={onHandleTime}\n />\n <ControlsWrapper>\n <Back15SecButton\n variant=\"tertiary\"\n title={t(\"audio.controls.rewind15sec\")}\n aria-label={t(\"audio.controls.rewind15sec\")}\n onClick={() => onSeekSeconds(-15)}\n >\n <Replay15Line />\n </Back15SecButton>\n <StyledPlayButton playing={playing} onClick={togglePlay} />\n <Forward15SecButton\n variant=\"tertiary\"\n title={t(\"audio.controls.forward15sec\")}\n aria-label={t(\"audio.controls.forward15sec\")}\n onClick={() => onSeekSeconds(15)}\n >\n <Forward15Line />\n </Forward15SecButton>\n <ProgressWrapper>\n <StyledText textStyle=\"label.medium\" asChild consumeCss>\n <div>{formatTime(currentTime)}</div>\n </StyledText>\n <AudioProgress currentTime={currentTime} duration={duration} onValueChange={handleSliderChange} />\n <StyledText textStyle=\"label.medium\" asChild consumeCss>\n <div>-{formatTime(Math.round(duration - currentTime))}</div>\n </StyledText>\n </ProgressWrapper>\n <FieldRoot>\n <StyledSelectRoot\n collection={speedValues}\n value={[speedValue.toString()]}\n onValueChange={(details) => onPlaybackRateChange(parseFloat(details.value[0]))}\n positioning={{ placement: \"top\" }}\n >\n <SelectLabel srOnly>{t(\"audio.controls.selectSpeed\")}</SelectLabel>\n <SelectControl>\n <SelectTrigger asChild>\n <SpeedButton\n variant=\"tertiary\"\n title={t(\"audio.controls.selectSpeed\")}\n aria-label={t(\"audio.controls.selectSpeed\")}\n >\n <span>{`${speedValue}x`}</span>\n </SpeedButton>\n </SelectTrigger>\n </SelectControl>\n <SelectContent>\n {speedValues.items.map((speed) => (\n <SelectItem key={speed} item={speed}>\n <SelectItemText>{speed}x</SelectItemText>\n <SelectItemIndicator>\n <CheckLine />\n </SelectItemIndicator>\n </SelectItem>\n ))}\n </SelectContent>\n </StyledSelectRoot>\n </FieldRoot>\n <PopoverRoot positioning={{ placement: \"top\" }}>\n <PopoverTrigger asChild>\n <VolumeButton variant=\"tertiary\" aria-label={t(\"audio.controls.adjustVolume\")}>\n <VolumeUpFill />\n </VolumeButton>\n </PopoverTrigger>\n <StyledPopoverContent>\n <VolumeSlider value={volumeValue} onValueChange={handleVolumeSliderChange} />\n </StyledPopoverContent>\n </PopoverRoot>\n </ControlsWrapper>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
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
+ import { type IconButtonProps } from "@ndla/primitives";
9
+ interface Props extends IconButtonProps {
10
+ playing?: boolean;
11
+ }
12
+ export declare const PlayButton: ({ playing, children, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,25 @@
1
+ require("../_virtual/_rolldown/runtime.js");
2
+ let _ndla_primitives = require("@ndla/primitives");
3
+ let react_i18next = require("react-i18next");
4
+ let _ndla_icons = require("@ndla/icons");
5
+ let react_jsx_runtime = require("react/jsx-runtime");
6
+ //#region src/AudioPlayer/PlayButton.tsx
7
+ /**
8
+ * Copyright (c) 2026-present, NDLA.
9
+ *
10
+ * This source code is licensed under the GPLv3 license found in the
11
+ * LICENSE file in the root directory of this source tree.
12
+ *
13
+ */
14
+ const PlayButton = ({ playing, children, ...rest }) => {
15
+ const { t } = (0, react_i18next.useTranslation)();
16
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_primitives.IconButton, {
17
+ "aria-label": playing ? t("audio.pause") : t("audio.play"),
18
+ ...rest,
19
+ children: children ?? (playing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.PauseLine, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ndla_icons.PlayFill, {}))
20
+ });
21
+ };
22
+ //#endregion
23
+ exports.PlayButton = PlayButton;
24
+
25
+ //# sourceMappingURL=PlayButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlayButton.js","names":["IconButton","PauseLine","PlayFill"],"sources":["../../src/AudioPlayer/PlayButton.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 { PauseLine, PlayFill } from \"@ndla/icons\";\nimport { IconButton, type IconButtonProps } from \"@ndla/primitives\";\nimport { useTranslation } from \"react-i18next\";\n\ninterface Props extends IconButtonProps {\n playing?: boolean;\n}\n\nexport const PlayButton = ({ playing, children, ...rest }: Props) => {\n const { t } = useTranslation();\n return (\n <IconButton aria-label={playing ? t(\"audio.pause\") : t(\"audio.play\")} {...rest}>\n {children ?? (playing ? <PauseLine /> : <PlayFill />)}\n </IconButton>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAa,cAAc,EAAE,SAAS,UAAU,GAAG,WAAkB;CACnE,MAAM,EAAE,OAAA,GAAA,cAAA,iBAAsB;AAC9B,QACE,iBAAA,GAAA,kBAAA,KAACA,iBAAAA,YAAD;EAAY,cAAY,UAAU,EAAE,cAAc,GAAG,EAAE,aAAa;EAAE,GAAI;YACvE,aAAa,UAAU,iBAAA,GAAA,kBAAA,KAACC,YAAAA,WAAD,EAAa,CAAA,GAAG,iBAAA,GAAA,kBAAA,KAACC,YAAAA,UAAD,EAAY,CAAA;EACzC,CAAA"}