npm.io
0.2.0 • Published 5h ago

@arraypress/waveform-playlist-svelte

Licence
MIT
Version
0.2.0
Deps
0
Size
34 kB
Vulns
0
Weekly
0

@arraypress/waveform-playlist-svelte

Svelte 5 component wrapper around @arraypress/waveform-playlist. Declarative tracks (with chapters + markers), typed props for every playlist + player option, and an exported imperative navigation API (selectTrack() / nextTrack() / previousTrack()).

The core library stays a zero-dependency vanilla-JS package that works anywhere a <script> tag does. This package adds the framework-native ergonomics Svelte developers expect — built with runes.

<script lang="ts">
  import { WaveformPlaylist } from '@arraypress/waveform-playlist-svelte';

  const tracks = [
    { url: '/audio/a.mp3', title: 'Track A' },
    { url: '/audio/b.mp3', title: 'Track B' },
  ];
</script>

<WaveformPlaylist {tracks} />

Installation

npm install @arraypress/waveform-playlist-svelte @arraypress/waveform-playlist @arraypress/waveform-player svelte

svelte (^5), @arraypress/waveform-playlist (^1.3), and @arraypress/waveform-player (^1.8) are peer dependencies.

Setup

Import both cores' CSS once in your app entry, and ensure the core player is loaded (the playlist instantiates window.WaveformPlayer for the active track):

import '@arraypress/waveform-player';                              // registers window.WaveformPlayer
import '@arraypress/waveform-player/dist/waveform-player.css';
import '@arraypress/waveform-playlist/dist/waveform-playlist.css';

The wrapper does not import CSS for you. The playlist's JS is loaded dynamically inside a $effect (browser-only), so SSR / SvelteKit prerendering doesn't trip over the browser-only audio APIs.

Usage

Tracks with metadata + chapters
<script lang="ts">
  import { WaveformPlaylist, type WaveformPlaylistTrackInput } from '@arraypress/waveform-playlist-svelte';

  const tracks: WaveformPlaylistTrackInput[] = [
    {
      url: '/audio/episode-1.mp3',
      title: 'Episode 1',
      artist: 'The Pilot',
      artwork: '/img/ep1.jpg',
      duration: '42:10',
      chapters: [
        { time: 0, label: 'Cold open' },
        { time: 90, label: 'Main topic', color: '#a855f7' },
        { time: '38:00', label: 'Wrap-up' },
      ],
    },
    { url: '/audio/episode-2.mp3', title: 'Episode 2' },
  ];
</script>

<WaveformPlaylist {tracks} layout="list" continuous showDuration />

Naming note. class, style, id, and other element attributes fall through to the host element; the base class wfp-host is always applied. The visual style is waveformStyle.

Imperative navigation via bind:this
<script lang="ts">
  import { WaveformPlaylist } from '@arraypress/waveform-playlist-svelte';
  let playlist: WaveformPlaylist;
</script>

<WaveformPlaylist bind:this={playlist} {tracks} />
<button onclick={() => playlist.previousTrack()}>Prev</button>
<button onclick={() => playlist.nextTrack()}>Next</button>
<button onclick={() => playlist.selectTrack(2)}>Track 3</button>

The exported methods (selectTrack(), seekToChapter(), nextTrack(), previousTrack(), getPlayer(), getCurrentTrackIndex(), getTracks()) pass straight through to the underlying instance. playlist.getInstance() returns the raw instance.

How it works

Tracks are rendered declaratively into the [data-track] / [data-chapter] markup the WaveformPlaylist constructor parses on mount — the same contract the vanilla library uses. When any construction prop changes (a serialised tracks change, layout, options, …), the wrapper destroys the instance and rebuilds it over the freshly-rendered markup.

There are no lifecycle callbacks — the playlist owns the embedded player's callbacks internally to drive continuous playback and chapter tracking. Observe playback via the embedded player from getPlayer().

Props

Every playlist option and forwarded player option is a typed prop; absent props are not forwarded, so the cores' own defaults apply. See src/lib/types.ts. Highlights: tracks (required), layout, continuous, expandChapters, showDuration, showChapterMarkers, chapterMarkerColor, showPlayState, plus the player surface (waveformStyle, height, samples, barWidth, colorPreset, colours, playbackRate, showControls, showInfo, showTime, showBPM, accessibleSeek, …).

TypeScript

import type {
  WaveformPlaylistProps,
  WaveformPlaylistExpose,
  WaveformPlaylistTrackInput,
  WaveformPlaylistChapterInput,
  WaveformPlaylistOptions,
  WaveformPlaylistTrack,
  WaveformStyle,
  ColorPreset,
} from '@arraypress/waveform-playlist-svelte';

Types are re-exported straight from the cores, so they can never drift. The package ships .svelte + .d.ts (generated by svelte-package).

Testing

npm test          # one-shot
npm run typecheck  # svelte-check
npm run build      # svelte-package → dist/

The core library is mocked at the module boundary (jsdom has no Web Audio API).

License

MIT ArrayPress

Keywords