A modern React wrapper for CropperJS 2.x web components
npm install @imerljak/react-cropper-2> A modern React wrapper for CropperJS 2.x


A TypeScript-first React library that provides idiomatic React bindings for CropperJS 2.x web components.
- ✅ CropperJS 2.x Support - Built for the latest CropperJS web components
- ✅ React 19 Compatible - Full support for React 19.x
- ✅ TypeScript First - Complete type safety with strict mode
- ✅ Three APIs - Component, simplified hook, and advanced hook
- ✅ Modern Architecture - Built on web standards
- ✅ Fully Tested - 96%+ test coverage with 55 passing tests
- ✅ Interactive Docs - Storybook documentation
The original react-cropper library only supports CropperJS 1.x. CropperJS 2.x is a complete rewrite using modern web components, requiring new React bindings. This library provides three flexible APIs to work with CropperJS 2.x in React applications.
``bash`
npm install @imerljak/react-cropper-2 cropperjs@2
The simplest way to use the library:
`tsx
import { useRef } from 'react';
import { Cropper, type CropperRef } from '@imerljak/react-cropper-2';
function App() {
const cropperRef = useRef
const handleGetBounds = () => {
const bounds = cropperRef.current?.getBounds();
console.log('Crop bounds:', bounds);
};
return (
$3
For more control and composition:
`tsx
import { useCropper } from '@imerljak/react-cropper-2';function App() {
const { renderCropper, bounds, reset, clear, getCroppedCanvas } = useCropper({
src: '/image.jpg',
alt: 'Crop me',
crossOrigin: 'anonymous',
aspectRatio: 16 / 9,
onReady: () => console.log('Ready!'),
onChange: (e) => console.log('Changed:', e.detail),
});
const handleExport = async () => {
const canvas = await getCroppedCanvas();
const url = canvas?.toDataURL('image/png');
// Use the cropped image
};
return (
{renderCropper({ style: { maxHeight: '500px' } })}
{bounds && {JSON.stringify(bounds, null, 2)}}
);
}
`$3
For maximum control, use the advanced hook:
`tsx
import { useCropperAdvanced } from '@imerljak/react-cropper-2';function App() {
const {
canvasRef,
selectionRef,
bounds,
isReady,
getBounds,
setBounds,
reset,
getCroppedCanvas,
} = useCropperAdvanced({
autoInitialize: true,
onReady: (canvas) => console.log('Ready!', canvas),
onChange: (e) => console.log('Changed:', e.detail),
});
return (
src="/image.jpg"
alt="Crop me"
crossorigin="anonymous"
rotatable
scalable
translatable
/>
ref={selectionRef}
aspect-ratio={16 / 9}
initial-coverage={0.8}
movable
resizable
zoomable
outlined
>
);
}
`API Documentation
$3
#### Props
| Prop | Type | Description |
|------|------|-------------|
|
src | string | Image URL (required) |
| alt | string | Image alt text |
| crossOrigin | 'anonymous' \| 'use-credentials' | CORS setting |
| aspectRatio | number | Aspect ratio constraint (e.g., 16/9) |
| initialCoverage | number | Initial crop coverage (0-1) |
| background | boolean | Show background (default: true) |
| rotatable | boolean | Enable rotation (default: true) |
| scalable | boolean | Enable scaling (default: true) |
| translatable | boolean | Enable translation (default: true) |
| movable | boolean | Enable moving selection (default: true) |
| resizable | boolean | Enable resizing selection (default: true) |
| zoomable | boolean | Enable zooming (default: true) |
| outlined | boolean | Show selection outline (default: true) |
| onReady | (canvas: CropperCanvasElement) => void | Callback when ready |
| onChange | CropperEventHandler | Callback when crop changes |
| onCropStart | CropperEventHandler | Callback when crop starts |
| onCropMove | CropperEventHandler | Callback during crop movement |
| onCropEnd | CropperEventHandler | Callback when crop ends |#### Ref Methods
`tsx
interface CropperRef {
getCanvas: () => CropperCanvasElement | null;
getBounds: () => CropperBounds | null;
setBounds: (bounds: Partial) => void;
reset: () => void;
clear: () => void;
getCroppedCanvas: (options?) => Promise;
}
`$3
Simplified hook that handles rendering for you.
`tsx
const {
renderCropper,
bounds,
isReady,
getBounds,
setBounds,
reset,
clear,
getCanvas,
getSelection,
getCroppedCanvas,
} = useCropper(options);
`$3
Advanced hook for maximum control. You manage rendering yourself.
`tsx
const {
canvasRef,
selectionRef,
bounds,
isReady,
getBounds,
setBounds,
reset,
clear,
getCanvas,
getSelection,
getCroppedCanvas,
} = useCropperAdvanced(options);
`Live Examples
Check out the interactive Storybook documentation with live examples for:
- Basic cropping
- Different aspect ratios
- Custom styling
- Event handling
- All three API approaches
- Advanced configurations
Development
`bash
Install dependencies
npm installStart example app
npm run devRun tests
npm testRun tests with coverage
npm run test:coverageBuild library
npm run buildStart Storybook
npm run storybookBuild Storybook
npm run build-storybook
`Project Structure
`
react-cropper-2/
├── src/
│ ├── components/
│ │ ├── Cropper.tsx # Main component
│ │ └── Cropper.test.tsx # Component tests
│ ├── hooks/
│ │ ├── useCropper.tsx # Simplified hook
│ │ ├── useCropper.test.ts # Hook tests
│ │ ├── useCropperAdvanced.ts # Advanced hook
│ │ └── useCropperAdvanced.test.ts
│ ├── types/
│ │ ├── index.ts # TypeScript types
│ │ └── jsx.d.ts # JSX declarations
│ ├── stories/ # Storybook stories
│ └── index.ts # Main export
├── examples/basic/ # Example application
├── tests/setup.ts # Test configuration
└── dist/ # Build output
``- React 18.0.0 or higher (works with React 19)
- CropperJS 2.0.1 or higher
- TypeScript 5.6+ (for TypeScript projects)
Supports all modern browsers that support:
- ES2020
- Web Components (Custom Elements)
- ES Modules
Contributions are welcome! Please feel free to submit issues and pull requests.
MIT © 2025
- CropperJS - The underlying cropping library
- react-cropper - Inspiration from the v1 wrapper
- CropperJS - The underlying library (v2.x)
- react-cropper - React wrapper for CropperJS v1.x