@arraypress/waveform-player 1.12.1 → 1.13.1

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.
@@ -813,9 +813,12 @@ var WaveformPlayer = class _WaveformPlayer {
813
813
  if (userOptions.src && !userOptions.url) userOptions.url = userOptions.src;
814
814
  this.options = mergeOptions(DEFAULT_OPTIONS, dataOptions, userOptions);
815
815
  const preset = getColorPreset(this.options.colorPreset);
816
+ this._autoTheme = this.options.colorPreset == null || !COLOR_PRESETS[this.options.colorPreset];
817
+ this._presetKeys = [];
816
818
  for (const [key, value] of Object.entries(preset)) {
817
819
  if (this.options[key] === null || this.options[key] === void 0) {
818
820
  this.options[key] = value;
821
+ this._presetKeys.push(key);
819
822
  }
820
823
  }
821
824
  const styleDefaults = STYLE_DEFAULTS[this.options.waveformStyle];
@@ -840,6 +843,7 @@ var WaveformPlayer = class _WaveformPlayer {
840
843
  this._ac = new AbortController();
841
844
  this.id = this.container.id || generateId(this.options.url);
842
845
  _WaveformPlayer.instances.set(this.id, this);
846
+ _WaveformPlayer._watchTheme();
843
847
  this.init();
844
848
  setTimeout(() => {
845
849
  this._emit("waveformplayer:ready", { player: this, url: this.options.url });
@@ -1834,6 +1838,73 @@ var WaveformPlayer = class _WaveformPlayer {
1834
1838
  this.bpmEl.style.display = "inline-flex";
1835
1839
  }
1836
1840
  }
1841
+ /**
1842
+ * Re-detect the page theme and re-apply auto colours + redraw, so an
1843
+ * auto-themed player adapts to a runtime light/dark switch (not just the
1844
+ * value present on load). No-op when the player uses an explicit
1845
+ * `colorPreset` or hand-set colours. Driven by the shared theme watcher.
1846
+ * @public
1847
+ */
1848
+ refreshTheme() {
1849
+ if (!this._autoTheme || !this._presetKeys || !this._presetKeys.length) return;
1850
+ const preset = getColorPreset(this.options.colorPreset);
1851
+ let changed = false;
1852
+ for (const key of this._presetKeys) {
1853
+ if (this.options[key] !== preset[key]) {
1854
+ this.options[key] = preset[key];
1855
+ changed = true;
1856
+ }
1857
+ }
1858
+ if (changed) this._applyThemeColors();
1859
+ }
1860
+ /**
1861
+ * Push the current resolved colours onto the live DOM (button border/icon,
1862
+ * title, subtitle, time, BPM) and redraw the waveform.
1863
+ * @private
1864
+ */
1865
+ _applyThemeColors() {
1866
+ const o = this.options;
1867
+ if (this.playBtn) {
1868
+ this.playBtn.style.borderColor = o.buttonColor;
1869
+ this.playBtn.style.color = o.buttonColor;
1870
+ }
1871
+ if (this.titleEl) this.titleEl.style.color = o.textColor;
1872
+ if (this.subtitleEl) this.subtitleEl.style.color = o.textSecondaryColor;
1873
+ this.container.querySelectorAll(".waveform-time, .waveform-bpm").forEach((el) => {
1874
+ el.style.color = o.textSecondaryColor;
1875
+ });
1876
+ if (this.canvas) this.drawWaveform();
1877
+ }
1878
+ /**
1879
+ * Lazily install ONE shared watcher that re-detects the theme for every
1880
+ * auto-themed instance when the document theme changes — a class/attribute
1881
+ * flip on `<html>`/`<body>` (Tailwind `dark`, `data-theme`,
1882
+ * `data-color-scheme`) or an OS `prefers-color-scheme` change. Event-driven
1883
+ * (MutationObserver + matchMedia), never a timer.
1884
+ * @private
1885
+ */
1886
+ static _watchTheme() {
1887
+ if (_WaveformPlayer._themeWatch || typeof document === "undefined") return;
1888
+ const refresh = () => requestAnimationFrame(() => {
1889
+ _WaveformPlayer.instances.forEach((p) => {
1890
+ try {
1891
+ p.refreshTheme();
1892
+ } catch (e) {
1893
+ }
1894
+ });
1895
+ });
1896
+ const opts = { attributes: true, attributeFilter: ["class", "data-theme", "data-color-scheme", "style"] };
1897
+ const obs = new MutationObserver(refresh);
1898
+ obs.observe(document.documentElement, opts);
1899
+ if (document.body) obs.observe(document.body, opts);
1900
+ let mq = null;
1901
+ try {
1902
+ mq = window.matchMedia("(prefers-color-scheme: dark)");
1903
+ mq.addEventListener("change", refresh);
1904
+ } catch (e) {
1905
+ }
1906
+ _WaveformPlayer._themeWatch = { obs, mq, refresh };
1907
+ }
1837
1908
  /**
1838
1909
  * Sync the speed control's label and the menu's active-option highlight to
1839
1910
  * the audio element's current `playbackRate`. No-op in external mode (no