@arraypress/waveform-player 1.10.0 → 1.12.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/index.d.ts CHANGED
@@ -133,6 +133,12 @@ export interface WaveformPlayerOptions {
133
133
  * @default 'default'
134
134
  */
135
135
  layout?: 'default' | 'preview';
136
+ /**
137
+ * Play/pause button style. `'minimal'` renders a bare glyph with no circle —
138
+ * the look sample-pack and beat stores use in preview grids.
139
+ * @default 'circle'
140
+ */
141
+ buttonStyle?: 'circle' | 'minimal';
136
142
  /** Show transport controls. @default true */
137
143
  showControls?: boolean;
138
144
  /** Show the info (title/subtitle) block. @default true */
@@ -143,6 +149,8 @@ export interface WaveformPlayerOptions {
143
149
  showHoverTime?: boolean;
144
150
  /** Show detected BPM. @default false */
145
151
  showBPM?: boolean;
152
+ /** Known BPM shown in the badge (with `showBPM`); wins over auto-detection. */
153
+ bpm?: number;
146
154
 
147
155
  // ── Behaviour ─────────────────────────────────────────────────
148
156
  /** Begin playback on load. @default false */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arraypress/waveform-player",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "Lightweight, customizable audio player with waveform visualization",
5
5
  "type": "module",
6
6
  "types": "./index.d.ts",
@@ -51,6 +51,32 @@
51
51
  transform: scale(1.05);
52
52
  }
53
53
 
54
+ /* Minimal button style — a bare play/pause glyph with no circle. Set via
55
+ `buttonStyle: 'minimal'` / data-button-style="minimal". Ideal for sample-pack
56
+ and beat-store preview grids. */
57
+ .waveform-btn-minimal {
58
+ /* A FIXED box is essential: toggling the play glyph (which is optically
59
+ nudged 1px) for the pause glyph would otherwise change the button's
60
+ auto width, shifting the adjacent waveform — and re-sampling its bars —
61
+ on every play/pause. Fixed width keeps the canvas (and bars) stable. */
62
+ width: 1.625rem;
63
+ height: 1.625rem;
64
+ min-width: 1.625rem;
65
+ border: none;
66
+ border-radius: 0;
67
+ opacity: 0.7;
68
+ }
69
+
70
+ .waveform-btn-minimal:hover:not(:disabled) {
71
+ opacity: 1;
72
+ transform: none;
73
+ }
74
+
75
+ .waveform-btn-minimal svg {
76
+ width: 22px;
77
+ height: 22px;
78
+ }
79
+
54
80
  .waveform-btn:disabled {
55
81
  cursor: not-allowed;
56
82
  opacity: 0.3;
package/src/js/core.js CHANGED
@@ -233,7 +233,7 @@ export class WaveformPlayer {
233
233
 
234
234
  // Build play button HTML (conditional)
235
235
  const buttonHTML = this.options.showControls ? `
236
- <button class="waveform-btn" aria-label="Play/Pause" style="
236
+ <button class="waveform-btn${this.options.buttonStyle === 'minimal' ? ' waveform-btn-minimal' : ''}" aria-label="Play/Pause" style="
237
237
  border-color: ${this.options.buttonColor};
238
238
  color: ${this.options.buttonColor};
239
239
  ">
@@ -326,6 +326,9 @@ export class WaveformPlayer {
326
326
 
327
327
  // Set canvas size
328
328
  this.resizeCanvas();
329
+
330
+ // Show a caller-supplied BPM immediately (no audio decode required).
331
+ this.updateBPMDisplay();
329
332
  }
330
333
 
331
334
  /**
@@ -1375,8 +1378,12 @@ export class WaveformPlayer {
1375
1378
  * @private
1376
1379
  */
1377
1380
  updateBPMDisplay() {
1378
- if (this.bpmEl && this.bpmValueEl && this.detectedBPM) {
1379
- this.bpmValueEl.textContent = Math.round(this.detectedBPM);
1381
+ // A caller-supplied `bpm` wins over auto-detection — useful when peaks
1382
+ // are pre-generated (so the audio is never decoded) but the BPM is known
1383
+ // anyway, e.g. sample-pack previews where the tempo is in the metadata.
1384
+ const bpm = this.options.bpm || this.detectedBPM;
1385
+ if (this.bpmEl && this.bpmValueEl && bpm) {
1386
+ this.bpmValueEl.textContent = Math.round(bpm);
1380
1387
  this.bpmEl.style.display = 'inline-flex';
1381
1388
  }
1382
1389
  }
package/src/js/themes.js CHANGED
@@ -151,8 +151,11 @@ export function getColorPreset(presetName) {
151
151
  export const DEFAULT_OPTIONS = {
152
152
  // Core settings
153
153
  url: '',
154
- height: 60,
155
- samples: 200,
154
+ height: 64,
155
+ // Source peak resolution. The drawer resamples these to fit
156
+ // canvasWidth / (barWidth + barSpacing) bars, so this is fidelity headroom,
157
+ // not the visible bar count.
158
+ samples: 256,
156
159
  preload: 'metadata',
157
160
 
158
161
  // Audio mode — 'self' = player owns the <audio> element (default, current
@@ -174,13 +177,17 @@ export const DEFAULT_OPTIONS = {
174
177
  // waveform and the meta row (time / speed / BPM) is trimmed — ideal for
175
178
  // sample-pack sample previews and dense grids.
176
179
  layout: 'default',
180
+ // Play/pause button style. 'circle' = bordered circle (default).
181
+ // 'minimal' = a bare play/pause glyph with no circle — the look sample-pack
182
+ // and beat stores use in their preview grids.
183
+ buttonStyle: 'circle',
177
184
 
178
185
  // Default waveform style
179
186
  waveformStyle: 'mirror',
180
187
  barWidth: 2,
181
188
  barSpacing: 0,
182
- // Rounded bar caps (px). 0 = square (default). Applies to bars/mirror.
183
- barRadius: 0,
189
+ // Rounded bar caps (px). 0 = square; 1 = soft caps (default). Applies to bars/mirror.
190
+ barRadius: 1,
184
191
 
185
192
  // Color preset: null = auto-detect, 'dark' = force dark, 'light' = force light
186
193
  colorPreset: null,
@@ -202,6 +209,9 @@ export const DEFAULT_OPTIONS = {
202
209
  showTime: true,
203
210
  showHoverTime: false,
204
211
  showBPM: false,
212
+ // Known BPM to display in the badge (with showBPM). Wins over auto-detection
213
+ // — set it when peaks are pre-generated so the tempo still shows. null = auto.
214
+ bpm: null,
205
215
  singlePlay: true,
206
216
  playOnSeek: true,
207
217
  enableMediaSession: true,
@@ -250,7 +260,7 @@ export const DEFAULT_OPTIONS = {
250
260
  */
251
261
  export const STYLE_DEFAULTS = {
252
262
  bars: {barWidth: 3, barSpacing: 1},
253
- mirror: {barWidth: 2, barSpacing: 0},
263
+ mirror: {barWidth: 2, barSpacing: 2},
254
264
  line: {barWidth: 2, barSpacing: 0},
255
265
  blocks: {barWidth: 4, barSpacing: 2},
256
266
  dots: {barWidth: 3, barSpacing: 3},
package/src/js/utils.js CHANGED
@@ -138,6 +138,7 @@ export function parseDataAttributes(element) {
138
138
  setNum('barRadius');
139
139
  if (element.dataset.buttonAlign) options.buttonAlign = element.dataset.buttonAlign;
140
140
  if (element.dataset.layout) options.layout = element.dataset.layout;
141
+ if (element.dataset.buttonStyle) options.buttonStyle = element.dataset.buttonStyle;
141
142
 
142
143
  // Color preset
143
144
  if (element.dataset.colorPreset) options.colorPreset = element.dataset.colorPreset;
@@ -163,6 +164,7 @@ export function parseDataAttributes(element) {
163
164
  setBool('showTime');
164
165
  setBool('showHoverTime');
165
166
  setBool('showBPM', 'showBpm');
167
+ setNum('bpm');
166
168
  setBool('singlePlay');
167
169
  setBool('playOnSeek');
168
170