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

@orchard9ai/cropper

v0.8.0

Published

A React image cropping component with aspect ratio controls

Readme

@orchard9ai/cropper

A React image cropping component with aspect ratio controls, built on top of react-image-crop.

Features

  • 🖼️ Image cropping with visual selection
  • 📐 Multiple aspect ratio presets (Freeform, Square, Landscape, Portrait, Original)
  • 👁️ Optional preview panel
  • 🌍 Internationalization support with customizable labels
  • 🎨 Dark theme with Tailwind CSS
  • ⌨️ Keyboard support (ESC to close)
  • 📱 Responsive design
  • 🔄 Loading states
  • 💾 State management with Zustand

Installation

npm install @orchard9ai/cropper react-image-crop
# or
yarn add @orchard9ai/cropper react-image-crop
# or
pnpm add @orchard9ai/cropper react-image-crop

Note: react-image-crop is now a peer dependency and must be installed separately for SSR compatibility.

Peer Dependencies

This package requires the following peer dependencies:

{
  "react": "^18.0.0",
  "react-dom": "^18.0.0",
  "react-image-crop": "^11.0.0"
}

Usage

Basic Example

import { CropModal, CropData } from '@orchard9ai/cropper';
import '@orchard9ai/cropper/styles'; // Import CSS styles

function App() {
  const [showCropper, setShowCropper] = useState(false);

  const handleCrop = async (cropData: CropData) => {
    console.log('Crop data:', cropData);
    // Send crop data to your API
    await api.cropImage(imageId, cropData);
  };

  return (
    <>
      <button onClick={() => setShowCropper(true)}>Open Cropper</button>

      {showCropper && (
        <CropModal
          imageUrl="https://example.com/image.jpg"
          onClose={() => setShowCropper(false)}
          onCrop={handleCrop}
        />
      )}
    </>
  );
}

With Preview

<CropModal
  imageUrl="https://example.com/image.jpg"
  previewUrl="https://example.com/preview.jpg"
  onClose={() => setShowCropper(false)}
  onCrop={handleCrop}
/>

With Initial Aspect Ratio

<CropModal
  imageUrl="https://example.com/image.jpg"
  aspectRatio={1} // Square aspect ratio
  onClose={() => setShowCropper(false)}
  onCrop={handleCrop}
/>

With Custom Labels (i18n)

<CropModal
  imageUrl="https://example.com/image.jpg"
  onClose={() => setShowCropper(false)}
  onCrop={handleCrop}
  labels={{
    title: 'Recortar Imagen',
    cancel: 'Cancelar',
    apply: 'Aplicar',
    loading: 'Procesando...',
    loadingImage: 'Cargando imagen...',
    original: 'Original',
    selection: 'Selección',
    aspectRatios: {
      freeform: 'Libre',
      square: 'Cuadrado',
      landscape: 'Horizontal',
      portrait: 'Vertical',
      original: 'Original',
    },
  }}
/>

API

CropModal Props

| Prop | Type | Required | Description | | ------------- | --------------------------------------- | -------- | ----------------------------------------- | | imageUrl | string | Yes | URL of the image to crop | | onClose | () => void | Yes | Callback when modal is closed | | onCrop | (cropData: CropData) => Promise<void> | Yes | Callback with crop data | | previewUrl | string | No | Optional preview image URL | | isLoading | boolean | No | Shows loading state | | aspectRatio | number | No | Initial aspect ratio (e.g., 1 for square) | | labels | Labels | No | Custom labels for i18n |

CropData Interface

interface CropData {
  x: number; // X coordinate of crop area
  y: number; // Y coordinate of crop area
  width: number; // Width of crop area
  height: number; // Height of crop area
  original_width: number; // Original image width
  original_height: number; // Original image height
  regenerate_variants?: boolean;
}

Labels Interface

interface Labels {
  title?: string;
  cancel?: string;
  apply?: string;
  loading?: string;
  loadingImage?: string;
  original?: string;
  selection?: string;
  aspectRatios?: {
    freeform?: string;
    square?: string;
    landscape?: string;
    portrait?: string;
    original?: string;
  };
}

Styling

This component uses Tailwind CSS for styling. Make sure to include the styles in your application:

import '@orchard9ai/cropper/styles';

If you're using Tailwind CSS in your project, ensure the package's files are included in your content configuration:

// tailwind.config.js
module.exports = {
  content: [
    // ... your other content paths
    './node_modules/@orchard9ai/cropper/dist/**/*.{js,mjs}',
  ],
  // ... rest of your config
};

Advanced Usage

Accessing the Store

For advanced use cases, you can access the crop store directly:

import { useCropStore } from '@orchard9ai/cropper';

function MyComponent() {
  const { crop, aspectRatio, setAspectRatio } = useCropStore();

  // Use store values and methods
}

Utility Functions

The package exports several utility functions:

import {
  formatDimensions,
  getAspectRatioLabel,
  percentCropToPixelCrop,
  pixelCropToPercentCrop,
  constrainCrop,
  debounce,
} from '@orchard9ai/cropper';

Migration from Original Component

If you're migrating from the original BulkUploadReview CropModal:

  1. Import Changes:

    // Before
    import { CropModal } from '@/pages/BulkUploadReview/components/CropModal';
    
    // After
    import { CropModal } from '@orchard9ai/cropper';
    import '@orchard9ai/cropper/styles';
  2. Type Import Changes:

    // Before
    import { CropData } from '@/types/CropTypes';
    
    // After
    import { CropData } from '@orchard9ai/cropper';
  3. Props: The component API remains the same, so no changes needed.

Development

Running Storybook

npm run storybook

Building

npm run build

Type Checking

npm run typecheck

License

MIT