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

@streamlayer/web-os

v0.5.3

Published

> **Alpha Version**: This feature is currently in alpha. Expect potential instability, including occasional freezes.

Readme

StreamLayerSDKTv Pause Ad Integration

Alpha Version: This feature is currently in alpha. Expect potential instability, including occasional freezes.

Prerequisites

1. PAL SDK

Add the Google PAL SDK to your HTML <head>:

<script type="text/javascript" src="https://imasdk.googleapis.com/pal/sdkloader/pal.js"></script>

2. Spatial Navigation

This feature uses @noriginmedia/norigin-spatial-navigation with shouldFocusDOMNode: true mode for remote control support.


Integration

Props

| Prop | Type | Description | |------|------|-------------| | showPauseAd | boolean | Controls pause ad visibility. Set to true when video pauses. | | onRenderPauseAd | (params: { rendered: boolean }) => void | Called when pause ad overlay renders. Use to hide your UI elements. | | onClosePauseAd | () => void | Called when pause ad closes without resuming video (user dismissed overlay). | | videoPlayerController | VideoPlayerCallback | Called when user resumes video via the pause ad overlay button. | | pauseAdVastUrl | Array<{ template: string; url: string }> | VAST tag configuration. |

pauseAdVastUrl Configuration

pauseAdVastUrl={[
  {
    template: 'default', // Currently only 'default' template is supported
    url: 'https://your-vast-tag-url.com/vast.xml',
  },
]}

Note: Only the first item in the array is used. Multi-item rotation is not yet supported.


Understanding showPauseAd vs pauseAdRendered

These two flags serve different purposes and are controlled by different parties:

| Flag | Controlled By | Purpose | |------|---------------|---------| | showPauseAd | You (integrator) | Request to show/hide pause ad | | pauseAdRendered | SDK (via callback) | Actual visibility state on screen |

Why two flags?

showPauseAd is your intent — "I want the pause ad to appear/disappear."

pauseAdRendered is the actual state — "The pause ad is currently visible on screen."

These values don't always match due to animation delays:

  • Opening delay (5 seconds): SDK waits before showing the overlay
  • Closing delay (400ms): SDK animates the overlay before removing it

State combinations

| showPauseAd | pauseAdRendered | State | |---------------|-------------------|-------| | false | false | Video playing or paused without ad | | true | false | Video paused, SDK preparing overlay (5s delay) | | true | true | Pause ad visible on screen | | false | true | Closing animation in progress (400ms) |

Timeline

Video pauses
    │
    ▼
showPauseAd = true              ← You set this on video pause
pauseAdRendered = false
    │
    │  ← 5 second delay (SDK loads ad, prepares overlay)
    ▼
showPauseAd = true
pauseAdRendered = true          ← SDK calls onRenderPauseAd({ rendered: true })
                                  Hide your UI controls now
    │
    │  ← User resumes video or closes overlay
    ▼
showPauseAd = false             ← You set this on play/close
pauseAdRendered = true          ← Still true! Closing animation playing
    │
    │  ← 400ms closing animation
    ▼
showPauseAd = false
pauseAdRendered = false         ← SDK calls onRenderPauseAd({ rendered: false })
                                  Safe to show your UI controls

Why this matters

Always use pauseAdRendered to control your UI visibility:

// Correct: hide UI based on actual render state
const showControls = !pauseAdRendered

// This ensures:
// 1. Your controls don't disappear 5s before the ad appears
// 2. Your controls don't reappear during the 400ms closing animation

If you used showPauseAd instead, your controls would:

  • Disappear immediately on pause (5s before the ad shows)
  • Reappear during the closing animation (overlapping with the ad)

Implementation Example

import { useState, useCallback, useRef } from 'react'
import { StreamLayerSDKTv, type VideoPlayerCallback } from '@streamlayer/sdk-web-os'

export const VideoView = () => {
  const [showPauseAd, setShowPauseAd] = useState(false)
  const [pauseAdRendered, setPauseAdRendered] = useState(false)
  const videoRef = useRef<HTMLVideoElement>(null)

  // Called when pause ad overlay renders/hides
  const onRenderPauseAd = useCallback((params: { rendered: boolean }) => {
    setPauseAdRendered(params.rendered)
  }, [])

  // Called when pause ad closes without video resumption
  const onClosePauseAd = useCallback(() => {
    setShowPauseAd(false)
  }, [])

  // Called when user clicks resume on pause ad overlay
  const videoPlayerController: VideoPlayerCallback = useCallback((data) => {
    if (data.play === true) {
      videoRef.current?.play()
    }
  }, [])

  // Video event handlers
  const onVideoPause = useCallback(() => {
    setShowPauseAd(true)
  }, [])

  const onVideoPlay = useCallback(() => {
    setShowPauseAd(false)
  }, [])

  // Hide your UI controls when pause ad is rendered
  const showControls = !pauseAdRendered

  return (
    <StreamLayerSDKTv
      showPauseAd={showPauseAd}
      onRenderPauseAd={onRenderPauseAd}
      onClosePauseAd={onClosePauseAd}
      videoPlayerController={videoPlayerController}
      pauseAdVastUrl={[
        {
          template: 'default',
          url: 'https://your-vast-tag-url.com',
        },
      ]}
    >
      {/* Your video container */}
      <div>
        <video
          ref={videoRef}
          onPause={onVideoPause}
          onPlay={onVideoPlay}
        />

        {/* Hide controls when pause ad is displayed */}
        {showControls && (
          <div className="video-controls">
            {/* Play button, timeline, etc. */}
          </div>
        )}
      </div>
    </StreamLayerSDKTv>
  )
}

Lifecycle Flow

Video Pauses
     │
     ▼
setShowPauseAd(true) ──► StreamLayerSDKTv receives showPauseAd=true
                                      │
                                      ▼
                         onRenderPauseAd({ rendered: true })
                                      │
                                      ▼
                         Hide your UI (controls, timeline, etc.)
                                      │
              ┌───────────────────────┴───────────────────────┐
              ▼                                               ▼
     User clicks RESUME                              User closes overlay
              │                                               │
              ▼                                               ▼
videoPlayerController({ play: true })                 onClosePauseAd()
              │                                               │
              ▼                                               ▼
     Resume video playback                        setShowPauseAd(false)
     setShowPauseAd(false)                        (video stays paused)

Key Points

  1. You control showPauseAd: Set it to true on video pause, false on play/resume.
  2. Hide UI on render: When onRenderPauseAd fires with rendered: true, hide your video controls (play button, timeline, etc.).
  3. Handle both exit paths: User can either resume video (via videoPlayerController) or dismiss the overlay (via onClosePauseAd).
  4. Single VAST tag: Only one item in pauseAdVastUrl is processed; additional items are ignored.