@arraypress/waveform-player 1.9.0 → 1.11.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
@@ -127,6 +127,18 @@ export interface WaveformPlayerOptions {
127
127
  // ── Layout / UI toggles ───────────────────────────────────────
128
128
  /** Play-button alignment. @default 'auto' */
129
129
  buttonAlign?: ButtonAlign;
130
+ /**
131
+ * Player layout. `'preview'` centers the title under the waveform and trims
132
+ * the meta row (time/speed/BPM) — ideal for sample-pack previews.
133
+ * @default 'default'
134
+ */
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';
130
142
  /** Show transport controls. @default true */
131
143
  showControls?: boolean;
132
144
  /** Show the info (title/subtitle) block. @default true */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arraypress/waveform-player",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Lightweight, customizable audio player with waveform visualization",
5
5
  "type": "module",
6
6
  "types": "./index.d.ts",
@@ -3,6 +3,9 @@
3
3
  font-family: inherit;
4
4
  color: inherit;
5
5
  line-height: var(--waveform-line-height, 1.4);
6
+ /* Neutral accent for the keyboard-focus ring + active states. Monochrome
7
+ by default (shadcn-style); override this variable to re-tint it. */
8
+ --wfp-accent: #71717a;
6
9
  }
7
10
 
8
11
  .waveform-player * {
@@ -48,6 +51,28 @@
48
51
  transform: scale(1.05);
49
52
  }
50
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
+ width: auto;
59
+ height: auto;
60
+ min-width: 0;
61
+ border: none;
62
+ border-radius: 0;
63
+ opacity: 0.7;
64
+ }
65
+
66
+ .waveform-btn-minimal:hover:not(:disabled) {
67
+ opacity: 1;
68
+ transform: none;
69
+ }
70
+
71
+ .waveform-btn-minimal svg {
72
+ width: 22px;
73
+ height: 22px;
74
+ }
75
+
51
76
  .waveform-btn:disabled {
52
77
  cursor: not-allowed;
53
78
  opacity: 0.3;
@@ -302,13 +327,13 @@
302
327
  }
303
328
 
304
329
  .speed-option.active {
305
- background: rgba(168, 85, 247, 0.2);
306
- color: #a855f7;
330
+ background: rgba(255, 255, 255, 0.16);
331
+ color: #fff;
307
332
  font-weight: 600;
308
333
  }
309
334
 
310
335
  .waveform-player.waveform-focused {
311
- outline: 2px solid rgba(168, 85, 247, 0.5);
336
+ outline: 2px solid var(--wfp-accent);
312
337
  outline-offset: 2px;
313
338
  border-radius: 4px;
314
339
  }
@@ -320,10 +345,28 @@
320
345
 
321
346
  /* Only show focus indicator when keyboard navigating (not clicking) */
322
347
  .waveform-player:focus-visible {
323
- outline: 1px solid rgba(168, 85, 247, 0.3);
348
+ outline: 1px solid var(--wfp-accent);
324
349
  outline-offset: 1px;
325
350
  }
326
351
 
352
+ /* ==========================================================================
353
+ 'preview' layout — compact, centered title under the waveform, trimmed
354
+ meta row. Ideal for sample-pack previews and dense grids.
355
+ ========================================================================== */
356
+ .waveform-layout-preview .waveform-meta {
357
+ display: none !important;
358
+ }
359
+
360
+ .waveform-layout-preview .waveform-info {
361
+ justify-content: center;
362
+ }
363
+
364
+ .waveform-layout-preview .waveform-text {
365
+ flex: 0 1 auto;
366
+ align-items: center;
367
+ text-align: center;
368
+ }
369
+
327
370
  /* Remove the class-based focus indicator since we're using :focus-visible */
328
371
  .waveform-player.waveform-focused {
329
372
  outline: none;
package/src/js/core.js CHANGED
@@ -224,9 +224,16 @@ export class WaveformPlayer {
224
224
  }
225
225
  }
226
226
 
227
+ // Compact 'preview' layout: centered title under the waveform with the
228
+ // meta row trimmed. Set via the `layout` option / data-layout="preview".
229
+ const isPreview = this.options.layout === 'preview';
230
+ if (isPreview) {
231
+ this.container.classList.add('waveform-layout-preview');
232
+ }
233
+
227
234
  // Build play button HTML (conditional)
228
235
  const buttonHTML = this.options.showControls ? `
229
- <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="
230
237
  border-color: ${this.options.buttonColor};
231
238
  color: ${this.options.buttonColor};
232
239
  ">
@@ -251,7 +258,7 @@ export class WaveformPlayer {
251
258
  <span class="waveform-title" style="color: ${this.options.textColor};"></span>
252
259
  ${this.options.subtitle ? `<span class="waveform-subtitle" style="color: ${this.options.textSecondaryColor};">${this.options.subtitle}</span>` : ''}
253
260
  </div>
254
- <div style="display: flex; align-items: center; gap: 1rem;">
261
+ <div class="waveform-meta" style="display: flex; align-items: center; gap: 1rem;">
255
262
  ${this.options.showBPM ? `
256
263
  <span class="waveform-bpm" style="color: ${this.options.textSecondaryColor}; display: none;">
257
264
  <span class="bpm-value">--</span> BPM
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
@@ -169,13 +172,22 @@ export const DEFAULT_OPTIONS = {
169
172
 
170
173
  // Layout Options
171
174
  buttonAlign: 'auto',
175
+ // Player layout. 'default' = play button + waveform with a left-aligned
176
+ // info row below. 'preview' = compact: the title is centered under the
177
+ // waveform and the meta row (time / speed / BPM) is trimmed — ideal for
178
+ // sample-pack sample previews and dense grids.
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',
172
184
 
173
185
  // Default waveform style
174
186
  waveformStyle: 'mirror',
175
187
  barWidth: 2,
176
188
  barSpacing: 0,
177
- // Rounded bar caps (px). 0 = square (default). Applies to bars/mirror.
178
- barRadius: 0,
189
+ // Rounded bar caps (px). 0 = square; 1 = soft caps (default). Applies to bars/mirror.
190
+ barRadius: 1,
179
191
 
180
192
  // Color preset: null = auto-detect, 'dark' = force dark, 'light' = force light
181
193
  colorPreset: null,
@@ -245,7 +257,7 @@ export const DEFAULT_OPTIONS = {
245
257
  */
246
258
  export const STYLE_DEFAULTS = {
247
259
  bars: {barWidth: 3, barSpacing: 1},
248
- mirror: {barWidth: 2, barSpacing: 0},
260
+ mirror: {barWidth: 2, barSpacing: 2},
249
261
  line: {barWidth: 2, barSpacing: 0},
250
262
  blocks: {barWidth: 4, barSpacing: 2},
251
263
  dots: {barWidth: 3, barSpacing: 3},
package/src/js/utils.js CHANGED
@@ -137,6 +137,8 @@ export function parseDataAttributes(element) {
137
137
  setNum('barSpacing');
138
138
  setNum('barRadius');
139
139
  if (element.dataset.buttonAlign) options.buttonAlign = element.dataset.buttonAlign;
140
+ if (element.dataset.layout) options.layout = element.dataset.layout;
141
+ if (element.dataset.buttonStyle) options.buttonStyle = element.dataset.buttonStyle;
140
142
 
141
143
  // Color preset
142
144
  if (element.dataset.colorPreset) options.colorPreset = element.dataset.colorPreset;