@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 CHANGED
@@ -47,6 +47,9 @@ Think Spotify's bottom player — but lightweight, zero-config, and works on any
47
47
  <!-- WaveformBar -->
48
48
  <link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-bar@latest/dist/waveform-bar.css">
49
49
  <script src="https://unpkg.com/@arraypress/waveform-bar@latest/dist/waveform-bar.js"></script>
50
+
51
+ <!-- Optional: Page icons (play/pause overlays, hearts, carts, etc.) -->
52
+ <link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-bar@latest/dist/waveform-bar-icons.css">
50
53
  ```
51
54
 
52
55
  ### NPM
@@ -75,6 +78,33 @@ npm install @arraypress/waveform-player @arraypress/waveform-bar
75
78
  Click the button → the bar slides up from the bottom → music plays. Add more buttons anywhere on the page and they all
76
79
  share the same player bar.
77
80
 
81
+ ## Inline WaveformPlayer integration (v1.3+)
82
+
83
+ When `@arraypress/waveform-player` 1.6+ instances are mounted on the same page with `audioMode: 'external'`, WaveformBar discovers them automatically and treats them as **synchronized visual surfaces**:
84
+
85
+ - Click the inline player's play button → playback happens in the bar
86
+ - The bar's audio progress mirrors into the inline canvas in real time (scrubber moves, play/pause icon flips)
87
+ - When the bar switches tracks, the previously-active inline player resets to paused
88
+
89
+ No configuration on the bar side — the discovery scan runs on init + MutationObserver tick, listening for `waveformplayer:request-play|pause|seek` events at the document level. Any inline player whose URL matches the bar's current track gets `setPlayingState(...)` and `setProgress(...)` calls pumped to it.
90
+
91
+ ```html
92
+ <!-- The same element doubles as a bar trigger (data-wb-play) AND an
93
+ inline visual surface (data-waveform-player + audio-mode). Single
94
+ audio source (the bar), multiple visual surfaces (bar + every
95
+ matching inline player). -->
96
+ <div data-waveform-player
97
+ data-audio-mode="external"
98
+ data-url="song.mp3"
99
+ data-waveform-style="bars"
100
+
101
+ data-wb-play
102
+ data-wb-url="song.mp3"
103
+ data-wb-title="..."></div>
104
+ ```
105
+
106
+ This is the SoundCloud / Bandcamp pattern — the persistent bar owns playback, but every place a track surfaces on the page gets its own playable, progress-aware visualization.
107
+
78
108
  ## Data Attributes
79
109
 
80
110
  ### Play Trigger (`data-wb-play`)
@@ -130,21 +160,62 @@ Add to any element to queue a track without immediately playing it.
130
160
  </button>
131
161
  ```
132
162
 
133
- ### Pre-Generated Waveform Data
163
+ ### Pre-Generated Waveforms
134
164
 
135
- Skip client-side audio analysis by providing pre-generated waveform peaks.
136
- Use [waveform-gen](https://github.com/arraypress/waveform-gen) to generate the data.
165
+ Skip client-side audio analysis by providing pre-generated waveform data. The `data-wb-waveform` attribute accepts three
166
+ formats:
167
+
168
+ | Format | Example | Description |
169
+ |---------------|--------------------------|--------------------------------------------------|
170
+ | JSON file URL | `waveforms/song.json` | Fetches peaks from `{ peaks: [...] }` or `[...]` |
171
+ | Inline array | `[0.2, 0.37, 0.41, ...]` | JSON array string |
172
+ | CSV string | `0.2,0.37,0.41,...` | Comma-separated values |
137
173
 
138
174
  ```html
175
+ <!-- JSON file — fetched automatically by the player -->
176
+ <div data-wb-play
177
+ data-url="audio/song.mp3"
178
+ data-title="My Song"
179
+ data-wb-waveform="waveforms/song.json">
180
+ </div>
139
181
 
182
+ <!-- Inline peaks -->
140
183
  <div data-wb-play
141
- data-url="song.mp3"
184
+ data-url="audio/song.mp3"
142
185
  data-title="My Song"
143
- data-wb-waveform='[0.12,0.45,0.89,0.34,0.67,0.92,0.15,0.78]'>
186
+ data-wb-waveform="[0.12,0.45,0.89,0.34,0.67]">
144
187
  </div>
145
188
  ```
146
189
 
147
- The waveform displays instantly on load without downloading and decoding the audio file.
190
+ Generate JSON files with [WaveformGen](https://github.com/arraypress/waveform-gen):
191
+
192
+ ```bash
193
+ npx @arraypress/waveform-gen ./audio/*.mp3 --output ./waveforms/ --bpm
194
+ ```
195
+
196
+ JSON waveform files can also include markers, which are loaded automatically if none are set via data attributes:
197
+
198
+ ```json
199
+ {
200
+ "peaks": [
201
+ 0.12,
202
+ 0.45,
203
+ 0.89,
204
+ 0.34,
205
+ ...
206
+ ],
207
+ "markers": [
208
+ {
209
+ "time": 0,
210
+ "label": "Intro"
211
+ },
212
+ {
213
+ "time": 30,
214
+ "label": "Chorus"
215
+ }
216
+ ]
217
+ }
218
+ ```
148
219
 
149
220
  ### DJ Mode Markers
150
221
 
@@ -166,32 +237,31 @@ and metadata at each marker boundary.
166
237
  </div>
167
238
  ```
168
239
 
169
- Markers can include: `time` (seconds, required), `label` (required), `title`, `artist`, `artwork`, `bpm`, `key`,
170
- `color`.
240
+ Markers can include: `time` (seconds, required), `label` (required), `title`, `artist`, `artwork`, `bpm`, `key`,`color`.
171
241
 
172
242
  The active marker on the waveform gently pulses to indicate the current section.
173
243
 
174
244
  ### Attribute Reference
175
245
 
176
- | Attribute | Description |
177
- |---------------------|------------------------------------------------------------|
178
- | `data-wb-play` | Makes element a play trigger (click to play) |
179
- | `data-wb-queue` | Makes element a queue trigger (click to add to queue) |
180
- | `data-url` | Audio file URL (required) |
181
- | `data-id` | Unique track identifier (defaults to URL) |
182
- | `data-title` | Track title |
183
- | `data-artist` | Artist or subtitle |
184
- | `data-artwork` | Album artwork URL |
185
- | `data-album` | Album name (for Media Session API) |
186
- | `data-link` | URL to navigate when clicking track info in the bar |
187
- | `data-duration` | Display duration string |
188
- | `data-bpm` | BPM value — displayed as a tag in the bar |
189
- | `data-key` | Musical key — displayed as a tag in the bar |
190
- | `data-meta` | JSON object of custom metadata (e.g. `'{"genre":"Trap"}'`) |
191
- | `data-wb-waveform` | Pre-generated waveform peaks JSON array |
192
- | `data-wb-markers` | JSON array of marker objects for DJ mode |
193
- | `data-wb-favorited` | `"true"` to pre-set favorite state (server-side seeding) |
194
- | `data-wb-in-cart` | `"true"` to pre-set cart state (server-side seeding) |
246
+ | Attribute | Description |
247
+ |---------------------|---------------------------------------------------------------------------|
248
+ | `data-wb-play` | Makes element a play trigger (click to play) |
249
+ | `data-wb-queue` | Makes element a queue trigger (click to add to queue) |
250
+ | `data-url` | Audio file URL (required) |
251
+ | `data-id` | Unique track identifier (defaults to URL) |
252
+ | `data-title` | Track title |
253
+ | `data-artist` | Artist or subtitle |
254
+ | `data-artwork` | Album artwork URL |
255
+ | `data-album` | Album name (for Media Session API) |
256
+ | `data-link` | URL to navigate when clicking track info in the bar |
257
+ | `data-duration` | Display duration string |
258
+ | `data-bpm` | BPM value — displayed as a tag in the bar |
259
+ | `data-key` | Musical key — displayed as a tag in the bar |
260
+ | `data-meta` | JSON object of custom metadata (e.g. `'{"genre":"Trap"}'`) |
261
+ | `data-wb-waveform` | Pre-generated waveform peaks: JSON array, CSV string, or `.json` file URL |
262
+ | `data-wb-markers` | JSON array of marker objects for DJ mode |
263
+ | `data-wb-favorited` | `"true"` to pre-set favorite state (server-side seeding) |
264
+ | `data-wb-in-cart` | `"true"` to pre-set cart state (server-side seeding) |
195
265
 
196
266
  All attributes also accept `data-wb-` prefixed versions (`data-wb-url`, `data-wb-title`, etc.) to avoid conflicts with
197
267
  other libraries.
@@ -238,11 +308,11 @@ WaveformBar.init({
238
308
  // Server-side actions (REST callbacks)
239
309
  actions: {
240
310
  favorite: {
241
- endpoint: '/api/favorites', // POST URL
311
+ endpoint: '/api/favorites',
242
312
  method: 'POST'
243
313
  },
244
314
  cart: {
245
- endpoint: '/api/cart', // POST URL
315
+ endpoint: '/api/cart',
246
316
  method: 'POST'
247
317
  }
248
318
  },
@@ -270,7 +340,6 @@ WaveformBar.init({
270
340
  ### Playback
271
341
 
272
342
  ```javascript
273
- // Play a track object
274
343
  WaveformBar.play({
275
344
  url: 'audio/song.mp3',
276
345
  title: 'My Song',
@@ -281,15 +350,12 @@ WaveformBar.play({
281
350
  link: '/products/my-song'
282
351
  });
283
352
 
284
- // Play by URL shorthand
285
353
  WaveformBar.play('audio/song.mp3');
286
-
287
- // Playback controls
288
354
  WaveformBar.togglePlay();
289
355
  WaveformBar.pause();
290
- WaveformBar.next(); // Next track (wraps if repeat: 'all')
291
- WaveformBar.previous(); // Previous track (restarts if >3s in)
292
- WaveformBar.skipTo(3); // Jump to queue index 3
356
+ WaveformBar.next();
357
+ WaveformBar.previous();
358
+ WaveformBar.skipTo(3);
293
359
  ```
294
360
 
295
361
  ### Repeat
@@ -299,102 +365,57 @@ WaveformBar.cycleRepeat(); // Cycles: off → all → one → off
299
365
  WaveformBar.setRepeat('all'); // Set directly: 'off', 'all', 'one'
300
366
  ```
301
367
 
302
- - **off** — Stops at end of queue
303
- - **all** — Loops back to first track after last; prev/next wrap around
304
- - **one** — Replays the current track indefinitely
305
-
306
368
  ### Markers / DJ Mode
307
369
 
308
370
  ```javascript
309
- // Seek to marker by index (0-based) on current track
310
371
  WaveformBar.seekToMarker(3);
311
-
312
- // Seek to marker by label name on current track
313
372
  WaveformBar.seekToMarkerByLabel('Horizon');
314
373
  ```
315
374
 
316
- Both methods auto-play if the player is paused. They only work on the currently loaded track's markers — if the track
317
- with markers isn't loaded, they silently return.
318
-
319
375
  ### Volume
320
376
 
321
377
  ```javascript
322
- WaveformBar.setVolume(0.5); // Set to 50%
323
- WaveformBar.getVolume(); // Returns 0.5
378
+ WaveformBar.setVolume(0.5);
379
+ WaveformBar.getVolume();
324
380
  WaveformBar.toggleMute();
325
- WaveformBar.isMutedState(); // true/false
326
381
  ```
327
382
 
328
- Volume and mute state persist in localStorage across sessions.
329
-
330
383
  ### Queue
331
384
 
332
385
  ```javascript
333
- // Add to end of queue
334
386
  WaveformBar.addToQueue({url: 'track.mp3', title: 'Next Up', artist: 'Someone'});
335
-
336
- // Remove by index
337
387
  WaveformBar.removeFromQueue(2);
338
-
339
- // Replay a previously played track (by URL)
340
- WaveformBar.replay('audio/old-track.mp3');
341
-
342
- // Clear upcoming tracks
343
388
  WaveformBar.clearQueue();
344
-
345
- // Clear play history
346
- WaveformBar.clearHistory();
347
389
  ```
348
390
 
349
- The queue panel shows three sections: **Now Playing** (click to toggle play/pause), **Up Next**, and **Previously Played
350
- **. Tracks can be removed individually from the queue via the × button on hover.
351
-
352
- ### Favorites
391
+ ### Favorites & Cart
353
392
 
354
393
  ```javascript
355
- WaveformBar.toggleFavorite(); // Toggle current track's favorite state
356
- WaveformBar.isFavorited('beat-001'); // Check by track ID
394
+ WaveformBar.toggleFavorite();
395
+ WaveformBar.isFavorited('beat-001');
396
+ WaveformBar.addToCart();
397
+ WaveformBar.isInCart('beat-001');
357
398
  ```
358
399
 
359
- Favorites persist in localStorage. Server-side state can be seeded via `data-wb-favorited="true"` on trigger elements —
360
- this is authoritative and overrides localStorage on page load.
361
-
362
- When a track is favorited/unfavorited, the `.wb-favorited` class is toggled on all matching trigger elements on the
363
- page.
364
-
365
- ### Cart
366
-
367
- ```javascript
368
- WaveformBar.addToCart(); // Add current track to cart
369
- WaveformBar.isInCart('beat-001'); // Check by track ID
370
- ```
371
-
372
- Cart state is NOT persisted to localStorage — it's server-authoritative. Seed from your server via
373
- `data-wb-in-cart="true"`. The `.wb-in-cart` class is toggled on matching trigger elements.
374
-
375
- If an `actions.cart.endpoint` is configured, a POST request fires automatically with the track data.
376
-
377
400
  ### State
378
401
 
379
402
  ```javascript
380
- WaveformBar.getCurrentTrack(); // { url, title, artist, bpm, key, ... }
381
- WaveformBar.isCurrentlyPlaying('song.mp3'); // true if this URL is actively playing
382
- WaveformBar.isCurrentTrack('song.mp3'); // true if current (playing or paused)
383
- WaveformBar.getQueue(); // Full queue array
384
- WaveformBar.getHistory(); // Previously played tracks
385
- WaveformBar.getPlayer(); // Underlying WaveformPlayer instance
403
+ WaveformBar.getCurrentTrack();
404
+ WaveformBar.isCurrentlyPlaying('song.mp3');
405
+ WaveformBar.isCurrentTrack('song.mp3');
406
+ WaveformBar.getQueue();
407
+ WaveformBar.getCurrentIndex();
408
+ WaveformBar.getPlayer();
386
409
  ```
387
410
 
388
411
  ### UI
389
412
 
390
413
  ```javascript
391
- WaveformBar.show(); // Show the bar
392
- WaveformBar.hide(); // Hide the bar
393
- WaveformBar.toggleQueuePanel(); // Toggle queue panel visibility
394
- WaveformBar.toggleVolumePopup(); // Toggle volume popup
395
- WaveformBar.closeQueuePanel();
396
- WaveformBar.closeVolumePopup();
397
- WaveformBar.destroy(); // Remove bar and clean up
414
+ WaveformBar.show();
415
+ WaveformBar.hide();
416
+ WaveformBar.toggleQueuePanel();
417
+ WaveformBar.toggleVolumePopup();
418
+ WaveformBar.destroy();
398
419
  ```
399
420
 
400
421
  ## DOM Events
@@ -405,10 +426,6 @@ All events bubble from the bar element and are prefixed with `waveformbar:`.
405
426
  document.addEventListener('waveformbar:play', (e) => {
406
427
  console.log('Playing:', e.detail.track);
407
428
  });
408
-
409
- document.addEventListener('waveformbar:trackchange', (e) => {
410
- console.log('Track changed:', e.detail.track, 'Index:', e.detail.index);
411
- });
412
429
  ```
413
430
 
414
431
  | Event | Detail |
@@ -434,16 +451,10 @@ WaveformBar automatically adds CSS classes to trigger elements on the page:
434
451
  | `.wb-favorited` | The element's track is favorited |
435
452
  | `.wb-in-cart` | The element's track is in the cart |
436
453
 
437
- These update in real-time as the user interacts with the bar.
438
-
439
454
  ## Helper CSS Classes
440
455
 
441
- Ready-made utility classes for common UI patterns. Add them to your trigger elements.
442
-
443
456
  ### Icon Swap (`wb-icon-swap`)
444
457
 
445
- Swaps play/pause content automatically based on playback state.
446
-
447
458
  ```html
448
459
 
449
460
  <button data-wb-play data-url="song.mp3" class="wb-icon-swap">
@@ -454,100 +465,74 @@ Swaps play/pause content automatically based on playback state.
454
465
 
455
466
  ### Equalizer Bars (`wb-eq-bars`)
456
467
 
457
- Animated equalizer bars that activate when the track is playing.
458
-
459
468
  ```html
460
-
461
- <tr data-wb-play data-url="song.mp3">
462
- <td>
463
- <span class="wb-eq-bars">
464
- <span></span><span></span><span></span><span></span>
465
- </span>
466
- </td>
467
- <td>Track Title</td>
468
- </tr>
469
+ <span class="wb-eq-bars"><span></span><span></span><span></span><span></span></span>
469
470
  ```
470
471
 
471
472
  ### Card Highlight (`wb-card-highlight`)
472
473
 
473
- Adds accent border and glow when the element's track is current.
474
-
475
- ```html
476
-
477
- <div data-wb-play data-url="song.mp3"
478
- class="wb-card-highlight"
479
- style="border: 1px solid transparent; border-radius: 8px;">
480
- <h3>Track Title</h3>
481
- </div>
482
- ```
474
+ Adds accent border when the element's track is current.
483
475
 
484
476
  ### Accent Text (`wb-accent-current`)
485
477
 
486
478
  Colors text with the accent color when the parent track is current.
487
479
 
488
- ```html
489
-
490
- <div data-wb-play data-url="song.mp3">
491
- <span class="wb-accent-current">Track Title</span>
492
- </div>
493
- ```
494
-
495
- ### Pulse Animation (`wb-pulse-playing`)
496
-
497
- Subtle opacity pulse on playing elements.
480
+ ### Favorite/Cart Visibility
498
481
 
499
482
  ```html
500
-
501
- <div data-wb-play data-url="song.mp3" class="wb-pulse-playing">
502
- <img src="cover.jpg">
503
- </div>
483
+ <span class="wb-hide-if-fav">♡ Save</span>
484
+ <span class="wb-show-if-fav">❤ Saved</span>
485
+ <span class="wb-hide-if-cart">🛒 Add</span>
486
+ <span class="wb-show-if-cart">✓ In Cart</span>
504
487
  ```
505
488
 
506
- ### Favorite/Cart Visibility
489
+ ## Page Icons
507
490
 
508
- Show or hide content based on favorite/cart state.
491
+ The optional `waveform-bar-icons.css` provides a lightweight SVG icon set for use in your page elements (play/pause
492
+ overlays, hearts, carts, etc.):
509
493
 
510
494
  ```html
511
495
 
512
- <div data-wb-play data-url="song.mp3" data-id="beat-001">
513
- <button>
514
- <span class="wb-hide-if-fav">♡ Save</span>
515
- <span class="wb-show-if-fav">❤ Saved</span>
516
- </button>
517
- <button>
518
- <span class="wb-hide-if-cart">🛒 Add to Cart</span>
519
- <span class="wb-show-if-cart">✓ In Cart</span>
520
- </button>
521
- </div>
522
- ```
496
+ <link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-bar@latest/dist/waveform-bar-icons.css">
497
+
498
+ <span class="wbi wbi-play"></span>
499
+ <span class="wbi wbi-pause"></span>
500
+ <span class="wbi wbi-heart"></span>
501
+ <span class="wbi wbi-heart-filled"></span>
502
+ <span class="wbi wbi-cart"></span>
503
+ <span class="wbi wbi-cart-check"></span>
504
+ <span class="wbi wbi-queue"></span>
505
+ <span class="wbi wbi-skip-back"></span>
506
+ <span class="wbi wbi-skip-forward"></span>
507
+ <span class="wbi wbi-volume-high"></span>
508
+ <span class="wbi wbi-volume-low"></span>
509
+ <span class="wbi wbi-volume-mute"></span>
510
+ <span class="wbi wbi-repeat"></span>
511
+ <span class="wbi wbi-repeat-one"></span>
512
+ <span class="wbi wbi-close"></span>
513
+ <span class="wbi wbi-check"></span>
514
+ <span class="wbi wbi-link"></span>
515
+ <span class="wbi wbi-download"></span>
516
+ <span class="wbi wbi-share"></span>
517
+ <span class="wbi wbi-music-note"></span>
518
+ ```
519
+
520
+ Icons inherit `color` from their parent and scale with `font-size`. Size variants: `.wbi-sm`, `.wbi-lg`, `.wbi-xl`,
521
+ `.wbi-2x`, `.wbi-3x`.
522
+
523
+ These are for your page elements only — the bar itself uses its own internal SVG icons and does not require this file.
523
524
 
524
525
  ## Persistence
525
526
 
526
- WaveformBar uses two storage mechanisms:
527
-
528
- **sessionStorage** (cleared when browser closes):
529
-
530
- - Queue contents and order
531
- - Current track index
532
- - Playback position
533
- - Playing state
534
-
535
- **localStorage** (persists across sessions):
527
+ **sessionStorage** (cleared when browser closes): queue, current track index, playback position, playing state.
536
528
 
537
- - Volume level
538
- - Mute state
539
- - Favorite track IDs
540
-
541
- When a user navigates between pages, the bar restores the queue, seeks to the saved position, and optionally resumes
542
- playback (if `autoResume: true`). Position is saved on every page unload for accuracy.
529
+ **localStorage** (persists across sessions): volume level, mute state, favorite track IDs.
543
530
 
544
531
  Cart state is intentionally NOT persisted — it seeds from `data-wb-in-cart` attributes on page load, making the server
545
532
  the source of truth.
546
533
 
547
534
  ## Custom Styling
548
535
 
549
- Override CSS custom properties to theme the bar:
550
-
551
536
  ```css
552
537
  .waveform-bar,
553
538
  .wb-queue-panel {
@@ -555,178 +540,32 @@ Override CSS custom properties to theme the bar:
555
540
  --wb-border: rgba(255, 255, 255, 0.1);
556
541
  --wb-text: #ffffff;
557
542
  --wb-text-muted: rgba(255, 255, 255, 0.5);
558
- --wb-accent: #1db954; /* e.g. Spotify green */
543
+ --wb-accent: #1db954;
559
544
  --wb-accent-light: #1ed760;
560
545
  --wb-hover: rgba(255, 255, 255, 0.08);
561
- --wb-tag-bg: rgba(29, 185, 84, 0.12);
562
- --wb-tag-text: #1db954;
563
546
  --wb-fav-color: #ef4444;
564
547
  --wb-cart-color: #4ade80;
565
548
  }
566
549
  ```
567
550
 
568
- A `.wb-light` class is available for light backgrounds:
569
-
570
- ```css
571
- .waveform-bar.wb-light {
572
- --wb-bg: rgba(255, 255, 255, 0.95);
573
- --wb-text: #1a1a1a;
574
- --wb-text-muted: rgba(0, 0, 0, 0.5);
575
- }
576
- ```
577
-
578
- ## Layout
579
-
580
- The bar uses a three-zone flex layout:
581
-
582
- ```
583
- [Left: controls + track info] — [Centre: waveform + time] — [Right: meta + actions + volume + queue]
584
- ```
585
-
586
- - **Left zone** — Prev, Play/Pause, Next, Repeat buttons + artwork + title/artist
587
- - **Centre zone** — Full-width waveform visualization + elapsed/total time
588
- - **Right zone** — BPM/key tags, favorite/cart buttons, volume popup, queue toggle
589
-
590
- On mobile (≤768px):
591
-
592
- - Left + Right share the top row
593
- - Waveform drops to a full-width second row
594
- - Meta tags, actions, and time display are hidden
595
- - Queue panel becomes full-width
596
-
597
- On small mobile (≤480px):
598
-
599
- - Prev/Next and Repeat buttons are hidden
600
- - Volume is hidden
601
- - Only play button, track info, and waveform remain
602
-
603
- ## Use Cases
604
-
605
- ### Beat Store
606
-
607
- ```html
608
-
609
- <div class="beat-card wb-card-highlight"
610
- data-wb-play
611
- data-url="beats/trap-42.mp3"
612
- data-id="beat-42"
613
- data-title="Trap Beat #42"
614
- data-artist="ProducerName"
615
- data-bpm="140"
616
- data-key="Cm"
617
- data-artwork="covers/trap-42.jpg"
618
- data-link="/beats/trap-42"
619
- data-wb-favorited="true">
620
- <img src="covers/trap-42.jpg">
621
- <h3 class="wb-accent-current">Trap Beat #42</h3>
622
- <p>140 BPM · Cm · $29.99</p>
623
- <span class="wb-eq-bars"><span></span><span></span><span></span><span></span></span>
624
- <button>
625
- <span class="wb-hide-if-fav">♡ Save</span>
626
- <span class="wb-show-if-fav">❤ Saved</span>
627
- </button>
628
- </div>
629
- <button data-wb-queue data-url="beats/trap-42.mp3" data-title="Trap Beat #42">+ Queue</button>
630
- ```
631
-
632
- ### Sample Library Table
633
-
634
- ```html
635
-
636
- <table>
637
- <tr data-wb-play
638
- data-url="samples/kick.wav"
639
- data-title="808 Kick"
640
- data-artist="Drum Kit Vol. 3"
641
- data-bpm="128"
642
- data-meta='{"format":"WAV"}'>
643
- <td><span class="wb-eq-bars"><span></span><span></span><span></span><span></span></span></td>
644
- <td class="wb-accent-current">808 Kick</td>
645
- <td>128 BPM</td>
646
- <td>WAV</td>
647
- </tr>
648
- </table>
649
- ```
650
-
651
- ### DJ Mix with Clickable Tracklist
652
-
653
- ```html
654
- <!-- Mix trigger with markers -->
655
- <div data-wb-play
656
- data-url="mixes/guestmix.mp3"
657
- data-title="Guest Mix"
658
- data-artist="Various Artists"
659
- data-wb-waveform='[0.1,0.3,0.5,...]'
660
- data-wb-markers='[
661
- {"time":0,"label":"Intro","title":"Opening","artist":"DJ One"},
662
- {"time":180,"label":"Drop","title":"Big Tune","artist":"Producer X"},
663
- {"time":360,"label":"Chill","title":"Wind Down","artist":"Ambient Co"}
664
- ]'>
665
- 🎧 Play Guest Mix
666
- </div>
667
-
668
- <!-- Clickable tracklist buttons -->
669
- <button onclick="WaveformBar.seekToMarkerByLabel('Intro')">00:00 — DJ One — Opening</button>
670
- <button onclick="WaveformBar.seekToMarkerByLabel('Drop')">03:00 — Producer X — Big Tune</button>
671
- <button onclick="WaveformBar.seekToMarkerByLabel('Chill')">06:00 — Ambient Co — Wind Down</button>
672
- ```
673
-
674
- ### Podcast
675
-
676
- ```html
677
-
678
- <button data-wb-play
679
- data-url="episodes/ep42.mp3"
680
- data-title="Ep 42: The Future of AI"
681
- data-artist="with Dr. Sarah Chen"
682
- data-artwork="ep42-cover.jpg"
683
- data-link="/episodes/42"
684
- class="wb-icon-swap">
685
- <span class="wb-show-play">▶ Listen</span>
686
- <span class="wb-show-pause">⏸ Playing</span>
687
- </button>
688
- ```
689
-
690
- ## Pre-Generating Waveforms
691
-
692
- Use [@arraypress/waveform-gen](https://github.com/arraypress/waveform-gen) to batch-generate waveform data:
693
-
694
- ```bash
695
- # Generate JSON files for all audio
696
- npx @arraypress/waveform-gen ./audio/*.mp3 --output ./waveforms/
697
-
698
- # Generate ready-to-paste HTML markup
699
- npx @arraypress/waveform-gen ./audio/*.mp3 --format html --output ./
700
- ```
701
-
702
- Then reference the data in your HTML:
703
-
704
- ```html
705
-
706
- <div data-wb-play
707
- data-url="song.mp3"
708
- data-title="My Song"
709
- data-wb-waveform='[0.12,0.45,0.89,0.34,0.67]'>
710
- </div>
711
- ```
712
-
713
551
  ## Browser Support
714
552
 
715
- - Chrome/Edge 90+
716
- - Firefox 88+
717
- - Safari 14+
718
- - Mobile browsers (iOS Safari, Chrome Android)
553
+ Chrome/Edge 90+, Firefox 88+, Safari 14+, iOS Safari, Chrome Android
719
554
 
720
555
  ## Dependencies
721
556
 
722
- - [WaveformPlayer](https://github.com/arraypress/waveform-player) ≥1.3.5 — must be loaded before WaveformBar
557
+ - [WaveformPlayer](https://github.com/arraypress/waveform-player) ≥1.5.0 — must be loaded before WaveformBar
723
558
 
724
- ## License
559
+ ## Ecosystem
725
560
 
726
- MIT © [ArrayPress](https://github.com/arraypress)
561
+ | Package | Description |
562
+ |-------------------------------------------------------------------------|-------------------------------------------------------------------|
563
+ | **[WaveformPlayer](https://github.com/arraypress/waveform-player)** | Core audio player with waveform visualization |
564
+ | **[WaveformBar](https://github.com/arraypress/waveform-bar)** | Persistent bottom-bar player with queue, favorites, cart, DJ mode |
565
+ | **[WaveformGen](https://github.com/arraypress/waveform-generator)** | CLI tool to pre-generate waveform JSON from audio files |
566
+ | **[WaveformPlaylist](https://github.com/arraypress/waveform-playlist)** | Playlist and chapter support addon |
567
+ | **[WaveformTracker](https://github.com/arraypress/waveform-tracker)** | Audio engagement analytics |
727
568
 
728
- ## Related
569
+ ## License
729
570
 
730
- - [WaveformPlayer](https://github.com/arraypress/waveform-player) — Core audio player with waveform visualization
731
- - [WaveformPlaylist](https://github.com/arraypress/waveform-playlist) — On-page playlist and chapter navigation
732
- - [WaveformGen](https://github.com/arraypress/waveform-generator) — CLI tool for batch waveform data generation
571
+ MIT © [ArrayPress](https://github.com/arraypress)