Skip to content

Framework wrappers

The thin framework wrappers version independently of the core libraries they wrap.

  • Types are now sourced directly from the core @arraypress/waveform-player package — a single source of truth. The shared option types (WaveformStyle, ColorPreset, AudioMode, AudioPreload, ButtonAlign, WaveformMarker, WaveformPeaks) are re-exported from the core, and WaveformPlayerProps now extends the core’s WaveformPlayerOptions instead of re-declaring every option, so the two packages can no longer drift. Every previously-exported type name is preserved.
  • Bumped the @arraypress/waveform-player peer (and dev) dependency to ^1.8.0, which ships the hand-authored index.d.ts these types adopt.
  • accessibleSeek, seekLabel, barRadius, and the gradient-array forms of waveformColor / progressColor are now exposed on WaveformPlayerProps (inherited from the core option surface), filling gaps where the previous hand-maintained copy had missed or drifted.
  • Bumped the @arraypress/waveform-player peer (and dev) dependency to ^1.7.2. Consumers now get the native accessible keyboard / ARIA seek slider by default. No component API changes.
  • Widened the astro peerDependency to ^6.0.0 || ^7.0.0 for Astro 7 readiness. No runtime changes — the component is unaffected by the Astro 7 compiler / Vite 8 (Rolldown) upgrade.

Initial release.

  • <WaveformPlayer> Astro component wrapping every option exposed by @arraypress/waveform-player 1.6.x as a typed prop:
    • Audio source props (url, audioMode, preload)
    • Waveform visualisation props (waveformStyle, height, samples, barWidth, barSpacing, waveform)
    • Colour props (colorPreset, waveformColor, progressColor, buttonColor, buttonHoverColor, textColor, textSecondaryColor, backgroundColor, borderColor)
    • Playback control props (playbackRate, showPlaybackSpeed, playbackRates)
    • UI toggle props (showControls, showInfo, showTime, showHoverTime, showBPM, buttonAlign)
    • Marker props (markers, showMarkers)
    • Content metadata props (title, subtitle, artwork, album)
    • Behaviour flags (autoplay, singlePlay, playOnSeek, enableMediaSession)
    • Icon props (playIcon, pauseIcon)
  • Astro-specific lazy prop that switches the init attribute to data-waveform-player-lazy and ships a single deduplicated IntersectionObserver for grids of many previews.
  • Astro-specific id, class, and style pass-throughs.
  • Public TypeScript types: WaveformPlayerProps, WaveformStyle, WaveformMarker, WaveformPeaks, ColorPreset, AudioMode, AudioPreload, ButtonAlign.
  • Ambient declaration for window.WaveformPlayer to type consumer scripts that reach for the global.
  • Vitest suite (29 tests) covering attribute mapping, omission semantics, JSON serialisation for array props, lazy-mount script presence, and pass-through props.
  • Documentation: full prop reference, setup guide, seven usage examples (examples/basic.astro).
  • Public types are now adopted from the core @arraypress/waveform-player (v1.8.0+), which ships a hand-authored index.d.ts. The shared option surface (WaveformStyle, ColorPreset, AudioMode, AudioPreload, ButtonAlign, WaveformMarker, WaveformPeaks) is re-exported from the core, and WaveformPlayerProps now extends the core’s WaveformPlayerOptions instead of re-declaring every field. The core is the single source of truth, so the wrapper’s types can no longer drift out of sync. Bumped the @arraypress/waveform-player peer (and dev) dependency to ^1.8.0.
  • Callback props (onLoad, onPlay, onPause, onEnd, onTimeUpdate, onError) and the WaveformPlayerHandle.instance accessor are now typed with the core’s WaveformPlayer class instead of unknown.
  • accessibleSeek, seekLabel, barRadius, and gradient-array waveform / progress colours (string[]) are now exposed as typed props — picked up for free by extending the core options and wired through to the underlying player.
  • Deleted src/core-module-shim.d.ts, the loose ambient declare module '@arraypress/waveform-player' shim that only existed while the core had no shipped types.
  • Bumped the @arraypress/waveform-player peer (and dev) dependency to ^1.7.2. Consumers now get the native accessible keyboard / ARIA seek slider by default. No component API changes.

Initial release.

  • <WaveformPlayer> React component wrapping every option exposed by @arraypress/waveform-player 1.6.x as a typed prop:
    • Audio source (url, audioMode, preload)
    • Waveform visualisation (waveformStyle, height, samples, barWidth, barSpacing, waveform)
    • Colours (colorPreset, waveformColor, progressColor, buttonColor, buttonHoverColor, textColor, textSecondaryColor, backgroundColor, borderColor)
    • Playback (playbackRate, showPlaybackSpeed, playbackRates)
    • UI toggles (showControls, showInfo, showTime, showHoverTime, showBPM, buttonAlign)
    • Markers (markers, showMarkers)
    • Metadata (title, subtitle, artwork, album)
    • Behaviour (autoplay, singlePlay, playOnSeek, enableMediaSession)
    • Icons (playIcon, pauseIcon)
  • Callback props (onLoad, onPlay, onPause, onEnd, onTimeUpdate, onError) that map to the library’s same-named option fields. Callbacks are deliberately NOT in the effect dep array, so a parent re-rendering with new inline functions doesn’t tear the player down.
  • React-specific extras: id, className, style, and ref forwarding via WaveformPlayerHandle.
  • WaveformPlayerHandle imperative API on the forwarded ref — play(), pause(), togglePlay(), seekTo(), seekToPercent(), setVolume(), setPlaybackRate(), setPlayingState(), setProgress(), loadTrack(), plus the raw instance.
  • SSR / RSC safe: the core library is loaded via dynamic import('@arraypress/waveform-player') inside the effect so the browser-only audio surface never runs server-side.
  • Identity-prop re-mount: when any library-construction prop changes (url, audioMode, etc.), the wrapper destroys the existing instance and creates a new one with the updated options. Simpler and more correct than diffing every option + calling granular updaters.
  • Public TypeScript types: WaveformPlayerProps, WaveformPlayerHandle, WaveformStyle, WaveformMarker, WaveformPeaks, ColorPreset, AudioMode, AudioPreload, ButtonAlign.
  • Ambient module shim for @arraypress/waveform-player so the wrapper typechecks cleanly until the core library ships its own .d.ts.
  • Vitest test suite (17 tests, jsdom + @testing-library/react) covering mount, unmount destroy, option pass-through, callback forwarding, identity-prop re-mount, callback-churn protection, ref forwarding, and the full imperative handle surface. The core library is mocked at the module boundary because jsdom has no Web Audio API.
  • Dual ESM (dist/index.js) + CJS (dist/index.cjs) build via tsup. .d.ts for both. React + the core library are externalised so they resolve to the consumer’s copies.
  • README with full prop reference, seven usage patterns, and the imperative-ref control example. examples/basic.tsx with seven copy-paste-ready snippets.

Initial release.

  • <WaveformPlayer> Vue 3 component wrapping every option exposed by @arraypress/waveform-player as a typed prop:
    • Audio source (url, src alias, audioMode, preload)
    • Waveform visualisation (waveformStyle, height, samples, barWidth, barSpacing, barRadius, waveform)
    • Colours (colorPreset, waveformColor, progressColor, buttonColor, buttonHoverColor, textColor, textSecondaryColor, backgroundColor, borderColor — strings or string[] gradients)
    • Playback (playbackRate, showPlaybackSpeed, playbackRates)
    • UI toggles (showControls, showInfo, showTime, showHoverTime, showBPM, buttonAlign, accessibleSeek, seekLabel, errorText)
    • Markers (markers, showMarkers)
    • Metadata (title, subtitle, artwork, album)
    • Behaviour (autoplay, singlePlay, playOnSeek, enableMediaSession)
    • Icons (playIcon, pauseIcon)
  • Lifecycle emits (load, play, pause, end, timeupdate, error), each forwarding the live WaveformPlayer instance. Wired through Vue’s stable emit, so listeners can change without tearing the player down.
  • Imperative API exposed via a template ref (WaveformPlayerExpose): play(), pause(), togglePlay(), seekTo(), seekToPercent(), setVolume(), setPlaybackRate(), setPlayingState(), setProgress(), loadTrack(), plus the raw instance.
  • class, style, and id fall through to the host element via Vue’s attribute inheritance; the base class wfp-host always applies.
  • SSR / Nuxt safe: the core library is loaded via dynamic import('@arraypress/waveform-player') inside onMounted so the browser-only audio surface never runs server-side.
  • Identity-prop re-mount: when any library-construction prop changes, the wrapper destroys the existing instance and creates a new one with the updated options. A monotonic mount token discards any in-flight async import that a newer mount (or unmount) has superseded.
  • Public types are adopted from the core @arraypress/waveform-player (WaveformStyle, ColorPreset, AudioMode, AudioPreload, ButtonAlign, WaveformMarker, WaveformPeaks), re-exported here so the wrapper’s types can never drift out of sync. WaveformPlayerProps is derived from the core’s WaveformPlayerOptions.
  • Dual ESM (dist/index.js) + CJS (dist/index.cjs) build via tsup, with .d.ts for both. Vue + the core library are externalised so they resolve to the consumer’s copies.
  • Vitest test suite (jsdom + @vue/test-utils) covering mount, option pass-through, the src → url alias, boolean-prop omission, emit forwarding, destroy-on-unmount, identity-prop re-mount, and the exposed imperative API. The core is mocked at the module boundary because jsdom has no Web Audio API.
  • README with full prop reference, seven usage patterns, and the imperative-ref control example. examples/basic.vue with seven copy-paste-ready snippets.

Initial release.

  • <WaveformPlayer> Svelte 5 component (built with runes) wrapping every option exposed by @arraypress/waveform-player as a typed prop:
    • Audio source (url, src alias, audioMode, preload)
    • Waveform visualisation (waveformStyle, height, samples, barWidth, barSpacing, barRadius, waveform)
    • Colours (colorPreset, waveformColor, progressColor, buttonColor, buttonHoverColor, textColor, textSecondaryColor, backgroundColor, borderColor — strings or string[] gradients)
    • Playback (playbackRate, showPlaybackSpeed, playbackRates)
    • UI toggles (showControls, showInfo, showTime, showHoverTime, showBPM, buttonAlign, accessibleSeek, seekLabel, errorText)
    • Markers (markers, showMarkers)
    • Metadata (title, subtitle, artwork, album)
    • Behaviour (autoplay, singlePlay, playOnSeek, enableMediaSession)
    • Icons (playIcon, pauseIcon)
  • Lowercase lifecycle callback props (onload, onplay, onpause, onend, ontimeupdate, onerror), each forwarding the live WaveformPlayer instance. Wired through reactive closures, so changing a handler never tears the player down.
  • Imperative API exported by the component instance (reachable via bind:this): play(), pause(), togglePlay(), seekTo(), seekToPercent(), setVolume(), setPlaybackRate(), setPlayingState(), setProgress(), loadTrack(), and getInstance().
  • class, style, id, and other element attributes fall through to the host element via ...rest; the base class wfp-host always applies.
  • SSR / SvelteKit safe: the core library is loaded via dynamic import('@arraypress/waveform-player') inside a browser-only $effect, so the audio surface never runs server-side.
  • Identity-prop re-mount: a single $effect reads every construction prop, so changing any of them destroys the existing instance and creates a new one. A monotonic mount token discards any in-flight async import that a newer mount (or unmount) has superseded.
  • Public types adopted from the core @arraypress/waveform-player (WaveformStyle, ColorPreset, AudioMode, AudioPreload, ButtonAlign, WaveformMarker, WaveformPeaks), re-exported here so the wrapper’s types can never drift. WaveformPlayerProps is derived from the core’s WaveformPlayerOptions.
  • Built with svelte-package (dist/ ships the preprocessed .svelte + generated .d.ts). Svelte + the core library are peer dependencies.
  • Vitest test suite (jsdom + @testing-library/svelte) covering mount, option pass-through, the src → url alias, boolean-prop omission, callback forwarding, destroy-on-unmount, identity-prop re-mount, and the exported imperative API. The core is mocked at the module boundary because jsdom has no Web Audio API.
  • README with full prop reference, seven usage patterns, and the imperative bind:this control example. examples/Basic.svelte with seven copy-paste-ready snippets.
  • Sync WaveformBarConfig to the bar’s mode API: layoutmode ('waveform' | 'classic'), remove maxWidth, add showShuffle / shuffle. Matches @arraypress/waveform-bar 1.7.0.
  • Bumped the @arraypress/waveform-player peer (and dev) dependency to ^1.7.2, which adds the native accessible keyboard / ARIA seek slider to the underlying player. No component API changes.
  • Widened the astro peerDependency to ^6.0.0 || ^7.0.0 for Astro 7 readiness. No runtime changes — the component is unaffected by the Astro 7 compiler / Vite 8 (Rolldown) upgrade.
  • <WaveformBarTrigger>’s default pause-icon SVG no longer carries an inline style="display:none;". The previous value beat the core library’s class-based toggle (.wb-icon-swap.wb-playing .wb-show-pause { display: inline; }), leaving the pause icon permanently hidden once a track started playing. The library’s own CSS already covers the initial-hidden state via .wb-icon-swap .wb-show-pause { display: none; }, so the inline style is redundant as well as harmful.
  • Added two regression tests pinning the no-inline-display contract so the bug can’t return.

Initial release.

  • <WaveformBar> — singleton mount component for the persistent bottom bar. Renders a transition:persist host div and an inline init script that calls window.WaveformBar.init(config) on every astro:page-load. Relocates the library’s .waveform-bar element into the persist host so view transitions keep it onscreen between navigations.
  • Typed WaveformBarConfig covering every option window.WaveformBar.init() accepts:
    • Persistence: persist, autoResume, continuous, repeat
    • UI toggles: showQueue, showPrevNext, showRepeat, showVolume, showMute, showTime, showTrackLink, showMeta, maxMeta
    • Theming: theme, defaultArtwork
    • Waveform visualisation: waveformStyle, waveformHeight, barWidth, barSpacing, waveformColor, progressColor, markerColor
    • Volume + persistence keys: volume, storageKey
    • Server-side actions: actions.favorite / actions.cart with endpoint URL + optional method / headers
  • <WaveformBarTrigger> — polymorphic click trigger. Renders a <button> by default; override via as="a" | "div" | "span". Emits the full data-wb-* attribute contract:
    • Track identity: url, id (falls back to url), title, artist, album, artwork, link
    • Display chips: duration, bpm, key, meta
    • Audio data: waveform (peaks array, URL, or inline JSON), markers (DJ-mode chapters)
    • Initial state: favorited, inCart
    • Behaviour: mode='play' | 'queue', href (when as="a"), ariaLabel, class, noDefaultIcons
  • Default slot ships the play / pause SVG pair the core library toggles via wb-show-play / wb-show-pause classes. Passing children replaces them.
  • Auto-generated aria-label when one isn’t supplied — Play {title} for play triggers, Add {title} to queue for queue triggers.
  • Public TypeScript types: WaveformBarProps, WaveformBarConfig, WaveformBarTriggerProps, WaveformBarTrackData, WaveformBarMarker, WaveformBarActions, WaveformBarAction, WaveformBarTheme, RepeatMode, TriggerMode, WaveformStyle.
  • Ambient declaration for window.WaveformBar covering the full public surface (play, pause, next, previous, addToQueue, setVolume, setRepeat, seekToMarker, etc.).
  • Vitest suite of 46 tests via Astro’s experimental_AstroContainer covering attribute mapping, omission semantics, JSON serialisation for arrays, polymorphic as, default-slot behaviour, aria-label generation, and a kitchen-sink scenario.
  • Documentation: full README with setup, prop tables, every usage pattern, and the waveformbar:* custom-event API. examples/basic.astro reference page with six demonstrations.
  • Sync WaveformBarConfig to the bar’s mode API: layoutmode ('waveform' | 'classic'), remove maxWidth, add showShuffle / shuffle. Matches @arraypress/waveform-bar 1.7.0.
  • Bumped the @arraypress/waveform-player peer (and dev) dependency to ^1.7.2 for the native accessible keyboard / ARIA seek slider. No component API changes.

Initial release.

  • <WaveformBar> — singleton mount component for the persistent bottom bar. Renders a persist host <div> and runs window.WaveformBar.init(config) inside an effect. Tears down on unmount (StrictMode-safe) and re-inits only when the structural shape of the config changes — passing a fresh object reference with the same shape doesn’t trigger churn. Relocates the bar element into the persist host so route changes / re-renders don’t tear it down.
  • <WaveformBarTrigger> — polymorphic click trigger. Defaults to <button>; override via as="a" | "div" | "span". Emits the full data-wb-* attribute contract:
    • Track identity: url, id, title, artist, album, artwork, link
    • Display chips: duration, bpm, musicalKey, meta
    • Audio data: waveform (peaks array, URL, or inline JSON), markers (DJ-mode chapters)
    • Initial state: favorited, inCart
    • Behaviour: mode='play' | 'queue', href (when as="a"), aria-label, className, style, noDefaultIcons, children
  • Default play / pause SVG pair rendered as the trigger’s children when no custom content is passed. The library’s wb-icon-swap CSS toggles them based on the active track state.
  • Auto-generated aria-label when one isn’t supplied — Play {title} for play triggers, Add {title} to queue for queue triggers.
  • Public TypeScript types: WaveformBarProps, WaveformBarConfig, WaveformBarTriggerProps, WaveformBarTrackData, WaveformBarMarker, WaveformBarActions, WaveformBarAction, WaveformBarTheme, RepeatMode, TriggerMode, WaveformStyle.
  • Ambient module shim for @arraypress/waveform-bar and @arraypress/waveform-player so the wrapper typechecks cleanly until the core libraries ship .d.ts of their own.
  • SSR / RSC safe: the core library loads via dynamic import() inside the effect, so the browser-only audio surface never evaluates server-side.
  • 46 Vitest tests via jsdom + @testing-library/react:
    • 28 tests for <WaveformBarTrigger> rendering + attribute mapping (no module mocking needed)
    • 18 tests for <WaveformBar> lifecycle (window global mocked since jsdom has no Web Audio)
  • Dual ESM (dist/index.js) + CJS (dist/index.cjs) build via tsup. .d.ts for both. React + the two core libraries externalised so they resolve to the consumer’s copies.
  • README with full prop reference, seven usage patterns, and the waveformbar:* custom-event API documented as the callback alternative.
  • examples/basic.tsx with seven copy-paste-ready snippets.

Initial release.

  • <WaveformBar> — singleton mount for the persistent bottom bar. Render once in your root layout. On mount it dynamically imports @arraypress/waveform-bar (SSR-safe) and calls window.WaveformBar.init(config); re-inits when the config’s structural shape changes (compared via JSON.stringify, so a fresh object with the same shape doesn’t churn); relocates the bar element into a persist host <div>; and calls destroy() on unmount. config, persist, hostId props; class / style fall through to the host (base class wb-host).
  • <WaveformBarTrigger> — polymorphic (as="button" | "a" | "div" | "span", default button) click trigger that emits the data-wb-* attribute contract the core library scans for. Maps track-data props (url, id, title, artist, album, artwork, link, duration, bpm, musicalKey, meta, waveform, markers, favorited, inCart) to attributes (arrays JSON-encoded; absent props emit no attribute). mode="play" | "queue", href (for as="a"), noDefaultIcons. Renders default play/pause SVGs unless slot content is provided. Auto-generates an aria-label from title. class, native listeners (@click), and other attributes fall through; the base class wb-icon-swap is always applied.
  • No lifecycle callback props — the bar dispatches every state change as a bubbling waveformbar:* CustomEvent; listen with addEventListener. This keeps callbacks from forcing a bar re-init (matching the React wrapper).
  • Public types mirroring the core surface: WaveformBarConfig, WaveformBarProps, WaveformBarTriggerProps, WaveformBarTrackData, WaveformBarMarker, WaveformBarActions, WaveformBarAction, WaveformBarTheme, RepeatMode, TriggerMode, WaveformStyle.
  • Dual ESM + CJS build via tsup with .d.ts for both. Vue + the core libraries are peer dependencies.
  • Vitest test suite (jsdom + @vue/test-utils, 13 tests) covering the singleton’s host render + init / re-init / destroy lifecycle, and the trigger’s data-wb-* contract, polymorphism, modes, default-icon handling, class merge, and click forwarding.

Initial release.

  • <WaveformBar> — singleton mount (Svelte 5 runes) for the persistent bottom bar. Render once in your root layout. A browser-only $effect dynamically imports @arraypress/waveform-bar (SSR-safe) and calls window.WaveformBar.init(config); a $derived config key re-inits only when the config’s structural shape (or persist) changes; the bar element is relocated into a persist host <div>; destroy() is called on unmount. config, persist, hostId props; class / attributes fall through to the host (base class wb-host).
  • <WaveformBarTrigger> — polymorphic (as="button" | "a" | "div" | "span" via <svelte:element>, default button) click trigger that emits the data-wb-* attribute contract the core library scans for. Maps track-data props (url, id, title, artist, album, artwork, link, duration, bpm, musicalKey, meta, waveform, markers, favorited, inCart) to attributes (arrays JSON-encoded; absent props emit no attribute). mode="play" | "queue", href (for as="a"), noDefaultIcons. Renders default play/pause SVGs unless children are slotted. Auto-generates an aria-label from title. class, native listeners (onclick), and other attributes fall through via ...rest; the base class wb-icon-swap is always applied.
  • No lifecycle callback props — the bar dispatches every state change as a bubbling waveformbar:* CustomEvent; listen with addEventListener.
  • Public types mirroring the core surface: WaveformBarConfig, WaveformBarProps, WaveformBarTriggerProps, WaveformBarTrackData, WaveformBarMarker, WaveformBarActions, WaveformBarAction, WaveformBarTheme, RepeatMode, TriggerMode, WaveformStyle.
  • Built with svelte-package (dist/ ships the preprocessed .svelte + generated .d.ts). Svelte + the core libraries are peer dependencies.
  • Vitest test suite (jsdom + @testing-library/svelte, 12 tests) covering the singleton’s host render + init / re-init / no-churn / destroy lifecycle, and the trigger’s data-wb-* contract, polymorphism, modes, default-icon handling, class merge, and click forwarding.
  • <WaveformPlaylist> Astro component wrapping @arraypress/waveform-playlist. Renders the library’s nested markup contract — a [data-waveform-playlist] container with one [data-track] child per track and one [data-chapter] child per chapter — from a single typed tracks array.
  • Typed props for the playlist’s own options:
    • layout ('list' | 'minimal'), continuous, expandChapters, showDuration, showChapterMarkers (boolean | null), chapterMarkerColor, showPlayState.
  • Typed pass-through of the WaveformPlayer options the playlist forwards to its embedded player — waveformStyle, height, samples, barWidth, barSpacing, barRadius, colorPreset, the colour options (including gradient-array waveformColor / progressColor), playbackRate, showPlaybackSpeed, playbackRates, showControls, showInfo, showTime, showHoverTime, showBPM, bpm, buttonAlign, buttonStyle, accessibleSeek, seekLabel, errorText, showMarkers, autoplay, singlePlay, playOnSeek, enableMediaSession, preload, playIcon, pauseIcon. The per-track content fields (url, title, subtitle, artwork, album, markers) live on each tracks entry instead, and the player’s layout / audioMode are intentionally not exposed (the playlist owns data-layout and always drives a self-mode player).
  • A typed tracks array (WaveformPlaylistTrackInput[]) with per-track url, title, subtitle, artwork, album, duration, markers, and chapters ({ time, label, color? }).
  • Astro-specific lazy prop that switches the init attribute to data-waveform-playlist-lazy and ships a single deduplicated IntersectionObserver that promotes the playlist on viewport entry, plus a non-lazy astro:page-load re-init for Astro View Transitions.
  • Astro-specific id, class, and style pass-throughs (wfpl-host is always applied to the container).
  • Public TypeScript types derived from the two core packages so they never drift: WaveformPlaylistProps, WaveformPlaylistTrackInput, and re-exports of WaveformPlaylistOptions / WaveformPlaylistTrack / WaveformPlaylistChapter / WaveformPlaylistMarker (from the playlist core) and WaveformStyle / WaveformMarker / WaveformPeaks / ColorPreset / AudioMode / AudioPreload / ButtonAlign (from the player core).
  • Vitest suite covering container option serialisation, omission semantics, JSON serialisation for array props, per-track and per-chapter rendering, lazy-mount and View-Transitions script presence, and the Astro extras.
  • Documentation: full prop reference, setup guide, and usage examples (examples/basic.astro).

Initial release.

  • <WaveformPlaylist> React component wrapping @arraypress/waveform-playlist:
    • A declarative, required tracks array (WaveformPlaylistTrackInput[]) rendered into the [data-track] / [data-chapter] child markup the playlist constructor parses on mount. Each track accepts url, title, subtitle, artwork, album, duration, markers, and chapters ({ time, label, color? }, where time is a seconds number or a 'M:SS' string).
    • Playlist options as typed props: layout ('list' | 'minimal'), continuous, expandChapters, showDuration, showChapterMarkers, chapterMarkerColor, showPlayState.
    • Pass-through player options forwarded to the embedded player (waveformStyle, height, samples, barWidth, barSpacing, barRadius, colours, playbackRate, showPlaybackSpeed, playbackRates, UI toggles, accessibleSeek, seekLabel, errorText, behaviour flags, icons, audioMode, preload).
    • React-specific extras: id, className, style, and ref forwarding via WaveformPlaylistHandle.
  • WaveformPlaylistHandle imperative API on the forwarded ref — selectTrack(), seekToChapter(), nextTrack(), previousTrack(), getPlayer(), getCurrentTrackIndex(), getTracks(), plus the raw instance escape hatch.
  • SSR / RSC safe: the playlist library is loaded via dynamic import('@arraypress/waveform-playlist') inside the effect so the browser-only audio surface never runs server-side.
  • Identity-prop re-mount: when any construction prop changes — the serialised tracks, layout, continuous, colours, sizing, etc. — the wrapper destroys the existing instance and creates a new one against the freshly-rendered markup. DOM-only props (className, style, id) do not trigger a re-mount.
  • The host container deliberately omits data-waveform-playlist so the library’s global auto-init never double-mounts on top of the instance the wrapper creates explicitly.
  • Public TypeScript types: WaveformPlaylistProps, WaveformPlaylistHandle, WaveformPlaylistTrackInput, WaveformPlaylistChapterInput, plus the re-exported core types (WaveformPlaylistOptions, WaveformPlaylistTrack, WaveformPlaylistChapter, WaveformPlaylistMarker, WaveformStyle, WaveformMarker, WaveformPeaks, ColorPreset, AudioMode, AudioPreload, ButtonAlign).
  • Vitest test suite (jsdom + @testing-library/react) covering track / chapter markup rendering, mount, unmount destroy, option pass-through, identity-prop re-mount, ref forwarding, and the full imperative handle surface. The core library is mocked at the module boundary because jsdom has no Web Audio API.
  • Dual ESM (dist/index.js) + CJS (dist/index.cjs) build via tsup, with .d.ts for both. React and both @arraypress/waveform-* cores are externalised so they resolve to the consumer’s copies.
  • README with full prop reference and usage patterns, and examples/basic.tsx with seven copy-paste-ready snippets.
  • @arraypress/waveform-playlist ^1.3.0
  • @arraypress/waveform-player ^1.8.0
  • react ^18.0.0 || ^19.0.0

Initial release.

  • <WaveformPlaylist> Vue 3 component wrapping @arraypress/waveform-playlist:
    • Declarative tracks prop (with optional per-track chapters and markers), rendered into the [data-track] / [data-chapter] markup the playlist constructor parses on mount.
    • Playlist options as typed props: layout ('list' | 'minimal'), continuous, expandChapters, showDuration, showChapterMarkers, chapterMarkerColor, showPlayState.
    • The full pass-through player-option surface (waveform style, sizing, colours, playback, UI toggles, accessibility, icons) — inherited from the core WaveformPlayerOptions via Omit<>, minus per-track content fields (which come from tracks).
  • Imperative navigation API exposed via a template ref (WaveformPlaylistExpose): selectTrack(), seekToChapter(), nextTrack(), previousTrack(), getPlayer(), getCurrentTrackIndex(), getTracks(), plus the raw instance.
  • class, style, and id fall through to the host element via Vue’s attribute inheritance; the base class wfp-host always applies.
  • SSR / Nuxt safe: the core library is loaded via dynamic import('@arraypress/waveform-playlist') inside onMounted.
  • Identity-prop re-mount: any construction-prop change (a serialised tracks change, layout, options, …) destroys and rebuilds the instance. A monotonic mount token discards a superseded in-flight import; the watcher uses flush: 'post' so the fresh markup is in the DOM before the constructor re-parses it.
  • No lifecycle emits — the playlist owns the embedded player’s callbacks internally (matching the React wrapper). Observe playback via the embedded player from getPlayer().
  • Public types adopted from both cores (@arraypress/waveform-playlist + @arraypress/waveform-player), re-exported so they can never drift.
  • Dual ESM + CJS build via tsup with .d.ts for both. Vue + both cores are peer dependencies.
  • Vitest test suite (jsdom + @vue/test-utils) covering host + track markup rendering, option mapping (tracks excluded), boolean-prop omission, destroy-on-unmount, identity-prop re-mount, and the exposed navigation API. The core is mocked at the module boundary.

Initial release.

  • <WaveformPlaylist> Svelte 5 component (built with runes) wrapping @arraypress/waveform-playlist:
    • Declarative tracks prop (with optional per-track chapters and markers), rendered into the [data-track] / [data-chapter] markup the playlist constructor parses on mount.
    • Playlist options as typed props: layout ('list' | 'minimal'), continuous, expandChapters, showDuration, showChapterMarkers, chapterMarkerColor, showPlayState.
    • The full pass-through player-option surface (waveform style, sizing, colours, playback, UI toggles, accessibility, icons) — inherited from the core WaveformPlayerOptions via Omit<>, minus per-track content fields (which come from tracks).
  • Imperative navigation API exported by the component instance (reachable via bind:this): selectTrack(), seekToChapter(), nextTrack(), previousTrack(), getPlayer(), getCurrentTrackIndex(), getTracks(), and getInstance().
  • class, style, id, and other element attributes fall through to the host element via ...rest; the base class wfp-host always applies.
  • SSR / SvelteKit safe: the core library is loaded via dynamic import('@arraypress/waveform-playlist') inside a browser-only $effect.
  • Identity-prop re-mount: a single $effect reads JSON.stringify(tracks)
    • every construction option, so any change destroys and rebuilds the instance over the freshly-rendered markup. A monotonic mount token discards a superseded in-flight import.
  • Public types adopted from both cores (@arraypress/waveform-playlist + @arraypress/waveform-player), re-exported so they can never drift.
  • Built with svelte-package (dist/ ships the preprocessed .svelte + generated .d.ts). Svelte + both cores are peer dependencies.
  • Vitest test suite (jsdom + @testing-library/svelte) covering host + track markup rendering, option mapping (tracks excluded), boolean-prop omission, destroy-on-unmount, identity-prop re-mount, and the exported navigation API. The core is mocked at the module boundary.