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-image-lab

v1.0.2

Published

A minimal, modern, TypeScript-first React 18+ component library for image uploading, camera capture, cropping, zooming, rotating, and resizing.

Readme


🚀 Live Demo

Try it out on CodeSandbox (Coming Soon)

React Image Lab Demo Placeholder


⚡ Why this library?

Building a robust image upload and cropping experience usually requires stitching together multiple libraries (one for UI, one for the cropper, one for canvas manipulation, one for camera access).

React Image Lab solves this by providing a unified, drop-in modal that handles the entire pipeline:

  1. Acquisition: Drag & Drop, File Browse, or Native Device Camera.
  2. Editing: High-performance zooming, rotation, and aspect-ratio locked cropping.
  3. Processing: Client-side canvas resizing and format conversion.

Comparison

| Feature | react-image-lab | react-easy-crop | react-avatar-editor | | ------------------- | --------------------------------------- | -------------------------- | -------------------------- | | UI Included? | ✅ Yes (Beautiful Modal & Controls) | ❌ No (Bring your own UI) | ❌ No (Canvas only) | | Camera Support | ✅ WebRTC built-in | ❌ No | ❌ No | | Client Resizing | ✅ Built-in (width/height/quality) | ❌ No | ❌ No | | Styling | ✅ Tailwind-friendly, auto-injected CSS | ⚠️ Manual styling required | ⚠️ Manual styling required |


✨ Features

  • All-in-One UI Modal: Fully fully built, accessible modal handling the entire flow.
  • Camera Integration: Seamlessly switch to front/back cameras to snap photos.
  • Advanced Cropping: Circular masks, fixed aspect ratios (1:1, 16:9, etc), zoom, and 360° rotation.
  • Client-Side Compression: Resizes and compresses images to WebP/JPEG/PNG before uploading, saving bandwidth.
  • TypeScript First: Written in strict TypeScript with comprehensive type definitions.
  • Zero Configuration: CSS is automatically injected. Works flawlessly with SSR frameworks like Next.js.
  • Performance Optimized: Built with strict React memoization to prevent canvas re-renders.

📦 Installation

npm install react-image-lab react-easy-crop

Note: react-easy-crop is a peer dependency used internally for its robust touch/mouse mapping engine.


💻 Usage

Drop the ImageStudio component anywhere in your app. It manages its own portal, so it will always render on top of your application layout safely.

import React, { useState } from "react";
import { ImageStudio } from "react-image-lab";

export default function App() {
  const [isOpen, setIsOpen] = useState(false);

  const handleSave = (file: File, objectUrl: string) => {
    console.log("Exported File:", file);

    // Example: Upload to your server
    // const formData = new FormData();
    // formData.append('avatar', file);
    // await fetch('/api/upload', { method: 'POST', body: formData });
  };

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>Upload Profile Picture</button>

      {isOpen && (
        <ImageStudio
          isOpen={isOpen}
          onClose={() => setIsOpen(false)}
          onSave={handleSave}
          title="Update Avatar"
          aspectRatio={1} // Force 1:1 square crop
          circularCrop={true} // Display circular clipping mask
          maxWidth={800} // Downscale to max 800px width
          exportFormat="image/webp" // Export as modern WebP
          quality={0.9} // 90% compression quality
          theme="dark" // Easily switch between "light" and "dark"
          accentColor="#10b981" // Override the default Indigo to custom Emerald
        />
      )}
    </div>
  );
}

⚙️ Props API

| Prop | Type | Default | Description | | ----------------- | --------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------- | | isOpen | boolean | Required | Controls visibility of the studio modal. | | onClose | () => void | Required | Triggered when the user clicks Cancel or the backdrop. | | onSave | (file: File, url: string) => void | undefined | Fired when export logic finishes successfully. returns the native File and a temporary object url. | | title | string | "React Image Studio" | The heading on top of the modal. | | aspectRatio | number \| undefined | undefined | Fixed aspect ratio map for Cropper (e.g 16/9, 1). If omitted, user can crop freely or select from a dropdown. | | circularCrop | boolean | false | Restricts the visual crop mask to a circular clipping path (perfect for avatars). | | maxWidth | number | undefined | Maximum width (px) of the final exported image. Preserves proportions. | | maxHeight | number | undefined | Maximum height (px) of the final exported image. Preserves proportions. | | quality | number | 0.95 | Quality ratio (0.0 - 1.0) applied to WebP/JPEG exports. | | exportFormat | 'image/jpeg' \| 'image/png' \| 'image/webp' | 'image/jpeg' | Desired final Mime type format for HTML5 canvas output. | | acceptedFormats | string | "image/*" | Accept attribute pattern for HTML <input type="file">. | | maxFileSizeMB | number | 5 | Rejects uploaded files larger than this size limit (in Megabytes). | | onError | (error: string) => void | undefined | Callback for internal errors (e.g. file too large, canvas crash). | | theme | 'light' \| 'dark' | 'light' | Toggles the entire UI to use the Light or Dark mode variable palette. | | accentColor | string | undefined | Provide any valid CSS color (HEX, RGB) to globally inject an override for the primary accent color. |


♿ Accessibility & UI

  • ARIA Compliant: Modal uses standard role="dialog" and aria-modal="true". Focus is trapped inside the modal while open, and background scrolling is locked.
  • Tailwind Friendly: Uses minimal native CSS with ris- prefixes to prevent global namespace pollution. Buttons inherit standard utility styles cleanly without requiring a massive CSS framework.

🗺️ Roadmap

  • [ ] Add explicit i18n support for translated UI strings.
  • [ ] Allow passing custom CSS classes for inner components (Uploader, Buttons).
  • [ ] Add optional image filters (e.g., Grayscale, Sepia) before export.
  • [ ] Implement framer-motion as an optional dependency for spring animations.

🛠️ Contributing

Contributions are always welcome!

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

📄 License

Distributed under the MIT License. See LICENSE for more information.