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

react-media-stack

v1.0.35

Published

High-performance scrolling React media feed library with virtualisation, caching, and custom overlay slots.

Downloads

4,138

Readme

MediaStack 🎬

media_stack is a high-performance React library for media (video and image) scroll feeds, supporting both vertical and horizontal snapping layouts. Engineered specifically for mobile-first scrolling applications (like TikTok feeds, Reels, and carousels), it provides built-in DOM virtualization, smart memory reclamation, and automatic video rotation capabilities.

Key Features

  • 🏎️ DOM Virtualization: Only mounts media items (videos/images) currently within or adjacent to the viewport, keeping the DOM extremely light.
  • Auto-Reclaiming Memory: Offscreen video elements are dynamically paused and their source streams wiped to release browser video hardware decoders and media caches.
  • 🔄 Auto-Rotation: Detects landscape media elements and rotates them by 90 degrees to fit a vertical 9:16 portrait viewport.
  • 🎛️ Granular UI Controls: Toggle default headers, mute buttons, meta description cards, sidebar widgets, and timelines easily.
  • 🖌️ Fully Customizable Overlays: Completely override the overlay UI using custom render functions.
  • 🔊 Global Audio Sync: Toggling mute on any video synchronizes volume state across all videos in the stack.

Installation

npm install media_stack

Ensure you import the CSS stylesheet in your project root (e.g. main.tsx or App.tsx):

import 'media_stack/dist/assets/index.css';

API Reference

<MediaStack />

The main scrolling viewport wrapper.

| Prop | Type | Default | Description | | :--- | :--- | :--- | :--- | | items | MediaItemData[] | Required | Array of media elements to scroll. | | direction | 'vertical' \| 'horizontal' | 'vertical' | Scroll layout snap alignment. | | autoPlay | boolean | true | Auto-play active video elements. | | muted | boolean | true | Initialize active videos as muted. | | loop | boolean | true | Loop video playback. | | hideScrollbar | boolean | true | Hide viewport scrollbars. | | showNavArrows | boolean | true | Show desktop left/right arrow controls. | | showProgressBar | boolean | true | Show timeline progress indicators. | | showMuteButton | boolean | true | Show default sound-mute control button. | | showSidebarActions | boolean | true | Show default like/reply/share sidebar. | | showMetaInfo | boolean | true | Show title and description info metadata. | | autoRotateLandscape | boolean | false | Rotate landscape media 90 degrees inside vertical layouts. | | onActiveIndexChange | (index: number) => void | undefined | Callback fired when user snaps to a different media index. | | onItemClick | (item: MediaItemData, index: number) => void | undefined | Callback fired when the media background is tapped. | | onLikeClick | (item: MediaItemData) => void | undefined | Callback for the Like button. | | onShareClick | (item: MediaItemData) => void | undefined | Callback for the Share button. | | onCommentClick | (item: MediaItemData) => void | undefined | Callback for the Reply/Comment button. | | renderCustomOverlay | (item, index, isActive) => ReactNode | undefined | Overrides the default layout overlays with custom code components. |

MediaStackRef

The forwarded ref exposes imperative control methods:

| Method | Description | | :--- | :--- | | scrollTo(target) | Jumps to the start, end, next, or previous item. | | destroy() | Releases internal timers, cached media URLs, and active playback state. |


MediaItemData Schema

Individual items passed into the items array follow this structure:

export interface MediaItemData {
  id: string | number;           // Unique element identifier
  type: 'image' | 'video';       // Media type
  src: string;                  // Direct media URL
  poster?: string;              // Image URL to show while video is loading/virtualized
  title?: string;               // Display title
  description?: string;         // Display description
  badge?: string;               // Display category badge (e.g. "TRENDING")
  fit?: 'cover' | 'contain';    // Visual scaling behavior (default: 'cover')
  customData?: Record<string, any>; // Optional container for extra data fields
}

Code Examples

Basic Usage (Vertical Reels Feed)

import { MediaStack, MediaItemData } from 'media_stack';

const FEEDS: MediaItemData[] = [
  {
    id: 1,
    type: 'video',
    src: 'https://example.com/video1.mp4',
    poster: 'https://example.com/poster1.jpg',
    title: 'Neon Skaters',
    description: 'Cruising through the retro streets.',
    badge: 'SPORTS',
  },
  {
    id: 2,
    type: 'image',
    src: 'https://example.com/art.jpg',
    title: 'Vaporwave Sunset',
    description: 'Chilled ambient design project.',
  }
];

export default function App() {
  return (
    <div style={{ width: '380px', height: '680px' }}>
      <MediaStack
        items={FEEDS}
        autoRotateLandscape={true}
        onLikeClick={(item) => console.log('Liked:', item.title)}
      />
    </div>
  );
}

Advanced (Custom Overlays)

import { MediaStack } from 'media_stack';

export default function CustomApp() {
  return (
    <MediaStack
      items={FEEDS}
      renderCustomOverlay={(item, index, isActive) => (
        <div style={{ position: 'absolute', top: 20, left: 20, color: 'white' }}>
          <h4>Custom Display: {item.title}</h4>
          {isActive && <p>Currently Active Slide</p>}
        </div>
      )}
    />
  );
}

Development & Verification

Running the Sandbox Demo

Start the interactive Vite dashboard panel:

npm run dev

Running Test Suites

  • Unit & Component Testing (Vitest):
    npm run test
  • End-to-End Testing (Playwright):
    npm run test:e2e