🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@audiodn/components

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@audiodn/components - npm Package Compare versions

Comparing version
0.3.1
to
0.4.0
+34
dist/lib/media-devices.d.ts
/**
* Shared audio input/output device helpers for the Player and Recorder.
*
* The selected microphone (input) and speaker (output) are page-wide
* preferences: picking one in any player or recorder should apply to every
* other instance and persist for the session. This mirrors how volume is
* coordinated in the player — a `sessionStorage`-backed value plus a document
* event that other instances listen to.
*
* Output routing relies on `HTMLMediaElement.setSinkId`, which is not available
* in every browser (notably Safari). When it is missing we simply skip the
* output UI and never claim to change the output device.
*/
export interface AudioDevice {
deviceId: string;
label: string;
}
/** Document events used to sync device selection across instances. */
export declare const INPUT_CHANGE_EVENT = "adn-inputchange";
export declare const OUTPUT_CHANGE_EVENT = "adn-outputchange";
/** True when the browser can route audio to a chosen output device. */
export declare function supportsSinkId(): boolean;
export declare function enumerateAudioInputs(): Promise<AudioDevice[]>;
export declare function enumerateAudioOutputs(): Promise<AudioDevice[]>;
export declare function getPreferredAudioInputId(): string;
export declare function setPreferredAudioInputId(deviceId: string): void;
export declare function getPreferredAudioOutputId(): string;
export declare function setPreferredAudioOutputId(deviceId: string): void;
/**
* Route a media element to the preferred output device. No-op when the API is
* unsupported or no device is selected. Failures (e.g. the device was
* unplugged) are swallowed so playback stays on the current sink.
*/
export declare function applySinkId(el: HTMLMediaElement | null | undefined, deviceId: string): Promise<void>;
import { w as d, n as E, r as U, i as b, a as I, b as y, t as R } from "./lit-DpNjQO9d.js";
import { t as V } from "./i18n-BI0dP23M.js";
function D(t) {
if (!t || typeof t != "object") return !1;
const e = t.url;
return !(typeof e != "string" || !e.trim() || /\/(null|undefined)(?:\/|$)/i.test(e));
}
function A(t) {
if (!t || typeof t != "object") return;
const e = t, n = {};
let o = !1;
for (const r of ["icon", "small", "regular", "large"]) {
const i = e[r];
D(i) && (n[r] = {
height: Number(i.height) || 0,
type: String(i.type || ""),
url: i.url.trim(),
width: Number(i.width) || 0
}, o = !0);
}
return o ? n : void 0;
}
const ct = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/></svg>`, lt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>`, pt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 5V2L7 7l5 5V8a5 5 0 1 1-4.9 6h-2.05A7 7 0 1 0 12 5z"/></svg>`, dt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l9.5 16.5H2.5L12 3z"/><path d="M12 10v4"/><path d="M12 17.5v.01"/></svg>`;
d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M475.8 175.3c3 8 .4 16.8-5.9 22.5l-39.6 36a176.6 176.6 0 0 1 0 46.5l39.6 36a20.7 20.7 0 0 1 5.9 22.5c-4 10.9-9 21.3-14.5 31.3l-4.3 7.4c-6 10.1-12.8 19.6-20.2 28.6a20.8 20.8 0 0 1-22.5 6.2l-51-16.2a176.3 176.3 0 0 1-40.3 23.2l-11.4 52.2a20.7 20.7 0 0 1-16.7 16.3 237 237 0 0 1-77.9 0c-8.4-1.4-14.8-8-16.6-16.3l-11.5-52.2a179 179 0 0 1-40.3-23.2l-51 16.3a21 21 0 0 1-22.4-6.2c-7.4-9-14.2-18.5-20.2-28.6l-4.3-7.4a234 234 0 0 1-14.5-31.3c-3-8-.4-16.9 5.9-22.5l39.6-36a179 179 0 0 1 0-46.6l-39.6-36a20.7 20.7 0 0 1-5.9-22.5c4-10.9 9-21.3 14.5-31.3l4.3-7.5c6-10 12.8-19.5 20.2-28.5a20.8 20.8 0 0 1 22.5-6.2l51 16.2A176.3 176.3 0 0 1 189 94.8l11.4-52.2a20.7 20.7 0 0 1 16.7-16.3 227.5 227.5 0 0 1 77.9-.1c8.4 1.4 14.8 8 16.6 16.3l11.5 52.2a179 179 0 0 1 40.3 23.2l51-16.2c8-2.5 17-.3 22.4 6.2 7.5 9 14.2 18.5 20.3 28.6l4.3 7.4c5.6 10 10.4 20.4 14.5 31.3l-.1.1ZM256 330a73 73 0 1 0 0-146 73 73 0 0 0 0 146Z"/></svg>`;
const ut = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M267.6 64.4A27.8 27.8 0 0 1 284 89.7v332.6a27.8 27.8 0 0 1-46.1 20.7L121 339H62.4A55.5 55.5 0 0 1 7 283.7v-55.4a55.5 55.5 0 0 1 55.4-55.5h58.7L237.9 69c8.1-7.3 19.8-9 29.7-4.6Zm107.8 114.7 47.6 47.6 47.6-47.6a20.8 20.8 0 0 1 29.3 29.3L452.3 256l47.6 47.6a20.8 20.8 0 0 1-29.3 29.3L423 285.3 375.4 333a20.8 20.8 0 0 1-29.3-29.3l47.6-47.6-47.6-47.6a20.8 20.8 0 0 1 29.3-29.3Z"/></svg>`, mt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M279.8 64.4A27.8 27.8 0 0 1 296 89.7v332.6a28 28 0 0 1-16.2 25.3 27.3 27.3 0 0 1-29.6-4.6l-116-104H76c-30.3 0-55-24.8-55-55.4v-55.4a55.3 55.3 0 0 1 55-55.5h58.3L250.2 69c8-7.3 19.7-9 29.6-4.6Zm149 62.3a166 166 0 0 1 0 257.6 20.8 20.8 0 0 1-26.1-32.2 124.4 124.4 0 0 0 0-193.2 20.8 20.8 0 0 1 26.1-32.2Zm-52.6 65a82.7 82.7 0 0 1 0 128.6 21 21 0 0 1-29.5-3c-7.3-8.9-6-22 3-29.2a41.2 41.2 0 0 0 0-64.3 20.7 20.7 0 0 1-3-29.2 21.1 21.1 0 0 1 29.5-3v.1Z"/></svg>`, ft = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M280.8 64.4A27.8 27.8 0 0 1 297 89.7v332.6a28 28 0 0 1-16.2 25.3 27.3 27.3 0 0 1-29.6-4.6l-116-104H77c-30.3 0-55-24.8-55-55.4v-55.4a55.3 55.3 0 0 1 55-55.5h58.3L251.2 69c8-7.3 19.7-9 29.6-4.6Zm96.4 127.3a82.7 82.7 0 0 1 0 128.6 21 21 0 0 1-29.5-3c-7.3-8.9-6-22 3-29.2a41.2 41.2 0 0 0 0-64.3 20.7 20.7 0 0 1-3-29.2 21.1 21.1 0 0 1 29.5-3v.1Z"/></svg>`, ht = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M96 480a32 32 0 1 1 0-64h320a32 32 0 1 1 0 64H96Zm182.6-137.4a32 32 0 0 1-45.3 0l-128-128a32 32 0 0 1 45.3-45.3l73.4 73.4V64a32 32 0 1 1 64 0v178.7l73.4-73.4a32 32 0 0 1 45.3 45.3l-128 128h-.1Z"/></svg>`, gt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M242.7 165.4h.1a22 22 0 0 1 6.5 4.6l45.4 45.2a22 22 0 0 1-31.1 31.2l-7.8-7.8v83.6a22 22 0 0 1-44 0v-83.6l-7.8 7.8a22 22 0 0 1-30.8.2l-.3-.3a22 22 0 0 1 0-31l45.3-45.3a22.1 22.1 0 0 1 .7-.7h.1l.4-.5h.2c1.6-1.5 3.4-2.6 5.3-3.4l.3-.1a22.2 22.2 0 0 1 7.6-1.7h.1a17.8 17.8 0 0 1 1.2 0h-.3a22.4 22.4 0 0 1 .9 0h.7c2.6.2 5 .8 7.3 1.8Z"/><path d="M199.1 21c68.5 0 131 35 167.3 91.1l.1.3h2a153.7 153.7 0 0 1 143.5 151v2.5c0 46.4-20.7 89.6-55.8 118.6a28.5 28.5 0 0 1-36.3-43.8A96.8 96.8 0 0 0 358.4 169c-15 0-29-7.9-36.7-20.9A142 142 0 0 0 57 220.3 142 142 0 0 0 98.5 321 28.4 28.4 0 1 1 58 361 199.2 199.2 0 0 1 199 21Z"/></svg>`, vt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.49 6-3.31 6-6.72h-1.7z"/></svg>`, wt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h12v12H6z"/></svg>`, xt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>`;
d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>`;
const yt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>`, bt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg>`, H = { VITE_API_URL: "https://api.audiodelivery.net" }, F = H, f = F?.VITE_API_URL;
class m extends Error {
constructor(e, n) {
super(e), this.name = "ApiError", this.status = n;
}
}
const S = 1, N = 1e3;
async function h(t, e) {
let n = null;
for (let o = 0; o <= S; o++)
try {
return await fetch(t, e);
} catch (r) {
n = r instanceof Error ? r : new Error(String(r)), o < S && await new Promise((i) => setTimeout(i, N * Math.pow(2, o)));
}
throw n || new m("Network request failed", 0);
}
async function g(t, e, n) {
return n();
}
function v(t, e = {}) {
return t ? {
...e,
headers: {
...e.headers,
"Accept-Language": t
}
} : e;
}
async function Z(t, e, n, o, r, i, s) {
const a = `/v1/play_session/${e}`;
return g("POST", a, async () => {
const l = `${f}${a}`, c = await h(l, v(i, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${t}`
},
body: JSON.stringify({
[`${e}_id`]: n,
variants: o,
...r && { expires_in: r },
// Requested download intent; the API key is the authoritative gate and
// the server stores (key AND this) on the session.
...s && { is_downloadable: !0 }
})
})), p = await c.json();
if (!c.ok || !p.ok)
throw new m(p.message || "Failed to create play session", c.status);
if (!p.tracks?.length)
throw new m("No tracks found in session", c.status);
const x = {
ok: p.ok,
playSessionId: p.play_session_id,
expiresAt: new Date(p.expires_at),
playSession: u(p.play_session),
tracks: []
};
x.playSession.expiresAt = new Date(x.playSession.expiresAt);
for (const O of p.tracks)
x.tracks.push(u(O));
return p.first_track && (x.firstTrack = B(p.first_track)), x;
});
}
async function G(t, e) {
const n = `/v1/play_session/${t}`;
return g("GET", n, async () => {
const o = `${f}${n}`, r = await h(o, v(e)), i = await r.json();
if (!r.ok || !i.ok)
throw new m(i.message || "Failed to fetch play session", r.status);
if (!i.tracks?.length)
throw new m("No tracks found in session", r.status);
const s = {
ok: i.ok,
playSessionId: i.play_session_id,
expiresAt: new Date(i.expires_at || i.play_session.expires_at),
playSession: u(i.play_session),
tracks: []
};
s.playSession.expiresAt = new Date(s.playSession.expiresAt);
for (const a of i.tracks)
s.tracks.push(u(a));
return i.first_track && (s.firstTrack = B(i.first_track)), s;
});
}
async function _t(t, e, n) {
const o = `/v1/play/${t}/${e}`;
return g("GET", o, async () => {
const r = `${f}${o}`, i = await h(r, v(n)), s = await i.json();
if (!i.ok || !s.ok)
throw new m(s.message || "Failed to fetch track data", i.status);
return {
ok: s.ok,
playSessionId: s.play_session_id,
trackId: s.track_id,
playSession: u(s.play_session),
track: u(s.track),
levels: u(s.levels),
variants: z(s.variants),
coverImage: A(u(s.cover_image))
};
});
}
async function kt(t, e, n, o) {
const r = `/v1/play/${t}/${e}/${encodeURIComponent(String(n).toLowerCase())}/download`;
return g("GET", r, async () => {
const i = `${f}${r}`, s = await h(i, v(o)), a = await s.json();
if (!s.ok || !a?.ok)
throw new m(a?.message || "Failed to fetch download URL", s.status);
return a;
});
}
async function St(t, e, n) {
const o = "/v1/upload_session";
return g("POST", o, async () => {
const r = `${f}${o}`, i = {};
e && (i.collection_id = e);
const s = await h(r, v(n, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${t}`
},
body: JSON.stringify(i)
})), a = await s.json();
if (!s.ok || !a?.ok)
throw new m(a?.message || "Failed to create upload session", s.status);
return a;
});
}
async function Tt(t, e, n, o, r) {
const i = "/v1/upload_session";
return g("POST", i, async () => {
const s = `${f}${i}`, a = { file_name: n };
o?.player_title && (a.player_title = o.player_title), o?.player_subtitle && (a.player_subtitle = o.player_subtitle), o?.player_color && (a.player_color = o.player_color), o?.metadata && (a.metadata = o.metadata), o?.organization_index && (a.organization_index = o.organization_index);
const l = { track: a };
e && (l.collection_id = e);
const c = await h(s, v(r, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${t}`
},
body: JSON.stringify(l)
})), p = await c.json();
if (!c.ok || !p?.ok)
throw new m(p?.message || "Failed to create upload session with track", c.status);
if (!p.track_id || !p.track_upload?.upload_url)
throw new m("Upload session created but track upload URL was missing", c.status);
return p;
});
}
async function $t(t, e) {
const n = `/v1/upload_session/${t}`;
return g("GET", n, async () => {
const o = `${f}${n}`, r = await h(o, v(e)), i = await r.json();
if (!r.ok || !i?.ok)
throw new m(i?.message || "Failed to fetch upload session", r.status);
return i;
});
}
async function Ct(t, e, n, o) {
const r = `/v1/upload/${t}/track`;
return g("POST", r, async () => {
const i = `${f}${r}`, s = await h(i, v(o, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
file_name: e,
file_size: n
})
})), a = await s.json();
if (!s.ok || !a?.ok)
throw new m(a?.message || "Failed to get upload URL", s.status);
return a;
});
}
function z(t) {
return t.map((e) => {
const n = u(e);
return e.data !== null && (n.isPreview = !0, n.preview = {
offsetStart: e.data.capture_start,
offsetEnd: e.data.capture_end,
duration: e.data.duration
}), n;
});
}
function B(t) {
return {
ok: !0,
playSessionId: "",
trackId: t.track_id,
playSession: {},
track: u(t.track),
levels: u(t.levels),
variants: z(t.variants),
coverImage: A(u(t.cover_image))
};
}
function T(t) {
return t.toLowerCase().replace(/([-_][a-z])/g, function(e) {
return e.toUpperCase().replace("-", "").replace("_", "");
});
}
function u(t) {
if (t == null) return t;
const e = {};
for (const [n, o] of Object.entries(t)) {
if (o != null && o.constructor === Object) {
e[T(n)] = u(o);
continue;
}
Object.hasOwn(t, n) && (e[T(n)] = o);
}
return e;
}
var W = Object.defineProperty, Y = Object.getOwnPropertyDescriptor, _ = (t, e, n, o) => {
for (var r = o > 1 ? void 0 : o ? Y(e, n) : e, i = t.length - 1, s; i >= 0; i--)
(s = t[i]) && (r = (o ? s(e, n, r) : s(r)) || r);
return o && r && W(e, n, r), r;
};
const P = 180, J = {
error: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M15 9l-6 6M9 9l6 6"/></svg>`,
warning: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l9.5 16.5H2.5L12 3z"/><path d="M12 10v4"/><path d="M12 17.5v.01"/></svg>`,
info: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5"/><path d="M12 8v.01"/></svg>`,
success: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M8.5 12.5l2.5 2.5 4.5-5"/></svg>`
};
let w = class extends I {
constructor() {
super(...arguments), this.duration = 5e3, this.locale = "en", this.notifications = [], this.nextId = 0;
}
add(t, e, n = {}) {
const o = n.duration ?? (t === "error" || t === "warning" ? 0 : this.duration), r = this.notifications.find((c) => !c.dismissing && c.type === t && c.message === e);
if (r)
return r.timeout && clearTimeout(r.timeout), r.action = n.action, o > 0 && (r.timeout = setTimeout(() => this.dismiss(r.id), o)), this.notifications = [...this.notifications], r.id;
const i = this.nextId++, s = { id: i, type: t, message: e, action: n.action };
o > 0 && (s.timeout = setTimeout(() => this.dismiss(i), o));
const a = [...this.notifications, s];
this.notifications = a.length > 4 ? a.slice(a.length - 4) : a;
const l = t === "error" ? "adn-error" : t === "success" ? "adn-success" : `adn-${t}`;
return this.dispatchEvent(new CustomEvent(l, {
detail: { message: e },
bubbles: !0,
composed: !0
})), i;
}
dismiss(t) {
const e = this.notifications.find((n) => n.id === t);
!e || e.dismissing || (e.timeout && clearTimeout(e.timeout), e.dismissing = !0, this.notifications = [...this.notifications], setTimeout(() => {
this.notifications = this.notifications.filter((n) => n.id !== t);
}, P));
}
clear() {
for (const t of this.notifications)
t.timeout && clearTimeout(t.timeout);
this.notifications = [];
}
runAction(t) {
t.action?.onClick(), this.dismiss(t.id);
}
disconnectedCallback() {
super.disconnectedCallback(), this.clear();
}
render() {
return this.notifications.length === 0 ? y`` : y`
<div class="notification-stack">
${[...this.notifications].reverse().map((t) => y`
<div
class="notification notification-${t.type} ${t.dismissing ? "is-dismissing" : ""}"
role=${t.type === "error" || t.type === "warning" ? "alert" : "status"}
aria-live=${t.type === "error" || t.type === "warning" ? "assertive" : "polite"}
>
<span class="notification-icon">${J[t.type]}</span>
<span class="notification-message">${t.message}</span>
${t.action ? y`
<button class="notification-action" @click=${() => this.runAction(t)}>${t.action.label}</button>
` : ""}
<button class="notification-dismiss" @click=${() => this.dismiss(t.id)} aria-label=${V(this.locale, "notification.dismiss")}>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>
</button>
</div>
`)}
</div>
`;
}
};
w.styles = q();
_([
E({ type: Number })
], w.prototype, "duration", 2);
_([
E({ type: String, attribute: "locale" })
], w.prototype, "locale", 2);
_([
U()
], w.prototype, "notifications", 2);
w = _([
R("audiodn-notification")
], w);
function q() {
return b`
.notification-stack {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 9999;
display: flex;
flex-direction: column;
gap: var(--adn-notification-gap, 6px);
padding: var(--adn-notification-padding, 6px);
pointer-events: none;
}
.notification {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
border-radius: var(--adn-notification-radius, 8px);
font-size: var(--adn-notification-font-size, var(--step--1, 0.833rem));
font-family: var(--adn-font-family, sans-serif);
line-height: 1.3;
color: var(--_notif-fg, #fff);
background: var(--_notif-bg);
box-shadow: var(--adn-notification-box-shadow, 0 4px 14px rgba(0, 0, 0, 0.35));
pointer-events: auto;
animation: notif-in 200ms cubic-bezier(0.16, 1, 0.3, 1);
}
.notification.is-dismissing {
animation: notif-out ${P}ms ease-in forwards;
pointer-events: none;
}
.notification-error {
--_notif-bg: var(--adn-notification-bg-error, #dc2626);
}
.notification-warning {
--_notif-bg: var(--adn-notification-bg-warning, #d97706);
}
.notification-info {
--_notif-bg: var(--adn-notification-bg-info, #2563eb);
}
.notification-success {
--_notif-bg: var(--adn-notification-bg-success, #16a34a);
}
.notification-icon {
display: inline-flex;
flex-shrink: 0;
}
.notification-icon svg {
width: 1.15em;
height: 1.15em;
}
.notification-message {
flex: 1;
min-width: 0;
}
.notification-action {
flex-shrink: 0;
appearance: none;
border: 1px solid currentColor;
background: transparent;
color: inherit;
font: inherit;
font-weight: 600;
padding: 3px 10px;
border-radius: 999px;
cursor: pointer;
opacity: 0.95;
transition: background-color 120ms ease, opacity 120ms ease;
}
.notification-action:hover {
background: rgba(255, 255, 255, 0.18);
opacity: 1;
}
.notification-dismiss {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
appearance: none;
border: none;
background: transparent;
color: inherit;
cursor: pointer;
padding: 2px;
opacity: 0.7;
transition: opacity 120ms ease;
}
.notification-dismiss svg {
width: 1em;
height: 1em;
}
.notification-dismiss:hover {
opacity: 1;
}
@keyframes notif-in {
from { opacity: 0; transform: translateY(-8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes notif-out {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
.notification,
.notification.is-dismissing {
animation-duration: 1ms;
}
}
`;
}
const Mt = b`
/* @link https://utopia.fyi/type/calculator?c=320,16,1.2,1240,18,1.25,5,3,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
/* Step -3: 9.2593px → 9.216px */
--step--3: clamp(0.576rem, 0.5796rem + -0.0047vw, 0.5787rem);
/* Step -2: 11.1111px → 11.52px */
--step--2: clamp(0.6944rem, 0.6856rem + 0.0444vw, 0.72rem);
/* Step -1: 13.3333px → 14.4px */
--step--1: clamp(0.8333rem, 0.8101rem + 0.1159vw, 0.9rem);
/* Step 0: 16px → 18px */
--step-0: clamp(1rem, 0.9565rem + 0.2174vw, 1.125rem);
/* Step 1: 19.2px → 22.5px */
--step-1: clamp(1.2rem, 1.1283rem + 0.3587vw, 1.4063rem);
/* Step 2: 23.04px → 28.125px */
--step-2: clamp(1.44rem, 1.3295rem + 0.5527vw, 1.7578rem);
/* Step 3: 27.648px → 35.1563px */
--step-3: clamp(1.728rem, 1.5648rem + 0.8161vw, 2.1973rem);
/* @link https://utopia.fyi/space/calculator?c=320,16,1.2,1240,18,1.25,5,1,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
/* Space 3xs: 4px → 5px */
--space-3xs: clamp(0.25rem, 0.2283rem + 0.1087vw, 0.3125rem);
/* Space 2xs: 8px → 9px */
--space-2xs: clamp(0.5rem, 0.4783rem + 0.1087vw, 0.5625rem);
/* Space xs: 12px → 14px */
--space-xs: clamp(0.75rem, 0.7065rem + 0.2174vw, 0.875rem);
/* Space s: 16px → 18px */
--space-s: clamp(1rem, 0.9565rem + 0.2174vw, 1.125rem);
/* Space m: 24px → 27px */
--space-m: clamp(1.5rem, 1.4348rem + 0.3261vw, 1.6875rem);
/* Space l: 32px → 36px */
--space-l: clamp(2rem, 1.913rem + 0.4348vw, 2.25rem);
/* Space xl: 48px → 54px */
--space-xl: clamp(3rem, 2.8696rem + 0.6522vw, 3.375rem);
/* Space 2xl: 64px → 72px */
--space-2xl: clamp(4rem, 3.8261rem + 0.8696vw, 4.5rem);
/* Space 3xl: 96px → 108px */
--space-3xl: clamp(6rem, 5.7391rem + 1.3043vw, 6.75rem);
/* One-up pairs */
/* Space 3xs-2xs: 4px → 9px */
--space-3xs-2xs: clamp(0.25rem, 0.1413rem + 0.5435vw, 0.5625rem);
/* Space 2xs-xs: 8px → 14px */
--space-2xs-xs: clamp(0.5rem, 0.3696rem + 0.6522vw, 0.875rem);
/* Space xs-s: 12px → 18px */
--space-xs-s: clamp(0.75rem, 0.6196rem + 0.6522vw, 1.125rem);
/* Space s-m: 16px → 27px */
--space-s-m: clamp(1rem, 0.7609rem + 1.1957vw, 1.6875rem);
/* Space m-l: 24px → 36px */
--space-m-l: clamp(1.5rem, 1.2391rem + 1.3043vw, 2.25rem);
/* Space l-xl: 32px → 54px */
--space-l-xl: clamp(2rem, 1.5217rem + 2.3913vw, 3.375rem);
/* Space xl-2xl: 48px → 72px */
--space-xl-2xl: clamp(3rem, 2.4783rem + 2.6087vw, 4.5rem);
/* Space 2xl-3xl: 64px → 108px */
--space-2xl-3xl: clamp(4rem, 3.0435rem + 4.7826vw, 6.75rem);
/* Custom pairs */
/* Space s-l: 16px → 36px */
--space-s-l: clamp(1rem, 0.5652rem + 2.1739vw, 2.25rem);
/* --adn-volume-width: clamp(3.125rem, -0.4464rem + 17.8571vw, 6.25rem); */
`, Et = b`
:host([theme="light"]) {
--_bg: var(--adn-bg, #f4f4f5);
--_bg-light: var(--adn-bg-light, #e4e4e7);
--_color-font: var(--adn-color-font, #1c1c1e);
--_color-font-muted: var(--adn-color-font-muted, #52525b);
--_border-color: var(--adn-border-color, #d4d4d8);
--_color-highlight: var(--adn-color-highlight, rgba(0, 0, 0, 0.06));
/* Darker greyscale accent so controls read on the light background. */
--_color-accent: var(--adn-color-accent, #52525b);
--_color-accent-rgb: var(--adn-color-accent-rgb, 82, 82, 91);
}
@media (prefers-color-scheme: light) {
:host([theme="auto"]) {
--_bg: var(--adn-bg, #f4f4f5);
--_bg-light: var(--adn-bg-light, #e4e4e7);
--_color-font: var(--adn-color-font, #1c1c1e);
--_color-font-muted: var(--adn-color-font-muted, #52525b);
--_border-color: var(--adn-border-color, #d4d4d8);
--_color-highlight: var(--adn-color-highlight, rgba(0, 0, 0, 0.06));
--_color-accent: var(--adn-color-accent, #52525b);
--_color-accent-rgb: var(--adn-color-accent-rgb, 82, 82, 91);
}
}
`, At = b`
*, *:before, *:after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
interpolate-size: allow-keywords;
}
img,canvas, svg {
display: block;
max-width: 100%;
}
input, button {
font: inherit;
}
`, X = 3e4;
async function zt({
playSessionId: t,
id: e,
apiKey: n,
scope: o,
variants: r,
sessionTtl: i,
locale: s,
downloadable: a
}) {
if (t)
try {
const c = await G(t, s);
if (c)
return c;
} catch (c) {
if (!(n && o && e))
throw new Error("failed to fetch session", { cause: c });
}
if (!n)
throw new Error("apiKey must be provided");
if (!o)
throw new Error("scope must be provided");
if (!e)
throw new Error("id must be provided");
if (!r.length)
throw new Error("no variants provided");
const l = await Z(n, o, e, r, i, s, a);
if (!l)
throw new Error("failed to load session data");
return l.tracks = l.tracks.sort((c, p) => c.order - p.order).map((c, p) => (c.order = p + 1, c)), l;
}
class Bt {
constructor() {
this._warningTimer = null, this._expiryTimer = null;
}
schedule(e, n) {
this.clear();
const o = Date.now(), i = e.getTime() - o, s = i - X;
if (i <= 0) {
n.onExpiry();
return;
}
s <= 0 ? n.onWarning() : this._warningTimer = setTimeout(n.onWarning, s), this._expiryTimer = setTimeout(n.onExpiry, i);
}
clear() {
this._warningTimer !== null && (clearTimeout(this._warningTimer), this._warningTimer = null), this._expiryTimer !== null && (clearTimeout(this._expiryTimer), this._expiryTimer = null);
}
}
const K = { r: 244, g: 244, b: 245 }, Q = { r: 0, g: 0, b: 0 }, $ = 3, tt = 0.02, L = (t, e, n) => Math.min(n, Math.max(e, t));
function j(t) {
if (typeof t != "string") return null;
let e = t.trim().replace(/^#/, "");
return e.length === 3 && (e = e.split("").map((n) => n + n).join("")), /^[0-9a-fA-F]{6}$/.test(e) ? {
r: parseInt(e.substring(0, 2), 16),
g: parseInt(e.substring(2, 4), 16),
b: parseInt(e.substring(4, 6), 16)
} : null;
}
function et({ r: t, g: e, b: n }) {
const o = (r) => L(Math.round(r), 0, 255).toString(16).padStart(2, "0");
return `#${o(t)}${o(e)}${o(n)}`;
}
function ot({ r: t, g: e, b: n }) {
const o = t / 255, r = e / 255, i = n / 255, s = Math.max(o, r, i), a = Math.min(o, r, i), l = s - a;
let c = 0;
l !== 0 && (s === o ? c = (r - i) / l % 6 : s === r ? c = (i - o) / l + 2 : c = (o - r) / l + 4, c *= 60, c < 0 && (c += 360));
const p = s === 0 ? 0 : l / s;
return { h: c, s: p, v: s };
}
function C({ h: t, s: e, v: n }) {
const o = n * e, r = o * (1 - Math.abs(t / 60 % 2 - 1)), i = n - o;
let s = 0, a = 0, l = 0;
return t < 60 ? (s = o, a = r, l = 0) : t < 120 ? (s = r, a = o, l = 0) : t < 180 ? (s = 0, a = o, l = r) : t < 240 ? (s = 0, a = r, l = o) : t < 300 ? (s = r, a = 0, l = o) : (s = o, a = 0, l = r), {
r: (s + i) * 255,
g: (a + i) * 255,
b: (l + i) * 255
};
}
function k({ r: t, g: e, b: n }) {
const o = [t / 255, e / 255, n / 255].map((r) => r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4));
return 0.2126 * o[0] + 0.7152 * o[1] + 0.0722 * o[2];
}
function M(t, e) {
const n = k(t), o = k(e), r = Math.max(n, o), i = Math.min(n, o);
return (r + 0.05) / (i + 0.05);
}
function Pt(t, e = 0.179) {
const n = j(t);
return n ? k(n) <= e : !0;
}
function nt(t, e, n) {
let { v: o } = t, r = C({ ...t, v: o });
if (M(r, e) >= $) return r;
for (let i = 0; i < 60 && (o = L(o + n * tt, 0, 1), r = C({ ...t, v: o }), !(M(r, e) >= $ || o === 0 || o === 1)); i++)
;
return r;
}
function rt(t, e) {
const n = j(t);
if (!n) return null;
const o = ot(n);
return et(nt(o, e === "light" ? K : Q, e === "light" ? -1 : 1));
}
const it = "#71717a";
function Lt(t) {
return rt(it, t) ?? (t === "light" ? "#52525b" : "#a1a1aa");
}
export {
zt as A,
m as B,
_t as C,
Lt as D,
Bt as S,
rt as a,
Ct as b,
Tt as c,
dt as d,
yt as e,
wt as f,
$t as g,
vt as h,
Pt as i,
xt as j,
ct as k,
lt as l,
bt as m,
At as n,
Mt as o,
j as p,
St as q,
gt as r,
D as s,
Et as t,
pt as u,
ut as v,
mt as w,
ft as x,
kt as y,
ht as z
};
const l = ["en", "fr", "es", "de"];
const n = {
"action.retry": "Retry",
"action.reload": "Reload",
"player.notify.loadFailed": "Couldn’t load the player.",
"player.notify.sessionExpired": "Your session expired.",
"player.notify.noSession": "No play session available",
"player.notify.trackLoadFailed": "Couldn’t load this track.",
"player.notify.playFailed": "Couldn’t play this track.",
"player.aria.loading": "Loading audio player",
"player.loadingText": "Loading audio player…",
"player.aria.region": "Audio player",
"player.status.playbackError": "Playback error",
"player.status.buffering": "Buffering",
"player.status.nowPlaying": "Now playing: {title}",
"playButton.retry": "Retry",
"playButton.loading": "Loading",
"playButton.pause": "Pause",
"playButton.play": "Play",
"progress.aria.label": "Playback progress",
"progress.aria.valueText": "{current} of {total}",
"playTime.aria": "Playback time: {elapsed} of {total}",
"volume.aria": "Volume",
"settings.aria": "More options",
"settings.download": "Download {label}",
"settings.notDownloadable": "This track isn’t downloadable.",
"settings.output.menuLabel": "Output device",
"settings.output.unnamed": "Speaker {n}",
"trackTitle.none": "No track selected",
"coverArt.none": "No cover art",
"coverArt.alt": "Cover art",
"tracklist.aria": "Track list",
"waveform.aria": "Audio waveform",
"notification.dismiss": "Dismiss notification",
"uploader.notify.sessionExpired": "Your upload session expired.",
"uploader.notify.uploadSuccess": "{filename} uploaded successfully",
"uploader.notify.uploadFailed": "{filename}: upload failed",
"uploader.notify.networkError": "{filename}: network error",
"uploader.notify.uploadFailedDetail": "{filename}: {error}",
"uploader.notify.noAudioFiles": "No audio files detected. Please select audio files.",
"uploader.notify.limitExceeded": "You can upload at most {limit} file(s).",
"uploader.error.tryAgain": "Try again",
"uploader.aria.loading": "Loading uploader",
"uploader.loadingText": "Loading…",
"uploader.aria.fileArea": "File upload area",
"uploader.dropHeading": "Drop Audio Tracks To Collection",
"uploader.or": "or",
"uploader.browseFiles": "Browse Files",
"uploader.aria.selectFiles": "Select audio files to upload",
"uploader.aria.totalProgress": "Total upload progress",
"uploader.totalProgressText": "{percent}% total",
"uploader.aria.queue": "Upload queue",
"uploader.aria.fileProgress": "Upload progress for {filename}",
"uploader.aria.retryFile": "Retry upload for {filename}",
"uploader.aria.cancelUpload": "Cancel upload for {filename}",
"uploader.aria.removeFile": "Remove file {filename}",
"recorder.notify.sessionExpired": "Your upload session expired.",
"recorder.notify.uploadSuccess": "Recording uploaded successfully",
"recorder.notify.uploadFailed": "Upload failed",
"recorder.notify.networkError": "Network error during upload",
"recorder.notify.uploadFailedDetail": "Upload failed: {error}",
"recorder.notify.micDenied": "Microphone access was denied.",
"recorder.notify.micUnavailable": "Microphone is not available.",
"recorder.notify.maxDuration": "Maximum recording length reached.",
"recorder.error.tryAgain": "Try again",
"recorder.aria.loading": "Loading recorder",
"recorder.loadingText": "Loading…",
"recorder.aria.region": "Voice recorder",
"recorder.aria.start": "Start recording",
"recorder.aria.pause": "Pause recording",
"recorder.aria.resume": "Resume recording",
"recorder.aria.stop": "Stop recording",
"recorder.aria.discard": "Discard recording",
"recorder.aria.send": "Confirm recording",
"recorder.aria.cancelCountdown": "Cancel countdown",
"recorder.idle.hint": "Tap to record",
"recorder.countdown.hint": "Get ready…",
"recorder.aria.selectMic": "Select microphone",
"recorder.device.unnamed": "Microphone {n}",
"recorder.device.menuLabel": "Microphones",
"recorder.aria.moreOptions": "More options",
"recorder.menu.preview": "Preview",
"recorder.menu.stopPreview": "Stop preview",
"recorder.menu.delete": "Delete",
"recorder.menu.stopUpload": "Stop upload",
"recorder.aria.cancelUpload": "Cancel upload",
"recorder.aria.play": "Play recording",
"recorder.aria.pausePreview": "Pause playback",
"recorder.aria.progress": "Upload progress",
"recorder.aria.done": "Upload complete",
"recorder.timer.preview": "{current}/{total}"
}, d = {
"action.retry": "Réessayer",
"action.reload": "Recharger",
"player.notify.loadFailed": "Impossible de charger le lecteur.",
"player.notify.sessionExpired": "Votre session a expiré.",
"player.notify.noSession": "Aucune session de lecture disponible",
"player.notify.trackLoadFailed": "Impossible de charger cette piste.",
"player.notify.playFailed": "Impossible de lire cette piste.",
"player.aria.loading": "Chargement du lecteur audio",
"player.loadingText": "Chargement du lecteur audio…",
"player.aria.region": "Lecteur audio",
"player.status.playbackError": "Erreur de lecture",
"player.status.buffering": "Mise en mémoire tampon",
"player.status.nowPlaying": "Lecture en cours : {title}",
"playButton.retry": "Réessayer",
"playButton.loading": "Chargement",
"playButton.pause": "Pause",
"playButton.play": "Lecture",
"progress.aria.label": "Progression de la lecture",
"progress.aria.valueText": "{current} sur {total}",
"playTime.aria": "Temps de lecture : {elapsed} sur {total}",
"volume.aria": "Volume",
"settings.aria": "Plus d’options",
"settings.download": "Télécharger {label}",
"settings.notDownloadable": "Cette piste n’est pas téléchargeable.",
"settings.output.menuLabel": "Périphérique de sortie",
"settings.output.unnamed": "Haut-parleur {n}",
"trackTitle.none": "Aucune piste sélectionnée",
"coverArt.none": "Pas de pochette",
"coverArt.alt": "Pochette",
"tracklist.aria": "Liste des pistes",
"waveform.aria": "Forme d’onde audio",
"notification.dismiss": "Ignorer la notification",
"uploader.notify.sessionExpired": "Votre session de téléversement a expiré.",
"uploader.notify.uploadSuccess": "{filename} téléversé avec succès",
"uploader.notify.uploadFailed": "{filename} : échec du téléversement",
"uploader.notify.networkError": "{filename} : erreur réseau",
"uploader.notify.uploadFailedDetail": "{filename} : {error}",
"uploader.notify.noAudioFiles": "Aucun fichier audio détecté. Veuillez sélectionner des fichiers audio.",
"uploader.notify.limitExceeded": "Vous ne pouvez téléverser que {limit} fichier(s).",
"uploader.error.tryAgain": "Réessayer",
"uploader.aria.loading": "Chargement du téléverseur",
"uploader.loadingText": "Chargement…",
"uploader.aria.fileArea": "Zone de téléversement de fichiers",
"uploader.dropHeading": "Déposez des pistes audio dans la collection",
"uploader.or": "ou",
"uploader.browseFiles": "Parcourir les fichiers",
"uploader.aria.selectFiles": "Sélectionner des fichiers audio à téléverser",
"uploader.aria.totalProgress": "Progression totale du téléversement",
"uploader.totalProgressText": "{percent}% au total",
"uploader.aria.queue": "File de téléversement",
"uploader.aria.fileProgress": "Progression du téléversement pour {filename}",
"uploader.aria.retryFile": "Réessayer le téléversement pour {filename}",
"uploader.aria.cancelUpload": "Annuler le téléversement pour {filename}",
"uploader.aria.removeFile": "Retirer le fichier {filename}",
"recorder.notify.sessionExpired": "Votre session de téléversement a expiré.",
"recorder.notify.uploadSuccess": "Enregistrement téléversé avec succès",
"recorder.notify.uploadFailed": "Échec du téléversement",
"recorder.notify.networkError": "Erreur réseau pendant le téléversement",
"recorder.notify.uploadFailedDetail": "Échec du téléversement : {error}",
"recorder.notify.micDenied": "L’accès au microphone a été refusé.",
"recorder.notify.micUnavailable": "Le microphone n’est pas disponible.",
"recorder.notify.maxDuration": "Durée maximale d’enregistrement atteinte.",
"recorder.error.tryAgain": "Réessayer",
"recorder.aria.loading": "Chargement de l’enregistreur",
"recorder.loadingText": "Chargement…",
"recorder.aria.region": "Enregistreur vocal",
"recorder.aria.start": "Démarrer l’enregistrement",
"recorder.aria.pause": "Mettre en pause",
"recorder.aria.resume": "Reprendre l’enregistrement",
"recorder.aria.stop": "Arrêter l’enregistrement",
"recorder.aria.discard": "Supprimer l’enregistrement",
"recorder.aria.send": "Confirmer l’enregistrement",
"recorder.aria.cancelCountdown": "Annuler le compte à rebours",
"recorder.idle.hint": "Appuyez pour enregistrer",
"recorder.countdown.hint": "Préparez-vous…",
"recorder.aria.selectMic": "Choisir le microphone",
"recorder.device.unnamed": "Microphone {n}",
"recorder.device.menuLabel": "Microphones",
"recorder.aria.moreOptions": "Plus d’options",
"recorder.menu.preview": "Écouter",
"recorder.menu.stopPreview": "Arrêter l’écoute",
"recorder.menu.delete": "Supprimer",
"recorder.menu.stopUpload": "Arrêter l’envoi",
"recorder.aria.cancelUpload": "Annuler le téléversement",
"recorder.aria.play": "Lire l’enregistrement",
"recorder.aria.pausePreview": "Mettre la lecture en pause",
"recorder.aria.progress": "Progression du téléversement",
"recorder.aria.done": "Téléversement terminé",
"recorder.timer.preview": "{current}/{total}"
}, s = {
"action.retry": "Reintentar",
"action.reload": "Recargar",
"player.notify.loadFailed": "No se pudo cargar el reproductor.",
"player.notify.sessionExpired": "Tu sesión ha expirado.",
"player.notify.noSession": "No hay sesión de reproducción disponible",
"player.notify.trackLoadFailed": "No se pudo cargar esta pista.",
"player.notify.playFailed": "No se pudo reproducir esta pista.",
"player.aria.loading": "Cargando el reproductor de audio",
"player.loadingText": "Cargando el reproductor de audio…",
"player.aria.region": "Reproductor de audio",
"player.status.playbackError": "Error de reproducción",
"player.status.buffering": "Almacenando en búfer",
"player.status.nowPlaying": "Reproduciendo: {title}",
"playButton.retry": "Reintentar",
"playButton.loading": "Cargando",
"playButton.pause": "Pausa",
"playButton.play": "Reproducir",
"progress.aria.label": "Progreso de reproducción",
"progress.aria.valueText": "{current} de {total}",
"playTime.aria": "Tiempo de reproducción: {elapsed} de {total}",
"volume.aria": "Volumen",
"settings.aria": "Más opciones",
"settings.download": "Descargar {label}",
"settings.notDownloadable": "Esta pista no se puede descargar.",
"settings.output.menuLabel": "Dispositivo de salida",
"settings.output.unnamed": "Altavoz {n}",
"trackTitle.none": "Ninguna pista seleccionada",
"coverArt.none": "Sin carátula",
"coverArt.alt": "Carátula",
"tracklist.aria": "Lista de pistas",
"waveform.aria": "Forma de onda de audio",
"notification.dismiss": "Descartar notificación",
"uploader.notify.sessionExpired": "Tu sesión de subida ha expirado.",
"uploader.notify.uploadSuccess": "{filename} subido correctamente",
"uploader.notify.uploadFailed": "{filename}: error al subir",
"uploader.notify.networkError": "{filename}: error de red",
"uploader.notify.uploadFailedDetail": "{filename}: {error}",
"uploader.notify.noAudioFiles": "No se detectaron archivos de audio. Selecciona archivos de audio.",
"uploader.notify.limitExceeded": "Solo puedes subir {limit} archivo(s).",
"uploader.error.tryAgain": "Intentar de nuevo",
"uploader.aria.loading": "Cargando el cargador",
"uploader.loadingText": "Cargando…",
"uploader.aria.fileArea": "Área de subida de archivos",
"uploader.dropHeading": "Suelta pistas de audio en la colección",
"uploader.or": "o",
"uploader.browseFiles": "Explorar archivos",
"uploader.aria.selectFiles": "Selecciona archivos de audio para subir",
"uploader.aria.totalProgress": "Progreso total de subida",
"uploader.totalProgressText": "{percent}% en total",
"uploader.aria.queue": "Cola de subida",
"uploader.aria.fileProgress": "Progreso de subida de {filename}",
"uploader.aria.retryFile": "Reintentar la subida de {filename}",
"uploader.aria.cancelUpload": "Cancelar la subida de {filename}",
"uploader.aria.removeFile": "Quitar el archivo {filename}",
"recorder.notify.sessionExpired": "Tu sesión de subida ha expirado.",
"recorder.notify.uploadSuccess": "Grabación subida correctamente",
"recorder.notify.uploadFailed": "Error al subir",
"recorder.notify.networkError": "Error de red durante la subida",
"recorder.notify.uploadFailedDetail": "Error al subir: {error}",
"recorder.notify.micDenied": "Se denegó el acceso al micrófono.",
"recorder.notify.micUnavailable": "El micrófono no está disponible.",
"recorder.notify.maxDuration": "Se alcanzó la duración máxima de grabación.",
"recorder.error.tryAgain": "Intentar de nuevo",
"recorder.aria.loading": "Cargando el grabador",
"recorder.loadingText": "Cargando…",
"recorder.aria.region": "Grabador de voz",
"recorder.aria.start": "Iniciar grabación",
"recorder.aria.pause": "Pausar grabación",
"recorder.aria.resume": "Reanudar grabación",
"recorder.aria.stop": "Detener grabación",
"recorder.aria.discard": "Descartar grabación",
"recorder.aria.send": "Confirmar grabación",
"recorder.aria.cancelCountdown": "Cancelar cuenta atrás",
"recorder.idle.hint": "Toca para grabar",
"recorder.countdown.hint": "Prepárate…",
"recorder.aria.selectMic": "Seleccionar micrófono",
"recorder.device.unnamed": "Micrófono {n}",
"recorder.device.menuLabel": "Micrófonos",
"recorder.aria.moreOptions": "Más opciones",
"recorder.menu.preview": "Escuchar",
"recorder.menu.stopPreview": "Detener escucha",
"recorder.menu.delete": "Eliminar",
"recorder.menu.stopUpload": "Detener subida",
"recorder.aria.cancelUpload": "Cancelar subida",
"recorder.aria.play": "Reproducir grabación",
"recorder.aria.pausePreview": "Pausar reproducción",
"recorder.aria.progress": "Progreso de subida",
"recorder.aria.done": "Subida completa",
"recorder.timer.preview": "{current}/{total}"
}, c = {
"action.retry": "Wiederholen",
"action.reload": "Neu laden",
"player.notify.loadFailed": "Player konnte nicht geladen werden.",
"player.notify.sessionExpired": "Ihre Sitzung ist abgelaufen.",
"player.notify.noSession": "Keine Wiedergabesitzung verfügbar",
"player.notify.trackLoadFailed": "Dieser Titel konnte nicht geladen werden.",
"player.notify.playFailed": "Dieser Titel konnte nicht abgespielt werden.",
"player.aria.loading": "Audio-Player wird geladen",
"player.loadingText": "Audio-Player wird geladen…",
"player.aria.region": "Audio-Player",
"player.status.playbackError": "Wiedergabefehler",
"player.status.buffering": "Puffern",
"player.status.nowPlaying": "Wird abgespielt: {title}",
"playButton.retry": "Wiederholen",
"playButton.loading": "Wird geladen",
"playButton.pause": "Pause",
"playButton.play": "Abspielen",
"progress.aria.label": "Wiedergabefortschritt",
"progress.aria.valueText": "{current} von {total}",
"playTime.aria": "Wiedergabezeit: {elapsed} von {total}",
"volume.aria": "Lautstärke",
"settings.aria": "Weitere Optionen",
"settings.download": "{label} herunterladen",
"settings.notDownloadable": "Dieser Titel kann nicht heruntergeladen werden.",
"settings.output.menuLabel": "Ausgabegerät",
"settings.output.unnamed": "Lautsprecher {n}",
"trackTitle.none": "Kein Titel ausgewählt",
"coverArt.none": "Kein Cover",
"coverArt.alt": "Cover",
"tracklist.aria": "Titelliste",
"waveform.aria": "Audio-Wellenform",
"notification.dismiss": "Benachrichtigung schließen",
"uploader.notify.sessionExpired": "Ihre Upload-Sitzung ist abgelaufen.",
"uploader.notify.uploadSuccess": "{filename} erfolgreich hochgeladen",
"uploader.notify.uploadFailed": "{filename}: Upload fehlgeschlagen",
"uploader.notify.networkError": "{filename}: Netzwerkfehler",
"uploader.notify.uploadFailedDetail": "{filename}: {error}",
"uploader.notify.noAudioFiles": "Keine Audiodateien erkannt. Bitte wählen Sie Audiodateien aus.",
"uploader.notify.limitExceeded": "Sie können höchstens {limit} Datei(en) hochladen.",
"uploader.error.tryAgain": "Erneut versuchen",
"uploader.aria.loading": "Uploader wird geladen",
"uploader.loadingText": "Wird geladen…",
"uploader.aria.fileArea": "Datei-Upload-Bereich",
"uploader.dropHeading": "Audiotitel in die Sammlung ziehen",
"uploader.or": "oder",
"uploader.browseFiles": "Dateien durchsuchen",
"uploader.aria.selectFiles": "Audiodateien zum Hochladen auswählen",
"uploader.aria.totalProgress": "Gesamter Upload-Fortschritt",
"uploader.totalProgressText": "{percent}% gesamt",
"uploader.aria.queue": "Upload-Warteschlange",
"uploader.aria.fileProgress": "Upload-Fortschritt für {filename}",
"uploader.aria.retryFile": "Upload für {filename} wiederholen",
"uploader.aria.cancelUpload": "Upload für {filename} abbrechen",
"uploader.aria.removeFile": "Datei {filename} entfernen",
"recorder.notify.sessionExpired": "Ihre Upload-Sitzung ist abgelaufen.",
"recorder.notify.uploadSuccess": "Aufnahme erfolgreich hochgeladen",
"recorder.notify.uploadFailed": "Upload fehlgeschlagen",
"recorder.notify.networkError": "Netzwerkfehler während des Uploads",
"recorder.notify.uploadFailedDetail": "Upload fehlgeschlagen: {error}",
"recorder.notify.micDenied": "Mikrofonzugriff wurde verweigert.",
"recorder.notify.micUnavailable": "Mikrofon ist nicht verfügbar.",
"recorder.notify.maxDuration": "Maximale Aufnahmedauer erreicht.",
"recorder.error.tryAgain": "Erneut versuchen",
"recorder.aria.loading": "Recorder wird geladen",
"recorder.loadingText": "Wird geladen…",
"recorder.aria.region": "Sprachrekorder",
"recorder.aria.start": "Aufnahme starten",
"recorder.aria.pause": "Aufnahme pausieren",
"recorder.aria.resume": "Aufnahme fortsetzen",
"recorder.aria.stop": "Aufnahme beenden",
"recorder.aria.discard": "Aufnahme verwerfen",
"recorder.aria.send": "Aufnahme bestätigen",
"recorder.aria.cancelCountdown": "Countdown abbrechen",
"recorder.idle.hint": "Tippen zum Aufnehmen",
"recorder.countdown.hint": "Bereit machen…",
"recorder.aria.selectMic": "Mikrofon auswählen",
"recorder.device.unnamed": "Mikrofon {n}",
"recorder.device.menuLabel": "Mikrofone",
"recorder.aria.moreOptions": "Weitere Optionen",
"recorder.menu.preview": "Anhören",
"recorder.menu.stopPreview": "Anhören stoppen",
"recorder.menu.delete": "Löschen",
"recorder.menu.stopUpload": "Upload stoppen",
"recorder.aria.cancelUpload": "Upload abbrechen",
"recorder.aria.play": "Aufnahme abspielen",
"recorder.aria.pausePreview": "Wiedergabe pausieren",
"recorder.aria.progress": "Upload-Fortschritt",
"recorder.aria.done": "Upload abgeschlossen",
"recorder.timer.preview": "{current}/{total}"
}, u = { en: n, fr: d, es: s, de: c };
function p(r) {
if (!r) return "en";
const e = r.toLowerCase().split("-")[0];
return l.includes(e ?? "") ? e : "en";
}
function f(r, e, a) {
const t = p(r ?? void 0);
let o = u[t][e] ?? n[e] ?? e;
if (a)
for (const i of Object.keys(a))
o = o.split(`{${i}}`).join(String(a[i]));
return o;
}
export {
f as t
};
class u {
#e;
constructor(n) {
this.#e = n;
}
get(n) {
const t = this.#e.getItem(n);
if (!t) return;
const i = JSON.parse(t);
if (i) {
if (i.expires && i.expires <= Date.now()) {
this.remove(n);
return;
}
return i.data;
}
}
set(n, t, i = 6e4) {
const o = {};
o.data = t, i && (i === !0 ? i = Date.now() : i = Date.now() + i, o.expires = i), this.#e.setItem(n, JSON.stringify(o));
}
remove(n) {
return this.#e.removeItem(n);
}
}
function d(e) {
return new u(e);
}
const p = "adn-inputchange", v = "adn-outputchange", s = "audioInputDeviceId", a = "audioOutputDeviceId";
function r() {
if (!(typeof sessionStorage > "u"))
return d(sessionStorage);
}
function c() {
return typeof HTMLMediaElement < "u" && typeof HTMLMediaElement.prototype.setSinkId == "function";
}
async function f(e) {
if (typeof navigator > "u" || !navigator.mediaDevices?.enumerateDevices)
return [];
try {
return (await navigator.mediaDevices.enumerateDevices()).filter((t) => t.kind === e && t.deviceId).map((t) => ({ deviceId: t.deviceId, label: t.label || "" }));
} catch {
return [];
}
}
function I() {
return f("audiooutput");
}
function g() {
const e = r()?.get(s);
return typeof e == "string" ? e : "";
}
function l(e) {
r()?.set(s, e, !1);
}
function m() {
const e = r()?.get(a);
return typeof e == "string" ? e : "";
}
function S(e) {
r()?.set(a, e, !1);
}
async function y(e, n) {
if (!e || !n || !c()) return;
const t = e;
if (typeof t.setSinkId == "function")
try {
await t.setSinkId(n);
} catch {
}
}
export {
p as I,
v as O,
y as a,
m as b,
c,
d,
I as e,
S as f,
g,
l as s
};
import { n as l, r as E, i as V, a as X, b as N, t as j } from "./lit-DpNjQO9d.js";
import { t as L } from "./i18n-BI0dP23M.js";
function q(t) {
if (t === void 0) return "--:--";
const i = Math.floor(t / 60) || 0, o = Math.round(t % 60) || 0;
return `${i}:${("" + o).padStart(2, "0")}`;
}
function et(t) {
if (t === void 0) return "0s";
const i = Math.floor(t / 60) || 0, o = Math.round(t % 60) || 0;
return [
i && i + "m",
o && o + "s"
].join(" ");
}
function it(t, i = 2) {
if (!+t) return "0 Bytes";
const o = 1e3, s = i < 0 ? 0 : i, e = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], r = Math.floor(Math.log(t) / Math.log(o));
return `${parseFloat((t / Math.pow(o, r)).toFixed(s))} ${e[r]}`;
}
let z, _, P, M, W, $, R, C, S;
const T = [];
function I(t, i) {
return _ = window.pageXOffset, M = window.pageYOffset, $ = window.innerHeight, C = window.innerWidth, P === void 0 && (P = _), W === void 0 && (W = M), S === void 0 && (S = C), R === void 0 && (R = $), (i || M !== W || _ !== P || $ !== R || C !== S) && (Y(t), P = _, W = M, R = $, S = C), requestAnimationFrame(I);
}
function Y(t) {
for (const i of T)
i({ x: _, y: M, px: P, py: W, vh: $, pvh: R, vw: C, pvw: S }, t);
}
function G(t) {
return T.indexOf(t) < 0 && T.push(t), z = z || I(performance.now()), {
update() {
return I(performance.now(), !0), this;
},
destroy() {
T.splice(T.indexOf(t), 1);
}
};
}
var U = Object.defineProperty, K = Object.getOwnPropertyDescriptor, a = (t, i, o, s) => {
for (var e = s > 1 ? void 0 : s ? K(i, o) : i, r = t.length - 1, c; r >= 0; r--)
(c = t[r]) && (e = (s ? c(i, o, e) : c(e)) || e);
return s && e && U(i, o, e), e;
};
let n = class extends X {
constructor() {
super(...arguments), this.levels = [], this.height = 120, this.lineColor = "#888888", this.lineWidth = 2, this.gap = 3, this.variant = "vertical", this.locale = "en", this.scaleStrength = 0.4, this.reflectionAngle = 45, this.reflectionSize = 0.25, this.reflectionOpacity = 0.55, this.highlightFrom = 0, this.highlightWidth = 1, this.min = 0, this.max = 1, this.duration = 0, this.progress = 0, this.data = new Float32Array(), this.hoverPosition = null, this.containerWidth = 0, this.canvas = null, this.ctx = null, this._srrafHandle = null, this._drawScheduled = !1, this._hoverRafId = null, this._cachedRect = null, this.draw = () => {
if (!this.canvas || !this.ctx) return;
const { lineWidth: t, gap: i, height: o, variant: s } = this, e = this.ctx, r = Math.max(1, window.devicePixelRatio || 1), c = this.canvas.clientWidth || this.getRect().width, v = Math.max(1, Math.round(c * r)), h = Math.max(1, Math.round(o * r));
this.canvas.width = v, this.canvas.height = h;
const u = t + i, O = Math.floor(
(c - t - (s === "wavy" ? u : 0)) / u
) + 1, b = [];
for (let d = 0; d < O; d++) {
const p = Math.round(d / O * this.data.length);
b.push(this.data[p]);
}
e.clearRect(0, 0, v, h), e.fillStyle = this.lineColor, e.strokeStyle = this.lineColor;
const k = Math.max(1, Math.round(t * r)), D = u * r;
if (s === "vertical")
b.forEach((d, p) => {
if (!d) return;
const g = Math.round(p * D), f = Math.round(d * h), y = Math.round((h - f) / 2);
e.fillRect(g, y, k, f);
});
else if (s === "reflection") {
const d = Math.max(0, this.reflectionSize), p = Math.round(h / (1 + d)), g = h - p, f = p, m = (0.5 - Math.max(0, Math.min(1, this.progress))) * 2 * (this.reflectionAngle * Math.PI / 180), A = Math.tan(m);
e.fillStyle = this.lineColor, b.forEach((w, H) => {
if (!w) return;
const F = Math.round(H * D), x = Math.round(w * p);
e.fillRect(F, f - x, k, x);
});
const B = e.createLinearGradient(0, f, 0, f + g);
B.addColorStop(0, this.colorToRgba(this.lineColor, this.reflectionOpacity)), B.addColorStop(0.75, this.colorToRgba(this.lineColor, this.reflectionOpacity * 0.5)), B.addColorStop(1, this.colorToRgba(this.lineColor, 0)), e.strokeStyle = B, e.lineWidth = k, b.forEach((w, H) => {
if (!w) return;
const F = Math.round(H * D) + k / 2, x = w * g;
e.beginPath(), e.moveTo(F, f), e.lineTo(F + A * x, f + x), e.stroke();
});
} else if (s === "wavy") {
e.scale(r, r), e.lineWidth = this.lineWidth, e.save();
const d = o / 2;
e.translate(0, d);
const p = c / b.length;
for (const [g, f] of b.entries()) {
if (!f) continue;
const y = g * u + Math.ceil(t / 2) + 0.5;
let m = f * (d - this.lineWidth * 2);
m < 0 ? m = 0 : m > d - this.lineWidth * 2 && (m = d - this.lineWidth * 2);
const A = (g + 1) % 2 ? m : -m;
e.beginPath(), e.moveTo(y, 0), e.lineTo(y, A), e.arc(
y + p / 2,
A,
Math.min(p / 2, Math.min(p / 2, m)),
Math.PI,
0,
!!((g + 1) % 2)
), e.lineTo(y + p, 0), e.stroke();
}
e.restore();
}
};
}
connectedCallback() {
super.connectedCallback(), this.updateLineColor(), this._srrafHandle = G(({ vw: t, pvw: i }) => {
t !== i && (this._cachedRect = null, this.computeWaveformWidth(), this.scheduleDraw());
});
}
disconnectedCallback() {
super.disconnectedCallback(), this._srrafHandle?.destroy(), this._srrafHandle = null, this._hoverRafId !== null && (cancelAnimationFrame(this._hoverRafId), this._hoverRafId = null);
}
willUpdate(t) {
this.style.setProperty("--_playheadPosition", this.progress * 100 + "%"), this.style.setProperty("--_playheadVisible", this.progress > 0 ? "1" : "0"), this.style.setProperty("--_hoverPosition", this.hoverPosition !== null ? this.hoverPosition * 100 + "%" : "0%"), this.style.setProperty("--_hoverVisible", this.hoverPosition !== null ? "1" : "0"), this.style.setProperty("--_highlightFrom", `${this.highlightFrom}px`), this.style.setProperty("--_maskWidth", `${Math.floor(this.containerWidth * this.highlightWidth)}px`), this.updateLineColor(), this.levels && t.has("levels") && this.processData();
}
render() {
return Z.call(this);
}
firstUpdated() {
this.canvas = this.renderRoot.querySelector("canvas"), this.canvas && (this.ctx = this.canvas.getContext("2d"));
}
updated() {
this.style.setProperty("--_pre-progress", `${this.min * 100}%`), this.max < 1 ? this.style.setProperty("--_width", `${this.max * 100}%`) : this.style.setProperty("--_width", `${this.progress * 100}%`), this.computeWaveformWidth(), this.scheduleDraw();
}
getRect() {
return this._cachedRect || (this._cachedRect = this.getBoundingClientRect()), this._cachedRect;
}
handleEvent(t) {
const i = t.currentTarget;
if (t.type === "mouseenter") {
i.style.setProperty("--_transitionSpeed", "0");
return;
}
if (t.type === "mouseleave") {
i.style.setProperty("--_transitionSpeed", "100ms"), this.hoverPosition = null;
return;
}
const o = this.getRect(), s = t.clientX - o.left;
if (s < 0 || s > this.containerWidth) {
this.hoverPosition = null;
return;
}
const e = Math.max(0, Math.min(1, s / this.containerWidth));
if (t.type === "mousemove") {
if (this._hoverRafId !== null) return;
this._hoverRafId = requestAnimationFrame(() => {
this._hoverRafId = null, this.hoverPosition = e;
});
}
t.type === "click" && this.dispatchEvent(
new CustomEvent("adni-seek", {
detail: { percent: e },
bubbles: !0
})
);
}
handleTouch(t) {
if (!(!t.touches.length && t.type !== "touchend")) {
if (t.type === "touchstart" || t.type === "touchmove") {
t.preventDefault();
const i = t.touches[0];
if (!i) return;
const o = this.getRect(), s = i.clientX - o.left, e = Math.max(0, Math.min(1, s / this.containerWidth));
this.hoverPosition = e;
}
t.type === "touchend" && (this.hoverPosition !== null && this.dispatchEvent(
new CustomEvent("adni-seek", {
detail: { percent: this.hoverPosition },
bubbles: !0
})
), this.hoverPosition = null);
}
}
computeWaveformWidth() {
this._cachedRect = null, this.containerWidth = this.getRect().width;
}
processData() {
const { levels: t, scaleStrength: i } = this;
if (!t || t.length === 0) {
this.data = new Float32Array();
return;
}
const o = Math.min(...t), e = Math.max(...t) - o;
let r = e === 0 ? t.map(() => 0.5) : t.map((h) => (h - o) / e), c = r.reduce((h, u) => h + u, 0) / t.length, v = 0;
for (; c > 1 - i && v < 10; )
r = r.map((h) => h * h), c = r.reduce((h, u) => h + u, 0) / t.length, v += 1;
this.data = new Float32Array(r);
}
// Normalize any CSS color to rgba() with the given alpha (via the canvas'
// own color parsing) so the reflection gradient can fade to transparent.
colorToRgba(t, i) {
const o = this.ctx;
if (!o) return `rgba(136, 136, 136, ${i})`;
o.fillStyle = "#000", o.fillStyle = t;
const s = o.fillStyle;
if (s.startsWith("#")) {
let r = s.slice(1);
r.length === 3 && (r = r.split("").map((u) => u + u).join(""));
const c = parseInt(r.slice(0, 2), 16), v = parseInt(r.slice(2, 4), 16), h = parseInt(r.slice(4, 6), 16);
return `rgba(${c}, ${v}, ${h}, ${i})`;
}
const e = s.match(/rgba?\(([^)]+)\)/);
if (e && e[1]) {
const [r, c, v] = e[1].split(",").map((h) => h.trim());
return `rgba(${r}, ${c}, ${v}, ${i})`;
}
return `rgba(136, 136, 136, ${i})`;
}
updateLineColor() {
const t = getComputedStyle(this), i = t.getPropertyValue("--adn-waveform-color-fg"), o = t.getPropertyValue("--adn-color-accent");
this.lineColor = i || o || t.getPropertyValue("--_color-accent");
}
scheduleDraw() {
this._drawScheduled || (this._drawScheduled = !0, requestAnimationFrame(() => {
this._drawScheduled = !1, this.draw();
}));
}
};
n.styles = J();
a([
l({ type: Array })
], n.prototype, "levels", 2);
a([
l({ type: Number })
], n.prototype, "height", 2);
a([
l({ type: String, attribute: "line-color" })
], n.prototype, "lineColor", 2);
a([
l({ type: Number, attribute: "line-width" })
], n.prototype, "lineWidth", 2);
a([
l({ type: Number })
], n.prototype, "gap", 2);
a([
l({ type: String })
], n.prototype, "variant", 2);
a([
l({ type: String, attribute: "locale" })
], n.prototype, "locale", 2);
a([
l({ type: Number, attribute: "scale-strength" })
], n.prototype, "scaleStrength", 2);
a([
l({ type: Number, attribute: "reflection-angle" })
], n.prototype, "reflectionAngle", 2);
a([
l({ type: Number, attribute: "reflection-size" })
], n.prototype, "reflectionSize", 2);
a([
l({ type: Number, attribute: "reflection-opacity" })
], n.prototype, "reflectionOpacity", 2);
a([
l({ type: Number, attribute: "highlight-from" })
], n.prototype, "highlightFrom", 2);
a([
l({ type: Number, attribute: "highlight-width" })
], n.prototype, "highlightWidth", 2);
a([
l()
], n.prototype, "min", 2);
a([
l()
], n.prototype, "max", 2);
a([
l({ type: Number })
], n.prototype, "duration", 2);
a([
l({ type: Number })
], n.prototype, "progress", 2);
a([
E()
], n.prototype, "data", 2);
a([
E()
], n.prototype, "hoverPosition", 2);
n = a([
j("audiodn-waveform")
], n);
function Z() {
const t = this.hoverPosition !== null && this.duration > 0 ? q(this.hoverPosition * this.duration) : null;
return N`
<div class="waveform-container"
@mouseenter=${this} @mouseleave=${this} @mousemove=${this}
@touchstart=${(i) => this.handleTouch(i)}
@touchmove=${(i) => this.handleTouch(i)}
@touchend=${(i) => this.handleTouch(i)}
>
<canvas @click=${this} role="img" aria-label=${L(this.locale, "waveform.aria")}></canvas>
<div class="playhead progress-playhead"></div>
<div class="playhead hover-playhead"></div>
${t !== null ? N`
<div class="hover-tooltip" style="left: ${this.hoverPosition * 100}%">${t}</div>
` : ""}
</div>
`;
}
function J() {
return V`
:host {
width: 100%;
position: relative;
display: flex;
justify-content: center;
height: 100%;
box-sizing: border-box;
background: var(--adn-waveform-bg);
border: var(--adn-waveform-border);
border-radius: var(--adn-waveform-radius);
padding: var(--adn-waveform-padding);
}
.waveform-container {
width: 100%;
position: relative;
--_transitionSpeed: 100ms;
touch-action: none;
}
.click-overlay {
position: absolute;
inset: 0;
height: 100%;
cursor: pointer;
z-index: 1000;
}
canvas {
width: 100%;
height: 100%;
mask: linear-gradient(to right,
rgba(255 255 255 / 0.5) var(--_pre-progress),
rgba(255 255 255 / 1) var(--_pre-progress),
rgba(255 255 255 / 1) var(--_width),
rgba(255 255 255 / 0.5) var(--_width)
);
}
.playhead {
width: var(--adn-waveform-playhead-width, 1px);
background: var(--adn-waveform-color-playhead, var(--_color-font));
height: 100%;
position: absolute;
inset-block: 0;
pointer-events: none;
}
.progress-playhead {
left: var(--_playheadPosition);
opacity: var(--_playheadVisible, 0);
}
.hover-playhead {
left: var(--_hoverPosition);
opacity: calc(0.5 * var(--_hoverVisible, 0));
}
.hover-tooltip {
position: absolute;
top: -24px;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.85);
color: #fff;
font-size: 11px;
padding: 2px 6px;
border-radius: 3px;
pointer-events: none;
white-space: nowrap;
font-family: sans-serif;
}
`;
}
export {
n as A,
et as a,
it as b,
q as f
};
+4
-0

@@ -12,2 +12,6 @@ import { LitElement } from 'lit';

buffering: boolean;
/** Playback progress (0..1) for the optional ring. Only shown when `showProgress`. */
progress: number;
/** When true, draw a circular progress ring around the button (inline player). */
showProgress: boolean;
locale: Locale;

@@ -14,0 +18,0 @@ static styles: import("lit").CSSResult;

import { LitElement } from 'lit';
import { type Locale } from '../lib/i18n.js';
import { type AudioDevice } from '../lib/media-devices.js';
import type { CSSResult, TemplateResult } from 'lit';

@@ -13,4 +14,8 @@ import type { TrackVariant } from '../lib/track.js';

protected isOpen: boolean;
protected outputs: AudioDevice[];
protected selectedOutputId: string;
static styles: CSSResult;
private get variantCount();
get showOutputPicker(): boolean;
get showVariantSection(): boolean;
get hasMenu(): boolean;

@@ -21,3 +26,8 @@ render(): TemplateResult;

updated(changedProperties: Map<string, unknown>): void;
connectedCallback(): void;
disconnectedCallback(): void;
refreshOutputs(): Promise<void>;
private readonly onDeviceChange;
private readonly onOutputChange;
outputLabel(device: AudioDevice, index: number): string;
handleEvent(event: Event): void;

@@ -24,0 +34,0 @@ protected handleKeydown(e: KeyboardEvent): void;

+1
-1
import { AudioDnPlayer as e } from "./player.js";
import { AudiodnUploader as f } from "./uploader.js";
import { A as p } from "./shared/waveform-DjrtM6Eb.js";
import { A as p } from "./shared/waveform-BkawXg58.js";
import { AudiodnRecorder as a } from "./recorder.js";

@@ -5,0 +5,0 @@ export {

export declare const LOCALES: readonly ["en", "fr", "es", "de"];
export type Locale = (typeof LOCALES)[number];
export declare const DEFAULT_LOCALE: Locale;
export type MessageKey = 'action.retry' | 'action.reload' | 'player.notify.loadFailed' | 'player.notify.sessionExpired' | 'player.notify.noSession' | 'player.notify.trackLoadFailed' | 'player.notify.playFailed' | 'player.aria.loading' | 'player.loadingText' | 'player.aria.region' | 'player.status.playbackError' | 'player.status.buffering' | 'player.status.nowPlaying' | 'playButton.retry' | 'playButton.loading' | 'playButton.pause' | 'playButton.play' | 'progress.aria.label' | 'progress.aria.valueText' | 'playTime.aria' | 'volume.aria' | 'settings.aria' | 'settings.download' | 'settings.notDownloadable' | 'trackTitle.none' | 'coverArt.none' | 'coverArt.alt' | 'tracklist.aria' | 'waveform.aria' | 'notification.dismiss' | 'uploader.notify.sessionExpired' | 'uploader.notify.uploadSuccess' | 'uploader.notify.uploadFailed' | 'uploader.notify.networkError' | 'uploader.notify.uploadFailedDetail' | 'uploader.notify.noAudioFiles' | 'uploader.notify.limitExceeded' | 'uploader.error.tryAgain' | 'uploader.aria.loading' | 'uploader.loadingText' | 'uploader.aria.fileArea' | 'uploader.dropHeading' | 'uploader.or' | 'uploader.browseFiles' | 'uploader.aria.selectFiles' | 'uploader.aria.totalProgress' | 'uploader.totalProgressText' | 'uploader.aria.queue' | 'uploader.aria.fileProgress' | 'uploader.aria.retryFile' | 'uploader.aria.cancelUpload' | 'uploader.aria.removeFile' | 'recorder.notify.sessionExpired' | 'recorder.notify.uploadSuccess' | 'recorder.notify.uploadFailed' | 'recorder.notify.networkError' | 'recorder.notify.uploadFailedDetail' | 'recorder.notify.micDenied' | 'recorder.notify.micUnavailable' | 'recorder.notify.maxDuration' | 'recorder.error.tryAgain' | 'recorder.aria.loading' | 'recorder.loadingText' | 'recorder.aria.region' | 'recorder.aria.start' | 'recorder.aria.pause' | 'recorder.aria.resume' | 'recorder.aria.stop' | 'recorder.aria.discard' | 'recorder.aria.send' | 'recorder.aria.cancelUpload' | 'recorder.aria.play' | 'recorder.aria.pausePreview' | 'recorder.aria.progress' | 'recorder.aria.done' | 'recorder.aria.cancelCountdown' | 'recorder.timer.preview' | 'recorder.idle.hint' | 'recorder.countdown.hint' | 'recorder.aria.selectMic' | 'recorder.device.unnamed' | 'recorder.device.menuLabel' | 'recorder.aria.moreOptions' | 'recorder.menu.preview' | 'recorder.menu.stopPreview' | 'recorder.menu.delete' | 'recorder.menu.stopUpload';
export type MessageKey = 'action.retry' | 'action.reload' | 'player.notify.loadFailed' | 'player.notify.sessionExpired' | 'player.notify.noSession' | 'player.notify.trackLoadFailed' | 'player.notify.playFailed' | 'player.aria.loading' | 'player.loadingText' | 'player.aria.region' | 'player.status.playbackError' | 'player.status.buffering' | 'player.status.nowPlaying' | 'playButton.retry' | 'playButton.loading' | 'playButton.pause' | 'playButton.play' | 'progress.aria.label' | 'progress.aria.valueText' | 'playTime.aria' | 'volume.aria' | 'settings.aria' | 'settings.download' | 'settings.notDownloadable' | 'settings.output.menuLabel' | 'settings.output.unnamed' | 'trackTitle.none' | 'coverArt.none' | 'coverArt.alt' | 'tracklist.aria' | 'waveform.aria' | 'notification.dismiss' | 'uploader.notify.sessionExpired' | 'uploader.notify.uploadSuccess' | 'uploader.notify.uploadFailed' | 'uploader.notify.networkError' | 'uploader.notify.uploadFailedDetail' | 'uploader.notify.noAudioFiles' | 'uploader.notify.limitExceeded' | 'uploader.error.tryAgain' | 'uploader.aria.loading' | 'uploader.loadingText' | 'uploader.aria.fileArea' | 'uploader.dropHeading' | 'uploader.or' | 'uploader.browseFiles' | 'uploader.aria.selectFiles' | 'uploader.aria.totalProgress' | 'uploader.totalProgressText' | 'uploader.aria.queue' | 'uploader.aria.fileProgress' | 'uploader.aria.retryFile' | 'uploader.aria.cancelUpload' | 'uploader.aria.removeFile' | 'recorder.notify.sessionExpired' | 'recorder.notify.uploadSuccess' | 'recorder.notify.uploadFailed' | 'recorder.notify.networkError' | 'recorder.notify.uploadFailedDetail' | 'recorder.notify.micDenied' | 'recorder.notify.micUnavailable' | 'recorder.notify.maxDuration' | 'recorder.error.tryAgain' | 'recorder.aria.loading' | 'recorder.loadingText' | 'recorder.aria.region' | 'recorder.aria.start' | 'recorder.aria.pause' | 'recorder.aria.resume' | 'recorder.aria.stop' | 'recorder.aria.discard' | 'recorder.aria.send' | 'recorder.aria.cancelUpload' | 'recorder.aria.play' | 'recorder.aria.pausePreview' | 'recorder.aria.progress' | 'recorder.aria.done' | 'recorder.aria.cancelCountdown' | 'recorder.timer.preview' | 'recorder.idle.hint' | 'recorder.countdown.hint' | 'recorder.aria.selectMic' | 'recorder.device.unnamed' | 'recorder.device.menuLabel' | 'recorder.aria.moreOptions' | 'recorder.menu.preview' | 'recorder.menu.stopPreview' | 'recorder.menu.delete' | 'recorder.menu.stopUpload';
type Messages = Record<MessageKey, string>;

@@ -6,0 +6,0 @@ export declare const catalogs: Readonly<Record<Locale, Readonly<Messages>>>;

@@ -26,2 +26,5 @@ import './components/cover-art.js';

size: string;
variant: 'default' | 'inline';
/** Play-button size (px) for the `inline` variant. Ignored otherwise. */
height?: number;
theme: Theme;

@@ -70,2 +73,6 @@ locale: Locale;

protected updated(changedProperties: Map<string, unknown>): void;
/** Square play-button edge (px) for the inline variant, clamped to a sane minimum. */
inlineButtonSize(): number;
/** Absolute playback fraction (0..1) of the active track, for the inline ring. */
inlineProgress(): number;
private getEffectiveTheme;

@@ -102,2 +109,3 @@ private loadSession;

handleUIChangeVolume(event: CustomEvent): void;
handleUISelectOutput(event: CustomEvent<string>): void;
protected handleKeydown(e: KeyboardEvent): void;

@@ -104,0 +112,0 @@ calculateCurrentTime(desiredTime: number | undefined, rawTime: boolean): number;

@@ -8,3 +8,3 @@ import { LitElement } from 'lit';

export type Theme = 'auto' | 'dark' | 'light';
export type RecorderVariant = 'panel' | 'regular' | 'tiny';
export type RecorderVariant = 'panel' | 'regular' | 'inline';
export type RecorderMode = 'idle' | 'countdown' | 'recording' | 'preview' | 'uploading' | 'done';

@@ -37,3 +37,3 @@ declare global {

variant: RecorderVariant;
/** Button size (px) for the `tiny` variant. Buttons are square (width = height). */
/** Button size (px) for the `inline` variant. Buttons are square (width = height). */
height: number;

@@ -64,4 +64,4 @@ sessionData?: UploadSessionData;

_deviceMenuOpen: boolean;
/** Transient failure flag: shows a red warning glyph in the tiny variant. */
_tinyError: boolean;
/** Transient failure flag: shows a red warning glyph in the inline variant. */
_inlineError: boolean;
private _mediaStream;

@@ -78,3 +78,3 @@ private _mediaRecorder;

private _doneTimer?;
private _tinyErrorTimer?;
private _inlineErrorTimer?;
private _maxDurationTimer?;

@@ -85,2 +85,4 @@ private _sessionTimer;

private _onDeviceChange;
private _onInputChange;
private _onOutputChange;
private _onDocPointerDown;

@@ -121,16 +123,16 @@ private _onRepositionDeviceMenu;

/** True for the compact, two-button layout. */
isTiny(): boolean;
/** Square button edge (px) for the tiny variant, clamped to a sane minimum. */
tinyButtonSize(): number;
isInline(): boolean;
/** Square button edge (px) for the inline variant, clamped to a sane minimum. */
inlineButtonSize(): number;
/** True when more than one mic is available and we are idle (picker is interactive). */
showDevicePicker(): boolean;
/** True when the tiny variant shows its contextual menu (preview or upload). */
/** True when the inline variant shows its contextual menu (preview or upload). */
showContextMenu(): boolean;
/** Any state in which the popover menu is allowed to open. */
canOpenMenu(): boolean;
/** Close the menu, then toggle preview playback (tiny contextual action). */
/** Close the menu, then toggle preview playback (inline contextual action). */
menuTogglePreview(): void;
/** Close the menu, then discard the recording (tiny contextual action). */
/** Close the menu, then discard the recording (inline contextual action). */
menuDelete(): void;
/** Close the menu, then cancel the in-flight upload (tiny contextual action). */
/** Close the menu, then cancel the in-flight upload (inline contextual action). */
menuCancelUpload(): void;

@@ -196,6 +198,6 @@ deviceLabel(device: {

/**
* Show a transient red warning glyph in the tiny variant (which suppresses the
* Show a transient red warning glyph in the inline variant (which suppresses the
* notification banner because it's too small to read inside a compact control).
*/
private flashTinyError;
private flashInlineError;
private resetToIdle;

@@ -202,0 +204,0 @@ handleMicClick(): void;

import { n as c, r as h, i as m, a as v, b as d, t as g } from "./shared/lit-DpNjQO9d.js";
import { t as f, S as b, a as y, p as _, i as x, g as w, q as u, b as k, d as $, r as E, n as T, o as S } from "./shared/color-C5w9LHXC.js";
import { t as a } from "./shared/i18n-CIM9pdy9.js";
import { t as f, S as b, a as y, p as _, i as x, g as w, q as u, b as k, d as $, r as E, n as T, o as S } from "./shared/color-BrgTYjY_.js";
import { t as a } from "./shared/i18n-BI0dP23M.js";
var C = Object.defineProperty, U = Object.getOwnPropertyDescriptor, l = (e, r, t, i) => {

@@ -5,0 +5,0 @@ for (var o = i > 1 ? void 0 : i ? U(r, t) : r, n = e.length - 1, p; n >= 0; n--)

import "./shared/lit-DpNjQO9d.js";
import { A as p } from "./shared/waveform-DjrtM6Eb.js";
import "./shared/i18n-CIM9pdy9.js";
import { A as p } from "./shared/waveform-BkawXg58.js";
import "./shared/i18n-BI0dP23M.js";
export {
p as AudioDnWaveform
};
{
"name": "@audiodn/components",
"version": "0.3.1",
"version": "0.4.0",
"description": "Custom web components for Audio Delivery Network",

@@ -5,0 +5,0 @@ "type": "module",

@@ -110,3 +110,5 @@ # AudioDN Components

| `variants` | string | `""` | Comma-separated variant indexes to request, in priority order — the **first is selected by default**. e.g. `"hq,lq"`. |
| `size` | string | `large` | Layout preset. Values: `small`, `regular`, `large`. |
| `size` | string | `large` | Layout preset for the `default` variant. Values: `small`, `regular`, `large`. |
| `variant` | string | `default` | Layout variant. `default` is the full player (cover art, title, waveform, controls, tracklist). `inline` is a compact play/pause button — with a circular progress ring that fills clockwise from the top — plus the settings menu, and shows no track information (surface it yourself). |
| `height` | number | `56` | `inline` variant only. Edge size (px) of the square play/pause button. |
| `locale` | string | `en` | UI language. Values: `en`, `fr`, `es`, `de`. |

@@ -233,4 +235,4 @@ | `volume` | number | `0.7` | Initial volume, `0`–`1`. Persisted to `sessionStorage` after the user changes it. |

| `auto-hide` | boolean | `false` | After a successful upload, sets the host to `display: none`. |
| `variant` | string | `panel` | Layout preset. `panel` (a.k.a. `regular`) is the full panel with waveform, timers, and separate controls. `tiny` is a compact two-button layout: a record button (with a source menu when more than one mic is available) that animates while recording, then a confirm button plus a contextual preview/delete menu. |
| `height` | number | `56` | `tiny` variant only. Edge size (px) of the square icon buttons; all tiny buttons share this size. |
| `variant` | string | `panel` | Layout preset. `panel` (a.k.a. `regular`) is the full panel with waveform, timers, and separate controls. `inline` is a compact two-button layout: a record button (with a source menu when more than one mic is available) that animates while recording, then a confirm button plus a contextual preview/delete menu. |
| `height` | number | `56` | `inline` variant only. Edge size (px) of the square icon buttons; all inline buttons share this size. |

@@ -237,0 +239,0 @@ ### Events

import { w as d, n as E, r as U, i as b, a as I, b as y, t as R } from "./lit-DpNjQO9d.js";
import { t as V } from "./i18n-CIM9pdy9.js";
function D(t) {
if (!t || typeof t != "object") return !1;
const e = t.url;
return !(typeof e != "string" || !e.trim() || /\/(null|undefined)(?:\/|$)/i.test(e));
}
function A(t) {
if (!t || typeof t != "object") return;
const e = t, n = {};
let o = !1;
for (const r of ["icon", "small", "regular", "large"]) {
const i = e[r];
D(i) && (n[r] = {
height: Number(i.height) || 0,
type: String(i.type || ""),
url: i.url.trim(),
width: Number(i.width) || 0
}, o = !0);
}
return o ? n : void 0;
}
const ct = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/></svg>`, lt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>`, pt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 5V2L7 7l5 5V8a5 5 0 1 1-4.9 6h-2.05A7 7 0 1 0 12 5z"/></svg>`, dt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l9.5 16.5H2.5L12 3z"/><path d="M12 10v4"/><path d="M12 17.5v.01"/></svg>`, ut = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M475.8 175.3c3 8 .4 16.8-5.9 22.5l-39.6 36a176.6 176.6 0 0 1 0 46.5l39.6 36a20.7 20.7 0 0 1 5.9 22.5c-4 10.9-9 21.3-14.5 31.3l-4.3 7.4c-6 10.1-12.8 19.6-20.2 28.6a20.8 20.8 0 0 1-22.5 6.2l-51-16.2a176.3 176.3 0 0 1-40.3 23.2l-11.4 52.2a20.7 20.7 0 0 1-16.7 16.3 237 237 0 0 1-77.9 0c-8.4-1.4-14.8-8-16.6-16.3l-11.5-52.2a179 179 0 0 1-40.3-23.2l-51 16.3a21 21 0 0 1-22.4-6.2c-7.4-9-14.2-18.5-20.2-28.6l-4.3-7.4a234 234 0 0 1-14.5-31.3c-3-8-.4-16.9 5.9-22.5l39.6-36a179 179 0 0 1 0-46.6l-39.6-36a20.7 20.7 0 0 1-5.9-22.5c4-10.9 9-21.3 14.5-31.3l4.3-7.5c6-10 12.8-19.5 20.2-28.5a20.8 20.8 0 0 1 22.5-6.2l51 16.2A176.3 176.3 0 0 1 189 94.8l11.4-52.2a20.7 20.7 0 0 1 16.7-16.3 227.5 227.5 0 0 1 77.9-.1c8.4 1.4 14.8 8 16.6 16.3l11.5 52.2a179 179 0 0 1 40.3 23.2l51-16.2c8-2.5 17-.3 22.4 6.2 7.5 9 14.2 18.5 20.3 28.6l4.3 7.4c5.6 10 10.4 20.4 14.5 31.3l-.1.1ZM256 330a73 73 0 1 0 0-146 73 73 0 0 0 0 146Z"/></svg>`, mt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M267.6 64.4A27.8 27.8 0 0 1 284 89.7v332.6a27.8 27.8 0 0 1-46.1 20.7L121 339H62.4A55.5 55.5 0 0 1 7 283.7v-55.4a55.5 55.5 0 0 1 55.4-55.5h58.7L237.9 69c8.1-7.3 19.8-9 29.7-4.6Zm107.8 114.7 47.6 47.6 47.6-47.6a20.8 20.8 0 0 1 29.3 29.3L452.3 256l47.6 47.6a20.8 20.8 0 0 1-29.3 29.3L423 285.3 375.4 333a20.8 20.8 0 0 1-29.3-29.3l47.6-47.6-47.6-47.6a20.8 20.8 0 0 1 29.3-29.3Z"/></svg>`, ft = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M279.8 64.4A27.8 27.8 0 0 1 296 89.7v332.6a28 28 0 0 1-16.2 25.3 27.3 27.3 0 0 1-29.6-4.6l-116-104H76c-30.3 0-55-24.8-55-55.4v-55.4a55.3 55.3 0 0 1 55-55.5h58.3L250.2 69c8-7.3 19.7-9 29.6-4.6Zm149 62.3a166 166 0 0 1 0 257.6 20.8 20.8 0 0 1-26.1-32.2 124.4 124.4 0 0 0 0-193.2 20.8 20.8 0 0 1 26.1-32.2Zm-52.6 65a82.7 82.7 0 0 1 0 128.6 21 21 0 0 1-29.5-3c-7.3-8.9-6-22 3-29.2a41.2 41.2 0 0 0 0-64.3 20.7 20.7 0 0 1-3-29.2 21.1 21.1 0 0 1 29.5-3v.1Z"/></svg>`, ht = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M280.8 64.4A27.8 27.8 0 0 1 297 89.7v332.6a28 28 0 0 1-16.2 25.3 27.3 27.3 0 0 1-29.6-4.6l-116-104H77c-30.3 0-55-24.8-55-55.4v-55.4a55.3 55.3 0 0 1 55-55.5h58.3L251.2 69c8-7.3 19.7-9 29.6-4.6Zm96.4 127.3a82.7 82.7 0 0 1 0 128.6 21 21 0 0 1-29.5-3c-7.3-8.9-6-22 3-29.2a41.2 41.2 0 0 0 0-64.3 20.7 20.7 0 0 1-3-29.2 21.1 21.1 0 0 1 29.5-3v.1Z"/></svg>`, gt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M96 480a32 32 0 1 1 0-64h320a32 32 0 1 1 0 64H96Zm182.6-137.4a32 32 0 0 1-45.3 0l-128-128a32 32 0 0 1 45.3-45.3l73.4 73.4V64a32 32 0 1 1 64 0v178.7l73.4-73.4a32 32 0 0 1 45.3 45.3l-128 128h-.1Z"/></svg>`, vt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M242.7 165.4h.1a22 22 0 0 1 6.5 4.6l45.4 45.2a22 22 0 0 1-31.1 31.2l-7.8-7.8v83.6a22 22 0 0 1-44 0v-83.6l-7.8 7.8a22 22 0 0 1-30.8.2l-.3-.3a22 22 0 0 1 0-31l45.3-45.3a22.1 22.1 0 0 1 .7-.7h.1l.4-.5h.2c1.6-1.5 3.4-2.6 5.3-3.4l.3-.1a22.2 22.2 0 0 1 7.6-1.7h.1a17.8 17.8 0 0 1 1.2 0h-.3a22.4 22.4 0 0 1 .9 0h.7c2.6.2 5 .8 7.3 1.8Z"/><path d="M199.1 21c68.5 0 131 35 167.3 91.1l.1.3h2a153.7 153.7 0 0 1 143.5 151v2.5c0 46.4-20.7 89.6-55.8 118.6a28.5 28.5 0 0 1-36.3-43.8A96.8 96.8 0 0 0 358.4 169c-15 0-29-7.9-36.7-20.9A142 142 0 0 0 57 220.3 142 142 0 0 0 98.5 321 28.4 28.4 0 1 1 58 361 199.2 199.2 0 0 1 199 21Z"/></svg>`, wt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.49 6-3.31 6-6.72h-1.7z"/></svg>`, xt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h12v12H6z"/></svg>`, yt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>`;
d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>`;
const bt = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>`, _t = d`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg>`, H = { VITE_API_URL: "https://api.audiodelivery.net" }, F = H, f = F?.VITE_API_URL;
class m extends Error {
constructor(e, n) {
super(e), this.name = "ApiError", this.status = n;
}
}
const S = 1, N = 1e3;
async function h(t, e) {
let n = null;
for (let o = 0; o <= S; o++)
try {
return await fetch(t, e);
} catch (r) {
n = r instanceof Error ? r : new Error(String(r)), o < S && await new Promise((i) => setTimeout(i, N * Math.pow(2, o)));
}
throw n || new m("Network request failed", 0);
}
async function g(t, e, n) {
return n();
}
function v(t, e = {}) {
return t ? {
...e,
headers: {
...e.headers,
"Accept-Language": t
}
} : e;
}
async function Z(t, e, n, o, r, i, s) {
const a = `/v1/play_session/${e}`;
return g("POST", a, async () => {
const l = `${f}${a}`, c = await h(l, v(i, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${t}`
},
body: JSON.stringify({
[`${e}_id`]: n,
variants: o,
...r && { expires_in: r },
// Requested download intent; the API key is the authoritative gate and
// the server stores (key AND this) on the session.
...s && { is_downloadable: !0 }
})
})), p = await c.json();
if (!c.ok || !p.ok)
throw new m(p.message || "Failed to create play session", c.status);
if (!p.tracks?.length)
throw new m("No tracks found in session", c.status);
const x = {
ok: p.ok,
playSessionId: p.play_session_id,
expiresAt: new Date(p.expires_at),
playSession: u(p.play_session),
tracks: []
};
x.playSession.expiresAt = new Date(x.playSession.expiresAt);
for (const O of p.tracks)
x.tracks.push(u(O));
return p.first_track && (x.firstTrack = B(p.first_track)), x;
});
}
async function G(t, e) {
const n = `/v1/play_session/${t}`;
return g("GET", n, async () => {
const o = `${f}${n}`, r = await h(o, v(e)), i = await r.json();
if (!r.ok || !i.ok)
throw new m(i.message || "Failed to fetch play session", r.status);
if (!i.tracks?.length)
throw new m("No tracks found in session", r.status);
const s = {
ok: i.ok,
playSessionId: i.play_session_id,
expiresAt: new Date(i.expires_at || i.play_session.expires_at),
playSession: u(i.play_session),
tracks: []
};
s.playSession.expiresAt = new Date(s.playSession.expiresAt);
for (const a of i.tracks)
s.tracks.push(u(a));
return i.first_track && (s.firstTrack = B(i.first_track)), s;
});
}
async function kt(t, e, n) {
const o = `/v1/play/${t}/${e}`;
return g("GET", o, async () => {
const r = `${f}${o}`, i = await h(r, v(n)), s = await i.json();
if (!i.ok || !s.ok)
throw new m(s.message || "Failed to fetch track data", i.status);
return {
ok: s.ok,
playSessionId: s.play_session_id,
trackId: s.track_id,
playSession: u(s.play_session),
track: u(s.track),
levels: u(s.levels),
variants: z(s.variants),
coverImage: A(u(s.cover_image))
};
});
}
async function St(t, e, n, o) {
const r = `/v1/play/${t}/${e}/${encodeURIComponent(String(n).toLowerCase())}/download`;
return g("GET", r, async () => {
const i = `${f}${r}`, s = await h(i, v(o)), a = await s.json();
if (!s.ok || !a?.ok)
throw new m(a?.message || "Failed to fetch download URL", s.status);
return a;
});
}
async function Tt(t, e, n) {
const o = "/v1/upload_session";
return g("POST", o, async () => {
const r = `${f}${o}`, i = {};
e && (i.collection_id = e);
const s = await h(r, v(n, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${t}`
},
body: JSON.stringify(i)
})), a = await s.json();
if (!s.ok || !a?.ok)
throw new m(a?.message || "Failed to create upload session", s.status);
return a;
});
}
async function $t(t, e, n, o, r) {
const i = "/v1/upload_session";
return g("POST", i, async () => {
const s = `${f}${i}`, a = { file_name: n };
o?.player_title && (a.player_title = o.player_title), o?.player_subtitle && (a.player_subtitle = o.player_subtitle), o?.player_color && (a.player_color = o.player_color), o?.metadata && (a.metadata = o.metadata), o?.organization_index && (a.organization_index = o.organization_index);
const l = { track: a };
e && (l.collection_id = e);
const c = await h(s, v(r, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${t}`
},
body: JSON.stringify(l)
})), p = await c.json();
if (!c.ok || !p?.ok)
throw new m(p?.message || "Failed to create upload session with track", c.status);
if (!p.track_id || !p.track_upload?.upload_url)
throw new m("Upload session created but track upload URL was missing", c.status);
return p;
});
}
async function Ct(t, e) {
const n = `/v1/upload_session/${t}`;
return g("GET", n, async () => {
const o = `${f}${n}`, r = await h(o, v(e)), i = await r.json();
if (!r.ok || !i?.ok)
throw new m(i?.message || "Failed to fetch upload session", r.status);
return i;
});
}
async function Mt(t, e, n, o) {
const r = `/v1/upload/${t}/track`;
return g("POST", r, async () => {
const i = `${f}${r}`, s = await h(i, v(o, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
file_name: e,
file_size: n
})
})), a = await s.json();
if (!s.ok || !a?.ok)
throw new m(a?.message || "Failed to get upload URL", s.status);
return a;
});
}
function z(t) {
return t.map((e) => {
const n = u(e);
return e.data !== null && (n.isPreview = !0, n.preview = {
offsetStart: e.data.capture_start,
offsetEnd: e.data.capture_end,
duration: e.data.duration
}), n;
});
}
function B(t) {
return {
ok: !0,
playSessionId: "",
trackId: t.track_id,
playSession: {},
track: u(t.track),
levels: u(t.levels),
variants: z(t.variants),
coverImage: A(u(t.cover_image))
};
}
function T(t) {
return t.toLowerCase().replace(/([-_][a-z])/g, function(e) {
return e.toUpperCase().replace("-", "").replace("_", "");
});
}
function u(t) {
if (t == null) return t;
const e = {};
for (const [n, o] of Object.entries(t)) {
if (o != null && o.constructor === Object) {
e[T(n)] = u(o);
continue;
}
Object.hasOwn(t, n) && (e[T(n)] = o);
}
return e;
}
var W = Object.defineProperty, Y = Object.getOwnPropertyDescriptor, _ = (t, e, n, o) => {
for (var r = o > 1 ? void 0 : o ? Y(e, n) : e, i = t.length - 1, s; i >= 0; i--)
(s = t[i]) && (r = (o ? s(e, n, r) : s(r)) || r);
return o && r && W(e, n, r), r;
};
const P = 180, J = {
error: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M15 9l-6 6M9 9l6 6"/></svg>`,
warning: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l9.5 16.5H2.5L12 3z"/><path d="M12 10v4"/><path d="M12 17.5v.01"/></svg>`,
info: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5"/><path d="M12 8v.01"/></svg>`,
success: d`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M8.5 12.5l2.5 2.5 4.5-5"/></svg>`
};
let w = class extends I {
constructor() {
super(...arguments), this.duration = 5e3, this.locale = "en", this.notifications = [], this.nextId = 0;
}
add(t, e, n = {}) {
const o = n.duration ?? (t === "error" || t === "warning" ? 0 : this.duration), r = this.notifications.find((c) => !c.dismissing && c.type === t && c.message === e);
if (r)
return r.timeout && clearTimeout(r.timeout), r.action = n.action, o > 0 && (r.timeout = setTimeout(() => this.dismiss(r.id), o)), this.notifications = [...this.notifications], r.id;
const i = this.nextId++, s = { id: i, type: t, message: e, action: n.action };
o > 0 && (s.timeout = setTimeout(() => this.dismiss(i), o));
const a = [...this.notifications, s];
this.notifications = a.length > 4 ? a.slice(a.length - 4) : a;
const l = t === "error" ? "adn-error" : t === "success" ? "adn-success" : `adn-${t}`;
return this.dispatchEvent(new CustomEvent(l, {
detail: { message: e },
bubbles: !0,
composed: !0
})), i;
}
dismiss(t) {
const e = this.notifications.find((n) => n.id === t);
!e || e.dismissing || (e.timeout && clearTimeout(e.timeout), e.dismissing = !0, this.notifications = [...this.notifications], setTimeout(() => {
this.notifications = this.notifications.filter((n) => n.id !== t);
}, P));
}
clear() {
for (const t of this.notifications)
t.timeout && clearTimeout(t.timeout);
this.notifications = [];
}
runAction(t) {
t.action?.onClick(), this.dismiss(t.id);
}
disconnectedCallback() {
super.disconnectedCallback(), this.clear();
}
render() {
return this.notifications.length === 0 ? y`` : y`
<div class="notification-stack">
${[...this.notifications].reverse().map((t) => y`
<div
class="notification notification-${t.type} ${t.dismissing ? "is-dismissing" : ""}"
role=${t.type === "error" || t.type === "warning" ? "alert" : "status"}
aria-live=${t.type === "error" || t.type === "warning" ? "assertive" : "polite"}
>
<span class="notification-icon">${J[t.type]}</span>
<span class="notification-message">${t.message}</span>
${t.action ? y`
<button class="notification-action" @click=${() => this.runAction(t)}>${t.action.label}</button>
` : ""}
<button class="notification-dismiss" @click=${() => this.dismiss(t.id)} aria-label=${V(this.locale, "notification.dismiss")}>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>
</button>
</div>
`)}
</div>
`;
}
};
w.styles = q();
_([
E({ type: Number })
], w.prototype, "duration", 2);
_([
E({ type: String, attribute: "locale" })
], w.prototype, "locale", 2);
_([
U()
], w.prototype, "notifications", 2);
w = _([
R("audiodn-notification")
], w);
function q() {
return b`
.notification-stack {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 9999;
display: flex;
flex-direction: column;
gap: var(--adn-notification-gap, 6px);
padding: var(--adn-notification-padding, 6px);
pointer-events: none;
}
.notification {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
border-radius: var(--adn-notification-radius, 8px);
font-size: var(--adn-notification-font-size, var(--step--1, 0.833rem));
font-family: var(--adn-font-family, sans-serif);
line-height: 1.3;
color: var(--_notif-fg, #fff);
background: var(--_notif-bg);
box-shadow: var(--adn-notification-box-shadow, 0 4px 14px rgba(0, 0, 0, 0.35));
pointer-events: auto;
animation: notif-in 200ms cubic-bezier(0.16, 1, 0.3, 1);
}
.notification.is-dismissing {
animation: notif-out ${P}ms ease-in forwards;
pointer-events: none;
}
.notification-error {
--_notif-bg: var(--adn-notification-bg-error, #dc2626);
}
.notification-warning {
--_notif-bg: var(--adn-notification-bg-warning, #d97706);
}
.notification-info {
--_notif-bg: var(--adn-notification-bg-info, #2563eb);
}
.notification-success {
--_notif-bg: var(--adn-notification-bg-success, #16a34a);
}
.notification-icon {
display: inline-flex;
flex-shrink: 0;
}
.notification-icon svg {
width: 1.15em;
height: 1.15em;
}
.notification-message {
flex: 1;
min-width: 0;
}
.notification-action {
flex-shrink: 0;
appearance: none;
border: 1px solid currentColor;
background: transparent;
color: inherit;
font: inherit;
font-weight: 600;
padding: 3px 10px;
border-radius: 999px;
cursor: pointer;
opacity: 0.95;
transition: background-color 120ms ease, opacity 120ms ease;
}
.notification-action:hover {
background: rgba(255, 255, 255, 0.18);
opacity: 1;
}
.notification-dismiss {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
appearance: none;
border: none;
background: transparent;
color: inherit;
cursor: pointer;
padding: 2px;
opacity: 0.7;
transition: opacity 120ms ease;
}
.notification-dismiss svg {
width: 1em;
height: 1em;
}
.notification-dismiss:hover {
opacity: 1;
}
@keyframes notif-in {
from { opacity: 0; transform: translateY(-8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes notif-out {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
.notification,
.notification.is-dismissing {
animation-duration: 1ms;
}
}
`;
}
const Et = b`
/* @link https://utopia.fyi/type/calculator?c=320,16,1.2,1240,18,1.25,5,3,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
/* Step -3: 9.2593px → 9.216px */
--step--3: clamp(0.576rem, 0.5796rem + -0.0047vw, 0.5787rem);
/* Step -2: 11.1111px → 11.52px */
--step--2: clamp(0.6944rem, 0.6856rem + 0.0444vw, 0.72rem);
/* Step -1: 13.3333px → 14.4px */
--step--1: clamp(0.8333rem, 0.8101rem + 0.1159vw, 0.9rem);
/* Step 0: 16px → 18px */
--step-0: clamp(1rem, 0.9565rem + 0.2174vw, 1.125rem);
/* Step 1: 19.2px → 22.5px */
--step-1: clamp(1.2rem, 1.1283rem + 0.3587vw, 1.4063rem);
/* Step 2: 23.04px → 28.125px */
--step-2: clamp(1.44rem, 1.3295rem + 0.5527vw, 1.7578rem);
/* Step 3: 27.648px → 35.1563px */
--step-3: clamp(1.728rem, 1.5648rem + 0.8161vw, 2.1973rem);
/* @link https://utopia.fyi/space/calculator?c=320,16,1.2,1240,18,1.25,5,1,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
/* Space 3xs: 4px → 5px */
--space-3xs: clamp(0.25rem, 0.2283rem + 0.1087vw, 0.3125rem);
/* Space 2xs: 8px → 9px */
--space-2xs: clamp(0.5rem, 0.4783rem + 0.1087vw, 0.5625rem);
/* Space xs: 12px → 14px */
--space-xs: clamp(0.75rem, 0.7065rem + 0.2174vw, 0.875rem);
/* Space s: 16px → 18px */
--space-s: clamp(1rem, 0.9565rem + 0.2174vw, 1.125rem);
/* Space m: 24px → 27px */
--space-m: clamp(1.5rem, 1.4348rem + 0.3261vw, 1.6875rem);
/* Space l: 32px → 36px */
--space-l: clamp(2rem, 1.913rem + 0.4348vw, 2.25rem);
/* Space xl: 48px → 54px */
--space-xl: clamp(3rem, 2.8696rem + 0.6522vw, 3.375rem);
/* Space 2xl: 64px → 72px */
--space-2xl: clamp(4rem, 3.8261rem + 0.8696vw, 4.5rem);
/* Space 3xl: 96px → 108px */
--space-3xl: clamp(6rem, 5.7391rem + 1.3043vw, 6.75rem);
/* One-up pairs */
/* Space 3xs-2xs: 4px → 9px */
--space-3xs-2xs: clamp(0.25rem, 0.1413rem + 0.5435vw, 0.5625rem);
/* Space 2xs-xs: 8px → 14px */
--space-2xs-xs: clamp(0.5rem, 0.3696rem + 0.6522vw, 0.875rem);
/* Space xs-s: 12px → 18px */
--space-xs-s: clamp(0.75rem, 0.6196rem + 0.6522vw, 1.125rem);
/* Space s-m: 16px → 27px */
--space-s-m: clamp(1rem, 0.7609rem + 1.1957vw, 1.6875rem);
/* Space m-l: 24px → 36px */
--space-m-l: clamp(1.5rem, 1.2391rem + 1.3043vw, 2.25rem);
/* Space l-xl: 32px → 54px */
--space-l-xl: clamp(2rem, 1.5217rem + 2.3913vw, 3.375rem);
/* Space xl-2xl: 48px → 72px */
--space-xl-2xl: clamp(3rem, 2.4783rem + 2.6087vw, 4.5rem);
/* Space 2xl-3xl: 64px → 108px */
--space-2xl-3xl: clamp(4rem, 3.0435rem + 4.7826vw, 6.75rem);
/* Custom pairs */
/* Space s-l: 16px → 36px */
--space-s-l: clamp(1rem, 0.5652rem + 2.1739vw, 2.25rem);
/* --adn-volume-width: clamp(3.125rem, -0.4464rem + 17.8571vw, 6.25rem); */
`, At = b`
:host([theme="light"]) {
--_bg: var(--adn-bg, #f4f4f5);
--_bg-light: var(--adn-bg-light, #e4e4e7);
--_color-font: var(--adn-color-font, #1c1c1e);
--_color-font-muted: var(--adn-color-font-muted, #52525b);
--_border-color: var(--adn-border-color, #d4d4d8);
--_color-highlight: var(--adn-color-highlight, rgba(0, 0, 0, 0.06));
/* Darker greyscale accent so controls read on the light background. */
--_color-accent: var(--adn-color-accent, #52525b);
--_color-accent-rgb: var(--adn-color-accent-rgb, 82, 82, 91);
}
@media (prefers-color-scheme: light) {
:host([theme="auto"]) {
--_bg: var(--adn-bg, #f4f4f5);
--_bg-light: var(--adn-bg-light, #e4e4e7);
--_color-font: var(--adn-color-font, #1c1c1e);
--_color-font-muted: var(--adn-color-font-muted, #52525b);
--_border-color: var(--adn-border-color, #d4d4d8);
--_color-highlight: var(--adn-color-highlight, rgba(0, 0, 0, 0.06));
--_color-accent: var(--adn-color-accent, #52525b);
--_color-accent-rgb: var(--adn-color-accent-rgb, 82, 82, 91);
}
}
`, zt = b`
*, *:before, *:after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
interpolate-size: allow-keywords;
}
img,canvas, svg {
display: block;
max-width: 100%;
}
input, button {
font: inherit;
}
`, X = 3e4;
async function Bt({
playSessionId: t,
id: e,
apiKey: n,
scope: o,
variants: r,
sessionTtl: i,
locale: s,
downloadable: a
}) {
if (t)
try {
const c = await G(t, s);
if (c)
return c;
} catch (c) {
if (!(n && o && e))
throw new Error("failed to fetch session", { cause: c });
}
if (!n)
throw new Error("apiKey must be provided");
if (!o)
throw new Error("scope must be provided");
if (!e)
throw new Error("id must be provided");
if (!r.length)
throw new Error("no variants provided");
const l = await Z(n, o, e, r, i, s, a);
if (!l)
throw new Error("failed to load session data");
return l.tracks = l.tracks.sort((c, p) => c.order - p.order).map((c, p) => (c.order = p + 1, c)), l;
}
class Pt {
constructor() {
this._warningTimer = null, this._expiryTimer = null;
}
schedule(e, n) {
this.clear();
const o = Date.now(), i = e.getTime() - o, s = i - X;
if (i <= 0) {
n.onExpiry();
return;
}
s <= 0 ? n.onWarning() : this._warningTimer = setTimeout(n.onWarning, s), this._expiryTimer = setTimeout(n.onExpiry, i);
}
clear() {
this._warningTimer !== null && (clearTimeout(this._warningTimer), this._warningTimer = null), this._expiryTimer !== null && (clearTimeout(this._expiryTimer), this._expiryTimer = null);
}
}
const K = { r: 244, g: 244, b: 245 }, Q = { r: 0, g: 0, b: 0 }, $ = 3, tt = 0.02, L = (t, e, n) => Math.min(n, Math.max(e, t));
function j(t) {
if (typeof t != "string") return null;
let e = t.trim().replace(/^#/, "");
return e.length === 3 && (e = e.split("").map((n) => n + n).join("")), /^[0-9a-fA-F]{6}$/.test(e) ? {
r: parseInt(e.substring(0, 2), 16),
g: parseInt(e.substring(2, 4), 16),
b: parseInt(e.substring(4, 6), 16)
} : null;
}
function et({ r: t, g: e, b: n }) {
const o = (r) => L(Math.round(r), 0, 255).toString(16).padStart(2, "0");
return `#${o(t)}${o(e)}${o(n)}`;
}
function ot({ r: t, g: e, b: n }) {
const o = t / 255, r = e / 255, i = n / 255, s = Math.max(o, r, i), a = Math.min(o, r, i), l = s - a;
let c = 0;
l !== 0 && (s === o ? c = (r - i) / l % 6 : s === r ? c = (i - o) / l + 2 : c = (o - r) / l + 4, c *= 60, c < 0 && (c += 360));
const p = s === 0 ? 0 : l / s;
return { h: c, s: p, v: s };
}
function C({ h: t, s: e, v: n }) {
const o = n * e, r = o * (1 - Math.abs(t / 60 % 2 - 1)), i = n - o;
let s = 0, a = 0, l = 0;
return t < 60 ? (s = o, a = r, l = 0) : t < 120 ? (s = r, a = o, l = 0) : t < 180 ? (s = 0, a = o, l = r) : t < 240 ? (s = 0, a = r, l = o) : t < 300 ? (s = r, a = 0, l = o) : (s = o, a = 0, l = r), {
r: (s + i) * 255,
g: (a + i) * 255,
b: (l + i) * 255
};
}
function k({ r: t, g: e, b: n }) {
const o = [t / 255, e / 255, n / 255].map((r) => r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4));
return 0.2126 * o[0] + 0.7152 * o[1] + 0.0722 * o[2];
}
function M(t, e) {
const n = k(t), o = k(e), r = Math.max(n, o), i = Math.min(n, o);
return (r + 0.05) / (i + 0.05);
}
function Lt(t, e = 0.179) {
const n = j(t);
return n ? k(n) <= e : !0;
}
function nt(t, e, n) {
let { v: o } = t, r = C({ ...t, v: o });
if (M(r, e) >= $) return r;
for (let i = 0; i < 60 && (o = L(o + n * tt, 0, 1), r = C({ ...t, v: o }), !(M(r, e) >= $ || o === 0 || o === 1)); i++)
;
return r;
}
function rt(t, e) {
const n = j(t);
if (!n) return null;
const o = ot(n);
return et(nt(o, e === "light" ? K : Q, e === "light" ? -1 : 1));
}
const it = "#71717a";
function jt(t) {
return rt(it, t) ?? (t === "light" ? "#52525b" : "#a1a1aa");
}
export {
gt as A,
Bt as B,
m as C,
kt as D,
jt as E,
Pt as S,
rt as a,
Mt as b,
$t as c,
dt as d,
bt as e,
xt as f,
Ct as g,
wt as h,
Lt as i,
yt as j,
ct as k,
lt as l,
_t as m,
zt as n,
Et as o,
j as p,
Tt as q,
vt as r,
D as s,
At as t,
pt as u,
mt as v,
ft as w,
ht as x,
St as y,
ut as z
};
const d = ["en", "fr", "es", "de"];
const n = {
"action.retry": "Retry",
"action.reload": "Reload",
"player.notify.loadFailed": "Couldn’t load the player.",
"player.notify.sessionExpired": "Your session expired.",
"player.notify.noSession": "No play session available",
"player.notify.trackLoadFailed": "Couldn’t load this track.",
"player.notify.playFailed": "Couldn’t play this track.",
"player.aria.loading": "Loading audio player",
"player.loadingText": "Loading audio player…",
"player.aria.region": "Audio player",
"player.status.playbackError": "Playback error",
"player.status.buffering": "Buffering",
"player.status.nowPlaying": "Now playing: {title}",
"playButton.retry": "Retry",
"playButton.loading": "Loading",
"playButton.pause": "Pause",
"playButton.play": "Play",
"progress.aria.label": "Playback progress",
"progress.aria.valueText": "{current} of {total}",
"playTime.aria": "Playback time: {elapsed} of {total}",
"volume.aria": "Volume",
"settings.aria": "Settings",
"settings.download": "Download {label}",
"settings.notDownloadable": "This track isn’t downloadable.",
"trackTitle.none": "No track selected",
"coverArt.none": "No cover art",
"coverArt.alt": "Cover art",
"tracklist.aria": "Track list",
"waveform.aria": "Audio waveform",
"notification.dismiss": "Dismiss notification",
"uploader.notify.sessionExpired": "Your upload session expired.",
"uploader.notify.uploadSuccess": "{filename} uploaded successfully",
"uploader.notify.uploadFailed": "{filename}: upload failed",
"uploader.notify.networkError": "{filename}: network error",
"uploader.notify.uploadFailedDetail": "{filename}: {error}",
"uploader.notify.noAudioFiles": "No audio files detected. Please select audio files.",
"uploader.notify.limitExceeded": "You can upload at most {limit} file(s).",
"uploader.error.tryAgain": "Try again",
"uploader.aria.loading": "Loading uploader",
"uploader.loadingText": "Loading…",
"uploader.aria.fileArea": "File upload area",
"uploader.dropHeading": "Drop Audio Tracks To Collection",
"uploader.or": "or",
"uploader.browseFiles": "Browse Files",
"uploader.aria.selectFiles": "Select audio files to upload",
"uploader.aria.totalProgress": "Total upload progress",
"uploader.totalProgressText": "{percent}% total",
"uploader.aria.queue": "Upload queue",
"uploader.aria.fileProgress": "Upload progress for {filename}",
"uploader.aria.retryFile": "Retry upload for {filename}",
"uploader.aria.cancelUpload": "Cancel upload for {filename}",
"uploader.aria.removeFile": "Remove file {filename}",
"recorder.notify.sessionExpired": "Your upload session expired.",
"recorder.notify.uploadSuccess": "Recording uploaded successfully",
"recorder.notify.uploadFailed": "Upload failed",
"recorder.notify.networkError": "Network error during upload",
"recorder.notify.uploadFailedDetail": "Upload failed: {error}",
"recorder.notify.micDenied": "Microphone access was denied.",
"recorder.notify.micUnavailable": "Microphone is not available.",
"recorder.notify.maxDuration": "Maximum recording length reached.",
"recorder.error.tryAgain": "Try again",
"recorder.aria.loading": "Loading recorder",
"recorder.loadingText": "Loading…",
"recorder.aria.region": "Voice recorder",
"recorder.aria.start": "Start recording",
"recorder.aria.pause": "Pause recording",
"recorder.aria.resume": "Resume recording",
"recorder.aria.stop": "Stop recording",
"recorder.aria.discard": "Discard recording",
"recorder.aria.send": "Confirm recording",
"recorder.aria.cancelCountdown": "Cancel countdown",
"recorder.idle.hint": "Tap to record",
"recorder.countdown.hint": "Get ready…",
"recorder.aria.selectMic": "Select microphone",
"recorder.device.unnamed": "Microphone {n}",
"recorder.device.menuLabel": "Microphones",
"recorder.aria.moreOptions": "More options",
"recorder.menu.preview": "Preview",
"recorder.menu.stopPreview": "Stop preview",
"recorder.menu.delete": "Delete",
"recorder.menu.stopUpload": "Stop upload",
"recorder.aria.cancelUpload": "Cancel upload",
"recorder.aria.play": "Play recording",
"recorder.aria.pausePreview": "Pause playback",
"recorder.aria.progress": "Upload progress",
"recorder.aria.done": "Upload complete",
"recorder.timer.preview": "{current}/{total}"
}, t = {
"action.retry": "Réessayer",
"action.reload": "Recharger",
"player.notify.loadFailed": "Impossible de charger le lecteur.",
"player.notify.sessionExpired": "Votre session a expiré.",
"player.notify.noSession": "Aucune session de lecture disponible",
"player.notify.trackLoadFailed": "Impossible de charger cette piste.",
"player.notify.playFailed": "Impossible de lire cette piste.",
"player.aria.loading": "Chargement du lecteur audio",
"player.loadingText": "Chargement du lecteur audio…",
"player.aria.region": "Lecteur audio",
"player.status.playbackError": "Erreur de lecture",
"player.status.buffering": "Mise en mémoire tampon",
"player.status.nowPlaying": "Lecture en cours : {title}",
"playButton.retry": "Réessayer",
"playButton.loading": "Chargement",
"playButton.pause": "Pause",
"playButton.play": "Lecture",
"progress.aria.label": "Progression de la lecture",
"progress.aria.valueText": "{current} sur {total}",
"playTime.aria": "Temps de lecture : {elapsed} sur {total}",
"volume.aria": "Volume",
"settings.aria": "Paramètres",
"settings.download": "Télécharger {label}",
"settings.notDownloadable": "Cette piste n’est pas téléchargeable.",
"trackTitle.none": "Aucune piste sélectionnée",
"coverArt.none": "Pas de pochette",
"coverArt.alt": "Pochette",
"tracklist.aria": "Liste des pistes",
"waveform.aria": "Forme d’onde audio",
"notification.dismiss": "Ignorer la notification",
"uploader.notify.sessionExpired": "Votre session de téléversement a expiré.",
"uploader.notify.uploadSuccess": "{filename} téléversé avec succès",
"uploader.notify.uploadFailed": "{filename} : échec du téléversement",
"uploader.notify.networkError": "{filename} : erreur réseau",
"uploader.notify.uploadFailedDetail": "{filename} : {error}",
"uploader.notify.noAudioFiles": "Aucun fichier audio détecté. Veuillez sélectionner des fichiers audio.",
"uploader.notify.limitExceeded": "Vous ne pouvez téléverser que {limit} fichier(s).",
"uploader.error.tryAgain": "Réessayer",
"uploader.aria.loading": "Chargement du téléverseur",
"uploader.loadingText": "Chargement…",
"uploader.aria.fileArea": "Zone de téléversement de fichiers",
"uploader.dropHeading": "Déposez des pistes audio dans la collection",
"uploader.or": "ou",
"uploader.browseFiles": "Parcourir les fichiers",
"uploader.aria.selectFiles": "Sélectionner des fichiers audio à téléverser",
"uploader.aria.totalProgress": "Progression totale du téléversement",
"uploader.totalProgressText": "{percent}% au total",
"uploader.aria.queue": "File de téléversement",
"uploader.aria.fileProgress": "Progression du téléversement pour {filename}",
"uploader.aria.retryFile": "Réessayer le téléversement pour {filename}",
"uploader.aria.cancelUpload": "Annuler le téléversement pour {filename}",
"uploader.aria.removeFile": "Retirer le fichier {filename}",
"recorder.notify.sessionExpired": "Votre session de téléversement a expiré.",
"recorder.notify.uploadSuccess": "Enregistrement téléversé avec succès",
"recorder.notify.uploadFailed": "Échec du téléversement",
"recorder.notify.networkError": "Erreur réseau pendant le téléversement",
"recorder.notify.uploadFailedDetail": "Échec du téléversement : {error}",
"recorder.notify.micDenied": "L’accès au microphone a été refusé.",
"recorder.notify.micUnavailable": "Le microphone n’est pas disponible.",
"recorder.notify.maxDuration": "Durée maximale d’enregistrement atteinte.",
"recorder.error.tryAgain": "Réessayer",
"recorder.aria.loading": "Chargement de l’enregistreur",
"recorder.loadingText": "Chargement…",
"recorder.aria.region": "Enregistreur vocal",
"recorder.aria.start": "Démarrer l’enregistrement",
"recorder.aria.pause": "Mettre en pause",
"recorder.aria.resume": "Reprendre l’enregistrement",
"recorder.aria.stop": "Arrêter l’enregistrement",
"recorder.aria.discard": "Supprimer l’enregistrement",
"recorder.aria.send": "Confirmer l’enregistrement",
"recorder.aria.cancelCountdown": "Annuler le compte à rebours",
"recorder.idle.hint": "Appuyez pour enregistrer",
"recorder.countdown.hint": "Préparez-vous…",
"recorder.aria.selectMic": "Choisir le microphone",
"recorder.device.unnamed": "Microphone {n}",
"recorder.device.menuLabel": "Microphones",
"recorder.aria.moreOptions": "Plus d’options",
"recorder.menu.preview": "Écouter",
"recorder.menu.stopPreview": "Arrêter l’écoute",
"recorder.menu.delete": "Supprimer",
"recorder.menu.stopUpload": "Arrêter l’envoi",
"recorder.aria.cancelUpload": "Annuler le téléversement",
"recorder.aria.play": "Lire l’enregistrement",
"recorder.aria.pausePreview": "Mettre la lecture en pause",
"recorder.aria.progress": "Progression du téléversement",
"recorder.aria.done": "Téléversement terminé",
"recorder.timer.preview": "{current}/{total}"
}, s = {
"action.retry": "Reintentar",
"action.reload": "Recargar",
"player.notify.loadFailed": "No se pudo cargar el reproductor.",
"player.notify.sessionExpired": "Tu sesión ha expirado.",
"player.notify.noSession": "No hay sesión de reproducción disponible",
"player.notify.trackLoadFailed": "No se pudo cargar esta pista.",
"player.notify.playFailed": "No se pudo reproducir esta pista.",
"player.aria.loading": "Cargando el reproductor de audio",
"player.loadingText": "Cargando el reproductor de audio…",
"player.aria.region": "Reproductor de audio",
"player.status.playbackError": "Error de reproducción",
"player.status.buffering": "Almacenando en búfer",
"player.status.nowPlaying": "Reproduciendo: {title}",
"playButton.retry": "Reintentar",
"playButton.loading": "Cargando",
"playButton.pause": "Pausa",
"playButton.play": "Reproducir",
"progress.aria.label": "Progreso de reproducción",
"progress.aria.valueText": "{current} de {total}",
"playTime.aria": "Tiempo de reproducción: {elapsed} de {total}",
"volume.aria": "Volumen",
"settings.aria": "Ajustes",
"settings.download": "Descargar {label}",
"settings.notDownloadable": "Esta pista no se puede descargar.",
"trackTitle.none": "Ninguna pista seleccionada",
"coverArt.none": "Sin carátula",
"coverArt.alt": "Carátula",
"tracklist.aria": "Lista de pistas",
"waveform.aria": "Forma de onda de audio",
"notification.dismiss": "Descartar notificación",
"uploader.notify.sessionExpired": "Tu sesión de subida ha expirado.",
"uploader.notify.uploadSuccess": "{filename} subido correctamente",
"uploader.notify.uploadFailed": "{filename}: error al subir",
"uploader.notify.networkError": "{filename}: error de red",
"uploader.notify.uploadFailedDetail": "{filename}: {error}",
"uploader.notify.noAudioFiles": "No se detectaron archivos de audio. Selecciona archivos de audio.",
"uploader.notify.limitExceeded": "Solo puedes subir {limit} archivo(s).",
"uploader.error.tryAgain": "Intentar de nuevo",
"uploader.aria.loading": "Cargando el cargador",
"uploader.loadingText": "Cargando…",
"uploader.aria.fileArea": "Área de subida de archivos",
"uploader.dropHeading": "Suelta pistas de audio en la colección",
"uploader.or": "o",
"uploader.browseFiles": "Explorar archivos",
"uploader.aria.selectFiles": "Selecciona archivos de audio para subir",
"uploader.aria.totalProgress": "Progreso total de subida",
"uploader.totalProgressText": "{percent}% en total",
"uploader.aria.queue": "Cola de subida",
"uploader.aria.fileProgress": "Progreso de subida de {filename}",
"uploader.aria.retryFile": "Reintentar la subida de {filename}",
"uploader.aria.cancelUpload": "Cancelar la subida de {filename}",
"uploader.aria.removeFile": "Quitar el archivo {filename}",
"recorder.notify.sessionExpired": "Tu sesión de subida ha expirado.",
"recorder.notify.uploadSuccess": "Grabación subida correctamente",
"recorder.notify.uploadFailed": "Error al subir",
"recorder.notify.networkError": "Error de red durante la subida",
"recorder.notify.uploadFailedDetail": "Error al subir: {error}",
"recorder.notify.micDenied": "Se denegó el acceso al micrófono.",
"recorder.notify.micUnavailable": "El micrófono no está disponible.",
"recorder.notify.maxDuration": "Se alcanzó la duración máxima de grabación.",
"recorder.error.tryAgain": "Intentar de nuevo",
"recorder.aria.loading": "Cargando el grabador",
"recorder.loadingText": "Cargando…",
"recorder.aria.region": "Grabador de voz",
"recorder.aria.start": "Iniciar grabación",
"recorder.aria.pause": "Pausar grabación",
"recorder.aria.resume": "Reanudar grabación",
"recorder.aria.stop": "Detener grabación",
"recorder.aria.discard": "Descartar grabación",
"recorder.aria.send": "Confirmar grabación",
"recorder.aria.cancelCountdown": "Cancelar cuenta atrás",
"recorder.idle.hint": "Toca para grabar",
"recorder.countdown.hint": "Prepárate…",
"recorder.aria.selectMic": "Seleccionar micrófono",
"recorder.device.unnamed": "Micrófono {n}",
"recorder.device.menuLabel": "Micrófonos",
"recorder.aria.moreOptions": "Más opciones",
"recorder.menu.preview": "Escuchar",
"recorder.menu.stopPreview": "Detener escucha",
"recorder.menu.delete": "Eliminar",
"recorder.menu.stopUpload": "Detener subida",
"recorder.aria.cancelUpload": "Cancelar subida",
"recorder.aria.play": "Reproducir grabación",
"recorder.aria.pausePreview": "Pausar reproducción",
"recorder.aria.progress": "Progreso de subida",
"recorder.aria.done": "Subida completa",
"recorder.timer.preview": "{current}/{total}"
}, c = {
"action.retry": "Wiederholen",
"action.reload": "Neu laden",
"player.notify.loadFailed": "Player konnte nicht geladen werden.",
"player.notify.sessionExpired": "Ihre Sitzung ist abgelaufen.",
"player.notify.noSession": "Keine Wiedergabesitzung verfügbar",
"player.notify.trackLoadFailed": "Dieser Titel konnte nicht geladen werden.",
"player.notify.playFailed": "Dieser Titel konnte nicht abgespielt werden.",
"player.aria.loading": "Audio-Player wird geladen",
"player.loadingText": "Audio-Player wird geladen…",
"player.aria.region": "Audio-Player",
"player.status.playbackError": "Wiedergabefehler",
"player.status.buffering": "Puffern",
"player.status.nowPlaying": "Wird abgespielt: {title}",
"playButton.retry": "Wiederholen",
"playButton.loading": "Wird geladen",
"playButton.pause": "Pause",
"playButton.play": "Abspielen",
"progress.aria.label": "Wiedergabefortschritt",
"progress.aria.valueText": "{current} von {total}",
"playTime.aria": "Wiedergabezeit: {elapsed} von {total}",
"volume.aria": "Lautstärke",
"settings.aria": "Einstellungen",
"settings.download": "{label} herunterladen",
"settings.notDownloadable": "Dieser Titel kann nicht heruntergeladen werden.",
"trackTitle.none": "Kein Titel ausgewählt",
"coverArt.none": "Kein Cover",
"coverArt.alt": "Cover",
"tracklist.aria": "Titelliste",
"waveform.aria": "Audio-Wellenform",
"notification.dismiss": "Benachrichtigung schließen",
"uploader.notify.sessionExpired": "Ihre Upload-Sitzung ist abgelaufen.",
"uploader.notify.uploadSuccess": "{filename} erfolgreich hochgeladen",
"uploader.notify.uploadFailed": "{filename}: Upload fehlgeschlagen",
"uploader.notify.networkError": "{filename}: Netzwerkfehler",
"uploader.notify.uploadFailedDetail": "{filename}: {error}",
"uploader.notify.noAudioFiles": "Keine Audiodateien erkannt. Bitte wählen Sie Audiodateien aus.",
"uploader.notify.limitExceeded": "Sie können höchstens {limit} Datei(en) hochladen.",
"uploader.error.tryAgain": "Erneut versuchen",
"uploader.aria.loading": "Uploader wird geladen",
"uploader.loadingText": "Wird geladen…",
"uploader.aria.fileArea": "Datei-Upload-Bereich",
"uploader.dropHeading": "Audiotitel in die Sammlung ziehen",
"uploader.or": "oder",
"uploader.browseFiles": "Dateien durchsuchen",
"uploader.aria.selectFiles": "Audiodateien zum Hochladen auswählen",
"uploader.aria.totalProgress": "Gesamter Upload-Fortschritt",
"uploader.totalProgressText": "{percent}% gesamt",
"uploader.aria.queue": "Upload-Warteschlange",
"uploader.aria.fileProgress": "Upload-Fortschritt für {filename}",
"uploader.aria.retryFile": "Upload für {filename} wiederholen",
"uploader.aria.cancelUpload": "Upload für {filename} abbrechen",
"uploader.aria.removeFile": "Datei {filename} entfernen",
"recorder.notify.sessionExpired": "Ihre Upload-Sitzung ist abgelaufen.",
"recorder.notify.uploadSuccess": "Aufnahme erfolgreich hochgeladen",
"recorder.notify.uploadFailed": "Upload fehlgeschlagen",
"recorder.notify.networkError": "Netzwerkfehler während des Uploads",
"recorder.notify.uploadFailedDetail": "Upload fehlgeschlagen: {error}",
"recorder.notify.micDenied": "Mikrofonzugriff wurde verweigert.",
"recorder.notify.micUnavailable": "Mikrofon ist nicht verfügbar.",
"recorder.notify.maxDuration": "Maximale Aufnahmedauer erreicht.",
"recorder.error.tryAgain": "Erneut versuchen",
"recorder.aria.loading": "Recorder wird geladen",
"recorder.loadingText": "Wird geladen…",
"recorder.aria.region": "Sprachrekorder",
"recorder.aria.start": "Aufnahme starten",
"recorder.aria.pause": "Aufnahme pausieren",
"recorder.aria.resume": "Aufnahme fortsetzen",
"recorder.aria.stop": "Aufnahme beenden",
"recorder.aria.discard": "Aufnahme verwerfen",
"recorder.aria.send": "Aufnahme bestätigen",
"recorder.aria.cancelCountdown": "Countdown abbrechen",
"recorder.idle.hint": "Tippen zum Aufnehmen",
"recorder.countdown.hint": "Bereit machen…",
"recorder.aria.selectMic": "Mikrofon auswählen",
"recorder.device.unnamed": "Mikrofon {n}",
"recorder.device.menuLabel": "Mikrofone",
"recorder.aria.moreOptions": "Weitere Optionen",
"recorder.menu.preview": "Anhören",
"recorder.menu.stopPreview": "Anhören stoppen",
"recorder.menu.delete": "Löschen",
"recorder.menu.stopUpload": "Upload stoppen",
"recorder.aria.cancelUpload": "Upload abbrechen",
"recorder.aria.play": "Aufnahme abspielen",
"recorder.aria.pausePreview": "Wiedergabe pausieren",
"recorder.aria.progress": "Upload-Fortschritt",
"recorder.aria.done": "Upload abgeschlossen",
"recorder.timer.preview": "{current}/{total}"
}, u = { en: n, fr: t, es: s, de: c };
function p(r) {
if (!r) return "en";
const e = r.toLowerCase().split("-")[0];
return d.includes(e ?? "") ? e : "en";
}
function f(r, e, a) {
const l = p(r ?? void 0);
let o = u[l][e] ?? n[e] ?? e;
if (a)
for (const i of Object.keys(a))
o = o.split(`{${i}}`).join(String(a[i]));
return o;
}
export {
f as t
};
import { n as l, r as E, i as V, a as X, b as N, t as j } from "./lit-DpNjQO9d.js";
import { t as L } from "./i18n-CIM9pdy9.js";
function q(t) {
if (t === void 0) return "--:--";
const i = Math.floor(t / 60) || 0, o = Math.round(t % 60) || 0;
return `${i}:${("" + o).padStart(2, "0")}`;
}
function et(t) {
if (t === void 0) return "0s";
const i = Math.floor(t / 60) || 0, o = Math.round(t % 60) || 0;
return [
i && i + "m",
o && o + "s"
].join(" ");
}
function it(t, i = 2) {
if (!+t) return "0 Bytes";
const o = 1e3, s = i < 0 ? 0 : i, e = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], r = Math.floor(Math.log(t) / Math.log(o));
return `${parseFloat((t / Math.pow(o, r)).toFixed(s))} ${e[r]}`;
}
let z, _, P, M, W, $, R, C, S;
const T = [];
function I(t, i) {
return _ = window.pageXOffset, M = window.pageYOffset, $ = window.innerHeight, C = window.innerWidth, P === void 0 && (P = _), W === void 0 && (W = M), S === void 0 && (S = C), R === void 0 && (R = $), (i || M !== W || _ !== P || $ !== R || C !== S) && (Y(t), P = _, W = M, R = $, S = C), requestAnimationFrame(I);
}
function Y(t) {
for (const i of T)
i({ x: _, y: M, px: P, py: W, vh: $, pvh: R, vw: C, pvw: S }, t);
}
function G(t) {
return T.indexOf(t) < 0 && T.push(t), z = z || I(performance.now()), {
update() {
return I(performance.now(), !0), this;
},
destroy() {
T.splice(T.indexOf(t), 1);
}
};
}
var U = Object.defineProperty, K = Object.getOwnPropertyDescriptor, a = (t, i, o, s) => {
for (var e = s > 1 ? void 0 : s ? K(i, o) : i, r = t.length - 1, c; r >= 0; r--)
(c = t[r]) && (e = (s ? c(i, o, e) : c(e)) || e);
return s && e && U(i, o, e), e;
};
let n = class extends X {
constructor() {
super(...arguments), this.levels = [], this.height = 120, this.lineColor = "#888888", this.lineWidth = 2, this.gap = 3, this.variant = "vertical", this.locale = "en", this.scaleStrength = 0.4, this.reflectionAngle = 45, this.reflectionSize = 0.25, this.reflectionOpacity = 0.55, this.highlightFrom = 0, this.highlightWidth = 1, this.min = 0, this.max = 1, this.duration = 0, this.progress = 0, this.data = new Float32Array(), this.hoverPosition = null, this.containerWidth = 0, this.canvas = null, this.ctx = null, this._srrafHandle = null, this._drawScheduled = !1, this._hoverRafId = null, this._cachedRect = null, this.draw = () => {
if (!this.canvas || !this.ctx) return;
const { lineWidth: t, gap: i, height: o, variant: s } = this, e = this.ctx, r = Math.max(1, window.devicePixelRatio || 1), c = this.canvas.clientWidth || this.getRect().width, v = Math.max(1, Math.round(c * r)), h = Math.max(1, Math.round(o * r));
this.canvas.width = v, this.canvas.height = h;
const u = t + i, O = Math.floor(
(c - t - (s === "wavy" ? u : 0)) / u
) + 1, b = [];
for (let d = 0; d < O; d++) {
const p = Math.round(d / O * this.data.length);
b.push(this.data[p]);
}
e.clearRect(0, 0, v, h), e.fillStyle = this.lineColor, e.strokeStyle = this.lineColor;
const k = Math.max(1, Math.round(t * r)), D = u * r;
if (s === "vertical")
b.forEach((d, p) => {
if (!d) return;
const g = Math.round(p * D), f = Math.round(d * h), y = Math.round((h - f) / 2);
e.fillRect(g, y, k, f);
});
else if (s === "reflection") {
const d = Math.max(0, this.reflectionSize), p = Math.round(h / (1 + d)), g = h - p, f = p, m = (0.5 - Math.max(0, Math.min(1, this.progress))) * 2 * (this.reflectionAngle * Math.PI / 180), A = Math.tan(m);
e.fillStyle = this.lineColor, b.forEach((w, H) => {
if (!w) return;
const F = Math.round(H * D), x = Math.round(w * p);
e.fillRect(F, f - x, k, x);
});
const B = e.createLinearGradient(0, f, 0, f + g);
B.addColorStop(0, this.colorToRgba(this.lineColor, this.reflectionOpacity)), B.addColorStop(0.75, this.colorToRgba(this.lineColor, this.reflectionOpacity * 0.5)), B.addColorStop(1, this.colorToRgba(this.lineColor, 0)), e.strokeStyle = B, e.lineWidth = k, b.forEach((w, H) => {
if (!w) return;
const F = Math.round(H * D) + k / 2, x = w * g;
e.beginPath(), e.moveTo(F, f), e.lineTo(F + A * x, f + x), e.stroke();
});
} else if (s === "wavy") {
e.scale(r, r), e.lineWidth = this.lineWidth, e.save();
const d = o / 2;
e.translate(0, d);
const p = c / b.length;
for (const [g, f] of b.entries()) {
if (!f) continue;
const y = g * u + Math.ceil(t / 2) + 0.5;
let m = f * (d - this.lineWidth * 2);
m < 0 ? m = 0 : m > d - this.lineWidth * 2 && (m = d - this.lineWidth * 2);
const A = (g + 1) % 2 ? m : -m;
e.beginPath(), e.moveTo(y, 0), e.lineTo(y, A), e.arc(
y + p / 2,
A,
Math.min(p / 2, Math.min(p / 2, m)),
Math.PI,
0,
!!((g + 1) % 2)
), e.lineTo(y + p, 0), e.stroke();
}
e.restore();
}
};
}
connectedCallback() {
super.connectedCallback(), this.updateLineColor(), this._srrafHandle = G(({ vw: t, pvw: i }) => {
t !== i && (this._cachedRect = null, this.computeWaveformWidth(), this.scheduleDraw());
});
}
disconnectedCallback() {
super.disconnectedCallback(), this._srrafHandle?.destroy(), this._srrafHandle = null, this._hoverRafId !== null && (cancelAnimationFrame(this._hoverRafId), this._hoverRafId = null);
}
willUpdate(t) {
this.style.setProperty("--_playheadPosition", this.progress * 100 + "%"), this.style.setProperty("--_playheadVisible", this.progress > 0 ? "1" : "0"), this.style.setProperty("--_hoverPosition", this.hoverPosition !== null ? this.hoverPosition * 100 + "%" : "0%"), this.style.setProperty("--_hoverVisible", this.hoverPosition !== null ? "1" : "0"), this.style.setProperty("--_highlightFrom", `${this.highlightFrom}px`), this.style.setProperty("--_maskWidth", `${Math.floor(this.containerWidth * this.highlightWidth)}px`), this.updateLineColor(), this.levels && t.has("levels") && this.processData();
}
render() {
return Z.call(this);
}
firstUpdated() {
this.canvas = this.renderRoot.querySelector("canvas"), this.canvas && (this.ctx = this.canvas.getContext("2d"));
}
updated() {
this.style.setProperty("--_pre-progress", `${this.min * 100}%`), this.max < 1 ? this.style.setProperty("--_width", `${this.max * 100}%`) : this.style.setProperty("--_width", `${this.progress * 100}%`), this.computeWaveformWidth(), this.scheduleDraw();
}
getRect() {
return this._cachedRect || (this._cachedRect = this.getBoundingClientRect()), this._cachedRect;
}
handleEvent(t) {
const i = t.currentTarget;
if (t.type === "mouseenter") {
i.style.setProperty("--_transitionSpeed", "0");
return;
}
if (t.type === "mouseleave") {
i.style.setProperty("--_transitionSpeed", "100ms"), this.hoverPosition = null;
return;
}
const o = this.getRect(), s = t.clientX - o.left;
if (s < 0 || s > this.containerWidth) {
this.hoverPosition = null;
return;
}
const e = Math.max(0, Math.min(1, s / this.containerWidth));
if (t.type === "mousemove") {
if (this._hoverRafId !== null) return;
this._hoverRafId = requestAnimationFrame(() => {
this._hoverRafId = null, this.hoverPosition = e;
});
}
t.type === "click" && this.dispatchEvent(
new CustomEvent("adni-seek", {
detail: { percent: e },
bubbles: !0
})
);
}
handleTouch(t) {
if (!(!t.touches.length && t.type !== "touchend")) {
if (t.type === "touchstart" || t.type === "touchmove") {
t.preventDefault();
const i = t.touches[0];
if (!i) return;
const o = this.getRect(), s = i.clientX - o.left, e = Math.max(0, Math.min(1, s / this.containerWidth));
this.hoverPosition = e;
}
t.type === "touchend" && (this.hoverPosition !== null && this.dispatchEvent(
new CustomEvent("adni-seek", {
detail: { percent: this.hoverPosition },
bubbles: !0
})
), this.hoverPosition = null);
}
}
computeWaveformWidth() {
this._cachedRect = null, this.containerWidth = this.getRect().width;
}
processData() {
const { levels: t, scaleStrength: i } = this;
if (!t || t.length === 0) {
this.data = new Float32Array();
return;
}
const o = Math.min(...t), e = Math.max(...t) - o;
let r = e === 0 ? t.map(() => 0.5) : t.map((h) => (h - o) / e), c = r.reduce((h, u) => h + u, 0) / t.length, v = 0;
for (; c > 1 - i && v < 10; )
r = r.map((h) => h * h), c = r.reduce((h, u) => h + u, 0) / t.length, v += 1;
this.data = new Float32Array(r);
}
// Normalize any CSS color to rgba() with the given alpha (via the canvas'
// own color parsing) so the reflection gradient can fade to transparent.
colorToRgba(t, i) {
const o = this.ctx;
if (!o) return `rgba(136, 136, 136, ${i})`;
o.fillStyle = "#000", o.fillStyle = t;
const s = o.fillStyle;
if (s.startsWith("#")) {
let r = s.slice(1);
r.length === 3 && (r = r.split("").map((u) => u + u).join(""));
const c = parseInt(r.slice(0, 2), 16), v = parseInt(r.slice(2, 4), 16), h = parseInt(r.slice(4, 6), 16);
return `rgba(${c}, ${v}, ${h}, ${i})`;
}
const e = s.match(/rgba?\(([^)]+)\)/);
if (e && e[1]) {
const [r, c, v] = e[1].split(",").map((h) => h.trim());
return `rgba(${r}, ${c}, ${v}, ${i})`;
}
return `rgba(136, 136, 136, ${i})`;
}
updateLineColor() {
const t = getComputedStyle(this), i = t.getPropertyValue("--adn-waveform-color-fg"), o = t.getPropertyValue("--adn-color-accent");
this.lineColor = i || o || t.getPropertyValue("--_color-accent");
}
scheduleDraw() {
this._drawScheduled || (this._drawScheduled = !0, requestAnimationFrame(() => {
this._drawScheduled = !1, this.draw();
}));
}
};
n.styles = J();
a([
l({ type: Array })
], n.prototype, "levels", 2);
a([
l({ type: Number })
], n.prototype, "height", 2);
a([
l({ type: String, attribute: "line-color" })
], n.prototype, "lineColor", 2);
a([
l({ type: Number, attribute: "line-width" })
], n.prototype, "lineWidth", 2);
a([
l({ type: Number })
], n.prototype, "gap", 2);
a([
l({ type: String })
], n.prototype, "variant", 2);
a([
l({ type: String, attribute: "locale" })
], n.prototype, "locale", 2);
a([
l({ type: Number, attribute: "scale-strength" })
], n.prototype, "scaleStrength", 2);
a([
l({ type: Number, attribute: "reflection-angle" })
], n.prototype, "reflectionAngle", 2);
a([
l({ type: Number, attribute: "reflection-size" })
], n.prototype, "reflectionSize", 2);
a([
l({ type: Number, attribute: "reflection-opacity" })
], n.prototype, "reflectionOpacity", 2);
a([
l({ type: Number, attribute: "highlight-from" })
], n.prototype, "highlightFrom", 2);
a([
l({ type: Number, attribute: "highlight-width" })
], n.prototype, "highlightWidth", 2);
a([
l()
], n.prototype, "min", 2);
a([
l()
], n.prototype, "max", 2);
a([
l({ type: Number })
], n.prototype, "duration", 2);
a([
l({ type: Number })
], n.prototype, "progress", 2);
a([
E()
], n.prototype, "data", 2);
a([
E()
], n.prototype, "hoverPosition", 2);
n = a([
j("audiodn-waveform")
], n);
function Z() {
const t = this.hoverPosition !== null && this.duration > 0 ? q(this.hoverPosition * this.duration) : null;
return N`
<div class="waveform-container"
@mouseenter=${this} @mouseleave=${this} @mousemove=${this}
@touchstart=${(i) => this.handleTouch(i)}
@touchmove=${(i) => this.handleTouch(i)}
@touchend=${(i) => this.handleTouch(i)}
>
<canvas @click=${this} role="img" aria-label=${L(this.locale, "waveform.aria")}></canvas>
<div class="playhead progress-playhead"></div>
<div class="playhead hover-playhead"></div>
${t !== null ? N`
<div class="hover-tooltip" style="left: ${this.hoverPosition * 100}%">${t}</div>
` : ""}
</div>
`;
}
function J() {
return V`
:host {
width: 100%;
position: relative;
display: flex;
justify-content: center;
height: 100%;
box-sizing: border-box;
background: var(--adn-waveform-bg);
border: var(--adn-waveform-border);
border-radius: var(--adn-waveform-radius);
padding: var(--adn-waveform-padding);
}
.waveform-container {
width: 100%;
position: relative;
--_transitionSpeed: 100ms;
touch-action: none;
}
.click-overlay {
position: absolute;
inset: 0;
height: 100%;
cursor: pointer;
z-index: 1000;
}
canvas {
width: 100%;
height: 100%;
mask: linear-gradient(to right,
rgba(255 255 255 / 0.5) var(--_pre-progress),
rgba(255 255 255 / 1) var(--_pre-progress),
rgba(255 255 255 / 1) var(--_width),
rgba(255 255 255 / 0.5) var(--_width)
);
}
.playhead {
width: var(--adn-waveform-playhead-width, 1px);
background: var(--adn-waveform-color-playhead, var(--_color-font));
height: 100%;
position: absolute;
inset-block: 0;
pointer-events: none;
}
.progress-playhead {
left: var(--_playheadPosition);
opacity: var(--_playheadVisible, 0);
}
.hover-playhead {
left: var(--_hoverPosition);
opacity: calc(0.5 * var(--_hoverVisible, 0));
}
.hover-tooltip {
position: absolute;
top: -24px;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.85);
color: #fff;
font-size: 11px;
padding: 2px 6px;
border-radius: 3px;
pointer-events: none;
white-space: nowrap;
font-family: sans-serif;
}
`;
}
export {
n as A,
et as a,
it as b,
q as f
};

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display