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

mui-image-editor

v0.1.3

Published

A React image editor component built with Material-UI

Downloads

409

Readme

MUI Image Editor

A powerful, feature-rich React image editor component built with Material-UI. Edit images directly in your React applications with support for cropping, rotation, flipping, filters, and more.

Version License

Features

  • 🎨 Comprehensive Editing Tools

    • Crop with aspect ratio controls
    • Rotate with fine angle adjustment
    • Flip horizontally or vertically
    • Custom filters with preview
  • 🖼️ Advanced Image Processing

    • High-quality canvas-based rendering
    • Undo/redo support
    • Before/after comparison view
    • Zoom and pan controls
    • Grid overlays (rule of thirds, golden ratio, pixel grid)
  • 🎯 Developer-Friendly

    • TypeScript support with full type definitions
    • Imperative API via refs
    • State management (save/restore editor state)
    • Customizable UI and theming
    • Internationalization (i18n) support
  • Performance

    • Efficient rendering engine
    • Preview mode for real-time feedback
    • Configurable performance options

Installation

npm install mui-image-editor

Peer Dependencies

This package requires the following peer dependencies:

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

Quick Start

import React, { useRef } from 'react';
import { ImageEditor, EditorHandle } from 'mui-image-editor';

function App() {
  const editorRef = useRef<EditorHandle>(null);

  const handleSave = (result) => {
    console.log('Saved image:', result);
    // result contains: blob, dataUrl, format, width, height, operations
  };

  return (
    <ImageEditor
      src="https://example.com/image.jpg"
      onSave={handleSave}
      ref={editorRef}
    />
  );
}

API Reference

ImageEditor Component

The main component that renders the image editor interface.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | src | string | required | Image source URL or data URI | | crossOrigin | "anonymous" \| "use-credentials" \| null | "anonymous" | CORS setting for image loading | | imageLoader | (src: string) => Promise<Blob \| ArrayBuffer \| File> | - | Custom image loader function | | initialState | EditorState | - | Initial editor state (operations, viewport) | | onSave | (result: SaveResult) => void | required | Callback when save is triggered | | onChange | (preview: HTMLCanvasElement \| ImageBitmap, operations: OperationManifest) => void | - | Callback on each edit operation | | onError | (err: Error) => void | - | Error handler | | output | OutputOptions | - | Output configuration | | ui | UIOptions | - | UI customization options | | filters | FilterDefinition[] | [traceLinesFilter] | Array of custom filters | | tools | ToolDefinition[] | - | Custom tool definitions | | engine | EngineOptions | - | Engine performance options | | i18n | I18nOptions | - | Internationalization options |

Output Options

{
  format?: "png" | "jpeg" | "webp";  // Default: "png"
  quality?: number;                   // Default: 0.92 (for jpeg/webp)
  preserveExif?: boolean;             // Default: false
  background?: string | null;         // Background color for transparent areas
  colorProfile?: "sRGB" | "display-p3" | "auto";
  returnDataUrl?: boolean;            // Include data URL in save result
  maxSize?: {
    width?: number;
    height?: number;
    fit?: "contain" | "cover" | "downscaleOnly";
  };
}

UI Options

{
  themeMode?: "light" | "dark" | "system";
  themeOverrides?: object;            // MUI theme overrides
  tokens?: Partial<DesignTokens>;     // Design token overrides
  toolbarPosition?: "top" | "left" | "right";
  showGrid?: boolean;
  gridType?: "ruleOfThirds" | "goldenRatio" | "pixel" | "none";
  snapping?: boolean;
  keyboardShortcuts?: boolean;       // Default: true
  mobileLayout?: "compact" | "auto";
}

Engine Options

{
  previewScale?: number;              // Preview resolution scale
  useWebGL?: boolean;                 // Use WebGL for rendering
  workerCount?: number;               // Number of web workers
  keyframeEvery?: number;             // Keyframe interval for history
  maxHistoryBytes?: number;           // Maximum history size
  downscaleLargeImages?: {
    maxMP?: number;                   // Max megapixels before downscaling
    method?: "pica" | "canvas";
  };
}

I18n Options

{
  t?: (key: string, params?: Record<string, any>) => string;  // Custom translation function
  strings?: Partial<Record<EditorStringKey, string>>;         // Custom string overrides
  locale?: string;                                             // Locale code (default: "en")
  rtl?: boolean;                                                // Right-to-left layout
}

EditorHandle (Ref API)

Access the editor instance via a ref to use imperative methods:

const editorRef = useRef<EditorHandle>(null);

// Methods available:
editorRef.current?.save();              // Save the edited image
editorRef.current?.reset();             // Reset to original image
editorRef.current?.undo();               // Undo last operation
editorRef.current?.redo();              // Redo last operation
editorRef.current?.zoomToFit();         // Zoom to fit image in viewport
editorRef.current?.zoom(scale);          // Set zoom level (0.05 - 8)
editorRef.current?.getState();          // Get current editor state
editorRef.current?.setState(state);     // Restore editor state

Examples

Basic Usage

import React, { useRef } from 'react';
import { ImageEditor, EditorHandle } from 'mui-image-editor';

function MyEditor() {
  const editorRef = useRef<EditorHandle>(null);

  return (
    <ImageEditor
      src="/path/to/image.jpg"
      onSave={(result) => {
        // Download the image
        const url = URL.createObjectURL(result.blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'edited-image.png';
        a.click();
      }}
      ref={editorRef}
    />
  );
}

With Built-in Filter

import React from 'react';
import { ImageEditor, traceLinesFilter } from 'mui-image-editor';

function App() {
  return (
    <ImageEditor
      src="/image.jpg"
      filters={[traceLinesFilter]}
      onSave={(result) => console.log(result)}
    />
  );
}

With Custom Filters

import React from 'react';
import { ImageEditor, FilterDefinition } from 'mui-image-editor';

const customFilter: FilterDefinition = {
  id: 'myFilter',
  name: 'My Custom Filter',
  ui: [
    {
      kind: 'slider',
      key: 'intensity',
      label: 'Intensity',
      min: 0,
      max: 100,
      default: 50
    }
  ],
  apply: async (ctx, params) => {
    const bitmap = await ctx.getImageBitmap();
    // Apply your filter logic
    return bitmap;
  },
  preview: async (ctx, params) => {
    // Preview version (can be faster/lower quality)
    return customFilter.apply(ctx, params);
  }
};

function App() {
  return (
    <ImageEditor
      src="/image.jpg"
      filters={[customFilter]}
      onSave={(result) => console.log(result)}
    />
  );
}

State Management

import React, { useRef, useState } from 'react';
import { ImageEditor, EditorHandle, EditorState } from 'mui-image-editor';

function App() {
  const editorRef = useRef<EditorHandle>(null);
  const [savedState, setSavedState] = useState<EditorState | null>(null);

  const saveState = () => {
    const state = editorRef.current?.getState();
    if (state) {
      setSavedState(state);
      localStorage.setItem('editorState', JSON.stringify(state));
    }
  };

  const restoreState = () => {
    if (savedState) {
      editorRef.current?.setState(savedState);
    }
  };

  return (
    <>
      <button onClick={saveState}>Save State</button>
      <button onClick={restoreState}>Restore State</button>
      <ImageEditor
        src="/image.jpg"
        initialState={savedState || undefined}
        onSave={(result) => console.log(result)}
        ref={editorRef}
      />
    </>
  );
}

Custom Image Loader

import React from 'react';
import { ImageEditor } from 'mui-image-editor';

function App() {
  const imageLoader = async (src: string) => {
    // Custom loading logic (e.g., from authenticated API)
    const response = await fetch(src, {
      headers: {
        'Authorization': 'Bearer token'
      }
    });
    return response.blob();
  };

  return (
    <ImageEditor
      src="https://api.example.com/protected-image.jpg"
      imageLoader={imageLoader}
      onSave={(result) => console.log(result)}
    />
  );
}

Internationalization

import React from 'react';
import { ImageEditor } from 'mui-image-editor';

function App() {
  return (
    <ImageEditor
      src="/image.jpg"
      i18n={{
        locale: 'pl',
        strings: {
          'editor.toolbar.save': 'Zapisz',
          'editor.toolbar.undo': 'Cofnij',
          'editor.toolbar.redo': 'Ponów'
        }
      }}
      onSave={(result) => console.log(result)}
    />
  );
}

Output Configuration

import React from 'react';
import { ImageEditor } from 'mui-image-editor';

function App() {
  return (
    <ImageEditor
      src="/image.jpg"
      output={{
        format: 'jpeg',
        quality: 0.9,
        maxSize: {
          width: 1920,
          height: 1080,
          fit: 'contain'
        },
        returnDataUrl: true
      }}
      onSave={(result) => {
        console.log('Format:', result.format);
        console.log('Size:', result.width, 'x', result.height);
        if (result.dataUrl) {
          console.log('Data URL:', result.dataUrl);
        }
      }}
    />
  );
}

Exports

The package exports the following:

  • ImageEditor - The main component (default export)
  • EditorHandle - Type for the editor ref
  • ImageEditorProps - Component props type
  • EditorState - Editor state type
  • Operation, OperationManifest - Operation types
  • FilterDefinition - Filter definition type
  • traceLinesFilter - Built-in edge detection filter
  • translations - Built-in translations object

Types

Operation Types

The editor supports several operation types:

  • CropOperation: { type: "crop", rect: {...}, aspect?: string | null }
  • RotateOperation: { type: "rotate", angle: number, expandCanvas: boolean, background?: string }
  • FlipOperation: { type: "flip", axis: "x" | "y" }
  • FilterOperation: { type: "filter", id: string, params: Record<string, any>, version?: string }

FilterDefinition

{
  id: string;
  name: string;
  version?: string;
  ui?: FilterUiParam[];
  preview?: (ctx: FilterContext, params: Record<string, any>) => Promise<ImageBitmap | ImageData>;
  apply: (ctx: FilterContext, params: Record<string, any>) => Promise<ImageBitmap | ImageData>;
  glApply?: (gl: WebGLRenderingContext, texture: WebGLTexture, params: Record<string, any>) => WebGLTexture;
}

Keyboard Shortcuts

  • Ctrl/Cmd + Z - Undo
  • Ctrl/Cmd + Shift + Z - Redo
  • Ctrl/Cmd + + - Zoom in
  • Ctrl/Cmd + - - Zoom out
  • Ctrl/Cmd + 0 - Zoom to fit
  • Space + Drag - Pan
  • B (hold) - Before/after comparison

Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)

Requires modern browser features:

  • Canvas API
  • ImageBitmap API
  • ES2021+ JavaScript

Development

Building the Library

npm run build:lib

This will create a dist folder with:

  • mui-image-editor.es.js - ES module build
  • mui-image-editor.cjs.js - CommonJS build
  • index.d.ts - TypeScript declarations

Publishing to npm

# Simple publish
npm run publish:npm

# Or use the interactive script
npm run publish:script
# or
node publish.js

Development Mode

npm run dev

License

MIT

Contributing

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

Support

For issues, questions, or feature requests, please open an issue on the GitHub repository.