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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@werk1/w1-system-videoblock

v2.0.1

Published

Universal video player supporting YouTube, Vimeo, HLS, DASH with coordination and GSAP integration for W1 System

Readme

@werk1/w1-system-videoblock

W1 System Video Components - Universal video player supporting YouTube, Vimeo, HLS, DASH, and progressive videos with coordination and GSAP integration.

Features

🌐 Universal Video Support

  • YouTube: Auto-detects and loads YouTube IFrame API
  • Vimeo: Auto-detects and loads Vimeo Player API
  • HLS Streaming: Auto-loads HLS.js for adaptive streaming
  • DASH Streaming: Auto-loads Dash.js for MPEG-DASH
  • Progressive: Native support for MP4, WebM, OGV

🎯 Smart Loading

  • On-Demand: Libraries loaded only when needed
  • Zero Overhead: No unused libraries in bundle
  • Native First: Uses browser native support when available
  • Graceful Fallback: Falls back to simpler implementations

🎮 Professional Features

  • Simplified Video Coordination: Smart coordination with platform-specific behavior
    • Native Videos: Full auto stop/resume based on visibility and priority
    • YouTube/Vimeo: Basic single-video mode + native platform behavior
  • Picture-in-Picture: Native PiP support
  • Keyboard Controls: Optional space/arrow key navigation
  • Custom Themes: Dark, light, transparent UI themes
  • Modern SVG Icons: Professional vector icons for all controls
  • Progress Tracking: Real-time callbacks and analytics
  • Smart Logging: Production-optimized logging system
  • Performance Optimized: Advanced state comparison and debouncing
  • Centralized Types: Single source of truth for all platform types

Architecture

  • W1VideoPlayer: Pure video engine (no store coordination)
  • W1VideoBlock: Complete coordinator with simplified platform-specific behavior
  • VideoCoordinationSlice: Zustand store integration with smart decision engine
  • Centralized Types: All YouTube, Vimeo, HLS, DASH types in single location
  • Icon Components: Scalable SVG icons (PlayIcon, PauseIcon, VolumeIcon, FullscreenIcon, PictureInPictureIcon)
  • Smart Logger: Environment-aware logging for clean production builds

Simplified Coordination Strategy

  • Native Videos (MP4, HLS, DASH): Full W1 coordination with custom visibility thresholds
  • External Platforms (YouTube, Vimeo): Basic single-video mode + native platform behavior
  • Manual Actions: Play/pause coordinates across all video types
  • Platform Behaviors: YouTube/Vimeo handle their own intersection observers and autoplay policies

Installation

npm install @werk1/w1-system-videoblock

Peer Dependencies

npm install react react-dom zustand

Components & Icons

Video Components

  • W1VideoBlock - Main orchestrator component (handles all coordination and store management)
  • W1VideoPlayer - Pure video engine (no store dependencies)
  • W1VideoControls - UI controls layer

Modern SVG Icons

  • PlayIcon - Professional play button
  • PauseIcon - Modern pause button
  • VolumeIcon - Dynamic volume icon (mute/low/high states)
  • FullscreenIcon - Enter/exit fullscreen toggle
  • PictureInPictureIcon - Picture-in-picture mode toggle

All icons support:

  • Scalable: size prop for any pixel size
  • Themeable: color="currentColor" inherits theme colors
  • Accessible: Built-in ARIA labels and roles
  • Lightweight: Optimized SVG paths

Basic Usage

Universal Video Support

import { W1VideoBlock } from '@werk1/w1-system-videoblock';

// Works with any video type
const VideoSection = () => {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <div>
      {/* YouTube Video */}
      <W1VideoBlock
        src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
        isVisible={isVisible}
        enableStreamingLibs={true}
        showControls={true}
        videoCoordinationStore={getVideoCoordinationStore}
      />

      {/* Vimeo Video */}
      <W1VideoBlock
        src="https://vimeo.com/1084537"
        isVisible={isVisible}
        enableStreamingLibs={true}
        showControls={true}
        videoCoordinationStore={getVideoCoordinationStore}
      />

      {/* HLS Stream */}
      <W1VideoBlock
        src="https://example.com/stream.m3u8"
        isVisible={isVisible}
        enableStreamingLibs={true}
        showControls={true}
        videoCoordinationStore={getVideoCoordinationStore}
      />

      {/* Progressive Video */}
      <W1VideoBlock
        src="video.mp4"
        isVisible={isVisible}
        priority={5}
        showControls={true}
        videoCoordinationStore={getVideoCoordinationStore}
      />
    </div>
  );
};

Using Individual Icons

import { PlayIcon, PauseIcon, VolumeIcon } from '@werk1/w1-system-videoblock';

const CustomControls = () => {
  return (
    <div>
      <button>
        <PlayIcon size={24} color="#ffffff" />
      </button>
      <button>
        <PauseIcon size={24} color="currentColor" />
      </button>
      <button>
        <VolumeIcon level={0.8} isMuted={false} size={20} />
      </button>
    </div>
  );
};

GSAP Integration

import { W1VideoBlock } from '@werk1/w1-system-videoblock';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

const AnimatedVideoSection = () => {
  const triggerRef = useRef();
  const [isVisible, setIsVisible] = useState(false);

  useLayoutEffect(() => {
    const trigger = ScrollTrigger.create({
      trigger: triggerRef.current,
      start: "top 80%",
      end: "bottom 20%",
      onEnter: () => setIsVisible(true),
      onLeave: () => setIsVisible(false),
    });

    return () => trigger.kill();
  }, []);

  return (
    <div ref={triggerRef}>
      <W1VideoBlock
        src="video.mp4"
        isVisible={isVisible}
        priority={10}
        videoCoordinationStore={getVideoCoordinationStore}
      />
    </div>
  );
};

BoundStore Integration

Add to your BoundStore

import { createVideoCoordinationSlice } from '@werk1/w1-system-videoblock';
import type { VideoCoordinationSlice } from '@werk1/w1-system-videoblock';

type BoundStore = DeviceInfoSlice &
  UIStateSlice &
  VideoCoordinationSlice; // Add video coordination

export const useBoundStore = create<BoundStore>()(
  persist(
    (...a) => ({
      ...createDeviceInfoSlice(...a),
      ...createUIStateSlice(...a),
      ...createVideoCoordinationSlice(...a), // Add video slice
    }),
    {
      name: 'app-state',
      partialize: (state) => ({
        ui: state.ui,
        // Don't persist video state
      }),
    },
  ),
);

Use Video Coordination

const VideoComponent = () => {
  const {
    currentlyPlayingVideoBlock,
    singleVideoMode,
    setSingleVideoMode
  } = useBoundStore();

  return (
    <div>
      <button onClick={() => setSingleVideoMode(!singleVideoMode)}>
        Single Video Mode: {singleVideoMode ? 'ON' : 'OFF'}
      </button>
      <p>Currently Playing: {currentlyPlayingVideoBlock?.id || 'None'}</p>
    </div>
  );
};

API Reference

W1VideoBlock Props

interface W1VideoBlockProps {
  src: string;                    // Video source URL
  isVisible: boolean;             // External visibility control
  priority?: number;              // Coordination priority (default: 0)

  // Video props
  autoplay?: boolean;             // Auto-play when visible
  muted?: boolean;                // Start muted
  loop?: boolean;                 // Loop video
  objectFit?: 'cover' | 'contain'; // Video sizing

  // Controls
  showControls?: boolean;         // Show video controls
  controlsTheme?: 'dark' | 'light' | 'transparent';
  showVolumeControl?: boolean;
  showFullscreen?: boolean;

  // Callbacks
  onVisibilityChange?: (isVisible: boolean) => void;
  onReady?: (methods: W1VideoPlayerMethods) => void;
}

Video Coordination

The system provides smart coordination with platform-specific behavior:

Native Videos (MP4, HLS, DASH)

  • Full Coordination: Auto stop/resume based on visibility and priority
  • Custom Thresholds: GSAP ScrollTrigger integration with configurable visibility zones
  • Priority System: Higher priority videos take precedence automatically
  • Seamless Behavior: Complete control over video lifecycle

External Platforms (YouTube, Vimeo)

  • Basic Single-Video Mode: Manual play pauses other videos
  • Platform-Native Behavior: Respect YouTube/Vimeo's built-in intersection observers
  • Simplified Integration: No fighting against platform autoplay policies
  • Stable Performance: Reliable behavior across platform updates

Coordination Features

  • Single Video Mode: Only one video plays at a time (default: enabled)
  • Manual Actions: Play/pause coordinates across all video types
  • Mobile Optimized: Respects mobile autoplay limitations
  • Mixed Coordination: Native and external videos work together seamlessly

Performance

  • Mobile-First: Optimized for mobile devices
  • Single Video Coordination: Prevents multiple video streams
  • GSAP Integration: Uses GSAP ScrollTrigger for smooth performance
  • Lazy Loading: Videos only load when needed
  • Smart State Comparison: 25x faster than JSON.stringify (50ms → 2ms)
  • Debounced Updates: Intelligent currentTime updates to prevent frame drops
  • Production Logging: Silent in production, debug-enabled in development

Debugging & Development

Smart Logging System

The package includes a production-optimized logging system:

// Enable debug logging in development
if (typeof window !== 'undefined') {
  window.W1_VIDEO_DEBUG = true;
}

// Or via environment variable
process.env.W1_VIDEO_DEBUG = 'true'

Logging Behavior:

  • Production: Silent (no console output)
  • Development: Full debug information
  • Debug Mode: Detailed video coordination and streaming logs

TypeScript

Full TypeScript support with comprehensive type definitions.

Examples

Custom Visibility Hook

import { useRef, useState, useLayoutEffect } from 'react';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

const useVideoVisibility = (options = {}) => {
  const triggerRef = useRef();
  const [isVisible, setIsVisible] = useState(false);

  useLayoutEffect(() => {
    const trigger = ScrollTrigger.create({
      trigger: triggerRef.current,
      start: "top 80%",
      end: "bottom 20%",
      onEnter: () => setIsVisible(true),
      onLeave: () => setIsVisible(false),
      onEnterBack: () => setIsVisible(true),
      onLeaveBack: () => setIsVisible(false),
      ...options,
    });

    return () => trigger.kill();
  }, []);

  return { triggerRef, isVisible };
};

Multiple Video Coordination

const MultiVideoSection = () => {
  const { triggerRef: triggerRef1, isVisible: isVisible1 } = useVideoVisibility();
  const { triggerRef: triggerRef2, isVisible: isVisible2 } = useVideoVisibility();

  return (
    <>
      <div ref={triggerRef1}>
        <W1VideoBlock
          src="hero-video.mp4"
          isVisible={isVisible1}
          priority={10}  // Higher priority
        />
      </div>

      <div ref={triggerRef2}>
        <W1VideoBlock
          src="background-video.mp4"
          isVisible={isVisible2}
          priority={5}   // Lower priority
        />
      </div>
    </>
  );
};

Browser Support

  • Modern browsers with ES2020 support
  • Chrome 80+
  • Firefox 78+
  • Safari 14+
  • Edge 80+

Mobile Support

  • iOS Safari 14+
  • Chrome Mobile 80+
  • Samsung Internet 13+

Troubleshooting

Video Won't Play on Mobile

Mobile browsers have strict autoplay policies. Ensure:

<W1VideoBlock
  src="video.mp4"
  muted={true}  // Required for autoplay
  playsInline={true}  // Prevents fullscreen on iOS
/>

Multiple Videos Playing

Check your BoundStore integration and single video mode:

const { singleVideoMode, setSingleVideoMode } = useBoundStore();

// Enable single video mode
useEffect(() => {
  setSingleVideoMode(true);
}, []);

YouTube/Vimeo Auto-Pause Behavior

YouTube and Vimeo have built-in intersection observers that pause videos when ~70% out of view. This is platform behavior and cannot be disabled:

  • Expected: YouTube/Vimeo videos pause themselves based on visibility
  • Solution: Use native MP4/HLS videos if you need custom visibility control
  • Mixed Usage: Combine native videos (full control) with YouTube/Vimeo (platform behavior)

Platform Coordination Differences

Different video types have different coordination capabilities:

// Native videos: Full coordination with custom thresholds
<W1VideoBlock src="video.mp4" isVisible={isVisible} priority={10} />

// YouTube/Vimeo: Basic single-video mode + platform behavior
<W1VideoBlock src="https://youtube.com/watch?v=..." isVisible={isVisible} />

GSAP ScrollTrigger Issues

Ensure GSAP ScrollTrigger is properly registered:

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/new-feature
  3. Commit changes: git commit -am 'Add new feature'
  4. Push to branch: git push origin feature/new-feature
  5. Submit a pull request

Development Setup

# Clone the repository
git clone https://github.com/werk1/w1-system-videoblock.git

# Install dependencies
npm install

# Build package
npm run build

# Run tests
npm test

Changelog

v1.3.0 (December 2024)

  • Simplified Coordination Architecture: Platform-specific coordination behavior
    • Native Videos: Full auto stop/resume with custom visibility thresholds
    • YouTube/Vimeo: Basic single-video mode + native platform behavior
  • Centralized Type System: Single source of truth for all platform types
  • Stable Platform Integration: No longer fights YouTube/Vimeo built-in behaviors
  • 🐛 Fixed: YouTube/Vimeo intersection observer conflicts
  • 🐛 Fixed: Removed duplicate type definitions across platform files
  • 📚 Documentation: Updated all docs to reflect simplified coordination approach

v1.2.0 (December 2024)

  • Performance Optimizations: 25x faster state comparison (JSON.stringify → smart shallow comparison)
  • Smart Logging System: Production-silent, development-verbose logging with debug flags
  • Architecture Cleanup: Clean separation between W1VideoPlayer (engine) and W1VideoBlock (coordinator)
  • UX Improvements: Fixed click behavior and controls visibility
  • Single Video Mode: Improved coordination timing for proper video switching
  • w1-system-core Integration: Ready for BoundStore pattern integration
  • 🐛 Fixed: Eliminated dual store registration complexity
  • 🐛 Fixed: External GSAP management (no more hardcoded animations)
  • 📚 Documentation: Complete integration guides and corrected package references

v1.1.0

  • Enhanced streaming support (YouTube, Vimeo, HLS, DASH)
  • Modern SVG icons with theme support
  • Professional UI controls with dark/light/transparent themes
  • Picture-in-Picture enhancements with metadata validation
  • Cross-browser compatibility improvements
  • TypeScript safety improvements

v1.0.0

  • Initial release
  • W1VideoPlayer headless component
  • W1VideoControls UI layer
  • W1VideoBlock orchestrator
  • VideoCoordinationSlice store integration
  • Mobile-first architecture
  • GSAP ScrollTrigger integration

License

MIT License

Copyright (c) 2024 WERK1

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

🔗 W1 System Core Integration

Adding VideoCoordination to Core BoundStore

When integrating with w1-system-core, add the video coordination slice to your main BoundStore:

// w1-system-core/src/stores/boundStore.ts
import { createVideoCoordinationSlice } from '@werk1/w1-system-videoblock';
import type { VideoCoordinationSlice } from '@werk1/w1-system-videoblock';

type BoundStore = DeviceInfoSlice &
  UIStateSlice &
  VideoCoordinationSlice; // Add video coordination

export const useBoundStore = create<BoundStore>()(
  persist(
    (...a) => ({
      ...createDeviceInfoSlice(...a),
      ...createUIStateSlice(...a),
      ...createVideoCoordinationSlice(...a), // Add video slice
    }),
    {
      name: 'app-state',
      partialize: (state) => ({
        ui: state.ui,
        deviceInfo: state.deviceInfo,
        // Don't persist video state (always starts fresh)
      }),
    },
  ),
);

Usage in Core Application

// In your w1-system-core pages/components
import { W1VideoBlock } from '@werk1/w1-system-videoblock';
import { useBoundStore } from '../stores/boundStore';

const VideoSection = () => {
  const [isVisible, setIsVisible] = useState(false);

  // Get video coordination from main bound store
  const getVideoCoordinationStore = useCallback(() => {
    return useBoundStore.getState();
  }, []);

  return (
    <W1VideoBlock
      src="video.mp4"
      isVisible={isVisible}
      videoCoordinationStore={getVideoCoordinationStore}
    />
  );
};

🎯 GSAP ScrollTrigger Integration (Complete Working Example)

The W1VideoBlock integrates perfectly with GSAP ScrollTrigger for scroll-based video visibility and autoplay. Here's the exact working pattern from our test environment:

'use client';

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { useCallback, useEffect, useRef, useState } from 'react';
import { create } from 'zustand';
import { W1VideoBlock, createVideoCoordinationSlice } from '@werk1/w1-system-videoblock';
import type { VideoCoordinationSlice } from '@werk1/w1-system-videoblock';

// Register GSAP plugins
if (typeof window !== 'undefined') {
  gsap.registerPlugin(ScrollTrigger);
}

// Video coordination store
type BoundStore = VideoCoordinationSlice;
const useBoundStore = create<BoundStore>()(createVideoCoordinationSlice);

// Custom visibility hook for GSAP integration
const useVideoVisibility = (options = {}) => {
  const triggerRef = useRef<HTMLDivElement>(null);
  const [isVisible, setIsVisible] = useState(false);
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  useEffect(() => {
    if (!isClient || !triggerRef.current) return;

    const trigger = ScrollTrigger.create({
      trigger: triggerRef.current,
      start: "top bottom-=20%",
      end: "bottom top+=20%",
      onEnter: () => setIsVisible(true),
      onLeave: () => setIsVisible(false),
      onEnterBack: () => setIsVisible(true),
      onLeaveBack: () => setIsVisible(false),
      ...options
    });

    return () => trigger.kill();
  }, [isClient, options]);

  return { triggerRef, isVisible };
};

export default function VideoPage() {
  const { triggerRef: triggerRef1, isVisible: isVisible1 } = useVideoVisibility();
  const { triggerRef: triggerRef2, isVisible: isVisible2 } = useVideoVisibility();

  const getVideoCoordinationStore = useCallback(() => {
    return useBoundStore.getState();
  }, []);

  return (
    <div>
      {/* Video 1 with GSAP ScrollTrigger */}
      <div ref={triggerRef1} style={{ height: '100vh', background: '#000', margin: '20px 0' }}>
        <h3 style={{ color: 'white', padding: '20px' }}>
          Video 1 (Visible: {isVisible1 ? 'YES' : 'NO'})
        </h3>
        <div style={{ height: '80%', padding: '20px' }}>
          <W1VideoBlock
            src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
            priority={10}
            isVisible={isVisible1} // CRITICAL: Pass GSAP-detected visibility
            showControls={true}
            videoCoordinationStore={getVideoCoordinationStore}
            enableStreamingLibs={true}
            enableKeyboardControls={true}
            style={{
              width: '100%',
              height: '100%',
              borderRadius: '12px',
              overflow: 'hidden'
            }}
          />
        </div>
      </div>

      {/* Video 2 with GSAP ScrollTrigger */}
      <div ref={triggerRef2} style={{ height: '100vh', background: '#333', margin: '20px 0' }}>
        <h3 style={{ color: 'white', padding: '20px' }}>
          YouTube Video (Visible: {isVisible2 ? 'YES' : 'NO'})
        </h3>
        <div style={{ height: '80%', padding: '20px' }}>
          <W1VideoBlock
            src="https://www.youtube.com/watch?v=YE7VzlLtp-4"
            priority={5}
            isVisible={isVisible2} // CRITICAL: Pass GSAP-detected visibility
            showControls={true}
            videoCoordinationStore={getVideoCoordinationStore}
            enableStreamingLibs={true}
            style={{
              width: '100%',
              height: '100%',
              borderRadius: '12px',
              overflow: 'hidden'
            }}
          />
        </div>
      </div>
    </div>
  );
}

🎯 Key Points

  1. Page-Level GSAP Integration: ScrollTrigger is implemented at the page level, not inside W1VideoBlock
  2. useVideoVisibility Hook: Creates individual triggerRef and isVisible state for each video
  3. Wrapper Pattern: Each video is wrapped in a <div ref={triggerRef}> for scroll detection
  4. isVisible Prop: W1VideoBlock receives the isVisible prop from the GSAP hook
  5. Video Coordination: Uses the Zustand store for single-video playback coordination

This pattern provides automatic scroll-based play/pause functionality with perfect GSAP integration.

🚀 Quick Start

npm install @werk1/w1-system-videoblock