npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wandelbots/video-player

v1.3.1

Published

Wandelbots Nova video player: framework-agnostic HTML5 video component with custom chrome, themed via @wandelbots/design-tokens.

Readme

@wandelbots/video-player

Framework-agnostic HTML5 video player with custom Nova chrome. No MUI, no Tailwind, no streaming library — a <video> element plus a themed control bar, so it drops into @wandelbots/mui and @wandelbots/hui apps alike.

Install

pnpm add @wandelbots/video-player

Usage

import "@wandelbots/design-tokens/css"
import "@wandelbots/video-player/styles.css"

import { VideoPlayer } from "@wandelbots/video-player"

;<VideoPlayer
  src="https://cdn.example.com/tutorial.mp4"
  poster="https://cdn.example.com/tutorial.webp"
  sources={[
    { label: "1080p", url: ".../1080p.mp4", width: 1920 },
    { label: "720p", url: ".../720p.mp4", width: 1280 },
    { label: "480p", url: ".../480p.mp4", width: 854 },
  ]}
/>

Both CSS imports are required: @wandelbots/design-tokens/css supplies the --wb-* variables the player's own --wbvp-* variables resolve against.

Props

| Prop | Type | Description | | --- | --- | --- | | src | string | Used when sources is empty; the renditions take over as soon as it is not. | | sources | VideoSource[] | Selectable renditions, highest quality first (or annotated with width). | | poster | string | Poster image. | | captionUrl | string | WebVTT URL. An empty fallback track is rendered when omitted. | | playerId | string | id on the root element. | | className | string | Appended to the root class list. | | borderless | boolean | Fills the container and drops the border, radius and shadow. | | showSettings | boolean | Shows the Video Settings control for speed and quality selection. Defaults to true. | | initialAspectRatio | number | Defaults to 16 / 9 until metadata loads. | | labels | Partial<VideoPlayerLabels> | Overrides individual strings from the locale bundle. | | locale | string | BCP-47 tag selecting a bundled language (en, de). Defaults to English. | | icons | Partial<VideoPlayerIcons> | Overrides individual control icons. | | onPlay / onPause / onEnded | () => void | Playback event callbacks. Internal source-swap pause/play events are excluded from onPlay and onPause. | | onReady | (handle: VideoPlayerHandle) => void | Fires once on mount with a stable handle (seekToSeconds, scrollIntoView). A new callback identity does not refire it. | | onAspectRatioChange | (ratio: number) => void | Fires once the intrinsic ratio is known, and again only if it changes. |

Video Settings

Video Settings includes playback speeds from 0.5x to 2x. The selected speed remains active when changing renditions. Set showSettings={false} to hide the control entirely.

Quality selection

sources are sorted by descending width when annotated, otherwise used in the order given. "Auto" picks the first entry above 1200px viewport width, the second above 900px, and the last below that. Switching renditions preserves the current time and play state.

"Auto" re-evaluates whenever the viewport crosses one of those breakpoints, so resizing the window can swap the rendition mid-playback. It is not bandwidth-aware and this is not adaptive bitrate — for live or bandwidth-adaptive streams you want a different component. Picking a rendition by hand pins it until the consumer remounts the player. Either way the swap is invisible to onPlay and onPause, so analytics never see a resize as a fresh start.

Theming

Every color, radius and gradient is a --wbvp-* custom property declared on .wbvp-root, defaulting to a --wb-zero-gravity-* token where one exists. Override any of them on your own wrapper:

.my-player {
  --wbvp-letterbox: #000;
  --wbvp-radius: var(--wb-radius-lg);
}

The defaults assume the player sits on a dark surface: the control chrome, the letterbox fill and the scrim gradients are all light-on-dark. On a light background, override at least --wbvp-on-surface, --wbvp-letterbox and --wbvp-controls-gradient-*.

| Variable | Purpose | | --- | --- | | --wbvp-accent | Accent for the selected Video Settings option. | | --wbvp-accent-hover | Hover tint for icon-only buttons. | | --wbvp-accent-selected | Background of the selected quality option. | | --wbvp-slider-rail | Unfilled seek and volume slider track. | | --wbvp-slider-fill | Filled seek and volume slider track, and thumb border. | | --wbvp-slider-thumb-background | Seek and volume slider thumb fill. | | --wbvp-slider-radius | Seek and volume slider track and thumb radius. | | --wbvp-slider-aura | Seek and volume slider thumb hover and active aura. | | --wbvp-slider-focus-ring | Seek and volume slider thumb focus ring. | | --wbvp-surface | Root background behind the frame. | | --wbvp-border / --wbvp-radius / --wbvp-shadow | Framing of the root element. | | --wbvp-on-surface | Control foreground: icons and time labels. | | --wbvp-letterbox | Fill behind the video, visible when the ratio doesn't match. | | --wbvp-fullscreen-backdrop | Frame background in fullscreen. | | --wbvp-popover-bg / --wbvp-popover-border | Volume popover and quality menu. | | --wbvp-btn-bg / --wbvp-btn-border / --wbvp-btn-border-strong | Round control buttons. | | --wbvp-btn-hover-bg / --wbvp-btn-hover-border | Their hover state. | | --wbvp-focus-ring | box-shadow applied on :focus-visible. | | --wbvp-scrim-border / --wbvp-scrim-fill / --wbvp-scrim-hover-fill | Center play button. | | --wbvp-controls-gradient-from / --wbvp-controls-gradient-to | Scrim behind the control bar. |

Accessibility

Every control carries an aria-label from labels, both sliders report an aria-valuetext (1:35, 80%) instead of raw numbers, and a caption track is always present — an empty WebVTT fallback when captionUrl is omitted. The quality menu is a role="menu" of menuitemradio options with arrow-key, Home/End and Escape handling, and it hands focus back to its trigger when it closes.

Once the player surface has focus — click the video, or focus any control — these shortcuts apply:

| Key | Action | | --- | --- | | Space / k | Play or pause | | / | Skip 5 seconds | | / | Volume ±10% | | m | Mute or unmute | | f | Toggle fullscreen |

Keys a focused control needs itself are left alone: arrows adjust the slider you are on, Space activates the button you are on, and the quality menu keeps its own arrow keys while open. prefers-reduced-motion: reduce disables the control transitions and the smooth scroll performed by scrollIntoView().

Browser support

Current Chrome, Edge, Firefox and Safari, plus iOS Safari. Requires color-mix() and CSS custom properties.

iPhone Safari implements no element fullscreen, so the fullscreen button hands the video to the native iOS player instead; the custom chrome is not shown in that mode. Where neither element fullscreen nor the iOS fallback exists, the button is not rendered at all rather than shipping a dead control.

Playback is progressive HTTP: whatever formats the browser itself supports, typically MP4/H.264 everywhere and WebM outside Safari.

Internationalization

The player ships its own strings for English and German, so most consumers only pick a language:

<VideoPlayer src={src} locale="de" />

locale takes any BCP-47 tag. The region subtag is ignored (de-AT uses the German bundle) and a language the package has no strings for falls back to English, so passing whatever your i18n runtime holds is safe. LOCALES exports the bundles if you want to read or extend them.

There is still no i18n runtime in the package. For a language it doesn't ship, or to change single strings, pass labels — it merges over the locale bundle, so a partial override keeps the rest of the chosen language:

<VideoPlayer src={src} locale="de" labels={{ play: "Film starten" }} />

captionsSrcLang and captionsLabel describe the caption file, not the UI. They follow locale, which is right when captions match the interface language — override them through labels when it doesn't.