ImageEditor
The all-in-one ImageEditor component provides a full-featured editing toolbar driven by a plugin system. Crop,
filter, tune, resize, frame and watermark — all in one component.
The crop stencil (overlay and handles) is shown only when the crop tab is active. When you switch to filters, finetune, frame, or watermark, the stencil is hidden so you can focus on the current tool.
Import
import { ImageEditor } from '@we-are-singular/svelte-chop-chop'; Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | ImageSource | — | Image URL, data URL, File , Blob , or HTMLImageElement . |
plugins | ChopPlugin[] | [] | Plugin instances that add toolbar tabs and functionality. |
aspectRatio | number | { min?: number; max?: number } | null | null | Initial crop aspect ratio. |
initialCropScale | number | 0.8 | Initial crop as fraction of image (0–1). 0.8 = 80% centered. Applied when changing aspect ratio or stencil too. |
class | string | '' | Extra CSS class on the root element. |
Events
| Event | Type | Description |
|---|---|---|
onexport | (blob: Blob) => void | Fires when the user presses the export/save button. Receives the
exported Blob . |
oncancel | () => void | Fires when the user presses cancel/close. |
Minimal editor (crop + rotate only)
Use ImageEditor without plugins for just crop and rotate:
Crop and rotate only (no plugins)
<ImageEditor src="/photo.jpg" style="height: 320px;" /> Full example with all plugins
ImageEditor with all plugins
<script lang="ts">
import { ImageEditor } from '@we-are-singular/svelte-chop-chop';
import { pluginFilters, pluginFinetune, pluginFrame, pluginWatermark, pluginResize } from '@we-are-singular/svelte-chop-chop';
import '@we-are-singular/svelte-chop-chop/themes/default';
function handleExport(result) {
if (result.blob) {
const url = URL.createObjectURL(result.blob);
const link = document.createElement('a');
link.href = url;
link.download = 'edited.jpg';
link.click();
URL.revokeObjectURL(url);
}
}
</script>
<ImageEditor
src="/photo.jpg"
plugins={[pluginFilters(), pluginFinetune(), pluginFrame(), pluginWatermark(), pluginResize()]}
onexport={handleExport}
/> Upload to server example
<script lang="ts">
import { ImageEditor } from '@we-are-singular/svelte-chop-chop';
import { pluginFilters } from '@we-are-singular/svelte-chop-chop/plugins/filters';
async function handleExport(blob: Blob) {
const formData = new FormData();
formData.append('image', blob, 'photo.jpg');
await fetch('/api/upload', { method: 'POST', body: formData });
}
</script>
<ImageEditor
src="/photo.jpg"
plugins={[pluginFilters()]}
onexport={handleExport}
/> Keyboard shortcuts
The editor accepts keyboard input when focused:
| Key | Action |
|---|---|
R | Rotate 90° clockwise |
Shift+R | Rotate 90° counter-clockwise |
H | Flip horizontal |
V | Flip vertical |
Ctrl+Z | Undo |
Ctrl+Shift+Z | Redo |
Arrow keys | Move crop 1px (10px with Shift) |
+ / - | Zoom in / out |
0 | Reset zoom (fit to view) |
Escape | Cancel / close |
Headless composable
For full UI control, use createImageEditor from the headless export. It returns a reactive state object with all actions:
import { createImageEditor } from '@we-are-singular/svelte-chop-chop/headless';
import { pluginFilters } from '@we-are-singular/svelte-chop-chop/plugins/filters';
import { pluginFinetune } from '@we-are-singular/svelte-chop-chop/plugins/finetune';
const editor = createImageEditor({
plugins: [pluginFilters(), pluginFinetune()],
});
// Load an image
await editor.loadImage('/photo.jpg');
// Apply a filter
editor.applyFilter('clarendon');
// Adjust finetune
editor.setFinetune('brightness', 20);
editor.setFinetune('contrast', 10);
// Rotate and flip
editor.rotate(90);
editor.flipX();
// Undo / redo
editor.undo();
// Export
const result = await editor.export({
format: 'image/webp',
quality: 0.9,
maxWidth: 1920,
});
// result.blob, result.file, result.dataURL, result.canvas
// result.coordinates, result.transforms, result.originalSize Export options
Export renders at full resolution using the original image pixels. The viewport size does not limit output — a large
image displayed small will export at its cropped region's actual dimensions. Use maxWidth / maxHeight to downscale if needed.
| Option | Type | Default | Description |
|---|---|---|---|
format | 'image/jpeg' | 'image/png' | 'image/webp' | 'image/png' | MIME type for the output image. |
quality | number | 0.92 | Compression quality 0–1 (JPEG/WebP only). |
maxWidth | number | — | Maximum output width. Downscales proportionally if exceeded. |
maxHeight | number | — | Maximum output height. Downscales proportionally if exceeded. |
shape | 'rect' | 'circle' | 'rect' | Crop shape. 'circle' applies a circular mask with transparent corners. Automatically uses PNG
if JPEG was selected (JPEG doesn't support transparency). |
postProcess | (ctx, canvas) => void | Promise | — | Hook to draw on the canvas after rendering but before encoding (e.g. custom watermark). |
ExportResult type
interface ExportResult {
canvas?: HTMLCanvasElement;
blob?: Blob;
file?: File;
dataURL?: string;
coordinates: CropCoordinates;
transforms: TransformState;
originalSize: { width: number; height: number };
filters?: FilterState; // Filter state applied at export
}