| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 // packages/block-library/build-module/playlist/view.mjs 2 import { store, getContext, getElement } from "@wordpress/interactivity"; 3 4 // node_modules/colord/index.mjs 5 var r = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }; 6 var t = function(r2) { 7 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) { 22 return { r: n(r2.r), g: n(r2.g), b: n(r2.b), a: n(r2.a, 3) }; 23 }; 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; 28 }; 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 }; 32 }; 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 }; 38 }; 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) }; 41 }; 42 var d = function(r2) { 43 return { h: n(r2.h), s: n(r2.s), l: n(r2.l), a: n(r2.a, 3) }; 44 }; 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; 48 }; 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); 83 }, "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]]; 88 } 89 return [null, void 0]; 90 }; 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]; 93 }; 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 }; 97 }; 98 var H = function(r2) { 99 return (299 * r2.r + 587 * r2.g + 114 * r2.b) / 1e3 / 255; 100 }; 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 }; 104 }; 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 }; 108 } 109 return r2.prototype.isValid = function() { 110 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; 157 })(); 158 var w = function(r2) { 159 return r2 instanceof j ? r2 : new j(r2); 160 }; 161 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); 169 } 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); 174 } 175 return t3.dataset.enableMediaSession !== void 0 && (e2.enableMediaSession = t3.dataset.enableMediaSession === "true"), e2; 176 } 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")}`; 181 } 182 function A(t3) { 183 let e2 = t3 || Math.random().toString(); 184 return btoa(e2.substring(0, 10)).replace(/[^a-zA-Z0-9]/g, ""); 185 } 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()); 190 } 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]); 194 return e2; 195 } 196 function B(t3, e2) { 197 let i2; 198 return function(...s2) { 199 let n2 = () => { 200 clearTimeout(i2), t3(...s2); 201 }; 202 clearTimeout(i2), i2 = setTimeout(n2, e2); 203 }; 204 } 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]); 215 else { 216 let l2 = t3[r2] * (1 - h2) + t3[o2] * h2; 217 i2.push(l2); 218 } 219 } 220 } 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]; 228 } 229 i2.push(o2); 230 } 231 } 232 return i2; 233 } 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); 242 } 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); 249 } 250 t3.restore(); 251 } 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); 260 } 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); 267 } 268 t3.restore(); 269 } 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 }); 279 } 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); 283 } 284 t3.stroke(), f2 && (t3.shadowBlur = 0); 285 }; 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(); 290 } 291 l2(s2.color, 2, 1, false), a2 > 0 && l2(s2.progressColor, 3, a2, true); 292 } 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); 304 } 305 } 306 } 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(); 315 } 316 } 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(); 324 } 325 } 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); 329 } 330 function I(t3) { 331 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); 340 }); 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; 346 } 347 } 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); 358 } 359 n2 = o2 * 0.8 + n2 * 0.2; 360 } 361 return s2; 362 } 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); 372 } 373 let c2 = Math.max(Math.abs(f2), Math.abs(y2)); 374 (o2 === 0 || c2 > n2[l2]) && (n2[l2] = c2); 375 } 376 } 377 let r2 = Math.max(...n2); 378 return r2 > 0 ? n2.map((o2) => o2 / r2) : n2; 379 } 380 async function M2(t3, e2 = 200, i2 = false) { 381 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; 388 } 389 } 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))); 395 } 396 return e2; 397 } 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); 403 } 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 { 416 } 417 if (window.matchMedia) { 418 if (window.matchMedia("(prefers-color-scheme: dark)").matches) return "dark"; 419 if (window.matchMedia("(prefers-color-scheme: light)").matches) return "light"; 420 } 421 return "dark"; 422 } 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]; 428 } 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 { 432 static instances = /* @__PURE__ */ new Map(); 433 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 } })); 443 }, 100); 444 } 445 init() { 446 this.createDOM(), this.createAudio(), this.initPlaybackSpeed(), this.initKeyboardControls(), this.bindEvents(), this.setupResizeObserver(), requestAnimationFrame(() => { 447 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); 451 }); 452 }); 453 } 454 createDOM() { 455 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 "> 465 <span class="waveform-icon-play">$this.options.playIcon}</span> 466 <span class="waveform-icon-pause" style="display:none;">$this.options.pauseIcon}</span> 467 </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 479 <div class="waveform-info"> 480 $this.options.artwork ? ` 481 <img class="waveform-artwork" src="$this.options.artwork}" alt="Album artwork" style=" 482 width: 40px; 483 height: 40px; 484 border-radius: 4px; 485 object-fit: cover; 486 flex-shrink: 0; 487 "> 488 ` : ""} 489 <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>` : ""} 492 </div> 493 <div style="display: flex; align-items: center; gap: 1rem;"> 494 $this.options.showBPM ? ` 495 <span class="waveform-bpm" style="color: $this.options.textSecondaryColor}; display: none;"> 496 <span class="bpm-value">--</span> BPM 497 </span> 498 ` : ""} 499 $this.options.showPlaybackSpeed ? ` 500 <div class="waveform-speed"> 501 <button class="speed-btn" aria-label="Playback speed"> 502 <span class="speed-value">1x</span> 503 </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("")} 506 </div> 507 </div> 508 ` : ""} 509 $this.options.showTime ? ` 510 <span class="waveform-time" style="color: $this.options.textSecondaryColor};"> 511 <span class="time-current">0:00</span> / <span class="time-total">0:00</span> 512 </span> 513 ` : ""} 514 </div> 515 </div> 516 </div> 517 </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(); 519 } 520 createAudio() { 521 this.audio = new Audio(), this.audio.preload = this.options.preload || "metadata", this.audio.crossOrigin = "anonymous"; 522 } 523 initPlaybackSpeed() { 524 this.options.playbackRate && this.options.playbackRate !== 1 && (this.audio.playbackRate = this.options.playbackRate), this.options.showPlaybackSpeed && this.initSpeedControls(); 525 } 526 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"; 536 } 537 }), this.updateSpeedUI()); 538 } 539 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) => { 545 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); 549 return; 550 } 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 }); 554 } 555 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)); 558 }), 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 })); 563 } 564 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); 566 } 567 setupResizeObserver() { 568 "ResizeObserver" in window && (this.resizeObserver = new ResizeObserver(() => { 569 this.resizeCanvas(); 570 }), this.canvas?.parentElement && this.resizeObserver.observe(this.canvas.parentElement)); 571 } 572 async load(e2) { 573 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); 579 }; 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); 589 } 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); 593 } finally { 594 this.setLoading(false); 595 } 596 } 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(); 599 } 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); 606 } 607 else this.waveformData = Array.isArray(e2) ? e2 : []; 608 this.drawWaveform(); 609 } 610 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 }); 612 } 613 resizeCanvas() { 614 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(); 617 } 618 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`); 622 return; 623 } 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); 630 })); 631 } 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); 636 } 637 setLoading(e2) { 638 this.isLoading = e2, this.loadingEl && (this.loadingEl.style.display = e2 ? "block" : "none"); 639 } 640 onMetadataLoaded() { 641 this.isDestroying || (this.totalTimeEl && (this.totalTimeEl.textContent = P(this.audio.duration)), this.renderMarkers()); 642 } 643 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); 648 } 649 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); 654 } 655 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)); 657 } 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)); 660 } 661 startSmoothUpdate() { 662 this.stopSmoothUpdate(); 663 let e2 = () => { 664 this.isPlaying && this.audio.duration && (this.updateProgress(), this.updateTimer = requestAnimationFrame(e2)); 665 }; 666 this.updateTimer = requestAnimationFrame(e2); 667 } 668 stopSmoothUpdate() { 669 this.updateTimer && (cancelAnimationFrame(this.updateTimer), this.updateTimer = null); 670 } 671 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); 675 } 676 updateBPMDisplay() { 677 this.bpmEl && this.bpmValueEl && this.detectedBPM && (this.bpmValueEl.textContent = Math.round(this.detectedBPM), this.bpmEl.style.display = "inline-flex"); 678 } 679 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`; 684 } 685 this.container.querySelectorAll(".speed-option").forEach((i2) => { 686 i2.classList.toggle("active", parseFloat(i2.dataset.rate) === this.audio.playbackRate); 687 }); 688 } 689 play() { 690 this.options.singlePlay && t2.currentlyPlaying && t2.currentlyPlaying !== this && t2.currentlyPlaying.pause(), t2.currentlyPlaying = this, this.audio.play(); 691 } 692 pause() { 693 t2.currentlyPlaying === this && (t2.currentlyPlaying = null), this.audio.pause(); 694 } 695 togglePlay() { 696 this.isPlaying ? this.pause() : this.play(); 697 } 698 seekTo(e2) { 699 this.audio && this.audio.duration && (this.audio.currentTime = Math.max(0, Math.min(e2, this.audio.duration)), this.updateProgress()); 700 } 701 seekToPercent(e2) { 702 this.audio && this.audio.duration && (this.audio.currentTime = this.audio.duration * Math.max(0, Math.min(1, e2)), this.updateProgress()); 703 } 704 setVolume(e2) { 705 this.audio && (this.audio.volume = Math.max(0, Math.min(1, e2))); 706 } 707 setPlaybackRate(e2) { 708 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(); 711 } 712 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 = []; 714 } 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); 721 } 722 if (e2 instanceof HTMLElement) return Array.from(this.instances.values()).find((i2) => i2.container === e2); 723 } 724 static getAllInstances() { 725 return Array.from(this.instances.values()); 726 } 727 static destroyAll() { 728 this.instances.forEach((e2) => e2.destroy()), this.instances.clear(); 729 } 730 static async generateWaveformData(e2, i2 = 200) { 731 try { 732 return (await M2(e2, i2)).peaks; 733 } catch (a2) { 734 throw console.error("Failed to generate waveform:", a2), a2; 735 } 736 } 737 }; 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 }); 747 } 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; 752 753 // packages/block-library/build-module/utils/waveform-utils.mjs 754 var DEFAULT_WAVEFORM_HEIGHT = 100; 755 function getComputedStyle2(element) { 756 return element.ownerDocument.defaultView.getComputedStyle(element); 757 } 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 }; 763 } 764 function createWaveformContainer({ 765 url, 766 title, 767 artist, 768 artwork, 769 waveformColor, 770 progressColor, 771 buttonColor, 772 height = DEFAULT_WAVEFORM_HEIGHT, 773 waveformStyle = "bars" 774 }) { 775 const container = document.createElement("div"); 776 container.setAttribute("data-waveform-player", ""); 777 container.setAttribute("data-url", url); 778 container.setAttribute("data-height", String(height)); 779 container.setAttribute("data-waveform-style", waveformStyle); 780 container.setAttribute("data-waveform-color", waveformColor); 781 container.setAttribute("data-progress-color", progressColor); 782 container.setAttribute("data-button-color", buttonColor); 783 container.setAttribute("data-text-color", buttonColor); 784 container.setAttribute("data-text-secondary-color", buttonColor); 785 if (title) { 786 container.setAttribute("data-title", title); 787 } 788 if (artist) { 789 container.setAttribute("data-subtitle", artist); 790 } 791 if (artwork) { 792 container.setAttribute("data-artwork", artwork); 793 } 794 return container; 795 } 796 function styleSvgIcons(container, buttonColor) { 797 const isButtonDark = w(buttonColor).isDark(); 798 const iconColor = isButtonDark ? "#ffffff" : "#000000"; 799 const svgPaths = container.querySelectorAll("svg path"); 800 svgPaths.forEach((path) => { 801 path.style.fill = iconColor; 802 }); 803 } 804 function setupPlayButtonAccessibility(container, { play: playLabel = "Play", pause: pauseLabel = "Pause" } = {}) { 805 const playBtn = container.querySelector(".waveform-btn"); 806 if (!playBtn) { 807 return; 808 } 809 playBtn.setAttribute("aria-label", playLabel); 810 const onPlay = () => playBtn.setAttribute("aria-label", pauseLabel); 811 const onPause = () => playBtn.setAttribute("aria-label", playLabel); 812 container.addEventListener("waveformplayer:play", onPlay); 813 container.addEventListener("waveformplayer:pause", onPause); 814 container.addEventListener("waveformplayer:ended", onPause); 815 return () => { 816 container.removeEventListener("waveformplayer:play", onPlay); 817 container.removeEventListener("waveformplayer:pause", onPause); 818 container.removeEventListener("waveformplayer:ended", onPause); 819 }; 820 } 821 function logPlayError(error) { 822 if (error.name === "AbortError") { 823 return; 824 } 825 console.error("Playlist play error:", error); 826 } 827 function initWaveformPlayer(element, { src, title, artist, image, autoPlay, onEnded, labels, waveformStyle }) { 828 const { textColor, waveformColor, progressColor } = getWaveformColors(element); 829 const container = createWaveformContainer({ 830 url: src, 831 title, 832 artist, 833 artwork: image, 834 waveformColor, 835 progressColor, 836 buttonColor: textColor, 837 waveformStyle 838 }); 839 element.appendChild(container); 840 const instance = new lt(container); 841 let cleanupAccessibility; 842 const handlers = { 843 ready: () => { 844 styleSvgIcons(container, textColor); 845 cleanupAccessibility = setupPlayButtonAccessibility( 846 container, 847 labels 848 ); 849 if (autoPlay) { 850 instance.play()?.catch(logPlayError); 851 } 852 }, 853 ended: () => onEnded?.() 854 }; 855 container.addEventListener("waveformplayer:ready", handlers.ready); 856 container.addEventListener("waveformplayer:ended", handlers.ended); 857 return { 858 instance, 859 container, 860 destroy: () => { 861 cleanupAccessibility?.(); 862 container.removeEventListener( 863 "waveformplayer:ready", 864 handlers.ready 865 ); 866 container.removeEventListener( 867 "waveformplayer:ended", 868 handlers.ended 869 ); 870 instance.destroy(); 871 container.remove(); 872 } 873 }; 874 } 875 876 // packages/block-library/build-module/playlist/view.mjs 877 var playerState = /* @__PURE__ */ new WeakMap(); 878 var { state } = store( 879 "core/playlist", 880 { 881 state: { 882 playlists: {}, 883 get isCurrentTrack() { 884 const { currentId, uniqueId } = getContext(); 885 return currentId === uniqueId; 886 } 887 }, 888 actions: { 889 changeTrack() { 890 const context = getContext(); 891 context.currentId = context.uniqueId; 892 } 893 }, 894 callbacks: { 895 initWaveformPlayer() { 896 const context = getContext(); 897 const { ref } = getElement(); 898 if (!context.currentId || !ref) { 899 return; 900 } 901 const track = state.playlists[context.playlistId]?.tracks[context.currentId]; 902 if (!track?.url) { 903 return; 904 } 905 const existing = playerState.get(ref); 906 if (existing?.url === track.url) { 907 return; 908 } 909 const shouldAutoPlay = !!existing?.url; 910 initPlayer(ref, track, shouldAutoPlay, context); 911 } 912 } 913 }, 914 { lock: true } 915 ); 916 function initPlayer(ref, track, shouldAutoPlay, context) { 917 const existing = playerState.get(ref); 918 if (existing?.instance) { 919 existing.instance.loadTrack(track.url, track.title, track.artist, { 920 artwork: track.image 921 }).then(() => { 922 existing.url = track.url; 923 if (shouldAutoPlay) { 924 existing.instance.play()?.catch(logPlayError); 925 } 926 }).catch(logPlayError); 927 return; 928 } 929 const labels = { 930 play: ref.dataset.labelPlay, 931 pause: ref.dataset.labelPause 932 }; 933 const player = initWaveformPlayer(ref, { 934 src: track.url, 935 title: track.title, 936 artist: track.artist, 937 image: track.image, 938 autoPlay: shouldAutoPlay, 939 labels, 940 waveformStyle: context.waveformStyle, 941 onEnded: () => { 942 const currentIndex = context.tracks.findIndex( 943 (uniqueId) => uniqueId === context.currentId 944 ); 945 const nextTrack = context.tracks[currentIndex + 1]; 946 if (nextTrack) { 947 context.currentId = nextTrack; 948 } 949 } 950 }); 951 playerState.set(ref, { 952 url: track.url, 953 instance: player.instance, 954 destroy: player.destroy 955 }); 956 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Fri Jul 3 08:20:12 2026 | Cross-referenced by PHPXref |