PluginProbe
Gutenberg / trunk
Gutenberg vtrunk
24.1.0 24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 All 404 releases
← All changes | build/modules/block-library/playlist/view.js +1497 -561 23.1.0 → trunk View file →
@@ -1,420 +1,563 @@
1 1 // packages/block-library/build-module/playlist/view.mjs
2 2 import { store, getContext, getElement } from "@wordpress/interactivity";
3 3
4 4 // node_modules/colord/index.mjs
5 -var r = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) };
6 -var t = function(r2) {
5 +for (r = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, t = function(r2) {
7 6 return "string" == typeof r2 ? r2.length > 0 : "number" == typeof r2;
8 -};
9 -var n = function(r2, t3, n2) {
10 - return void 0 === t3 && (t3 = 0), void 0 === n2 && (n2 = Math.pow(10, t3)), Math.round(n2 * r2) / n2 + 0;
11 -};
12 -var e = function(r2, t3, n2) {
13 - return void 0 === t3 && (t3 = 0), void 0 === n2 && (n2 = 1), r2 > n2 ? n2 : r2 > t3 ? r2 : t3;
14 -};
15 -var u = function(r2) {
16 - return (r2 = isFinite(r2) ? r2 % 360 : 0) > 0 ? r2 : r2 + 360;
17 -};
18 -var a = function(r2) {
19 - return { r: e(r2.r, 0, 255), g: e(r2.g, 0, 255), b: e(r2.b, 0, 255), a: e(r2.a) };
20 -};
21 -var o = function(r2) {
7 +}, n = function(r2, t2, n2) {
8 + return void 0 === t2 && (t2 = 0), void 0 === n2 && (n2 = Math.pow(10, t2)), Math.round(n2 * r2) / n2 + 0;
9 +}, u = function(r2, t2, n2) {
10 + return void 0 === t2 && (t2 = 0), void 0 === n2 && (n2 = 1), r2 > n2 ? n2 : r2 > t2 ? r2 : t2;
11 +}, e2 = function(r2) {
12 + return (r2 = isFinite(r2) ? r2 % 360 : 0) < 0 ? r2 + 360 : r2;
13 +}, o = function(r2, t2) {
14 + return void 0 === t2 && (t2 = 0), n(r2, t2) % 360;
15 +}, a = function(r2) {
16 + return { r: u(r2.r, 0, 255), g: u(r2.g, 0, 255), b: u(r2.b, 0, 255), a: u(r2.a) };
17 +}, i = function(r2) {
22 18 return { r: n(r2.r), g: n(r2.g), b: n(r2.b), a: n(r2.a, 3) };
19 +}, s = /^#([0-9a-f]{3,8})$/i, d = function(r2, t2) {
20 + var n2 = r2.charCodeAt(t2);
21 + return (15 & n2) + 9 * (n2 >> 6);
22 +}, h = function(r2, t2) {
23 + return d(r2, t2) << 4 | d(r2, t2 + 1);
24 +}, b = [], f = 0; f < 256; f++) b.push((f < 16 ? "0" : "") + f.toString(16));
25 +var r;
26 +var t;
27 +var n;
28 +var u;
29 +var e2;
30 +var o;
31 +var a;
32 +var i;
33 +var s;
34 +var d;
35 +var h;
36 +var b;
37 +var f;
38 +var g = function(r) {
39 + return b[u(r, 0, 255)];
23 40 };
24 -var i = /^#([0-9a-f]{3,8})$/i;
25 -var s = function(r2) {
26 - var t3 = r2.toString(16);
27 - return t3.length < 2 ? "0" + t3 : t3;
41 +var c = function(r) {
42 + var t = r.r, n = r.g, u = r.b, e2 = r.a, o = Math.max(t, n, u), a = o - Math.min(t, n, u), i = a ? o === t ? (n - u) / a : o === n ? 2 + (u - t) / a : 4 + (t - n) / a : 0;
43 + return { h: 60 * (i < 0 ? i + 6 : i), s: o ? a / o * 100 : 0, v: o / 255 * 100, a: e2 };
28 44 };
29 -var h = function(r2) {
30 - var t3 = r2.r, n2 = r2.g, e2 = r2.b, u2 = r2.a, a2 = Math.max(t3, n2, e2), o2 = a2 - Math.min(t3, n2, e2), i2 = o2 ? a2 === t3 ? (n2 - e2) / o2 : a2 === n2 ? 2 + (e2 - t3) / o2 : 4 + (t3 - n2) / o2 : 0;
31 - return { h: 60 * (i2 < 0 ? i2 + 6 : i2), s: a2 ? o2 / a2 * 100 : 0, v: a2 / 255 * 100, a: u2 };
45 +var v = function(r) {
46 + var t = r.h, n = r.s, u = r.v, e2 = r.a;
47 + t = t / 360 * 6, n /= 100, u /= 100;
48 + var o = Math.floor(t), a = u * (1 - n), i = u * (1 - (t - o) * n), s = u * (1 - (1 - t + o) * n), d = o % 6;
49 + return { r: 255 * [u, i, a, a, s, u][d], g: 255 * [s, u, u, i, a, a][d], b: 255 * [a, a, s, u, u, i][d], a: e2 };
32 50 };
33 -var b = function(r2) {
34 - var t3 = r2.h, n2 = r2.s, e2 = r2.v, u2 = r2.a;
35 - t3 = t3 / 360 * 6, n2 /= 100, e2 /= 100;
36 - var a2 = Math.floor(t3), o2 = e2 * (1 - n2), i2 = e2 * (1 - (t3 - a2) * n2), s2 = e2 * (1 - (1 - t3 + a2) * n2), h2 = a2 % 6;
37 - return { r: 255 * [e2, i2, o2, o2, s2, e2][h2], g: 255 * [s2, e2, e2, i2, o2, o2][h2], b: 255 * [o2, o2, s2, e2, e2, i2][h2], a: u2 };
51 +var l = function(r) {
52 + return { h: e2(r.h), s: u(r.s, 0, 100), l: u(r.l, 0, 100), a: u(r.a) };
38 53 };
39 -var g = function(r2) {
40 - return { h: u(r2.h), s: e(r2.s, 0, 100), l: e(r2.l, 0, 100), a: e(r2.a) };
54 +var p = function(r) {
55 + return { h: o(r.h), s: n(r.s), l: n(r.l), a: n(r.a, 3) };
41 56 };
42 -var d = function(r2) {
43 - return { h: n(r2.h), s: n(r2.s), l: n(r2.l), a: n(r2.a, 3) };
57 +var m = function(r) {
58 + return v((n = (t = r).s, { h: t.h, s: (n *= ((u = t.l) < 50 ? u : 100 - u) / 100) > 0 ? 2 * n / (u + n) * 100 : 0, v: u + n, a: t.a }));
59 + var t, n, u;
44 60 };
45 -var f = function(r2) {
46 - return b((n2 = (t3 = r2).s, { h: t3.h, s: (n2 *= ((e2 = t3.l) < 50 ? e2 : 100 - e2) / 100) > 0 ? 2 * n2 / (e2 + n2) * 100 : 0, v: e2 + n2, a: t3.a }));
47 - var t3, n2, e2;
61 +var y = function(r) {
62 + return { h: (t = c(r)).h, s: (e2 = (200 - (n = t.s)) * (u = t.v) / 100) > 0 && e2 < 200 ? n * u / 100 / (e2 <= 100 ? e2 : 200 - e2) * 100 : 0, l: e2 / 2, a: t.a };
63 + var t, n, u, e2;
48 64 };
49 -var c = function(r2) {
50 - return { h: (t3 = h(r2)).h, s: (u2 = (200 - (n2 = t3.s)) * (e2 = t3.v) / 100) > 0 && u2 < 200 ? n2 * e2 / 100 / (u2 <= 100 ? u2 : 200 - u2) * 100 : 0, l: u2 / 2, a: t3.a };
51 - var t3, n2, e2, u2;
52 -};
53 -var l = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i;
54 -var p = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i;
55 -var v = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i;
56 -var m = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i;
57 -var y = { string: [[function(r2) {
58 - var t3 = i.exec(r2);
59 - return t3 ? (r2 = t3[1]).length <= 4 ? { r: parseInt(r2[0] + r2[0], 16), g: parseInt(r2[1] + r2[1], 16), b: parseInt(r2[2] + r2[2], 16), a: 4 === r2.length ? n(parseInt(r2[3] + r2[3], 16) / 255, 2) : 1 } : 6 === r2.length || 8 === r2.length ? { r: parseInt(r2.substr(0, 2), 16), g: parseInt(r2.substr(2, 2), 16), b: parseInt(r2.substr(4, 2), 16), a: 8 === r2.length ? n(parseInt(r2.substr(6, 2), 16) / 255, 2) : 1 } : null : null;
60 -}, "hex"], [function(r2) {
61 - var t3 = v.exec(r2) || m.exec(r2);
62 - return t3 ? t3[2] !== t3[4] || t3[4] !== t3[6] ? null : a({ r: Number(t3[1]) / (t3[2] ? 100 / 255 : 1), g: Number(t3[3]) / (t3[4] ? 100 / 255 : 1), b: Number(t3[5]) / (t3[6] ? 100 / 255 : 1), a: void 0 === t3[7] ? 1 : Number(t3[7]) / (t3[8] ? 100 : 1) }) : null;
63 -}, "rgb"], [function(t3) {
64 - var n2 = l.exec(t3) || p.exec(t3);
65 - if (!n2) return null;
66 - var e2, u2, a2 = g({ h: (e2 = n2[1], u2 = n2[2], void 0 === u2 && (u2 = "deg"), Number(e2) * (r[u2] || 1)), s: Number(n2[3]), l: Number(n2[4]), a: void 0 === n2[5] ? 1 : Number(n2[5]) / (n2[6] ? 100 : 1) });
67 - return f(a2);
68 -}, "hsl"]], object: [[function(r2) {
69 - var n2 = r2.r, e2 = r2.g, u2 = r2.b, o2 = r2.a, i2 = void 0 === o2 ? 1 : o2;
70 - return t(n2) && t(e2) && t(u2) ? a({ r: Number(n2), g: Number(e2), b: Number(u2), a: Number(i2) }) : null;
71 -}, "rgb"], [function(r2) {
72 - var n2 = r2.h, e2 = r2.s, u2 = r2.l, a2 = r2.a, o2 = void 0 === a2 ? 1 : a2;
73 - if (!t(n2) || !t(e2) || !t(u2)) return null;
74 - var i2 = g({ h: Number(n2), s: Number(e2), l: Number(u2), a: Number(o2) });
75 - return f(i2);
76 -}, "hsl"], [function(r2) {
77 - var n2 = r2.h, a2 = r2.s, o2 = r2.v, i2 = r2.a, s2 = void 0 === i2 ? 1 : i2;
78 - if (!t(n2) || !t(a2) || !t(o2)) return null;
79 - var h2 = (function(r3) {
80 - return { h: u(r3.h), s: e(r3.s, 0, 100), v: e(r3.v, 0, 100), a: e(r3.a) };
81 - })({ h: Number(n2), s: Number(a2), v: Number(o2), a: Number(s2) });
82 - return b(h2);
65 +var N = /^hsla?\(\s*([+-]?(?:\d*\.\d+|\d+))(deg|rad|grad|turn)?\s*,\s*([+-]?(?:\d*\.\d+|\d+))%\s*,\s*([+-]?(?:\d*\.\d+|\d+))%\s*(?:,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
66 +var x = /^hsla?\(\s*([+-]?(?:\d*\.\d+|\d+))(deg|rad|grad|turn)?\s+([+-]?(?:\d*\.\d+|\d+))%\s+([+-]?(?:\d*\.\d+|\d+))%\s*(?:\/\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
67 +var M = /^rgba?\(\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*(?:,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
68 +var H = /^rgba?\(\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s+([+-]?(?:\d*\.\d+|\d+))(%)?\s+([+-]?(?:\d*\.\d+|\d+))(%)?\s*(?:\/\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
69 +var $ = { string: [[function(r) {
70 + if (!s.test(r)) return null;
71 + var t = r.length;
72 + return t <= 5 ? { r: 17 * d(r, 1), g: 17 * d(r, 2), b: 17 * d(r, 3), a: 5 === t ? n(17 * d(r, 4) / 255, 2) : 1 } : 7 === t || 9 === t ? { r: h(r, 1), g: h(r, 3), b: h(r, 5), a: 9 === t ? n(h(r, 7) / 255, 2) : 1 } : null;
73 +}, "hex"], [function(r) {
74 + var t = M.exec(r) || H.exec(r);
75 + return t ? t[2] !== t[4] || t[4] !== t[6] ? null : a({ r: Number(t[1]) / (t[2] ? 100 / 255 : 1), g: Number(t[3]) / (t[4] ? 100 / 255 : 1), b: Number(t[5]) / (t[6] ? 100 / 255 : 1), a: void 0 === t[7] ? 1 : Number(t[7]) / (t[8] ? 100 : 1) }) : null;
76 +}, "rgb"], [function(t) {
77 + var n = N.exec(t) || x.exec(t);
78 + if (!n) return null;
79 + var u, e2, o = l({ h: (u = n[1], e2 = n[2], void 0 === e2 && (e2 = "deg"), Number(u) * (r[e2] || 1)), s: Number(n[3]), l: Number(n[4]), a: void 0 === n[5] ? 1 : Number(n[5]) / (n[6] ? 100 : 1) });
80 + return m(o);
81 +}, "hsl"]], object: [[function(r) {
82 + var n = r.r, u = r.g, e2 = r.b, o = r.a, i = void 0 === o ? 1 : o;
83 + return t(n) && t(u) && t(e2) ? a({ r: Number(n), g: Number(u), b: Number(e2), a: Number(i) }) : null;
84 +}, "rgb"], [function(r) {
85 + var n = r.h, u = r.s, e2 = r.l, o = r.a, a = void 0 === o ? 1 : o;
86 + if (!t(n) || !t(u) || !t(e2)) return null;
87 + var i = l({ h: Number(n), s: Number(u), l: Number(e2), a: Number(a) });
88 + return m(i);
89 +}, "hsl"], [function(r) {
90 + var n = r.h, o = r.s, a = r.v, i = r.a, s = void 0 === i ? 1 : i;
91 + if (!t(n) || !t(o) || !t(a)) return null;
92 + var d = (function(r2) {
93 + return { h: e2(r2.h), s: u(r2.s, 0, 100), v: u(r2.v, 0, 100), a: u(r2.a) };
94 + })({ h: Number(n), s: Number(o), v: Number(a), a: Number(s) });
95 + return v(d);
83 96 }, "hsv"]] };
84 -var N = function(r2, t3) {
85 - for (var n2 = 0; n2 < t3.length; n2++) {
86 - var e2 = t3[n2][0](r2);
87 - if (e2) return [e2, t3[n2][1]];
97 +var j = function(r, t) {
98 + for (var n = 0; n < t.length; n++) {
99 + var u = t[n][0](r);
100 + if (u) return [u, t[n][1]];
88 101 }
89 102 return [null, void 0];
90 103 };
91 -var x = function(r2) {
92 - return "string" == typeof r2 ? N(r2.trim(), y.string) : "object" == typeof r2 && null !== r2 ? N(r2, y.object) : [null, void 0];
104 +var w = function(r) {
105 + return "string" == typeof r ? j(r.trim(), $.string) : "object" == typeof r && null !== r ? j(r, $.object) : [null, void 0];
93 106 };
94 -var M = function(r2, t3) {
95 - var n2 = c(r2);
96 - return { h: n2.h, s: e(n2.s + 100 * t3, 0, 100), l: n2.l, a: n2.a };
107 +var k = function(r, t) {
108 + var n = y(r);
109 + return { h: n.h, s: u(n.s + 100 * t, 0, 100), l: n.l, a: n.a };
97 110 };
98 -var H = function(r2) {
99 - return (299 * r2.r + 587 * r2.g + 114 * r2.b) / 1e3 / 255;
111 +var E = function(r) {
112 + return (299 * r.r + 587 * r.g + 114 * r.b) / 1e3 / 255;
100 113 };
101 -var $ = function(r2, t3) {
102 - var n2 = c(r2);
103 - return { h: n2.h, s: n2.s, l: e(n2.l + 100 * t3, 0, 100), a: n2.a };
114 +var R = function(r, t) {
115 + var n = y(r);
116 + return { h: n.h, s: n.s, l: u(n.l + 100 * t, 0, 100), a: n.a };
104 117 };
105 -var j = (function() {
106 - function r2(r3) {
107 - this.parsed = x(r3)[0], this.rgba = this.parsed || { r: 0, g: 0, b: 0, a: 1 };
118 +var q = (function() {
119 + function r(r2) {
120 + this.parsed = w(r2)[0], this.rgba = this.parsed || { r: 0, g: 0, b: 0, a: 1 };
108 121 }
109 - return r2.prototype.isValid = function() {
122 + return r.prototype.isValid = function() {
110 123 return null !== this.parsed;
111 - }, r2.prototype.brightness = function() {
112 - return n(H(this.rgba), 2);
113 - }, r2.prototype.isDark = function() {
114 - return H(this.rgba) < 0.5;
115 - }, r2.prototype.isLight = function() {
116 - return H(this.rgba) >= 0.5;
117 - }, r2.prototype.toHex = function() {
118 - return r3 = o(this.rgba), t3 = r3.r, e2 = r3.g, u2 = r3.b, i2 = (a2 = r3.a) < 1 ? s(n(255 * a2)) : "", "#" + s(t3) + s(e2) + s(u2) + i2;
119 - var r3, t3, e2, u2, a2, i2;
120 - }, r2.prototype.toRgb = function() {
121 - return o(this.rgba);
122 - }, r2.prototype.toRgbString = function() {
123 - return r3 = o(this.rgba), t3 = r3.r, n2 = r3.g, e2 = r3.b, (u2 = r3.a) < 1 ? "rgba(" + t3 + ", " + n2 + ", " + e2 + ", " + u2 + ")" : "rgb(" + t3 + ", " + n2 + ", " + e2 + ")";
124 - var r3, t3, n2, e2, u2;
125 - }, r2.prototype.toHsl = function() {
126 - return d(c(this.rgba));
127 - }, r2.prototype.toHslString = function() {
128 - return r3 = d(c(this.rgba)), t3 = r3.h, n2 = r3.s, e2 = r3.l, (u2 = r3.a) < 1 ? "hsla(" + t3 + ", " + n2 + "%, " + e2 + "%, " + u2 + ")" : "hsl(" + t3 + ", " + n2 + "%, " + e2 + "%)";
129 - var r3, t3, n2, e2, u2;
130 - }, r2.prototype.toHsv = function() {
131 - return r3 = h(this.rgba), { h: n(r3.h), s: n(r3.s), v: n(r3.v), a: n(r3.a, 3) };
132 - var r3;
133 - }, r2.prototype.invert = function() {
134 - return w({ r: 255 - (r3 = this.rgba).r, g: 255 - r3.g, b: 255 - r3.b, a: r3.a });
135 - var r3;
136 - }, r2.prototype.saturate = function(r3) {
137 - return void 0 === r3 && (r3 = 0.1), w(M(this.rgba, r3));
138 - }, r2.prototype.desaturate = function(r3) {
139 - return void 0 === r3 && (r3 = 0.1), w(M(this.rgba, -r3));
140 - }, r2.prototype.grayscale = function() {
141 - return w(M(this.rgba, -1));
142 - }, r2.prototype.lighten = function(r3) {
143 - return void 0 === r3 && (r3 = 0.1), w($(this.rgba, r3));
144 - }, r2.prototype.darken = function(r3) {
145 - return void 0 === r3 && (r3 = 0.1), w($(this.rgba, -r3));
146 - }, r2.prototype.rotate = function(r3) {
147 - return void 0 === r3 && (r3 = 15), this.hue(this.hue() + r3);
148 - }, r2.prototype.alpha = function(r3) {
149 - return "number" == typeof r3 ? w({ r: (t3 = this.rgba).r, g: t3.g, b: t3.b, a: r3 }) : n(this.rgba.a, 3);
150 - var t3;
151 - }, r2.prototype.hue = function(r3) {
152 - var t3 = c(this.rgba);
153 - return "number" == typeof r3 ? w({ h: r3, s: t3.s, l: t3.l, a: t3.a }) : n(t3.h);
154 - }, r2.prototype.isEqual = function(r3) {
155 - return this.toHex() === w(r3).toHex();
156 - }, r2;
124 + }, r.prototype.brightness = function() {
125 + return n(E(this.rgba), 2);
126 + }, r.prototype.isDark = function() {
127 + return E(this.rgba) < 0.5;
128 + }, r.prototype.isLight = function() {
129 + return E(this.rgba) >= 0.5;
130 + }, r.prototype.toHex = function() {
131 + return r2 = i(this.rgba), t = r2.r, u = r2.g, e2 = r2.b, a = (o = r2.a) < 1 ? g(n(255 * o)) : "", "#" + g(t) + g(u) + g(e2) + a;
132 + var r2, t, u, e2, o, a;
133 + }, r.prototype.toRgb = function() {
134 + return i(this.rgba);
135 + }, r.prototype.toRgbString = function() {
136 + return r2 = i(this.rgba), t = r2.r, n = r2.g, u = r2.b, (e2 = r2.a) < 1 ? "rgba(" + t + ", " + n + ", " + u + ", " + e2 + ")" : "rgb(" + t + ", " + n + ", " + u + ")";
137 + var r2, t, n, u, e2;
138 + }, r.prototype.toHsl = function() {
139 + return p(y(this.rgba));
140 + }, r.prototype.toHslString = function() {
141 + return r2 = p(y(this.rgba)), t = r2.h, n = r2.s, u = r2.l, (e2 = r2.a) < 1 ? "hsla(" + t + ", " + n + "%, " + u + "%, " + e2 + ")" : "hsl(" + t + ", " + n + "%, " + u + "%)";
142 + var r2, t, n, u, e2;
143 + }, r.prototype.toHsv = function() {
144 + return r2 = c(this.rgba), { h: o(r2.h), s: n(r2.s), v: n(r2.v), a: n(r2.a, 3) };
145 + var r2;
146 + }, r.prototype.invert = function() {
147 + return A({ r: 255 - (r2 = this.rgba).r, g: 255 - r2.g, b: 255 - r2.b, a: r2.a });
148 + var r2;
149 + }, r.prototype.saturate = function(r2) {
150 + return void 0 === r2 && (r2 = 0.1), A(k(this.rgba, r2));
151 + }, r.prototype.desaturate = function(r2) {
152 + return void 0 === r2 && (r2 = 0.1), A(k(this.rgba, -r2));
153 + }, r.prototype.grayscale = function() {
154 + return A(k(this.rgba, -1));
155 + }, r.prototype.lighten = function(r2) {
156 + return void 0 === r2 && (r2 = 0.1), A(R(this.rgba, r2));
157 + }, r.prototype.darken = function(r2) {
158 + return void 0 === r2 && (r2 = 0.1), A(R(this.rgba, -r2));
159 + }, r.prototype.rotate = function(r2) {
160 + return void 0 === r2 && (r2 = 15), this.hue(y(this.rgba).h + r2);
161 + }, r.prototype.alpha = function(r2) {
162 + return "number" == typeof r2 ? A({ r: (t = this.rgba).r, g: t.g, b: t.b, a: r2 }) : n(this.rgba.a, 3);
163 + var t;
164 + }, r.prototype.hue = function(r2) {
165 + var t = y(this.rgba);
166 + return "number" == typeof r2 ? A({ h: r2, s: t.s, l: t.l, a: t.a }) : o(t.h);
167 + }, r.prototype.isEqual = function(r2) {
168 + return this.toHex() === A(r2).toHex();
169 + }, r;
157 170 })();
158 -var w = function(r2) {
159 - return r2 instanceof j ? r2 : new j(r2);
171 +var A = function(r) {
172 + return r instanceof q ? r : new q(r);
160 173 };
161 174
162 -// packages/block-library/node_modules/@arraypress/waveform-player/dist/waveform-player.esm.js
163 -function L(t3) {
164 - let e2 = {};
165 - if (t3.dataset.url && (e2.url = t3.dataset.url), t3.dataset.height && (e2.height = parseInt(t3.dataset.height)), t3.dataset.samples && (e2.samples = parseInt(t3.dataset.samples)), t3.dataset.preload && (e2.preload = t3.dataset.preload), t3.dataset.waveformStyle && (e2.waveformStyle = t3.dataset.waveformStyle), t3.dataset.barWidth && (e2.barWidth = parseInt(t3.dataset.barWidth)), t3.dataset.barSpacing && (e2.barSpacing = parseInt(t3.dataset.barSpacing)), t3.dataset.buttonAlign && (e2.buttonAlign = t3.dataset.buttonAlign), t3.dataset.colorPreset && (e2.colorPreset = t3.dataset.colorPreset), t3.dataset.waveformColor && (e2.waveformColor = t3.dataset.waveformColor), t3.dataset.progressColor && (e2.progressColor = t3.dataset.progressColor), t3.dataset.buttonColor && (e2.buttonColor = t3.dataset.buttonColor), t3.dataset.buttonHoverColor && (e2.buttonHoverColor = t3.dataset.buttonHoverColor), t3.dataset.textColor && (e2.textColor = t3.dataset.textColor), t3.dataset.textSecondaryColor && (e2.textSecondaryColor = t3.dataset.textSecondaryColor), t3.dataset.backgroundColor && (e2.backgroundColor = t3.dataset.backgroundColor), t3.dataset.borderColor && (e2.borderColor = t3.dataset.borderColor), t3.dataset.color && (e2.waveformColor = t3.dataset.color), t3.dataset.theme && (e2.colorPreset = t3.dataset.theme), t3.dataset.autoplay && (e2.autoplay = t3.dataset.autoplay === "true"), t3.dataset.showTime && (e2.showTime = t3.dataset.showTime === "true"), t3.dataset.showHoverTime && (e2.showHoverTime = t3.dataset.showHoverTime === "true"), t3.dataset.showBpm && (e2.showBPM = t3.dataset.showBpm === "true"), t3.dataset.singlePlay && (e2.singlePlay = t3.dataset.singlePlay === "true"), t3.dataset.playOnSeek && (e2.playOnSeek = t3.dataset.playOnSeek === "true"), t3.dataset.title && (e2.title = t3.dataset.title), t3.dataset.subtitle && (e2.subtitle = t3.dataset.subtitle), t3.dataset.album && (e2.album = t3.dataset.album), t3.dataset.artwork && (e2.artwork = t3.dataset.artwork), t3.dataset.waveform && (e2.waveform = t3.dataset.waveform), t3.dataset.markers) try {
166 - e2.markers = JSON.parse(t3.dataset.markers);
167 - } catch (i2) {
168 - console.warn("Invalid markers JSON:", i2);
175 +// node_modules/@arraypress/waveform-player/dist/waveform-player.esm.js
176 +function $2(e2) {
177 + let t = -1 / 0;
178 + for (let i = 0; i < e2.length; i++) e2[i] > t && (t = e2[i]);
179 + return t;
180 +}
181 +function S(e2) {
182 + return String(e2 ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
183 +}
184 +function q2(e2) {
185 + return S(typeof e2 == "number" ? `${e2}px` : e2);
186 +}
187 +function st(e2) {
188 + if (typeof e2 != "string" || e2 === "") return false;
189 + try {
190 + let t = new URL(e2, "http://localhost/");
191 + return t.protocol === "http:" || t.protocol === "https:";
192 + } catch {
193 + return false;
169 194 }
170 - if (t3.dataset.playbackRate && (e2.playbackRate = parseFloat(t3.dataset.playbackRate)), t3.dataset.showPlaybackSpeed !== void 0 && (e2.showPlaybackSpeed = t3.dataset.showPlaybackSpeed === "true"), t3.dataset.playbackRates) try {
171 - e2.playbackRates = JSON.parse(t3.dataset.playbackRates);
172 - } catch (i2) {
173 - console.warn("Invalid playbackRates JSON:", i2);
195 +}
196 +function m2(e2, t = 0, i = 1) {
197 + return Math.max(t, Math.min(e2, i));
198 +}
199 +function _(e2, t = null, i = {}) {
200 + let { min: s = -1 / 0, max: r = 1 / 0, integer: a = false } = i, o = typeof e2 == "number" ? e2 : typeof e2 == "string" && e2.trim() !== "" ? Number(e2) : NaN;
201 + if (!Number.isFinite(o)) return t;
202 + let n = m2(o, s, r);
203 + return a ? Math.round(n) : n;
204 +}
205 +function H2(e2, t = null) {
206 + if (Array.isArray(e2)) return e2;
207 + if (typeof e2 == "string" && e2.trim().startsWith("[")) try {
208 + let i = JSON.parse(e2);
209 + if (Array.isArray(i)) return i;
210 + } catch {
174 211 }
175 - return t3.dataset.enableMediaSession !== void 0 && (e2.enableMediaSession = t3.dataset.enableMediaSession === "true"), e2;
212 + return t;
176 213 }
177 -function P(t3) {
178 - if (!t3 || isNaN(t3)) return "0:00";
179 - let e2 = Math.floor(t3 / 60), i2 = Math.floor(t3 % 60);
180 - return `${e2}:${i2.toString().padStart(2, "0")}`;
214 +function D(e2, t = {}) {
215 + let { min: i = -1 / 0, max: s = 1 / 0, fallback: r = null } = t, a = H2(e2);
216 + if (!a && typeof e2 == "string" && e2.trim() !== "" && (a = e2.split(/[,\s]+/)), !a) return r;
217 + let o = a.map((n) => _(n)).filter((n) => n !== null && n >= i && n <= s);
218 + return o.length ? o : r;
181 219 }
182 -function A(t3) {
183 - let e2 = t3 || Math.random().toString();
184 - return btoa(e2.substring(0, 10)).replace(/[^a-zA-Z0-9]/g, "");
220 +function rt(e2, t, i = null) {
221 + return t.includes(e2) ? e2 : i;
185 222 }
186 -function R(t3) {
187 - if (!t3) return "Audio";
188 - let e2 = t3.split("/");
189 - return e2[e2.length - 1].split(".")[0].replace(/[-_]/g, " ").replace(/\b\w/g, (s2) => s2.toUpperCase());
223 +function at(e2) {
224 + if (typeof e2 == "string") {
225 + let t = e2.trim().toLowerCase();
226 + return t !== "" && t !== "false" && t !== "0";
227 + }
228 + return !!e2;
190 229 }
191 -function C(...t3) {
192 - let e2 = {};
193 - for (let i2 of t3) for (let a2 in i2) i2[a2] !== null && i2[a2] !== void 0 && (e2[a2] = i2[a2]);
230 +function vt(e2) {
231 + return e2 === void 0 ? void 0 : e2 === "true";
232 +}
233 +function it(e2) {
234 + if (typeof e2 == "string" && e2.trim().startsWith("[")) try {
235 + return JSON.parse(e2);
236 + } catch {
237 + }
194 238 return e2;
195 239 }
196 -function B(t3, e2) {
197 - let i2;
198 - return function(...s2) {
199 - let n2 = () => {
200 - clearTimeout(i2), t3(...s2);
240 +function O(e2) {
241 + let t = {}, i = (o, n = o) => {
242 + let l2 = vt(e2.dataset[n]);
243 + l2 !== void 0 && (t[o] = l2);
244 + }, s = (o, n = o, l2 = false) => {
245 + let h = e2.dataset[n];
246 + h && (t[o] = l2 ? parseFloat(h) : parseInt(h, 10));
247 + }, r = (o, n = o) => {
248 + let l2 = e2.dataset[n];
249 + l2 && (t[o] = /^\d+(\.\d+)?$/.test(l2.trim()) ? parseFloat(l2) : l2);
250 + }, a = (o, n = o) => {
251 + let l2 = e2.dataset[n];
252 + if (!l2) return;
253 + let h = H2(l2);
254 + h ? t[o] = h : console.warn(`[WaveformPlayer] Invalid ${n} attribute, expected a JSON array:`, l2);
255 + };
256 + if (e2.dataset.src && (t.url = e2.dataset.src), e2.dataset.url && (t.url = e2.dataset.url), s("height"), s("samples"), e2.dataset.preload && (t.preload = e2.dataset.preload), e2.dataset.crossOrigin && (t.crossOrigin = e2.dataset.crossOrigin), e2.dataset.audioMode && (t.audioMode = e2.dataset.audioMode), e2.dataset.style && (t.waveformStyle = e2.dataset.style), e2.dataset.waveformStyle && (t.waveformStyle = e2.dataset.waveformStyle), e2.dataset.waveformGradient && (t.waveformGradient = e2.dataset.waveformGradient), s("barWidth"), s("barSpacing"), s("barRadius"), e2.dataset.buttonAlign && (t.buttonAlign = e2.dataset.buttonAlign), e2.dataset.layout && (t.layout = e2.dataset.layout), e2.dataset.buttonStyle && (t.buttonStyle = e2.dataset.buttonStyle), r("buttonSize"), r("buttonRadius"), e2.dataset.colorPreset && (t.colorPreset = e2.dataset.colorPreset), e2.dataset.waveformColor && (t.waveformColor = it(e2.dataset.waveformColor)), e2.dataset.progressColor && (t.progressColor = it(e2.dataset.progressColor)), e2.dataset.color && (t.waveformColor = e2.dataset.color), e2.dataset.theme && (t.colorPreset = e2.dataset.theme), i("autoplay"), i("showControls"), i("showInfo"), i("showTime"), i("showHoverTime"), i("seekHandle"), i("showBPM", "showBpm"), s("bpm"), i("singlePlay"), i("playOnSeek"), e2.dataset.title && (t.title = e2.dataset.title), e2.dataset.artist && (t.artist = e2.dataset.artist), e2.dataset.album && (t.album = e2.dataset.album), e2.dataset.artwork && (t.artwork = e2.dataset.artwork), e2.dataset.artworkPosition && (t.artworkPosition = e2.dataset.artworkPosition), e2.dataset.waveform && (t.waveform = e2.dataset.waveform), a("markers"), s("playbackRate", "playbackRate", true), i("showPlaybackSpeed"), e2.dataset.playbackRates) {
257 + let o = D(e2.dataset.playbackRates);
258 + o ? t.playbackRates = o : console.warn("[WaveformPlayer] Invalid playbackRates attribute:", e2.dataset.playbackRates);
259 + }
260 + return i("enableMediaSession"), i("showMarkers"), i("accessibleSeek"), e2.dataset.seekLabel && (t.seekLabel = e2.dataset.seekLabel), e2.dataset.seekValueText && (t.seekValueText = e2.dataset.seekValueText), e2.dataset.errorText && (t.errorText = e2.dataset.errorText), e2.dataset.playPauseLabel && (t.playPauseLabel = e2.dataset.playPauseLabel), e2.dataset.speedLabel && (t.speedLabel = e2.dataset.speedLabel), e2.dataset.artworkAlt && (t.artworkAlt = e2.dataset.artworkAlt), e2.dataset.unknownTrackText && (t.unknownTrackText = e2.dataset.unknownTrackText), t;
261 +}
262 +function ot(e2, ...t) {
263 + let i = 0;
264 + return e2.replace(/%(?:(\d+)\$)?s/g, (s, r) => {
265 + let a = r ? Number(r) - 1 : i++;
266 + return t[a] ?? s;
267 + });
268 +}
269 +function E2(e2) {
270 + let t = Number(e2);
271 + if (!t || !Number.isFinite(t) || t < 0) return "0:00";
272 + let i = Math.floor(t / 3600), s = Math.floor(t % 3600 / 60), r = Math.floor(t % 60);
273 + return i > 0 ? `${i}:${s.toString().padStart(2, "0")}:${r.toString().padStart(2, "0")}` : `${s}:${r.toString().padStart(2, "0")}`;
274 +}
275 +var St = 0;
276 +function nt(e2) {
277 + let t = e2 || "audio", i = 5381;
278 + for (let s = 0; s < t.length; s++) i = (i << 5) + i + t.charCodeAt(s) | 0;
279 + return `wp_${(i >>> 0).toString(36)}_${(St++).toString(36)}`;
280 +}
281 +function I(e2) {
282 + if (!e2) return "Audio";
283 + let t = e2.split("/");
284 + return t[t.length - 1].split(".")[0].replace(/[-_]/g, " ").replace(/\b\w/g, (r) => r.toUpperCase());
285 +}
286 +function U(e2) {
287 + if (typeof e2 != "string") return null;
288 + let t = e2.match(/rgba?\(\s*([\d.]+)\s*[,\s]\s*([\d.]+)\s*[,\s]\s*([\d.]+)\s*(?:[,/]\s*([\d.]+)(%?))?/i);
289 + if (!t) return null;
290 + let i = Number(t[1]), s = Number(t[2]), r = Number(t[3]);
291 + if (!Number.isFinite(i) || !Number.isFinite(s) || !Number.isFinite(r)) return null;
292 + let a = t[4] === void 0 ? 1 : Number(t[4]);
293 + return Number.isFinite(a) ? (t[5] === "%" && (a /= 100), { r: i, g: s, b: r, a: m2(a, 0, 1) }) : null;
294 +}
295 +function lt(e2) {
296 + let t = U(e2);
297 + return !t || t.a <= 0 ? null : (t.r * 299 + t.g * 587 + t.b * 114) / 1e3;
298 +}
299 +function j2(...e2) {
300 + let t = {};
301 + for (let i of e2) for (let s in i) i[s] !== null && i[s] !== void 0 && (t[s] = i[s]);
302 + return t;
303 +}
304 +function ht(e2, t) {
305 + let i;
306 + return function(...r) {
307 + let a = () => {
308 + clearTimeout(i), e2(...r);
201 309 };
202 - clearTimeout(i2), i2 = setTimeout(n2, e2);
310 + clearTimeout(i), i = setTimeout(a, t);
203 311 };
204 312 }
205 -function S(t3, e2) {
206 - if (t3.length === e2) return t3;
207 - if (t3.length === 0 || e2 === 0) return [];
208 - let i2 = [];
209 - if (e2 > t3.length) {
210 - let a2 = (t3.length - 1) / (e2 - 1);
211 - for (let s2 = 0; s2 < e2; s2++) {
212 - let n2 = s2 * a2, r2 = Math.floor(n2), o2 = Math.ceil(n2), h2 = n2 - r2;
213 - if (o2 >= t3.length) i2.push(t3[t3.length - 1]);
214 - else if (r2 === o2) i2.push(t3[r2]);
313 +function B(e2, t) {
314 + if (e2.length === t) return e2;
315 + if (e2.length === 0 || t === 0) return [];
316 + let i = [];
317 + if (t > e2.length) {
318 + let s = (e2.length - 1) / (t - 1);
319 + for (let r = 0; r < t; r++) {
320 + let a = r * s, o = Math.floor(a), n = Math.ceil(a), l2 = a - o;
321 + if (n >= e2.length) i.push(e2[e2.length - 1]);
322 + else if (o === n) i.push(e2[o]);
215 323 else {
216 - let l2 = t3[r2] * (1 - h2) + t3[o2] * h2;
217 - i2.push(l2);
324 + let h = e2[o] * (1 - l2) + e2[n] * l2;
325 + i.push(h);
218 326 }
219 327 }
220 328 } else {
221 - let a2 = t3.length / e2;
222 - for (let s2 = 0; s2 < e2; s2++) {
223 - let n2 = Math.floor(s2 * a2), r2 = Math.floor((s2 + 1) * a2), o2 = 0, h2 = 0;
224 - for (let l2 = n2; l2 <= r2 && l2 < t3.length; l2++) t3[l2] > o2 && (o2 = t3[l2]), h2++;
225 - if (h2 === 0) {
226 - let l2 = Math.min(Math.round(s2 * a2), t3.length - 1);
227 - o2 = t3[l2];
329 + let s = e2.length / t;
330 + for (let r = 0; r < t; r++) {
331 + let a = Math.floor(r * s), o = Math.floor((r + 1) * s), n = 0, l2 = 0;
332 + for (let h = a; h <= o && h < e2.length; h++) e2[h] > n && (n = e2[h]), l2++;
333 + if (l2 === 0) {
334 + let h = Math.min(Math.round(r * s), e2.length - 1);
335 + n = e2[h];
228 336 }
229 - i2.push(o2);
337 + i.push(n);
230 338 }
231 339 }
232 - return i2;
340 + return i;
233 341 }
234 -function x2(t3, e2, i2, a2, s2) {
235 - let n2 = window.devicePixelRatio || 1, r2 = s2.barWidth * n2, o2 = s2.barSpacing * n2, h2 = Math.floor(e2.width / (r2 + o2)), l2 = S(i2, h2), d2 = e2.height, p2 = a2 * e2.width;
236 - t3.clearRect(0, 0, e2.width, e2.height);
237 - for (let y2 = 0; y2 < l2.length; y2++) {
238 - let f2 = y2 * (r2 + o2);
239 - if (f2 + r2 > e2.width) break;
240 - let c2 = l2[y2] * d2 * 0.9, m2 = d2 - c2;
241 - t3.fillStyle = s2.color, t3.fillRect(f2, m2, r2, c2);
342 +function P(e2, t, i, s) {
343 + if (!Array.isArray(t)) return t;
344 + if (t.length < 2) return t[0];
345 + let r = i.width, a = i.height, o = s && s.waveformGradient, [n, l2, h, c2] = o === "horizontal" ? [0, 0, r, 0] : o === "diagonal" ? [0, 0, r, a] : [0, 0, 0, a];
346 + try {
347 + let d = e2.createLinearGradient(n, l2, h, c2);
348 + return t.forEach((b, y2) => d.addColorStop(y2 / (t.length - 1), b)), d;
349 + } catch {
350 + return t[0];
242 351 }
243 - t3.save(), t3.beginPath(), t3.rect(0, 0, p2, d2), t3.clip();
244 - for (let y2 = 0; y2 < l2.length; y2++) {
245 - let f2 = y2 * (r2 + o2);
246 - if (f2 > p2) break;
247 - let c2 = l2[y2] * d2 * 0.9, m2 = d2 - c2;
248 - t3.fillStyle = s2.progressColor, t3.fillRect(f2, m2, r2, c2);
352 +}
353 +function x2(e2, t, i, s, r, a) {
354 + if ((Array.isArray(a) ? a.some((n) => n > 0) : a > 0) && typeof e2.roundRect == "function") {
355 + let n = Math.min(s / 2, Math.abs(r) / 2), l2 = (h) => m2(h, 0, n);
356 + e2.beginPath(), e2.roundRect(t, i, s, r, Array.isArray(a) ? a.map(l2) : l2(a)), e2.fill();
357 + } else e2.fillRect(t, i, s, r);
358 +}
359 +function pt(e2, t) {
360 + return (e2.barRadius || 0) * t;
361 +}
362 +function Et(e2, t) {
363 + let i = pt(e2, t);
364 + return [i, i, 0, 0];
365 +}
366 +function ct(e2, t, i, s, r) {
367 + let a = r / 2;
368 + e2.beginPath(), e2.moveTo(t, s - a), e2.lineTo(i - a, s - a), e2.arc(i - a, s, a, -Math.PI / 2, Math.PI / 2), e2.lineTo(t, s + a), e2.arc(t, s, a, Math.PI / 2, -Math.PI / 2), e2.closePath();
369 +}
370 +function V(e2, t, i, s, r) {
371 + let a = window.devicePixelRatio || 1, o = r.barWidth * a, n = r.barSpacing * a, l2 = Math.floor(t.width / (o + n)), h = B(i, l2), c2 = t.height, d = s * t.width, b = Et(r, a), y2 = P(e2, r.color, t, r), w2 = P(e2, r.progressColor, t, r);
372 + e2.clearRect(0, 0, t.width, t.height), e2.fillStyle = y2;
373 + for (let f = 0; f < h.length; f++) {
374 + let p2 = f * (o + n);
375 + if (p2 + o > t.width) break;
376 + let g2 = h[f] * c2 * 0.9, u = c2 - g2;
377 + x2(e2, p2, u, o, g2, b);
249 378 }
250 - t3.restore();
379 + e2.save(), e2.beginPath(), e2.rect(0, 0, d, c2), e2.clip(), e2.fillStyle = w2;
380 + for (let f = 0; f < h.length; f++) {
381 + let p2 = f * (o + n);
382 + if (p2 > d) break;
383 + let g2 = h[f] * c2 * 0.9, u = c2 - g2;
384 + x2(e2, p2, u, o, g2, b);
385 + }
386 + e2.restore();
251 387 }
252 -function q(t3, e2, i2, a2, s2) {
253 - let n2 = window.devicePixelRatio || 1, r2 = s2.barWidth * n2, o2 = s2.barSpacing * n2, h2 = Math.floor(e2.width / (r2 + o2)), l2 = S(i2, h2), d2 = e2.height, p2 = d2 / 2, y2 = a2 * e2.width;
254 - t3.clearRect(0, 0, e2.width, e2.height);
255 - for (let f2 = 0; f2 < l2.length; f2++) {
256 - let c2 = f2 * (r2 + o2);
257 - if (c2 + r2 > e2.width) break;
258 - let m2 = l2[f2] * d2 * 0.45;
259 - t3.fillStyle = s2.color, t3.fillRect(c2, p2 - m2, r2, m2), t3.fillRect(c2, p2, r2, m2);
388 +function Pt(e2, t, i, s, r) {
389 + let a = window.devicePixelRatio || 1, o = r.barWidth * a, n = r.barSpacing * a, l2 = Math.floor(t.width / (o + n)), h = B(i, l2), c2 = t.height, d = c2 / 2, b = s * t.width, y2 = pt(r, a), w2 = [y2, y2, 0, 0], f = [0, 0, y2, y2], p2 = P(e2, r.color, t, r), g2 = P(e2, r.progressColor, t, r);
390 + e2.clearRect(0, 0, t.width, t.height), e2.fillStyle = p2;
391 + for (let u = 0; u < h.length; u++) {
392 + let k2 = u * (o + n);
393 + if (k2 + o > t.width) break;
394 + let v2 = h[u] * c2 * 0.45;
395 + x2(e2, k2, d - v2, o, v2, w2), x2(e2, k2, d, o, v2, f);
260 396 }
261 - t3.save(), t3.beginPath(), t3.rect(0, 0, y2, d2), t3.clip();
262 - for (let f2 = 0; f2 < l2.length; f2++) {
263 - let c2 = f2 * (r2 + o2);
264 - if (c2 > y2) break;
265 - let m2 = l2[f2] * d2 * 0.45;
266 - t3.fillStyle = s2.progressColor, t3.fillRect(c2, p2 - m2, r2, m2), t3.fillRect(c2, p2, r2, m2);
397 + e2.save(), e2.beginPath(), e2.rect(0, 0, b, c2), e2.clip(), e2.fillStyle = g2;
398 + for (let u = 0; u < h.length; u++) {
399 + let k2 = u * (o + n);
400 + if (k2 > b) break;
401 + let v2 = h[u] * c2 * 0.45;
402 + x2(e2, k2, d - v2, o, v2, w2), x2(e2, k2, d, o, v2, f);
267 403 }
268 - t3.restore();
404 + e2.restore();
269 405 }
270 -function $2(t3, e2, i2, a2, s2) {
271 - let n2 = e2.width, r2 = e2.height, o2 = r2 / 2, h2 = r2 * 0.35;
272 - t3.clearRect(0, 0, n2, r2);
273 - let l2 = (d2, p2, y2 = 1, f2 = false) => {
274 - f2 && (t3.shadowBlur = 12, t3.shadowColor = d2), t3.strokeStyle = d2, t3.lineWidth = p2, t3.lineCap = "round", t3.lineJoin = "round", t3.beginPath(), t3.moveTo(0, o2);
275 - let c2 = [], m2 = Math.floor(i2.length * y2);
276 - for (let u2 = 0; u2 < m2; u2++) {
277 - let v2 = u2 / (i2.length - 1) * n2, k = i2[u2], b2 = Math.sin(u2 * 0.1) * k, w2 = o2 + b2 * h2;
278 - c2.push({ x: v2, y: w2 });
406 +function Tt(e2, t, i, s, r) {
407 + let a = t.width, o = t.height, n = o / 2, l2 = o * 0.35;
408 + e2.clearRect(0, 0, a, o);
409 + let h = (c2, d, b = 1, y2 = false) => {
410 + let w2 = P(e2, c2, t, r), f = Array.isArray(c2) ? c2[c2.length - 1] : c2;
411 + y2 && (e2.shadowBlur = 12, e2.shadowColor = f), e2.strokeStyle = w2, e2.lineWidth = d, e2.lineCap = "round", e2.lineJoin = "round", e2.beginPath(), e2.moveTo(0, n);
412 + let p2 = [], g2 = Math.floor(i.length * b);
413 + for (let u = 0; u < g2; u++) {
414 + let k2 = u / (i.length - 1) * a, v2 = i[u], A2 = Math.sin(u * 0.1) * v2, L = n + A2 * l2;
415 + p2.push({ x: k2, y: L });
279 416 }
280 - for (let u2 = 0; u2 < c2.length - 1; u2++) {
281 - let v2 = c2[u2].x + (c2[u2 + 1].x - c2[u2].x) * 0.5, k = c2[u2].y, b2 = c2[u2 + 1].x - (c2[u2 + 1].x - c2[u2].x) * 0.5, w2 = c2[u2 + 1].y;
282 - t3.bezierCurveTo(v2, k, b2, w2, c2[u2 + 1].x, c2[u2 + 1].y);
417 + for (let u = 0; u < p2.length - 1; u++) {
418 + let k2 = p2[u].x + (p2[u + 1].x - p2[u].x) * 0.5, v2 = p2[u].y, A2 = p2[u + 1].x - (p2[u + 1].x - p2[u].x) * 0.5, L = p2[u + 1].y;
419 + e2.bezierCurveTo(k2, v2, A2, L, p2[u + 1].x, p2[u + 1].y);
283 420 }
284 - t3.stroke(), f2 && (t3.shadowBlur = 0);
421 + e2.stroke(), y2 && (e2.shadowBlur = 0);
285 422 };
286 - t3.strokeStyle = "rgba(255, 255, 255, 0.03)", t3.lineWidth = 0.5, t3.beginPath(), t3.moveTo(0, o2), t3.lineTo(n2, o2), t3.stroke();
287 - for (let d2 = 0; d2 <= 10; d2++) {
288 - let p2 = n2 / 10 * d2;
289 - t3.beginPath(), t3.moveTo(p2, 0), t3.lineTo(p2, r2), t3.stroke();
423 + e2.strokeStyle = "rgba(255, 255, 255, 0.03)", e2.lineWidth = 0.5, e2.beginPath(), e2.moveTo(0, n), e2.lineTo(a, n), e2.stroke();
424 + for (let c2 = 0; c2 <= 10; c2++) {
425 + let d = a / 10 * c2;
426 + e2.beginPath(), e2.moveTo(d, 0), e2.lineTo(d, o), e2.stroke();
290 427 }
291 - l2(s2.color, 2, 1, false), a2 > 0 && l2(s2.progressColor, 3, a2, true);
428 + h(r.color, 2, 1, false), s > 0 && h(r.progressColor, 3, s, true);
292 429 }
293 -function U(t3, e2, i2, a2, s2) {
294 - let n2 = window.devicePixelRatio || 1, r2 = (s2.barWidth || 3) * n2, o2 = (s2.barSpacing || 1) * n2, h2 = Math.floor(e2.width / (r2 + o2)), l2 = S(i2, h2), d2 = e2.height, p2 = 4 * n2, y2 = 2 * n2, f2 = a2 * e2.width, c2 = d2 / 2;
295 - t3.clearRect(0, 0, e2.width, e2.height);
296 - for (let m2 = 0; m2 < l2.length; m2++) {
297 - let u2 = m2 * (r2 + o2);
298 - if (u2 + r2 > e2.width) break;
299 - let v2 = l2[m2] * d2 * 0.9, k = Math.floor(v2 / (p2 + y2));
300 - t3.fillStyle = u2 < f2 ? s2.progressColor : s2.color;
301 - for (let b2 = 0; b2 < k; b2++) {
302 - let w2 = b2 * (p2 + y2);
303 - t3.fillRect(u2, c2 - w2 - p2, r2, p2), b2 > 0 && t3.fillRect(u2, c2 + w2, r2, p2);
430 +function ut(e2, t, i, s, r) {
431 + let a = window.devicePixelRatio || 1, o = (r.barWidth || 3) * a, n = (r.barSpacing || 1) * a, l2 = Math.floor(t.width / (o + n)), h = B(i, l2), c2 = t.height, d = 4 * a, b = 2 * a, y2 = s * t.width, w2 = c2 / 2, f = P(e2, r.color, t, r), p2 = P(e2, r.progressColor, t, r);
432 + e2.clearRect(0, 0, t.width, t.height);
433 + for (let g2 = 0; g2 < h.length; g2++) {
434 + let u = g2 * (o + n);
435 + if (u + o > t.width) break;
436 + let k2 = h[g2] * c2 * 0.9, v2 = Math.floor(k2 / (d + b));
437 + e2.fillStyle = u < y2 ? p2 : f;
438 + for (let A2 = 0; A2 < v2; A2++) {
439 + let L = A2 * (d + b);
440 + e2.fillRect(u, w2 - L - d, o, d), A2 > 0 && e2.fillRect(u, w2 + L, o, d);
304 441 }
305 442 }
306 443 }
307 -function F(t3, e2, i2, a2, s2) {
308 - let n2 = window.devicePixelRatio || 1, r2 = (s2.barWidth || 2) * n2, o2 = (s2.barSpacing || 3) * n2, h2 = Math.floor(e2.width / (r2 + o2)), l2 = S(i2, h2), d2 = e2.height, p2 = Math.max(1.5 * n2, r2 / 2), y2 = a2 * e2.width, f2 = d2 / 2;
309 - t3.clearRect(0, 0, e2.width, e2.height);
310 - for (let c2 = 0; c2 < l2.length; c2++) {
311 - let m2 = c2 * (r2 + o2) + r2 / 2;
312 - if (m2 > e2.width) break;
313 - let u2 = l2[c2] * d2 * 0.9;
314 - t3.fillStyle = m2 < y2 ? s2.progressColor : s2.color, t3.beginPath(), t3.arc(m2, f2 - u2 / 2, p2, 0, Math.PI * 2), t3.fill(), t3.beginPath(), t3.arc(m2, f2 + u2 / 2, p2, 0, Math.PI * 2), t3.fill();
444 +function dt(e2, t, i, s, r) {
445 + let a = window.devicePixelRatio || 1, o = (r.barWidth || 2) * a, n = (r.barSpacing || 3) * a, l2 = Math.floor(t.width / (o + n)), h = B(i, l2), c2 = t.height, d = Math.max(1.5 * a, o / 2), b = s * t.width, y2 = c2 / 2, w2 = P(e2, r.color, t, r), f = P(e2, r.progressColor, t, r);
446 + e2.clearRect(0, 0, t.width, t.height);
447 + for (let p2 = 0; p2 < h.length; p2++) {
448 + let g2 = p2 * (o + n) + o / 2;
449 + if (g2 > t.width) break;
450 + let u = h[p2] * c2 * 0.9;
451 + e2.fillStyle = g2 < b ? f : w2, e2.beginPath(), e2.arc(g2, y2 - u / 2, d, 0, Math.PI * 2), e2.fill(), e2.beginPath(), e2.arc(g2, y2 + u / 2, d, 0, Math.PI * 2), e2.fill();
315 452 }
316 453 }
317 -function N2(t3, e2, i2, a2, s2) {
318 - let n2 = e2.width, r2 = e2.height, o2 = r2 / 2, h2 = 4, l2 = h2 / 2;
319 - if (t3.clearRect(0, 0, n2, r2), t3.fillStyle = s2.color || "rgba(255, 255, 255, 0.2)", t3.beginPath(), t3.moveTo(l2, o2 - h2 / 2), t3.lineTo(n2 - l2, o2 - h2 / 2), t3.arc(n2 - l2, o2, h2 / 2, -Math.PI / 2, Math.PI / 2), t3.lineTo(l2, o2 + h2 / 2), t3.arc(l2, o2, h2 / 2, Math.PI / 2, -Math.PI / 2), t3.closePath(), t3.fill(), a2 > 0) {
320 - let d2 = Math.max(l2 * 2, a2 * n2);
321 - t3.shadowBlur = 8, t3.shadowColor = s2.progressColor, t3.fillStyle = s2.progressColor || "rgba(255, 255, 255, 0.9)", t3.beginPath(), t3.moveTo(l2, o2 - h2 / 2), t3.lineTo(d2 - l2, o2 - h2 / 2), t3.arc(d2 - l2, o2, h2 / 2, -Math.PI / 2, Math.PI / 2), t3.lineTo(l2, o2 + h2 / 2), t3.arc(l2, o2, h2 / 2, Math.PI / 2, -Math.PI / 2), t3.closePath(), t3.fill(), t3.shadowBlur = 0;
322 - let p2 = 8, y2 = d2;
323 - t3.shadowBlur = 4, t3.shadowColor = "rgba(0, 0, 0, 0.3)", t3.shadowOffsetY = 2, t3.fillStyle = "#ffffff", t3.beginPath(), t3.arc(y2, o2, p2, 0, Math.PI * 2), t3.fill(), t3.shadowBlur = 0, t3.shadowOffsetY = 0, t3.fillStyle = s2.progressColor || "rgba(255, 255, 255, 0.9)", t3.beginPath(), t3.arc(y2, o2, p2 * 0.4, 0, Math.PI * 2), t3.fill();
454 +function At(e2, t, i, s, r) {
455 + let a = t.width, o = t.height, n = o / 2, l2 = 4, h = l2 / 2, c2 = !!r.seekActive;
456 + if (e2.clearRect(0, 0, a, o), e2.fillStyle = P(e2, r.color, t, r) || "rgba(255, 255, 255, 0.2)", ct(e2, h, a, n, l2), e2.fill(), s > 0) {
457 + let d = Math.max(h * 2, s * a);
458 + e2.save(), e2.globalAlpha = r.seekHandle && !c2 ? 0.7 : 1, e2.fillStyle = P(e2, r.progressColor, t, r) || "rgba(255, 255, 255, 0.9)", ct(e2, h, d, n, l2), e2.fill(), e2.restore();
324 459 }
325 460 }
326 -var Y = { bars: x2, mirror: q, line: $2, blocks: U, dots: F, seekbar: N2 };
327 -function W(t3, e2, i2, a2, s2) {
328 - (Y[s2.waveformStyle] || x2)(t3, e2, i2, a2, s2);
461 +var Mt = { bars: V, bar: V, mirror: Pt, line: Tt, blocks: ut, block: ut, dots: dt, dot: dt, seekbar: At };
462 +function ft(e2, t, i, s, r) {
463 + (Mt[r.waveformStyle] || V)(e2, t, i, s, r);
329 464 }
330 -function I(t3) {
465 +function mt(e2) {
331 466 try {
332 - let e2 = t3.getChannelData(0), i2 = t3.sampleRate, a2 = j2(e2, i2);
333 - if (a2.length < 2) return 120;
334 - let s2 = [];
335 - for (let h2 = 1; h2 < a2.length; h2++) s2.push((a2[h2] - a2[h2 - 1]) / i2);
336 - let n2 = {};
337 - s2.forEach((h2) => {
338 - let l2 = 60 / h2, d2 = Math.round(l2 / 3) * 3;
339 - d2 > 60 && d2 < 200 && (n2[d2] = (n2[d2] || 0) + 1);
467 + let t = e2.getChannelData(0), i = e2.sampleRate, s = Ct(t, i);
468 + if (s.length < 2) return 120;
469 + let r = [];
470 + for (let l2 = 1; l2 < s.length; l2++) r.push((s[l2] - s[l2 - 1]) / i);
471 + let a = {};
472 + r.forEach((l2) => {
473 + let h = 60 / l2, c2 = Math.round(h / 3) * 3;
474 + c2 > 60 && c2 < 200 && (a[c2] = (a[c2] || 0) + 1);
340 475 });
341 - let r2 = 0, o2 = 120;
342 - for (let [h2, l2] of Object.entries(n2)) l2 > r2 && (r2 = l2, o2 = parseInt(h2));
343 - return o2 < 70 && n2[o2 * 2] ? o2 *= 2 : o2 > 160 && n2[Math.round(o2 / 2)] && (o2 = Math.round(o2 / 2)), o2 - 1;
344 - } catch (e2) {
345 - return console.warn("BPM detection failed:", e2), null;
476 + let o = 0, n = 120;
477 + for (let [l2, h] of Object.entries(a)) h > o && (o = h, n = parseInt(l2));
478 + return n < 70 && a[n * 2] ? n *= 2 : n > 160 && a[Math.round(n / 2)] && (n = Math.round(n / 2)), n - 1;
479 + } catch (t) {
480 + return console.warn("[WaveformPlayer] BPM detection failed:", t), null;
346 481 }
347 482 }
348 -function j2(t3, e2) {
349 - let s2 = [], n2 = 0;
350 - for (let r2 = 0; r2 < t3.length - 2048; r2 += 1024) {
351 - let o2 = 0;
352 - for (let d2 = r2; d2 < r2 + 2048; d2++) o2 += t3[d2] * t3[d2];
353 - o2 = o2 / 2048;
354 - let h2 = o2 - n2, l2 = n2 * 1.8 + 0.01;
355 - if (h2 > l2 && o2 > 0.01) {
356 - let d2 = s2[s2.length - 1] || 0, p2 = e2 * 0.15;
357 - r2 - d2 > p2 && s2.push(r2);
483 +function Ct(e2, t) {
484 + let r = [], a = 0;
485 + for (let o = 0; o < e2.length - 2048; o += 1024) {
486 + let n = 0;
487 + for (let c2 = o; c2 < o + 2048; c2++) n += e2[c2] * e2[c2];
488 + n = n / 2048;
489 + let l2 = n - a, h = a * 1.8 + 0.01;
490 + if (l2 > h && n > 0.01) {
491 + let c2 = r[r.length - 1] || 0, d = t * 0.15;
492 + o - c2 > d && r.push(o);
358 493 }
359 - n2 = o2 * 0.8 + n2 * 0.2;
494 + a = n * 0.8 + a * 0.2;
360 495 }
361 - return s2;
496 + return r;
362 497 }
363 -function V(t3, e2 = 200) {
364 - let i2 = t3.length / e2, a2 = ~~(i2 / 10) || 1, s2 = t3.numberOfChannels, n2 = [];
365 - for (let o2 = 0; o2 < s2; o2++) {
366 - let h2 = t3.getChannelData(o2);
367 - for (let l2 = 0; l2 < e2; l2++) {
368 - let d2 = ~~(l2 * i2), p2 = ~~(d2 + i2), y2 = 0, f2 = 0;
369 - for (let m2 = d2; m2 < p2; m2 += a2) {
370 - let u2 = h2[m2];
371 - u2 > f2 && (f2 = u2), u2 < y2 && (y2 = u2);
498 +function Lt(e2, t = 1800) {
499 + let i = e2.length / t, s = e2.numberOfChannels, r = [];
500 + for (let o = 0; o < s; o++) {
501 + let n = e2.getChannelData(o);
502 + for (let l2 = 0; l2 < t; l2++) {
503 + let h = ~~(l2 * i), c2 = ~~(h + i), d = 0, b = 0;
504 + for (let w2 = h; w2 < c2; w2++) {
505 + let f = n[w2];
506 + f > b && (b = f), f < d && (d = f);
372 507 }
373 - let c2 = Math.max(Math.abs(f2), Math.abs(y2));
374 - (o2 === 0 || c2 > n2[l2]) && (n2[l2] = c2);
508 + let y2 = Math.max(Math.abs(b), Math.abs(d));
509 + (o === 0 || y2 > r[l2]) && (r[l2] = y2);
375 510 }
376 511 }
377 - let r2 = Math.max(...n2);
378 - return r2 > 0 ? n2.map((o2) => o2 / r2) : n2;
512 + let a = $2(r);
513 + return a > 0 ? r.map((o) => o / a) : r;
379 514 }
380 -async function M2(t3, e2 = 200, i2 = false) {
515 +async function G(e2, t = 1800, i = false) {
516 + let s;
381 517 try {
382 - let a2 = new (window.AudioContext || window.webkitAudioContext)(), n2 = await (await fetch(t3)).arrayBuffer(), r2 = await a2.decodeAudioData(n2), o2 = V(r2, e2);
383 - o2 = J(o2);
384 - let h2 = null;
385 - return i2 && (h2 = await I(r2)), a2.close(), { peaks: o2, bpm: h2 };
386 - } catch (a2) {
387 - throw console.error("Failed to generate waveform:", a2), a2;
518 + let r = window.AudioContext || window.webkitAudioContext;
519 + s = new r();
520 + let o = await (await fetch(e2)).arrayBuffer(), n = await s.decodeAudioData(o), l2 = Lt(n, t);
521 + l2 = _t(l2);
522 + let h = null;
523 + return i && (h = mt(n)), { peaks: l2, bpm: h };
524 + } finally {
525 + s && s.close();
388 526 }
389 527 }
390 -function D(t3 = 200) {
391 - let e2 = [];
392 - for (let i2 = 0; i2 < t3; i2++) {
393 - let a2 = Math.random() * 0.5 + 0.3, s2 = Math.sin(i2 / t3 * Math.PI * 4) * 0.2;
394 - e2.push(Math.max(0.1, Math.min(1, a2 + s2)));
528 +function yt(e2 = 1800) {
529 + let t = [];
530 + for (let i = 0; i < e2; i++) {
531 + let s = Math.random() * 0.5 + 0.3, r = Math.sin(i / e2 * Math.PI * 4) * 0.2;
532 + t.push(m2(s + r, 0.1, 1));
395 533 }
396 - return e2;
534 + return t;
397 535 }
398 -function J(t3, e2 = 0.95) {
399 - let i2 = Math.max(...t3);
400 - if (i2 === 0 || i2 > e2) return t3;
401 - let a2 = e2 / i2;
402 - return t3.map((s2) => s2 * a2);
536 +function _t(e2, t = 0.95) {
537 + let i = $2(e2);
538 + if (i === 0 || i > t) return e2;
539 + let s = t / i;
540 + return e2.map((r) => r * s);
403 541 }
404 -function G() {
405 - let t3 = document.documentElement, e2 = document.body;
406 - if (t3.classList.contains("dark") || t3.classList.contains("dark-mode") || t3.classList.contains("theme-dark") || t3.getAttribute("data-theme") === "dark" || t3.getAttribute("data-color-scheme") === "dark" || e2.classList.contains("dark") || e2.classList.contains("dark-mode") || e2.getAttribute("data-theme") === "dark") return "dark";
407 - if (t3.classList.contains("light") || t3.classList.contains("light-mode") || t3.classList.contains("theme-light") || t3.getAttribute("data-theme") === "light" || t3.getAttribute("data-color-scheme") === "light" || e2.classList.contains("light") || e2.classList.contains("light-mode") || e2.getAttribute("data-theme") === "light") return "light";
408 - try {
409 - let a2 = getComputedStyle(document.body).backgroundColor.match(/\d+/g);
410 - if (a2 && a2.length >= 3) {
411 - let [s2, n2, r2] = a2.map(Number), o2 = (s2 * 299 + n2 * 587 + r2 * 114) / 1e3;
412 - if (o2 > 128) return "light";
413 - if (o2 < 128) return "dark";
414 - }
415 - } catch {
542 +var K = 128;
543 +function gt(e2) {
544 + let t = document.documentElement, i = document.body;
545 + return t.classList.contains(e2) || t.classList.contains(`${e2}-mode`) || t.classList.contains(`theme-${e2}`) || t.getAttribute("data-theme") === e2 || t.getAttribute("data-color-scheme") === e2 || i.classList.contains(e2) || i.classList.contains(`${e2}-mode`) || i.getAttribute("data-theme") === e2;
546 +}
547 +function xt(e2) {
548 + let t = 0, i = 0;
549 + for (let s = e2; s && s.nodeType === 1 && i < 0.995; s = s.parentElement) {
550 + let r = U(getComputedStyle(s).backgroundColor);
551 + if (!r || r.a <= 0) continue;
552 + let a = r.a * (1 - i);
553 + t += (r.r * 299 + r.g * 587 + r.b * 114) / 1e3 * a, i += a;
416 554 }
555 + return { sum: t, alpha: i };
556 +}
557 +function Rt() {
558 + let e2 = lt(getComputedStyle(document.body).color);
559 + if (e2 !== null) return e2 > K ? "dark" : "light";
417 560 if (window.matchMedia) {
418 561 if (window.matchMedia("(prefers-color-scheme: dark)").matches) return "dark";
419 562 if (window.matchMedia("(prefers-color-scheme: light)").matches) return "light";
420 563 }
@@ -419,67 +562,130 @@
419 562 if (window.matchMedia("(prefers-color-scheme: light)").matches) return "light";
420 563 }
421 564 return "dark";
422 565 }
423 -var E = { dark: { waveformColor: "rgba(255, 255, 255, 0.3)", progressColor: "rgba(255, 255, 255, 0.9)", buttonColor: "rgba(255, 255, 255, 0.9)", buttonHoverColor: "rgba(255, 255, 255, 1)", textColor: "#ffffff", textSecondaryColor: "rgba(255, 255, 255, 0.6)", backgroundColor: "rgba(255, 255, 255, 0.03)", borderColor: "rgba(255, 255, 255, 0.1)" }, light: { waveformColor: "rgba(0, 0, 0, 0.2)", progressColor: "rgba(0, 0, 0, 0.8)", buttonColor: "rgba(0, 0, 0, 0.8)", buttonHoverColor: "rgba(0, 0, 0, 0.9)", textColor: "#333333", textSecondaryColor: "rgba(0, 0, 0, 0.6)", backgroundColor: "rgba(0, 0, 0, 0.02)", borderColor: "rgba(0, 0, 0, 0.1)" } };
424 -function z(t3) {
425 - if (t3 && E[t3]) return E[t3];
426 - let e2 = G();
427 - return E[e2];
566 +function R2(e2) {
567 + if (gt("dark")) return "dark";
568 + if (gt("light")) return "light";
569 + try {
570 + let t = e2 && e2.nodeType === 1 ? e2 : document.body, { sum: i, alpha: s } = xt(t), r = Rt(), a = i + (r === "dark" ? 0 : 255) * (1 - s);
571 + return a > K ? "light" : a < K ? "dark" : r;
572 + } catch {
573 + return "dark";
574 + }
428 575 }
429 -var O = { url: "", height: 60, samples: 200, preload: "metadata", playbackRate: 1, showPlaybackSpeed: false, playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2], buttonAlign: "auto", waveformStyle: "mirror", barWidth: 2, barSpacing: 0, colorPreset: null, waveformColor: null, progressColor: null, buttonColor: null, buttonHoverColor: null, textColor: null, textSecondaryColor: null, backgroundColor: null, borderColor: null, autoplay: false, showTime: true, showHoverTime: false, showBPM: false, singlePlay: true, playOnSeek: true, enableMediaSession: true, markers: [], showMarkers: true, title: null, subtitle: null, artwork: null, album: "", playIcon: '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M8 5v14l11-7z"/></svg>', pauseIcon: '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M6 4h4v16H6zM14 4h4v16h-4z"/></svg>', onLoad: null, onPlay: null, onPause: null, onEnd: null, onError: null, onTimeUpdate: null };
430 -var H2 = { bars: { barWidth: 3, barSpacing: 1 }, mirror: { barWidth: 2, barSpacing: 0 }, line: { barWidth: 2, barSpacing: 0 }, blocks: { barWidth: 4, barSpacing: 2 }, dots: { barWidth: 3, barSpacing: 3 }, seekbar: { barWidth: 1, barSpacing: 0 } };
431 -var g2 = class t2 {
576 +var C = { dark: { waveformColor: "rgba(255, 255, 255, 0.3)", progressColor: "rgba(255, 255, 255, 0.9)" }, light: { waveformColor: "rgba(0, 0, 0, 0.2)", progressColor: "rgba(0, 0, 0, 0.8)" } };
577 +function J(e2, t) {
578 + if (e2 && C[e2]) return C[e2];
579 + let i = R2(t);
580 + return C[i];
581 +}
582 +var W = { url: "", height: 64, samples: 1800, preload: "metadata", crossOrigin: null, audioMode: "self", playbackRate: 1, showPlaybackSpeed: false, playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2], buttonAlign: "auto", layout: "default", buttonStyle: "circle", buttonSize: null, buttonRadius: null, waveformStyle: "mirror", barWidth: 2, barSpacing: 0, barRadius: 1, waveformGradient: "vertical", colorPreset: null, waveformColor: null, progressColor: null, autoplay: false, showControls: true, showInfo: true, showTime: true, showHoverTime: false, seekHandle: false, showBPM: false, bpm: null, singlePlay: true, playOnSeek: true, enableMediaSession: true, markers: [], showMarkers: true, accessibleSeek: true, seekLabel: null, seekValueText: null, title: null, artist: null, artwork: null, artworkPosition: "info", album: "", errorText: "Unable to load audio", playPauseLabel: "Play/Pause", speedLabel: "Playback speed", artworkAlt: "Album artwork", unknownTrackText: "Unknown Track", playIcon: '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M8 5v14l11-7z"/></svg>', pauseIcon: '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M6 4h4v16H6zM14 4h4v16h-4z"/></svg>', onLoad: null, onPlay: null, onPause: null, onEnd: null, onError: null, onTimeUpdate: null, onNextTrack: null, onPreviousTrack: null };
583 +var X = { bars: { barWidth: 3, barSpacing: 1 }, mirror: { barWidth: 2, barSpacing: 2 }, line: { barWidth: 2, barSpacing: 0 }, blocks: { barWidth: 4, barSpacing: 2 }, dots: { barWidth: 3, barSpacing: 3 }, seekbar: { barWidth: 1, barSpacing: 0 } };
584 +var Q = ["auto", "top", "center", "bottom"];
585 +var N2 = 0.25;
586 +var F = 4;
587 +var Dt = { buttonAlign: Q, layout: ["default", "preview"], buttonStyle: ["circle", "minimal"], artworkPosition: ["info", "button"], waveformStyle: Object.keys(X), waveformGradient: ["vertical", "horizontal", "diagonal"], audioMode: ["self", "external"], preload: ["none", "metadata", "auto"], colorPreset: Object.keys(C), crossOrigin: ["anonymous", "use-credentials"] };
588 +var Bt = { height: { min: 1, integer: true }, samples: { min: 1, integer: true }, barWidth: { min: 0 }, barSpacing: { min: 0 }, barRadius: { min: 0 }, bpm: { min: 1 }, playbackRate: { min: N2, max: F } };
589 +var Ht = ["autoplay", "showControls", "showInfo", "showTime", "showHoverTime", "seekHandle", "showBPM", "singlePlay", "playOnSeek", "enableMediaSession", "showMarkers", "accessibleSeek", "showPlaybackSpeed"];
590 +var Ot = ["onLoad", "onPlay", "onPause", "onEnd", "onError", "onTimeUpdate", "onNextTrack", "onPreviousTrack"];
591 +function Y(e2, t) {
592 + console.warn(`[WaveformPlayer] Invalid ${e2} option, using default:`, t);
593 +}
594 +function z(e2) {
595 + let t = H2(e2);
596 + return t ? t.reduce((i, s) => {
597 + let r = s && typeof s == "object" ? _(s.time, null, { min: 0 }) : null;
598 + return r === null ? (Y("marker", s), i) : (i.push({ ...s, time: r, label: s.label == null ? "" : s.label }), i);
599 + }, []) : (e2 != null && Y("markers", e2), []);
600 +}
601 +function Z(e2) {
602 + let t = (s) => e2[s] != null, i = (s) => {
603 + Y(s, e2[s]), e2[s] = W[s];
604 + };
605 + for (let [s, r] of Object.entries(Bt)) {
606 + if (!t(s)) continue;
607 + let a = _(e2[s], null, r);
608 + a === null ? i(s) : e2[s] = a;
609 + }
610 + for (let [s, r] of Object.entries(Dt)) t(s) && rt(e2[s], r) === null && i(s);
611 + for (let s of Ht) e2[s] = at(e2[s]);
612 + for (let s of Ot) t(s) && typeof e2[s] != "function" && i(s);
613 + if (t("playbackRates")) {
614 + let s = D(e2.playbackRates, { min: N2, max: F, fallback: null });
615 + s === null ? i("playbackRates") : e2.playbackRates = s;
616 + }
617 + e2.markers = z(e2.markers);
618 + for (let s of ["buttonSize", "buttonRadius"]) {
619 + if (!t(s)) continue;
620 + let r = e2[s];
621 + (typeof r == "number" ? Number.isFinite(r) : typeof r == "string" && r.trim() !== "") || i(s);
622 + }
623 + for (let s of ["waveformColor", "progressColor"]) {
624 + if (!t(s)) continue;
625 + let r = e2[s];
626 + !(typeof r == "string" && r.trim() !== "") && !Array.isArray(r) && i(s);
627 + }
628 + return e2;
629 +}
630 +var It = "data:image/svg+xml," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect width="24" height="24" rx="4" fill="#71717a" fill-opacity="0.15"/><g fill="none" stroke="#a1a1aa" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="17" r="2.2"/><circle cx="17" cy="15" r="2.2"/><path d="M10.2 17V7l9-1.6v9"/></g></svg>');
631 +var bt = 5;
632 +var wt = 10;
633 +var Wt = 'button, a[href], input, [role="slider"]';
634 +var T = class e {
432 635 static instances = /* @__PURE__ */ new Map();
433 636 static currentlyPlaying = null;
434 - constructor(e2, i2 = {}) {
435 - if (this.container = typeof e2 == "string" ? document.querySelector(e2) : e2, !this.container) throw new Error("WaveformPlayer: Container element not found");
436 - let a2 = L(this.container);
437 - this.options = C(O, a2, i2);
438 - let s2 = z(this.options.colorPreset);
439 - for (let [r2, o2] of Object.entries(s2)) (this.options[r2] === null || this.options[r2] === void 0) && (this.options[r2] = o2);
440 - let n2 = H2[this.options.waveformStyle];
441 - n2 && (a2.barWidth === void 0 && i2.barWidth === void 0 && (this.options.barWidth = n2.barWidth), a2.barSpacing === void 0 && i2.barSpacing === void 0 && (this.options.barSpacing = n2.barSpacing)), this.audio = null, this.canvas = null, this.ctx = null, this.waveformData = [], this.progress = 0, this.isPlaying = false, this.isLoading = false, this.hasError = false, this.updateTimer = null, this.resizeObserver = null, this.id = this.container.id || A(this.options.url), t2.instances.set(this.id, this), this.init(), setTimeout(() => {
442 - this.container.dispatchEvent(new CustomEvent("waveformplayer:ready", { bubbles: true, detail: { player: this, url: this.options.url } }));
637 + constructor(t, i = {}) {
638 + if (this.container = typeof t == "string" ? document.querySelector(t) : t, !this.container) throw new Error("[WaveformPlayer] Container element not found");
639 + let s = O(this.container), r = { ...i };
640 + r.style && !r.waveformStyle && (r.waveformStyle = r.style), r.src && !r.url && (r.url = r.src), this.options = Z(j2(W, s, r));
641 + let a = J(this.options.colorPreset, this.container);
642 + this._autoTheme = this.options.colorPreset == null || !C[this.options.colorPreset], this._presetKeys = [], this._scheme = this.options.colorPreset && C[this.options.colorPreset] ? this.options.colorPreset : R2(this.container);
643 + for (let [n, l2] of Object.entries(a)) (this.options[n] === null || this.options[n] === void 0) && (this.options[n] = l2, this._presetKeys.push(n));
644 + let o = X[this.options.waveformStyle];
645 + o && (s.barWidth === void 0 && i.barWidth === void 0 && (this.options.barWidth = o.barWidth), s.barSpacing === void 0 && i.barSpacing === void 0 && (this.options.barSpacing = o.barSpacing)), this.audio = null, this.canvas = null, this.ctx = null, this.waveformData = [], this.progress = 0, this._activeMarkerIndex = -1, this._markerLabelTimer = null, this.isPlaying = false, this.isLoading = false, this.hasError = false, this.updateTimer = null, this.resizeObserver = null, this._ac = new AbortController(), this.id = this.container.id || nt(this.options.url), e.instances.set(this.id, this), e._watchTheme();
646 + try {
647 + this.init();
648 + } catch (n) {
649 + throw e.instances.delete(this.id), this._ac.abort(), n;
650 + }
651 + setTimeout(() => {
652 + this._emit("waveformplayer:ready", { player: this, url: this.options.url });
443 653 }, 100);
444 654 }
655 + _emit(t, i, s = false) {
656 + let r = new CustomEvent(t, { bubbles: true, cancelable: s, detail: i });
657 + return this.container.dispatchEvent(r), r;
658 + }
659 + _requestSeek(t) {
660 + this._emit("waveformplayer:request-seek", { ...this._buildTrackDetail(), percent: t }, true).defaultPrevented || (this.progress = t, this.drawWaveform?.());
661 + }
445 662 init() {
446 - this.createDOM(), this.createAudio(), this.initPlaybackSpeed(), this.initKeyboardControls(), this.bindEvents(), this.setupResizeObserver(), requestAnimationFrame(() => {
663 + this.createDOM(), this.createAudio(), this.initPlaybackSpeed(), this.initKeyboardControls(), this.initSeekControl(), this.bindEvents(), this.setupResizeObserver(), requestAnimationFrame(() => {
447 664 this.resizeCanvas(), this.options.url && this.load(this.options.url).then(() => {
448 - this.options.autoplay && this.play();
449 - }).catch((e2) => {
450 - console.error("Failed to load audio:", e2);
665 + this.options.autoplay && this.play()?.catch(() => {
666 + });
667 + }).catch((t) => {
668 + console.error("[WaveformPlayer] Failed to load audio:", t);
451 669 });
452 670 });
453 671 }
454 672 createDOM() {
455 673 this.container.innerHTML = "", this.container.className = "waveform-player";
456 - let e2 = this.options.buttonAlign;
457 - e2 === "auto" && (this.options.waveformStyle === "bars" ? e2 = "bottom" : e2 = "center"), this.container.innerHTML = `
458 - <div class="waveform-player-inner">
459 - <div class="waveform-body">
460 - <div class="waveform-track waveform-align-${e2}">
461 - <button class="waveform-btn" aria-label="Play/Pause" style="
462 - border-color: ${this.options.buttonColor};
463 - color: ${this.options.buttonColor};
464 - ">
674 + let t = Q.includes(this.options.buttonAlign) ? this.options.buttonAlign : "auto";
675 + t === "auto" && (this.options.waveformStyle === "bars" ? t = "bottom" : t = "center"), this.options.layout === "preview" && this.container.classList.add("waveform-layout-preview"), this.container.classList.toggle("waveform-theme-light", this._scheme === "light");
676 + let s = [];
677 + this.options.buttonSize != null && s.push(`--wfp-btn-size: ${q2(this.options.buttonSize)}`), this.options.buttonRadius != null && s.push(`--wfp-btn-radius: ${q2(this.options.buttonRadius)}`);
678 + let r = s.length ? ` style="${s.join("; ")};"` : "", a = this.options.artworkPosition === "button" && this.options.artwork, o = a ? `<img class="waveform-btn-artwork" src="${S(this.options.artwork)}" alt="" aria-hidden="true">` : "", n = this.options.showControls ? `
679 + <button class="waveform-btn${this.options.buttonStyle === "minimal" ? " waveform-btn-minimal" : ""}${a ? " waveform-btn-has-artwork" : ""}" aria-label="${S(this.options.playPauseLabel)}"${r}>
680 + ${o}
465 681 <span class="waveform-icon-play">${this.options.playIcon}</span>
466 682 <span class="waveform-icon-pause" style="display:none;">${this.options.pauseIcon}</span>
467 683 </button>
468 -
469 - <div class="waveform-container">
470 - <canvas></canvas>
471 - <div class="waveform-markers"></div>
472 - <div class="waveform-loading" style="display:none;"></div>
473 - <div class="waveform-error" style="display:none;">
474 - <span class="waveform-error-text">Unable to load audio</span>
475 - </div>
476 - </div>
477 - </div>
478 -
684 + ` : "", l2 = this.options.showInfo ? `
479 685 <div class="waveform-info">
480 - ${this.options.artwork ? `
481 - <img class="waveform-artwork" src="${this.options.artwork}" alt="Album artwork" style="
686 + ${this.options.artworkPosition !== "button" && this.options.artwork ? `
687 + <img class="waveform-artwork" src="${S(this.options.artwork)}" alt="${S(this.options.artworkAlt)}" style="
482 688 width: 40px;
483 689 height: 40px;
484 690 border-radius: 4px;
485 691 object-fit: cover;
@@ -486,84 +692,313 @@
486 692 flex-shrink: 0;
487 693 ">
488 694 ` : ""}
489 695 <div class="waveform-text">
490 - <span class="waveform-title" style="color: ${this.options.textColor};"></span>
491 - ${this.options.subtitle ? `<span class="waveform-subtitle" style="color: ${this.options.textSecondaryColor};">${this.options.subtitle}</span>` : ""}
696 + <span class="waveform-title"></span>
697 + ${this.options.artist ? `<span class="waveform-artist">${S(this.options.artist)}</span>` : ""}
492 698 </div>
493 - <div style="display: flex; align-items: center; gap: 1rem;">
699 + <div class="waveform-meta" style="display: flex; align-items: center; gap: 1rem;">
494 700 ${this.options.showBPM ? `
495 - <span class="waveform-bpm" style="color: ${this.options.textSecondaryColor}; display: none;">
701 + <span class="waveform-bpm" style="display: none;">
496 702 <span class="bpm-value">--</span> BPM
497 703 </span>
498 704 ` : ""}
499 705 ${this.options.showPlaybackSpeed ? `
500 706 <div class="waveform-speed">
501 - <button class="speed-btn" aria-label="Playback speed">
707 + <button class="speed-btn" aria-label="${S(this.options.speedLabel)}" aria-haspopup="menu" aria-expanded="false">
502 708 <span class="speed-value">1x</span>
503 709 </button>
504 - <div class="speed-menu" style="display: none;">
505 - ${this.options.playbackRates.map((i2) => `<button class="speed-option" data-rate="${i2}">${i2}x</button>`).join("")}
710 + <div class="speed-menu" role="menu" aria-label="${S(this.options.speedLabel)}" style="display: none;">
711 + ${this.options.playbackRates.map((h) => `<button class="speed-option" role="menuitemradio" tabindex="-1" aria-checked="false" data-rate="${h}">${h}x</button>`).join("")}
506 712 </div>
507 713 </div>
508 714 ` : ""}
509 715 ${this.options.showTime ? `
510 - <span class="waveform-time" style="color: ${this.options.textSecondaryColor};">
716 + <span class="waveform-time">
511 717 <span class="time-current">0:00</span> / <span class="time-total">0:00</span>
512 718 </span>
513 719 ` : ""}
514 720 </div>
515 721 </div>
722 + ` : "";
723 + this.container.innerHTML = `
724 + <div class="waveform-player-inner">
725 + <div class="waveform-body">
726 + <div class="waveform-track waveform-align-${t}">
727 + ${n}
728 +
729 + <div class="waveform-container">
730 + <canvas></canvas>
731 + <div class="waveform-markers"></div>
732 + <div class="waveform-loading" style="display:none;"></div>
733 + <div class="waveform-error" style="display:none;" role="alert">
734 + <span class="waveform-error-text">${S(this.options.errorText)}</span>
735 + </div>
736 + </div>
737 + </div>
738 +
739 + ${l2}
516 740 </div>
517 741 </div>
518 -`, this.playBtn = this.container.querySelector(".waveform-btn"), this.canvas = this.container.querySelector("canvas"), this.ctx = this.canvas.getContext("2d"), this.titleEl = this.container.querySelector(".waveform-title"), this.subtitleEl = this.container.querySelector(".waveform-subtitle"), this.artworkEl = this.container.querySelector(".waveform-artwork"), this.currentTimeEl = this.container.querySelector(".time-current"), this.totalTimeEl = this.container.querySelector(".time-total"), this.bpmEl = this.container.querySelector(".waveform-bpm"), this.bpmValueEl = this.container.querySelector(".bpm-value"), this.loadingEl = this.container.querySelector(".waveform-loading"), this.errorEl = this.container.querySelector(".waveform-error"), this.markersContainer = this.container.querySelector(".waveform-markers"), this.speedBtn = this.container.querySelector(".speed-btn"), this.speedMenu = this.container.querySelector(".speed-menu"), this.resizeCanvas();
742 +`, this.playBtn = this.container.querySelector(".waveform-btn"), this.canvas = this.container.querySelector("canvas"), this.ctx = this.canvas.getContext("2d"), this.titleEl = this.container.querySelector(".waveform-title"), this.artistEl = this.container.querySelector(".waveform-artist"), this.artworkEl = this.container.querySelector(".waveform-artwork, .waveform-btn-artwork"), this.bindArtworkFallback(this.artworkEl), this.currentTimeEl = this.container.querySelector(".time-current"), this.totalTimeEl = this.container.querySelector(".time-total"), this.bpmEl = this.container.querySelector(".waveform-bpm"), this.bpmValueEl = this.container.querySelector(".bpm-value"), this.loadingEl = this.container.querySelector(".waveform-loading"), this.errorEl = this.container.querySelector(".waveform-error"), this.markersContainer = this.container.querySelector(".waveform-markers"), this.speedBtn = this.container.querySelector(".speed-btn"), this.speedMenu = this.container.querySelector(".speed-menu"), this.resizeCanvas(), this.updateBPMDisplay();
519 743 }
744 + bindArtworkFallback(t) {
745 + t && t.addEventListener("error", () => {
746 + t.src.startsWith("data:") || (t.src = It);
747 + }, { signal: this._ac.signal });
748 + }
749 + createArtworkElement() {
750 + let t = document.createElement("img");
751 + return t.className = "waveform-artwork", t.style.width = "40px", t.style.height = "40px", t.style.borderRadius = "4px", t.style.objectFit = "cover", t.style.flexShrink = "0", this.bindArtworkFallback(t), t;
752 + }
753 + createButtonArtworkElement() {
754 + let t = document.createElement("img");
755 + return t.className = "waveform-btn-artwork", t.alt = "", t.setAttribute("aria-hidden", "true"), this.bindArtworkFallback(t), t;
756 + }
757 + createArtistElement() {
758 + let t = document.createElement("span");
759 + return t.className = "waveform-artist", t;
760 + }
761 + syncArtist(t) {
762 + if (this.options.artist = t || null, !!this.options.showInfo) {
763 + if (!t) {
764 + this.artistEl?.remove(), this.artistEl = null;
765 + return;
766 + }
767 + if (!this.artistEl) {
768 + let i = this.container.querySelector(".waveform-title");
769 + if (!i) return;
770 + this.artistEl = this.createArtistElement(), i.after(this.artistEl);
771 + }
772 + this.artistEl.textContent = t, this.artistEl.style.display = "";
773 + }
774 + }
775 + syncButtonArtwork(t) {
776 + if (this.playBtn) {
777 + if (!t) {
778 + this.artworkEl?.remove(), this.artworkEl = null, this.playBtn.classList.remove("waveform-btn-has-artwork");
779 + return;
780 + }
781 + this.artworkEl || (this.artworkEl = this.createButtonArtworkElement(), this.playBtn.prepend(this.artworkEl)), this.artworkEl.src = t, this.playBtn.classList.add("waveform-btn-has-artwork");
782 + }
783 + }
784 + syncArtwork(t, i = "") {
785 + if (this.options.artwork = t || null, this.options.artworkAlt = i || "", this.options.artworkPosition === "button") {
786 + this.syncButtonArtwork(this.options.artwork);
787 + return;
788 + }
789 + if (this.options.showInfo) {
790 + if (!t) {
791 + this.artworkEl?.remove(), this.artworkEl = null;
792 + return;
793 + }
794 + if (!this.artworkEl) {
795 + let s = this.container.querySelector(".waveform-text");
796 + if (!s) return;
797 + this.artworkEl = this.createArtworkElement(), s.before(this.artworkEl);
798 + }
799 + this.artworkEl.src = t, this.artworkEl.alt = i || "";
800 + }
801 + }
520 802 createAudio() {
521 - this.audio = new Audio(), this.audio.preload = this.options.preload || "metadata", this.audio.crossOrigin = "anonymous";
803 + if (this.options.audioMode === "external") {
804 + this.audio = null;
805 + return;
806 + }
807 + this.audio = new Audio(), this.audio.preload = this.options.preload || "metadata", this.options.crossOrigin && (this.audio.crossOrigin = this.options.crossOrigin);
522 808 }
523 809 initPlaybackSpeed() {
524 - this.options.playbackRate && this.options.playbackRate !== 1 && (this.audio.playbackRate = this.options.playbackRate), this.options.showPlaybackSpeed && this.initSpeedControls();
810 + this.audio && this.options.playbackRate && this.options.playbackRate !== 1 && (this.audio.playbackRate = this.options.playbackRate), this.options.showPlaybackSpeed && this.initSpeedControls();
525 811 }
526 812 initSpeedControls() {
527 - let e2 = this.container.querySelector(".speed-btn"), i2 = this.container.querySelector(".speed-menu");
528 - !e2 || !i2 || (e2.addEventListener("click", (a2) => {
529 - a2.stopPropagation(), i2.style.display = i2.style.display === "none" ? "block" : "none";
530 - }), document.addEventListener("click", () => {
531 - i2.style.display = "none";
532 - }), i2.addEventListener("click", (a2) => {
533 - if (a2.stopPropagation(), a2.target.classList.contains("speed-option")) {
534 - let s2 = parseFloat(a2.target.dataset.rate);
535 - this.setPlaybackRate(s2), i2.style.display = "none";
813 + let t = this.container.querySelector(".speed-btn"), i = this.container.querySelector(".speed-menu");
814 + if (!t || !i) return;
815 + let s = () => Array.from(i.querySelectorAll(".speed-option")), r = () => i.style.display !== "none", a = (l2) => {
816 + if (i.style.display = l2 ? "block" : "none", t.setAttribute("aria-expanded", l2 ? "true" : "false"), l2) {
817 + let h = s();
818 + (h.find((c2) => c2.getAttribute("aria-checked") === "true") || h[0])?.focus();
536 819 }
537 - }), this.updateSpeedUI());
820 + }, o = (l2) => {
821 + let h = s();
822 + h.length && h[(l2 + h.length) % h.length].focus();
823 + }, n = (l2) => {
824 + this.setPlaybackRate(parseFloat(l2.dataset.rate)), a(false), t.focus();
825 + };
826 + t.addEventListener("click", (l2) => {
827 + l2.stopPropagation(), a(!r());
828 + }, { signal: this._ac.signal }), document.addEventListener("click", () => a(false), { signal: this._ac.signal }), i.addEventListener("click", (l2) => {
829 + l2.stopPropagation();
830 + let h = l2.target.closest(".speed-option");
831 + h && n(h);
832 + }, { signal: this._ac.signal }), t.closest(".waveform-speed")?.addEventListener("keydown", (l2) => {
833 + let h = s(), c2 = h.indexOf(document.activeElement);
834 + if (!r()) {
835 + (l2.key === "ArrowDown" || l2.key === "ArrowUp") && document.activeElement === t && (l2.preventDefault(), a(true));
836 + return;
837 + }
838 + switch (l2.key) {
839 + case "ArrowDown":
840 + l2.preventDefault(), o(c2 < 0 ? 0 : c2 + 1);
841 + break;
842 + case "ArrowUp":
843 + l2.preventDefault(), o(c2 < 0 ? h.length - 1 : c2 - 1);
844 + break;
845 + case "Home":
846 + l2.preventDefault(), o(0);
847 + break;
848 + case "End":
849 + l2.preventDefault(), o(h.length - 1);
850 + break;
851 + case "Escape":
852 + l2.preventDefault(), a(false), t.focus();
853 + break;
854 + case "Tab":
855 + a(false);
856 + break;
857 + }
858 + }, { signal: this._ac.signal }), this.updateSpeedUI();
538 859 }
539 860 initKeyboardControls() {
540 - this.container.setAttribute("tabindex", "-1"), this.container.addEventListener("click", () => {
541 - t2.getAllInstances().forEach((e2) => {
542 - e2 !== this && e2.container.setAttribute("tabindex", "-1");
543 - }), this.container.setAttribute("tabindex", "0"), this.container.focus();
544 - }), this.container.addEventListener("keydown", (e2) => {
861 + this.container.setAttribute("tabindex", "-1"), this.container.addEventListener("click", (t) => {
862 + t.target.closest(Wt) || (e.getAllInstances().forEach((i) => {
863 + i !== this && i.container.setAttribute("tabindex", "-1");
864 + }), this.container.setAttribute("tabindex", "0"), this.container.focus());
865 + }, { signal: this._ac.signal }), this.container.addEventListener("keydown", (t) => {
545 866 if (document.activeElement !== this.container) return;
546 - let i2 = e2.key, a2 = this.audio.currentTime;
547 - if (i2 >= "0" && i2 <= "9") {
548 - e2.preventDefault(), this.seekToPercent(parseInt(i2) / 10);
867 + let i = t.key, s = !!this.audio, r = s ? this.audio.currentTime : 0;
868 + if (s && i >= "0" && i <= "9") {
869 + t.preventDefault(), this.seekToPercent(parseInt(i) / 10);
549 870 return;
550 871 }
551 - let s2 = { " ": () => this.togglePlay(), ArrowLeft: () => this.seekTo(Math.max(0, a2 - 5)), ArrowRight: () => this.seekTo(Math.min(this.audio.duration, a2 + 5)), ArrowUp: () => this.setVolume(Math.min(1, this.audio.volume + 0.1)), ArrowDown: () => this.setVolume(Math.max(0, this.audio.volume - 0.1)), m: () => this.audio.muted = !this.audio.muted, M: () => this.audio.muted = !this.audio.muted };
552 - s2[i2] && (e2.preventDefault(), s2[i2]());
553 - });
872 + let a = { " ": () => this.togglePlay() };
873 + s && (a.ArrowLeft = () => this.seekTo(m2(r - 5, 0, this.audio.duration)), a.ArrowRight = () => this.seekTo(m2(r + 5, 0, this.audio.duration)), a.ArrowUp = () => this.setVolume(m2(this.audio.volume + 0.1)), a.ArrowDown = () => this.setVolume(m2(this.audio.volume - 0.1)), a.m = a.M = () => this.audio.muted = !this.audio.muted), a[i] && (t.preventDefault(), a[i]());
874 + }, { signal: this._ac.signal });
554 875 }
876 + initSeekControl() {
877 + this.options.accessibleSeek && (this.seekEl = this.container.querySelector(".waveform-container"), this.seekEl && (this.seekEl.setAttribute("role", "slider"), this.seekEl.setAttribute("tabindex", "0"), this.seekEl.setAttribute("aria-valuemin", "0"), this.applySeekLabel(), this.updateSeekAccessibility(), this.seekEl.addEventListener("keydown", (t) => {
878 + if (t.key === " " || t.key === "Spacebar") {
879 + t.preventDefault(), t.stopPropagation(), this.togglePlay();
880 + return;
881 + }
882 + let i = this.getSeekDuration();
883 + if (!i) return;
884 + let s = this.getSeekCurrentTime(), r;
885 + switch (t.key) {
886 + case "ArrowLeft":
887 + case "ArrowDown":
888 + r = s - bt;
889 + break;
890 + case "ArrowRight":
891 + case "ArrowUp":
892 + r = s + bt;
893 + break;
894 + case "PageDown":
895 + r = s - wt;
896 + break;
897 + case "PageUp":
898 + r = s + wt;
899 + break;
900 + case "Home":
901 + r = 0;
902 + break;
903 + case "End":
904 + r = i;
905 + break;
906 + default:
907 + return;
908 + }
909 + t.preventDefault(), t.stopPropagation(), this.seekToSeconds(r);
910 + }, { signal: this._ac.signal })));
911 + }
912 + getSeekDuration() {
913 + return this.options.audioMode === "external" ? this._extDuration || 0 : this.audio && Number.isFinite(this.audio.duration) ? this.audio.duration : 0;
914 + }
915 + getSeekCurrentTime() {
916 + return this.options.audioMode === "external" ? this.progress * (this._extDuration || 0) : this.audio && Number.isFinite(this.audio.currentTime) ? this.audio.currentTime : 0;
917 + }
918 + seekToSeconds(t) {
919 + let i = this.getSeekDuration();
920 + if (!i) return;
921 + let s = m2(t, 0, i);
922 + if (this.options.audioMode === "external") {
923 + this._requestSeek(s / i), this.updateSeekAccessibility();
924 + return;
925 + }
926 + this.seekTo(s);
927 + }
928 + applySeekLabel(t = this.options.title) {
929 + if (!this.seekEl) return;
930 + let i = this.options.seekLabel || t || "Seek";
931 + this.seekEl.setAttribute("aria-label", i);
932 + }
933 + updateSeekAccessibility() {
934 + if (!this.seekEl) return;
935 + let t = this.getSeekDuration(), i = Math.min(this.getSeekCurrentTime(), t);
936 + this.seekEl.setAttribute("aria-valuemax", String(Math.round(t))), this.seekEl.setAttribute("aria-valuenow", String(Math.round(i))), this.seekEl.setAttribute("aria-valuetext", ot(this.options.seekValueText || "%1$s of %2$s", E2(i), E2(t)));
937 + }
555 938 initMediaSession() {
556 - !("mediaSession" in navigator) || !this.options.enableMediaSession || (navigator.mediaSession.metadata = new MediaMetadata({ title: this.options.title || "Unknown Track", artist: this.options.subtitle || "", album: this.options.album || "", artwork: this.options.artwork ? [{ src: this.options.artwork, sizes: "512x512", type: "image/jpeg" }] : [] }), navigator.mediaSession.setActionHandler("play", () => this.play()), navigator.mediaSession.setActionHandler("pause", () => this.pause()), navigator.mediaSession.setActionHandler("seekbackward", () => {
557 - this.seekTo(Math.max(0, this.audio.currentTime - 10));
939 + if (!("mediaSession" in navigator) || !this.options.enableMediaSession || !this.audio) return;
940 + this._applyMediaMetadata(), navigator.mediaSession.setActionHandler("play", () => this.play()), navigator.mediaSession.setActionHandler("pause", () => this.pause()), navigator.mediaSession.setActionHandler("seekbackward", () => {
941 + this.seekTo(m2(this.audio.currentTime - 10, 0, this.audio.duration));
558 942 }), navigator.mediaSession.setActionHandler("seekforward", () => {
559 - this.seekTo(Math.min(this.audio.duration, this.audio.currentTime + 10));
560 - }), navigator.mediaSession.setActionHandler("seekto", (e2) => {
561 - e2.seekTime !== null && this.seekTo(e2.seekTime);
562 - }));
943 + this.seekTo(m2(this.audio.currentTime + 10, 0, this.audio.duration));
944 + }), navigator.mediaSession.setActionHandler("seekto", (s) => {
945 + s.seekTime !== null && this.seekTo(s.seekTime);
946 + });
947 + let t = this.options.onNextTrack, i = this.options.onPreviousTrack;
948 + try {
949 + navigator.mediaSession.setActionHandler("nexttrack", typeof t == "function" ? () => t(this) : null);
950 + } catch {
951 + }
952 + try {
953 + navigator.mediaSession.setActionHandler("previoustrack", typeof i == "function" ? () => i(this) : null);
954 + } catch {
955 + }
563 956 }
957 + _applyMediaMetadata() {
958 + !("mediaSession" in navigator) || !this.options.enableMediaSession || (navigator.mediaSession.metadata = new MediaMetadata({ title: this.options.title || this.options.unknownTrackText, artist: this.options.artist || "", album: this.options.album || "", artwork: this.options.artwork ? [{ src: this.options.artwork, sizes: "512x512", type: "image/jpeg" }] : [] }));
959 + }
960 + _updateMediaSession(t) {
961 + if (!(!("mediaSession" in navigator) || !this.options.enableMediaSession || !this.audio)) try {
962 + t === "playing" && this.initMediaSession(), navigator.mediaSession.playbackState = t;
963 + let i = this.audio.duration;
964 + navigator.mediaSession.setPositionState && i && isFinite(i) && navigator.mediaSession.setPositionState({ duration: i, playbackRate: this.audio.playbackRate || 1, position: m2(this.audio.currentTime, 0, i) });
965 + } catch {
966 + }
967 + }
564 968 bindEvents() {
565 - this.playBtn.addEventListener("click", () => this.togglePlay()), this.audio.addEventListener("loadstart", () => this.setLoading(true)), this.audio.addEventListener("loadedmetadata", () => this.onMetadataLoaded()), this.audio.addEventListener("canplay", () => this.setLoading(false)), this.audio.addEventListener("play", () => this.onPlay()), this.audio.addEventListener("pause", () => this.onPause()), this.audio.addEventListener("ended", () => this.onEnded()), this.audio.addEventListener("error", (e2) => this.onError(e2)), this.canvas.addEventListener("click", (e2) => this.handleCanvasClick(e2)), this.resizeHandler = B(() => this.resizeCanvas(), 100), window.addEventListener("resize", this.resizeHandler);
969 + this.playBtn && this.playBtn.addEventListener("click", () => this.togglePlay()), this.audio && (this.audio.addEventListener("loadstart", () => this.setLoading(true)), this.audio.addEventListener("loadedmetadata", () => this.onMetadataLoaded()), this.audio.addEventListener("canplay", () => this.setLoading(false)), this.audio.addEventListener("play", () => this.onPlay()), this.audio.addEventListener("pause", () => this.onPause()), this.audio.addEventListener("ended", () => this.onEnded()), this.audio.addEventListener("error", (i) => this.onError(i))), this.canvas.addEventListener("click", (i) => this.handleCanvasClick(i)), this._dragging = false, this._seekHover = false, this._handleNear = false, this.canvas.addEventListener("pointerenter", () => {
970 + this._seekHover = true, this.drawWaveform(), this._updateSeekHandle();
971 + }), this.canvas.addEventListener("pointerleave", () => {
972 + this._seekHover = false, this._handleNear = false, this._dragging || this._hideHoverTip(), this.drawWaveform(), this._updateSeekHandle();
973 + }), this.canvas.addEventListener("pointerdown", (i) => {
974 + if (!(i.pointerType === "mouse" && i.button !== 0)) {
975 + this._dragging = true;
976 + try {
977 + this.canvas.setPointerCapture(i.pointerId);
978 + } catch {
979 + }
980 + this._scrubTo(i.clientX);
981 + }
982 + }), this.canvas.addEventListener("pointermove", (i) => {
983 + if (this._dragging) {
984 + this._scrubTo(i.clientX);
985 + return;
986 + }
987 + let s = this.canvas.getBoundingClientRect();
988 + s.width && (this._handleNear = Math.abs(i.clientX - s.left - this.progress * s.width) <= 10, this._updateSeekHandle());
989 + });
990 + let t = (i) => {
991 + if (this._dragging) {
992 + this._dragging = false, this._suppressClick = true;
993 + try {
994 + this.canvas.releasePointerCapture(i.pointerId);
995 + } catch {
996 + }
997 + this._seekFromPointer(i.clientX), !this._seekHover && !this.options.showHoverTime && this._hideHoverTip(), this._updateSeekHandle();
998 + }
999 + };
1000 + this.canvas.addEventListener("pointerup", t), this.canvas.addEventListener("pointercancel", t), this.setupHoverTime(), this.setupSeekHandle(), this.resizeHandler = ht(() => this.resizeCanvas(), 100), window.addEventListener("resize", this.resizeHandler);
566 1001 }
567 1002 setupResizeObserver() {
568 1003 "ResizeObserver" in window && (this.resizeObserver = new ResizeObserver(() => {
569 1004 this.resizeCanvas();
@@ -568,200 +1003,492 @@
568 1003 "ResizeObserver" in window && (this.resizeObserver = new ResizeObserver(() => {
569 1004 this.resizeCanvas();
570 1005 }), this.canvas?.parentElement && this.resizeObserver.observe(this.canvas.parentElement));
571 1006 }
572 - async load(e2) {
1007 + async load(t) {
573 1008 try {
574 - this.setLoading(true), this.progress = 0, this.hasError = false, this.audio.src = e2, await new Promise((a2, s2) => {
575 - let n2 = () => {
576 - this.audio.removeEventListener("loadedmetadata", n2), this.audio.removeEventListener("error", r2), a2();
577 - }, r2 = (o2) => {
578 - this.audio.removeEventListener("loadedmetadata", n2), this.audio.removeEventListener("error", r2), s2(o2);
1009 + this.setLoading(true), this.progress = 0, this.hasError = false, this.container.classList.remove("waveform-is-placeholder");
1010 + let i = !!this.options.waveform;
1011 + i && this.setWaveformData(this.options.waveform);
1012 + let s = this.options.title || I(t);
1013 + if (this.titleEl && (this.titleEl.textContent = s), this.applySeekLabel(s), this.audio && (this.audio.src = t, this.audio.preload !== "none" && await new Promise((r, a) => {
1014 + let o = () => {
1015 + this.audio.removeEventListener("loadedmetadata", o), this.audio.removeEventListener("error", n), r();
1016 + }, n = (l2) => {
1017 + this.audio.removeEventListener("loadedmetadata", o), this.audio.removeEventListener("error", n), a(l2);
579 1018 };
580 - this.audio.addEventListener("loadedmetadata", n2), this.audio.addEventListener("error", r2);
581 - });
582 - let i2 = this.options.title || R(e2);
583 - if (this.titleEl && (this.titleEl.textContent = i2), this.options.waveform) this.setWaveformData(this.options.waveform);
584 - else try {
585 - let a2 = await M2(e2, this.options.samples, this.options.showBPM);
586 - this.waveformData = a2.peaks, a2.bpm && (this.detectedBPM = a2.bpm, this.updateBPMDisplay());
587 - } catch (a2) {
588 - console.warn("Using placeholder waveform:", a2), this.waveformData = D(this.options.samples);
1019 + this.audio.addEventListener("loadedmetadata", o), this.audio.addEventListener("error", n);
1020 + })), !i) try {
1021 + let r = await G(t, this.options.samples, this.options.showBPM);
1022 + this.waveformData = r.peaks, r.bpm && (this.detectedBPM = r.bpm, this.updateBPMDisplay());
1023 + } catch (r) {
1024 + console.warn("[WaveformPlayer] Using placeholder waveform:", r), this.waveformData = yt(this.options.samples), this.container.classList.add("waveform-is-placeholder");
589 1025 }
590 - this.drawWaveform(), this.renderMarkers(), this.initMediaSession(), this.options.onLoad && this.options.onLoad(this);
591 - } catch (i2) {
592 - console.error("Failed to load audio:", i2), this.onError(i2);
1026 + this.drawWaveform(), this.renderMarkers(), this.options.onLoad && this.options.onLoad(this);
1027 + } catch (i) {
1028 + this.onError(i);
593 1029 } finally {
594 1030 this.setLoading(false);
595 1031 }
596 1032 }
597 - async loadTrack(e2, i2 = null, a2 = null, s2 = {}) {
598 - this.isPlaying && this.pause(), this.audio.src = "", this.audio.load(), this.hasError = false, this.errorEl && (this.errorEl.style.display = "none"), this.canvas && (this.canvas.style.opacity = "1"), this.playBtn && (this.playBtn.disabled = false), this.progress = 0, this.waveformData = [], this.options = C(this.options, { url: e2, title: i2 || this.options.title, subtitle: a2 || this.options.subtitle, ...s2 }), s2.preload && (this.audio.preload = s2.preload), this.subtitleEl && (a2 ? (this.subtitleEl.textContent = a2, this.subtitleEl.style.display = "") : a2 === "" && (this.subtitleEl.style.display = "none")), s2.artwork && this.artworkEl && (this.artworkEl.src = s2.artwork), s2.markers && (this.options.markers = s2.markers), await this.load(e2), this.play();
1033 + async loadTrack(t, i = null, s = null, r = {}) {
1034 + let a = Object.prototype.hasOwnProperty.call(r, "artwork"), o = Object.prototype.hasOwnProperty.call(r, "artworkAlt");
1035 + this.isPlaying && this.pause(), this.audio && (this.audio.src = "", this.audio.load()), this.hasError = false, this.errorEl && (this.errorEl.style.display = "none"), this.canvas && (this.canvas.style.opacity = "1"), this.playBtn && (this.playBtn.disabled = false), this.progress = 0, this.waveformData = [], this.options = Z(j2(this.options, { url: t, title: i === null ? this.options.title : i, artist: s === null ? this.options.artist : s, ...r })), a && (this.options.artwork = r.artwork || null), o ? this.options.artworkAlt = r.artworkAlt || "" : a && (this.options.artworkAlt = this.options.artwork ? W.artworkAlt : ""), r.preload && this.audio && (this.audio.preload = this.options.preload), r.crossOrigin && this.audio && (this.audio.crossOrigin = this.options.crossOrigin), s !== null && this.syncArtist(s), (a || o) && this.syncArtwork(a ? r.artwork : this.options.artwork, o ? r.artworkAlt : this.options.artworkAlt), this.options.markers = r.markers ? z(r.markers) : [], this.options.waveform = r.waveform || null, await this.load(t), r.autoplay !== false && this.play()?.catch(() => {
1036 + });
599 1037 }
600 - setWaveformData(e2) {
601 - if (typeof e2 == "string") try {
602 - let i2 = JSON.parse(e2);
603 - this.waveformData = Array.isArray(i2) ? i2 : [];
604 - } catch {
605 - this.waveformData = e2.split(",").map(Number);
1038 + setWaveformData(t) {
1039 + if (typeof t == "string" && t.trim().endsWith(".json")) {
1040 + fetch(t.trim()).then((i) => i.json()).then((i) => {
1041 + this.waveformData = Array.isArray(i) ? i : i.peaks || [], i.markers && !this.options.markers?.length && (this.options.markers = z(i.markers), this.renderMarkers()), this.drawWaveform();
1042 + }).catch(() => {
1043 + });
1044 + return;
606 1045 }
607 - else this.waveformData = Array.isArray(e2) ? e2 : [];
608 - this.drawWaveform();
1046 + this.waveformData = D(t, { fallback: [] }), this.drawWaveform();
609 1047 }
610 1048 drawWaveform() {
611 - !this.ctx || this.waveformData.length === 0 || W(this.ctx, this.canvas, this.waveformData, this.progress, { ...this.options, waveformStyle: this.options.waveformStyle || "bars", color: this.options.waveformColor, progressColor: this.options.progressColor });
1049 + !this.ctx || this.waveformData.length === 0 || ft(this.ctx, this.canvas, this.waveformData, this.progress, { ...this.options, waveformStyle: this.options.waveformStyle || "bars", color: this.options.waveformColor, progressColor: this.options.progressColor, seekActive: this._seekHover || this._dragging });
612 1050 }
613 1051 resizeCanvas() {
614 1052 if (!this.canvas || this.isDestroying) return;
615 - let e2 = window.devicePixelRatio || 1, i2 = this.canvas.getBoundingClientRect();
616 - this.canvas.width = i2.width * e2, this.canvas.height = this.options.height * e2, this.canvas.style.height = this.options.height + "px", this.canvas.parentElement.style.height = this.options.height + "px", this.drawWaveform();
1053 + let t = window.devicePixelRatio || 1, i = this.canvas.parentElement.getBoundingClientRect();
1054 + this.canvas.width = i.width * t, this.canvas.height = this.options.height * t, this.canvas.parentElement.style.height = this.options.height + "px", this.drawWaveform();
617 1055 }
618 1056 renderMarkers() {
619 - !this.options.showMarkers || !this.options.markers?.length || !this.markersContainer || (this.markersContainer.innerHTML = "", !(!this.audio || !this.audio.duration || this.audio.duration === 0) && this.options.markers.forEach((e2, i2) => {
620 - if (e2.time > this.audio.duration) {
621 - console.warn(`Marker "${e2.label}" at ${e2.time}s exceeds audio duration of ${this.audio.duration}s`);
1057 + if (!this.markersContainer || (this.markersContainer.innerHTML = "", this._activeMarkerIndex = -1, clearTimeout(this._markerLabelTimer), !this.options.showMarkers || !this.options.markers?.length)) return;
1058 + let t = this.getSeekDuration();
1059 + t && this.options.markers.forEach((i, s) => {
1060 + if (i.time > t) {
1061 + console.warn(`[WaveformPlayer] Marker "${i.label}" at ${i.time}s exceeds audio duration of ${t}s`);
622 1062 return;
623 1063 }
624 - let a2 = e2.time / this.audio.duration * 100, s2 = document.createElement("button");
625 - s2.className = "waveform-marker", s2.style.left = `${a2}%`, s2.style.backgroundColor = e2.color || "rgba(255, 255, 255, 0.5)", s2.setAttribute("aria-label", e2.label), s2.setAttribute("data-time", e2.time);
626 - let n2 = document.createElement("span");
627 - n2.className = "waveform-marker-tooltip", n2.textContent = e2.label, s2.appendChild(n2), s2.addEventListener("click", (r2) => {
628 - r2.stopPropagation(), this.seekTo(e2.time), this.options.playOnSeek && !this.isPlaying && this.play();
629 - }), this.markersContainer.appendChild(s2);
1064 + let r = i.time / t * 100, a = document.createElement("button");
1065 + a.className = "waveform-marker", a.style.left = `${r}%`, a.style.backgroundColor = i.color || "rgba(255, 255, 255, 0.5)", a.setAttribute("aria-label", i.label), a.setAttribute("data-time", i.time);
1066 + let o = document.createElement("span");
1067 + o.className = "waveform-marker-tooltip", o.textContent = i.label, a.appendChild(o), a.addEventListener("click", (n) => {
1068 + n.stopPropagation(), this.seekTo(i.time), this.options.playOnSeek && !this.isPlaying && this.play();
1069 + }), this.markersContainer.appendChild(a);
1070 + });
1071 + }
1072 + setActiveMarker(t) {
1073 + if (!this.markersContainer) return;
1074 + this.markersContainer.querySelectorAll(".waveform-marker").forEach((s, r) => s.classList.toggle("active", r === t));
1075 + }
1076 + updateActiveMarker() {
1077 + if (!this.markersContainer) return;
1078 + let t = this.markersContainer.querySelectorAll(".waveform-marker");
1079 + if (!t.length) return;
1080 + let i = this.getSeekDuration(), s = i ? this.progress * i : 0, r = -1, a = -1 / 0;
1081 + t.forEach((o, n) => {
1082 + let l2 = parseFloat(o.getAttribute("data-time"));
1083 + Number.isFinite(l2) && l2 <= s + 0.05 && l2 > a && (a = l2, r = n);
1084 + }), r !== this._activeMarkerIndex && (this._activeMarkerIndex = r, this.setActiveMarker(r), clearTimeout(this._markerLabelTimer), t.forEach((o, n) => o.classList.toggle("show-label", n === r)), r >= 0 && (this._markerLabelTimer = setTimeout(() => {
1085 + this.markersContainer?.querySelectorAll(".waveform-marker").forEach((o) => o.classList.remove("show-label"));
1086 + }, 2500)));
1087 + }
1088 + setupHoverTime() {
1089 + if (!this.seekEl) return;
1090 + let t = document.createElement("div");
1091 + t.className = "waveform-hover-time", t.setAttribute("aria-hidden", "true"), this.seekEl.appendChild(t), this.hoverTimeEl = t, this.options.showHoverTime && (this.seekEl.addEventListener("pointermove", (i) => {
1092 + this._dragging || this._updateHoverTip(i.clientX);
1093 + }), this.seekEl.addEventListener("pointerleave", () => {
1094 + this._dragging || this._hideHoverTip();
630 1095 }));
631 1096 }
632 - handleCanvasClick(e2) {
633 - if (!this.audio.duration) return;
634 - let i2 = this.canvas.getBoundingClientRect(), a2 = e2.clientX - i2.left, s2 = Math.max(0, Math.min(1, a2 / i2.width));
635 - this.seekToPercent(s2);
1097 + _updateHoverTip(t) {
1098 + let i = this.hoverTimeEl;
1099 + if (!i) return;
1100 + let s = this.getSeekDuration();
1101 + if (!s) {
1102 + i.style.opacity = "0";
1103 + return;
1104 + }
1105 + let r = this.canvas.getBoundingClientRect(), a = m2((t - r.left) / r.width);
1106 + i.textContent = E2(a * s), i.style.left = a * 100 + "%", i.style.opacity = "1";
636 1107 }
637 - setLoading(e2) {
638 - this.isLoading = e2, this.loadingEl && (this.loadingEl.style.display = e2 ? "block" : "none");
1108 + _hideHoverTip() {
1109 + this.hoverTimeEl && (this.hoverTimeEl.style.opacity = "0");
639 1110 }
1111 + _scrubTo(t) {
1112 + let i = this.canvas.getBoundingClientRect();
1113 + if (!i.width) return;
1114 + this.progress = m2((t - i.left) / i.width), this.drawWaveform(), this._updateSeekHandle();
1115 + let s = this.getSeekDuration();
1116 + s && this.currentTimeEl ? (this.currentTimeEl.textContent = E2(this.progress * s), this._hideHoverTip()) : this._updateHoverTip(t);
1117 + }
1118 + setupSeekHandle() {
1119 + if (!this.options.seekHandle || this.options.waveformStyle !== "seekbar" || !this.seekEl) return;
1120 + let t = document.createElement("div");
1121 + t.className = "waveform-seek-handle", t.setAttribute("aria-hidden", "true"), this.seekEl.appendChild(t), this.seekHandleEl = t;
1122 + }
1123 + _updateSeekHandle() {
1124 + let t = this.seekHandleEl;
1125 + t && (t.style.left = this.progress * 100 + "%", t.classList.toggle("is-visible", this._seekHover || this._dragging), t.classList.toggle("is-active", this._dragging || this._handleNear));
1126 + }
1127 + handleCanvasClick(t) {
1128 + if (this._suppressClick) {
1129 + this._suppressClick = false;
1130 + return;
1131 + }
1132 + this._seekFromPointer(t.clientX);
1133 + }
1134 + _seekFromPointer(t) {
1135 + let i = this.canvas.getBoundingClientRect();
1136 + if (!i.width) return;
1137 + let s = m2((t - i.left) / i.width);
1138 + if (this.options.audioMode === "external") {
1139 + this._requestSeek(s);
1140 + return;
1141 + }
1142 + !this.audio || !this.audio.duration || this.seekToPercent(s);
1143 + }
1144 + setLoading(t) {
1145 + if (this.isLoading = t, this.loadingEl) {
1146 + let i = t && this.waveformData.length === 0;
1147 + this.loadingEl.style.display = i ? "block" : "none";
1148 + }
1149 + this.seekEl && this.seekEl.setAttribute("aria-busy", t ? "true" : "false");
1150 + }
640 1151 onMetadataLoaded() {
641 - this.isDestroying || (this.totalTimeEl && (this.totalTimeEl.textContent = P(this.audio.duration)), this.renderMarkers());
1152 + this.isDestroying || (this.totalTimeEl && (this.totalTimeEl.textContent = E2(this.audio.duration)), this.renderMarkers(), this.updateSeekAccessibility());
642 1153 }
1154 + setPlayButtonState(t) {
1155 + if (!this.playBtn) return;
1156 + this.playBtn.classList.toggle("playing", t);
1157 + let i = this.playBtn.querySelector(".waveform-icon-play"), s = this.playBtn.querySelector(".waveform-icon-pause");
1158 + i && (i.style.display = t ? "none" : "flex"), s && (s.style.display = t ? "flex" : "none");
1159 + }
643 1160 onPlay() {
644 - if (this.isDestroying) return;
645 - this.isPlaying = true, this.playBtn.classList.add("playing");
646 - let e2 = this.playBtn.querySelector(".waveform-icon-play"), i2 = this.playBtn.querySelector(".waveform-icon-pause");
647 - e2 && (e2.style.display = "none"), i2 && (i2.style.display = "flex"), this.startSmoothUpdate(), this.container.dispatchEvent(new CustomEvent("waveformplayer:play", { bubbles: true, detail: { player: this, url: this.options.url } })), this.options.onPlay && this.options.onPlay(this);
1161 + this.isDestroying || (this.isPlaying = true, this.setPlayButtonState(true), this.startSmoothUpdate(), this._updateMediaSession("playing"), this._emit("waveformplayer:play", { player: this, url: this.options.url }), this.options.onPlay && this.options.onPlay(this));
648 1162 }
649 1163 onPause() {
650 - if (this.isDestroying) return;
651 - this.isPlaying = false, this.playBtn.classList.remove("playing");
652 - let e2 = this.playBtn.querySelector(".waveform-icon-play"), i2 = this.playBtn.querySelector(".waveform-icon-pause");
653 - e2 && (e2.style.display = "flex"), i2 && (i2.style.display = "none"), this.stopSmoothUpdate(), this.container.dispatchEvent(new CustomEvent("waveformplayer:pause", { bubbles: true, detail: { player: this, url: this.options.url } })), this.options.onPause && this.options.onPause(this);
1164 + this.isDestroying || (this.isPlaying = false, this.setPlayButtonState(false), this.stopSmoothUpdate(), this._updateMediaSession("paused"), this._emit("waveformplayer:pause", { player: this, url: this.options.url }), this.options.onPause && this.options.onPause(this));
654 1165 }
655 1166 onEnded() {
656 - this.isDestroying || (this.progress = 0, this.audio.currentTime = 0, this.drawWaveform(), this.currentTimeEl && (this.currentTimeEl.textContent = "0:00"), this.container.dispatchEvent(new CustomEvent("waveformplayer:ended", { bubbles: true, detail: { player: this, url: this.options.url } })), this.onPause(), this.options.onEnd && this.options.onEnd(this));
1167 + if (this.isDestroying) return;
1168 + let t = this.audio.duration;
1169 + this.progress = 0, this.audio.currentTime = 0, this.drawWaveform(), this.currentTimeEl && (this.currentTimeEl.textContent = "0:00"), this._emit("waveformplayer:ended", { player: this, url: this.options.url, currentTime: t, duration: t }), this.onPause(), this.options.onEnd && this.options.onEnd(this);
657 1170 }
658 - onError(e2) {
659 - this.isDestroying || (console.error("Audio error:", e2), this.hasError = true, this.setLoading(false), this.errorEl && (this.errorEl.style.display = "flex"), this.canvas && (this.canvas.style.opacity = "0.2"), this.playBtn && (this.playBtn.disabled = true), this.options.onError && this.options.onError(e2, this));
1171 + onError(t) {
1172 + this.isDestroying || (console.error("[WaveformPlayer] Audio error:", t), this.hasError = true, this.setLoading(false), this.errorEl && (this.errorEl.style.display = "flex"), this.canvas && (this.canvas.style.opacity = "0.2"), this.playBtn && (this.playBtn.disabled = true), this.options.onError && this.options.onError(t, this));
660 1173 }
661 1174 startSmoothUpdate() {
662 1175 this.stopSmoothUpdate();
663 - let e2 = () => {
664 - this.isPlaying && this.audio.duration && (this.updateProgress(), this.updateTimer = requestAnimationFrame(e2));
1176 + let t = () => {
1177 + this.isPlaying && this.audio && this.audio.duration && (this.updateProgress(), this.updateTimer = requestAnimationFrame(t));
665 1178 };
666 - this.updateTimer = requestAnimationFrame(e2);
1179 + this.updateTimer = requestAnimationFrame(t);
667 1180 }
668 1181 stopSmoothUpdate() {
669 1182 this.updateTimer && (cancelAnimationFrame(this.updateTimer), this.updateTimer = null);
670 1183 }
671 1184 updateProgress() {
672 - if (!this.audio.duration) return;
673 - let e2 = this.audio.currentTime / this.audio.duration;
674 - Math.abs(e2 - this.progress) > 1e-3 && (this.progress = e2, this.drawWaveform()), this.currentTimeEl && (this.currentTimeEl.textContent = P(this.audio.currentTime)), this.container.dispatchEvent(new CustomEvent("waveformplayer:timeupdate", { bubbles: true, detail: { player: this, currentTime: this.audio.currentTime, duration: this.audio.duration, url: this.options.url } })), this.options.onTimeUpdate && this.options.onTimeUpdate(this.audio.currentTime, this.audio.duration, this);
1185 + if (!this.audio || !this.audio.duration || this._dragging) return;
1186 + let t = this.audio.currentTime / this.audio.duration;
1187 + Math.abs(t - this.progress) > 1e-3 && (this.progress = t, this.drawWaveform(), this._updateSeekHandle()), this.currentTimeEl && (this.currentTimeEl.textContent = E2(this.audio.currentTime)), this._emit("waveformplayer:timeupdate", { player: this, currentTime: this.audio.currentTime, duration: this.audio.duration, progress: this.progress, url: this.options.url }), this.options.onTimeUpdate && this.options.onTimeUpdate(this.audio.currentTime, this.audio.duration, this), this.updateActiveMarker(), this.updateSeekAccessibility();
675 1188 }
676 1189 updateBPMDisplay() {
677 - this.bpmEl && this.bpmValueEl && this.detectedBPM && (this.bpmValueEl.textContent = Math.round(this.detectedBPM), this.bpmEl.style.display = "inline-flex");
1190 + let t = this.options.bpm || this.detectedBPM;
1191 + this.bpmEl && this.bpmValueEl && t && (this.bpmValueEl.textContent = Math.round(t), this.bpmEl.style.display = "inline-flex");
678 1192 }
1193 + refreshTheme() {
1194 + if (!this._autoTheme) return;
1195 + this._scheme = R2(this.container);
1196 + let t = J(this.options.colorPreset, this.container);
1197 + for (let i of this._presetKeys || []) i in t && (this.options[i] = t[i]);
1198 + this._applyThemeColors();
1199 + }
1200 + _applyThemeColors() {
1201 + this.container.classList.toggle("waveform-theme-light", this._scheme === "light"), this.canvas && this.drawWaveform();
1202 + }
1203 + static _watchTheme() {
1204 + if (e._themeWatch || typeof document > "u") return;
1205 + let t = () => requestAnimationFrame(() => {
1206 + e.instances.forEach((a) => {
1207 + try {
1208 + a.refreshTheme();
1209 + } catch {
1210 + }
1211 + });
1212 + }), i = { attributes: true, attributeFilter: ["class", "data-theme", "data-color-scheme", "style"] }, s = new MutationObserver(t);
1213 + s.observe(document.documentElement, i), document.body && s.observe(document.body, i);
1214 + let r = null;
1215 + try {
1216 + r = window.matchMedia("(prefers-color-scheme: dark)"), r.addEventListener("change", t);
1217 + } catch {
1218 + }
1219 + e._themeWatch = { obs: s, mq: r, refresh: t };
1220 + }
679 1221 updateSpeedUI() {
680 - let e2 = this.container.querySelector(".speed-value");
681 - if (e2) {
682 - let i2 = this.audio.playbackRate;
683 - e2.textContent = i2 === 1 ? "1x" : `${i2}x`;
1222 + if (!this.audio) return;
1223 + let t = this.container.querySelector(".speed-value");
1224 + if (t) {
1225 + let i = this.audio.playbackRate;
1226 + t.textContent = i === 1 ? "1x" : `${i}x`;
684 1227 }
685 - this.container.querySelectorAll(".speed-option").forEach((i2) => {
686 - i2.classList.toggle("active", parseFloat(i2.dataset.rate) === this.audio.playbackRate);
1228 + this.container.querySelectorAll(".speed-option").forEach((i) => {
1229 + let s = parseFloat(i.dataset.rate) === this.audio.playbackRate;
1230 + i.classList.toggle("active", s), i.setAttribute("aria-checked", s ? "true" : "false");
687 1231 });
688 1232 }
689 1233 play() {
690 - this.options.singlePlay && t2.currentlyPlaying && t2.currentlyPlaying !== this && t2.currentlyPlaying.pause(), t2.currentlyPlaying = this, this.audio.play();
1234 + if (this.options.singlePlay && e.currentlyPlaying && e.currentlyPlaying !== this && e.currentlyPlaying.pause(), this.options.audioMode === "external") {
1235 + this._emit("waveformplayer:request-play", this._buildTrackDetail(), true).defaultPrevented || (e.currentlyPlaying = this);
1236 + return;
1237 + }
1238 + return e.currentlyPlaying = this, this.audio.play();
691 1239 }
692 1240 pause() {
693 - t2.currentlyPlaying === this && (t2.currentlyPlaying = null), this.audio.pause();
1241 + if (e.currentlyPlaying === this && (e.currentlyPlaying = null), this.options.audioMode === "external") {
1242 + this._emit("waveformplayer:request-pause", this._buildTrackDetail(), true);
1243 + return;
1244 + }
1245 + this.audio.pause();
694 1246 }
1247 + _buildTrackDetail() {
1248 + return { url: this.options.url, title: this.options.title, artist: this.options.artist, artwork: this.options.artwork, markers: this.options.markers, waveform: this.options.waveform, id: this.id, player: this };
1249 + }
1250 + setPlayingState(t) {
1251 + let i = this.isPlaying;
1252 + this.isPlaying = !!t, this.setPlayButtonState(this.isPlaying), this.isPlaying && !i ? (this.startSmoothUpdate?.(), this._emit("waveformplayer:play", { player: this, url: this.options.url }), this.options.onPlay && this.options.onPlay(this)) : !this.isPlaying && i && (this.stopSmoothUpdate?.(), this._emit("waveformplayer:pause", { player: this, url: this.options.url }), this.options.onPause && this.options.onPause(this));
1253 + }
1254 + setProgress(t, i) {
1255 + !i || i <= 0 || (this.progress = m2(t / i), this.currentTimeEl && (this.currentTimeEl.textContent = E2(t)), this._extDuration = i, this.totalTimeEl && (!this.totalTimeEl.dataset._extSet || this.totalTimeEl.dataset._extDur !== String(i)) && (this.totalTimeEl.textContent = E2(i), this.totalTimeEl.dataset._extSet = "1", this.totalTimeEl.dataset._extDur = String(i)), this.drawWaveform?.(), this.updateActiveMarker(), this._emit("waveformplayer:timeupdate", { player: this, currentTime: t, duration: i, progress: this.progress, url: this.options.url }), this.options.onTimeUpdate && this.options.onTimeUpdate(t, i, this), this.progress >= 1 ? this._extEnded || (this._extEnded = true, this._emit("waveformplayer:ended", { player: this, url: this.options.url, currentTime: i, duration: i }), this.options.onEnd && this.options.onEnd(this)) : this._extEnded = false, this.updateSeekAccessibility());
1256 + }
695 1257 togglePlay() {
696 1258 this.isPlaying ? this.pause() : this.play();
697 1259 }
698 - seekTo(e2) {
699 - this.audio && this.audio.duration && (this.audio.currentTime = Math.max(0, Math.min(e2, this.audio.duration)), this.updateProgress());
1260 + seekTo(t) {
1261 + this.audio && this.audio.duration && (this.audio.currentTime = m2(t, 0, this.audio.duration), this.updateProgress());
700 1262 }
701 - seekToPercent(e2) {
702 - this.audio && this.audio.duration && (this.audio.currentTime = this.audio.duration * Math.max(0, Math.min(1, e2)), this.updateProgress());
1263 + seekToPercent(t) {
1264 + this.audio && this.audio.duration && (this.audio.currentTime = this.audio.duration * m2(t), this.updateProgress());
703 1265 }
704 - setVolume(e2) {
705 - this.audio && (this.audio.volume = Math.max(0, Math.min(1, e2)));
1266 + setVolume(t) {
1267 + let i = Number(t);
1268 + this.audio && Number.isFinite(i) && (this.audio.volume = m2(i));
706 1269 }
707 - setPlaybackRate(e2) {
1270 + setPlaybackRate(t) {
708 1271 if (!this.audio) return;
709 - let i2 = Math.max(0.5, Math.min(2, e2));
710 - this.audio.playbackRate = i2, this.options.playbackRate = i2, this.updateSpeedUI();
1272 + let i = _(t, null, { min: N2, max: F });
1273 + i !== null && (this.audio.playbackRate = i, this.options.playbackRate = i, this.updateSpeedUI());
711 1274 }
712 1275 destroy() {
713 - this.isDestroying = true, this.pause(), this.stopSmoothUpdate(), this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.resizeHandler && (window.removeEventListener("resize", this.resizeHandler), this.resizeHandler = null), t2.instances.delete(this.id), t2.currentlyPlaying === this && (t2.currentlyPlaying = null), this.audio && (this.audio.pause(), this.audio.src = "", this.audio.load(), this.audio = null), this.container.innerHTML = "", this.canvas = null, this.ctx = null, this.playBtn = null, this.waveformData = [];
1276 + this.isDestroying = true, this._emit("waveformplayer:destroy", { player: this, url: this.options.url }), this.pause(), this.stopSmoothUpdate(), clearTimeout(this._markerLabelTimer), this._ac?.abort(), this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.resizeHandler && (window.removeEventListener("resize", this.resizeHandler), this.resizeHandler = null), e.instances.delete(this.id), e.currentlyPlaying === this && (e.currentlyPlaying = null), this.audio && (this.audio.pause(), this.audio.src = "", this.audio.load(), this.audio = null), this.container.innerHTML = "", delete this.container.dataset.waveformInitialized, this.canvas = null, this.ctx = null, this.playBtn = null, this.waveformData = [];
714 1277 }
715 - static getInstance(e2) {
716 - if (typeof e2 == "string") {
717 - let i2 = this.instances.get(e2);
718 - if (i2) return i2;
719 - let a2 = document.getElementById(e2);
720 - if (a2) return Array.from(this.instances.values()).find((s2) => s2.container === a2);
1278 + static getInstance(t) {
1279 + if (typeof t == "string") {
1280 + let i = this.instances.get(t);
1281 + if (i) return i;
1282 + let s = document.getElementById(t);
1283 + if (s) return Array.from(this.instances.values()).find((r) => r.container === s);
721 1284 }
722 - if (e2 instanceof HTMLElement) return Array.from(this.instances.values()).find((i2) => i2.container === e2);
1285 + if (t instanceof HTMLElement) return Array.from(this.instances.values()).find((i) => i.container === t);
723 1286 }
724 1287 static getAllInstances() {
725 1288 return Array.from(this.instances.values());
726 1289 }
727 1290 static destroyAll() {
728 - this.instances.forEach((e2) => e2.destroy()), this.instances.clear();
1291 + this.instances.forEach((t) => t.destroy()), this.instances.clear();
729 1292 }
730 - static async generateWaveformData(e2, i2 = 200) {
1293 + static async generateWaveformData(t, i = 1800) {
731 1294 try {
732 - return (await M2(e2, i2)).peaks;
733 - } catch (a2) {
734 - throw console.error("Failed to generate waveform:", a2), a2;
1295 + return (await G(t, i)).peaks;
1296 + } catch (s) {
1297 + throw console.error("[WaveformPlayer] Failed to generate waveform:", s), s;
735 1298 }
736 1299 }
1300 + static getPeaksUrl(t) {
1301 + if (!t) return;
1302 + let i = t.replace(/\.(mp3|wav|ogg|flac|m4a|aac)(\?[^#]*)?(#.*)?$/i, ".json$2$3");
1303 + return i === t ? void 0 : i;
1304 + }
737 1305 };
738 -function T() {
739 - if (typeof document > "u") return;
740 - document.querySelectorAll("[data-waveform-player]").forEach((e2) => {
741 - if (e2.dataset.waveformInitialized !== "true") try {
742 - new g2(e2), e2.dataset.waveformInitialized = "true";
743 - } catch (i2) {
744 - console.error("Failed to initialize WaveformPlayer:", i2, e2);
745 - }
746 - });
1306 +T.utils = { formatTime: E2, extractTitleFromUrl: I, escapeHtml: S, isSafeHref: st, parseDataAttributes: O, detectColorScheme: R2 };
1307 +var et = () => typeof window < "u" && typeof document < "u";
1308 +var Nt = () => true;
1309 +function kt(e2) {
1310 + if (!(e2.dataset.waveformInitialized === "true" || T.getInstance(e2))) try {
1311 + new T(e2), e2.dataset.waveformInitialized = "true";
1312 + } catch (t) {
1313 + console.error("[WaveformPlayer] Failed to initialize:", t, e2);
1314 + }
747 1315 }
748 -typeof document < "u" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", T) : T());
749 -g2.init = T;
750 -typeof window < "u" && (window.WaveformPlayer = g2);
751 -var lt = g2;
1316 +function tt(e2 = document) {
1317 + if (!et()) return;
1318 + let t = e2 || document;
1319 + t.matches?.("[data-waveform-player]") && kt(t), t.querySelectorAll("[data-waveform-player]").forEach(kt);
1320 +}
1321 +et() && !Nt() && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => tt()) : tt());
1322 +T.init = tt;
1323 +et() && (window.WaveformPlayer = T);
1324 +var se = T;
752 1325
753 1326 // packages/block-library/build-module/utils/waveform-utils.mjs
754 1327 var DEFAULT_WAVEFORM_HEIGHT = 100;
1328 +var DEFAULT_SEEK_LABEL = "Seek";
755 1329 function getComputedStyle2(element) {
756 1330 return element.ownerDocument.defaultView.getComputedStyle(element);
757 1331 }
758 -function getWaveformColors(element) {
759 - const textColor = getComputedStyle2(element).color;
760 - const waveformColor = w(textColor).alpha(0.3).toRgbString();
761 - const progressColor = w(textColor).alpha(0.6).toRgbString();
762 - return { textColor, waveformColor, progressColor };
1332 +function getTopLevelGradientParts(gradientValue) {
1333 + const match = gradientValue?.trim().match(/^[\w-]+-gradient\((.*)\)$/i);
1334 + if (!match) {
1335 + return [];
1336 + }
1337 + const parts = [];
1338 + let depth = 0;
1339 + let current = "";
1340 + for (const character of match[1]) {
1341 + if (character === "(") {
1342 + ++depth;
1343 + } else if (character === ")") {
1344 + --depth;
1345 + }
1346 + if (character === "," && depth === 0) {
1347 + parts.push(current.trim());
1348 + current = "";
1349 + continue;
1350 + }
1351 + current += character;
1352 + }
1353 + if (current.trim()) {
1354 + parts.push(current.trim());
1355 + }
1356 + return parts;
763 1357 }
1358 +function getLeadingColorFunction(value) {
1359 + const match = value.match(/^([\w-]+)\(/);
1360 + if (!match) {
1361 + return;
1362 + }
1363 + const supportedFunctions = [
1364 + "color",
1365 + "color-mix",
1366 + "hsl",
1367 + "hsla",
1368 + "hwb",
1369 + "lab",
1370 + "lch",
1371 + "oklab",
1372 + "oklch",
1373 + "rgb",
1374 + "rgba",
1375 + "var"
1376 + ];
1377 + if (!supportedFunctions.includes(match[1].toLowerCase())) {
1378 + return;
1379 + }
1380 + let depth = 0;
1381 + let foundOpeningParenthesis = false;
1382 + for (let index = 0; index < value.length; index++) {
1383 + const character = value[index];
1384 + if (character === "(") {
1385 + foundOpeningParenthesis = true;
1386 + ++depth;
1387 + } else if (character === ")") {
1388 + --depth;
1389 + }
1390 + if (foundOpeningParenthesis && depth === 0) {
1391 + return value.slice(0, index + 1);
1392 + }
1393 + }
1394 +}
1395 +function getColorStopValue(gradientPart) {
1396 + const colorFunction = getLeadingColorFunction(gradientPart);
1397 + if (colorFunction) {
1398 + return colorFunction;
1399 + }
1400 + const [possibleColor] = gradientPart.split(/\s+/);
1401 + if (A(possibleColor).isValid()) {
1402 + return possibleColor;
1403 + }
1404 +}
1405 +function getWaveformGradientDirection(gradientValue) {
1406 + const parts = getTopLevelGradientParts(gradientValue);
1407 + const direction = parts[0];
1408 + const angleMatch = direction?.match(/^(-?\d+(?:\.\d+)?)deg$/i);
1409 + if (angleMatch) {
1410 + const angle = (Number(angleMatch[1]) % 360 + 360) % 360;
1411 + if (angle === 90 || angle === 270) {
1412 + return "horizontal";
1413 + }
1414 + if (angle === 0 || angle === 180) {
1415 + return "vertical";
1416 + }
1417 + return "diagonal";
1418 + }
1419 + if (!direction?.startsWith("to ")) {
1420 + return void 0;
1421 + }
1422 + const sideOrCorner = direction.toLowerCase().replace(/^to\s+/, "");
1423 + const hasHorizontalSide = sideOrCorner.includes("left") || sideOrCorner.includes("right");
1424 + const hasVerticalSide = sideOrCorner.includes("top") || sideOrCorner.includes("bottom");
1425 + if (hasHorizontalSide && hasVerticalSide) {
1426 + return "diagonal";
1427 + }
1428 + if (hasHorizontalSide) {
1429 + return "horizontal";
1430 + }
1431 + if (hasVerticalSide) {
1432 + return "vertical";
1433 + }
1434 +}
1435 +function resolveColorValue(element, colorValue) {
1436 + if (!colorValue || A(colorValue).isValid()) {
1437 + return colorValue;
1438 + }
1439 + const colorResolver = element.ownerDocument.createElement("span");
1440 + colorResolver.style.color = colorValue;
1441 + if (!colorResolver.style.color) {
1442 + return colorValue;
1443 + }
1444 + element.appendChild(colorResolver);
1445 + const resolvedColor = getComputedStyle2(colorResolver).color;
1446 + colorResolver.remove();
1447 + return resolvedColor && A(resolvedColor).isValid() ? resolvedColor : colorValue;
1448 +}
1449 +function getResolvedGradientStops(element, gradientValue) {
1450 + const stops = getWaveformGradientStops(gradientValue)?.map((colorValue) => resolveColorValue(element, colorValue)).filter((colorValue) => A(colorValue).isValid());
1451 + return stops?.length > 1 ? stops : void 0;
1452 +}
1453 +function applyAlpha(colorValue, alpha) {
1454 + if (Array.isArray(colorValue)) {
1455 + return colorValue.map(
1456 + (color) => A(color).alpha(alpha).toRgbString()
1457 + );
1458 + }
1459 + return A(colorValue).alpha(alpha).toRgbString();
1460 +}
1461 +function getRepresentativeColor(colorValue) {
1462 + if (Array.isArray(colorValue)) {
1463 + return colorValue[colorValue.length - 1];
1464 + }
1465 + return colorValue;
1466 +}
1467 +function getWaveformGradientStops(gradientValue) {
1468 + const stops = getTopLevelGradientParts(gradientValue).map(getColorStopValue).filter(Boolean);
1469 + return stops.length > 1 ? stops : void 0;
1470 +}
1471 +function serializeColorValue(colorValue) {
1472 + return Array.isArray(colorValue) ? JSON.stringify(colorValue) : colorValue;
1473 +}
1474 +function getWaveformColors(element, waveformColorValue, textColorValue, waveformGradientValue) {
1475 + const textColor = textColorValue || getComputedStyle2(element).color;
1476 + const waveformGradientStops = getResolvedGradientStops(
1477 + element,
1478 + waveformGradientValue
1479 + );
1480 + const waveformBaseColor = waveformGradientStops || waveformColorValue || textColor;
1481 + const waveformColor = applyAlpha(waveformBaseColor, 0.3);
1482 + const progressColor = applyAlpha(waveformBaseColor, 0.6);
1483 + const waveformGradient = waveformGradientStops ? getWaveformGradientDirection(waveformGradientValue) : void 0;
1484 + return {
1485 + textColor,
1486 + waveformColor,
1487 + progressColor,
1488 + ...waveformGradient && { waveformGradient }
1489 + };
1490 +}
764 1491 function createWaveformContainer({
765 1492 url,
766 1493 title,
767 1494 artist,
@@ -767,19 +1494,39 @@
767 1494 artist,
768 1495 artwork,
769 1496 waveformColor,
770 1497 progressColor,
1498 + waveformGradient,
771 1499 buttonColor,
772 - height = DEFAULT_WAVEFORM_HEIGHT
1500 + seekLabel,
1501 + seekValueText,
1502 + height = DEFAULT_WAVEFORM_HEIGHT,
1503 + waveformStyle = "bars"
773 1504 }) {
774 1505 const container = document.createElement("div");
775 1506 container.setAttribute("data-waveform-player", "");
776 1507 container.setAttribute("data-url", url);
777 1508 container.setAttribute("data-height", String(height));
778 - container.setAttribute("data-waveform-style", "bars");
779 - container.setAttribute("data-waveform-color", waveformColor);
780 - container.setAttribute("data-progress-color", progressColor);
1509 + container.setAttribute("data-waveform-style", waveformStyle);
1510 + container.setAttribute(
1511 + "data-waveform-color",
1512 + serializeColorValue(waveformColor)
1513 + );
1514 + container.setAttribute(
1515 + "data-progress-color",
1516 + serializeColorValue(progressColor)
1517 + );
1518 + if (waveformGradient) {
1519 + container.setAttribute("data-waveform-gradient", waveformGradient);
1520 + }
781 1521 container.setAttribute("data-button-color", buttonColor);
1522 + container.setAttribute(
1523 + "data-seek-label",
1524 + getSeekControlLabel(seekLabel)
1525 + );
1526 + if (seekValueText) {
1527 + container.setAttribute("data-seek-value-text", seekValueText);
1528 + }
782 1529 container.setAttribute("data-text-color", buttonColor);
783 1530 container.setAttribute("data-text-secondary-color", buttonColor);
784 1531 if (title) {
785 1532 container.setAttribute("data-title", title);
@@ -784,9 +1531,9 @@
784 1531 if (title) {
785 1532 container.setAttribute("data-title", title);
786 1533 }
787 1534 if (artist) {
788 - container.setAttribute("data-subtitle", artist);
1535 + container.setAttribute("data-artist", artist);
789 1536 }
790 1537 if (artwork) {
791 1538 container.setAttribute("data-artwork", artwork);
792 1539 }
@@ -791,10 +1538,56 @@
791 1538 container.setAttribute("data-artwork", artwork);
792 1539 }
793 1540 return container;
794 1541 }
1542 +function applyWaveformPlayerStyles(container, {
1543 + backgroundColor,
1544 + backgroundGradient,
1545 + textColor,
1546 + playButtonColor,
1547 + playButtonGradient
1548 +} = {}) {
1549 + const waveformContainer = container.querySelector(".waveform-container");
1550 + const playButton = container.querySelector(".waveform-btn");
1551 + const playButtonBaseColor = getRepresentativeColor(
1552 + getResolvedGradientStops(container, playButtonGradient) || playButtonColor
1553 + );
1554 + if (playButtonBaseColor) {
1555 + container.style.setProperty(
1556 + "--wfp-button-color",
1557 + playButtonBaseColor
1558 + );
1559 + } else {
1560 + container.style.removeProperty("--wfp-button-color");
1561 + }
1562 + if (textColor) {
1563 + container.style.setProperty("--wfp-text-color", textColor);
1564 + container.style.setProperty("--wfp-text-secondary-color", textColor);
1565 + } else {
1566 + container.style.removeProperty("--wfp-text-color");
1567 + container.style.removeProperty("--wfp-text-secondary-color");
1568 + }
1569 + if (playButton) {
1570 + if (playButtonGradient) {
1571 + playButton.style.background = playButtonGradient;
1572 + } else {
1573 + playButton.style.removeProperty("background");
1574 + }
1575 + }
1576 + if (waveformContainer) {
1577 + if (backgroundGradient) {
1578 + waveformContainer.style.background = backgroundGradient;
1579 + } else if (backgroundColor) {
1580 + waveformContainer.style.removeProperty("background");
1581 + waveformContainer.style.backgroundColor = backgroundColor;
1582 + } else {
1583 + waveformContainer.style.removeProperty("background");
1584 + waveformContainer.style.removeProperty("background-color");
1585 + }
1586 + }
1587 +}
795 1588 function styleSvgIcons(container, buttonColor) {
796 - const isButtonDark = w(buttonColor).isDark();
1589 + const isButtonDark = A(buttonColor).isDark();
797 1590 const iconColor = isButtonDark ? "#ffffff" : "#000000";
798 1591 const svgPaths = container.querySelectorAll("svg path");
799 1592 svgPaths.forEach((path) => {
800 1593 path.style.fill = iconColor;
@@ -816,8 +1609,34 @@
816 1609 container.removeEventListener("waveformplayer:pause", onPause);
817 1610 container.removeEventListener("waveformplayer:ended", onPause);
818 1611 };
819 1612 }
1613 +function getSeekControlLabel(label) {
1614 + return label || DEFAULT_SEEK_LABEL;
1615 +}
1616 +function updateSeekControlLabel(instance, label) {
1617 + const seekLabel = getSeekControlLabel(label);
1618 + instance.options.seekLabel = seekLabel;
1619 + instance.applySeekLabel?.(seekLabel);
1620 + const seekControl = instance?.container?.querySelector(
1621 + ".waveform-container"
1622 + );
1623 + if (seekControl) {
1624 + seekControl.setAttribute("aria-label", seekLabel);
1625 + }
1626 +}
1627 +function setupPlayButtonArtwork(container, artworkUrl) {
1628 + if (!artworkUrl) {
1629 + container.classList.remove("has-play-button-artwork");
1630 + container.style.removeProperty("--wp--playlist--play-button-artwork");
1631 + return;
1632 + }
1633 + container.classList.add("has-play-button-artwork");
1634 + container.style.setProperty(
1635 + "--wp--playlist--play-button-artwork",
1636 + `url(${JSON.stringify(artworkUrl)})`
1637 + );
1638 +}
820 1639 function logPlayError(error) {
821 1640 if (error.name === "AbortError") {
822 1641 return;
823 1642 }
@@ -822,26 +1641,72 @@
822 1641 return;
823 1642 }
824 1643 console.error("Playlist play error:", error);
825 1644 }
826 -function initWaveformPlayer(element, { src, title, artist, image, autoPlay, onEnded, labels }) {
827 - const { textColor, waveformColor, progressColor } = getWaveformColors(element);
1645 +function initWaveformPlayer(element, {
1646 + src,
1647 + title,
1648 + artist,
1649 + image,
1650 + imageAlt,
1651 + waveformColor: waveformColorValue,
1652 + waveformGradient: waveformGradientValue,
1653 + textColor: textColorValue,
1654 + backgroundColor,
1655 + backgroundGradient,
1656 + autoPlay,
1657 + onEnded,
1658 + labels,
1659 + waveformStyle,
1660 + showPlayButtonArtwork = false
1661 +}) {
1662 + const playerArtwork = showPlayButtonArtwork ? void 0 : image;
1663 + const { textColor, waveformColor, progressColor, waveformGradient } = getWaveformColors(
1664 + element,
1665 + waveformColorValue,
1666 + textColorValue,
1667 + waveformGradientValue
1668 + );
1669 + const waveformGradientStops = getResolvedGradientStops(
1670 + element,
1671 + waveformGradientValue
1672 + );
1673 + const waveformButtonColor = getRepresentativeColor(
1674 + waveformGradientStops || waveformColorValue
1675 + );
828 1676 const container = createWaveformContainer({
829 1677 url: src,
830 1678 title,
831 1679 artist,
832 - artwork: image,
1680 + artwork: playerArtwork,
833 1681 waveformColor,
834 1682 progressColor,
835 - buttonColor: textColor
1683 + waveformGradient,
1684 + buttonColor: textColor,
1685 + seekLabel: title || labels?.seek,
1686 + seekValueText: labels?.seekValueText,
1687 + waveformStyle
836 1688 });
837 1689 element.appendChild(container);
838 - const instance = new lt(container);
839 - let cleanupAccessibility;
1690 + const instance = new se(container);
1691 + if (instance.artworkEl) {
1692 + instance.artworkEl.alt = imageAlt || "";
1693 + }
1694 + applyWaveformPlayerStyles(container, {
1695 + backgroundColor,
1696 + backgroundGradient,
1697 + textColor,
1698 + playButtonColor: showPlayButtonArtwork ? void 0 : waveformButtonColor,
1699 + playButtonGradient: showPlayButtonArtwork ? void 0 : waveformGradientValue
1700 + });
1701 + let cleanupPlayButtonAccessibility;
840 1702 const handlers = {
841 1703 ready: () => {
842 - styleSvgIcons(container, textColor);
843 - cleanupAccessibility = setupPlayButtonAccessibility(
1704 + styleSvgIcons(container, waveformButtonColor || textColor);
1705 + if (showPlayButtonArtwork) {
1706 + setupPlayButtonArtwork(container, image);
1707 + }
1708 + cleanupPlayButtonAccessibility = setupPlayButtonAccessibility(
844 1709 container,
845 1710 labels
846 1711 );
847 1712 if (autoPlay) {
@@ -855,9 +1720,9 @@
855 1720 return {
856 1721 instance,
857 1722 container,
858 1723 destroy: () => {
859 - cleanupAccessibility?.();
1724 + cleanupPlayButtonAccessibility?.();
860 1725 container.removeEventListener(
861 1726 "waveformplayer:ready",
862 1727 handlers.ready
863 1728 );
@@ -872,8 +1737,9 @@
872 1737 }
873 1738
874 1739 // packages/block-library/build-module/playlist/view.mjs
875 1740 var playerState = /* @__PURE__ */ new WeakMap();
1741 +var playlistPlayerState = /* @__PURE__ */ new Map();
876 1742 var { state } = store(
877 1743 "core/playlist",
878 1744 {
879 1745 state: {
@@ -878,16 +1744,37 @@
878 1744 {
879 1745 state: {
880 1746 playlists: {},
881 1747 get isCurrentTrack() {
882 - const { currentId, uniqueId } = getContext();
883 - return currentId === uniqueId;
1748 + const { currentId, trackId } = getContext();
1749 + return currentId === trackId;
1750 + },
1751 + get isCurrentTrackPlaying() {
1752 + const { currentId, isPlaying, trackId } = getContext();
1753 + return currentId === trackId && !!isPlaying;
1754 + },
1755 + get trackButtonActionLabel() {
1756 + const { labelPauseTrack, labelSelectTrack } = getContext();
1757 + return state.isCurrentTrackPlaying ? labelPauseTrack : labelSelectTrack;
884 1758 }
885 1759 },
886 1760 actions: {
887 1761 changeTrack() {
888 1762 const context = getContext();
889 - context.currentId = context.uniqueId;
1763 + if (context.currentId === context.trackId) {
1764 + const player = playlistPlayerState.get(
1765 + context.playlistId
1766 + )?.instance;
1767 + if (player?.isPlaying) {
1768 + context.isPlaying = false;
1769 + player.pause();
1770 + } else {
1771 + player?.play()?.catch(logPlayError);
1772 + }
1773 + return;
1774 + }
1775 + context.isPlaying = false;
1776 + context.currentId = context.trackId;
890 1777 }
891 1778 },
892 1779 callbacks: {
893 1780 initWaveformPlayer() {
@@ -912,22 +1799,47 @@
912 1799 { lock: true }
913 1800 );
914 1801 function initPlayer(ref, track, shouldAutoPlay, context) {
915 1802 const existing = playerState.get(ref);
1803 + const showPlayButtonArtwork = context.showPlayButtonArtwork === true;
1804 + const playerArtwork = showPlayButtonArtwork ? "" : track.image;
916 1805 if (existing?.instance) {
917 - existing.instance.loadTrack(track.url, track.title, track.artist, {
918 - artwork: track.image
919 - }).then(() => {
920 - existing.url = track.url;
921 - if (shouldAutoPlay) {
922 - existing.instance.play()?.catch(logPlayError);
923 - }
924 - }).catch(logPlayError);
925 - return;
1806 + const shouldRecreatePlayer = !!existing.instance.artworkEl !== !!playerArtwork;
1807 + if (shouldRecreatePlayer) {
1808 + existing.destroy?.();
1809 + playerState.delete(ref);
1810 + } else {
1811 + playlistPlayerState.set(context.playlistId, existing);
1812 + existing.instance.loadTrack(track.url, track.title, track.artist, {
1813 + artwork: playerArtwork,
1814 + artworkAlt: playerArtwork ? track.imageAlt : ""
1815 + }).then(() => {
1816 + existing.url = track.url;
1817 + if (existing.instance.artworkEl) {
1818 + existing.instance.artworkEl.alt = track.imageAlt || "";
1819 + }
1820 + updateSeekControlLabel(
1821 + existing.instance,
1822 + track.title || ref.dataset.labelSeek
1823 + );
1824 + if (showPlayButtonArtwork) {
1825 + setupPlayButtonArtwork(
1826 + existing.container,
1827 + track.image
1828 + );
1829 + }
1830 + if (shouldAutoPlay) {
1831 + existing.instance.play()?.catch(logPlayError);
1832 + }
1833 + }).catch(logPlayError);
1834 + return;
1835 + }
926 1836 }
927 1837 const labels = {
928 1838 play: ref.dataset.labelPlay,
929 - pause: ref.dataset.labelPause
1839 + pause: ref.dataset.labelPause,
1840 + seek: ref.dataset.labelSeek,
1841 + seekValueText: ref.dataset.labelSeekValue
930 1842 };
931 1843 const player = initWaveformPlayer(ref, {
932 1844 src: track.url,
933 1845 title: track.title,
@@ -932,13 +1844,20 @@
932 1844 src: track.url,
933 1845 title: track.title,
934 1846 artist: track.artist,
935 1847 image: track.image,
1848 + imageAlt: track.imageAlt,
1849 + waveformColor: ref.dataset.waveformPlayerColor,
1850 + waveformGradient: ref.dataset.waveformPlayerGradient,
1851 + backgroundColor: ref.dataset.waveformPlayerBackgroundColor,
1852 + backgroundGradient: ref.dataset.waveformPlayerBackgroundGradient,
936 1853 autoPlay: shouldAutoPlay,
937 1854 labels,
1855 + waveformStyle: context.waveformStyle,
1856 + showPlayButtonArtwork,
938 1857 onEnded: () => {
939 1858 const currentIndex = context.tracks.findIndex(
940 - (uniqueId) => uniqueId === context.currentId
1859 + (trackId) => trackId === context.currentId
941 1860 );
942 1861 const nextTrack = context.tracks[currentIndex + 1];
943 1862 if (nextTrack) {
944 1863 context.currentId = nextTrack;
@@ -944,11 +1863,28 @@
944 1863 context.currentId = nextTrack;
945 1864 }
946 1865 }
947 1866 });
948 - playerState.set(ref, {
1867 + const setIsPlaying = (isPlaying) => {
1868 + context.isPlaying = isPlaying;
1869 + };
1870 + const onPlay = () => setIsPlaying(true);
1871 + const onPause = () => setIsPlaying(false);
1872 + player.container.addEventListener("waveformplayer:play", onPlay);
1873 + player.container.addEventListener("waveformplayer:pause", onPause);
1874 + player.container.addEventListener("waveformplayer:ended", onPause);
1875 + const destroy = () => {
1876 + player.container.removeEventListener("waveformplayer:play", onPlay);
1877 + player.container.removeEventListener("waveformplayer:pause", onPause);
1878 + player.container.removeEventListener("waveformplayer:ended", onPause);
1879 + player.destroy();
1880 + };
1881 + const nextState = {
949 1882 url: track.url,
950 1883 instance: player.instance,
951 - destroy: player.destroy
952 - });
1884 + container: player.container,
1885 + destroy
1886 + };
1887 + playerState.set(ref, nextState);
1888 + playlistPlayerState.set(context.playlistId, nextState);
953 1889 }
954 1890 //# sourceMappingURL=view.js.map