a11y-player
Version:
An accessible DAISY format audiobook player for React applications
871 lines (870 loc) • 30 kB
JavaScript
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
};