@bensitu/image-editor 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +152 -96
  2. package/dist/cjs/index.cjs +534 -139
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/esm/core/default-options.js +8 -6
  5. package/dist/esm/core/default-options.js.map +1 -1
  6. package/dist/esm/core/public-types.js.map +1 -1
  7. package/dist/esm/core/state-serializer.js +8 -0
  8. package/dist/esm/core/state-serializer.js.map +1 -1
  9. package/dist/esm/crop/crop-controller.js +218 -10
  10. package/dist/esm/crop/crop-controller.js.map +1 -1
  11. package/dist/esm/export/export-format.js.map +1 -1
  12. package/dist/esm/export/export-service.js +57 -56
  13. package/dist/esm/export/export-service.js.map +1 -1
  14. package/dist/esm/image/image-loader.js +2 -2
  15. package/dist/esm/image/image-loader.js.map +1 -1
  16. package/dist/esm/image/transform-controller.js +42 -0
  17. package/dist/esm/image/transform-controller.js.map +1 -1
  18. package/dist/esm/image-editor.js +139 -14
  19. package/dist/esm/image-editor.js.map +1 -1
  20. package/dist/esm/utils/file.js +10 -0
  21. package/dist/esm/utils/file.js.map +1 -1
  22. package/dist/types/core/default-options.d.ts.map +1 -1
  23. package/dist/types/core/public-types.d.ts +68 -50
  24. package/dist/types/core/public-types.d.ts.map +1 -1
  25. package/dist/types/core/state-serializer.d.ts +5 -1
  26. package/dist/types/core/state-serializer.d.ts.map +1 -1
  27. package/dist/types/crop/crop-controller.d.ts +12 -7
  28. package/dist/types/crop/crop-controller.d.ts.map +1 -1
  29. package/dist/types/export/export-format.d.ts +7 -10
  30. package/dist/types/export/export-format.d.ts.map +1 -1
  31. package/dist/types/export/export-service.d.ts +27 -32
  32. package/dist/types/export/export-service.d.ts.map +1 -1
  33. package/dist/types/export/overlay-merge-service.d.ts +3 -3
  34. package/dist/types/export/overlay-merge-service.d.ts.map +1 -1
  35. package/dist/types/image/image-loader.d.ts +5 -5
  36. package/dist/types/image/image-loader.d.ts.map +1 -1
  37. package/dist/types/image/transform-controller.d.ts +14 -7
  38. package/dist/types/image/transform-controller.d.ts.map +1 -1
  39. package/dist/types/image-editor.d.ts +22 -12
  40. package/dist/types/image-editor.d.ts.map +1 -1
  41. package/dist/types/index.d.cts +1 -1
  42. package/dist/types/index.d.cts.map +1 -1
  43. package/dist/types/index.d.ts +1 -1
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/dist/types/utils/file.d.ts +13 -0
  46. package/dist/types/utils/file.d.ts.map +1 -1
  47. package/dist/umd/image-editor.umd.js +1 -1
  48. package/dist/umd/image-editor.umd.js.map +1 -1
  49. package/package.json +1 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  A lightweight, TypeScript-first canvas image editor built on top of
8
8
  [Fabric.js](https://fabricjs.com/) v7. `ImageEditor` wraps a Fabric canvas
9
9
  with image loading, scale and rotation, mask creation, Text and Draw
10
- annotations, crop, Mosaic mode, history (undo/redo), layer operations, and
10
+ annotations, crop, Mosaic mode, base-image flips, history (undo/redo), layer operations, and
11
11
  base64/file export — exposed as a single canonical class
12
12
  with a stable public surface.
13
13
 
@@ -129,6 +129,8 @@ resolve to `undefined`.
129
129
  <input id="rotateLeftDegreesInput" type="number" value="90" />
130
130
  <button id="rotateRightButton">Rotate Right</button>
131
131
  <input id="rotateRightDegreesInput" type="number" value="90" />
132
+ <button id="flipHorizontalButton">Flip Horizontal</button>
133
+ <button id="flipVerticalButton">Flip Vertical</button>
132
134
 
133
135
  <button id="createMaskButton">Add Mask</button>
134
136
  <button id="removeSelectedMaskButton">Remove Mask</button>
@@ -155,6 +157,16 @@ resolve to `undefined`.
155
157
  <ul id="annotationList"></ul>
156
158
 
157
159
  <button id="enterCropModeButton">Crop</button>
160
+ <select id="cropAspectRatioSelect">
161
+ <option value="free">Free</option>
162
+ <option value="1:1">1:1</option>
163
+ <option value="3:4">3:4</option>
164
+ <option value="4:3">4:3</option>
165
+ <option value="3:2">3:2</option>
166
+ <option value="2:3">2:3</option>
167
+ <option value="9:16">9:16</option>
168
+ <option value="16:9">16:9</option>
169
+ </select>
158
170
  <button id="applyCropButton">Apply Crop</button>
159
171
  <button id="cancelCropButton">Cancel Crop</button>
160
172
 
@@ -212,11 +224,14 @@ editor.init({
212
224
  rotateLeftDegreesInput: 'rotateLeftDegreesInput',
213
225
  rotateRightButton: 'rotateRightButton',
214
226
  rotateRightDegreesInput: 'rotateRightDegreesInput',
227
+ flipHorizontalButton: 'flipHorizontalButton',
228
+ flipVerticalButton: 'flipVerticalButton',
215
229
  createMaskButton: 'createMaskButton',
216
230
  removeSelectedMaskButton: 'removeSelectedMaskButton',
217
231
  removeAllMasksButton: 'removeAllMasksButton',
218
232
  maskList: 'maskList',
219
233
  enterCropModeButton: 'enterCropModeButton',
234
+ cropAspectRatioSelect: 'cropAspectRatioSelect',
220
235
  applyCropButton: 'applyCropButton',
221
236
  cancelCropButton: 'cancelCropButton',
222
237
  enterMosaicModeButton: 'enterMosaicModeButton',
@@ -270,7 +285,7 @@ const { ImageEditor } = require('@bensitu/image-editor');
270
285
  const editor = new ImageEditor(fabric, { canvasWidth: 800, canvasHeight: 600 });
271
286
  ```
272
287
 
273
- In v2.2, `require('@bensitu/image-editor')` returns a namespace object with
288
+ In v2, `require('@bensitu/image-editor')` returns a namespace object with
274
289
  `ImageEditor`, `default`, and the editor object guards
275
290
  (`isBaseImageObject`, `isMaskObject`, `isAnnotationObject`,
276
291
  `isTextAnnotationObject`, `isDrawAnnotationObject`, `isSessionObject`, and
@@ -314,12 +329,12 @@ new ImageEditor(options?: ImageEditorOptions) // UMD: reads globalThis.fabric
314
329
 
315
330
  ### Image loading
316
331
 
317
- | Method | Description |
318
- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
319
- | `loadImage(base64, options?)` | Load an image from a `data:image/...` URL. Returns `Promise<void>`. Transactional: any failure restores the prior canvas, scroll, overflow, and snapshot state. |
320
- | `isImageLoaded()` | Returns `true` if a valid image is currently loaded on the canvas. |
321
- | `isBusy()` | Returns `true` while the editor is loading, animating, or in Crop, Mosaic, Text, or Draw mode. |
322
- | `setLayoutMode(mode)` | Select the layout strategy for future image loads. `mode` is `'fit'`, `'cover'`, or `'expand'`. |
332
+ | Method | Description |
333
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
334
+ | `loadImage(base64, options?)` | Load a supported raster image data URL (`png`, `jpeg`, `webp`, `gif`, or `bmp`). Returns `Promise<void>`. Transactional: any failure restores the prior canvas, scroll, overflow, and snapshot state. |
335
+ | `isImageLoaded()` | Returns `true` if a valid image is currently loaded on the canvas. |
336
+ | `isBusy()` | Returns `true` while the editor is loading, animating, or in Crop, Mosaic, Text, or Draw mode. |
337
+ | `setLayoutMode(mode)` | Select the layout strategy for future image loads. `mode` is `'fit'`, `'cover'`, or `'expand'`. |
323
338
 
324
339
  `LoadImageOptions` currently includes `preserveScroll?: boolean` for
325
340
  preserving the container's scroll position across both successful loads and
@@ -350,11 +365,18 @@ the JPEG, PNG, or WebP export options.
350
365
 
351
366
  ### Transforms
352
367
 
353
- | Method | Description |
354
- | ----------------------- | --------------------------------------------------------------------------------------------------- |
355
- | `scaleImage(factor)` | Scale to `factor` (clamped to `[minScale, maxScale]`). Non-finite values are no-ops. Animated. |
356
- | `rotateImage(degrees)` | Rotate to `degrees`. Non-finite values resolve without changing canvas state. Animated. |
357
- | `resetImageTransform()` | Animate to scale 1 and rotation 0. Records exactly one history entry covering the entire transform. |
368
+ | Method | Description |
369
+ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
370
+ | `scaleImage(factor)` | Scale to `factor` (clamped to `[minScale, maxScale]`). Non-finite values are no-ops. Animated. |
371
+ | `rotateImage(degrees)` | Rotate to `degrees`. Non-finite values resolve without changing canvas state. Animated. |
372
+ | `flipHorizontal()` | Toggle horizontal flip on the base image only. Masks, annotations, and session overlays are not mirrored. Returns `Promise<void>`. |
373
+ | `flipVertical()` | Toggle vertical flip on the base image only. Masks, annotations, and session overlays are not mirrored. Returns `Promise<void>`. |
374
+ | `resetImageTransform()` | Animate to scale 1, rotation 0, and an unflipped state. Records exactly one history entry covering the entire transform. |
375
+
376
+ ```ts
377
+ await editor.flipHorizontal();
378
+ await editor.flipVertical();
379
+ ```
358
380
 
359
381
  ### Masks
360
382
 
@@ -393,11 +415,29 @@ editor.createMask({ color: 'rgba(0, 128, 255, 0.35)' }); // Per-call override.
393
415
 
394
416
  ### Crop
395
417
 
396
- | Method | Description |
397
- | ----------------- | ------------------------------------------------------------------------------------ |
398
- | `enterCropMode()` | Add an interactive crop rectangle on top of the image. |
399
- | `applyCrop()` | Apply the current crop region. Atomic: failure rolls back to the pre-crop snapshot. |
400
- | `cancelCrop()` | Cancel crop mode and restore the prior canvas state without pushing a history entry. |
418
+ | Method | Description |
419
+ | --------------------------- | ------------------------------------------------------------------------------------ |
420
+ | `enterCropMode(options?)` | Add an interactive crop rectangle on top of the image. |
421
+ | `setCropAspectRatio(ratio)` | Update the active crop rectangle ratio while crop mode is open. |
422
+ | `applyCrop()` | Apply the current crop region. Atomic: failure rolls back to the pre-crop snapshot. |
423
+ | `cancelCrop()` | Cancel crop mode and restore the prior canvas state without pushing a history entry. |
424
+
425
+ `enterCropMode({ aspectRatio })` locks the crop rectangle to a preset or custom
426
+ ratio. Supported preset strings are `'free'`, `'1:1'`, `'3:4'`, `'4:3'`,
427
+ `'3:2'`, `'2:3'`, `'16:9'`, and `'9:16'`. Custom ratios use
428
+ `{ width, height }`. Per-call options override `crop.aspectRatio` from the
429
+ constructor.
430
+
431
+ When `cropAspectRatioSelect` is bound through `init(idMap)`, the built-in Crop
432
+ button uses the select's current value and changing the select while crop mode
433
+ is open calls `setCropAspectRatio()` to resize the active crop rectangle.
434
+
435
+ ```ts
436
+ editor.enterCropMode({ aspectRatio: '1:1' });
437
+ editor.enterCropMode({ aspectRatio: '16:9' });
438
+ editor.setCropAspectRatio('4:3');
439
+ editor.enterCropMode({ aspectRatio: { width: 2, height: 1 } });
440
+ ```
401
441
 
402
442
  ### Mosaic mode
403
443
 
@@ -508,30 +548,39 @@ base image below overlays and session objects above overlays.
508
548
  | `mergeAnnotations()` | Bake annotations into the base image atomically. Returns `Promise<void>`. |
509
549
  | `exportImageBase64(options?)` | Returns `Promise<string>` (data URL). Resolves to `''` with a warning when no image is loaded. |
510
550
  | `exportImageFile(options?)` | Returns `Promise<File>`. Rejects when no image is loaded. |
511
- | `downloadImage(options?)` | Triggers a browser download. Also accepts a filename string. No-op when no image is loaded. |
512
-
513
- `Base64ExportOptions` and `ImageFileExportOptions` separate overlay rendering
514
- from export region selection. `DownloadImageOptions` supports the same overlay
515
- rendering flags plus `fileName`:
516
-
517
- | Option | Default | Description |
518
- | ------------------ | --------- | ------------------------------------------------------------------------------------------- |
519
- | `mergeMasks` | `true` | Render masks into exported pixels. Mask labels are never exported. |
520
- | `mergeAnnotations` | `true` | Render non-hidden annotations into exported pixels. |
521
- | `exportArea` | `'image'` | `'image'` clips to the image bounding box; `'canvas'` exports the canvas. |
522
- | `fileType` | `'jpeg'` | `'png'`, `'jpeg'`, `'jpg'`, `'webp'`, or matching full MIME strings. |
523
- | `format` | `'jpeg'` | Alias for `fileType` on `exportImageBase64`; `fileType` wins when both set. |
524
- | `quality` | `0.92` | Lossy quality clamped to `[0, 1]`; ignored for PNG. |
525
- | `multiplier` | `1` | Output resolution multiplier. |
526
- | `fileName` | option | `ImageFileExportOptions` and `DownloadImageOptions`. Defaults to `defaultDownloadFileName`. |
551
+ | `downloadImage(options?)` | Returns `Promise<void>` and triggers a browser download. No-op when no image is loaded. |
552
+
553
+ All export APIs use the same `ImageExportOptions` shape:
554
+
555
+ | Option | Default | Description |
556
+ | ------------------ | --------- | --------------------------------------------------------------------------------- |
557
+ | `mergeMasks` | `true` | Render masks into exported pixels. Mask labels are never exported. |
558
+ | `mergeAnnotations` | `true` | Render non-hidden annotations into exported pixels. |
559
+ | `exportArea` | `'image'` | `'image'` clips to the image bounding box; `'canvas'` exports the canvas. |
560
+ | `fileType` | `'jpeg'` | `'png'`, `'jpeg'`, `'jpg'`, `'webp'`, or matching full MIME strings. |
561
+ | `format` | `'jpeg'` | Alias for `fileType` on all export APIs; `fileType` wins when both set. |
562
+ | `quality` | `0.92` | Lossy quality clamped to `[0, 1]`; ignored for PNG. |
563
+ | `multiplier` | `1` | Output resolution multiplier. |
564
+ | `fileName` | option | `exportImageFile()` and `downloadImage()`. Defaults to `defaultDownloadFileName`. |
527
565
 
528
566
  ```ts
529
567
  await editor.exportImageBase64({ mergeMasks: true, mergeAnnotations: true });
530
568
  await editor.exportImageBase64({ mergeMasks: false, mergeAnnotations: true });
531
569
  await editor.exportImageBase64({ mergeMasks: true, mergeAnnotations: false });
532
570
  await editor.exportImageBase64({ mergeMasks: false, mergeAnnotations: false });
533
- editor.downloadImage({ mergeMasks: false, mergeAnnotations: false });
534
- editor.downloadImage('edited_image.jpg'); // Backwards-compatible filename shorthand.
571
+
572
+ const dataUrl = await editor.exportImageBase64({ fileType: 'png', exportArea: 'image' });
573
+ const file = await editor.exportImageFile({
574
+ fileType: 'webp',
575
+ quality: 0.85,
576
+ fileName: 'edited',
577
+ });
578
+ await editor.downloadImage({
579
+ fileType: 'png',
580
+ fileName: 'edited',
581
+ mergeMasks: false,
582
+ mergeAnnotations: false,
583
+ });
535
584
  ```
536
585
 
537
586
  `mergeMasks` and `mergeAnnotations` in export options affect the rendered output
@@ -554,59 +603,59 @@ Pass an `ImageEditorOptions` object as the second constructor argument
554
603
  (or as the only argument when using the UMD global form). Unknown keys are
555
604
  ignored; nested `label` and `crop` objects are deep-merged with the defaults.
556
605
 
557
- | Option | Default | Description |
558
- | --------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
559
- | `canvasWidth` | `800` | Initial and hidden-container fallback canvas width in pixels. |
560
- | `canvasHeight` | `600` | Initial and hidden-container fallback canvas height in pixels. |
561
- | `backgroundColor` | `'transparent'` | Fabric canvas background color. |
562
- | `animationDuration` | `300` | Duration of scale and rotate animations (ms). |
563
- | `minScale` | `0.1` | Minimum scale factor. |
564
- | `maxScale` | `5.0` | Maximum scale factor. |
565
- | `scaleStep` | `0.05` | Scale delta per zoom step. |
566
- | `rotationStep` | `90` | Rotation step in degrees. |
567
- | `defaultLayoutMode` | `'expand'` | Initial layout mode for image loads until changed by `setLayoutMode()`. Use `'fit'`, `'cover'`, or `'expand'`. Invalid runtime values fall back to `'expand'`. |
568
- | `downsampleOnLoad` | `true` | Downsample large images on load. |
569
- | `downsampleMaxWidth` | `4000` | Max width before downsampling kicks in. |
570
- | `downsampleMaxHeight` | `3000` | Max height before downsampling kicks in. |
571
- | `downsampleQuality` | `0.92` | Lossy quality used when downsampling and exporting. |
572
- | `preserveSourceFormat` | `true` | Preserve PNG/WebP MIME through downsampling unless `downsampleMimeType` is set. |
573
- | `downsampleMimeType` | `null` | Explicit downsample MIME type. Overrides `preserveSourceFormat`. |
574
- | `imageLoadTimeoutMs` | `30000` | Maximum duration for both decode and Fabric image creation during `loadImage`. |
575
- | `exportMultiplier` | `1` | Output resolution multiplier. |
576
- | `maxExportPixels` | `50000000` | Maximum output pixel count after applying the export multiplier. Invalid values fall back to this default. |
577
- | `maxHistorySize` | `50` | Maximum undo-history entries. Snapshots may include full image data URLs, so large images can duplicate memory across history entries. Lower this for memory-constrained pages. |
578
- | `exportAreaByDefault` | `'image'` | Default export region for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
579
- | `mergeMasksByDefault` | `true` | Default mask rendering behavior for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
580
- | `mergeAnnotationsByDefault` | `true` | Default annotation rendering behavior for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
581
- | `defaultMaskWidth` | `50` | Default mask width. |
582
- | `defaultMaskHeight` | `80` | Default mask height. |
583
- | `defaultMaskConfig` | `{}` | Defaults applied by `createMask()` after `defaultMaskWidth` / `defaultMaskHeight` and before per-call config. Supports `MaskConfig` fields except `onCreate` and `fabricGenerator`. |
584
- | `defaultMosaicConfig` | see source | Defaults used to initialize the current Mosaic tool config. Supports `brushSize`, `blockSize`, preview circle styling, `outputFileType`, and `outputQuality`. Runtime Mosaic setters update the current config only. |
585
- | `defaultTextConfig` | see source | Defaults used to initialize the current Text annotation config. Runtime Text setters update the current config only. |
586
- | `defaultDrawConfig` | see source | Defaults used to initialize the current Draw mode config. Runtime Draw setters update the current config only. |
587
- | `maskRotatable` | `false` | Allow masks to be rotated by the user. |
588
- | `maskLabelOnSelect` | `true` | Show a label above a selected mask. |
589
- | `maskLabelOffset` | `3` | Pixel offset of the label from the mask's top-left corner. |
590
- | `maskName` | `'mask'` | Prefix used for auto-generated mask names. |
591
- | `textAnnotationName` | `'text'` | Prefix used for auto-generated text annotation names. |
592
- | `drawAnnotationName` | `'draw'` | Prefix used for auto-generated draw annotation names. |
593
- | `groupSelection` | `false` | Allow Fabric multi-object group selection on the canvas. |
594
- | `showPlaceholder` | `true` | Show a placeholder element while no image is loaded. |
595
- | `initialImageBase64` | `null` | Base64 data URL auto-loaded after construction. |
596
- | `defaultDownloadFileName` | `'edited_image.jpg'` | Default file name used by `downloadImage()`. |
597
- | `onImageLoadStart` | `null` | Called before a valid image load begins. |
598
- | `onImageLoaded` | `null` | Called as `(info, context)` once after a successful `loadImage`. Extra arguments are ignored by existing zero-argument JavaScript handlers. |
599
- | `onImageCleared` | `null` | Called when a committed image is replaced or cleared. |
600
- | `onImageChanged` | `null` | Called with a safe editor state snapshot after visible editor state changes. |
601
- | `onBusyChange` | `null` | Called only when the public busy state changes. |
602
- | `onEditorDisposed` | `null` | Called once when `dispose()` performs teardown. |
603
- | `onMasksChanged` | `null` | Called with a shallow copy of current mask objects after the mask collection changes. |
604
- | `onAnnotationsChanged` | `null` | Called with a shallow copy of current annotation objects after the annotation collection changes. |
605
- | `onSelectionChange` | `null` | Called with selected object payload after selection changes. |
606
- | `onError` | `null` | Called as `(error, message)` when the editor reports an error. |
607
- | `onWarning` | `null` | Called as `(error, message)` when the editor reports a recoverable warning. |
608
- | `label` | see source | `LabelConfig` for selected-mask labels (`getText`, `textOptions`, `create`). |
609
- | `crop` | see source | `CropConfig` (`minWidth`, `minHeight`, `padding`, `hideMasksDuringCrop`, `preserveMasksAfterCrop`, `allowRotationOfCropRect`, `exportFileType`, `exportQuality`). `applyCrop()` preserves the current image format by default (`'source'`) and falls back to PNG when unknown. |
606
+ | Option | Default | Description |
607
+ | --------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
608
+ | `canvasWidth` | `800` | Initial and hidden-container fallback canvas width in pixels. |
609
+ | `canvasHeight` | `600` | Initial and hidden-container fallback canvas height in pixels. |
610
+ | `backgroundColor` | `'transparent'` | Fabric canvas background color. |
611
+ | `animationDuration` | `300` | Duration of scale and rotate animations (ms). |
612
+ | `minScale` | `0.1` | Minimum scale factor. |
613
+ | `maxScale` | `5.0` | Maximum scale factor. |
614
+ | `scaleStep` | `0.05` | Scale delta per zoom step. |
615
+ | `rotationStep` | `90` | Rotation step in degrees. |
616
+ | `defaultLayoutMode` | `'expand'` | Initial layout mode for image loads until changed by `setLayoutMode()`. Use `'fit'`, `'cover'`, or `'expand'`. Invalid runtime values fall back to `'expand'`. |
617
+ | `downsampleOnLoad` | `true` | Downsample large images on load. |
618
+ | `downsampleMaxWidth` | `4000` | Max width before downsampling kicks in. |
619
+ | `downsampleMaxHeight` | `3000` | Max height before downsampling kicks in. |
620
+ | `downsampleQuality` | `0.92` | Lossy quality used when downsampling and exporting. |
621
+ | `preserveSourceFormat` | `true` | Preserve PNG/WebP MIME through downsampling unless `downsampleMimeType` is set. |
622
+ | `downsampleMimeType` | `null` | Explicit downsample MIME type. Overrides `preserveSourceFormat`. |
623
+ | `imageLoadTimeoutMs` | `30000` | Maximum duration for both decode and Fabric image creation during `loadImage`. |
624
+ | `exportMultiplier` | `1` | Output resolution multiplier. |
625
+ | `maxExportPixels` | `50000000` | Maximum output pixel count after applying the export multiplier. Invalid values fall back to this default. |
626
+ | `maxHistorySize` | `50` | Maximum undo-history entries. Snapshots may include full image data URLs, so large images can duplicate memory across history entries. Lower this for memory-constrained pages. |
627
+ | `exportAreaByDefault` | `'image'` | Default export region for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
628
+ | `mergeMasksByDefault` | `true` | Default mask rendering behavior for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
629
+ | `mergeAnnotationsByDefault` | `true` | Default annotation rendering behavior for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
630
+ | `defaultMaskWidth` | `50` | Default mask width. |
631
+ | `defaultMaskHeight` | `80` | Default mask height. |
632
+ | `defaultMaskConfig` | `{}` | Defaults applied by `createMask()` after `defaultMaskWidth` / `defaultMaskHeight` and before per-call config. Supports `MaskConfig` fields except `onCreate` and `fabricGenerator`. |
633
+ | `defaultMosaicConfig` | see source | Defaults used to initialize the current Mosaic tool config. Supports `brushSize`, `blockSize`, preview circle styling, `outputFileType`, and `outputQuality`. Runtime Mosaic setters update the current config only. |
634
+ | `defaultTextConfig` | see source | Defaults used to initialize the current Text annotation config. Runtime Text setters update the current config only. |
635
+ | `defaultDrawConfig` | see source | Defaults used to initialize the current Draw mode config. Runtime Draw setters update the current config only. |
636
+ | `maskRotatable` | `false` | Allow masks to be rotated by the user. |
637
+ | `maskLabelOnSelect` | `true` | Show a label above a selected mask. |
638
+ | `maskLabelOffset` | `3` | Pixel offset of the label from the mask's top-left corner. |
639
+ | `maskName` | `'mask'` | Prefix used for auto-generated mask names. |
640
+ | `textAnnotationName` | `'text'` | Prefix used for auto-generated text annotation names. |
641
+ | `drawAnnotationName` | `'draw'` | Prefix used for auto-generated draw annotation names. |
642
+ | `groupSelection` | `false` | Allow Fabric multi-object group selection on the canvas. |
643
+ | `showPlaceholder` | `true` | Show a placeholder element while no image is loaded. |
644
+ | `initialImageBase64` | `null` | Base64 data URL auto-loaded after construction. |
645
+ | `defaultDownloadFileName` | `'edited_image'` | Default filename base used by `exportImageFile()` and `downloadImage()`. The resolved export format supplies or corrects the extension. |
646
+ | `onImageLoadStart` | `null` | Called before a valid image load begins. |
647
+ | `onImageLoaded` | `null` | Called as `(info, context)` once after a successful `loadImage`. Extra arguments are ignored by existing zero-argument JavaScript handlers. |
648
+ | `onImageCleared` | `null` | Called when a committed image is replaced or cleared. |
649
+ | `onImageChanged` | `null` | Called with a safe editor state snapshot after visible editor state changes. |
650
+ | `onBusyChange` | `null` | Called only when the public busy state changes. |
651
+ | `onEditorDisposed` | `null` | Called once when `dispose()` performs teardown. |
652
+ | `onMasksChanged` | `null` | Called with a shallow copy of current mask objects after the mask collection changes. |
653
+ | `onAnnotationsChanged` | `null` | Called with a shallow copy of current annotation objects after the annotation collection changes. |
654
+ | `onSelectionChange` | `null` | Called with selected object payload after selection changes. |
655
+ | `onError` | `null` | Called as `(error, message)` when the editor reports an error. |
656
+ | `onWarning` | `null` | Called as `(error, message)` when the editor reports a recoverable warning. |
657
+ | `label` | see source | `LabelConfig` for selected-mask labels (`getText`, `textOptions`, `create`). |
658
+ | `crop` | see source | `CropConfig` (`minWidth`, `minHeight`, `padding`, `aspectRatio`, `hideMasksDuringCrop`, `preserveMasksAfterCrop`, `allowRotationOfCropRect`, `exportFileType`, `exportQuality`). `applyCrop()` preserves the current image format by default (`'source'`) and falls back to PNG when unknown. |
610
659
 
611
660
  `crop.exportFileType` defaults to `'source'`. Supported explicit values are
612
661
  `'png'`, `'jpeg'`, `'jpg'`, `'webp'`, and full image MIME strings. PNG is
@@ -619,23 +668,28 @@ preserve the current image MIME type when known and fall back to PNG when the
619
668
  source format cannot be determined. JPEG/WebP commits use
620
669
  `defaultMosaicConfig.outputQuality` when finite, otherwise `downsampleQuality`.
621
670
 
622
- ## Breaking changes in v2.2.0
671
+ ## Breaking changes in v2
623
672
 
673
+ - `Base64ExportOptions`, `ImageFileExportOptions`, and `DownloadImageOptions`
674
+ were replaced by `ImageExportOptions`.
675
+ - `downloadImage(fileName: string)` was removed. Use
676
+ `downloadImage({ fileName })`.
677
+ - `downloadImage()` now returns `Promise<void>`.
678
+ - `defaultDownloadFileName` now defaults to `'edited_image'`; export format
679
+ resolution supplies or corrects the final extension.
624
680
  - All editor-owned Fabric objects now require `editorObjectKind`.
625
681
  - `isMaskObject()` is strict and rejects legacy objects with only `maskId`.
626
682
  - `MaskObject.maskUid` is required.
627
683
  - Serialized states without `editorObjectKind` are not migrated.
628
684
  - Export option mergeMask was removed; use `mergeMasks`.
629
685
  - Constructor option mergeMaskByDefault was removed; use `mergeMasksByDefault`.
630
- - `ImageFileExportOptions` keeps `fileType` only; `format` remains limited to
631
- `exportImageBase64`.
632
686
 
633
687
  ## Example workflow
634
688
 
635
689
  1. Construct `ImageEditor` with options and call `init(idMap)` to wire it up.
636
690
  2. Load an image via `loadImage(base64)` or the bound file input.
637
- 3. Adjust with `scaleImage`, `rotateImage`, `resetImageTransform`, Crop mode,
638
- Mosaic mode, Text mode, or Draw mode.
691
+ 3. Adjust with `scaleImage`, `rotateImage`, `flipHorizontal`, `flipVertical`,
692
+ `resetImageTransform`, Crop mode, Mosaic mode, Text mode, or Draw mode.
639
693
  4. Add `createMask` and annotation calls, then inspect via `maskList` and
640
694
  `annotationList`.
641
695
  5. Use `mergeMasks()` or `mergeAnnotations()` to bake overlays into the image, then
@@ -714,8 +768,10 @@ import type {
714
768
  ExportArea,
715
769
  CropExportFileType,
716
770
  MosaicOutputFileType,
717
- Base64ExportOptions,
718
- ImageFileExportOptions,
771
+ ImageExportOptions,
772
+ CropAspectRatioPreset,
773
+ CropAspectRatio,
774
+ CropModeOptions,
719
775
  ImageInfo,
720
776
  ImageEditorState,
721
777
  ImageEditorSelection,