> For AI agents: the complete documentation index is available at https://wallarm.github.io/design-system/llms.txt, the full documentation bundle is available at https://wallarm.github.io/design-system/llms-full.txt.

# ImageCropper

Select part of an image by moving and zooming it inside a fixed frame, then export a Blob at the exact outputSize. The frame follows the output aspect ratio and preserves the source proportions. Compose Slider for zoom, FileUpload for choosing a file, and your own Save action through ImageCropperContext. All processing runs in the browser; the consumer owns uploading. Preview rounding is visual only: the saved image is rectangular. Remote images need crossOrigin="anonymous" on ImageCropperImage and server CORS permission for canvas export; local file/object URLs also work. Size the preview with width classes; CSS scale transforms on ancestors are not supported by the underlying crop geometry. Arrow keys pan, Shift accelerates, and +/− zoom.

[Source](https://github.com/wallarm/design-system/tree/main/packages/design-system/src/components/ImageCropper) · [Storybook](https://wallarm.github.io/design-system/storybook/?path=/docs/inputs-imagecropper--overview)

```tsx
export const Avatar = () => <Example compact />;
```

## Usage

```tsx
import { ImageCropper } from '@wallarm-org/design-system/ImageCropper';
```

## Examples

### Landscape

Wide source and output: a 600 × 300 image is cropped to a 320 × 180 result.

```tsx
import { LANDSCAPE } from './stories/fixtures';

export const Landscape = () => (
  <Example source={LANDSCAPE} outputSize={{ width: 320, height: 180 }} />
);
```

### With file upload

FileUpload owns picking and validation; useFilePreviewUrl releases the local object URL.

```tsx
export const WithFileUpload = () => <Example upload />;
```

### Controlled

The parent can accept or reject zoom changes; the image and external slider follow its value.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';

export const Controlled = () => {
  const [zoom, setZoom] = useState(1.5);
  const [locked, setLocked] = useState(false);
  return (
    <div className='flex flex-col items-center gap-16'>
      <Example
        zoom={zoom}
        onZoomChange={value => {
          if (!locked) setZoom(value);
        }}
      />
      <Button
        variant='secondary'
        color='neutral'
        data-testid='cropper-lock-zoom'
        onClick={() => setLocked(value => !value)}
      >
        {locked ? 'Unlock zoom' : 'Lock zoom'}
      </Button>
    </div>
  );
};
```

### Geometry

Color bands make source proportions and the exact exported selection easy to verify.

```tsx
import { WIDE_BANDS } from './stories/fixtures';

export const Geometry = () => (
  <Example source={WIDE_BANDS} outputSize={{ width: 64, height: 64 }} geometry />
);
```

## Props

| Prop           | Type                                                 | Default | Description                                                                        |
| -------------- | ---------------------------------------------------- | ------- | ---------------------------------------------------------------------------------- |
| outputSize \*  | `ImageCropperSize`                                   |         | Exact exported pixel dimensions; also determines the visible frame's aspect ratio. |
| zoom           | `number \| undefined`                                |         |                                                                                    |
| defaultZoom    | `number \| undefined`                                | `1`     |                                                                                    |
| minZoom        | `number \| undefined`                                | `1`     | The minimum scale, relative to the image covering the frame. Must be at least 1.   |
| maxZoom        | `number \| undefined`                                | `5`     |                                                                                    |
| onZoomChange   | `((zoom: number) => void) \| undefined`              |         |                                                                                    |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                    |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                    |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                    |
| id             | `string \| undefined`                                |         |                                                                                    |
| tabIndex       | `number \| undefined`                                |         |                                                                                    |
| title          | `string \| undefined`                                |         |                                                                                    |
| rel            | `string \| undefined`                                |         |                                                                                    |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                    |
| data-testid    | `string \| undefined`                                |         |                                                                                    |

### ImageCropperGrid

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ImageCropperImage

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| alt            | `string \| undefined`                                |         |             |
| height         | `string \| number \| undefined`                      |         |             |
| loading        | `"eager" \| "lazy" \| undefined`                     |         |             |
| src            | `string \| undefined`                                |         |             |
| width          | `string \| number \| undefined`                      |         |             |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ImageCropperSelection

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ImageCropperViewport

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |
