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

@streamslice/widget

v1.0.8

Published

Floating video player widget with Amazon IVS support

Readme

Widget

A floating video player library for embedding live streams on any website.

Features

  • Draggable and resizable floating window
  • Automatic playlist fetching by page URL
  • Playback controls (play/pause, volume, quality, fullscreen)
  • Dark and light themes
  • TypeScript support

Installation

NPM

npm install @streamslice/widget

CDN

<!-- Minified (recommended for production) -->
<script src="https://unpkg.com/@streamslice/widget"></script>

<!-- Or via jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@streamslice/widget"></script>

Usage

ES Modules

import { StreamSlice } from '@streamslice/widget';

const widget = new StreamSlice({
  autoPlay: true,
  muted: false,
  theme: 'dark',
  onReady: () => console.log('Widget ready'),
  onError: (error) => console.error('Error:', error),
});

// Initialize widget
widget.init();

UMD (Browser)

<script src="https://unpkg.com/@streamslice/widget"></script>
<script>
  const widget = new StreamSlice.StreamSlice({
    autoPlay: true,
    theme: 'dark',
  });
  
  widget.init();
</script>

Demo Mode

Demo mode renders a looping muted YouTube video in place of the live IVS stream and adds an interactive fake chat panel below the player. The widget skips the playlist API entirely, so you can preview the UI on any page without configuring a stream.

import { StreamSlice } from '@streamslice/widget';

const widget = new StreamSlice({
  demo: true,
  demoVideoId: 'aqz-KE-bpKQ', // required when demo is true
  theme: 'dark',
  onDemoChatMessage: (msg) => console.log(msg.kind, msg.author, msg.message),
});

widget.init();

UMD usage:

<script src="https://unpkg.com/@streamslice/widget"></script>
<script>
  new StreamSlice.StreamSlice({ demo: true, demoVideoId: 'aqz-KE-bpKQ' }).init();
</script>

Notes:

  • demoVideoId is required when demo is true. If omitted, onError fires with { code: 'DEMO_CONFIG' } and the widget shows a no-stream state.
  • The quality selector UI is hidden in demo mode (YouTube handles adaptive quality).
  • The live badge is hidden in demo mode.
  • Fullscreen covers the entire widget (video + chat) instead of just the video container.
  • Volume, mute, play/pause, close, drag, and resize controls all work against the YouTube player.
  • Custom scripts via demoChatScript replace the built-in script entirely. Omit it to use the default loop.

Configuration

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | position | { x: number, y: number } | { x: 20, y: 20 } | Initial window position | | size | { width: number, height: number } | { width: 400, height: 280 } | Initial window size | | minSize | { width: number, height: number } | { width: 320, height: 220 } | Minimum window size | | maxSize | { width: number, height: number } | { width: 800, height: 600 } | Maximum window size | | autoPlay | boolean | true | Auto-play when stream loads | | muted | boolean | false | Start muted | | volume | number | 1 | Initial volume (0-1) | | showControls | boolean | true | Show player controls | | zIndex | number | 999999 | Window z-index | | theme | 'dark' \| 'light' | 'dark' | Color theme | | className | string | - | Additional CSS class | | demo | boolean | false | Enable demo mode (skip playlist API, use YouTube + fake chat) | | demoVideoId | string | - | YouTube video ID to loop in demo mode (required when demo is true) | | demoChatScript | Array<{ message: string; author?: string; delayMs: number; avatarColor?: string }> | built-in script | Scripted chat entries cycled infinitely in demo mode |

Callbacks

| Callback | Parameters | Description | |----------|-----------|-------------| | onReady | - | Called when widget is ready for playback | | onPlay | - | Called when playback starts | | onPause | - | Called when playback pauses | | onError | { code: string, message: string } | Called on error | | onClose | - | Called when widget is closed | | onResize | { width: number, height: number } | Called when window is resized | | onMove | { x: number, y: number } | Called when window is moved | | onDemoChatMessage | { author: string, message: string, kind: 'scripted' \| 'user' \| 'reply', timestamp: number } | Called for every rendered demo-chat message (demo mode only) |

API

Methods

// Playback control
widget.play();
widget.pause();
widget.togglePlayPause();

// Volume
widget.setVolume(0.5); // 0-1
widget.getVolume();
widget.mute();
widget.unmute();
widget.toggleMute();

// Quality
widget.setQuality('720p');
widget.getQualities(); // ['Auto', '1080p', '720p', '480p', ...]

// Fullscreen
widget.toggleFullscreen();

// Window position and size
widget.setPosition({ x: 100, y: 100 });
widget.setSize({ width: 500, height: 350 });

// Visibility
widget.show();
widget.hide();
widget.close();

// State
widget.isReady(); // boolean
widget.getState(); // PlayerState

// Cleanup
widget.destroy();

// Static method to remove injected styles
StreamSlice.removeStyles();

PlayerState

interface PlayerState {
  isPlaying: boolean;
  isMuted: boolean;
  volume: number;
  isFullscreen: boolean;
  isLoading: boolean;
  duration: number;
  currentTime: number;
  isLive: boolean;
  quality: string;
  availableQualities: string[];
}

## Build

```bash
# Install dependencies
npm install

# Build
npm run build

# Build with watch mode
npm run dev

# Run example server
npm run serve

Output Files

| File | Size | Description | |------|------|-------------| | streamslice.js | ~55 KB | UMD, development | | streamslice.min.js | ~33 KB | UMD, minified (production) | | streamslice.esm.js | ~50 KB | ES Modules | | streamslice.esm.min.js | ~33 KB | ES Modules, minified |

Project Structure

src/
├── index.ts           # Entry point
├── StreamSlice.ts     # Main class
├── api/
│   └── client.ts      # API client
├── player/
│   ├── IVSPlayer.ts      # Amazon IVS Player wrapper
│   └── YouTubePlayer.ts  # YouTube IFrame wrapper (demo mode)
├── ui/
│   ├── FloatingWindow.ts  # Floating window (video + optional chat)
│   ├── PlayerControls.ts  # Player controls
│   ├── DemoChatPanel.ts   # Demo-mode fake chat panel
│   └── icons.ts           # SVG icons
├── styles/
│   └── index.ts       # CSS styles
└── types/
    └── index.ts       # TypeScript types

License

MIT