Image Cropper

An image cropper built on top of @origin-space/image-cropper.

Preview

Use mouse wheel or pinch gesture to zoom. Drag with mouse or touch, or use arrow keys to pan the image within the crop area.

Installation

CLI

npx shadcn@latest add https://kelvinmai.io/r/image-cropper.json

Manual

Install the following dependencies

npm install clsx tailwind-merge @origin-space/image-cropper

Add a classname utility function

import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
};

Copy and paste the following code into your project

components/image-cropper.tsx
'use client';
import * as React from 'react';
import { Cropper } from '@origin-space/image-cropper';
import { cn } from '@/lib/utils';
export type Area = { x: number; y: number; width: number; height: number };
export const ImageCropper: React.FC<
React.ComponentProps<typeof Cropper.Root>
> = ({ className, children, ...props }) => {
return (
<Cropper.Root
data-slot='cropper'
className={cn(
'relative flex w-full cursor-move touch-none items-center justify-center overflow-hidden focus:outline-none',
className,
)}
{...props}
>
<Cropper.Description
data-slot='cropper-description'
className='sr-only'
/>
{children}
</Cropper.Root>
);
};
export const ImageCropperImage: React.FC<
React.ComponentProps<typeof Cropper.Image>
> = ({ className, ...props }) => {
return (
<Cropper.Image
data-slot='cropper-image'
className={cn(
'pointer-events-none h-full w-full object-cover',
className,
)}
{...props}
/>
);
};
export const ImageCropperArea: React.FC<
React.ComponentProps<typeof Cropper.CropArea>
> = ({ className, ...props }) => {
return (
<Cropper.CropArea
data-slot='cropper-crop-area'
className={cn(
'pointer-events-none absolute border-3 border-white shadow-[0_0_0_9999px_rgba(0,0,0,0.3)] in-[[data-slot=cropper]:focus-visible]:ring-[3px] in-[[data-slot=cropper]:focus-visible]:ring-white/5',
className,
)}
{...props}
/>
);
};

Update the import paths to match your project setup

Usage

import { ImageCropper } from '@/components/ui/image-cropper';
export default function ColorPickerDemo() {
const [cropData, setCropData] = React.useState<Area | null>(null);
return (
<ImageCropper image='https://image.url' onCropChange={setCropData}>
<ImageCropperImage />
<ImageCropperArea />
</ImageCropper>
);
}

API Reference

Props

NameTypeDefaultDescription
image
string
Required
URL of the image to crop.
children
React.ReactNode
Required
Should include Cropper.Image, Cropper.CropArea, and Cropper.Description.
aspectRatio
number
1
The desired width/height aspect ratio (e.g., 1, 1.5, 4 / 3, 16 / 9).
cropPadding
number
25
Minimum padding (in pixels) between the crop area edges and the container edges.
minZoom
number
1
Minimum zoom level (1 = 100% original size relative to crop area).
maxZoom
number
3
Maximum zoom level.
zoomSensitivity
number
0.005
Multiplier for mouse wheel delta to control zoom speed.
keyboardStep
number
10
Number of pixels to pan the image when using arrow keys.
zoom
number
undefined
Controlled zoom level. If provided, component zoom state is controlled externally.
onCropChange
(pixels: Area | null) => void
undefined
Callback function triggered whenever the crop area changes. Receives pixel data or null if invalid.
onZoomChange
(zoom: number) => void
undefined
Callback function triggered when the zoom level changes interactively. Essential for controlled zoom prop.

The Area object received by onCropChange contains the following properties relative to the original image dimensions:

NameTypeDescription
x
number
The x-coordinate of the top-left corner of the cropped area.
y
number
The y-coordinate of the top-left corner of the cropped area.
width
number
The width of the cropped area in pixels.
height
number
The width of the cropped area in pixels.

Examples

With Mask

Use mouse wheel or pinch gesture to zoom. Drag with mouse or touch, or use arrow keys to pan the image within the crop area.

With Preview

Use mouse wheel or pinch gesture to zoom. Drag with mouse or touch, or use arrow keys to pan the image within the crop area.
Image preview