Skip to content

Framework wrappers

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

  • crossOrigin prop. Exposes the option added in @arraypress/waveform-player@1.23.0, emitted as data-cross-origin ('anonymous' | 'use-credentials'). Omitted by default so the player behaves like a native <audio> and never forces a CORS request that would break CDN media without Access-Control-Allow-Origin.
  • buttonRadius and artworkPosition props. Exposes the two options added in @arraypress/waveform-player 1.22.0: buttonRadius sets the play button’s corner radius (0 for square, or any CSS length), and artworkPosition ('info' | 'button') chooses whether the cover renders in the info row or becomes the play button itself.

    Both prop types already flowed through automatically, since the props derive from the core’s WaveformPlayerOptions — but the data-* emission is written by hand, so until now they would have type-checked and then silently done nothing. Tests now cover the mapping for exactly that reason.

    The peer range stays ^1.20.0: the props only appear once the consumer’s own core is on 1.22.0, so nothing breaks on an older one.

  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.
  • BREAKING: the six DOM-chrome colour props — buttonColor, buttonHoverColor, textColor, textSecondaryColor, backgroundColor, and borderColor — are gone (the core library moved this chrome to CSS variables). Theme the button and text via --wfp-button-color, --wfp-text-color, --wfp-text-secondary-color, etc. in your own CSS instead. waveformColor, progressColor, colorPreset, and waveformGradient remain props.
  • 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, artist, 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).
  • crossOrigin prop. Exposes the option added in @arraypress/waveform-player@1.23.0: sets the CORS mode of the underlying <audio> ('anonymous' | 'use-credentials'). Omitted from the options bag by default so the player behaves like a native <audio> and never forces a CORS request that would break CDN media without Access-Control-Allow-Origin.
  • buttonRadius and artworkPosition props. Exposes the two options added in @arraypress/waveform-player 1.22.0: buttonRadius sets the play button’s corner radius (0 for square, or any CSS length), and artworkPosition ('info' | 'button') chooses whether the cover renders in the info row or becomes the play button itself.

    Both prop types already flowed through automatically, since the props derive from the core’s WaveformPlayerOptions — but the options bag is written by hand, so until now they would have type-checked and then silently done nothing. Tests now cover the mapping for exactly that reason.

    The peer range stays ^1.20.0: the props only appear once the consumer’s own core is on 1.22.0, so nothing breaks on an older one.

  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.
  • 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, artist, 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.
  • crossOrigin prop. Exposes the option added in @arraypress/waveform-player@1.23.0: sets the CORS mode of the underlying <audio> ('anonymous' | 'use-credentials'). Declared as a runtime prop and omitted from the options bag by default so the player behaves like a native <audio> and never forces a CORS request that would break CDN media without Access-Control-Allow-Origin.
  • buttonRadius and artworkPosition props. Exposes the two options added in @arraypress/waveform-player 1.22.0: buttonRadius sets the play button’s corner radius (0 for square, or any CSS length), and artworkPosition ('info' | 'button') chooses whether the cover renders in the info row or becomes the play button itself.

    Both prop types already flowed through automatically, since the props derive from the core’s WaveformPlayerOptions — but the options mapping is written by hand, so until now they would have type-checked and then silently done nothing. Tests now cover the mapping for exactly that reason.

    The peer range stays ^1.20.0: the props only appear once the consumer’s own core is on 1.22.0, so nothing breaks on an older one.

  • buttonSize accepts a number again. The prop was declared type: String, so :button-size="64" failed Vue’s runtime type check and warned, even though the core accepts a number (px) or a unit string. It now declares [String, Number], matching the core. buttonRadius takes the same pair.
  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.

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, waveformGradient — strings or string[] gradients). DOM chrome (button, title, meta text) is themed via CSS variables (--wfp-button-color, --wfp-text-color, --wfp-text-secondary-color), not JS options.
    • Playback (playbackRate, showPlaybackSpeed, playbackRates)
    • UI toggles (showControls, showInfo, showTime, showHoverTime, showBPM, buttonAlign, accessibleSeek, seekLabel, errorText)
    • Markers (markers, showMarkers)
    • Metadata (title, artist, 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.
  • crossOrigin prop. Exposes the option added in @arraypress/waveform-player@1.23.0: sets the CORS mode of the underlying <audio> ('anonymous' | 'use-credentials'). Omitted from the options bag by default so the player behaves like a native <audio> and never forces a CORS request that would break CDN media without Access-Control-Allow-Origin.
  • buttonRadius and artworkPosition props. Exposes the two options added in @arraypress/waveform-player 1.22.0: buttonRadius sets the play button’s corner radius (0 for square, or any CSS length), and artworkPosition ('info' | 'button') chooses whether the cover renders in the info row or becomes the play button itself.

    Both prop types already flowed through automatically, since the props derive from the core’s WaveformPlayerOptions — but the options mapping is written by hand, so until now they would have type-checked and then silently done nothing. Tests now cover the mapping for exactly that reason.

    The peer range stays ^1.20.0: the props only appear once the consumer’s own core is on 1.22.0, so nothing breaks on an older one.

  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.

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 — strings or string[] gradients). DOM chrome (button, title, meta text) is themed via CSS variables (--wfp-button-color, --wfp-text-color, --wfp-text-secondary-color), not JS options.
    • Playback (playbackRate, showPlaybackSpeed, playbackRates)
    • UI toggles (showControls, showInfo, showTime, showHoverTime, showBPM, buttonAlign, accessibleSeek, seekLabel, errorText)
    • Markers (markers, showMarkers)
    • Metadata (title, artist, 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.
  • crossOrigin config key. Added to WaveformBarConfig and forwarded verbatim to window.WaveformBar.init(). Requires @arraypress/waveform-bar@^1.11.0 for it to reach the embedded player.
  • Accept the new localizable player-string keys — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — in the bar config; they are forwarded to the embedded player. Requires @arraypress/waveform-bar@^1.10.0.
  • 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.
  • crossOrigin config key. Added to WaveformBarConfig and forwarded verbatim to window.WaveformBar.init(). Requires @arraypress/waveform-bar@^1.11.0 for it to reach the embedded player.
  • Accept the new localizable player-string keys — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — in the bar config; they are forwarded to the embedded player. Requires @arraypress/waveform-bar@^1.10.0.
  • 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.
  • crossOrigin config key. Added to WaveformBarConfig and forwarded verbatim to window.WaveformBar.init(). Requires @arraypress/waveform-bar@^1.11.0 for it to reach the embedded player.
  • Accept the new localizable player-string keys — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — in the bar config; they are forwarded to the embedded player. Requires @arraypress/waveform-bar@^1.10.0.

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.
  • crossOrigin config key. Added to WaveformBarConfig and forwarded verbatim to window.WaveformBar.init(). Requires @arraypress/waveform-bar@^1.11.0 for it to reach the embedded player.
  • Accept the new localizable player-string keys — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — in the bar config; they are forwarded to the embedded player. Requires @arraypress/waveform-bar@^1.10.0.

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.
  • Forward the core player’s crossOrigin option to the embedded player. Added to the Astro.props destructure and emitted as the data-cross-origin container attribute. This option shipped across the rest of the waveform family in @arraypress/waveform-player@1.23.0 but was missed in the playlist wrappers, so it was previously accepted by the types and silently dropped at runtime. Requires @arraypress/waveform-player@^1.23.0 and @arraypress/waveform-playlist@^1.7.2 (the version that began forwarding it to each track’s player).
  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.
  • <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, artist, 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, artist, 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).
  • Forward the core player’s crossOrigin option to the embedded player. Forwarded in the constructor options builder and added to the remount useEffect dependency array. This option shipped across the rest of the waveform family in @arraypress/waveform-player@1.23.0 but was missed in the playlist wrappers, so it was previously accepted by the types and silently dropped at runtime. Requires @arraypress/waveform-player@^1.23.0 and @arraypress/waveform-playlist@^1.7.2 (the version that began forwarding it to each track’s player).
  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.

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, artist, 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
  • Forward the core player’s crossOrigin option to the embedded player. Added as a runtime props declaration (PropType<AudioCrossOrigin>), set in the options builder, and added to the remount watcher. This option shipped across the rest of the waveform family in @arraypress/waveform-player@1.23.0 but was missed in the playlist wrappers, so it was previously accepted by the types and silently dropped at runtime. Requires @arraypress/waveform-player@^1.23.0 and @arraypress/waveform-playlist@^1.7.2 (the version that began forwarding it to each track’s player).
  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.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.
  • Forward the core player’s crossOrigin option to the embedded player. Added to the $props() destructure (an undestructured prop falls into ...rest and is never forwarded) and set in the options builder. This option shipped across the rest of the waveform family in @arraypress/waveform-player@1.23.0 but was missed in the playlist wrappers, so it was previously accepted by the types and silently dropped at runtime. Requires @arraypress/waveform-player@^1.23.0 and @arraypress/waveform-playlist@^1.7.2 (the version that began forwarding it to each track’s player).
  • Forward the core player’s new localizable UI-string options — seekValueText, playPauseLabel, speedLabel, artworkAlt, and unknownTrackText — through to the underlying player. Requires @arraypress/waveform-player@^1.20.0.

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.