@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.
- package/README.md +152 -96
- package/dist/cjs/index.cjs +534 -139
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/core/default-options.js +8 -6
- package/dist/esm/core/default-options.js.map +1 -1
- package/dist/esm/core/public-types.js.map +1 -1
- package/dist/esm/core/state-serializer.js +8 -0
- package/dist/esm/core/state-serializer.js.map +1 -1
- package/dist/esm/crop/crop-controller.js +218 -10
- package/dist/esm/crop/crop-controller.js.map +1 -1
- package/dist/esm/export/export-format.js.map +1 -1
- package/dist/esm/export/export-service.js +57 -56
- package/dist/esm/export/export-service.js.map +1 -1
- package/dist/esm/image/image-loader.js +2 -2
- package/dist/esm/image/image-loader.js.map +1 -1
- package/dist/esm/image/transform-controller.js +42 -0
- package/dist/esm/image/transform-controller.js.map +1 -1
- package/dist/esm/image-editor.js +139 -14
- package/dist/esm/image-editor.js.map +1 -1
- package/dist/esm/utils/file.js +10 -0
- package/dist/esm/utils/file.js.map +1 -1
- package/dist/types/core/default-options.d.ts.map +1 -1
- package/dist/types/core/public-types.d.ts +68 -50
- package/dist/types/core/public-types.d.ts.map +1 -1
- package/dist/types/core/state-serializer.d.ts +5 -1
- package/dist/types/core/state-serializer.d.ts.map +1 -1
- package/dist/types/crop/crop-controller.d.ts +12 -7
- package/dist/types/crop/crop-controller.d.ts.map +1 -1
- package/dist/types/export/export-format.d.ts +7 -10
- package/dist/types/export/export-format.d.ts.map +1 -1
- package/dist/types/export/export-service.d.ts +27 -32
- package/dist/types/export/export-service.d.ts.map +1 -1
- package/dist/types/export/overlay-merge-service.d.ts +3 -3
- package/dist/types/export/overlay-merge-service.d.ts.map +1 -1
- package/dist/types/image/image-loader.d.ts +5 -5
- package/dist/types/image/image-loader.d.ts.map +1 -1
- package/dist/types/image/transform-controller.d.ts +14 -7
- package/dist/types/image/transform-controller.d.ts.map +1 -1
- package/dist/types/image-editor.d.ts +22 -12
- package/dist/types/image-editor.d.ts.map +1 -1
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/file.d.ts +13 -0
- package/dist/types/utils/file.d.ts.map +1 -1
- package/dist/umd/image-editor.umd.js +1 -1
- package/dist/umd/image-editor.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/image-editor.js
CHANGED
|
@@ -12,7 +12,7 @@ import { enterDrawMode as enterDrawModeImpl, exitDrawMode as exitDrawModeImpl, u
|
|
|
12
12
|
import { isAnnotationLocked, isAnnotationUnlocked } from './annotation/annotation-lock.js';
|
|
13
13
|
import { syncAnnotationRuntimeStates } from './annotation/annotation-style.js';
|
|
14
14
|
import { normalizeLayerOrder, getEditableOverlayRange } from './core/layer-order.js';
|
|
15
|
-
import { applyCrop as applyCropImpl, cancelCrop as cancelCropImpl, enterCropMode as enterCropModeImpl, } from './crop/crop-controller.js';
|
|
15
|
+
import { applyCrop as applyCropImpl, cancelCrop as cancelCropImpl, enterCropMode as enterCropModeImpl, setCropAspectRatio as setCropAspectRatioImpl, } from './crop/crop-controller.js';
|
|
16
16
|
import { enterMosaicMode as enterMosaicModeImpl, exitMosaicMode as exitMosaicModeImpl, updateMosaicPreview, } from './mosaic/mosaic-controller.js';
|
|
17
17
|
import { downloadImage as downloadImageImpl, exportImageBase64 as exportImageBase64Impl, exportImageFile as exportImageFileImpl, mergeAnnotations as mergeAnnotationsImpl, mergeMasks as mergeMasksImpl, } from './export/export-service.js';
|
|
18
18
|
import { loadImage as loadImageImpl } from './image/image-loader.js';
|
|
@@ -24,7 +24,7 @@ import { renderMaskList, updateMaskListSelection } from './mask/mask-list.js';
|
|
|
24
24
|
import { applyMaskSelectedStyle, applyMaskUnselectedStyle, reattachMaskHoverHandlers, } from './mask/mask-style.js';
|
|
25
25
|
import { DomBindings } from './ui/dom-bindings.js';
|
|
26
26
|
import { setPlaceholderVisible as setPlaceholderVisibleImpl } from './ui/visibility-state.js';
|
|
27
|
-
import { inferImageMimeType, readFileAsDataUrl, resetFileInput } from './utils/file.js';
|
|
27
|
+
import { inferImageMimeType, isSupportedImageDataUrl, readFileAsDataUrl, resetFileInput, } from './utils/file.js';
|
|
28
28
|
import { detectSourceMimeType } from './image/image-resampler.js';
|
|
29
29
|
const LAYOUT_EPSILON = 0.5;
|
|
30
30
|
const INTERNAL_OPERATION_TOKEN = Symbol('ImageEditorInternalOperation');
|
|
@@ -35,6 +35,8 @@ const CROP_MODE_CONTROL_KEYS = [
|
|
|
35
35
|
'rotateRightDegreesInput',
|
|
36
36
|
'rotateLeftButton',
|
|
37
37
|
'rotateRightButton',
|
|
38
|
+
'flipHorizontalButton',
|
|
39
|
+
'flipVerticalButton',
|
|
38
40
|
'createMaskButton',
|
|
39
41
|
'removeSelectedMaskButton',
|
|
40
42
|
'removeAllMasksButton',
|
|
@@ -63,6 +65,7 @@ const CROP_MODE_CONTROL_KEYS = [
|
|
|
63
65
|
'redoButton',
|
|
64
66
|
'imageInput',
|
|
65
67
|
'enterCropModeButton',
|
|
68
|
+
'cropAspectRatioSelect',
|
|
66
69
|
'applyCropButton',
|
|
67
70
|
'cancelCropButton',
|
|
68
71
|
'enterMosaicModeButton',
|
|
@@ -70,8 +73,12 @@ const CROP_MODE_CONTROL_KEYS = [
|
|
|
70
73
|
'mosaicBrushSizeInput',
|
|
71
74
|
'mosaicBlockSizeInput',
|
|
72
75
|
];
|
|
73
|
-
const CROP_MODE_ENABLED_KEYS = [
|
|
74
|
-
|
|
76
|
+
const CROP_MODE_ENABLED_KEYS = [
|
|
77
|
+
'cropAspectRatioSelect',
|
|
78
|
+
'applyCropButton',
|
|
79
|
+
'cancelCropButton',
|
|
80
|
+
];
|
|
81
|
+
const CROP_SESSION_ALLOWED_OPERATIONS = new Set(['setCropAspectRatio', 'applyCrop', 'cancelCrop']);
|
|
75
82
|
const TEXT_MODE_ENABLED_KEYS = [
|
|
76
83
|
'exitTextModeButton',
|
|
77
84
|
'textColorInput',
|
|
@@ -88,6 +95,8 @@ const MOSAIC_MODE_CONTROL_KEYS = [
|
|
|
88
95
|
'rotateRightDegreesInput',
|
|
89
96
|
'rotateLeftButton',
|
|
90
97
|
'rotateRightButton',
|
|
98
|
+
'flipHorizontalButton',
|
|
99
|
+
'flipVerticalButton',
|
|
91
100
|
'createMaskButton',
|
|
92
101
|
'removeSelectedMaskButton',
|
|
93
102
|
'removeAllMasksButton',
|
|
@@ -116,6 +125,7 @@ const MOSAIC_MODE_CONTROL_KEYS = [
|
|
|
116
125
|
'redoButton',
|
|
117
126
|
'imageInput',
|
|
118
127
|
'enterCropModeButton',
|
|
128
|
+
'cropAspectRatioSelect',
|
|
119
129
|
'applyCropButton',
|
|
120
130
|
'cancelCropButton',
|
|
121
131
|
'enterMosaicModeButton',
|
|
@@ -145,6 +155,8 @@ const IMAGE_EDITOR_OPERATIONS = new Set([
|
|
|
145
155
|
'saveState',
|
|
146
156
|
'scaleImage',
|
|
147
157
|
'rotateImage',
|
|
158
|
+
'flipHorizontal',
|
|
159
|
+
'flipVertical',
|
|
148
160
|
'resetImageTransform',
|
|
149
161
|
'createMask',
|
|
150
162
|
'removeSelectedMask',
|
|
@@ -174,6 +186,7 @@ const IMAGE_EDITOR_OPERATIONS = new Set([
|
|
|
174
186
|
'bringSelectedObjectToFront',
|
|
175
187
|
'sendSelectedObjectToBack',
|
|
176
188
|
'enterCropMode',
|
|
189
|
+
'setCropAspectRatio',
|
|
177
190
|
'applyCrop',
|
|
178
191
|
'cancelCrop',
|
|
179
192
|
'enterMosaicMode',
|
|
@@ -530,6 +543,8 @@ export class ImageEditor {
|
|
|
530
543
|
rotateRightDegreesInput: 'rotateRightDegreesInput',
|
|
531
544
|
rotateLeftButton: 'rotateLeftButton',
|
|
532
545
|
rotateRightButton: 'rotateRightButton',
|
|
546
|
+
flipHorizontalButton: 'flipHorizontalButton',
|
|
547
|
+
flipVerticalButton: 'flipVerticalButton',
|
|
533
548
|
createMaskButton: 'createMaskButton',
|
|
534
549
|
removeSelectedMaskButton: 'removeSelectedMaskButton',
|
|
535
550
|
removeAllMasksButton: 'removeAllMasksButton',
|
|
@@ -560,6 +575,7 @@ export class ImageEditor {
|
|
|
560
575
|
redoButton: 'redoButton',
|
|
561
576
|
imageInput: 'imageInput',
|
|
562
577
|
enterCropModeButton: 'enterCropModeButton',
|
|
578
|
+
cropAspectRatioSelect: 'cropAspectRatioSelect',
|
|
563
579
|
applyCropButton: 'applyCropButton',
|
|
564
580
|
cancelCropButton: 'cancelCropButton',
|
|
565
581
|
enterMosaicModeButton: 'enterMosaicModeButton',
|
|
@@ -667,6 +683,12 @@ export class ImageEditor {
|
|
|
667
683
|
this.bindElementIfExists('resetImageTransformButton', 'click', () => {
|
|
668
684
|
void this.resetImageTransform();
|
|
669
685
|
});
|
|
686
|
+
this.bindElementIfExists('flipHorizontalButton', 'click', () => {
|
|
687
|
+
void this.flipHorizontal();
|
|
688
|
+
});
|
|
689
|
+
this.bindElementIfExists('flipVerticalButton', 'click', () => {
|
|
690
|
+
void this.flipVertical();
|
|
691
|
+
});
|
|
670
692
|
this.bindElementIfExists('createMaskButton', 'click', () => {
|
|
671
693
|
this.createMask();
|
|
672
694
|
});
|
|
@@ -751,7 +773,11 @@ export class ImageEditor {
|
|
|
751
773
|
void this.rotateImage(this.currentRotation + step);
|
|
752
774
|
});
|
|
753
775
|
this.bindElementIfExists('enterCropModeButton', 'click', () => {
|
|
754
|
-
this.enterCropMode();
|
|
776
|
+
this.enterCropMode({ aspectRatio: this.getSelectedCropAspectRatio() });
|
|
777
|
+
});
|
|
778
|
+
this.bindElementIfExists('cropAspectRatioSelect', 'change', () => {
|
|
779
|
+
if (this.cropSession)
|
|
780
|
+
this.setCropAspectRatio(this.getSelectedCropAspectRatio());
|
|
755
781
|
});
|
|
756
782
|
this.bindElementIfExists('applyCropButton', 'click', () => {
|
|
757
783
|
void this.applyCrop().catch((error) => {
|
|
@@ -904,7 +930,7 @@ export class ImageEditor {
|
|
|
904
930
|
return;
|
|
905
931
|
if (this.isDisposed)
|
|
906
932
|
return;
|
|
907
|
-
if (
|
|
933
|
+
if (!isSupportedImageDataUrl(base64))
|
|
908
934
|
return;
|
|
909
935
|
if (!this.canRunIdleOperation('loadImage', options))
|
|
910
936
|
return;
|
|
@@ -1038,12 +1064,27 @@ export class ImageEditor {
|
|
|
1038
1064
|
return false;
|
|
1039
1065
|
}
|
|
1040
1066
|
}
|
|
1067
|
+
getSelectedCropAspectRatio() {
|
|
1068
|
+
const inputId = this.elements.cropAspectRatioSelect;
|
|
1069
|
+
const inputEl = inputId
|
|
1070
|
+
? document.getElementById(inputId)
|
|
1071
|
+
: null;
|
|
1072
|
+
const value = inputEl && 'value' in inputEl ? String(inputEl.value).trim() : '';
|
|
1073
|
+
return (value || 'free');
|
|
1074
|
+
}
|
|
1041
1075
|
isExpectedIdleGuardError(error, operationName) {
|
|
1042
1076
|
return (error instanceof Error &&
|
|
1043
1077
|
error.message.startsWith(`[ImageEditor] Cannot run "${operationName}" `));
|
|
1044
1078
|
}
|
|
1045
1079
|
assertCanQueueAnimation(operationName, options) {
|
|
1046
|
-
|
|
1080
|
+
const token = this.getInternalOperationToken(options);
|
|
1081
|
+
this.operationGuard.assertCanQueueAnimation(operationName, token);
|
|
1082
|
+
const activeToolMode = this.getActiveToolMode();
|
|
1083
|
+
if (activeToolMode &&
|
|
1084
|
+
!this.operationGuard.isOwnOperation(token) &&
|
|
1085
|
+
!TOOL_MODE_ALLOWED_OPERATIONS[activeToolMode].has(operationName)) {
|
|
1086
|
+
throw new Error(`[ImageEditor] Cannot run "${operationName}" while ${activeToolMode} mode is active.`);
|
|
1087
|
+
}
|
|
1047
1088
|
}
|
|
1048
1089
|
isImageLoaded() {
|
|
1049
1090
|
var _a, _b;
|
|
@@ -1158,6 +1199,7 @@ export class ImageEditor {
|
|
|
1158
1199
|
return this.getActiveToolMode() !== null;
|
|
1159
1200
|
}
|
|
1160
1201
|
getEditorState() {
|
|
1202
|
+
var _a, _b;
|
|
1161
1203
|
const canvasWidth = this.canvas ? this.canvas.getWidth() : 0;
|
|
1162
1204
|
const canvasHeight = this.canvas ? this.canvas.getHeight() : 0;
|
|
1163
1205
|
const image = this.getImageInfo();
|
|
@@ -1168,6 +1210,8 @@ export class ImageEditor {
|
|
|
1168
1210
|
annotationCount: this.getAnnotations().length,
|
|
1169
1211
|
currentScale: this.currentScale,
|
|
1170
1212
|
currentRotation: this.currentRotation,
|
|
1213
|
+
isFlippedHorizontally: !!((_a = this.originalImage) === null || _a === void 0 ? void 0 : _a.flipX),
|
|
1214
|
+
isFlippedVertically: !!((_b = this.originalImage) === null || _b === void 0 ? void 0 : _b.flipY),
|
|
1171
1215
|
isBusy: this.isBusy(),
|
|
1172
1216
|
activeToolMode: this.getActiveToolMode(),
|
|
1173
1217
|
isCropMode: this.cropSession !== null,
|
|
@@ -1497,6 +1541,70 @@ export class ImageEditor {
|
|
|
1497
1541
|
this.emitBusyChangeIfChanged(context);
|
|
1498
1542
|
});
|
|
1499
1543
|
}
|
|
1544
|
+
flipHorizontal() {
|
|
1545
|
+
if (this.isDisposed || !this.transformController)
|
|
1546
|
+
return Promise.resolve();
|
|
1547
|
+
try {
|
|
1548
|
+
this.assertCanQueueAnimation('flipHorizontal');
|
|
1549
|
+
}
|
|
1550
|
+
catch (error) {
|
|
1551
|
+
return Promise.reject(error);
|
|
1552
|
+
}
|
|
1553
|
+
const controller = this.transformController;
|
|
1554
|
+
const context = this.buildCallbackContext('flipHorizontal', false);
|
|
1555
|
+
const job = this.animQueue.add(async () => {
|
|
1556
|
+
if (this.isDisposed)
|
|
1557
|
+
return;
|
|
1558
|
+
this.updateUi();
|
|
1559
|
+
try {
|
|
1560
|
+
await controller.flipHorizontal();
|
|
1561
|
+
if (!this.isDisposed)
|
|
1562
|
+
this.emitImageChanged(context);
|
|
1563
|
+
}
|
|
1564
|
+
finally {
|
|
1565
|
+
if (!this.isDisposed) {
|
|
1566
|
+
this.updateInputs();
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
this.emitBusyChangeIfChanged(context);
|
|
1571
|
+
return job.finally(() => {
|
|
1572
|
+
this.refreshUiAfterQueuedAnimation();
|
|
1573
|
+
this.emitBusyChangeIfChanged(context);
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
flipVertical() {
|
|
1577
|
+
if (this.isDisposed || !this.transformController)
|
|
1578
|
+
return Promise.resolve();
|
|
1579
|
+
try {
|
|
1580
|
+
this.assertCanQueueAnimation('flipVertical');
|
|
1581
|
+
}
|
|
1582
|
+
catch (error) {
|
|
1583
|
+
return Promise.reject(error);
|
|
1584
|
+
}
|
|
1585
|
+
const controller = this.transformController;
|
|
1586
|
+
const context = this.buildCallbackContext('flipVertical', false);
|
|
1587
|
+
const job = this.animQueue.add(async () => {
|
|
1588
|
+
if (this.isDisposed)
|
|
1589
|
+
return;
|
|
1590
|
+
this.updateUi();
|
|
1591
|
+
try {
|
|
1592
|
+
await controller.flipVertical();
|
|
1593
|
+
if (!this.isDisposed)
|
|
1594
|
+
this.emitImageChanged(context);
|
|
1595
|
+
}
|
|
1596
|
+
finally {
|
|
1597
|
+
if (!this.isDisposed) {
|
|
1598
|
+
this.updateInputs();
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
this.emitBusyChangeIfChanged(context);
|
|
1603
|
+
return job.finally(() => {
|
|
1604
|
+
this.refreshUiAfterQueuedAnimation();
|
|
1605
|
+
this.emitBusyChangeIfChanged(context);
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1500
1608
|
resetImageTransform() {
|
|
1501
1609
|
if (this.isDisposed || !this.transformController)
|
|
1502
1610
|
return Promise.resolve();
|
|
@@ -2385,7 +2493,7 @@ export class ImageEditor {
|
|
|
2385
2493
|
this.updateUi();
|
|
2386
2494
|
}
|
|
2387
2495
|
}
|
|
2388
|
-
downloadImage(options) {
|
|
2496
|
+
async downloadImage(options) {
|
|
2389
2497
|
if (!this.canvas)
|
|
2390
2498
|
return;
|
|
2391
2499
|
if (!this.canRunIdleOperation('downloadImage'))
|
|
@@ -2396,7 +2504,7 @@ export class ImageEditor {
|
|
|
2396
2504
|
this.emitBusyChangeIfChanged(callbackContext);
|
|
2397
2505
|
const exportContext = this.buildExportServiceContext();
|
|
2398
2506
|
try {
|
|
2399
|
-
downloadImageImpl(exportContext, options);
|
|
2507
|
+
await downloadImageImpl(exportContext, options);
|
|
2400
2508
|
}
|
|
2401
2509
|
finally {
|
|
2402
2510
|
this.operationGuard.endBusyOperation(operationToken);
|
|
@@ -2671,7 +2779,7 @@ export class ImageEditor {
|
|
|
2671
2779
|
},
|
|
2672
2780
|
};
|
|
2673
2781
|
}
|
|
2674
|
-
enterCropMode() {
|
|
2782
|
+
enterCropMode(options = {}) {
|
|
2675
2783
|
if (!this.canvas || !this.originalImage)
|
|
2676
2784
|
return;
|
|
2677
2785
|
if (this.cropSession)
|
|
@@ -2681,12 +2789,23 @@ export class ImageEditor {
|
|
|
2681
2789
|
if (!this.canRunIdleOperation('enterCropMode'))
|
|
2682
2790
|
return;
|
|
2683
2791
|
const cropControllerContext = this.buildCropControllerContext();
|
|
2684
|
-
enterCropModeImpl(cropControllerContext);
|
|
2792
|
+
enterCropModeImpl(cropControllerContext, options);
|
|
2685
2793
|
this.updateUi();
|
|
2686
2794
|
const callbackContext = this.buildCallbackContext('enterCropMode', false);
|
|
2687
2795
|
this.emitBusyChangeIfChanged(callbackContext);
|
|
2688
2796
|
this.emitImageChanged(callbackContext);
|
|
2689
2797
|
}
|
|
2798
|
+
setCropAspectRatio(aspectRatio) {
|
|
2799
|
+
if (!this.canvas || !this.cropSession)
|
|
2800
|
+
return;
|
|
2801
|
+
if (!this.canRunIdleOperation('setCropAspectRatio'))
|
|
2802
|
+
return;
|
|
2803
|
+
const cropControllerContext = this.buildCropControllerContext();
|
|
2804
|
+
setCropAspectRatioImpl(cropControllerContext, aspectRatio);
|
|
2805
|
+
this.updateUi();
|
|
2806
|
+
const callbackContext = this.buildCallbackContext('setCropAspectRatio', false);
|
|
2807
|
+
this.emitImageChanged(callbackContext);
|
|
2808
|
+
}
|
|
2690
2809
|
cancelCrop() {
|
|
2691
2810
|
if (!this.canvas || !this.cropSession)
|
|
2692
2811
|
return;
|
|
@@ -2831,7 +2950,7 @@ export class ImageEditor {
|
|
|
2831
2950
|
}
|
|
2832
2951
|
}
|
|
2833
2952
|
updateUi() {
|
|
2834
|
-
var _a;
|
|
2953
|
+
var _a, _b, _c;
|
|
2835
2954
|
if (!this.canvas)
|
|
2836
2955
|
return;
|
|
2837
2956
|
const hasImage = !!this.originalImage;
|
|
@@ -2843,7 +2962,10 @@ export class ImageEditor {
|
|
|
2843
2962
|
const hasSelectedMask = !!(activeObject && isMaskObject(activeObject));
|
|
2844
2963
|
const hasSelectedAnnotation = !!(activeObject && isAnnotationObject(activeObject));
|
|
2845
2964
|
const hasSelectedEditableObject = !!activeObject && isEditableOverlayObject(activeObject);
|
|
2846
|
-
const isDefaultTransform = this.currentScale === 1 &&
|
|
2965
|
+
const isDefaultTransform = this.currentScale === 1 &&
|
|
2966
|
+
this.currentRotation === 0 &&
|
|
2967
|
+
!((_a = this.originalImage) === null || _a === void 0 ? void 0 : _a.flipX) &&
|
|
2968
|
+
!((_b = this.originalImage) === null || _b === void 0 ? void 0 : _b.flipY);
|
|
2847
2969
|
const canUndo = this.historyManager.canUndo();
|
|
2848
2970
|
const canRedo = this.historyManager.canRedo();
|
|
2849
2971
|
const isInCropMode = this.cropSession !== null;
|
|
@@ -2851,7 +2973,7 @@ export class ImageEditor {
|
|
|
2851
2973
|
const isInTextMode = this.textSession !== null;
|
|
2852
2974
|
const isInDrawMode = this.drawSession !== null;
|
|
2853
2975
|
const isBusy = this.operationGuard.isBusy() || this.animQueue.isBusy();
|
|
2854
|
-
const isMosaicApplying = ((
|
|
2976
|
+
const isMosaicApplying = ((_c = this.mosaicSession) === null || _c === void 0 ? void 0 : _c.isApplying) === true;
|
|
2855
2977
|
if (isInCropMode) {
|
|
2856
2978
|
CROP_MODE_CONTROL_KEYS.forEach((key) => {
|
|
2857
2979
|
this.setControlEnabled(key, !isBusy && CROP_MODE_ENABLED_KEYS.includes(key));
|
|
@@ -2884,6 +3006,8 @@ export class ImageEditor {
|
|
|
2884
3006
|
this.setControlEnabled('zoomOutButton', hasImage && !isBusy && this.currentScale > this.options.minScale);
|
|
2885
3007
|
this.setControlEnabled('rotateLeftButton', hasImage && !isBusy);
|
|
2886
3008
|
this.setControlEnabled('rotateRightButton', hasImage && !isBusy);
|
|
3009
|
+
this.setControlEnabled('flipHorizontalButton', hasImage && !isBusy);
|
|
3010
|
+
this.setControlEnabled('flipVerticalButton', hasImage && !isBusy);
|
|
2887
3011
|
this.setControlEnabled('createMaskButton', hasImage && !isBusy);
|
|
2888
3012
|
this.setControlEnabled('removeSelectedMaskButton', hasSelectedMask && !isBusy);
|
|
2889
3013
|
this.setControlEnabled('removeAllMasksButton', hasMasks && !isBusy);
|
|
@@ -2901,6 +3025,7 @@ export class ImageEditor {
|
|
|
2901
3025
|
this.setControlEnabled('undoButton', hasImage && !isBusy && canUndo);
|
|
2902
3026
|
this.setControlEnabled('redoButton', hasImage && !isBusy && canRedo);
|
|
2903
3027
|
this.setControlEnabled('enterCropModeButton', hasImage && !isBusy);
|
|
3028
|
+
this.setControlEnabled('cropAspectRatioSelect', hasImage && !isBusy);
|
|
2904
3029
|
this.setControlEnabled('enterMosaicModeButton', hasImage && !isBusy);
|
|
2905
3030
|
this.setControlEnabled('enterTextModeButton', hasImage && !isBusy);
|
|
2906
3031
|
this.setControlEnabled('enterDrawModeButton', hasImage && !isBusy);
|