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

chat-media-view

v0.2.0

Published

Telegram-style image grid for React chat applications

Readme

chat-media-view

chat-media-view is an npm library designed to provide a flexible and efficient solution for displaying media in chat applications. It offers a responsive grid layout for images and videos, with features like dynamic resizing, lazy loading, and a customizable lightbox component for an enhanced viewing experience.

Features

  • Responsive Grid Layout: Automatically adjusts media display based on container size.
  • Dynamic Media Handling: Supports both images and videos, with intelligent loading strategies.
  • Customizable Lightbox: Full-screen media viewer with navigation and zoom capabilities.
  • Performance Optimized: Lazy loading and efficient rendering for smooth user experience.
  • Accessibility: Built with accessibility in mind, supporting keyboard navigation and ARIA attributes.
  • TypeScript Support: Fully typed for better developer experience.

Installation

npm install chat-media-view
# or
yarn add chat-media-view

Usage

ChatMediaView Component

The ChatMediaView component is the main entry point for displaying a collection of media items.

import React from 'react';
import { ChatMediaView, MediaItem } from 'chat-media-view';

const media: MediaItem[] = [
  {
    id: '1',
    type: 'image',
    url: 'https://example.com/image1.jpg',
    alt: 'Description of image 1',
    dimensions: { width: 1200, height: 800 }, // Optional: for aspect ratio calculation
    thumbnailUrl: 'https://example.com/image1-thumb.jpg', // Optional: for faster loading
  },
  {
    id: '2',
    type: 'video',
    url: 'https://example.com/video1.mp4',
    alt: 'Description of video 1',
    dimensions: { width: 1920, height: 1080 },
    thumbnailUrl: 'https://example.com/video1-thumb.jpg',
  },
  {
    id: '3',
    type: 'image',
    url: 'https://example.com/image2.jpg',
    alt: 'Description of image 2',
    dimensions: { width: 900, height: 1600 },
  },
];

const MyChatComponent = () => {
  return (
    <div style={{ width: '100%', maxWidth: '800px', margin: 'auto' }}>
      <ChatMediaView media={media} />
    </div>
  );
};

export default MyChatComponent;

Props

| Prop Name | Type | Description | Default | | :---------------- | :------------------- | :----------------------------------------------------------------- | :-------- | | media | MediaItem[] | An array of media objects to display. | [] | | onMediaClick | (item: MediaItem) => void | Callback when a media item is clicked. Receives the clicked item. | undefined | | aspectRatio | number | Desired aspect ratio for grid items (width / height). | 1 | | gap | number | Gap between grid items in pixels. | 4 | | initialIndex | number | Initial index of the media item to display in the lightbox. | 0 | | placeholder | React.ReactNode | Custom placeholder to display while media is loading. | undefined | | maxRows | number | Maximum number of rows to display in the grid. | undefined | | showControls | boolean | Show/hide lightbox navigation controls. | true | | showThumbnails | boolean | Show/hide thumbnail strip in the lightbox. | true | | zoomLevel | number | Initial zoom level for images in the lightbox. | 1 | | allowZoom | boolean | Allow/disallow zooming in the lightbox. | true | | downloadable | boolean | Allow/disallow downloading media from the lightbox. | true | | downloadFileName| (item: MediaItem, index: number) => string | Function to generate download file name. | undefined | | overlayColor | string | Color of the lightbox overlay. | 'rgba(0, 0, 0, 0.9)' |

MediaItem Type

interface MediaItem {
  id: string;
  type: 'image' | 'video';
  url: string;
  alt: string;
  dimensions?: { width: number; height: number };
  thumbnailUrl?: string; // Optional: URL for a thumbnail image
}

Lightbox Component (Internal Use)

The Lightbox component is used internally by ChatMediaView to display media in a full-screen overlay. While it's primarily for internal use, its props are documented here for comprehensive understanding.

Props

| Prop Name | Type | Description | Default | | :------------------ | :--------------------- | :---------------------------------------------------------- | :------ | | media | MediaItem[] | An array of media objects to display. | [] | | currentIndex | number | The index of the currently displayed media item. | 0 | | isOpen | boolean | Controls the visibility of the lightbox. | false | | onClose | () => void | Callback function when the lightbox is closed. | | | onNext | () => void | Callback function for navigating to the next media item. | | | onPrev | () => void | Callback function for navigating to the previous media item.| | | showControls | boolean | Show/hide navigation controls (arrows, close button). | true | | showThumbnails | boolean | Show/hide thumbnail strip at bottom. | true | | zoomLevel | number | Initial zoom level for images. | 1 | | allowZoom | boolean | Allow/disallow zooming. | true | | downloadable | boolean | Allow/disallow downloading media. | true | | downloadFileName | (item: MediaItem, index: number) => string | Function to generate download file name. | | | overlayColor | string | Color of the lightbox overlay. | 'rgba(0, 0, 0, 0.9)' |

Development

To set up the project for development:

git clone https://github.com/your-username/chat-media-view.git
cd chat-media-view
npm install
npm run dev

Running Storybook

Storybook is used for component development and testing.

npm run storybook

This will start Storybook in development mode, usually at http://localhost:6006.

Building the Library

To build the library for publishing:

npm run build

The build output will be in the dist directory.

Contributing

We welcome contributions! Please see our CONTRIBUTING.md for more details.

Migration from v0.1.x

Breaking Changes in v0.2.0

| Before (v0.1.x) | After (v0.2.0) | |-----------------|----------------| | images prop | items prop | | onImageClick callback | onMediaClick callback | | ImageItem type | MediaItem type with type: 'image' | | thumbhash field | blurhash field | | isDownloading in useDownload | status === 'downloading' | | ThumbHash utilities exported | Removed |

Migration Steps

  1. Update props: Replace images with items and onImageClick with onMediaClick
  2. Update types: Change ImageItem to MediaItem and add type: 'image' to each item
  3. Update placeholder hashes: Replace thumbhash with blurhash field
  4. Update download status checks: Replace isDownloading with status === 'downloading'
// Before (v0.1.x)
const images: ImageItem[] = [
  { src: 'photo.jpg', width: 800, height: 600, thumbhash: 'YTkG...' }
]
<ChatMediaGrid images={images} onImageClick={(i, img) => console.log(i)} />

// After (v0.2.0)
const items: MediaItem[] = [
  { type: 'image', src: 'photo.jpg', width: 800, height: 600, blurhash: 'LEHV...' }
]
<ChatMediaGrid items={items} onMediaClick={(i, item) => console.log(i)} />

License

This project is licensed under the MIT License.