UNPKG

a11y-player

Version:

An accessible DAISY format audiobook player for React applications

871 lines (870 loc) 30 kB
import { jsxs as C, jsx as c } from "react/jsx-runtime"; import R, { useRef as j, useState as _, useEffect as b, useCallback as I, forwardRef as oe, useImperativeHandle as me } from "react"; import { useParams as ye } from "react-router-dom"; const ve = (e) => { const n = (t, a) => { const r = { ...a, parent: t.parentSmil || null }; if (a.children) { const i = a.children.reduce(n, { flattened: [...t.flattened, r], parentSmil: r.smilFile }); return { ...t, flattened: i.flattened }; } return { ...t, flattened: [...t.flattened, r] }; }; return e.reduce(n, { flattened: [], parentSmil: null }).flattened; }, le = (e) => !e || e.flat.length <= 0 ? null : e.flat[0], be = (e) => { const n = le(e); return n && n.smilFile; }, Xe = (e, n) => { const t = (a, r) => { if (a.found) return a; if (r.smilFile === n) return { ...a, found: r }; if (r.children) { const i = r.children.reduce(t, { found: null, previous: r }); if (i.found) return i; } return { found: null, previous: r }; }; return e.reduce(t, { found: null, previous: null }); }, Y = (e, n) => { const t = e.findIndex((a) => a === n) + 1; return t <= e.length - 1 ? e[t] : null; }, ee = (e, n) => { const t = e.findIndex((a) => a === n) - 1; return t >= 0 ? e[t] : null; }, ge = (e, n) => e.find((t) => t.smilFile === n) || null, we = (e, n, t) => { const a = j(new Audio()), [r, i] = _(null), [l, u] = _(null), [s, g] = _(!1), [p, d] = _(null), [m, A] = _(0), w = (r == null ? void 0 : r.smilFile) || be(n), [D, y] = _(!1), o = a.current, N = (f, S, k = 0) => { if (!f) return; const x = () => { u(k), i(f), S && !s && g(!0); }; if (f === r) { x(); return; } y(!0), fetch(`${e}/${f.smilFile}`).then((T) => T.text()).then((T) => { var M; const E = (M = new DOMParser().parseFromString(T, "application/xml").querySelector("audio")) == null ? void 0 : M.getAttribute("src"); if (!a.current || !E) return; const W = a.current; W.src = `${e}/${E}`, x(); }).catch((T) => { console.error("Failed to fetch SMIL file:", T), y(!1); }); }; b(() => { const f = le(n); if (f) { if (t) { const [S, k] = t.split(":"), x = n.flat.find((T) => T.smilFile === S); if (x) { N(x, !1, parseFloat(k)); return; } } N(f, !1, 0); } }, [n, t]); const L = I((f, S = 0) => { if (r === null) return; const k = f === "prev" ? ee(n.flat, r) : Y(n.flat, r); k ? N(k, s, S) : f === "prev" ? N(r, s, 0) : N(r, s, S); }, [Y, ee, N, n, r, s]), P = I((f) => { if (r === null || !o) return; const S = o.currentTime + f, k = S, x = S, T = S - o.duration, F = k > o.duration, V = k < 0; if (F) { L("next", T); return; } else if (V) { L("prev", x); return; } u(k); }, [r, o]), O = I(() => { if (o) { if (p === null) { d(o.playbackRate); return; } o.playbackRate !== p && (o.playbackRate = p); } }, [o, p]), v = I(() => { if (l !== null && !(r === null || !o)) { if (D && y(!1), l > o.duration) { if (Y(n.flat, r) === null) { o.currentTime = o.duration; return; } L("next", l - o.duration); return; } else if (l < 0) if (o.duration + l < 0) { if (ee(n.flat, r) === null) { o.currentTime = 0; return; } L("prev", o.duration + l); return; } else { o.currentTime = o.duration + l, u(null); return; } o.currentTime = l, O(), u(null); } }, [o, l, y]); return b(() => { l === null || D || v(); }, [l, D]), b(() => { O(); }, [o, p]), b(() => { r === null || !o || (s && o.paused && o.play(), !s && !o.paused && o.pause()); }, [o, r, s]), b(() => { if (r === null || !a.current) return; const f = a.current, S = () => L("next", 0), k = () => A(f.currentTime || 0); return f.addEventListener("loadedmetadata", v), f.addEventListener("ended", S), f.addEventListener("timeupdate", k), () => { f.removeEventListener("loadedmetadata", v), f.removeEventListener("ended", S), f.removeEventListener("timeupdate", k); }; }, [r, n]), { audioRef: a, setAudioFor: N, currentSection: r, lastKnownBookmark: `${w}:${Math.floor(m)}`, isPlaying: s, togglePlayPause: () => g(!s), currentTime: m, moveHeadAcrossBy: P, moveToPrevNextSection: L, playbackRate: p || 1, setPlaybackRate: d }; }, Pe = { audioPlayer: "Audio Player", previousSection: "Previous Section", nextSection: "Next Section", play: "Play", pause: "Pause", backward30Seconds: "Backward 30 Seconds", forward30Seconds: "Forward 30 Seconds", speed: "Speed", decreasePlaybackRate: "Decrease playback rate", increasePlaybackRate: "Increase playback rate", toggleSectionsView: "Toggle sections view", shareLink: "Share link to current position", linkCopied: "Link copied!", failedToCopy: "Failed to copy", tableOfContents: "Table of Contents", noTitle: "No title", unknownAuthor: "Unknown author", defaultBookTitle: "Daisy player" }, Se = { audioPlayer: "Lecteur Audio", previousSection: "Section Précédente", nextSection: "Section Suivante", play: "Lecture", pause: "Pause", backward30Seconds: "Reculer de 30 Secondes", forward30Seconds: "Avancer de 30 Secondes", speed: "Vitesse", decreasePlaybackRate: "Diminuer la vitesse de lecture", increasePlaybackRate: "Augmenter la vitesse de lecture", toggleSectionsView: "Afficher/Masquer les sections", shareLink: "Partager un lien vers la position actuelle", linkCopied: "Lien copié !", failedToCopy: "Échec de la copie", tableOfContents: "Table des matières", noTitle: "Sans titre", unknownAuthor: "Auteur inconnu", defaultBookTitle: "Lecteur Daisy" }, ke = { audioPlayer: "Audio-Player", previousSection: "Vorheriger Abschnitt", nextSection: "Nächster Abschnitt", play: "Abspielen", pause: "Pause", backward30Seconds: "30 Sekunden zurück", forward30Seconds: "30 Sekunden vorwärts", speed: "Geschwindigkeit", decreasePlaybackRate: "Wiedergabegeschwindigkeit verringern", increasePlaybackRate: "Wiedergabegeschwindigkeit erhöhen", toggleSectionsView: "Abschnittsansicht umschalten", shareLink: "Link zur aktuellen Position teilen", linkCopied: "Link kopiert!", failedToCopy: "Kopieren fehlgeschlagen", tableOfContents: "Inhaltsverzeichnis", noTitle: "Kein Titel", unknownAuthor: "Unbekannter Autor", defaultBookTitle: "Daisy-Player" }, Ce = { audioPlayer: "Lettore Audio", previousSection: "Sezione Precedente", nextSection: "Sezione Successiva", play: "Riproduci", pause: "Pausa", backward30Seconds: "Indietro di 30 Secondi", forward30Seconds: "Avanti di 30 Secondi", speed: "Velocità", decreasePlaybackRate: "Diminuisci velocità di riproduzione", increasePlaybackRate: "Aumenta velocità di riproduzione", toggleSectionsView: "Attiva/disattiva vista sezioni", shareLink: "Condividi link alla posizione attuale", linkCopied: "Link copiato!", failedToCopy: "Copia fallita", tableOfContents: "Indice", noTitle: "Nessun titolo", unknownAuthor: "Autore sconosciuto", defaultBookTitle: "Lettore Daisy" }, _e = { audioPlayer: "Reproductor de Audio", previousSection: "Sección Anterior", nextSection: "Sección Siguiente", play: "Reproducir", pause: "Pausar", backward30Seconds: "Retroceder 30 Segundos", forward30Seconds: "Avanzar 30 Segundos", speed: "Velocidad", decreasePlaybackRate: "Disminuir velocidad de reproducción", increasePlaybackRate: "Aumentar velocidad de reproducción", toggleSectionsView: "Alternar vista de secciones", shareLink: "Compartir enlace a la posición actual", linkCopied: "¡Enlace copiado!", failedToCopy: "Error al copiar", tableOfContents: "Tabla de contenidos", noTitle: "Sin título", unknownAuthor: "Autor desconocido", defaultBookTitle: "Reproductor Daisy" }, U = { en: Pe, fr: Se, de: ke, it: Ce, es: _e }, Ae = (e) => { const n = e.toLowerCase().substring(0, 2); return U[n] ? U[n] : U.en; }, J = (e) => { const n = Ae(e); return (t) => n[t] || U.en[t]; }, xe = ({ sectionsHolder: e, onSectionClick: n, currentSection: t, toggleDisplay: a, isDisplayed: r = !1, language: i = "en" }) => { const l = J(i), [u, s] = _(null), g = (t == null ? void 0 : t.smilFile) || null; b(() => { if (!r || u === t) return; s(t); const m = document.getElementsByClassName("Sections__Button--selected")[0]; m && (m.focus(), setTimeout(() => m.scrollIntoView({ behavior: "smooth", block: "center" }), 100)); }, [t, r]); const p = (d, m, A = !1) => /* @__PURE__ */ c( "ul", { className: `Sections__List Sections__List--level${m}`, "aria-hidden": !A, hidden: !A, children: d.map((w) => /* @__PURE__ */ C("li", { children: [ /* @__PURE__ */ c( "button", { className: `Sections__Button${g === w.smilFile ? " Sections__Button--selected" : ""}`, onClick: () => n( ge(e.flat, w.smilFile), !0, 0 ), children: w.title } ), w.children && p(w.children, m + 1, A) || null ] }, w.smilFile)) } ); return /* @__PURE__ */ C( "div", { className: `Sections__Container Sections__Container--${r ? "visible" : "hidden"}`, "aria-hidden": !r, hidden: !r, children: [ /* @__PURE__ */ c( "div", { className: "Sections__BackArrow", onClick: a, role: "button", "aria-label": "Close sections view", tabIndex: r ? 0 : void 0, children: "←" } ), /* @__PURE__ */ c("h2", { children: l("tableOfContents") }), p(e.tree, 0, r) ] } ); }, Ne = (e) => { const t = new DOMParser().parseFromString(e, "text/html"), a = Array.from(t.querySelectorAll("h1, h2, h3")), r = [], i = []; return a.forEach((l) => { var d, m; const u = parseInt(l.tagName[1]), s = ((m = (d = l.querySelector("a")) == null ? void 0 : d.getAttribute("href")) == null ? void 0 : m.split("#")[0]) ?? "", p = { title: l.textContent ?? "Unknown Title", level: u, smilFile: s }; for (; r.length && r[r.length - 1].level >= u; ) r.pop(); if (r.length) { const A = r[r.length - 1]; A.children = A.children ?? [], A.children.push(p); } else i.push(p); r.push(p); }), { tree: i, flat: ve(i) }; }, Te = (e) => { var i, l; const t = new DOMParser().parseFromString(e, "text/html"), a = ((i = t.querySelector('meta[name="dc:title"]')) == null ? void 0 : i.getAttribute("content")) ?? "Unknown Title", r = ((l = t.querySelector('meta[name="dc:creator"]')) == null ? void 0 : l.getAttribute("content")) ?? "Unknown Author"; return { title: a, author: r }; }, Fe = (e) => { const [n, t] = _({ tree: [], flat: [] }), [a, r] = _(null); return b(() => { fetch(`${e}/ncc.html`).then((i) => i.text()).then((i) => (r(Te(i)), i)).then((i) => { t(Ne(i)); }).catch((i) => console.error("Failed to fetch book sections:", i)); }, [e]), { sectionsHolder: n, bookInfo: a }; }; var ce = { color: void 0, size: void 0, className: void 0, style: void 0, attr: void 0 }, re = R.createContext && /* @__PURE__ */ R.createContext(ce), Le = ["attr", "size", "title"]; function Oe(e, n) { if (e == null) return {}; var t = Be(e, n), a, r; if (Object.getOwnPropertySymbols) { var i = Object.getOwnPropertySymbols(e); for (r = 0; r < i.length; r++) a = i[r], !(n.indexOf(a) >= 0) && Object.prototype.propertyIsEnumerable.call(e, a) && (t[a] = e[a]); } return t; } function Be(e, n) { if (e == null) return {}; var t = {}; for (var a in e) if (Object.prototype.hasOwnProperty.call(e, a)) { if (n.indexOf(a) >= 0) continue; t[a] = e[a]; } return t; } function H() { return H = Object.assign ? Object.assign.bind() : function(e) { for (var n = 1; n < arguments.length; n++) { var t = arguments[n]; for (var a in t) Object.prototype.hasOwnProperty.call(t, a) && (e[a] = t[a]); } return e; }, H.apply(this, arguments); } function ae(e, n) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var a = Object.getOwnPropertySymbols(e); n && (a = a.filter(function(r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, a); } return t; } function Z(e) { for (var n = 1; n < arguments.length; n++) { var t = arguments[n] != null ? arguments[n] : {}; n % 2 ? ae(Object(t), !0).forEach(function(a) { Ve(e, a, t[a]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ae(Object(t)).forEach(function(a) { Object.defineProperty(e, a, Object.getOwnPropertyDescriptor(t, a)); }); } return e; } function Ve(e, n, t) { return n = De(n), n in e ? Object.defineProperty(e, n, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[n] = t, e; } function De(e) { var n = Re(e, "string"); return typeof n == "symbol" ? n : n + ""; } function Re(e, n) { if (typeof e != "object" || !e) return e; var t = e[Symbol.toPrimitive]; if (t !== void 0) { var a = t.call(e, n); if (typeof a != "object") return a; throw new TypeError("@@toPrimitive must return a primitive value."); } return (n === "string" ? String : Number)(e); } function se(e) { return e && e.map((n, t) => /* @__PURE__ */ R.createElement(n.tag, Z({ key: t }, n.attr), se(n.child))); } function B(e) { return (n) => /* @__PURE__ */ R.createElement(ze, H({ attr: Z({}, e.attr) }, n), se(e.child)); } function ze(e) { var n = (t) => { var { attr: a, size: r, title: i } = e, l = Oe(e, Le), u = r || t.size || "1em", s; return t.className && (s = t.className), e.className && (s = (s ? s + " " : "") + e.className), /* @__PURE__ */ R.createElement("svg", H({ stroke: "currentColor", fill: "currentColor", strokeWidth: "0" }, t.attr, a, l, { className: s, style: Z(Z({ color: e.color || t.color }, t.style), e.style), height: u, width: u, xmlns: "http://www.w3.org/2000/svg" }), i && /* @__PURE__ */ R.createElement("title", null, i), e.children); }; return re !== void 0 ? /* @__PURE__ */ R.createElement(re.Consumer, null, (t) => n(t)) : n(ce); } function je(e) { return B({ attr: { viewBox: "0 0 512 512" }, child: [{ tag: "path", attr: { d: "M80 368H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm0-320H16A16 16 0 0 0 0 64v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16V64a16 16 0 0 0-16-16zm0 160H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm416 176H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z" }, child: [] }] })(e); } function Ie(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M416 208H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h384c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z" }, child: [] }] })(e); } function Ee(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M144 479H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zm304-48V79c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h96c26.5 0 48-21.5 48-48z" }, child: [] }] })(e); } function Me(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z" }, child: [] }] })(e); } function $e(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z" }, child: [] }] })(e); } function Ke(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M352 320c-22.608 0-43.387 7.819-59.79 20.895l-102.486-64.054a96.551 96.551 0 0 0 0-41.683l102.486-64.054C308.613 184.181 329.392 192 352 192c53.019 0 96-42.981 96-96S405.019 0 352 0s-96 42.981-96 96c0 7.158.79 14.13 2.276 20.841L155.79 180.895C139.387 167.819 118.608 160 96 160c-53.019 0-96 42.981-96 96s42.981 96 96 96c22.608 0 43.387-7.819 59.79-20.895l102.486 64.054A96.301 96.301 0 0 0 256 416c0 53.019 42.981 96 96 96s96-42.981 96-96-42.981-96-96-96z" }, child: [] }] })(e); } function We(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M64 468V44c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12v176.4l195.5-181C352.1 22.3 384 36.6 384 64v384c0 27.4-31.9 41.7-52.5 24.6L136 292.7V468c0 6.6-5.4 12-12 12H76c-6.6 0-12-5.4-12-12z" }, child: [] }] })(e); } function qe(e) { return B({ attr: { viewBox: "0 0 448 512" }, child: [{ tag: "path", attr: { d: "M384 44v424c0 6.6-5.4 12-12 12h-48c-6.6 0-12-5.4-12-12V291.6l-195.5 181C95.9 489.7 64 475.4 64 448V64c0-27.4 31.9-41.7 52.5-24.6L312 219.3V44c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12z" }, child: [] }] })(e); } const Ge = ({ appUrl: e, pathPrefix: n, path: t, language: a = "en" }) => { const r = J(a), [i, l] = _(null), [u, s] = _(null), g = async () => { try { const d = `${e}/${n}/${t}`; await navigator.clipboard.writeText(d), l(!0), s(t), setTimeout(() => { l(null); }, 3e3); } catch (d) { l(!1), console.error("Failed to copy text: ", d), setTimeout(() => { l(null); }, 3e3); } }; return b(() => { u !== null && u !== t && (s(null), l(null)); }, [t]), /* @__PURE__ */ c( "button", { onClick: g, disabled: t === null, className: `ShareButton ${i === !0 ? "ShareButton--success" : i === !1 ? "ShareButton--error" : ""}`, "aria-label": r("shareLink"), title: r("shareLink"), children: /* @__PURE__ */ c("span", { children: i === !0 ? r("linkCopied") : i === !1 ? r("failedToCopy") : /* @__PURE__ */ c(Ke, {}) }) } ); }; function ie(e) { return B({ attr: { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, child: [{ tag: "path", attr: { d: "M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747" }, child: [] }, { tag: "path", attr: { d: "M20 4v5h-5" }, child: [] }] })(e); } const Ue = ({ audioRef: e, title: n, playing: t, moveHeadAcrossBy: a, moveToPrevNextSection: r, currentTime: i, togglePlayPause: l, playbackRate: u, setPlaybackRate: s, isDisplayed: g = !0, language: p = "en" }) => { const d = J(p), m = j(null), [A, w] = _(0); b(() => { const y = e.current; y && w(i / y.duration * 100 || 0); }, [i, e]); const D = I((y) => { if (g) switch (y.key) { case "k": case " ": y.preventDefault(), l(); break; case "j": case "ArrowLeft": y.preventDefault(), a(-10); break; case "l": case "ArrowRight": y.preventDefault(), a(10); break; case "ArrowUp": y.preventDefault(), s(u + 0.1); break; case "ArrowDown": y.preventDefault(), s(u - 0.1); break; } }, [g, s, a, l, u]); return b(() => { if (!g) return; const o = document.getElementsByClassName("AudioPlayer__Control--play-pause")[0]; o && o.focus(); }, [g]), /* @__PURE__ */ C( "div", { className: "AudioPlayer", role: "region", "aria-label": d("audioPlayer"), ref: m, tabIndex: 0, onKeyDown: D, children: [ /* @__PURE__ */ c("audio", { ref: e, "aria-label": n, preload: "metadata", className: "AudioPlayer__Audio" }), /* @__PURE__ */ c("h2", { className: "AudioPlayer__Title", children: n }), /* @__PURE__ */ C("div", { className: "AudioPlayer__Controls", children: [ /* @__PURE__ */ C("div", { className: "AudioPlayer__ControlColumns", children: [ /* @__PURE__ */ C("div", { className: "AudioPlayer__ControlsColumn", children: [ /* @__PURE__ */ c( "button", { className: "AudioPlayer__Control", onClick: () => r("prev"), "aria-label": d("previousSection"), children: /* @__PURE__ */ c(We, {}) } ), /* @__PURE__ */ c( "button", { className: "AudioPlayer__Control AudioPlayer__Control--mirrored", onClick: () => a(-30), "aria-label": d("backward30Seconds"), children: /* @__PURE__ */ c(ie, {}) } ) ] }), /* @__PURE__ */ c("div", { className: "AudioPlayer__ControlsColumn AudioPlayer__ControlsColumn--play", children: /* @__PURE__ */ c( "button", { className: `AudioPlayer__Control AudioPlayer__Control--play-pause AudioPlayer__Control--${t ? "playing" : "paused"}`, onClick: l, "aria-label": d(t ? "pause" : "play"), children: t ? /* @__PURE__ */ c(Ee, {}) : /* @__PURE__ */ c(Me, {}) } ) }), /* @__PURE__ */ C("div", { className: "AudioPlayer__ControlsColumn AudioPlayer__ControlsColumn--reverse", children: [ /* @__PURE__ */ c( "button", { className: "AudioPlayer__Control", onClick: () => a(30), "aria-label": d("forward30Seconds"), children: /* @__PURE__ */ c(ie, {}) } ), /* @__PURE__ */ c( "button", { className: "AudioPlayer__Control", onClick: () => r("next"), "aria-label": d("nextSection"), children: /* @__PURE__ */ c(qe, {}) } ) ] }) ] }), /* @__PURE__ */ C( "div", { className: "AudioPlayer__ControlsRow AudioPlayer__ControlsRow--speed", role: "group", "aria-label": d("speed"), children: [ /* @__PURE__ */ c( "button", { className: "AudioPlayer__Control", onClick: () => s(u - 0.25), "aria-label": `${d("decreasePlaybackRate")} ${u - 0.25}`, children: /* @__PURE__ */ c(Ie, {}) } ), /* @__PURE__ */ C("div", { className: "AudioPlayer__SpeedText", "aria-live": "polite", children: [ /* @__PURE__ */ c("span", { children: d("speed") }), /* @__PURE__ */ C("strong", { children: [ u, " x" ] }) ] }), /* @__PURE__ */ c( "button", { className: "AudioPlayer__Control", onClick: () => s(u + 0.25), "aria-label": `${d("increasePlaybackRate")} ${u + 0.25}`, children: /* @__PURE__ */ c($e, {}) } ) ] } ) ] }), /* @__PURE__ */ C("div", { className: "AudioPlayer__ProgressContainer", children: [ /* @__PURE__ */ C( "progress", { className: "AudioPlayer__Progress", value: A, max: "100", "aria-hidden": "true", children: [ A, "%" ] } ), /* @__PURE__ */ C("span", { className: "AudioPlayer__Time", "aria-live": "off", children: [ Math.trunc(i), " / ", Math.round(e.current.duration), " s" ] }) ] }) ] } ); }, ue = oe(({ dirUrl: e, appUrl: n, pathPrefix: t, initialBookmark: a, className: r = "", language: i = "en", onTimeUpdate: l, timeUpdateInterval: u = 1e3, onBookmarkChange: s, onPlaybackStateChange: g, onPlay: p, onPause: d, onSeek: m }, A) => { const w = J(i), D = j(null), { sectionsHolder: y, bookInfo: o } = Fe(e), { audioRef: N, setAudioFor: L, lastKnownBookmark: P, currentSection: O, isPlaying: v, togglePlayPause: f, moveHeadAcrossBy: S, moveToPrevNextSection: k, playbackRate: x, setPlaybackRate: T, currentTime: F } = we(e, y, a), [V, E] = _("playerView"), [W, M] = _(!1), [te, de] = _(""), $ = j(null), z = j(l), ne = j(0); b(() => { z.current = l; }, [l]), b(() => { if (!z.current) return; const h = () => { z.current && z.current(F, P, v); }; return $.current && clearInterval($.current), $.current = setInterval(h, u), () => { $.current && clearInterval($.current); }; }, [u]), b(() => { if (!z.current) return; const h = Date.now(); h - ne.current >= Math.min(u, 1e3) && (z.current(F, P, v), ne.current = h); }, [F, P, v, u]), b(() => { P !== te && (de(P), s && P && s(P)); }, [P, te, s]), b(() => { if (!g || !N.current || !O) return; const h = N.current; g({ currentTime: F, duration: h.duration || 0, isPlaying: v, currentBookmark: P, playbackRate: x }); }, [g, F, v, P, x, O]), b(() => { v && p ? p() : !v && d && d(); }, [v, p, d]), me(A, () => ({ getCurrentTime: () => F, getDuration: () => { var h; return ((h = N.current) == null ? void 0 : h.duration) || 0; }, isPlaying: () => v, getCurrentBookmark: () => P, getPlaybackRate: () => x, togglePlayPause: () => f(), seek: (h) => { const [X, q] = h.split(":"), G = y.flat.find((pe) => pe.smilFile === X); G && (L(G, v, parseFloat(q) || 0), m && m(h)); } }), [F, v, P, x, f, y, L, m]), b(() => { V === "sectionsView" ? v && (M(!0), f()) : V === "playerView" && W && !v && (f(), M(!1)); }, [V, v, f, W]); const fe = (h, X, q) => { if (L(h, X, q), E("playerView"), m && h) { const G = `${h.smilFile}:${Math.floor(q)}`; m(G); } }, K = () => { E((h) => h === "sectionsView" ? "playerView" : "sectionsView"); }, Q = V !== "playerView", he = I((h) => { switch (h.key) { case "i": h.preventDefault(), K(); break; } if (Q) switch (h.key) { case "Escape": h.preventDefault(), K(); break; } }, [K, Q]); return /* @__PURE__ */ C( "div", { className: `DaisyPlayer__Container ${r}`, ref: D, tabIndex: 0, onKeyDown: he, children: [ /* @__PURE__ */ C("div", { className: "DaisyPlayer__OtherButtons", children: [ /* @__PURE__ */ c( Ge, { appUrl: n, pathPrefix: t, path: P, language: i } ), /* @__PURE__ */ c( "button", { className: "DaisyPlayer__ToggleSectionsViewButton", onClick: K, "aria-label": w("toggleSectionsView"), title: w("toggleSectionsView"), children: /* @__PURE__ */ c(je, {}) } ) ] }), /* @__PURE__ */ c("h1", { children: (o == null ? void 0 : o.title) || w("defaultBookTitle") }), /* @__PURE__ */ c("h3", { children: (o == null ? void 0 : o.author) || w("unknownAuthor") }), /* @__PURE__ */ c("div", { className: "DaisyPlayer__PlayerContainer", children: /* @__PURE__ */ c( Ue, { setPlaybackRate: T, playbackRate: x, moveToPrevNextSection: k, audioRef: N, title: (O == null ? void 0 : O.title) || w("noTitle"), playing: v, moveHeadAcrossBy: S, currentTime: F, togglePlayPause: f, isDisplayed: !Q, language: i } ) }), /* @__PURE__ */ c( xe, { isDisplayed: V === "sectionsView", toggleDisplay: K, sectionsHolder: y, onSectionClick: fe, currentSection: O, language: i } ) ] } ); }); ue.displayName = "DaisyPlayer"; const He = oe(({ pathPrefix: e, bookmarkParam: n = "bookmark", language: t = "en", className: a = "", ...r }, i) => { const u = ye()[n]; return /* @__PURE__ */ c( ue, { ref: i, initialBookmark: u, pathPrefix: e, language: t, className: a, ...r } ); }); He.displayName = "DaisyPlayerWithRouter"; export { ue as DaisyPlayer, He as DaisyPlayerWithRouter, J as createTranslator, ge as flatFindBySmil, Y as flatGetNext, ee as flatGetPrev, ve as flatten, le as getFirst, be as getFirstSmil, Ae as getTranslations, Xe as treeFindBySmil };