{"_id":"@ashutoshmishr0/image-cropper","_rev":"4-6ed7483e977e8d7116f3f53637dd16ac","name":"@ashutoshmishr0/image-cropper","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@ashutoshmishr0/image-cropper","version":"1.0.0","keywords":["image","cropper","crop","react","nextjs","avatar","circle-crop","modal","ui"],"author":{"name":"ashutoshmishr0"},"license":"MIT","_id":"@ashutoshmishr0/image-cropper@1.0.0","maintainers":[{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"}],"homepage":"https://github.com/ashutoshmishr0/image-cropper#readme","bugs":{"url":"https://github.com/ashutoshmishr0/image-cropper/issues"},"dist":{"shasum":"f7b4cfd0db8fd1176a625c74e3650e1364750ca6","tarball":"https://registry.npmjs.org/@ashutoshmishr0/image-cropper/-/image-cropper-1.0.0.tgz","fileCount":5,"integrity":"sha512-4FoF6nuw1GoM7E3hBCE88vFm8Tfa8+QYHoulOv+dqlYdJZDtNhs7ohHrcoXMPT0CNR1KA+MEeuNkeMACIHnpxg==","signatures":[{"sig":"MEYCIQCVvVXfkQ92WARJLJNJ+tW/PAmqJueuLILAH8sclgDBTgIhALjSDjHqD513ohQOyKHhnjo6Q1t8excfh0UUg8gwdxpQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":50480},"main":"dist/index.cjs.js","types":"dist/index.d.ts","module":"dist/index.esm.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.esm.js","require":"./dist/index.cjs.js"}},"scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"},"repository":{"url":"git+https://github.com/ashutoshmishr0/image-cropper.git","type":"git"},"_npmVersion":"11.10.0","description":"A beautiful React image cropper modal. Click to pick a file, crop with drag/zoom/resize, get base64 PNG output. Supports circle, square, and rectangle shapes. Works with Next.js App Router.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.21.5"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/image-cropper_1.0.0_1781405563788_0.6578465784300014","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@ashutoshmishr0/image-cropper","version":"1.0.1","keywords":["image","cropper","crop","react","nextjs","avatar","circle-crop","modal","ui"],"author":{"name":"ashutoshmishr0"},"license":"MIT","_id":"@ashutoshmishr0/image-cropper@1.0.1","maintainers":[{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"}],"homepage":"https://github.com/ashutoshmishr0/image-cropper#readme","bugs":{"url":"https://github.com/ashutoshmishr0/image-cropper/issues"},"dist":{"shasum":"d152b07fab7a61c3184b4698da460e6b7257f5fd","tarball":"https://registry.npmjs.org/@ashutoshmishr0/image-cropper/-/image-cropper-1.0.1.tgz","fileCount":5,"integrity":"sha512-brPdaRsPJ5kmodEA+/BQgC5suftXba6K0AJCTBvjZ/AiDqB37MR6PuZLYU1Ttx35PDKxfdzkYVFNkcHjTH6qCg==","signatures":[{"sig":"MEQCIEn2sNkAKA/aXgnIjdfRuwSop2NrKC6I5O2lHkAmQnPGAiAGmYV4ZnBamKmx1w0wgahuZz+b4EOGVie3q+xORiAmKw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61678},"main":"dist/index.cjs.js","types":"dist/index.d.ts","module":"dist/index.esm.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.esm.js","require":"./dist/index.cjs.js"}},"gitHead":"93f7f28ce206e8606ac669326900434226e1f1ef","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"},"repository":{"url":"git+https://github.com/ashutoshmishr0/image-cropper.git","type":"git"},"_npmVersion":"11.10.0","description":"A beautiful React image cropper modal. Click to pick a file, crop with drag/zoom/resize, get base64 PNG output. Supports circle, square, and rectangle shapes. Works with Next.js App Router.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.21.5"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/image-cropper_1.0.1_1784361229878_0.056526951902825306","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@ashutoshmishr0/image-cropper","version":"1.0.2","description":"A beautiful React image cropper modal. Click to pick a file, crop with drag/zoom/resize, get base64 PNG output. Supports circle, square, and rectangle shapes. Works with Next.js App Router.","main":"dist/index.cjs.js","module":"dist/index.esm.js","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.esm.js","require":"./dist/index.cjs.js","types":"./dist/index.d.ts"}},"scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"keywords":["image","cropper","crop","react","nextjs","avatar","circle-crop","modal","ui"],"author":{"name":"ashutoshmishr0"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ashutoshmishr0/image-cropper.git"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"devDependencies":{"esbuild":"^0.21.5"},"gitHead":"93f7f28ce206e8606ac669326900434226e1f1ef","_id":"@ashutoshmishr0/image-cropper@1.0.2","bugs":{"url":"https://github.com/ashutoshmishr0/image-cropper/issues"},"homepage":"https://github.com/ashutoshmishr0/image-cropper#readme","_nodeVersion":"22.14.0","_npmVersion":"11.10.0","dist":{"integrity":"sha512-H5+lFzg7wnsdxiA/UNXPUPszsTgQIPTlxZuetgWC75eDDcZEK7k+iNQtHdWMDoLFDdFufFUWzdKD5mJncxtYNA==","shasum":"6f4c66f7868cce865c302373d8ff9e9c6a827a62","tarball":"https://registry.npmjs.org/@ashutoshmishr0/image-cropper/-/image-cropper-1.0.2.tgz","fileCount":5,"unpackedSize":63821,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDaV7/Qq+mU/ncX6QRTFH/z2VcMJhwIWIYVlbCDb80j5QIhAMwoSJBQFK+Jss0B/ItMHhUwkbfAMt4GgyDDsgV3i/tL"}]},"_npmUser":{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"},"directories":{},"maintainers":[{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"},{"name":"anurag_org","email":"ranurag404@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/image-cropper_1.0.2_1784368513080_0.6049797433532957"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-14T02:52:43.647Z","modified":"2026-07-18T09:55:13.357Z","1.0.0":"2026-06-14T02:52:43.941Z","1.0.1":"2026-07-18T07:53:50.034Z","1.0.2":"2026-07-18T09:55:13.222Z"},"bugs":{"url":"https://github.com/ashutoshmishr0/image-cropper/issues"},"author":{"name":"ashutoshmishr0"},"license":"MIT","homepage":"https://github.com/ashutoshmishr0/image-cropper#readme","keywords":["image","cropper","crop","react","nextjs","avatar","circle-crop","modal","ui"],"repository":{"type":"git","url":"git+https://github.com/ashutoshmishr0/image-cropper.git"},"description":"A beautiful React image cropper modal. Click to pick a file, crop with drag/zoom/resize, get base64 PNG output. Supports circle, square, and rectangle shapes. Works with Next.js App Router.","maintainers":[{"name":"ashutoshmishr0","email":"ashutoshmishra8796@gmail.com"},{"name":"anurag_org","email":"ranurag404@gmail.com"}],"readme":"# @ashutoshmishr0/image-cropper\n\nA beautiful, zero-dependency React image cropper modal. The user clicks a trigger, picks an image file, and a smooth modal opens with a full crop interface — drag to pan, zoom slider, resize handles, and shape masks (rectangle, square, circle). On confirm, the cropped image is returned as a base64 PNG string.\n\nWorks with Next.js App Router, Pages Router, and any React application.\n\n---\n\n## Installation\n\n```bash\nnpm install @ashutoshmishr0/image-cropper\n```\n\n---\n\n## How It Works\n\nThe component handles everything internally — you don't manage the file picker yourself:\n\n1. Wrap any element (or use the built-in default button) as `children`\n2. User clicks it — a file picker opens automatically\n3. User selects an image — the crop modal opens\n4. User drags, zooms, and resizes the crop area\n5. User clicks **\"Crop & Apply\"** — `onCrop` fires with the base64 PNG\n6. Modal closes — do whatever you want with the result (preview, upload, etc.)\n\n> **Important:** Do not pass your own `<input type=\"file\">` or an `image` prop. The component manages file selection internally — you only need `onCrop`.\n\n---\n\n## Basic Usage\n\n```tsx\n'use client';\n\nimport { useState } from 'react';\nimport ImageCropper from '@ashutoshmishr0/image-cropper';\n\nexport default function Page() {\n  const [preview, setPreview] = useState<string | null>(null);\n\n  return (\n    <div>\n      <ImageCropper onCrop={(base64) => setPreview(base64)} />\n\n      {preview && <img src={preview} alt=\"Cropped\" />}\n    </div>\n  );\n}\n```\n\n---\n\n## Custom Trigger Button\n\nPass any element as `children`. Clicking it opens the file picker.\n\n```tsx\n<ImageCropper onCrop={(base64) => setPreview(base64)}>\n  <button className=\"your-own-button\">Upload Photo</button>\n</ImageCropper>\n```\n\n---\n\n## Shapes\n\nThe `shape` prop controls the crop mask. There are three options:\n\n| Shape | Value | Ratio Behavior |\n|---|---|---|\n| Rectangle (default) | `\"rect\"` | Free ratio, or locked via `aspectRatio` / `outputWidth`+`outputHeight` |\n| Square | `\"square\"` | Always locked to 1:1 |\n| Circle | `\"circle\"` | Always locked to 1:1 (output is a transparent-background circular PNG) |\n\n### Rectangle — free crop (no fixed ratio)\n\n```tsx\n<ImageCropper\n  shape=\"rect\"\n  onCrop={(base64, cropArea) => {\n    console.log(base64);\n    console.log(cropArea); // { x, y, width, height } in natural image pixels\n  }}\n/>\n```\n\n### Rectangle — fixed aspect ratio (e.g. 16:9 banner)\n\n```tsx\n<ImageCropper\n  shape=\"rect\"\n  aspectRatio={16 / 9}\n  outputWidth={1200}\n  outputHeight={675}\n  onCrop={(base64) => setBanner(base64)}\n/>\n```\n\n### Square crop\n\n```tsx\n<ImageCropper\n  shape=\"square\"\n  outputWidth={500}\n  outputHeight={500}\n  onCrop={(base64) => setImage(base64)}\n/>\n```\n\n### Circle crop (e.g. avatar)\n\n```tsx\n<ImageCropper\n  shape=\"circle\"\n  outputWidth={200}\n  outputHeight={200}\n  onCrop={(base64) => setAvatar(base64)}\n>\n  <img\n    src={avatar || '/default-avatar.png'}\n    style={{ width: 80, height: 80, borderRadius: '50%', cursor: 'pointer' }}\n    alt=\"Click to change avatar\"\n  />\n</ImageCropper>\n```\n\n> When `shape` is `\"square\"` or `\"circle\"`, the crop ratio is automatically locked to 1:1 — you don't need to also pass `aspectRatio`.\n\n---\n\n## Fixed Pixel Output\n\nPass `outputWidth` and `outputHeight` together to force the exported image to that exact pixel size, regardless of how the crop box is resized on screen. This also locks the crop box's ratio to `outputWidth / outputHeight`.\n\n```tsx\n<ImageCropper\n  shape=\"rect\"\n  outputWidth={800}\n  outputHeight={400}\n  onCrop={(base64) => setImage(base64)}\n/>\n```\n\nIf `outputWidth`/`outputHeight` are omitted, the exported image size matches whatever the user resized the crop box to.\n\n---\n\n## Themes\n\nThe `theme` prop switches between a dark modal (default) and a light modal.\n\n```tsx\n<ImageCropper theme=\"dark\" onCrop={(base64) => setImage(base64)} />\n<ImageCropper theme=\"light\" onCrop={(base64) => setImage(base64)} />\n```\n\n---\n\n## Opening Programmatically (via ref)\n\n```tsx\n'use client';\n\nimport { useRef } from 'react';\nimport ImageCropper, { type ImageCropperRef } from '@ashutoshmishr0/image-cropper';\n\nexport default function Page() {\n  const cropperRef = useRef<ImageCropperRef>(null);\n\n  return (\n    <>\n      <button onClick={() => cropperRef.current?.open()}>\n        Open Cropper\n      </button>\n\n      <ImageCropper\n        ref={cropperRef}\n        onCrop={(base64) => console.log(base64)}\n      />\n    </>\n  );\n}\n```\n\n---\n\n## Uploading the Cropped Image to a Server\n\n```tsx\n<ImageCropper\n  shape=\"circle\"\n  outputWidth={300}\n  outputHeight={300}\n  onCrop={async (base64) => {\n    const blob = await fetch(base64).then((r) => r.blob());\n    const formData = new FormData();\n    formData.append('avatar', blob, 'avatar.png');\n    await fetch('/api/upload', { method: 'POST', body: formData });\n  }}\n>\n  <button>Upload Avatar</button>\n</ImageCropper>\n```\n\n---\n\n## All Props\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `onCrop` | `(base64: string, cropArea: CropArea) => void` | required | Called when the user confirms the crop |\n| `children` | `ReactNode` | `undefined` | Any clickable element that triggers the file picker. If omitted, a default \"Choose Image\" button is shown. |\n| `shape` | `\"rect\"` \\| `\"circle\"` \\| `\"square\"` | `\"rect\"` | Shape of the crop mask |\n| `outputWidth` | `number` | `undefined` | Output width in pixels. Locks aspect ratio when combined with `outputHeight`. |\n| `outputHeight` | `number` | `undefined` | Output height in pixels |\n| `aspectRatio` | `number` | `undefined` | Lock crop ratio without fixing output size (e.g. `16 / 9`). Ignored when `outputWidth` and `outputHeight` are both set, or when `shape` is `\"square\"`/`\"circle\"`. |\n| `theme` | `\"dark\"` \\| `\"light\"` | `\"dark\"` | Visual theme of the modal |\n| `showSizeBadge` | `boolean` | `true` | Show the \"W × H px\" badge under the crop area |\n| `closeOnBackdropClick` | `boolean` | `false` | Whether clicking outside the modal closes it |\n| `cropperWidth` | `number` | `520` | Width of the crop canvas inside the modal |\n| `cropperHeight` | `number` | `420` | Height of the crop canvas inside the modal |\n| `minCropWidth` | `number` | `40` | Minimum crop box width in screen pixels |\n| `minCropHeight` | `number` | `40` | Minimum crop box height in screen pixels |\n| `showGrid` | `boolean` | `true` | Show rule-of-thirds grid lines inside the crop area |\n| `showZoom` | `boolean` | `true` | Show the zoom slider |\n| `borderRadius` | `string` | `\"0px\"` | Border radius of the crop box. Only applies when `shape` is `\"rect\"`. |\n| `confirmLabel` | `string` | `\"Crop & Apply\"` | Label for the confirm button |\n| `cancelLabel` | `string` | `\"Cancel\"` | Label for the cancel button |\n| `accept` | `string` | `\"image/*\"` | Accepted file types for the file picker |\n| `triggerClassName` | `string` | `\"\"` | CSS class applied to the trigger wrapper |\n\n---\n\n## Ref Methods\n\n```ts\ninterface ImageCropperRef {\n  open: () => void; // Programmatically open the file picker\n}\n```\n\n---\n\n## CropArea Object\n\nThe second argument in `onCrop` contains the crop coordinates in natural image pixels (not screen pixels).\n\n```ts\ninterface CropArea {\n  x: number;       // left position in original image\n  y: number;       // top position in original image\n  width: number;   // width of cropped region\n  height: number;  // height of cropped region\n}\n```\n\n---\n\n## TypeScript Imports\n\n```ts\nimport ImageCropper from '@ashutoshmishr0/image-cropper';\nimport type {\n  ImageCropperProps,\n  ImageCropperRef,\n  CropArea,\n  CropShape,\n} from '@ashutoshmishr0/image-cropper';\n```\n\n---\n\n## Notes for Next.js\n\nAdd `\"use client\"` at the top of any file that uses this component — it relies on browser-only APIs (canvas, pointer events, `FileReader`) and cannot render on the server.\n\n```tsx\n'use client';\nimport ImageCropper from '@ashutoshmishr0/image-cropper';\n```\n\n---\n\n## Common Mistakes\n\n| Mistake | Fix |\n|---|---|\n| Passing an `image` prop | Not supported — the component manages file selection internally. Remove it and any manual `<input type=\"file\">`. |\n| Using `onCropComplete` | The callback prop is named `onCrop`, not `onCropComplete`. |\n| Using `shape=\"rectangle\"` | The valid values are `\"rect\"`, `\"square\"`, `\"circle\"` — not `\"rectangle\"`. |\n| Setting `aspectRatio` on `shape=\"circle\"` or `\"square\"` | Unnecessary — ratio is auto-locked to 1:1 for these shapes. |","readmeFilename":"README.md"}