@arraypress/waveform-bar 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -334
- package/dist/waveform-bar-icons.css +14 -5
- package/dist/waveform-bar.esm.js +101 -14
- package/dist/waveform-bar.js +101 -14
- package/dist/waveform-bar.min.js +8 -8
- package/package.json +1 -1
- package/src/css/waveform-bar-icons.css +14 -5
- package/src/js/core.js +132 -17
|
@@ -5,12 +5,21 @@
|
|
|
5
5
|
* MIT License
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
*
|
|
8
|
+
* <span class="wbi wbi-play"></span>
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
.wbi
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
.wbi {
|
|
12
|
+
display: inline-block;
|
|
13
|
+
width: 1em;
|
|
14
|
+
height: 1em;
|
|
15
|
+
background-color: currentColor;
|
|
16
|
+
-webkit-mask-size: contain;
|
|
17
|
+
mask-size: contain;
|
|
18
|
+
-webkit-mask-repeat: no-repeat;
|
|
19
|
+
mask-repeat: no-repeat;
|
|
20
|
+
-webkit-mask-position: center;
|
|
21
|
+
mask-position: center;
|
|
22
|
+
vertical-align: -0.125em;
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
.wbi-sm {
|
|
@@ -136,4 +145,4 @@
|
|
|
136
145
|
.wbi-share {
|
|
137
146
|
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z'/></svg>");
|
|
138
147
|
mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z'/></svg>");
|
|
139
|
-
}
|
|
148
|
+
}
|
package/dist/waveform-bar.esm.js
CHANGED
|
@@ -317,8 +317,6 @@ var DEFAULTS = {
|
|
|
317
317
|
waveformColor: null,
|
|
318
318
|
progressColor: null,
|
|
319
319
|
markerColor: "rgba(255, 255, 255, 0.25)",
|
|
320
|
-
configPath: null,
|
|
321
|
-
// Directory for auto-resolved config JSON files (e.g. 'waveforms/')
|
|
322
320
|
volume: 1,
|
|
323
321
|
storageKey: "waveform-bar",
|
|
324
322
|
actions: null,
|
|
@@ -538,6 +536,7 @@ var WaveformBar = class {
|
|
|
538
536
|
this.isPlaying = true;
|
|
539
537
|
this._updatePlayButton();
|
|
540
538
|
this._syncPageState();
|
|
539
|
+
this._pumpExternalPlayState(true);
|
|
541
540
|
const track = this.getCurrentTrack();
|
|
542
541
|
this._emit("play", { track });
|
|
543
542
|
if (this.config.onPlay) this.config.onPlay(track);
|
|
@@ -546,6 +545,7 @@ var WaveformBar = class {
|
|
|
546
545
|
this.isPlaying = false;
|
|
547
546
|
this._updatePlayButton();
|
|
548
547
|
this._syncPageState();
|
|
548
|
+
this._pumpExternalPlayState(false);
|
|
549
549
|
this._saveState();
|
|
550
550
|
const track = this.getCurrentTrack();
|
|
551
551
|
this._emit("pause", { track });
|
|
@@ -555,6 +555,7 @@ var WaveformBar = class {
|
|
|
555
555
|
this.isPlaying = false;
|
|
556
556
|
this._updatePlayButton();
|
|
557
557
|
this._syncPageState();
|
|
558
|
+
this._pumpExternalPlayState(false);
|
|
558
559
|
if (this.timeCurrentEl) this.timeCurrentEl.textContent = "0:00";
|
|
559
560
|
if (this.repeat === "one") {
|
|
560
561
|
if (this.player) {
|
|
@@ -576,6 +577,7 @@ var WaveformBar = class {
|
|
|
576
577
|
this._lastPosition = currentTime;
|
|
577
578
|
if (this.timeCurrentEl) this.timeCurrentEl.textContent = formatTime(currentTime);
|
|
578
579
|
if (this.timeTotalEl) this.timeTotalEl.textContent = formatTime(duration);
|
|
580
|
+
this._pumpExternalProgress(currentTime, duration);
|
|
579
581
|
if (!this._lastSaveTime || currentTime - this._lastSaveTime > 2) {
|
|
580
582
|
this._lastSaveTime = currentTime;
|
|
581
583
|
this._saveState();
|
|
@@ -614,6 +616,102 @@ var WaveformBar = class {
|
|
|
614
616
|
if (track) this.addToQueue(track);
|
|
615
617
|
});
|
|
616
618
|
});
|
|
619
|
+
this._attachExternalPlayers();
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Discover external-mode WaveformPlayer instances and listen for
|
|
623
|
+
* their request-play / request-pause / request-seek events. Also
|
|
624
|
+
* builds a url → Set<WaveformPlayer> map used by _syncPageState()
|
|
625
|
+
* and the onTimeUpdate callback to push state into the matching
|
|
626
|
+
* inline visualizations.
|
|
627
|
+
*
|
|
628
|
+
* Idempotent — safe to call repeatedly. Late-mounted players are
|
|
629
|
+
* picked up by the MutationObserver in _observeDOM().
|
|
630
|
+
*
|
|
631
|
+
* @private
|
|
632
|
+
*/
|
|
633
|
+
_attachExternalPlayers() {
|
|
634
|
+
if (!this._externalListenersBound) {
|
|
635
|
+
this._externalListenersBound = true;
|
|
636
|
+
document.addEventListener("waveformplayer:request-play", (e) => {
|
|
637
|
+
const t = e.detail;
|
|
638
|
+
if (!t || !t.url) return;
|
|
639
|
+
e.preventDefault();
|
|
640
|
+
this.play(t);
|
|
641
|
+
});
|
|
642
|
+
document.addEventListener("waveformplayer:request-pause", (e) => {
|
|
643
|
+
const t = e.detail;
|
|
644
|
+
if (!t || !t.url) return;
|
|
645
|
+
const current = this.getCurrentTrack();
|
|
646
|
+
if (current && current.url === t.url) {
|
|
647
|
+
e.preventDefault();
|
|
648
|
+
if (this.isPlaying) this.togglePlay();
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
document.addEventListener("waveformplayer:request-seek", (e) => {
|
|
652
|
+
const t = e.detail;
|
|
653
|
+
if (!t || !t.url || typeof t.percent !== "number") return;
|
|
654
|
+
const current = this.getCurrentTrack();
|
|
655
|
+
if (current && current.url === t.url && this.player && this.player.audio) {
|
|
656
|
+
e.preventDefault();
|
|
657
|
+
this.player.seekToPercent(t.percent);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
this._externalPlayers = /* @__PURE__ */ new Map();
|
|
662
|
+
const WP = window.WaveformPlayer;
|
|
663
|
+
if (!WP || !WP.instances) return;
|
|
664
|
+
document.querySelectorAll('[data-waveform-player][data-audio-mode="external"]').forEach((el) => {
|
|
665
|
+
const inst = WP.instances.get(el.id);
|
|
666
|
+
if (!inst || !inst.options || !inst.options.url) return;
|
|
667
|
+
const url = inst.options.url;
|
|
668
|
+
if (!this._externalPlayers.has(url)) this._externalPlayers.set(url, /* @__PURE__ */ new Set());
|
|
669
|
+
this._externalPlayers.get(url).add(inst);
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Push playing-state into every external-mode player whose URL
|
|
674
|
+
* matches the currently playing track. Other URLs get set to
|
|
675
|
+
* false (paused) — covers the case where the bar switched tracks
|
|
676
|
+
* and the previously-current external player should stop showing
|
|
677
|
+
* its play indicator.
|
|
678
|
+
*
|
|
679
|
+
* @private
|
|
680
|
+
* @param {boolean} playing
|
|
681
|
+
*/
|
|
682
|
+
_pumpExternalPlayState(playing) {
|
|
683
|
+
if (!this._externalPlayers || this._externalPlayers.size === 0) return;
|
|
684
|
+
const current = this.getCurrentTrack();
|
|
685
|
+
const currentUrl = current ? current.url : null;
|
|
686
|
+
this._externalPlayers.forEach((set, url) => {
|
|
687
|
+
const isCurrent = url === currentUrl;
|
|
688
|
+
set.forEach((player) => {
|
|
689
|
+
if (typeof player.setPlayingState === "function") {
|
|
690
|
+
player.setPlayingState(isCurrent && playing);
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Push progress (currentTime + duration) into the external-mode
|
|
697
|
+
* player(s) tracking the current URL. Called on every timeupdate
|
|
698
|
+
* tick of the internal player.
|
|
699
|
+
*
|
|
700
|
+
* @private
|
|
701
|
+
* @param {number} currentTime
|
|
702
|
+
* @param {number} duration
|
|
703
|
+
*/
|
|
704
|
+
_pumpExternalProgress(currentTime, duration) {
|
|
705
|
+
if (!this._externalPlayers || this._externalPlayers.size === 0) return;
|
|
706
|
+
const current = this.getCurrentTrack();
|
|
707
|
+
if (!current) return;
|
|
708
|
+
const set = this._externalPlayers.get(current.url);
|
|
709
|
+
if (!set) return;
|
|
710
|
+
set.forEach((player) => {
|
|
711
|
+
if (typeof player.setProgress === "function") {
|
|
712
|
+
player.setProgress(currentTime, duration);
|
|
713
|
+
}
|
|
714
|
+
});
|
|
617
715
|
}
|
|
618
716
|
_observeDOM() {
|
|
619
717
|
if (typeof MutationObserver === "undefined") return;
|
|
@@ -969,6 +1067,7 @@ var WaveformBar = class {
|
|
|
969
1067
|
_loadCurrentTrack() {
|
|
970
1068
|
const track = this.getCurrentTrack();
|
|
971
1069
|
if (!track || !this.player) return;
|
|
1070
|
+
this._pumpExternalPlayState(false);
|
|
972
1071
|
this.show();
|
|
973
1072
|
this._updateTrackDisplay(track);
|
|
974
1073
|
this._updateFavoriteUI();
|
|
@@ -976,12 +1075,6 @@ var WaveformBar = class {
|
|
|
976
1075
|
if (track.waveform) {
|
|
977
1076
|
loadOpts.waveform = track.waveform;
|
|
978
1077
|
}
|
|
979
|
-
if (this.config.configPath && track.url) {
|
|
980
|
-
const audioFile = track.url.split("/").pop().split("?")[0];
|
|
981
|
-
const jsonFile = audioFile.replace(/\.[^.]+$/, ".json");
|
|
982
|
-
const path = this.config.configPath.replace(/\/?$/, "/");
|
|
983
|
-
loadOpts.config = path + jsonFile;
|
|
984
|
-
}
|
|
985
1078
|
if (track.markers && track.markers.length) {
|
|
986
1079
|
const defaultColor = this.config.markerColor;
|
|
987
1080
|
loadOpts.markers = track.markers.map((m) => ({
|
|
@@ -1322,12 +1415,6 @@ var WaveformBar = class {
|
|
|
1322
1415
|
if (track.waveform) {
|
|
1323
1416
|
this.player.options.waveform = track.waveform;
|
|
1324
1417
|
}
|
|
1325
|
-
if (this.config.configPath && track.url) {
|
|
1326
|
-
const audioFile = track.url.split("/").pop().split("?")[0];
|
|
1327
|
-
const jsonFile = audioFile.replace(/\.[^.]+$/, ".json");
|
|
1328
|
-
const path = this.config.configPath.replace(/\/?$/, "/");
|
|
1329
|
-
this.player.options.config = path + jsonFile;
|
|
1330
|
-
}
|
|
1331
1418
|
this.player.options.title = track.title || "";
|
|
1332
1419
|
this.player.options.subtitle = track.artist || "";
|
|
1333
1420
|
if (track.markers && track.markers.length) {
|
package/dist/waveform-bar.js
CHANGED
|
@@ -318,8 +318,6 @@
|
|
|
318
318
|
waveformColor: null,
|
|
319
319
|
progressColor: null,
|
|
320
320
|
markerColor: "rgba(255, 255, 255, 0.25)",
|
|
321
|
-
configPath: null,
|
|
322
|
-
// Directory for auto-resolved config JSON files (e.g. 'waveforms/')
|
|
323
321
|
volume: 1,
|
|
324
322
|
storageKey: "waveform-bar",
|
|
325
323
|
actions: null,
|
|
@@ -539,6 +537,7 @@
|
|
|
539
537
|
this.isPlaying = true;
|
|
540
538
|
this._updatePlayButton();
|
|
541
539
|
this._syncPageState();
|
|
540
|
+
this._pumpExternalPlayState(true);
|
|
542
541
|
const track = this.getCurrentTrack();
|
|
543
542
|
this._emit("play", { track });
|
|
544
543
|
if (this.config.onPlay) this.config.onPlay(track);
|
|
@@ -547,6 +546,7 @@
|
|
|
547
546
|
this.isPlaying = false;
|
|
548
547
|
this._updatePlayButton();
|
|
549
548
|
this._syncPageState();
|
|
549
|
+
this._pumpExternalPlayState(false);
|
|
550
550
|
this._saveState();
|
|
551
551
|
const track = this.getCurrentTrack();
|
|
552
552
|
this._emit("pause", { track });
|
|
@@ -556,6 +556,7 @@
|
|
|
556
556
|
this.isPlaying = false;
|
|
557
557
|
this._updatePlayButton();
|
|
558
558
|
this._syncPageState();
|
|
559
|
+
this._pumpExternalPlayState(false);
|
|
559
560
|
if (this.timeCurrentEl) this.timeCurrentEl.textContent = "0:00";
|
|
560
561
|
if (this.repeat === "one") {
|
|
561
562
|
if (this.player) {
|
|
@@ -577,6 +578,7 @@
|
|
|
577
578
|
this._lastPosition = currentTime;
|
|
578
579
|
if (this.timeCurrentEl) this.timeCurrentEl.textContent = formatTime(currentTime);
|
|
579
580
|
if (this.timeTotalEl) this.timeTotalEl.textContent = formatTime(duration);
|
|
581
|
+
this._pumpExternalProgress(currentTime, duration);
|
|
580
582
|
if (!this._lastSaveTime || currentTime - this._lastSaveTime > 2) {
|
|
581
583
|
this._lastSaveTime = currentTime;
|
|
582
584
|
this._saveState();
|
|
@@ -615,6 +617,102 @@
|
|
|
615
617
|
if (track) this.addToQueue(track);
|
|
616
618
|
});
|
|
617
619
|
});
|
|
620
|
+
this._attachExternalPlayers();
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Discover external-mode WaveformPlayer instances and listen for
|
|
624
|
+
* their request-play / request-pause / request-seek events. Also
|
|
625
|
+
* builds a url → Set<WaveformPlayer> map used by _syncPageState()
|
|
626
|
+
* and the onTimeUpdate callback to push state into the matching
|
|
627
|
+
* inline visualizations.
|
|
628
|
+
*
|
|
629
|
+
* Idempotent — safe to call repeatedly. Late-mounted players are
|
|
630
|
+
* picked up by the MutationObserver in _observeDOM().
|
|
631
|
+
*
|
|
632
|
+
* @private
|
|
633
|
+
*/
|
|
634
|
+
_attachExternalPlayers() {
|
|
635
|
+
if (!this._externalListenersBound) {
|
|
636
|
+
this._externalListenersBound = true;
|
|
637
|
+
document.addEventListener("waveformplayer:request-play", (e) => {
|
|
638
|
+
const t = e.detail;
|
|
639
|
+
if (!t || !t.url) return;
|
|
640
|
+
e.preventDefault();
|
|
641
|
+
this.play(t);
|
|
642
|
+
});
|
|
643
|
+
document.addEventListener("waveformplayer:request-pause", (e) => {
|
|
644
|
+
const t = e.detail;
|
|
645
|
+
if (!t || !t.url) return;
|
|
646
|
+
const current = this.getCurrentTrack();
|
|
647
|
+
if (current && current.url === t.url) {
|
|
648
|
+
e.preventDefault();
|
|
649
|
+
if (this.isPlaying) this.togglePlay();
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
document.addEventListener("waveformplayer:request-seek", (e) => {
|
|
653
|
+
const t = e.detail;
|
|
654
|
+
if (!t || !t.url || typeof t.percent !== "number") return;
|
|
655
|
+
const current = this.getCurrentTrack();
|
|
656
|
+
if (current && current.url === t.url && this.player && this.player.audio) {
|
|
657
|
+
e.preventDefault();
|
|
658
|
+
this.player.seekToPercent(t.percent);
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
this._externalPlayers = /* @__PURE__ */ new Map();
|
|
663
|
+
const WP = window.WaveformPlayer;
|
|
664
|
+
if (!WP || !WP.instances) return;
|
|
665
|
+
document.querySelectorAll('[data-waveform-player][data-audio-mode="external"]').forEach((el) => {
|
|
666
|
+
const inst = WP.instances.get(el.id);
|
|
667
|
+
if (!inst || !inst.options || !inst.options.url) return;
|
|
668
|
+
const url = inst.options.url;
|
|
669
|
+
if (!this._externalPlayers.has(url)) this._externalPlayers.set(url, /* @__PURE__ */ new Set());
|
|
670
|
+
this._externalPlayers.get(url).add(inst);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Push playing-state into every external-mode player whose URL
|
|
675
|
+
* matches the currently playing track. Other URLs get set to
|
|
676
|
+
* false (paused) — covers the case where the bar switched tracks
|
|
677
|
+
* and the previously-current external player should stop showing
|
|
678
|
+
* its play indicator.
|
|
679
|
+
*
|
|
680
|
+
* @private
|
|
681
|
+
* @param {boolean} playing
|
|
682
|
+
*/
|
|
683
|
+
_pumpExternalPlayState(playing) {
|
|
684
|
+
if (!this._externalPlayers || this._externalPlayers.size === 0) return;
|
|
685
|
+
const current = this.getCurrentTrack();
|
|
686
|
+
const currentUrl = current ? current.url : null;
|
|
687
|
+
this._externalPlayers.forEach((set, url) => {
|
|
688
|
+
const isCurrent = url === currentUrl;
|
|
689
|
+
set.forEach((player) => {
|
|
690
|
+
if (typeof player.setPlayingState === "function") {
|
|
691
|
+
player.setPlayingState(isCurrent && playing);
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Push progress (currentTime + duration) into the external-mode
|
|
698
|
+
* player(s) tracking the current URL. Called on every timeupdate
|
|
699
|
+
* tick of the internal player.
|
|
700
|
+
*
|
|
701
|
+
* @private
|
|
702
|
+
* @param {number} currentTime
|
|
703
|
+
* @param {number} duration
|
|
704
|
+
*/
|
|
705
|
+
_pumpExternalProgress(currentTime, duration) {
|
|
706
|
+
if (!this._externalPlayers || this._externalPlayers.size === 0) return;
|
|
707
|
+
const current = this.getCurrentTrack();
|
|
708
|
+
if (!current) return;
|
|
709
|
+
const set = this._externalPlayers.get(current.url);
|
|
710
|
+
if (!set) return;
|
|
711
|
+
set.forEach((player) => {
|
|
712
|
+
if (typeof player.setProgress === "function") {
|
|
713
|
+
player.setProgress(currentTime, duration);
|
|
714
|
+
}
|
|
715
|
+
});
|
|
618
716
|
}
|
|
619
717
|
_observeDOM() {
|
|
620
718
|
if (typeof MutationObserver === "undefined") return;
|
|
@@ -970,6 +1068,7 @@
|
|
|
970
1068
|
_loadCurrentTrack() {
|
|
971
1069
|
const track = this.getCurrentTrack();
|
|
972
1070
|
if (!track || !this.player) return;
|
|
1071
|
+
this._pumpExternalPlayState(false);
|
|
973
1072
|
this.show();
|
|
974
1073
|
this._updateTrackDisplay(track);
|
|
975
1074
|
this._updateFavoriteUI();
|
|
@@ -977,12 +1076,6 @@
|
|
|
977
1076
|
if (track.waveform) {
|
|
978
1077
|
loadOpts.waveform = track.waveform;
|
|
979
1078
|
}
|
|
980
|
-
if (this.config.configPath && track.url) {
|
|
981
|
-
const audioFile = track.url.split("/").pop().split("?")[0];
|
|
982
|
-
const jsonFile = audioFile.replace(/\.[^.]+$/, ".json");
|
|
983
|
-
const path = this.config.configPath.replace(/\/?$/, "/");
|
|
984
|
-
loadOpts.config = path + jsonFile;
|
|
985
|
-
}
|
|
986
1079
|
if (track.markers && track.markers.length) {
|
|
987
1080
|
const defaultColor = this.config.markerColor;
|
|
988
1081
|
loadOpts.markers = track.markers.map((m) => ({
|
|
@@ -1323,12 +1416,6 @@
|
|
|
1323
1416
|
if (track.waveform) {
|
|
1324
1417
|
this.player.options.waveform = track.waveform;
|
|
1325
1418
|
}
|
|
1326
|
-
if (this.config.configPath && track.url) {
|
|
1327
|
-
const audioFile = track.url.split("/").pop().split("?")[0];
|
|
1328
|
-
const jsonFile = audioFile.replace(/\.[^.]+$/, ".json");
|
|
1329
|
-
const path = this.config.configPath.replace(/\/?$/, "/");
|
|
1330
|
-
this.player.options.config = path + jsonFile;
|
|
1331
|
-
}
|
|
1332
1419
|
this.player.options.title = track.title || "";
|
|
1333
1420
|
this.player.options.subtitle = track.artist || "";
|
|
1334
1421
|
if (track.markers && track.markers.length) {
|
package/dist/waveform-bar.min.js
CHANGED
|
@@ -22,26 +22,26 @@
|
|
|
22
22
|
<button class="wb-btn wb-btn-sm wb-queue-clear" aria-label="Clear queue">Clear</button>
|
|
23
23
|
</div>
|
|
24
24
|
<div class="wb-queue-body"></div>
|
|
25
|
-
`,s}function
|
|
25
|
+
`,s}function x(s,t,e,i,r){if(!s)return;let a=Math.max(0,e.length-1-i);if(t&&(t.textContent=a),e.length===0){s.innerHTML=`<div class="wb-queue-empty">${n.queue}<p>Queue is empty</p></div>`;return}let l="";if(i>=0&&i<e.length){let o=e[i];l+='<div class="wb-queue-label">Now Playing</div>',l+=`<div class="wb-queue-item wb-queue-current" data-qi="${i}">
|
|
26
26
|
<span class="wb-queue-num">${n.speaker}</span>
|
|
27
27
|
<div class="wb-queue-info">
|
|
28
28
|
<div class="wb-queue-item-title">${u(o.title)}</div>
|
|
29
29
|
<div class="wb-queue-item-artist">${u(o.artist)}</div>
|
|
30
30
|
</div>
|
|
31
|
-
</div>`}let
|
|
31
|
+
</div>`}let h=!1;for(let o=i+1;o<e.length;o++){h||(l+='<div class="wb-queue-label">Next Up</div>',h=!0);let c=e[o];l+=`<div class="wb-queue-item" data-qi="${o}">
|
|
32
32
|
<span class="wb-queue-num">${o-i}</span>
|
|
33
33
|
<div class="wb-queue-info">
|
|
34
|
-
<div class="wb-queue-item-title">${u(
|
|
35
|
-
<div class="wb-queue-item-artist">${u(
|
|
34
|
+
<div class="wb-queue-item-title">${u(c.title)}</div>
|
|
35
|
+
<div class="wb-queue-item-artist">${u(c.artist)}</div>
|
|
36
36
|
</div>
|
|
37
37
|
<button class="wb-queue-remove" data-qi="${o}" aria-label="Remove">${n.close}</button>
|
|
38
|
-
</div>`}if(i>0){l+='<div class="wb-queue-label">Previously Played</div>';for(let o=i-1;o>=0;o--){let
|
|
38
|
+
</div>`}if(i>0){l+='<div class="wb-queue-label">Previously Played</div>';for(let o=i-1;o>=0;o--){let c=e[o];l+=`<div class="wb-queue-item wb-queue-played" data-qi="${o}">
|
|
39
39
|
<span class="wb-queue-num">${o+1}</span>
|
|
40
40
|
<div class="wb-queue-info">
|
|
41
|
-
<div class="wb-queue-item-title">${u(
|
|
42
|
-
<div class="wb-queue-item-artist">${u(
|
|
41
|
+
<div class="wb-queue-item-title">${u(c.title)}</div>
|
|
42
|
+
<div class="wb-queue-item-artist">${u(c.artist)}</div>
|
|
43
43
|
</div>
|
|
44
|
-
</div>`}}s.innerHTML=l,s.querySelectorAll(".wb-queue-item[data-qi]").forEach(o=>{o.addEventListener("click",h=>{h.target.closest(".wb-queue-remove")||r.onSkipTo&&r.onSkipTo(parseInt(o.dataset.qi))})}),s.querySelectorAll(".wb-queue-remove").forEach(o=>{o.addEventListener("click",h=>{h.stopPropagation(),r.onRemove&&r.onRemove(parseInt(o.dataset.qi))})})}var x={persist:!0,autoResume:!0,continuous:!0,repeat:"off",showRepeat:!0,showQueue:!0,showPrevNext:!0,showVolume:!0,showMute:!0,showMeta:!0,showTime:!0,showTrackLink:!0,maxMeta:3,defaultArtwork:null,theme:null,waveformStyle:"mirror",waveformHeight:32,barWidth:2,barSpacing:0,waveformColor:null,progressColor:null,markerColor:"rgba(255, 255, 255, 0.25)",configPath:null,volume:1,storageKey:"waveform-bar",actions:null,onPlay:null,onPause:null,onTrackChange:null,onQueueChange:null,onVolumeChange:null,onFavorite:null,onCart:null},f=class{constructor(){this.config=null,this.player=null,this.queue=[],this.currentIndex=-1,this.isPlaying=!1,this.isInitialized=!1,this.queueOpen=!1,this.volume=1,this.isMuted=!1,this._volumeBeforeMute=1,this._lastPosition=0,this._favorites=new Set,this._cartItems=new Set,this._observer=null,this._activeMarkers=null,this._currentMarkerIndex=-1,this.repeat="off",this.barEl=null,this.queueEl=null,this.waveformContainer=null,this.volumePopupEl=null,this.titleEl=null,this.artistEl=null,this.metaEl=null,this.playBtnEl=null,this.repeatBtnEl=null,this.queueBtnEl=null,this.queueBodyEl=null,this.queueCountEl=null,this.volumeSliderEl=null,this.muteBtnEl=null,this.favBtnEl=null,this.cartBtnEl=null,this.timeCurrentEl=null,this.timeTotalEl=null}init(t={}){return this.isInitialized&&this.destroy(),this.config={...x,...t},this.volume=this.config.volume,typeof window.WaveformPlayer>"u"?(console.error("WaveformBar: WaveformPlayer is required."),this):(this._createBar(),this._createQueue(),this._initPlayer(),this._bindTriggers(),this._observeDOM(),this.config.persist&&(this._restoreVolume(),this._restoreFavorites()),this._seedFromAttributes(),this.config.persist&&this._restoreState(),this.isInitialized=!0,this._beforeUnloadHandler=()=>this._saveState(),window.addEventListener("beforeunload",this._beforeUnloadHandler),this)}destroy(){return this.player&&(this.player.destroy(),this.player=null),this.barEl&&(this.barEl.remove(),this.barEl=null),this.queueEl&&(this.queueEl.remove(),this.queueEl=null),this._observer&&(this._observer.disconnect(),this._observer=null),this._beforeUnloadHandler&&(window.removeEventListener("beforeunload",this._beforeUnloadHandler),this._beforeUnloadHandler=null),document.querySelectorAll("[data-wb-play],[data-wb-queue]").forEach(t=>delete t._wbBound),document.querySelectorAll(".wb-current,.wb-playing").forEach(t=>t.classList.remove("wb-current","wb-playing")),this.queue=[],this.currentIndex=-1,this.isPlaying=!1,this.queueOpen=!1,this.isInitialized=!1,this.config=null,this}_createBar(){this.barEl=document.createElement("div"),this.barEl.className="waveform-bar";let t=this.config.theme||this._detectTheme();t==="light"&&this.barEl.classList.add("wb-light"),this._resolvedTheme=t,this.barEl.id="waveform-bar",this.barEl.innerHTML=k(this.config),document.body.appendChild(this.barEl),this.titleEl=this.barEl.querySelector(".wb-title"),this.artistEl=this.barEl.querySelector(".wb-artist"),this.metaEl=this.barEl.querySelector(".wb-meta"),this.playBtnEl=this.barEl.querySelector(".wb-play"),this.waveformContainer=this.barEl.querySelector(".wb-waveform-container"),this.queueBtnEl=this.barEl.querySelector(".wb-queue-btn"),this.muteBtnEl=this.barEl.querySelector(".wb-mute"),this.volumeSliderEl=this.barEl.querySelector(".wb-volume-slider"),this.favBtnEl=this.barEl.querySelector(".wb-fav"),this.cartBtnEl=this.barEl.querySelector(".wb-cart"),this.timeCurrentEl=this.barEl.querySelector(".wb-time-current"),this.timeTotalEl=this.barEl.querySelector(".wb-time-total"),this.playBtnEl.addEventListener("click",()=>this.togglePlay());let e=this.barEl.querySelector(".wb-prev"),i=this.barEl.querySelector(".wb-next");e&&e.addEventListener("click",()=>this.previous()),i&&i.addEventListener("click",()=>this.next()),this.repeatBtnEl=this.barEl.querySelector(".wb-repeat"),this.repeatBtnEl&&(this.repeat=this.config.repeat||"off",this._updateRepeatButton(),this.repeatBtnEl.addEventListener("click",()=>this.cycleRepeat())),this.queueBtnEl&&this.queueBtnEl.addEventListener("click",()=>this.toggleQueuePanel()),this.volumePopupEl=this.barEl.querySelector(".wb-volume-popup");let r=this.barEl.querySelector(".wb-volume");if(this.muteBtnEl&&this.muteBtnEl.addEventListener("click",a=>{a.stopPropagation(),this.toggleMute()}),r&&this.volumePopupEl){let a;r.addEventListener("mouseenter",()=>{clearTimeout(a),this.openVolumePopup()}),r.addEventListener("mouseleave",()=>{a=setTimeout(()=>this.closeVolumePopup(),300)})}this.volumeSliderEl&&this.volumeSliderEl.addEventListener("input",a=>{a.stopPropagation(),this.setVolume(parseInt(a.target.value)/100)}),document.addEventListener("click",a=>{this.volumePopupEl?.classList.contains("wb-volume-open")&&!this.barEl.querySelector(".wb-volume")?.contains(a.target)&&this.closeVolumePopup()}),this.favBtnEl&&this.favBtnEl.addEventListener("click",()=>this.toggleFavorite()),this.cartBtnEl&&this.cartBtnEl.addEventListener("click",()=>this.addToCart()),this.config.showTrackLink&&this.barEl.querySelector(".wb-track").addEventListener("click",()=>{let a=this.getCurrentTrack();a&&a.link&&(window.location.href=a.link)})}_createQueue(){this.config.showQueue&&(this.queueEl=q(),this._resolvedTheme==="light"&&this.queueEl.classList.add("wb-light"),document.body.appendChild(this.queueEl),this.queueBodyEl=this.queueEl.querySelector(".wb-queue-body"),this.queueCountEl=this.queueEl.querySelector(".wb-queue-count"),this.queueEl.querySelector(".wb-queue-clear").addEventListener("click",()=>this.clearQueue()),document.addEventListener("click",t=>{this.queueOpen&&!this.queueEl.contains(t.target)&&!this.queueBtnEl.contains(t.target)&&this.closeQueuePanel()}))}_initPlayer(){let t={showControls:!1,showInfo:!1,waveformStyle:this.config.waveformStyle,height:this.config.waveformHeight,barWidth:this.config.barWidth,barSpacing:this.config.barSpacing,singlePlay:!1,onPlay:()=>{this.isPlaying=!0,this._updatePlayButton(),this._syncPageState();let e=this.getCurrentTrack();this._emit("play",{track:e}),this.config.onPlay&&this.config.onPlay(e)},onPause:()=>{this.isPlaying=!1,this._updatePlayButton(),this._syncPageState(),this._saveState();let e=this.getCurrentTrack();this._emit("pause",{track:e}),this.config.onPause&&this.config.onPause(e)},onEnd:()=>{if(this.isPlaying=!1,this._updatePlayButton(),this._syncPageState(),this.timeCurrentEl&&(this.timeCurrentEl.textContent="0:00"),this.repeat==="one"){this.player&&(this.player.seekTo(0),this.player.play().catch(()=>{}));return}this.config.continuous&&this.currentIndex<this.queue.length-1?(this.currentIndex++,this._loadCurrentTrack()):this.repeat==="all"&&this.queue.length>0&&(this.currentIndex=0,this._loadCurrentTrack())},onTimeUpdate:(e,i)=>{this._lastPosition=e,this.timeCurrentEl&&(this.timeCurrentEl.textContent=v(e)),this.timeTotalEl&&(this.timeTotalEl.textContent=v(i)),(!this._lastSaveTime||e-this._lastSaveTime>2)&&(this._lastSaveTime=e,this._saveState()),this._activeMarkers&&this._checkMarkerBoundary(e)},onLoad:null};this.config.waveformColor&&(t.waveformColor=this.config.waveformColor),this.config.progressColor&&(t.progressColor=this.config.progressColor),this.player=new window.WaveformPlayer(this.waveformContainer,t),this.player.setVolume(this.volume)}_bindTriggers(){document.querySelectorAll("[data-wb-play]").forEach(t=>{t._wbBound||(t._wbBound=!0,t.addEventListener("click",e=>{e.preventDefault();let i=p(t);i&&this.play(i)}))}),document.querySelectorAll("[data-wb-queue]").forEach(t=>{t._wbBound||(t._wbBound=!0,t.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation();let i=p(t);i&&this.addToQueue(i)}))})}_observeDOM(){typeof MutationObserver>"u"||(this._observer=new MutationObserver(()=>{this._bindTriggers(),this._syncPageState()}),this._observer.observe(document.body,{childList:!0,subtree:!0}))}play(t){let e=typeof t=="string"?{url:t,id:t,title:d(t)}:t;if(!e||!e.url)return this;let i=this.getCurrentTrack();if(i&&i.url===e.url)return this.togglePlay(),this;let r=this.queue.findIndex(a=>a.url===e.url);if(r>=0)this.queue[r]={...this.queue[r],...e},this.currentIndex=r;else{let a=this.currentIndex+1;this.queue.splice(a,0,e),this.currentIndex=a}return this._loadCurrentTrack(),this}addToQueue(t){let e=typeof t=="string"?{url:t,id:t,title:d(t)}:t;return!e||!e.url?this:this.queue.find(i=>i.url===e.url)?this:(this.queue.push(e),this._renderQueue(),this._saveState(),this._updateNavButtons(),this.currentIndex===-1&&(this.currentIndex=0,this._loadCurrentTrack()),this.config.onQueueChange&&this.config.onQueueChange(this.queue,this.currentIndex),this)}togglePlay(){return this.player?(this.isPlaying?this.player.pause():this.player.play(),this):this}pause(){return this.player&&this.isPlaying&&this.player.pause(),this}next(){return this.currentIndex<this.queue.length-1?(this.currentIndex++,this._loadCurrentTrack()):this.repeat==="all"&&this.queue.length>0&&(this.currentIndex=0,this._loadCurrentTrack()),this}previous(){return this.player&&this.player.audio&&this.player.audio.currentTime>3?(this.player.seekTo(0),this):(this.currentIndex>0?(this.currentIndex--,this._loadCurrentTrack()):this.repeat==="all"&&this.queue.length>0&&(this.currentIndex=this.queue.length-1,this._loadCurrentTrack()),this)}skipTo(t){return t<0||t>=this.queue.length?this:t===this.currentIndex?(this.togglePlay(),this):(this.currentIndex=t,this._loadCurrentTrack(),this)}seekToMarker(t){if(!this._activeMarkers||t<0||t>=this._activeMarkers.length)return this;let e=this._activeMarkers[t];return this.player&&(this.player.seekTo(e.time),this.isPlaying||this.togglePlay()),this}seekToMarkerByLabel(t){if(!this._activeMarkers)return this;let e=this._activeMarkers.findIndex(i=>(i.label||i.title||"").toLowerCase()===t.toLowerCase());return e>=0&&this.seekToMarker(e),this}setVolume(t){return this.volume=Math.max(0,Math.min(1,t)),this.isMuted=this.volume===0,this.player&&this.player.setVolume(this.volume),this._updateVolumeUI(),y(this.config.storageKey,this.volume,this.isMuted,this._volumeBeforeMute),this._emit("volumechange",{volume:this.volume}),this.config.onVolumeChange&&this.config.onVolumeChange(this.volume),this}getVolume(){return this.volume}toggleMute(){return this.isMuted?this.setVolume(this._volumeBeforeMute||1):(this._volumeBeforeMute=this.volume,this.isMuted=!0,this.player&&this.player.setVolume(0),this._updateVolumeUI()),this}toggleFavorite(){let t=this.getCurrentTrack();if(!t)return this;let e=t.id||t.url,i=this._favorites.has(e);return i?this._favorites.delete(e):this._favorites.add(e),this._updateFavoriteUI(),this._syncFavoriteAttributes(t.url,!i),m(this.config.storageKey,this._favorites),this._emit("favorite",{track:t,favorited:!i}),this.config.onFavorite&&this.config.onFavorite(t,!i),this.config.actions?.favorite&&b(this.config.actions.favorite,{action:"favorite",id:e,url:t.url,title:t.title,favorited:!i}),this}addToCart(){let t=this.getCurrentTrack();if(!t)return this;let e=t.id||t.url;return this._cartItems.add(e),this.cartBtnEl&&(this.cartBtnEl.classList.add("wb-action-done"),setTimeout(()=>this.cartBtnEl.classList.remove("wb-action-done"),1500)),this._syncCartAttributes(t.url,!0),this._emit("cart",{track:t}),this.config.onCart&&this.config.onCart(t),this.config.actions?.cart&&b(this.config.actions.cart,{action:"cart",id:e,url:t.url,title:t.title}),this}isFavorited(t){if(!t){let e=this.getCurrentTrack();t=e?e.id||e.url:null}return t?this._favorites.has(t):!1}isInCart(t){if(!t){let e=this.getCurrentTrack();t=e?e.id||e.url:null}return t?this._cartItems.has(t):!1}removeFromQueue(t){return t<0||t>=this.queue.length||t===this.currentIndex?this:(this.queue.splice(t,1),t<this.currentIndex&&this.currentIndex--,this._renderQueue(),this._saveState(),this._updateNavButtons(),this._emit("queuechange",{queue:this.queue,currentIndex:this.currentIndex}),this.config.onQueueChange&&this.config.onQueueChange(this.queue,this.currentIndex),this)}clearQueue(){let t=this.getCurrentTrack();return this.queue=t?[t]:[],this.currentIndex=t?0:-1,this._renderQueue(),this._saveState(),this._updateNavButtons(),this._emit("queuechange",{queue:this.queue,currentIndex:this.currentIndex}),this.config.onQueueChange&&this.config.onQueueChange(this.queue,this.currentIndex),this}getCurrentTrack(){return this.currentIndex>=0&&this.currentIndex<this.queue.length?this.queue[this.currentIndex]:null}getQueue(){return[...this.queue]}getCurrentIndex(){return this.currentIndex}isCurrentlyPlaying(t){let e=this.getCurrentTrack();return this.isPlaying&&e&&e.url===t}isCurrentTrack(t){let e=this.getCurrentTrack();return e&&e.url===t}getPlayer(){return this.player}_emit(t,e={}){this.barEl&&this.barEl.dispatchEvent(new CustomEvent("waveformbar:"+t,{bubbles:!0,detail:e}))}show(){return this.barEl&&this.barEl.classList.add("wb-active"),this}hide(){return this.barEl&&this.barEl.classList.remove("wb-active"),this.closeQueuePanel(),this.closeVolumePopup(),this}toggleQueuePanel(){return this.queueOpen?this.closeQueuePanel():this.openQueuePanel()}openQueuePanel(){if(!this.queueEl)return this;if(this.queueOpen=!0,this.closeVolumePopup(),this.queueBtnEl){let t=this.queueBtnEl.getBoundingClientRect();this.queueEl.style.right=window.innerWidth-t.right+"px"}return this.queueEl.classList.add("wb-queue-open"),this.queueBtnEl&&this.queueBtnEl.classList.add("wb-active"),this._renderQueue(),this}closeQueuePanel(){return this.queueEl?(this.queueOpen=!1,this.queueEl.classList.remove("wb-queue-open"),this.queueBtnEl&&this.queueBtnEl.classList.remove("wb-active"),this):this}toggleVolumePopup(){return this.volumePopupEl?.classList.contains("wb-volume-open")?this.closeVolumePopup():this.openVolumePopup(),this}openVolumePopup(){return this.volumePopupEl?(this.closeQueuePanel(),this.volumePopupEl.classList.add("wb-volume-open"),this.muteBtnEl&&this.muteBtnEl.classList.add("wb-active"),this):this}closeVolumePopup(){return this.volumePopupEl?(this.volumePopupEl.classList.remove("wb-volume-open"),this.muteBtnEl&&this.muteBtnEl.classList.remove("wb-active"),this):this}_loadCurrentTrack(){let t=this.getCurrentTrack();if(!t||!this.player)return;this.show(),this._updateTrackDisplay(t),this._updateFavoriteUI();let e={artwork:t.artwork,album:t.album};if(t.waveform&&(e.waveform=t.waveform),this.config.configPath&&t.url){let r=t.url.split("/").pop().split("?")[0].replace(/\.[^.]+$/,".json"),a=this.config.configPath.replace(/\/?$/,"/");e.config=a+r}if(t.markers&&t.markers.length){let i=this.config.markerColor;e.markers=t.markers.map(r=>({...r,color:r.color||i}))}else e.markers=[];this.player.loadTrack(t.url,t.title,t.artist,e),this._activeMarkers=t.markers&&t.markers.length?t.markers:null,this._currentMarkerIndex=-1,this.player&&this.player.setVolume(this.isMuted?0:this.volume),this._renderQueue(),this._syncPageState(),this._saveState(),this._updateNavButtons(),this._emit("trackchange",{track:t,index:this.currentIndex}),this.config.onTrackChange&&this.config.onTrackChange(t,this.currentIndex)}_updateTrackDisplay(t){this.titleEl&&this._setScrollText(this.titleEl,t.title||"Untitled"),this.artistEl&&this._setScrollText(this.artistEl,t.artist||"");let e=this.barEl.querySelector(".wb-artwork");if(e){let r=t.artwork||this.config.defaultArtwork;e.innerHTML=r?`<img src="${u(r)}" alt="${u(t.title)}" />`:n.music}this.metaEl&&this.config.showMeta&&this._renderMeta(t);let i=this.barEl.querySelector(".wb-track");i&&(i.style.cursor=t.link?"pointer":"default"),this.timeCurrentEl&&(this.timeCurrentEl.textContent="0:00"),this.timeTotalEl&&(this.timeTotalEl.textContent="0:00")}_setScrollText(t,e){t.classList.remove("wb-scrolling"),t.textContent=e,requestAnimationFrame(()=>{if(t.scrollWidth>t.clientWidth){let i=t.scrollWidth-t.clientWidth,r=Math.max(4,i/20);t.innerHTML=`<span class="wb-scroll-inner">${u(e)}</span>`,t.style.setProperty("--wb-scroll-distance",`-${i+48}px`),t.style.setProperty("--wb-scroll-duration",`${r}s`),t.classList.add("wb-scrolling")}})}_renderMeta(t){if(!this.metaEl)return;let e=[];if(t.bpm&&e.push({label:t.bpm+" BPM",type:"bpm"}),t.key&&e.push({label:t.key,type:"key"}),t.duration&&e.push({label:t.duration,type:"duration"}),t.meta)for(let[r,a]of Object.entries(t.meta))a&&e.length<this.config.maxMeta&&e.push({label:String(a),type:r});let i=e.slice(0,this.config.maxMeta);this.metaEl.style.display=i.length?"flex":"none",this.metaEl.innerHTML=i.map(r=>`<span class="wb-tag wb-tag-${u(r.type)}">${u(r.label)}</span>`).join("")}_updatePlayButton(){if(!this.playBtnEl)return;let t=this.playBtnEl.querySelector(".wb-icon-play"),e=this.playBtnEl.querySelector(".wb-icon-pause");t&&(t.style.display=this.isPlaying?"none":"block"),e&&(e.style.display=this.isPlaying?"block":"none"),this.playBtnEl.title=this.isPlaying?"Pause":"Play"}_updateNavButtons(){let t=this.barEl?.querySelector(".wb-prev"),e=this.barEl?.querySelector(".wb-next");this.repeat==="all"?(t&&t.classList.remove("wb-disabled"),e&&e.classList.remove("wb-disabled")):(t&&t.classList.toggle("wb-disabled",this.currentIndex<=0),e&&e.classList.toggle("wb-disabled",this.currentIndex>=this.queue.length-1))}cycleRepeat(){let t=["off","all","one"],e=t.indexOf(this.repeat);return this.repeat=t[(e+1)%t.length],this._updateRepeatButton(),this._updateNavButtons(),this._emit("repeatchange",{mode:this.repeat}),this}setRepeat(t){return["off","all","one"].includes(t)&&(this.repeat=t,this._updateRepeatButton(),this._updateNavButtons(),this._emit("repeatchange",{mode:this.repeat})),this}_updateRepeatButton(){if(!this.repeatBtnEl)return;let t={off:n.repeatOff,all:n.repeatAll,one:n.repeatOne},e={off:"Repeat: Off",all:"Repeat: All",one:"Repeat: One"};this.repeatBtnEl.innerHTML=t[this.repeat],this.repeatBtnEl.title=e[this.repeat],this.repeatBtnEl.classList.toggle("wb-repeat-active",this.repeat!=="off")}_checkMarkerBoundary(t){if(!this._activeMarkers)return;let e=-1;for(let l=this._activeMarkers.length-1;l>=0;l--)if(t>=this._activeMarkers[l].time){e=l;break}if(e===this._currentMarkerIndex||(this._currentMarkerIndex=e,e<0))return;let i=this._activeMarkers[e],r=this.getCurrentTrack();i.title&&this.titleEl&&this._setScrollText(this.titleEl,i.title),i.artist&&this.artistEl&&this._setScrollText(this.artistEl,i.artist);let a=this.waveformContainer?.querySelectorAll(".waveform-marker");if(a&&a.forEach((l,c)=>l.classList.toggle("wb-marker-active",c===e)),i.artwork){let l=this.barEl.querySelector(".wb-artwork");l&&(l.innerHTML=`<img src="${i.artwork}" alt="${i.title||""}" />`)}if(this.metaEl&&(i.bpm||i.key)){let l={...r||{},bpm:i.bpm||"",key:i.key||""};this._renderMeta(l)}this._emit("markerchange",{marker:i,index:e,track:r})}_updateVolumeUI(){this.volumeSliderEl&&(this.volumeSliderEl.value=this.isMuted?0:Math.round(this.volume*100)),this.muteBtnEl&&(this.isMuted||this.volume===0?(this.muteBtnEl.innerHTML=n.volMute,this.muteBtnEl.classList.add("wb-muted"),this.muteBtnEl.title="Unmute"):this.volume<.5?(this.muteBtnEl.innerHTML=n.volLow,this.muteBtnEl.classList.remove("wb-muted"),this.muteBtnEl.title="Mute"):(this.muteBtnEl.innerHTML=n.volHigh,this.muteBtnEl.classList.remove("wb-muted"),this.muteBtnEl.title="Mute"))}_detectTheme(){let t=document.documentElement,e=document.body,i=["dark","dark-mode","theme-dark"],r=["light","light-mode","theme-light"];for(let a of i)if(t.classList.contains(a)||e.classList.contains(a))return"dark";if(t.getAttribute("data-theme")==="dark"||e.getAttribute("data-theme")==="dark")return"dark";for(let a of r)if(t.classList.contains(a)||e.classList.contains(a))return"light";if(t.getAttribute("data-theme")==="light"||e.getAttribute("data-theme")==="light")return"light";try{let l=getComputedStyle(e).backgroundColor.match(/\d+/g);if(l&&l.length>=3){let c=(l[0]*299+l[1]*587+l[2]*114)/1e3;if(c>128)return"light";if(c<128)return"dark"}}catch{}return window.matchMedia?.("(prefers-color-scheme: light)").matches?"light":"dark"}_updateFavoriteUI(){if(!this.favBtnEl)return;let t=this.isFavorited();this.favBtnEl.innerHTML=t?n.heartFilled:n.heart,this.favBtnEl.classList.toggle("wb-fav-active",t)}_renderQueue(){B(this.queueBodyEl,this.queueCountEl,this.queue,this.currentIndex,{onSkipTo:t=>this.skipTo(t),onRemove:t=>this.removeFromQueue(t)})}_syncPageState(){let t=this.getCurrentTrack(),e=t?t.url:null;document.querySelectorAll("[data-wb-play]").forEach(i=>{let r=i.dataset.wbUrl||i.dataset.url,a=i.dataset.wbId||i.dataset.id||r,l=r&&r===e;i.classList.toggle("wb-current",l),i.classList.toggle("wb-playing",l&&this.isPlaying),i.classList.toggle("wb-favorited",this._favorites.has(a)),i.classList.toggle("wb-in-cart",this._cartItems.has(a))})}_seedFromAttributes(){let t=!1,e=!1;document.querySelectorAll("[data-wb-play]").forEach(i=>{let r=i.dataset.wbId||i.dataset.id||i.dataset.wbUrl||i.dataset.url;r&&(i.dataset.wbFavorited==="true"&&(this._favorites.add(r),t=!0),i.dataset.wbInCart==="true"&&(this._cartItems.add(r),e=!0))}),t&&m(this.config.storageKey,this._favorites)}_syncFavoriteAttributes(t,e){document.querySelectorAll("[data-wb-play]").forEach(i=>{(i.dataset.wbUrl||i.dataset.url)===t&&(i.dataset.wbFavorited=e?"true":"false",i.classList.toggle("wb-favorited",e))})}_syncCartAttributes(t,e){document.querySelectorAll("[data-wb-play]").forEach(i=>{(i.dataset.wbUrl||i.dataset.url)===t&&(i.dataset.wbInCart=e?"true":"false",i.classList.toggle("wb-in-cart",e))})}_saveState(){this.config.persist&&g(this.config.storageKey,{queue:this.queue,currentIndex:this.currentIndex,position:this._lastPosition||0,isPlaying:this.isPlaying})}_restoreState(){if(!this.config.persist)return;let t=w(this.config.storageKey);if(!t)return;this.queue=t.queue,this.currentIndex=t.currentIndex;let e=this.getCurrentTrack();if(e){if(this.show(),this._updateTrackDisplay(e),this._updateFavoriteUI(),this._updateNavButtons(),e.waveform&&(this.player.options.waveform=e.waveform),this.config.configPath&&e.url){let r=e.url.split("/").pop().split("?")[0].replace(/\.[^.]+$/,".json"),a=this.config.configPath.replace(/\/?$/,"/");this.player.options.config=a+r}if(this.player.options.title=e.title||"",this.player.options.subtitle=e.artist||"",e.markers&&e.markers.length){let i=this.config.markerColor;this.player.options.markers=e.markers.map(r=>({...r,color:r.color||i})),this._activeMarkers=e.markers}else this.player.options.markers=[],this._activeMarkers=null;this._currentMarkerIndex=-1,this.player.load(e.url).then(()=>{if(this.player&&this.player.setVolume(this.isMuted?0:this.volume),t.isPlaying&&this.config.autoResume)try{let i=this.player.play();i&&typeof i.catch=="function"&&i.catch(()=>{this.isPlaying=!1,this._updatePlayButton(),this._syncPageState()})}catch{this.isPlaying=!1,this._updatePlayButton(),this._syncPageState()}t.position>0&&setTimeout(()=>{this.player&&(this.player.seekTo(t.position),this._lastPosition=t.position)},100)}).catch(()=>{}),this._renderQueue(),this._syncPageState()}}_restoreVolume(){let t=E(this.config.storageKey);t&&(this.volume=t.volume,this.isMuted=t.muted,this._volumeBeforeMute=t.volumeBeforeMute,this.player&&this.player.setVolume(this.isMuted?0:this.volume),this._updateVolumeUI())}_restoreFavorites(){this._favorites=_(this.config.storageKey)}};var C=new f;typeof window<"u"&&(window.WaveformBar=C);var W=C;})();
|
|
44
|
+
</div>`}}s.innerHTML=l,s.querySelectorAll(".wb-queue-item[data-qi]").forEach(o=>{o.addEventListener("click",c=>{c.target.closest(".wb-queue-remove")||r.onSkipTo&&r.onSkipTo(parseInt(o.dataset.qi))})}),s.querySelectorAll(".wb-queue-remove").forEach(o=>{o.addEventListener("click",c=>{c.stopPropagation(),r.onRemove&&r.onRemove(parseInt(o.dataset.qi))})})}var B={persist:!0,autoResume:!0,continuous:!0,repeat:"off",showRepeat:!0,showQueue:!0,showPrevNext:!0,showVolume:!0,showMute:!0,showMeta:!0,showTime:!0,showTrackLink:!0,maxMeta:3,defaultArtwork:null,theme:null,waveformStyle:"mirror",waveformHeight:32,barWidth:2,barSpacing:0,waveformColor:null,progressColor:null,markerColor:"rgba(255, 255, 255, 0.25)",volume:1,storageKey:"waveform-bar",actions:null,onPlay:null,onPause:null,onTrackChange:null,onQueueChange:null,onVolumeChange:null,onFavorite:null,onCart:null},f=class{constructor(){this.config=null,this.player=null,this.queue=[],this.currentIndex=-1,this.isPlaying=!1,this.isInitialized=!1,this.queueOpen=!1,this.volume=1,this.isMuted=!1,this._volumeBeforeMute=1,this._lastPosition=0,this._favorites=new Set,this._cartItems=new Set,this._observer=null,this._activeMarkers=null,this._currentMarkerIndex=-1,this.repeat="off",this.barEl=null,this.queueEl=null,this.waveformContainer=null,this.volumePopupEl=null,this.titleEl=null,this.artistEl=null,this.metaEl=null,this.playBtnEl=null,this.repeatBtnEl=null,this.queueBtnEl=null,this.queueBodyEl=null,this.queueCountEl=null,this.volumeSliderEl=null,this.muteBtnEl=null,this.favBtnEl=null,this.cartBtnEl=null,this.timeCurrentEl=null,this.timeTotalEl=null}init(t={}){return this.isInitialized&&this.destroy(),this.config={...B,...t},this.volume=this.config.volume,typeof window.WaveformPlayer>"u"?(console.error("WaveformBar: WaveformPlayer is required."),this):(this._createBar(),this._createQueue(),this._initPlayer(),this._bindTriggers(),this._observeDOM(),this.config.persist&&(this._restoreVolume(),this._restoreFavorites()),this._seedFromAttributes(),this.config.persist&&this._restoreState(),this.isInitialized=!0,this._beforeUnloadHandler=()=>this._saveState(),window.addEventListener("beforeunload",this._beforeUnloadHandler),this)}destroy(){return this.player&&(this.player.destroy(),this.player=null),this.barEl&&(this.barEl.remove(),this.barEl=null),this.queueEl&&(this.queueEl.remove(),this.queueEl=null),this._observer&&(this._observer.disconnect(),this._observer=null),this._beforeUnloadHandler&&(window.removeEventListener("beforeunload",this._beforeUnloadHandler),this._beforeUnloadHandler=null),document.querySelectorAll("[data-wb-play],[data-wb-queue]").forEach(t=>delete t._wbBound),document.querySelectorAll(".wb-current,.wb-playing").forEach(t=>t.classList.remove("wb-current","wb-playing")),this.queue=[],this.currentIndex=-1,this.isPlaying=!1,this.queueOpen=!1,this.isInitialized=!1,this.config=null,this}_createBar(){this.barEl=document.createElement("div"),this.barEl.className="waveform-bar";let t=this.config.theme||this._detectTheme();t==="light"&&this.barEl.classList.add("wb-light"),this._resolvedTheme=t,this.barEl.id="waveform-bar",this.barEl.innerHTML=k(this.config),document.body.appendChild(this.barEl),this.titleEl=this.barEl.querySelector(".wb-title"),this.artistEl=this.barEl.querySelector(".wb-artist"),this.metaEl=this.barEl.querySelector(".wb-meta"),this.playBtnEl=this.barEl.querySelector(".wb-play"),this.waveformContainer=this.barEl.querySelector(".wb-waveform-container"),this.queueBtnEl=this.barEl.querySelector(".wb-queue-btn"),this.muteBtnEl=this.barEl.querySelector(".wb-mute"),this.volumeSliderEl=this.barEl.querySelector(".wb-volume-slider"),this.favBtnEl=this.barEl.querySelector(".wb-fav"),this.cartBtnEl=this.barEl.querySelector(".wb-cart"),this.timeCurrentEl=this.barEl.querySelector(".wb-time-current"),this.timeTotalEl=this.barEl.querySelector(".wb-time-total"),this.playBtnEl.addEventListener("click",()=>this.togglePlay());let e=this.barEl.querySelector(".wb-prev"),i=this.barEl.querySelector(".wb-next");e&&e.addEventListener("click",()=>this.previous()),i&&i.addEventListener("click",()=>this.next()),this.repeatBtnEl=this.barEl.querySelector(".wb-repeat"),this.repeatBtnEl&&(this.repeat=this.config.repeat||"off",this._updateRepeatButton(),this.repeatBtnEl.addEventListener("click",()=>this.cycleRepeat())),this.queueBtnEl&&this.queueBtnEl.addEventListener("click",()=>this.toggleQueuePanel()),this.volumePopupEl=this.barEl.querySelector(".wb-volume-popup");let r=this.barEl.querySelector(".wb-volume");if(this.muteBtnEl&&this.muteBtnEl.addEventListener("click",a=>{a.stopPropagation(),this.toggleMute()}),r&&this.volumePopupEl){let a;r.addEventListener("mouseenter",()=>{clearTimeout(a),this.openVolumePopup()}),r.addEventListener("mouseleave",()=>{a=setTimeout(()=>this.closeVolumePopup(),300)})}this.volumeSliderEl&&this.volumeSliderEl.addEventListener("input",a=>{a.stopPropagation(),this.setVolume(parseInt(a.target.value)/100)}),document.addEventListener("click",a=>{this.volumePopupEl?.classList.contains("wb-volume-open")&&!this.barEl.querySelector(".wb-volume")?.contains(a.target)&&this.closeVolumePopup()}),this.favBtnEl&&this.favBtnEl.addEventListener("click",()=>this.toggleFavorite()),this.cartBtnEl&&this.cartBtnEl.addEventListener("click",()=>this.addToCart()),this.config.showTrackLink&&this.barEl.querySelector(".wb-track").addEventListener("click",()=>{let a=this.getCurrentTrack();a&&a.link&&(window.location.href=a.link)})}_createQueue(){this.config.showQueue&&(this.queueEl=q(),this._resolvedTheme==="light"&&this.queueEl.classList.add("wb-light"),document.body.appendChild(this.queueEl),this.queueBodyEl=this.queueEl.querySelector(".wb-queue-body"),this.queueCountEl=this.queueEl.querySelector(".wb-queue-count"),this.queueEl.querySelector(".wb-queue-clear").addEventListener("click",()=>this.clearQueue()),document.addEventListener("click",t=>{this.queueOpen&&!this.queueEl.contains(t.target)&&!this.queueBtnEl.contains(t.target)&&this.closeQueuePanel()}))}_initPlayer(){let t={showControls:!1,showInfo:!1,waveformStyle:this.config.waveformStyle,height:this.config.waveformHeight,barWidth:this.config.barWidth,barSpacing:this.config.barSpacing,singlePlay:!1,onPlay:()=>{this.isPlaying=!0,this._updatePlayButton(),this._syncPageState(),this._pumpExternalPlayState(!0);let e=this.getCurrentTrack();this._emit("play",{track:e}),this.config.onPlay&&this.config.onPlay(e)},onPause:()=>{this.isPlaying=!1,this._updatePlayButton(),this._syncPageState(),this._pumpExternalPlayState(!1),this._saveState();let e=this.getCurrentTrack();this._emit("pause",{track:e}),this.config.onPause&&this.config.onPause(e)},onEnd:()=>{if(this.isPlaying=!1,this._updatePlayButton(),this._syncPageState(),this._pumpExternalPlayState(!1),this.timeCurrentEl&&(this.timeCurrentEl.textContent="0:00"),this.repeat==="one"){this.player&&(this.player.seekTo(0),this.player.play().catch(()=>{}));return}this.config.continuous&&this.currentIndex<this.queue.length-1?(this.currentIndex++,this._loadCurrentTrack()):this.repeat==="all"&&this.queue.length>0&&(this.currentIndex=0,this._loadCurrentTrack())},onTimeUpdate:(e,i)=>{this._lastPosition=e,this.timeCurrentEl&&(this.timeCurrentEl.textContent=v(e)),this.timeTotalEl&&(this.timeTotalEl.textContent=v(i)),this._pumpExternalProgress(e,i),(!this._lastSaveTime||e-this._lastSaveTime>2)&&(this._lastSaveTime=e,this._saveState()),this._activeMarkers&&this._checkMarkerBoundary(e)},onLoad:null};this.config.waveformColor&&(t.waveformColor=this.config.waveformColor),this.config.progressColor&&(t.progressColor=this.config.progressColor),this.player=new window.WaveformPlayer(this.waveformContainer,t),this.player.setVolume(this.volume)}_bindTriggers(){document.querySelectorAll("[data-wb-play]").forEach(t=>{t._wbBound||(t._wbBound=!0,t.addEventListener("click",e=>{e.preventDefault();let i=p(t);i&&this.play(i)}))}),document.querySelectorAll("[data-wb-queue]").forEach(t=>{t._wbBound||(t._wbBound=!0,t.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation();let i=p(t);i&&this.addToQueue(i)}))}),this._attachExternalPlayers()}_attachExternalPlayers(){this._externalListenersBound||(this._externalListenersBound=!0,document.addEventListener("waveformplayer:request-play",e=>{let i=e.detail;!i||!i.url||(e.preventDefault(),this.play(i))}),document.addEventListener("waveformplayer:request-pause",e=>{let i=e.detail;if(!i||!i.url)return;let r=this.getCurrentTrack();r&&r.url===i.url&&(e.preventDefault(),this.isPlaying&&this.togglePlay())}),document.addEventListener("waveformplayer:request-seek",e=>{let i=e.detail;if(!i||!i.url||typeof i.percent!="number")return;let r=this.getCurrentTrack();r&&r.url===i.url&&this.player&&this.player.audio&&(e.preventDefault(),this.player.seekToPercent(i.percent))})),this._externalPlayers=new Map;let t=window.WaveformPlayer;!t||!t.instances||document.querySelectorAll('[data-waveform-player][data-audio-mode="external"]').forEach(e=>{let i=t.instances.get(e.id);if(!i||!i.options||!i.options.url)return;let r=i.options.url;this._externalPlayers.has(r)||this._externalPlayers.set(r,new Set),this._externalPlayers.get(r).add(i)})}_pumpExternalPlayState(t){if(!this._externalPlayers||this._externalPlayers.size===0)return;let e=this.getCurrentTrack(),i=e?e.url:null;this._externalPlayers.forEach((r,a)=>{let l=a===i;r.forEach(h=>{typeof h.setPlayingState=="function"&&h.setPlayingState(l&&t)})})}_pumpExternalProgress(t,e){if(!this._externalPlayers||this._externalPlayers.size===0)return;let i=this.getCurrentTrack();if(!i)return;let r=this._externalPlayers.get(i.url);r&&r.forEach(a=>{typeof a.setProgress=="function"&&a.setProgress(t,e)})}_observeDOM(){typeof MutationObserver>"u"||(this._observer=new MutationObserver(()=>{this._bindTriggers(),this._syncPageState()}),this._observer.observe(document.body,{childList:!0,subtree:!0}))}play(t){let e=typeof t=="string"?{url:t,id:t,title:d(t)}:t;if(!e||!e.url)return this;let i=this.getCurrentTrack();if(i&&i.url===e.url)return this.togglePlay(),this;let r=this.queue.findIndex(a=>a.url===e.url);if(r>=0)this.queue[r]={...this.queue[r],...e},this.currentIndex=r;else{let a=this.currentIndex+1;this.queue.splice(a,0,e),this.currentIndex=a}return this._loadCurrentTrack(),this}addToQueue(t){let e=typeof t=="string"?{url:t,id:t,title:d(t)}:t;return!e||!e.url?this:this.queue.find(i=>i.url===e.url)?this:(this.queue.push(e),this._renderQueue(),this._saveState(),this._updateNavButtons(),this.currentIndex===-1&&(this.currentIndex=0,this._loadCurrentTrack()),this.config.onQueueChange&&this.config.onQueueChange(this.queue,this.currentIndex),this)}togglePlay(){return this.player?(this.isPlaying?this.player.pause():this.player.play(),this):this}pause(){return this.player&&this.isPlaying&&this.player.pause(),this}next(){return this.currentIndex<this.queue.length-1?(this.currentIndex++,this._loadCurrentTrack()):this.repeat==="all"&&this.queue.length>0&&(this.currentIndex=0,this._loadCurrentTrack()),this}previous(){return this.player&&this.player.audio&&this.player.audio.currentTime>3?(this.player.seekTo(0),this):(this.currentIndex>0?(this.currentIndex--,this._loadCurrentTrack()):this.repeat==="all"&&this.queue.length>0&&(this.currentIndex=this.queue.length-1,this._loadCurrentTrack()),this)}skipTo(t){return t<0||t>=this.queue.length?this:t===this.currentIndex?(this.togglePlay(),this):(this.currentIndex=t,this._loadCurrentTrack(),this)}seekToMarker(t){if(!this._activeMarkers||t<0||t>=this._activeMarkers.length)return this;let e=this._activeMarkers[t];return this.player&&(this.player.seekTo(e.time),this.isPlaying||this.togglePlay()),this}seekToMarkerByLabel(t){if(!this._activeMarkers)return this;let e=this._activeMarkers.findIndex(i=>(i.label||i.title||"").toLowerCase()===t.toLowerCase());return e>=0&&this.seekToMarker(e),this}setVolume(t){return this.volume=Math.max(0,Math.min(1,t)),this.isMuted=this.volume===0,this.player&&this.player.setVolume(this.volume),this._updateVolumeUI(),y(this.config.storageKey,this.volume,this.isMuted,this._volumeBeforeMute),this._emit("volumechange",{volume:this.volume}),this.config.onVolumeChange&&this.config.onVolumeChange(this.volume),this}getVolume(){return this.volume}toggleMute(){return this.isMuted?this.setVolume(this._volumeBeforeMute||1):(this._volumeBeforeMute=this.volume,this.isMuted=!0,this.player&&this.player.setVolume(0),this._updateVolumeUI()),this}toggleFavorite(){let t=this.getCurrentTrack();if(!t)return this;let e=t.id||t.url,i=this._favorites.has(e);return i?this._favorites.delete(e):this._favorites.add(e),this._updateFavoriteUI(),this._syncFavoriteAttributes(t.url,!i),m(this.config.storageKey,this._favorites),this._emit("favorite",{track:t,favorited:!i}),this.config.onFavorite&&this.config.onFavorite(t,!i),this.config.actions?.favorite&&b(this.config.actions.favorite,{action:"favorite",id:e,url:t.url,title:t.title,favorited:!i}),this}addToCart(){let t=this.getCurrentTrack();if(!t)return this;let e=t.id||t.url;return this._cartItems.add(e),this.cartBtnEl&&(this.cartBtnEl.classList.add("wb-action-done"),setTimeout(()=>this.cartBtnEl.classList.remove("wb-action-done"),1500)),this._syncCartAttributes(t.url,!0),this._emit("cart",{track:t}),this.config.onCart&&this.config.onCart(t),this.config.actions?.cart&&b(this.config.actions.cart,{action:"cart",id:e,url:t.url,title:t.title}),this}isFavorited(t){if(!t){let e=this.getCurrentTrack();t=e?e.id||e.url:null}return t?this._favorites.has(t):!1}isInCart(t){if(!t){let e=this.getCurrentTrack();t=e?e.id||e.url:null}return t?this._cartItems.has(t):!1}removeFromQueue(t){return t<0||t>=this.queue.length||t===this.currentIndex?this:(this.queue.splice(t,1),t<this.currentIndex&&this.currentIndex--,this._renderQueue(),this._saveState(),this._updateNavButtons(),this._emit("queuechange",{queue:this.queue,currentIndex:this.currentIndex}),this.config.onQueueChange&&this.config.onQueueChange(this.queue,this.currentIndex),this)}clearQueue(){let t=this.getCurrentTrack();return this.queue=t?[t]:[],this.currentIndex=t?0:-1,this._renderQueue(),this._saveState(),this._updateNavButtons(),this._emit("queuechange",{queue:this.queue,currentIndex:this.currentIndex}),this.config.onQueueChange&&this.config.onQueueChange(this.queue,this.currentIndex),this}getCurrentTrack(){return this.currentIndex>=0&&this.currentIndex<this.queue.length?this.queue[this.currentIndex]:null}getQueue(){return[...this.queue]}getCurrentIndex(){return this.currentIndex}isCurrentlyPlaying(t){let e=this.getCurrentTrack();return this.isPlaying&&e&&e.url===t}isCurrentTrack(t){let e=this.getCurrentTrack();return e&&e.url===t}getPlayer(){return this.player}_emit(t,e={}){this.barEl&&this.barEl.dispatchEvent(new CustomEvent("waveformbar:"+t,{bubbles:!0,detail:e}))}show(){return this.barEl&&this.barEl.classList.add("wb-active"),this}hide(){return this.barEl&&this.barEl.classList.remove("wb-active"),this.closeQueuePanel(),this.closeVolumePopup(),this}toggleQueuePanel(){return this.queueOpen?this.closeQueuePanel():this.openQueuePanel()}openQueuePanel(){if(!this.queueEl)return this;if(this.queueOpen=!0,this.closeVolumePopup(),this.queueBtnEl){let t=this.queueBtnEl.getBoundingClientRect();this.queueEl.style.right=window.innerWidth-t.right+"px"}return this.queueEl.classList.add("wb-queue-open"),this.queueBtnEl&&this.queueBtnEl.classList.add("wb-active"),this._renderQueue(),this}closeQueuePanel(){return this.queueEl?(this.queueOpen=!1,this.queueEl.classList.remove("wb-queue-open"),this.queueBtnEl&&this.queueBtnEl.classList.remove("wb-active"),this):this}toggleVolumePopup(){return this.volumePopupEl?.classList.contains("wb-volume-open")?this.closeVolumePopup():this.openVolumePopup(),this}openVolumePopup(){return this.volumePopupEl?(this.closeQueuePanel(),this.volumePopupEl.classList.add("wb-volume-open"),this.muteBtnEl&&this.muteBtnEl.classList.add("wb-active"),this):this}closeVolumePopup(){return this.volumePopupEl?(this.volumePopupEl.classList.remove("wb-volume-open"),this.muteBtnEl&&this.muteBtnEl.classList.remove("wb-active"),this):this}_loadCurrentTrack(){let t=this.getCurrentTrack();if(!t||!this.player)return;this._pumpExternalPlayState(!1),this.show(),this._updateTrackDisplay(t),this._updateFavoriteUI();let e={artwork:t.artwork,album:t.album};if(t.waveform&&(e.waveform=t.waveform),t.markers&&t.markers.length){let i=this.config.markerColor;e.markers=t.markers.map(r=>({...r,color:r.color||i}))}else e.markers=[];this.player.loadTrack(t.url,t.title,t.artist,e),this._activeMarkers=t.markers&&t.markers.length?t.markers:null,this._currentMarkerIndex=-1,this.player&&this.player.setVolume(this.isMuted?0:this.volume),this._renderQueue(),this._syncPageState(),this._saveState(),this._updateNavButtons(),this._emit("trackchange",{track:t,index:this.currentIndex}),this.config.onTrackChange&&this.config.onTrackChange(t,this.currentIndex)}_updateTrackDisplay(t){this.titleEl&&this._setScrollText(this.titleEl,t.title||"Untitled"),this.artistEl&&this._setScrollText(this.artistEl,t.artist||"");let e=this.barEl.querySelector(".wb-artwork");if(e){let r=t.artwork||this.config.defaultArtwork;e.innerHTML=r?`<img src="${u(r)}" alt="${u(t.title)}" />`:n.music}this.metaEl&&this.config.showMeta&&this._renderMeta(t);let i=this.barEl.querySelector(".wb-track");i&&(i.style.cursor=t.link?"pointer":"default"),this.timeCurrentEl&&(this.timeCurrentEl.textContent="0:00"),this.timeTotalEl&&(this.timeTotalEl.textContent="0:00")}_setScrollText(t,e){t.classList.remove("wb-scrolling"),t.textContent=e,requestAnimationFrame(()=>{if(t.scrollWidth>t.clientWidth){let i=t.scrollWidth-t.clientWidth,r=Math.max(4,i/20);t.innerHTML=`<span class="wb-scroll-inner">${u(e)}</span>`,t.style.setProperty("--wb-scroll-distance",`-${i+48}px`),t.style.setProperty("--wb-scroll-duration",`${r}s`),t.classList.add("wb-scrolling")}})}_renderMeta(t){if(!this.metaEl)return;let e=[];if(t.bpm&&e.push({label:t.bpm+" BPM",type:"bpm"}),t.key&&e.push({label:t.key,type:"key"}),t.duration&&e.push({label:t.duration,type:"duration"}),t.meta)for(let[r,a]of Object.entries(t.meta))a&&e.length<this.config.maxMeta&&e.push({label:String(a),type:r});let i=e.slice(0,this.config.maxMeta);this.metaEl.style.display=i.length?"flex":"none",this.metaEl.innerHTML=i.map(r=>`<span class="wb-tag wb-tag-${u(r.type)}">${u(r.label)}</span>`).join("")}_updatePlayButton(){if(!this.playBtnEl)return;let t=this.playBtnEl.querySelector(".wb-icon-play"),e=this.playBtnEl.querySelector(".wb-icon-pause");t&&(t.style.display=this.isPlaying?"none":"block"),e&&(e.style.display=this.isPlaying?"block":"none"),this.playBtnEl.title=this.isPlaying?"Pause":"Play"}_updateNavButtons(){let t=this.barEl?.querySelector(".wb-prev"),e=this.barEl?.querySelector(".wb-next");this.repeat==="all"?(t&&t.classList.remove("wb-disabled"),e&&e.classList.remove("wb-disabled")):(t&&t.classList.toggle("wb-disabled",this.currentIndex<=0),e&&e.classList.toggle("wb-disabled",this.currentIndex>=this.queue.length-1))}cycleRepeat(){let t=["off","all","one"],e=t.indexOf(this.repeat);return this.repeat=t[(e+1)%t.length],this._updateRepeatButton(),this._updateNavButtons(),this._emit("repeatchange",{mode:this.repeat}),this}setRepeat(t){return["off","all","one"].includes(t)&&(this.repeat=t,this._updateRepeatButton(),this._updateNavButtons(),this._emit("repeatchange",{mode:this.repeat})),this}_updateRepeatButton(){if(!this.repeatBtnEl)return;let t={off:n.repeatOff,all:n.repeatAll,one:n.repeatOne},e={off:"Repeat: Off",all:"Repeat: All",one:"Repeat: One"};this.repeatBtnEl.innerHTML=t[this.repeat],this.repeatBtnEl.title=e[this.repeat],this.repeatBtnEl.classList.toggle("wb-repeat-active",this.repeat!=="off")}_checkMarkerBoundary(t){if(!this._activeMarkers)return;let e=-1;for(let l=this._activeMarkers.length-1;l>=0;l--)if(t>=this._activeMarkers[l].time){e=l;break}if(e===this._currentMarkerIndex||(this._currentMarkerIndex=e,e<0))return;let i=this._activeMarkers[e],r=this.getCurrentTrack();i.title&&this.titleEl&&this._setScrollText(this.titleEl,i.title),i.artist&&this.artistEl&&this._setScrollText(this.artistEl,i.artist);let a=this.waveformContainer?.querySelectorAll(".waveform-marker");if(a&&a.forEach((l,h)=>l.classList.toggle("wb-marker-active",h===e)),i.artwork){let l=this.barEl.querySelector(".wb-artwork");l&&(l.innerHTML=`<img src="${i.artwork}" alt="${i.title||""}" />`)}if(this.metaEl&&(i.bpm||i.key)){let l={...r||{},bpm:i.bpm||"",key:i.key||""};this._renderMeta(l)}this._emit("markerchange",{marker:i,index:e,track:r})}_updateVolumeUI(){this.volumeSliderEl&&(this.volumeSliderEl.value=this.isMuted?0:Math.round(this.volume*100)),this.muteBtnEl&&(this.isMuted||this.volume===0?(this.muteBtnEl.innerHTML=n.volMute,this.muteBtnEl.classList.add("wb-muted"),this.muteBtnEl.title="Unmute"):this.volume<.5?(this.muteBtnEl.innerHTML=n.volLow,this.muteBtnEl.classList.remove("wb-muted"),this.muteBtnEl.title="Mute"):(this.muteBtnEl.innerHTML=n.volHigh,this.muteBtnEl.classList.remove("wb-muted"),this.muteBtnEl.title="Mute"))}_detectTheme(){let t=document.documentElement,e=document.body,i=["dark","dark-mode","theme-dark"],r=["light","light-mode","theme-light"];for(let a of i)if(t.classList.contains(a)||e.classList.contains(a))return"dark";if(t.getAttribute("data-theme")==="dark"||e.getAttribute("data-theme")==="dark")return"dark";for(let a of r)if(t.classList.contains(a)||e.classList.contains(a))return"light";if(t.getAttribute("data-theme")==="light"||e.getAttribute("data-theme")==="light")return"light";try{let l=getComputedStyle(e).backgroundColor.match(/\d+/g);if(l&&l.length>=3){let h=(l[0]*299+l[1]*587+l[2]*114)/1e3;if(h>128)return"light";if(h<128)return"dark"}}catch{}return window.matchMedia?.("(prefers-color-scheme: light)").matches?"light":"dark"}_updateFavoriteUI(){if(!this.favBtnEl)return;let t=this.isFavorited();this.favBtnEl.innerHTML=t?n.heartFilled:n.heart,this.favBtnEl.classList.toggle("wb-fav-active",t)}_renderQueue(){x(this.queueBodyEl,this.queueCountEl,this.queue,this.currentIndex,{onSkipTo:t=>this.skipTo(t),onRemove:t=>this.removeFromQueue(t)})}_syncPageState(){let t=this.getCurrentTrack(),e=t?t.url:null;document.querySelectorAll("[data-wb-play]").forEach(i=>{let r=i.dataset.wbUrl||i.dataset.url,a=i.dataset.wbId||i.dataset.id||r,l=r&&r===e;i.classList.toggle("wb-current",l),i.classList.toggle("wb-playing",l&&this.isPlaying),i.classList.toggle("wb-favorited",this._favorites.has(a)),i.classList.toggle("wb-in-cart",this._cartItems.has(a))})}_seedFromAttributes(){let t=!1,e=!1;document.querySelectorAll("[data-wb-play]").forEach(i=>{let r=i.dataset.wbId||i.dataset.id||i.dataset.wbUrl||i.dataset.url;r&&(i.dataset.wbFavorited==="true"&&(this._favorites.add(r),t=!0),i.dataset.wbInCart==="true"&&(this._cartItems.add(r),e=!0))}),t&&m(this.config.storageKey,this._favorites)}_syncFavoriteAttributes(t,e){document.querySelectorAll("[data-wb-play]").forEach(i=>{(i.dataset.wbUrl||i.dataset.url)===t&&(i.dataset.wbFavorited=e?"true":"false",i.classList.toggle("wb-favorited",e))})}_syncCartAttributes(t,e){document.querySelectorAll("[data-wb-play]").forEach(i=>{(i.dataset.wbUrl||i.dataset.url)===t&&(i.dataset.wbInCart=e?"true":"false",i.classList.toggle("wb-in-cart",e))})}_saveState(){this.config.persist&&g(this.config.storageKey,{queue:this.queue,currentIndex:this.currentIndex,position:this._lastPosition||0,isPlaying:this.isPlaying})}_restoreState(){if(!this.config.persist)return;let t=w(this.config.storageKey);if(!t)return;this.queue=t.queue,this.currentIndex=t.currentIndex;let e=this.getCurrentTrack();if(e){if(this.show(),this._updateTrackDisplay(e),this._updateFavoriteUI(),this._updateNavButtons(),e.waveform&&(this.player.options.waveform=e.waveform),this.player.options.title=e.title||"",this.player.options.subtitle=e.artist||"",e.markers&&e.markers.length){let i=this.config.markerColor;this.player.options.markers=e.markers.map(r=>({...r,color:r.color||i})),this._activeMarkers=e.markers}else this.player.options.markers=[],this._activeMarkers=null;this._currentMarkerIndex=-1,this.player.load(e.url).then(()=>{if(this.player&&this.player.setVolume(this.isMuted?0:this.volume),t.isPlaying&&this.config.autoResume)try{let i=this.player.play();i&&typeof i.catch=="function"&&i.catch(()=>{this.isPlaying=!1,this._updatePlayButton(),this._syncPageState()})}catch{this.isPlaying=!1,this._updatePlayButton(),this._syncPageState()}t.position>0&&setTimeout(()=>{this.player&&(this.player.seekTo(t.position),this._lastPosition=t.position)},100)}).catch(()=>{}),this._renderQueue(),this._syncPageState()}}_restoreVolume(){let t=E(this.config.storageKey);t&&(this.volume=t.volume,this.isMuted=t.muted,this._volumeBeforeMute=t.volumeBeforeMute,this.player&&this.player.setVolume(this.isMuted?0:this.volume),this._updateVolumeUI())}_restoreFavorites(){this._favorites=_(this.config.storageKey)}};var P=new f;typeof window<"u"&&(window.WaveformBar=P);var W=P;})();
|
|
45
45
|
/**
|
|
46
46
|
* WaveformBar v1.0.0
|
|
47
47
|
* Persistent bottom audio player bar for WaveformPlayer
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arraypress/waveform-bar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Persistent bottom audio player bar for WaveformPlayer - queue management, page persistence, and seamless playback.",
|
|
5
5
|
"main": "dist/waveform-bar.js",
|
|
6
6
|
"module": "dist/waveform-bar.esm.js",
|
|
@@ -5,12 +5,21 @@
|
|
|
5
5
|
* MIT License
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
*
|
|
8
|
+
* <span class="wbi wbi-play"></span>
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
.wbi
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
.wbi {
|
|
12
|
+
display: inline-block;
|
|
13
|
+
width: 1em;
|
|
14
|
+
height: 1em;
|
|
15
|
+
background-color: currentColor;
|
|
16
|
+
-webkit-mask-size: contain;
|
|
17
|
+
mask-size: contain;
|
|
18
|
+
-webkit-mask-repeat: no-repeat;
|
|
19
|
+
mask-repeat: no-repeat;
|
|
20
|
+
-webkit-mask-position: center;
|
|
21
|
+
mask-position: center;
|
|
22
|
+
vertical-align: -0.125em;
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
.wbi-sm {
|
|
@@ -136,4 +145,4 @@
|
|
|
136
145
|
.wbi-share {
|
|
137
146
|
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z'/></svg>");
|
|
138
147
|
mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z'/></svg>");
|
|
139
|
-
}
|
|
148
|
+
}
|