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

mui-image-gallery-viewer

v1.0.1

Published

A production-grade image gallery viewer component using MUI with configurable rail positioning, pagination, and multiple transition effects

Readme

mui-image-gallery-viewer

A production-grade image gallery viewer component for React using Material-UI (MUI) with configurable rail positioning, pagination, lazy loading, and multiple transition effects.

Features

✨ Configurable Rail Positioning - Place the thumbnail rail on left, right, top, or bottom ✨ Multiple Transition Effects - 9 different animation effects (fade, slide, carousel, cube, flip, rotate, zoom, etc.) ✨ Image Zoom - Built-in zoom functionality with mouse wheel and keyboard support (1x to 5x) ✨ Image Pan - Drag to pan zoomed images ✨ Download Images - Download images with fallback for CORS-protected URLs ✨ Smart Pagination - Automatic pagination for large image sets (10+ images) ✨ Lazy Loading - Efficient lazy loading with Intersection Observer ✨ Image Captions - Optional captions with smooth animations ✨ Responsive Design - Mobile-first design that works on all screen sizes ✨ Keyboard Navigation - Arrow keys for navigation, +/- for zoom, 0 for reset ✨ Accessibility - ARIA labels and semantic HTML ✨ TypeScript - Full TypeScript support with comprehensive type definitions ✨ Theme Integration - Seamless MUI theme integration with sx props

Installation

npm install mui-image-gallery-viewer
# or
yarn add mui-image-gallery-viewer
# or
pnpm add mui-image-gallery-viewer

Peer Dependencies

Make sure you have the following installed:

npm install react react-dom @mui/material @emotion/react @emotion/styled

Quick Start

import { ImageGallery } from "mui-image-gallery-viewer";

const images = [
  {
    id: "1",
    src: "https://example.com/image1.jpg",
    alt: "Image 1",
    thumbnailSrc: "https://example.com/image1-thumb.jpg",
  },
  // ... more images
];

function App() {
  return (
    <ImageGallery
      images={images}
      railPosition="left"
      transitionEffect="fade"
      containerHeight="100vh"
      containerWidth="100%"
    />
  );
}

export default App;

Props

ImageGallery Props

interface ImageGalleryProps {
  // Image data
  images: ImageItem[];

  // Layout
  railPosition?: "left" | "right" | "top" | "bottom"; // default: "left"
  containerHeight?: string | number; // default: "100%"
  containerWidth?: string | number; // default: "100%"

  // Rail styling
  railWidth?: string | number;
  railThickness?: string | number;
  railBackgroundColor?: string;
  railHoverEffect?: boolean; // default: true
  railBorderRadius?: string | number;

  // Transitions
  transitionEffect?:
    | "fade"
    | "slide"
    | "slideover"
    | "carousel"
    | "cube"
    | "flip"
    | "rotate"
    | "zoom"
    | "zoomIn"; // default: "fade"
  transitionDuration?: number; // default: 300 (ms)

  // Pagination
  imagesPerPage?: number; // default: 10
  enablePagination?: boolean; // default: true
  enableLazyLoading?: boolean; // default: true

  // Display
  showCaptions?: boolean; // default: false
  raiseOnHover?: boolean; // default: true

  // Callbacks
  onImageChange?: (image: ImageItem, index: number) => void;
  onPageChange?: (page: number) => void;

  // Styling
  sx?: SxProps<Theme>;
  railSx?: SxProps<Theme>;
  viewerSx?: SxProps<Theme>;
  paginationSx?: SxProps<Theme>;
}

ImageItem

interface ImageItem {
  id: string;
  src: string;
  alt: string;
  thumbnailSrc?: string; // Optional: separate thumbnail
  caption?: string; // Optional: caption for image
  loading?: "eager" | "lazy"; // default: "lazy"
}

Rail Positions

The thumbnail rail can be positioned on any side:

// Left side (default)
<ImageGallery images={images} railPosition="left" />

// Right side
<ImageGallery images={images} railPosition="right" />

// Top side
<ImageGallery images={images} railPosition="top" />

// Bottom side
<ImageGallery images={images} railPosition="bottom" />

Transition Effects

Nine different animation effects:

// Fade transition
<ImageGallery images={images} transitionEffect="fade" />

// Slide transition
<ImageGallery images={images} transitionEffect="slide" />

// Carousel 3D effect
<ImageGallery images={images} transitionEffect="carousel" />

// Cube flip
<ImageGallery images={images} transitionEffect="cube" />

// Full flip
<ImageGallery images={images} transitionEffect="flip" />

// Rotation
<ImageGallery images={images} transitionEffect="rotate" />

// Zoom in/out
<ImageGallery images={images} transitionEffect="zoom" />
<ImageGallery images={images} transitionEffect="zoomIn" />

// Slide over effect
<ImageGallery images={images} transitionEffect="slideover" />

Advanced Usage

Custom Styling with sx Prop

<ImageGallery
  images={images}
  sx={{
    borderRadius: 2,
    boxShadow: 3,
  }}
  railSx={{
    backgroundColor: "#f5f5f5",
  }}
  viewerSx={{
    backgroundColor: "#000",
  }}
/>

Handling Events

<ImageGallery
  images={images}
  onImageChange={(image, index) => {
    console.log(`Now viewing image ${index + 1}: ${image.alt}`);
  }}
  onPageChange={(page) => {
    console.log(`Moved to page ${page}`);
  }}
/>

Large Image Sets with Pagination

const [images, setImages] = useState<ImageItem[]>([]);

const handlePageChange = async (page: number) => {
  // Fetch images for the page
  const newImages = await fetchImagesForPage(page);
  setImages((prev) => [...prev, ...newImages]);
};

<ImageGallery
  images={images}
  imagesPerPage={10}
  enablePagination={true}
  enableLazyLoading={true}
  onPageChange={handlePageChange}
/>;

Responsive Container

<Box sx={{ width: "100%", height: "100vh" }}>
  <ImageGallery
    images={images}
    containerHeight="100%"
    containerWidth="100%"
  />
</Box>

With Zoom and Download

<ImageGallery
  images={images}
  enableZoom={true}
  enableDownload={true}
  minZoom={1}
  maxZoom={5}
/>

Full Featured Gallery

<ImageGallery
  images={images}
  railPosition="left"
  transitionEffect="fade"
  showCaptions={true}
  enableZoom={true}
  enableDownload={true}
  enablePagination={true}
  enableLazyLoading={true}
  imagesPerPage={10}
  onImageChange={(image, index) => console.log(`Viewing: ${image.alt}`)}
/>

Zoom & Pan

When enableZoom is true:

<ImageGallery
  images={images}
  enableZoom={true}
  minZoom={1}
  maxZoom={5}
/>
  • Mouse Wheel - Zoom in/out
  • Click & Drag - Pan zoomed image
  • + Key - Zoom in
  • - Key - Zoom out
  • 0 Key - Reset zoom to 100%

Download

Enable image download functionality:

<ImageGallery
  images={images}
  enableDownload={true}
/>

Downloads work with:

  • CORS-enabled origins
  • Same-origin images
  • Cross-origin images (with blob fallback)

Keyboard Navigation

  • Arrow Left (←) - Previous image
  • Arrow Right (→) - Next image
  • Tab - Navigate between controls
  • Enter/Space - Select thumbnail
  • + / = - Zoom in (when zoom enabled)
  • - / _ - Zoom out (when zoom enabled)
  • 0 - Reset zoom (when zoom enabled)

Accessibility

  • Full keyboard navigation support
  • ARIA labels on all interactive elements
  • Semantic HTML structure
  • Screen reader friendly
  • Respects prefers-reduced-motion setting

Browser Support

  • Chrome/Edge (latest 2 versions)
  • Firefox (latest 2 versions)
  • Safari (latest 2 versions)
  • Mobile browsers (iOS Safari, Chrome Mobile)

Dependencies

  • React 18+
  • Material-UI 5.14+
  • Framer Motion 11+
  • Emotion React & Styled (peer dependencies of MUI)

Additional Components

ImageGrid

Display images in a responsive grid with lightbox integration:

import { ImageGrid, Lightbox } from "mui-image-gallery-viewer";
import { useState } from "react";

function App() {
  const [lightboxOpen, setLightboxOpen] = useState(false);
  const [selectedIndex, setSelectedIndex] = useState(0);

  return (
    <>
      <ImageGrid
        images={images}
        onImageClick={(_, index) => {
          setSelectedIndex(index);
          setLightboxOpen(true);
        }}
        columns={4}
        gap={16}
      />

      <Lightbox
        images={images}
        open={lightboxOpen}
        onClose={() => setLightboxOpen(false)}
        initialIndex={selectedIndex}
        enableZoom={true}
        enableDownload={true}
      />
    </>
  );
}

ImageCompare

Side-by-side image comparison with slider:

import { ImageCompare } from "mui-image-gallery-viewer";

<ImageCompare
  beforeImage="/images/before.jpg"
  afterImage="/images/after.jpg"
  beforeLabel="Before"
  afterLabel="After"
  height="500px"
/>

Examples

See the Storybook for interactive examples of all features.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT © 2024 Ankit Shukla