@bensitu/image-editor 1.4.2 → 1.5.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.
@@ -1,9 +1,9 @@
1
1
  import S from"fabric";/**
2
2
  * @file image-editor.js
3
3
  * @module image-editor
4
- * @version 1.4.2
4
+ * @version 1.5.0
5
5
  * @author Ben Situ
6
6
  * @license MIT
7
7
  * @description Lightweight canvas-based image editor with masking/transform/export support.
8
- */var _=null,N=Symbol.for("ImageEditorInternalOperation");function W(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:null}function P(){let b=W();return b&&b.fabric?b.fabric:null}function L(b){return _=b||P(),_}function R(){return _||L(),_}var T=class{constructor(t={}){let e={getText:o=>o.maskName,textOptions:{fontSize:12,fill:"#fff",backgroundColor:"rgba(0,0,0,0.7)",padding:2,fontFamily:"monospace",fontWeight:"bold",selectable:!1,evented:!1,originX:"left",originY:"top"}},i={minWidth:100,minHeight:100,padding:10,hideMasksDuringCrop:!0,preserveMasksAfterCrop:!1,allowRotationOfCropRect:!1},s=t.label||{},a=t.crop||{};this.options={canvasWidth:800,canvasHeight:600,backgroundColor:"transparent",animationDuration:300,minScale:.1,maxScale:5,scaleStep:.05,rotationStep:90,expandCanvasToImage:!0,fitImageToCanvas:!1,coverImageToCanvas:!1,downsampleOnLoad:!0,downsampleMaxWidth:4e3,downsampleMaxHeight:3e3,downsampleQuality:.92,preserveSourceFormat:!0,downsampleMimeType:null,imageLoadTimeoutMs:3e4,exportMultiplier:1,exportImageAreaByDefault:!0,defaultMaskWidth:50,defaultMaskHeight:80,maskRotatable:!1,maskLabelOnSelect:!0,maskLabelOffset:3,maskName:"mask",groupSelection:!1,showPlaceholder:!0,initialImageBase64:null,defaultDownloadFileName:"edited_image.jpg",onError:null,onWarning:null,...t,label:{...e,...s,textOptions:{...e.textOptions,...s.textOptions||{}}},crop:{...i,...a}},this._fabricLoaded=!!R(),this._fabricLoaded||this._reportError("fabric.js is not loaded. Please include fabric.js first. Initialization will be aborted."),this.canvas=null,this.canvasElement=null,this.containerElement=null,this.placeholderElement=null,this.originalImage=null,this.baseImageScale=1,this.currentScale=1,this.currentRotation=0,this.maskCounter=0,this.isAnimating=!1,this._isLoading=!1,this._activeOperationName=null,this._activeOperationToken=null,this.elements={},this.isImageLoadedToCanvas=!1,this.maxHistorySize=50,this._handlersByElementKey={},this._elementCache={},this._elementOriginalPointerEvents=new Map,this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null,this._lastSnapshot=null,this._cropMode=!1,this._cropRect=null,this._cropHandlers=[],this._cropPrevEvented=null,this._prevSelectionSetting=void 0,this._containerOriginalOverflow=null,this._lastContainerViewportSize=null,this._canvasElementOriginalStyle=null,this._visibilityStateByElement=new WeakMap,this._scrollbarSizeCache=null,this._activeAnimationRejectors=new Set,this._disposed=!1,this._initialized=!1,this.onImageLoaded=typeof t.onImageLoaded=="function"?t.onImageLoaded:null,this.animationQueue=new C,this.historyManager=new M(this.maxHistorySize)}get canvasEl(){return this.canvasElement}set canvasEl(t){this.canvasElement=t}get containerEl(){return this.containerElement}set containerEl(t){this.containerElement=t}get placeholderEl(){return this.placeholderElement}set placeholderEl(t){this.placeholderElement=t}init(t={}){if(!this._fabricLoaded)return;(this._initialized||this.canvas)&&this.dispose(),this._disposed=!1,this._initialized=!0,this.animationQueue=new C,this.historyManager=new M(this.maxHistorySize),this._visibilityStateByElement=new WeakMap,this._activeAnimationRejectors=new Set,this._isLoading=!1,this._activeOperationName=null,this._activeOperationToken=null,this._elementOriginalPointerEvents=new Map,this._containerOriginalOverflow=null,this._lastContainerViewportSize=null,this._canvasElementOriginalStyle=null;let e={canvas:"fabricCanvas",canvasContainer:null,imgPlaceholder:"imgPlaceholder",scaleRate:"scaleRate",rotationLeftInput:"rotationLeftInput",rotationRightInput:"rotationRightInput",rotateLeftBtn:"rotateLeftBtn",rotateRightBtn:"rotateRightBtn",addMaskBtn:"addMaskBtn",removeMaskBtn:"removeMaskBtn",removeAllMasksBtn:"removeAllMasksBtn",mergeBtn:"mergeBtn",downloadBtn:"downloadBtn",maskList:"maskList",zoomInBtn:"zoomInBtn",zoomOutBtn:"zoomOutBtn",resetBtn:"resetBtn",undoBtn:"undoBtn",redoBtn:"redoBtn",imageInput:"imageInput",cropBtn:"cropBtn",applyCropBtn:"applyCropBtn",cancelCropBtn:"cancelCropBtn"};this.elements={...e,...t},this._elementCache={},this._initCanvas(),this._bindEvents(),this._updateInputs(),this._updateMaskList(),this._updateUI(),this.options.initialImageBase64?this.loadImage(this.options.initialImageBase64):this._updatePlaceholderStatus()}_reportError(t,e=null){let i=this.options&&this.options.onError;if(typeof i=="function")try{i(e,t)}catch{}}_reportWarning(t,e=null){let i=this.options&&this.options.onWarning;if(typeof i=="function")try{i(e,t)}catch{}}_initCanvas(){let t=this._getElement("canvas");if(!t)throw new Error("Canvas is not found: "+this.elements.canvas);if(this.canvasElement=t,this._canvasElementOriginalStyle={display:t.style.display||"",width:t.style.width||"",height:t.style.height||"",maxWidth:t.style.maxWidth||""},this.elements.canvasContainer){let s=this._getElement("canvasContainer");this.containerElement=s||t.parentElement}else this.containerElement=t.parentElement;this.placeholderElement=this._getElement("imgPlaceholder")||null;let e=this.options.canvasWidth,i=this.options.canvasHeight;if(this.containerElement){let s=Math.floor(this.containerElement.clientWidth),a=Math.floor(this.containerElement.clientHeight);s>0&&a>0&&(e=s,i=a,this._lastContainerViewportSize={width:s,height:a})}this.canvas=new _.Canvas(t,{width:e,height:i,backgroundColor:this.options.backgroundColor,selection:this.options.groupSelection,preserveObjectStacking:!0}),this.canvas.on("selection:created",s=>this._handleSelectionChanged(s.selected)),this.canvas.on("selection:updated",s=>this._handleSelectionChanged(s.selected)),this.canvas.on("selection:cleared",()=>this._handleSelectionChanged([])),this.canvas.on("object:moving",s=>{s.target&&s.target.maskId&&this._syncMaskLabel(s.target)}),this.canvas.on("object:scaling",s=>{s.target&&s.target.maskId&&this._syncMaskLabel(s.target)}),this.canvas.on("object:rotating",s=>{s.target&&s.target.maskId&&this._syncMaskLabel(s.target)}),this.canvas.on("object:modified",s=>this._handleObjectModified(s.target)),this.canvasElement.style.display="block"}_getElement(t){let e=this.elements&&this.elements[t];if(!e)return null;if(this._elementCache&&Object.prototype.hasOwnProperty.call(this._elementCache,t))return this._elementCache[t];let i=document.getElementById(e);return this._elementCache&&(this._elementCache[t]=i||null),i||null}_handleObjectModified(t){let e=this._getModifiedMasks(t);e.length&&(e.forEach(i=>{typeof i.setCoords=="function"&&i.setCoords(),this._syncMaskLabel(i)}),this._expandCanvasToFitObjects(e),this.saveState())}_getModifiedMasks(t){if(!t)return[];if(t.maskId)return[t];let e=typeof t.getObjects=="function"?t.getObjects():[];return Array.isArray(e)?e.filter(i=>i&&i.maskId):[]}_syncContainerOverflow(t={}){if(!this.containerElement||!this.containerElement.style)return;this._captureContainerOverflowState();let e=t.preserveScroll===!0;this.options.coverImageToCanvas?(this.containerElement.style.overflow="scroll",e||(this.containerElement.scrollLeft=0,this.containerElement.scrollTop=0)):this.options.fitImageToCanvas?(this.containerElement.style.overflow="auto",e||(this.containerElement.scrollLeft=0,this.containerElement.scrollTop=0)):this._restoreContainerOverflowState()}_captureContainerOverflowState(){!this.containerElement||!this.containerElement.style||this._containerOriginalOverflow||(this._containerOriginalOverflow={overflow:this.containerElement.style.overflow||"",overflowX:this.containerElement.style.overflowX||"",overflowY:this.containerElement.style.overflowY||""})}_restoreContainerOverflowState(){!this.containerElement||!this.containerElement.style||!this._containerOriginalOverflow||(this.containerElement.style.overflow=this._containerOriginalOverflow.overflow,this.containerElement.style.overflowX=this._containerOriginalOverflow.overflowX,this.containerElement.style.overflowY=this._containerOriginalOverflow.overflowY)}_restoreContainerOverflowSnapshot(t){!this.containerElement||!this.containerElement.style||!t||(this.containerElement.style.overflow=t.overflow||"",this.containerElement.style.overflowX=t.overflowX||"",this.containerElement.style.overflowY=t.overflowY||"")}_bindEvents(){this._bindIfExists("uploadArea","click",()=>{let t=this._getElement("uploadArea");this._isElementDisabled(t)||this._getElement("imageInput")?.click()}),this._bindIfExists("imageInput","change",t=>{let e=t.target.files&&t.target.files[0];e&&this._loadImageFile(e).catch(i=>this._reportError("Image file could not be loaded",i)).finally(()=>{t.target.value=""})}),this._bindIfExists("zoomInBtn","click",()=>this.scaleImage(this.currentScale+this.options.scaleStep).catch(t=>this._reportError("scaleImage failed",t))),this._bindIfExists("zoomOutBtn","click",()=>this.scaleImage(this.currentScale-this.options.scaleStep).catch(t=>this._reportError("scaleImage failed",t))),this._bindIfExists("resetBtn","click",()=>{this.resetImageTransform().catch(t=>this._reportError("resetImageTransform failed",t))}),this._bindIfExists("addMaskBtn","click",()=>this.createMask()),this._bindIfExists("removeMaskBtn","click",()=>this.removeSelectedMask()),this._bindIfExists("removeAllMasksBtn","click",()=>this.removeAllMasks()),this._bindIfExists("mergeBtn","click",()=>this.mergeMasks().catch(t=>this._reportError("merge error",t))),this._bindIfExists("downloadBtn","click",()=>this.downloadImage()),this._bindIfExists("undoBtn","click",()=>this.undo().catch(t=>this._reportError("undo failed",t))),this._bindIfExists("redoBtn","click",()=>this.redo().catch(t=>this._reportError("redo failed",t))),this._bindIfExists("rotateLeftBtn","click",()=>{let t=this._getElement("rotationLeftInput"),e=this.options.rotationStep;if(t){let i=parseFloat(t.value);isNaN(i)||(e=i)}this.rotateImage(this.currentRotation-e).catch(i=>this._reportError("rotateImage failed",i))}),this._bindIfExists("rotateRightBtn","click",()=>{let t=this._getElement("rotationRightInput"),e=this.options.rotationStep;if(t){let i=parseFloat(t.value);isNaN(i)||(e=i)}this.rotateImage(this.currentRotation+e).catch(i=>this._reportError("rotateImage failed",i))}),this._bindIfExists("cropBtn","click",()=>this.enterCropMode()),this._bindIfExists("applyCropBtn","click",()=>{this.applyCrop().catch(t=>this._reportError("applyCrop failed",t))}),this._bindIfExists("cancelCropBtn","click",()=>this.cancelCrop()),this._bindIfExists("maskList","click",t=>this._handleMaskListClick(t))}_bindIfExists(t,e,i){let s=this._getElement(t);s&&(s.addEventListener(e,i),this._handlersByElementKey=this._handlersByElementKey||{},this._handlersByElementKey[t]||(this._handlersByElementKey[t]=[]),this._handlersByElementKey[t].push({eventName:e,handler:i}))}_loadImageFile(t){if(!this._isSupportedImageFile(t)){let e=new Error("Selected file is not a supported image");return this._reportError("Selected file is not a supported image",e),Promise.reject(e)}return new Promise((e,i)=>{let s=new FileReader;s.onload=a=>{this.loadImage(a.target.result).then(e).catch(i)},s.onerror=a=>{let o=new Error("Image file could not be read");this._reportError("Image file could not be read",a),i(o)},s.readAsDataURL(t)})}_isSupportedImageFile(t){if(!t)return!1;if(typeof t.type=="string"&&t.type.startsWith("image/"))return!0;let e=String(t.name||"");return/\.(avif|bmp|gif|jpe?g|png|webp)$/i.test(e)}_warnOnImageLayoutOptionConflict(){let t=[["fitImageToCanvas",this.options.fitImageToCanvas],["coverImageToCanvas",this.options.coverImageToCanvas],["expandCanvasToImage",this.options.expandCanvasToImage]].filter(([,e])=>!!e).map(([e])=>e);t.length<=1||this._reportWarning(`Only one image layout mode should be enabled. Active modes: ${t.join(", ")}.`)}async loadImage(t,e={}){if(!this._fabricLoaded||!this.canvas||this._disposed||!t||typeof t!="string"||!t.startsWith("data:image/"))return;this._assertIdleForOperation("loadImage",e),this._isLoading=!0,this._updateUI(),this._warnOnImageLayoutOptionConflict();let i=this._captureLoadImageTransaction();try{let s=await this._createImageElement(t);if(this._disposed||!this.canvas)throw new Error("Editor was disposed while loading image");let a=t,o=Number(this.options.downsampleMaxWidth),c=Number(this.options.downsampleMaxHeight);if(this.options.downsampleOnLoad&&o>0&&c>0){if(s.naturalWidth>o||s.naturalHeight>c){let m=Math.min(o/s.naturalWidth,c/s.naturalHeight),g=Math.round(s.naturalWidth*m),p=Math.round(s.naturalHeight*m);a=this._resampleImageToDataURL(s,g,p,this._normalizeQuality(this.options.downsampleQuality),t)}}else this.options.downsampleOnLoad&&this._reportWarning("loadImage: downsample limits must be positive numbers; using the original image");let l=await this._createFabricImageFromURL(a);if(this._disposed||!this.canvas)throw new Error("Editor was disposed while loading image");this.canvas.discardActiveObject(),this._hideAllMaskLabels(),this.canvas.clear(),this.canvas.setBackgroundColor(this.options.backgroundColor,this.canvas.renderAll.bind(this.canvas)),l.set({originX:"left",originY:"top",selectable:!1,evented:!1}),this._setPlaceholderVisible(!1),this._syncContainerOverflow({preserveScroll:e.preserveScroll===!0});let r=l.width,n=l.height,h=this._getContainerViewportSize(),f=h.width,d=h.height;if(this.options.fitImageToCanvas){let u=Math.max(1,f-1),m=Math.max(1,d-1);this._setCanvasSizeInt(u,m);let g=Math.min(u/r,m/n,1);l.set({left:0,top:0}),l.scale(g),this.baseImageScale=l.scaleX||1}else if(this.options.coverImageToCanvas){let u=this._calculateCoverCanvasLayout(r,n);this._setCanvasSizeInt(u.canvasWidth,u.canvasHeight),l.set({left:0,top:0}),l.scale(u.scale),this.baseImageScale=l.scaleX||1}else if(this.options.expandCanvasToImage){let u=Math.max(f,Math.floor(r)),m=Math.max(d,Math.floor(n));this._setCanvasSizeInt(u,m),l.set({left:0,top:0}),l.scale(1),this.baseImageScale=1}else{let u=Math.max(this.options.canvasWidth,f),m=Math.max(this.options.canvasHeight,d);this._setCanvasSizeInt(u,m);let g=Math.min(u/r,m/n,1);l.set({left:0,top:0}),l.scale(g),this.baseImageScale=l.scaleX||1}this.originalImage=l,this.canvas.add(l),this.canvas.sendToBack(l),this._clearMaskPlacementMemory(),e.resetMaskCounter!==!1&&(this.maskCounter=0),this.currentScale=1,this.currentRotation=0,this._updateInputs(),this._updateMaskList(),this.isImageLoadedToCanvas=!0,this._updateUI(),this.canvas.renderAll(),this._lastSnapshot=this._captureCanvasStateOrThrow("loadImage"),typeof this.onImageLoaded=="function"&&this.onImageLoaded()}catch(s){throw await this._rollbackLoadImageTransaction(i),s}finally{this._isLoading=!1,!this._disposed&&this.canvas&&this._updateUI()}}isImageLoaded(){let t=R();return!!(this.originalImage&&t&&this.originalImage instanceof t.Image&&this.originalImage.width>0&&this.originalImage.height>0)}isBusy(){return!!(this.isAnimating||this._cropMode||this._isLoading||this._activeOperationToken||this.animationQueue&&this.animationQueue.isBusy())}_createImageElement(t,e=this.options.imageLoadTimeoutMs){return new Promise((i,s)=>{let a=new Image,o=!1,c=Number.isFinite(Number(e))&&Number(e)>0?Number(e):3e4,l,r=n=>{o||(o=!0,clearTimeout(l),a.onload=null,a.onerror=null,n())};l=setTimeout(()=>{r(()=>s(new Error("Image load timed out")));try{a.src=""}catch(n){}},c),a.onload=()=>r(()=>i(a)),a.onerror=n=>r(()=>s(n)),a.src=t})}_createFabricImageFromURL(t,e=this.options.imageLoadTimeoutMs){return new Promise((i,s)=>{let a=this._getSafeTimeoutMs(e),o=!1,c,l=r=>{o||(o=!0,clearTimeout(c),r())};c=setTimeout(()=>{l(()=>s(new Error("Fabric image load timed out")))},a);try{_.Image.fromURL(t,r=>{l(()=>{if(!r){s(new Error("Image could not be loaded"));return}i(r)})},{crossOrigin:"anonymous"})}catch(r){l(()=>s(r))}})}_getSafeTimeoutMs(t){let e=Number(t);return Number.isFinite(e)&&e>0?e:3e4}_captureLoadImageTransaction(){return{canvasState:this._serializeCanvasState(),baseImageScale:this.baseImageScale,currentScale:this.currentScale,currentRotation:this.currentRotation,maskCounter:this.maskCounter,isImageLoadedToCanvas:this.isImageLoadedToCanvas,lastSnapshot:this._lastSnapshot,lastMask:this._lastMask,lastMaskInitialLeft:this._lastMaskInitialLeft,lastMaskInitialTop:this._lastMaskInitialTop,lastMaskInitialWidth:this._lastMaskInitialWidth,containerOverflow:this.containerElement&&this.containerElement.style?{overflow:this.containerElement.style.overflow||"",overflowX:this.containerElement.style.overflowX||"",overflowY:this.containerElement.style.overflowY||""}:null,scrollLeft:this.containerElement?this.containerElement.scrollLeft:0,scrollTop:this.containerElement?this.containerElement.scrollTop:0,placeholderVisibility:this._captureElementVisibility(this.placeholderElement),canvasVisibility:this._captureElementVisibility(this._getCanvasVisibilityElement())}}async _rollbackLoadImageTransaction(t){if(!t||!this.canvas||this._disposed)return;let e=!1;try{t.canvasState&&(await this.loadFromState(t.canvasState),e=!0)}catch(i){this._lastMask=null,this._reportError("loadImage rollback failed",i)}this.baseImageScale=t.baseImageScale,this.currentScale=t.currentScale,this.currentRotation=t.currentRotation,this.maskCounter=t.maskCounter,this.isImageLoadedToCanvas=t.isImageLoadedToCanvas,this._lastSnapshot=t.lastSnapshot,e?this._restoreLastMaskReference(t.lastMask):this._lastMask=null,this._lastMaskInitialLeft=t.lastMaskInitialLeft,this._lastMaskInitialTop=t.lastMaskInitialTop,this._lastMaskInitialWidth=t.lastMaskInitialWidth,this._restoreElementVisibility(this.placeholderElement,t.placeholderVisibility),this._restoreElementVisibility(this._getCanvasVisibilityElement(),t.canvasVisibility),this.containerElement&&(this.containerElement.scrollLeft=t.scrollLeft,this.containerElement.scrollTop=t.scrollTop,this._restoreContainerOverflowSnapshot(t.containerOverflow)),this._updateInputs(),this._updateMaskList(),this._updateUI(),this.canvas&&this.canvas.renderAll()}_restoreLastMaskReference(t){if(!this.canvas){this._lastMask=null;return}let e=this.canvas.getObjects().filter(s=>s.maskId),i=t&&t.maskId;this._lastMask=e.find(s=>s.maskId===i)||e[e.length-1]||null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null)}_resampleImageToDataURL(t,e,i,s=.92,a=null){let o=Math.max(1,Number(t&&(t.naturalWidth||t.width))||0),c=Math.max(1,Number(t&&(t.naturalHeight||t.height))||0),l=Math.round(Number(e)),r=Math.round(Number(i));if(!Number.isFinite(l)||!Number.isFinite(r)||l<=0||r<=0)throw new Error("Invalid image resample target dimensions");let n=document.createElement("canvas");n.width=l,n.height=r;let h=n.getContext("2d");if(!h)throw new Error("2D canvas context is unavailable");return h.drawImage(t,0,0,o,c,0,0,l,r),n.toDataURL(this._getDownsampleMimeType(a),s)}_getDataUrlMimeType(t){let e=String(t||"").match(/^data:([^;,]+)[;,]/i);return e?e[1].toLowerCase():""}_getDownsampleMimeType(t){if(this.options.downsampleMimeType)return`image/${this._normalizeImageFormat(this.options.downsampleMimeType)}`;let e=this._getDataUrlMimeType(t);return this.options.preserveSourceFormat!==!1&&(e==="image/png"||e==="image/webp")?e:"image/jpeg"}_captureCanvasStateOrThrow(t){let e=this._serializeCanvasState();if(!e)throw new Error(`${t}: canvas state is unavailable`);return e}_setCanvasSizeInt(t,e){let i=Math.max(1,Math.round(Number(t)||1)),s=Math.max(1,Math.round(Number(e)||1));this.canvas.setWidth(i),this.canvas.setHeight(s),typeof this.canvas.calcOffset=="function"&&this.canvas.calcOffset(),this.canvasElement&&(this.canvasElement.style.width=i+"px",this.canvasElement.style.height=s+"px")}_ceilCanvasDimension(t){let e=Number(t)||0,i=Math.round(e);return Math.abs(e-i)<.01?i:Math.ceil(e)}_getContainerViewportSize(){if(!this.containerElement)return{width:Math.max(1,Math.floor(this.options.canvasWidth||1)),height:Math.max(1,Math.floor(this.options.canvasHeight||1))};let t=Math.floor(this.containerElement.clientWidth||0),e=Math.floor(this.containerElement.clientHeight||0),i=Math.max(1,t||this._lastContainerViewportSize?.width||this.options.canvasWidth||1),s=Math.max(1,e||this._lastContainerViewportSize?.height||this.options.canvasHeight||1);if(t>0&&e>0&&(this._lastContainerViewportSize={width:t,height:e}),this._hasFixedContainerScrollbars())return{width:i,height:s};let a=this._getContainerOverflowValues(),o=a.x.some(n=>n==="auto"||n==="scroll"),c=a.y.some(n=>n==="auto"||n==="scroll"),l=o&&this.containerElement.scrollWidth>this.containerElement.clientWidth,r=c&&this.containerElement.scrollHeight>this.containerElement.clientHeight;if(l||r){let n=this._getScrollbarSize();r&&(i+=n.width),l&&(s+=n.height)}return{width:i,height:s}}_getContainerOverflowValues(){if(!this.containerElement)return{x:[],y:[]};let t=this.containerElement.style.overflow,e=this.containerElement.style.overflowX,i=this.containerElement.style.overflowY,s="",a="",o="";if(typeof window<"u"&&typeof window.getComputedStyle=="function"){let c=window.getComputedStyle(this.containerElement);s=c.overflow,a=c.overflowX,o=c.overflowY}return{x:[t,e,s,a],y:[t,i,s,o]}}_hasFixedContainerScrollbars(){if(!this.containerElement)return!1;let t=this._getContainerOverflowValues();return[...t.x,...t.y].some(e=>e==="scroll")}_getScrollbarSize(){if(this._scrollbarSizeCache)return{...this._scrollbarSizeCache};if(typeof document>"u"||!document.createElement||!document.body)return{width:0,height:0};let t=document.createElement("div");t.style.position="absolute",t.style.visibility="hidden",t.style.overflow="scroll",t.style.width="100px",t.style.height="100px",t.style.top="-9999px",document.body.appendChild(t);let e=Math.max(0,t.offsetWidth-t.clientWidth),i=Math.max(0,t.offsetHeight-t.clientHeight);return document.body.removeChild(t),this._scrollbarSizeCache={width:e,height:i},{...this._scrollbarSizeCache}}_getScrollSafetyMargin(){return 2}_getScrollableCanvasSize(t,e,i=this._getContainerViewportSize()){if(this._hasFixedContainerScrollbars()){let r=this._getScrollSafetyMargin(),n=Math.max(1,i.width-r),h=Math.max(1,i.height-r);return{width:t>i.width+.5?this._ceilCanvasDimension(t):n,height:e>i.height+.5?this._ceilCanvasDimension(e):h,viewportWidth:i.width,viewportHeight:i.height,hasHorizontal:!0,hasVertical:!0}}let s=this._getScrollbarSize(),a=!1,o=!1,c,l;for(let r=0;r<4;r+=1){c=Math.max(1,i.width-(a?s.width:0)),l=Math.max(1,i.height-(o?s.height:0));let n=e>l+.5,h=t>c+.5;if(n===a&&h===o)break;a=n,o=h}return c=Math.max(1,i.width-(a?s.width:0)),l=Math.max(1,i.height-(o?s.height:0)),{width:o?this._ceilCanvasDimension(t):c,height:a?this._ceilCanvasDimension(e):l,viewportWidth:c,viewportHeight:l,hasHorizontal:o,hasVertical:a}}_calculateCoverCanvasLayout(t,e){let i=this._getContainerViewportSize();if(this._hasFixedContainerScrollbars()){let d=this._getScrollSafetyMargin(),u=Math.max(1,i.width-d),m=Math.max(1,i.height-d),g=Math.min(1,Math.max(u/t,m/e)),p=t*g,y=e*g,I=this._getScrollableCanvasSize(p,y,i);return{scale:g,canvasWidth:I.width,canvasHeight:I.height}}let s=this._getScrollbarSize(),a=!1,o=!1,c=1,l=t,r=e,n,h;for(let d=0;d<4;d+=1){n=Math.max(1,i.width-(a?s.width:0)),h=Math.max(1,i.height-(o?s.height:0)),c=Math.min(1,Math.max(n/t,h/e)),l=t*c,r=e*c;let u=r>h+.5,m=l>n+.5;if(u===a&&m===o)break;a=u,o=m}let f=this._getScrollableCanvasSize(l,r,i);return{scale:c,canvasWidth:f.width,canvasHeight:f.height}}_getStateProperties(){return["maskId","maskName","maskLabel","isCropRect","originalAlpha","originalStroke","originalStrokeWidth","selectable","evented","hasControls","lockRotation","borderColor","cornerColor","cornerSize","transparentCorners","strokeUniform","strokeDashArray"]}_getMaskNormalStyle(t){let e=Number(t&&t.originalStrokeWidth),i=Number(t&&t.originalAlpha),s={stroke:t&&t.originalStroke||"#ccc",strokeWidth:Number.isFinite(e)?e:1};return Number.isFinite(i)&&(s.opacity=i),s}_withNormalizedMaskStyles(t){if(!this.canvas)return t();let e=this.canvas.getObjects().filter(s=>s.maskId),i=[];try{e.forEach(a=>{let o=this._getMaskNormalStyle(a),c={};Object.keys(o).forEach(n=>{a[n]!==o[n]&&(c[n]=o[n])});let l=Object.keys(c);if(!l.length)return;let r={object:a};l.forEach(n=>{r[n]=a[n]}),i.push(r),a.set(c)});let s=t();if(s&&typeof s.then=="function")throw new Error("_withNormalizedMaskStyles callback must be synchronous");return s}finally{i.forEach(s=>{try{let a={};Object.keys(s).forEach(o=>{o!=="object"&&(a[o]=s[o])}),s.object.set(a)}catch(a){}})}}_restoreMaskControls(t){if(!t)return;let e=Number(t.cornerSize);t.set({selectable:t.selectable!==!1,evented:t.evented!==!1,hasControls:t.hasControls!==!1,lockRotation:typeof t.lockRotation=="boolean"?t.lockRotation:!this.options.maskRotatable,borderColor:t.borderColor||"red",cornerColor:t.cornerColor||"black",cornerSize:Number.isFinite(e)?e:8,transparentCorners:t.transparentCorners===!0,strokeUniform:t.strokeUniform!==!1}),typeof t.setCoords=="function"&&t.setCoords()}_serializeEditorMetadata(){let t=Number(this.baseImageScale),e=Number(this.currentScale),i=Number(this.currentRotation),s=Number(this.maskCounter);return{version:1,baseImageScale:Number.isFinite(t)&&t>0?t:1,currentScale:Number.isFinite(e)&&e>0?e:1,currentRotation:Number.isFinite(i)?i:0,maskCounter:Number.isFinite(s)&&s>0?Math.floor(s):0}}_serializeCanvasState(){return this.canvas?this._withNormalizedMaskStyles(()=>{let t=this.canvas.toJSON(this._getStateProperties());return Array.isArray(t.objects)&&(t.objects=t.objects.filter(e=>!e.isCropRect&&!e.maskLabel)),t.imageEditorMetadata=this._serializeEditorMetadata(),JSON.stringify(t)}):null}_normalizeQuality(t,e=void 0){let i=e??this.options.downsampleQuality,s=i==null?NaN:Number(i),a=Number.isFinite(s)?Math.max(0,Math.min(1,s)):.92;if(t==null)return a;let o=Number(t);return Number.isFinite(o)?Math.max(0,Math.min(1,o)):a}_normalizeImageFormat(t){return{jpeg:"jpeg",jpg:"jpeg","image/jpeg":"jpeg",png:"png","image/png":"png",webp:"webp","image/webp":"webp"}[String(t||"jpeg").toLowerCase()]||"jpeg"}_getClampedCanvasRegion(t,e={}){let i=Math.max(1,Math.round(this.canvas.getWidth())),s=Math.max(1,Math.round(this.canvas.getHeight())),a=Number(t.left)||0,o=Number(t.top)||0,c=Math.max(0,Number(t.width)||0),l=Math.max(0,Number(t.height)||0),n=e.includePartialPixels!==!1?Math.ceil:Math.floor,h=Math.min(i-1,Math.max(0,Math.floor(a))),f=Math.min(s-1,Math.max(0,Math.floor(o))),d=Math.min(i,Math.max(h+1,n(a+c))),u=Math.min(s,Math.max(f+1,n(o+l)));return{sourceX:h,sourceY:f,sourceWidth:Math.max(1,d-h),sourceHeight:Math.max(1,u-f)}}_hasFractionalCanvasEdge(t){let e=Number(t);return Number.isFinite(e)?Math.abs(e-Math.round(e))>.01:!1}_getPartialExportEdges(t){if(!t)return null;let e=Math.abs((Number(this.originalImage&&this.originalImage.angle)||0)%90);return e<.01||Math.abs(e-90)<.01?{left:this._hasFractionalCanvasEdge(t.left),top:this._hasFractionalCanvasEdge(t.top),right:this._hasFractionalCanvasEdge((Number(t.left)||0)+(Number(t.width)||0)),bottom:this._hasFractionalCanvasEdge((Number(t.top)||0)+(Number(t.height)||0))}:null}async _sealPartialTransparentEdges(t,e){if(!e||!Object.values(e).some(Boolean))return t;let i=await this._createImageElement(t),s=Math.max(1,i.naturalWidth||i.width||1),a=Math.max(1,i.naturalHeight||i.height||1),o=document.createElement("canvas");o.width=s,o.height=a;let c=o.getContext("2d");if(!c)throw new Error("2D canvas context is unavailable");c.drawImage(i,0,0,s,a);let l=c.getImageData(0,0,s,a),r=l.data,n=(h,f,d,u)=>{let m=(f*s+h)*4,g=(u*s+d)*4;r[m+3]===0&&r[g+3]>0&&(r[m]=r[g],r[m+1]=r[g+1],r[m+2]=r[g+2],r[m+3]=r[g+3]),r[m+3]>0&&r[m+3]<255&&(r[m+3]=255)};if(e.left&&s>1)for(let h=0;h<a;h+=1)n(0,h,1,h);if(e.right&&s>1)for(let h=0;h<a;h+=1)n(s-1,h,s-2,h);if(e.top&&a>1)for(let h=0;h<s;h+=1)n(h,0,h,1);if(e.bottom&&a>1)for(let h=0;h<s;h+=1)n(h,a-1,h,a-2);return c.putImageData(l,0,0),o.toDataURL("image/png")}async _exportCanvasRegionToDataURL({sourceX:t,sourceY:e,sourceWidth:i,sourceHeight:s,multiplier:a=1,quality:o=.92,format:c="jpeg",sealPartialEdges:l=null}){let r=Math.max(1,Number(a)||1),n=this._normalizeImageFormat(c),h=n==="jpeg"?"png":n,f=this.canvas.toDataURL({format:h,quality:o,multiplier:r,left:t,top:e,width:i,height:s});return f=await this._sealPartialTransparentEdges(f,l),n!=="jpeg"?f:this._convertDataUrlToOpaqueJpeg(f,o)}async _convertDataUrlToOpaqueJpeg(t,e=.92){let i=await this._createImageElement(t),s=Math.max(1,i.naturalWidth||i.width||1),a=Math.max(1,i.naturalHeight||i.height||1),o=document.createElement("canvas");o.width=s,o.height=a;let c=o.getContext("2d");if(!c)throw new Error("2D canvas context is unavailable");return c.fillStyle=this._getJpegBackgroundColor(),c.fillRect(0,0,s,a),c.drawImage(i,0,0,s,a),o.toDataURL("image/jpeg",this._normalizeQuality(e))}_getJpegBackgroundColor(){let t=String(this.options.backgroundColor||"").trim();return!t||this._isTransparentCssColor(t)?"#ffffff":t}_isTransparentCssColor(t){let e=String(t||"").trim().toLowerCase();if(!e||e==="transparent")return!0;let i=e.match(/^#(?:[0-9a-f]{3}([0-9a-f])|[0-9a-f]{6}([0-9a-f]{2}))$/i);if(i){let o=i[1]||i[2];return o==="0"||o==="00"}let s=e.match(/^(?:rgba?|hsla?)\([^)]*\/\s*([^)]+)\)$/i);if(s)return this._isZeroCssAlpha(s[1]);let a=e.match(/^(?:rgba|hsla)\((.*)\)$/i);if(a){let o=a[1].split(",");if(o.length>=4)return this._isZeroCssAlpha(o[o.length-1])}return!1}_isZeroCssAlpha(t){let e=String(t||"").trim();return e?e.endsWith("%")?Number.parseFloat(e)===0:Number(e)===0:!1}_decodeBase64Payload(t){let e=String(t||"");if(typeof atob=="function")return Uint8Array.from(atob(e),i=>i.charCodeAt(0));if(typeof Buffer<"u"&&typeof Buffer.from=="function")return new Uint8Array(Buffer.from(e,"base64"));throw new Error("Base64 decoding is unavailable")}_getObjectTopLeftPoint(t){if(!t)return{x:0,y:0};t.setCoords();let e=t.getBoundingRect(!0,!0);return{x:e.left,y:e.top}}_getObjectCoordinateTopLeftPoint(t){if(!t)return{x:0,y:0};t.setCoords();let e=typeof t.getCoords=="function"?t.getCoords():null;return e&&e.length?e[0]:this._getObjectTopLeftPoint(t)}_getObjectOriginPoint(t,e,i){return t?typeof t.getPointByOrigin=="function"?t.getPointByOrigin(e,i):this._getObjectTopLeftPoint(t):{x:0,y:0}}_translateObjectByCanvasOffset(t,e,i){if(t){if(typeof t.getCenterPoint=="function"&&typeof t.setPositionByOrigin=="function"){let s=t.getCenterPoint(),a=new _.Point(s.x+e,s.y+i);t.setPositionByOrigin(a,"center","center")}else t.set({left:(t.left||0)+e,top:(t.top||0)+i});t.setCoords()}}_setObjectOriginKeepingPosition(t,e,i,s){!t||!s||!t.setPositionByOrigin||(t.set({originX:e,originY:i}),t.setPositionByOrigin(s,e,i),t.setCoords())}_alignObjectBoundingBoxToCanvasTopLeft(t){if(!t)return;t.setCoords();let e=t.getBoundingRect(!0,!0),i=e.left,s=e.top;t.set({left:(t.left||0)-i,top:(t.top||0)-s}),t.setCoords(),this.canvas.renderAll()}_updateCanvasSizeToImageBounds(){if(!this.originalImage)return;this.originalImage.setCoords();let t=this.originalImage.getBoundingRect(!0,!0),e=this._getScrollableCanvasSize(t.width,t.height);this._setCanvasSizeInt(e.width,e.height)}_shouldResizeCanvasToContentBounds(){return!!(this.options.expandCanvasToImage||this.options.coverImageToCanvas||this.options.fitImageToCanvas)}_expandCanvasToFitObjects(t,e=10){if(!(!this.canvas||!Array.isArray(t)||!t.length||!this._shouldResizeCanvasToContentBounds()))try{let i=this.canvas.getWidth(),s=this.canvas.getHeight(),a=i,o=s;t.forEach(f=>{if(!f)return;typeof f.setCoords=="function"&&f.setCoords();let d=f.getBoundingRect(!0,!0);a=Math.max(a,Math.ceil(d.left+d.width+e)),o=Math.max(o,Math.ceil(d.top+d.height+e))});let c=this.options.fitImageToCanvas||this.options.coverImageToCanvas,l=0,r=0;if(c){let f=this._getContainerViewportSize(),d=this._getScrollSafetyMargin();l=Math.max(1,f.width-d),r=Math.max(1,f.height-d)}else this.containerElement&&(l=Math.floor(this.containerElement.clientWidth||0),r=Math.floor(this.containerElement.clientHeight||0));let n=Math.max(i,l,a),h=Math.max(s,r,o);(n!==i||h!==s)&&this._setCanvasSizeInt(n,h)}catch(i){this._reportWarning("expandCanvasToFitObjects: failed to expand canvas",i)}}_expandCanvasToFitObject(t,e=10){this._expandCanvasToFitObjects([t],e)}scaleImage(t,e={}){try{this._assertCanQueueAnimation("scaleImage",e)}catch(i){return Promise.reject(i)}return this.animationQueue.add(()=>this._scaleImageImpl(t,e)).finally(()=>{!this._disposed&&this.canvas&&this._updateUI()})}_getInternalOperationToken(t){return t&&t[N]}_isOwnInternalOperation(t){let e=this._getInternalOperationToken(t);return!!e&&e===this._activeOperationToken}_beginBusyOperation(t){let e=Symbol(t);return this._activeOperationName=t,this._activeOperationToken=e,this._updateUI(),e}_endBusyOperation(t){t&&t===this._activeOperationToken&&(this._activeOperationName=null,this._activeOperationToken=null,this._updateUI())}_withInternalOperationOptions(t,e={}){return{...e,[N]:t}}_assertEditorAvailable(t){if(this._disposed||!this.canvas)throw new Error(`${t} cannot run after the editor has been disposed`)}_assertIdleForOperation(t,e={}){this._assertEditorAvailable(t);let i=this._isOwnInternalOperation(e);if(this.isAnimating||this.animationQueue&&this.animationQueue.isBusy())throw new Error(`${t} cannot run while an animation is running`);if(this._isLoading&&!i)throw new Error(`${t} cannot run while an image is loading`);if(this._activeOperationToken&&!i)throw new Error(`${t} cannot run while ${this._activeOperationName||"another operation"} is running`)}_assertCanQueueAnimation(t,e={}){if(this._assertEditorAvailable(t),this._isLoading&&!this._isOwnInternalOperation(e))throw new Error(`${t} cannot run while an image is loading`);if(this._activeOperationToken&&!this._isOwnInternalOperation(e))throw new Error(`${t} cannot run while ${this._activeOperationName||"another operation"} is running`)}_canMutateNow(t,e={}){try{return this._assertIdleForOperation(t,e),!0}catch(i){return this._reportError(`${t} blocked`,i),!1}}_rejectActiveAnimations(t){let e=t instanceof Error?t:new Error(String(t||"Animation cancelled"));this._activeAnimationRejectors.forEach(i=>{try{i(e)}catch(s){}}),this._activeAnimationRejectors.clear()}_animateFabricProperty(t,e,i){return new Promise((s,a)=>{if(this._disposed||!this.canvas||!t){a(new Error("Animation cannot start after editor disposal"));return}let o=!1,c=Math.max(0,Number(this.options.animationDuration)||0),l=Math.max(1e3,c+1e3),r,n=h=>{o||(o=!0,clearTimeout(r),this._activeAnimationRejectors.delete(a),h())};this._activeAnimationRejectors.add(a),r=setTimeout(()=>{n(()=>a(new Error(`Animation timed out while changing ${e}`)))},l);try{t.animate(e,i,{duration:c,onChange:()=>{!this._disposed&&this.canvas&&this.canvas.renderAll()},onComplete:()=>n(s)})}catch(h){n(()=>a(h))}})}async _scaleImageImpl(t,e={}){if(!this.originalImage||this._disposed||this.isAnimating)return;let i=e.saveHistory!==!1,s=!1;try{t=Math.max(this.options.minScale,Math.min(this.options.maxScale,t)),this.currentScale=t,this.isAnimating=!0,s=!0,this._updateUI();let a=this.baseImageScale*t,o=this._getObjectTopLeftPoint(this.originalImage);if(this._setObjectOriginKeepingPosition(this.originalImage,"left","top",o),await Promise.all([this._animateFabricProperty(this.originalImage,"scaleX",a),this._animateFabricProperty(this.originalImage,"scaleY",a)]),this._disposed||!this.canvas||!this.originalImage)throw new Error("Editor was disposed during scale animation");this.originalImage.set({scaleX:a,scaleY:a}),this.originalImage.setCoords(),this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds(),this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage),this.canvas.getObjects().forEach(c=>{c.maskId&&this._syncMaskLabel(c)}),this._updateInputs(),i&&this.saveState()}finally{s&&(this.isAnimating=!1,this._updateInputs(),this._updateUI())}}rotateImage(t,e={}){try{this._assertCanQueueAnimation("rotateImage",e)}catch(i){return Promise.reject(i)}return this.animationQueue.add(()=>this._rotateImageImpl(t,e)).finally(()=>{!this._disposed&&this.canvas&&this._updateUI()})}async _rotateImageImpl(t,e={}){if(!this.originalImage||this._disposed||this.isAnimating||isNaN(t))return;let i=e.saveHistory!==!1,s=this.originalImage,a=s.originX||"left",o=s.originY||"top",c=this._getObjectOriginPoint(s,a,o),l=!1,r=!1;try{this.currentRotation=t,this.isAnimating=!0,l=!0,this._updateUI();let n=s.getCenterPoint();if(this._setObjectOriginKeepingPosition(s,"center","center",n),await this._animateFabricProperty(s,"angle",t),this._disposed||!this.canvas||!this.originalImage)throw new Error("Editor was disposed during rotation animation");this.originalImage.set("angle",t),this.originalImage.setCoords(),this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds(),this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage);let h=this._getObjectCoordinateTopLeftPoint(this.originalImage);this._setObjectOriginKeepingPosition(this.originalImage,"left","top",h),this.canvas.getObjects().forEach(f=>{f.maskId&&this._syncMaskLabel(f)}),this._updateInputs(),i&&this.saveState(),r=!0}finally{!r&&!this._disposed&&s&&this._setObjectOriginKeepingPosition(s,a,o,c),l&&(this.isAnimating=!1,this._updateInputs(),this._updateUI())}}resetImageTransform(){if(!this.originalImage)return Promise.resolve();try{this._assertCanQueueAnimation("resetImageTransform")}catch(t){return Promise.reject(t)}return this.animationQueue.add(async()=>{let t=this._lastSnapshot||this._captureCanvasStateOrThrow("resetImageTransform");await this._scaleImageImpl(1,{saveHistory:!1}),await this._rotateImageImpl(0,{saveHistory:!1});let e=this._captureCanvasStateOrThrow("resetImageTransform");this._pushStateTransition(t,e)}).finally(()=>{!this._disposed&&this.canvas&&this._updateUI()}).catch(t=>{throw this._reportError("resetImageTransform() failed",t),t})}reset(){return this.resetImageTransform()}loadFromState(t){return!t||!this.canvas||this._disposed?Promise.resolve():((this._cropMode||this._cropRect)&&(this._removeCropRect(),this._restoreCropObjectState(),this._cropMode=!1,this._prevSelectionSetting!==void 0&&this.canvas&&(this.canvas.selection=!!this._prevSelectionSetting),this._prevSelectionSetting=void 0),new Promise((e,i)=>{try{let s=typeof t=="string"?JSON.parse(t):t,a=s&&s.imageEditorMetadata?s.imageEditorMetadata:null;a&&Object.prototype.hasOwnProperty.call(a,"version")&&Number(a.version)!==1&&this._reportWarning(`loadFromState: unsupported editor metadata version ${a.version}`),this.canvas.loadFromJSON(s,async()=>{try{if(this._disposed||!this.canvas){i(new Error("Editor was disposed while loading state"));return}if(await this._waitForFabricImagesReady(this.canvas.getObjects()),this._disposed||!this.canvas){i(new Error("Editor was disposed while loading state"));return}this._hideAllMaskLabels();let o=this.canvas.getObjects();if(this.originalImage=o.find(n=>n.type==="image"&&!n.maskId)||null,this.originalImage){this.originalImage.set({originX:"left",originY:"top",selectable:!1,evented:!1,hasControls:!1,hoverCursor:"default"}),this.canvas.sendToBack(this.originalImage);let n=Number(a&&a.baseImageScale),h=Number(a&&a.currentScale),f=Number(a&&a.currentRotation);if(Number.isFinite(n)&&n>0&&(this.baseImageScale=n),Number.isFinite(h)&&h>0)this.currentScale=h;else{let d=Number(this.baseImageScale)||1,u=Number(this.originalImage.scaleX)||d;this.currentScale=u/d}this.currentRotation=Number.isFinite(f)?f:Number(this.originalImage.angle)||0}else this.baseImageScale=1,this.currentScale=1,this.currentRotation=0;let c=o.filter(n=>n.maskId);c.forEach(n=>{this._restoreMaskControls(n),this._rebindMaskEvents(n),n.set(this._getMaskNormalStyle(n))});let l=Number(a&&a.maskCounter),r=c.reduce((n,h)=>Math.max(n,h.maskId),0);this.maskCounter=Number.isFinite(l)&&l>=r?Math.floor(l):r,this._lastMask=c.length?c[c.length-1]:null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null),this.isImageLoadedToCanvas=!!this.originalImage,this.canvas.renderAll(),this._updateInputs(),this._updateMaskList(),this._updatePlaceholderStatus(),this._lastSnapshot=this._serializeCanvasState(),this._updateUI(),e()}catch(o){this._reportError("loadFromState() failed",o),i(o)}})}catch(s){this._reportError("loadFromState() failed",s),i(s)}}))}async _waitForFabricImagesReady(t){let e=(t||[]).filter(i=>i&&i.type==="image");await Promise.all(e.map(i=>this._waitForImageElementReady(typeof i.getElement=="function"?i.getElement():i._element)))}_waitForImageElementReady(t){return!t||(Number(t.naturalWidth)>0||Number(t.width)>0)&&(Number(t.naturalHeight)>0||Number(t.height)>0)?Promise.resolve():t.complete?Promise.reject(new Error("Image could not be loaded while restoring state")):new Promise((i,s)=>{let a=!1,o,c=n=>{a||(a=!0,clearTimeout(o),typeof t.removeEventListener=="function"?(t.removeEventListener("load",l),t.removeEventListener("error",r)):(t.onload=null,t.onerror=null),n())},l=()=>{let n=(Number(t.naturalWidth)>0||Number(t.width)>0)&&(Number(t.naturalHeight)>0||Number(t.height)>0);c(()=>{n?i():s(new Error("Image could not be loaded while restoring state"))})},r=n=>c(()=>s(n instanceof Error?n:new Error("Image could not be loaded while restoring state")));o=setTimeout(()=>{c(()=>s(new Error("Image load timed out while restoring state")))},this._getSafeTimeoutMs(this.options.imageLoadTimeoutMs)),typeof t.addEventListener=="function"?(t.addEventListener("load",l,{once:!0}),t.addEventListener("error",r,{once:!0})):(t.onload=l,t.onerror=r)})}saveState(){if(this.canvas)try{let t=this._captureCanvasStateOrThrow("saveState"),e=this._lastSnapshot||t;if(t===e)return;let i=!1,s=new k(()=>{if(i)return this.loadFromState(t);i=!0},()=>this.loadFromState(e));this.historyManager.execute(s),this._lastSnapshot=t}catch(t){this._reportWarning("saveState: failed to save canvas snapshot",t)}finally{this._updateUI()}}_pushStateTransition(t,e){if(!t||!e){this._reportWarning("History transition skipped because a canvas snapshot is unavailable");return}if(t===e)return;this.historyManager||(this.historyManager=new M(this.maxHistorySize||50));let i=new k(()=>this.loadFromState(e),()=>this.loadFromState(t));this.historyManager.push(i),this._lastSnapshot=e,this._updateUI()}undo(){return this.historyManager.undo().then(()=>{this._updateUI()}).catch(t=>{throw this._reportError("undo failed",t),t})}redo(){return this.historyManager.redo().then(()=>{this._updateUI()}).catch(t=>{throw this._reportError("redo failed",t),t})}_rebindMaskEvents(t){if(!t)return;if(t.__imageEditorMaskHandlers)try{t.off("mouseover",t.__imageEditorMaskHandlers.mouseover),t.off("mouseout",t.__imageEditorMaskHandlers.mouseout)}catch(a){}let e={};Number.isFinite(Number(t.originalAlpha))||(e.originalAlpha=Number.isFinite(Number(t.opacity))?Number(t.opacity):.5),t.originalStroke||(e.originalStroke=t.stroke||"#ccc"),Number.isFinite(Number(t.originalStrokeWidth))||(e.originalStrokeWidth=Number.isFinite(Number(t.strokeWidth))?Number(t.strokeWidth):1),Object.keys(e).length&&t.set(e);let i=()=>{let a=Number(t.originalAlpha);t.set({stroke:"#ff5500",strokeWidth:2,opacity:Math.min((Number.isFinite(a)?a:.5)+.2,1)}),t.canvas&&t.canvas.requestRenderAll()},s=()=>{t.set(this._getMaskNormalStyle(t)),t.canvas&&t.canvas.requestRenderAll()};t.on("mouseover",i),t.on("mouseout",s),t.__imageEditorMaskHandlers={mouseover:i,mouseout:s}}createMask(t={}){if(!this.canvas||!this._canMutateNow("createMask"))return null;let e=t.shape||"rect",i={shape:e,width:this.options.defaultMaskWidth,height:this.options.defaultMaskHeight,color:"rgba(0,0,0,0.5)",alpha:.5,gap:5,left:void 0,top:void 0,angle:0,selectable:!0,...t},s=10,a,o,c=u=>{let m=this.canvas?this.canvas.getWidth():0,g=this.canvas?this.canvas.getHeight():0;return u==="height"?g:u==="min"?Math.min(m,g):m},l=(u,m,g="width")=>{if(typeof u=="function")return u(this.canvas,this.options);if(typeof u=="string"&&u.endsWith("%")){let p=Number.parseFloat(u)/100;return Number.isFinite(p)?Math.floor(c(g)*p):m}return u??m};if(i.left===void 0&&this._lastMask){let u=this._lastMask;typeof u.setCoords=="function"&&u.setCoords();let m=typeof u.getBoundingRect=="function"?u.getBoundingRect(!0,!0):{left:u.left||s,top:u.top||s,width:u.width||0};a=Math.round(m.left+m.width+i.gap),o=Math.round(m.top??s)}else a=l(i.left,s,"width"),o=l(i.top,s,"height");i.width=l(i.width,this.options.defaultMaskWidth,"width"),i.height=l(i.height,this.options.defaultMaskHeight,"height"),i.left=a,i.top=o;let r;if(typeof i.fabricGenerator=="function")r=i.fabricGenerator(i,this.canvas,this.options);else switch(e){case"circle":r=new _.Circle({left:a,top:o,radius:l(i.radius,Math.min(i.width,i.height)/2,"min"),fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break;case"ellipse":r=new _.Ellipse({left:a,top:o,rx:l(i.rx,i.width/2,"width"),ry:l(i.ry,i.height/2,"height"),fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break;case"polygon":{let u=i.points||[];Array.isArray(u)&&u.length&&(u=u.map(m=>Array.isArray(m)?{x:Number(m[0]),y:Number(m[1])}:{x:Number(m.x),y:Number(m.y)})),r=new _.Polygon(u,{left:a,top:o,fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break}default:r=new _.Rect({left:a,top:o,width:l(i.width,this.options.defaultMaskWidth,"width"),height:l(i.height,this.options.defaultMaskHeight,"height"),fill:i.color,opacity:i.alpha,angle:i.angle,rx:i.rx,ry:i.ry,...i.styles})}if(!r||typeof r.set!="function"||typeof r.setCoords!="function")return this._reportWarning("fabricGenerator returned an invalid Fabric object"),null;let n=i.styles||{},h=u=>Object.prototype.hasOwnProperty.call(n,u),f={selectable:i.selectable!==!1,hasControls:"hasControls"in i?i.hasControls:!0,lockRotation:!this.options.maskRotatable,borderColor:"borderColor"in i?i.borderColor:"red",cornerColor:"cornerColor"in i?i.cornerColor:"black",cornerSize:"cornerSize"in i?i.cornerSize:8,transparentCorners:"transparentCorners"in i?i.transparentCorners:!1,stroke:h("stroke")?n.stroke:"#ccc",strokeWidth:h("strokeWidth")?n.strokeWidth:1,opacity:h("opacity")?n.opacity:i.alpha,strokeUniform:"strokeUniform"in i?i.strokeUniform:h("strokeUniform")?n.strokeUniform:!0};h("strokeDashArray")&&(f.strokeDashArray=n.strokeDashArray),r.set(f),r.setCoords(),r.set({originalAlpha:Number.isFinite(Number(r.opacity))?Number(r.opacity):i.alpha,originalStroke:r.stroke||"#ccc",originalStrokeWidth:Number.isFinite(Number(r.strokeWidth))?Number(r.strokeWidth):1}),this._rebindMaskEvents(r),this._expandCanvasToFitObject(r),this._lastMaskInitialLeft=a,this._lastMaskInitialTop=o,this._lastMaskInitialWidth=l(i.width,this.options.defaultMaskWidth,"width");let d=++this.maskCounter;return r.set({maskId:d,maskName:`${this.options.maskName}${d}`}),this._lastMask=r,this.canvas.add(r),this.canvas.bringToFront(r),i.selectable&&this.canvas.setActiveObject(r),this._handleSelectionChanged([r]),this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),this.saveState(),typeof i.onCreate=="function"&&i.onCreate(r,this.canvas),r}addMask(t={}){return this.createMask(t)}removeSelectedMask(){if(!this.canvas||!this._canMutateNow("removeSelectedMask"))return;let t=this.canvas.getActiveObject(),e=this._getModifiedMasks(t);if(!e.length)return;this.canvas.discardActiveObject(),e.forEach(s=>{this._removeLabelForMask(s),this.canvas.remove(s)});let i=this.canvas.getObjects().filter(s=>s.maskId);this._lastMask=i.length?i[i.length-1]:null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null),this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),this.saveState()}removeAllMasks(t={}){if(!this.canvas||!this._canMutateNow("removeAllMasks",t))return;let e=t.saveHistory!==!1,i=this.canvas.getObjects().filter(s=>s.maskId);i.forEach(s=>this._removeLabelForMask(s)),i.forEach(s=>this.canvas.remove(s)),this.canvas.discardActiveObject(),this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null,this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),e&&this.saveState()}_removeLabelForMask(t){if(!(!t||!this.canvas)&&t.__label){try{this.canvas.getObjects().includes(t.__label)&&this.canvas.remove(t.__label)}catch(e){}try{delete t.__label}catch(e){}}}_captureMaskLabelBackups(t){if(!this.canvas)return[];let e=new Set(this.canvas.getObjects());return(t||[]).map(i=>{let s=i&&i.__label?i.__label:null;return{mask:i,label:s,hadLabel:!!s,labelInCanvas:!!s&&e.has(s),visible:s?s.visible:void 0}})}_restoreMaskLabelBackups(t){if(!this.canvas||!Array.isArray(t))return;let e=new Set(this.canvas.getObjects());t.forEach(i=>{if(!(!i||!i.mask))try{if(!i.hadLabel){i.mask.__label&&this._removeLabelForMask(i.mask);return}if(i.mask.__label=i.label,!i.label)return;i.labelInCanvas&&!e.has(i.label)&&(this.canvas.add(i.label),e.add(i.label)),i.visible!==void 0&&i.label.set({visible:i.visible}),i.labelInCanvas&&this.canvas.bringToFront(i.label),this._syncMaskLabel(i.mask)}catch(s){}})}_captureActiveObjectBackup(){if(!this.canvas)return null;let t=this.canvas.getActiveObject();if(!t)return null;let e=typeof t.getObjects=="function"?t.getObjects():[t];return{activeObject:t,selectedObjects:e}}_restoreActiveObjectBackup(t){if(!this.canvas||!t||!t.activeObject)return;let e=this.canvas.getObjects(),i=Array.isArray(t.selectedObjects)?t.selectedObjects:[];if(i.length?i.every(a=>e.includes(a)):e.includes(t.activeObject))try{this.canvas.setActiveObject(t.activeObject)}catch(a){}}_captureMaskExportBackups(t){return(t||[]).map(e=>({object:e,visible:e.visible,opacity:e.opacity,fill:e.fill,strokeWidth:e.strokeWidth,stroke:e.stroke,selectable:e.selectable,lockRotation:e.lockRotation}))}_restoreMaskExportBackups(t){(t||[]).forEach(e=>{try{e.object.set({visible:e.visible,opacity:e.opacity,fill:e.fill,strokeWidth:e.strokeWidth,stroke:e.stroke,selectable:e.selectable,lockRotation:e.lockRotation}),e.object.setCoords()}catch(i){}})}_getMaskCreationIndex(t){let e=Number(t&&t.maskId);if(Number.isFinite(e)&&e>0)return Math.floor(e)-1;let i=this.canvas?this.canvas.getObjects().filter(s=>s.maskId):[];return Math.max(0,i.indexOf(t))}_createLabelForMask(t){if(!t||!this.options.maskLabelOnSelect)return;this._removeLabelForMask(t);let e=null;if(this.options.label&&typeof this.options.label.create=="function"&&(e=this.options.label.create(t,_),(!e||typeof e.set!="function")&&(this._reportWarning("label.create() returned an invalid Fabric object; using the default label"),e=null)),!e){let i=t.maskName,s={left:0,top:0,fontSize:12,fill:"#fff",backgroundColor:"rgba(0,0,0,0.7)",selectable:!1,evented:!1,padding:2,originX:"left",originY:"top"};this.options.label&&(typeof this.options.label.getText=="function"&&(i=this.options.label.getText(t,this._getMaskCreationIndex(t))),this.options.label.textOptions&&Object.assign(s,this.options.label.textOptions)),e=new _.Text(i,s)}e.maskLabel=!0,t.__label=e,this.canvas.add(e),this.canvas.bringToFront(e),this._syncMaskLabel(t)}_hideAllMaskLabels(){if(!this.canvas)return;let t=this.canvas.getObjects(),e=new Set(t);t.filter(s=>s.maskLabel).forEach(s=>{try{e.has(s)&&(this.canvas.remove(s),e.delete(s))}catch(a){}}),t.forEach(s=>{if(s.maskId&&s.__label)try{delete s.__label}catch(a){}})}_syncMaskLabel(t){if(!t||!this.options.maskLabelOnSelect||!t.__label)return;typeof t.setCoords=="function"&&t.setCoords();let e=t.getBoundingRect?t.getBoundingRect(!0,!0):null;if(!e)return;let i={x:e.left,y:e.top},s=t.getCenterPoint(),a=s.x-i.x,o=s.y-i.y,c=Math.sqrt(a*a+o*o)||1,l=a/c,r=o/c,n=Math.max(0,this.options.maskLabelOffset??3),h=i.x+l*n,f=i.y+r*n;t.__label.set({left:Math.round(h),top:Math.round(f),angle:t.angle||0,originX:"left",originY:"top",visible:!0}),t.__label.setCoords(),typeof this.canvas.requestRenderAll=="function"?this.canvas.requestRenderAll():this.canvas.renderAll()}_showLabelForMask(t){t&&this.options.maskLabelOnSelect&&(t.__label||this._createLabelForMask(t),t.__label.set({visible:!0}),this._syncMaskLabel(t))}_handleSelectionChanged(t){let e=(t||[]).find(s=>s.maskId);this.canvas.getObjects().filter(s=>s.maskId).forEach(s=>{if(s!==e){if(s.__label){try{this.canvas.remove(s.__label)}catch(o){}delete s.__label}let a=Number(s.originalStrokeWidth);s.set({stroke:s.originalStroke||"#ccc",strokeWidth:Number.isFinite(a)?a:1})}else s.set({stroke:"#ff0000",strokeWidth:1})}),e&&this._showLabelForMask(e),this._updateMaskListSelection(e),this.canvas.renderAll(),this._updateUI()}_updateMaskList(){let t=this._getElement("maskList");if(!t)return;t.innerHTML="",this.canvas.getObjects().filter(i=>i.maskId).forEach(i=>{let s=document.createElement("li");s.className="list-group-item mask-item",s.textContent=i.maskName,s.dataset.maskId=String(i.maskId),t.appendChild(s)})}_handleMaskListClick(t){if(!this.canvas)return;let e=t.target&&t.target.closest?t.target.closest(".mask-item"):null;if(!e||!e.dataset)return;let i=Number(e.dataset.maskId),s=this.canvas.getObjects().find(a=>Number(a.maskId)===i);s&&(this.canvas.setActiveObject(s),this._handleSelectionChanged([s]))}_updateMaskListSelection(t){let e=this._getElement("maskList");if(!e)return;e.querySelectorAll(".mask-item").forEach(s=>{let a=!!t&&Number(s.dataset.maskId)===Number(t.maskId);s.classList.toggle("active",a),s.classList.toggle("selected",a)})}async mergeMasks(){if(!this.originalImage||(this._assertIdleForOperation("mergeMasks"),!this.canvas.getObjects().filter(s=>s.maskId).length))return;let e=this._serializeCanvasState(),i=this._beginBusyOperation("mergeMasks");this.canvas.discardActiveObject(),this.canvas.renderAll();try{let s=await this.exportImageBase64(this._withInternalOperationOptions(i,{exportImageArea:!0,multiplier:this.options.exportMultiplier,fileType:"png"}));if(this.removeAllMasks(this._withInternalOperationOptions(i,{saveHistory:!1})),this.canvas.getObjects().some(o=>o.maskId))throw new Error("Masks could not be removed during merge");await this.loadImage(s,this._withInternalOperationOptions(i,{preserveScroll:!0,resetMaskCounter:!1}));let a=this._serializeCanvasState();this._pushStateTransition(e,a)}catch(s){this._reportError("merge error",s);try{await this.loadFromState(e)}catch(a){this._reportError("mergeMasks rollback failed",a)}throw s}finally{this._endBusyOperation(i)}}async merge(){return this.mergeMasks()}downloadImage(t=this.options.defaultDownloadFileName){if(!this.originalImage||!this._canMutateNow("downloadImage"))return;let e=this.options.exportImageAreaByDefault;this.exportImageBase64({exportImageArea:e,multiplier:this.options.exportMultiplier}).then(i=>{let s=document.createElement("a");s.download=t,s.href=i,document.body.appendChild(s),s.click(),document.body.removeChild(s)}).catch(i=>this._reportError("download error",i))}async exportImageBase64(t={}){if(!this.originalImage)throw new Error("No image loaded");this._assertIdleForOperation("exportImageBase64",t);let e=typeof t.exportImageArea=="boolean"?t.exportImageArea:this.options.exportImageAreaByDefault,i=t.multiplier||this.options.exportMultiplier||1,s=this._normalizeQuality(t.quality??this.options.downsampleQuality),a=this._normalizeImageFormat(t.fileType||t.format);if(!e){let h=this.canvas.getObjects().filter(p=>p.maskId||p.maskLabel),f=this.canvas.getObjects().filter(p=>p.maskId),d=h.map(p=>({object:p,visible:p.visible})),u=this._captureMaskExportBackups(f),m=this._captureMaskLabelBackups(f),g=this._captureActiveObjectBackup();try{h.forEach(I=>{I.set({visible:!1})}),this.canvas.discardActiveObject(),this.canvas.renderAll(),this.originalImage.setCoords();let p=this.originalImage.getBoundingRect(!0,!0),y=this._getClampedCanvasRegion(p);return await this._exportCanvasRegionToDataURL({...y,multiplier:i,quality:s,format:a,sealPartialEdges:this._getPartialExportEdges(p)})}finally{d.forEach(p=>{try{p.object.set({visible:p.visible})}catch(y){}}),this._restoreMaskExportBackups(u),this._restoreMaskLabelBackups(m),this._restoreActiveObjectBackup(g),this.canvas.renderAll()}}let o=this.canvas.getObjects().filter(h=>h.maskId),c=this._captureMaskExportBackups(o),l=this._captureMaskLabelBackups(o),r=this._captureActiveObjectBackup(),n;try{o.forEach(d=>this._removeLabelForMask(d)),this.canvas.discardActiveObject(),this.canvas.renderAll(),o.forEach(d=>{d.set({opacity:1,fill:"#000000",strokeWidth:0,stroke:null,selectable:!1}),d.setCoords()}),this.canvas.renderAll(),this.originalImage.setCoords();let h=this.originalImage.getBoundingRect(!0,!0),f=this._getClampedCanvasRegion(h);n=await this._exportCanvasRegionToDataURL({...f,multiplier:i,quality:s,format:a,sealPartialEdges:this._getPartialExportEdges(h)})}finally{this._restoreMaskExportBackups(c),this._restoreMaskLabelBackups(l),this._restoreActiveObjectBackup(r),this.canvas.renderAll()}return n}async getImageBase64(t={}){return this.exportImageBase64(t)}async exportImageFile(t={}){if(!this.originalImage)throw new Error("No image loaded");this._assertIdleForOperation("exportImageFile");let{mergeMask:e=!0,fileType:i="jpeg",quality:s=this.options.downsampleQuality??.92,multiplier:a=this.options.exportMultiplier??1,fileName:o=this.options.defaultDownloadFileName??"exported_image.jpg"}=t,c=this._normalizeImageFormat(i),l=this._normalizeQuality(s),r;e?r=await this.exportImageBase64({exportImageArea:!0,multiplier:a,quality:l,fileType:c}):r=await this.exportImageBase64({exportImageArea:!1,multiplier:a,quality:l,fileType:c});let n=r;n.startsWith(`data:image/${c}`)||(n=await new Promise((d,u)=>{let m=new window.Image;m.crossOrigin="Anonymous",m.onload=()=>{try{let g=document.createElement("canvas");g.width=m.width,g.height=m.height;let p=g.getContext("2d");if(!p)throw new Error("Unable to create 2D canvas context for export conversion");p.drawImage(m,0,0);let y=g.toDataURL(`image/${c}`,l);d(y)}catch(g){u(g)}},m.onerror=u,m.src=r}));let h=this._decodeBase64Payload(n.split(",")[1]),f=`image/${c}`;return new File([h],o,{type:f})}_clearMaskPlacementMemory(){this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null}async _restoreStateAfterCropFailure(t,e,i){if(this._reportError(e,i),this._cropRect&&this.canvas&&this._removeCropRect(),this._cropRect=null,this._cropMode=!1,this.canvas&&this._prevSelectionSetting!==void 0&&(this.canvas.selection=!!this._prevSelectionSetting),this._prevSelectionSetting=void 0,t)try{await this.loadFromState(t)}catch(s){this._reportError("applyCrop: rollback failed",s)}this._updateUI(),this.canvas&&this.canvas.renderAll()}_restoreCropObjectState(){Array.isArray(this._cropPrevEvented)&&this._cropPrevEvented.forEach(t=>{try{t.object.set({evented:t.evented,selectable:t.selectable,visible:t.visible})}catch(e){}}),this._cropPrevEvented=null}_removeCropRect(){if(this._cropRect){try{this._cropHandlers&&this._cropHandlers.length&&this._cropHandlers.forEach(t=>{t.handlers.forEach(e=>{t.target&&typeof t.target.off=="function"&&t.target.off(e.eventName,e.handler)})})}catch(t){}try{this.canvas&&this.canvas.remove(this._cropRect)}catch(t){}this._cropRect=null,this._cropHandlers=[]}}enterCropMode(){if(!this.canvas||!this.originalImage||this._cropMode||!this._canMutateNow("enterCropMode")||!this.isImageLoaded())return;this._removeCropRect(),this._cropMode=!0,this._prevSelectionSetting=this.canvas.selection,this.canvas.selection=!1,this.canvas.discardActiveObject(),this.originalImage.setCoords();let t=this.originalImage.getBoundingRect(!0,!0),e=this.options.crop&&this.options.crop.padding?this.options.crop.padding:10,i=Math.max(0,Math.floor(t.left+e)),s=Math.max(0,Math.floor(t.top+e)),a=Math.max(1,Math.floor(t.width-e*2)),o=Math.max(1,Math.floor(t.height-e*2)),c=Math.max(1,Number(this.options.crop.minWidth)||50),l=Math.max(1,Number(this.options.crop.minHeight)||50),r=Math.min(c,a),n=Math.min(l,o),h=r,f=n,d=new _.Rect({left:i,top:s,width:h,height:f,fill:"rgba(0,0,0,0.12)",stroke:"#00aaff",strokeDashArray:[6,4],strokeWidth:1,strokeUniform:!0,selectable:!0,hasRotatingPoint:!!(this.options.crop&&this.options.crop.allowRotationOfCropRect),lockRotation:!(this.options.crop&&this.options.crop.allowRotationOfCropRect),cornerSize:8,objectCaching:!1,originX:"left",originY:"top",lockScalingFlip:!0});this.canvas.add(d),d.isCropRect=!0,this.canvas.bringToFront(d),this.canvas.setActiveObject(d),this._cropRect=d,this._cropPrevEvented=[];let u=!!(this.options.crop&&this.options.crop.hideMasksDuringCrop);this.canvas.getObjects().forEach(g=>{if(g!==d){this._cropPrevEvented.push({object:g,evented:g.evented,selectable:g.selectable,visible:g.visible});try{let p={evented:!1,selectable:!1};u&&(g.maskId||g.maskLabel)&&(p.visible=!1),g.set(p)}catch(p){}}});let m=()=>{try{let g=Math.max(1,Number(d.width)||1),p=Math.max(1,Number(d.height)||1),y=Math.min(a/g,Math.max(r/g,Number(d.scaleX)||1)),I=Math.min(o/p,Math.max(n/p,Number(d.scaleY)||1));d.set({scaleX:y,scaleY:I}),d.setCoords();let v=d.getBoundingRect(!0,!0),x=Number(t.left)||0,O=Number(t.top)||0,B=x+(Number(t.width)||0),A=O+(Number(t.height)||0),w=0,E=0;v.left<x?w=x-v.left:v.left+v.width>B&&(w=B-(v.left+v.width)),v.top<O?E=O-v.top:v.top+v.height>A&&(E=A-(v.top+v.height)),(w||E)&&(d.set({left:(Number(d.left)||0)+w,top:(Number(d.top)||0)+E}),d.setCoords()),this.canvas.requestRenderAll()}catch(g){}};d.on("modified",m),d.on("moving",m),d.on("scaling",m),this._cropHandlers.push({target:d,handlers:[{eventName:"modified",handler:m},{eventName:"moving",handler:m},{eventName:"scaling",handler:m}]}),this._updateUI(),this.canvas.renderAll()}cancelCrop(){!this.canvas||!this._cropMode||(this._removeCropRect(),this._restoreCropObjectState(),this._cropMode=!1,this.canvas.selection=!!this._prevSelectionSetting,this._prevSelectionSetting=void 0,this.canvas.discardActiveObject(),this._updateUI(),this.canvas.renderAll())}async applyCrop(){if(!this.canvas||!this._cropMode||!this._cropRect)return;this._assertIdleForOperation("applyCrop"),this._cropRect.setCoords();let t=this._cropRect.getBoundingRect(!0,!0),e=this._getClampedCanvasRegion(t,{includePartialPixels:!1}),i=!!(this.options.crop&&this.options.crop.preserveMasksAfterCrop);this._restoreCropObjectState();let s;try{s=this._serializeCanvasState()}catch(l){this._reportWarning("applyCrop: could not serialize before state",l),s=null}let a=[];try{let l=this.canvas.getObjects().filter(r=>r.maskId);l&&l.length&&(l.forEach(r=>{r.setCoords();let n=r.getBoundingRect(!0,!0),h=n.left<e.sourceX+e.sourceWidth&&n.left+n.width>e.sourceX&&n.top<e.sourceY+e.sourceHeight&&n.top+n.height>e.sourceY;this._removeLabelForMask(r),this.canvas.remove(r),i&&h&&(this._translateObjectByCanvasOffset(r,-e.sourceX,-e.sourceY),r.set({visible:!0}),a.push(r))}),this._clearMaskPlacementMemory(),this.canvas.discardActiveObject(),this.canvas.renderAll())}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: failed to prepare masks",l);return}this._removeCropRect(),this._cropMode=!1,this.canvas.selection=!!this._prevSelectionSetting,this._prevSelectionSetting=void 0;let o;try{o=await this._exportCanvasRegionToDataURL({...e,multiplier:1,quality:this._normalizeQuality(this.options.downsampleQuality),format:"jpeg"})}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: failed to create cropped image",l);return}try{await this.loadImage(o,{resetMaskCounter:!1}),a.length&&(a.forEach(l=>{this._rebindMaskEvents(l),this.canvas.add(l),this.canvas.bringToFront(l)}),this._lastMask=a[a.length-1],this.maskCounter=a.reduce((l,r)=>Math.max(l,r.maskId||0),this.maskCounter),this._updateMaskList(),this.canvas.renderAll())}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: loadImage(croppedBase64) failed",l);return}let c;try{c=a.length?this._serializeCanvasState():this._lastSnapshot}catch(l){this._reportWarning("applyCrop: failed to serialize after state",l),c=null}try{this._pushStateTransition(s,c)}catch(l){this._reportWarning("applyCrop: failed to push history command",l)}this._updateUI(),this.canvas.renderAll()}_updateInputs(){let t=this._getElement("scaleRate");t&&(t.value=Math.round(this.currentScale*100))}_updateUI(){if(!this.canvas)return;let t=!!this.originalImage,i=(t?this.canvas.getObjects().filter(h=>h.maskId):[]).length>0,s=this.canvas.getActiveObject(),a=s&&s.maskId,o=this.currentScale===1&&this.currentRotation===0,c=this.historyManager?.canUndo(),l=this.historyManager?.canRedo(),r=!!this._cropMode,n=this.isBusy();if(r){for(let h of Object.keys(this.elements||{}))this._getElement(h)&&(h==="applyCropBtn"||h==="cancelCropBtn"?this._setDisabled(h,!1):this._setDisabled(h,!0));return}this._setDisabled("zoomInBtn",!t||n||this.currentScale>=this.options.maxScale),this._setDisabled("zoomOutBtn",!t||n||this.currentScale<=this.options.minScale),this._setDisabled("rotateLeftBtn",!t||n),this._setDisabled("rotateRightBtn",!t||n),this._setDisabled("addMaskBtn",!t||n),this._setDisabled("removeMaskBtn",!a||n),this._setDisabled("removeAllMasksBtn",!i||n),this._setDisabled("mergeBtn",!t||!i||n),this._setDisabled("downloadBtn",!t||n),this._setDisabled("resetBtn",!t||o||n),this._setDisabled("undoBtn",!t||n||!c),this._setDisabled("redoBtn",!t||n||!l),this._setDisabled("cropBtn",!t||n),this._setDisabled("applyCropBtn",!0),this._setDisabled("cancelCropBtn",!0),this._setDisabled("scaleRate",!t||n),this._setDisabled("rotationLeftInput",!t||n),this._setDisabled("rotationRightInput",!t||n),this._setDisabled("maskList",!t||n),this._setDisabled("imageInput",n),this._setDisabled("uploadArea",n)}_setDisabled(t,e){let i=this._getElement(t);if(i){if("disabled"in i){i.disabled=!!e;return}this._elementOriginalPointerEvents||(this._elementOriginalPointerEvents=new Map),this._elementOriginalPointerEvents.has(t)||this._elementOriginalPointerEvents.set(t,i.style.pointerEvents||""),e?(i.setAttribute("aria-disabled","true"),i.style.pointerEvents="none"):(i.removeAttribute("aria-disabled"),i.style.pointerEvents=this._elementOriginalPointerEvents.get(t)??"")}}_isElementDisabled(t){return t?"disabled"in t?!!t.disabled:t.getAttribute("aria-disabled")==="true":!1}_updatePlaceholderStatus(){this.options.showPlaceholder&&this._setPlaceholderVisible(!this.originalImage)}_setPlaceholderVisible(t){this.placeholderElement&&this._setElementVisible(this.placeholderElement,t);let e=this._getCanvasVisibilityElement();e&&e!==this.placeholderElement&&this._setElementVisible(e,!t)}_getCanvasVisibilityElement(){let t=this.canvas&&this.canvas.wrapperEl?this.canvas.wrapperEl:null;return this.containerElement&&this.placeholderElement&&(this.containerElement===this.placeholderElement||this.containerElement.contains(this.placeholderElement))?t||this.canvasElement:this.containerElement||t||this.canvasElement}_setElementVisible(t,e){t&&(this._rememberElementVisibility(t),t.hidden=!e,t.setAttribute("aria-hidden",e?"false":"true"),t.classList&&t.classList.toggle("d-none",!e))}_rememberElementVisibility(t){!t||this._visibilityStateByElement.has(t)||this._visibilityStateByElement.set(t,this._captureElementVisibility(t))}_captureElementVisibility(t){return t?{hidden:t.hidden,ariaHidden:t.getAttribute("aria-hidden"),className:t.className}:null}_restoreElementVisibility(t,e){!t||!e||(t.hidden=!!e.hidden,e.ariaHidden===null?t.removeAttribute("aria-hidden"):t.setAttribute("aria-hidden",e.ariaHidden),t.className=e.className||"")}dispose(){this._disposed=!0,this._rejectActiveAnimations(new Error("Editor disposed during animation")),this.animationQueue&&this.animationQueue.cancelAll(new Error("Editor disposed")),this._isLoading=!1,this._activeOperationName=null,this._activeOperationToken=null;try{for(let[t,e]of Object.entries(this._handlersByElementKey||{})){let i=this._getElement(t);i&&e.forEach(s=>{try{i.removeEventListener(s.eventName,s.handler)}catch(a){}})}}catch(t){}if(this._cropRect){try{this.canvas.remove(this._cropRect)}catch(t){}this._cropRect=null}if(this.containerElement&&this._containerOriginalOverflow)try{this._restoreContainerOverflowState()}catch(t){}if(this._visibilityStateByElement)try{[this.placeholderElement,this._getCanvasVisibilityElement()].forEach(t=>{let e=t?this._visibilityStateByElement.get(t):null;e&&this._restoreElementVisibility(t,e)})}catch(t){}if(this.canvasElement&&this._canvasElementOriginalStyle)try{this.canvasElement.style.display=this._canvasElementOriginalStyle.display,this.canvasElement.style.width=this._canvasElementOriginalStyle.width,this.canvasElement.style.height=this._canvasElementOriginalStyle.height}catch(t){}if(this.canvas){try{this.canvas.dispose()}catch(t){}this.canvas=null,this.canvasElement=null,this.isImageLoadedToCanvas=!1}this._handlersByElementKey={},this._elementCache={},this._elementOriginalPointerEvents=new Map,this._clearMaskPlacementMemory(),this.originalImage=null,this.baseImageScale=1,this.currentScale=1,this.currentRotation=0,this.isAnimating=!1,this._isLoading=!1,this._cropMode=!1,this._cropRect=null,this._cropHandlers=[],this._cropPrevEvented=null,this._prevSelectionSetting=void 0,this._lastContainerViewportSize=null,this._initialized=!1}},C=class{constructor(){this.animationTasks=[],this.isRunning=!1,this.currentTask=null,this._generation=0}async add(t){return new Promise((e,i)=>{this.animationTasks.push({animationFn:t,resolve:e,reject:i,isSettled:!1}),this.isRunning||this._drainQueue()})}isBusy(){return this.isRunning||this.animationTasks.length>0}cancelAll(t=new Error("Animation queue cancelled")){this._generation+=1;let e=t instanceof Error?t:new Error(String(t));[...this.currentTask?[this.currentTask]:[],...this.animationTasks.splice(0)].forEach(s=>{!s||s.isSettled||(s.isSettled=!0,s.reject(e))}),this.isRunning=!1,this.currentTask=null}async _drainQueue(){if(this.isRunning)return;let t=this._generation;this.isRunning=!0;try{for(;this.animationTasks.length>0&&t===this._generation;){let e=this.animationTasks.shift();this.currentTask=e;try{let i=await e.animationFn();t===this._generation&&!e.isSettled&&(e.isSettled=!0,e.resolve(i))}catch(i){t===this._generation&&!e.isSettled&&(e.isSettled=!0,e.reject(i))}finally{t===this._generation&&this.currentTask===e&&(this.currentTask=null)}}}finally{t===this._generation&&(this.isRunning=!1,this.currentTask=null)}}},k=class{constructor(t,e){this.execute=t,this.undo=e}},M=class{constructor(t=50){this.history=[],this.currentIndex=-1,this.maxSize=t,this.pending=Promise.resolve()}enqueue(t){let e=this.pending.then(()=>Promise.resolve().then(t));return this.pending=e.catch(()=>{}),e}execute(t){let e=t.execute();return e&&typeof e.then=="function"?this.enqueue(()=>Promise.resolve(e).then(()=>{this.push(t)})):(this.push(t),e)}push(t){this.currentIndex<this.history.length-1&&(this.history=this.history.slice(0,this.currentIndex+1)),this.history.push(t),this.history.length>this.maxSize&&this.history.shift(),this.currentIndex=this.history.length-1}canUndo(){return this.currentIndex>=0}canRedo(){return this.currentIndex<this.history.length-1}undo(){return this.enqueue(async()=>{if(this.currentIndex>=0){let t=this.currentIndex;await this.history[t].undo(),this.currentIndex=t-1}})}redo(){return this.enqueue(async()=>{if(this.currentIndex<this.history.length-1){let t=this.currentIndex+1;await this.history[t].execute(),this.currentIndex=t}})}};var F=T;var z=S&&(S.fabric||S.default||S);L(z);var U=F;export{F as ImageEditor,U as default};
8
+ */var _=null,N=Symbol.for("ImageEditorInternalOperation");function W(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:null}function P(){let b=W();return b&&b.fabric?b.fabric:null}function A(b){return _=b||P(),_}function R(){return _||A(),_}var B=class{constructor(t={}){let e={getText:o=>o.maskName,textOptions:{fontSize:12,fill:"#fff",backgroundColor:"rgba(0,0,0,0.7)",padding:2,fontFamily:"monospace",fontWeight:"bold",selectable:!1,evented:!1,originX:"left",originY:"top"}},i={minWidth:100,minHeight:100,padding:10,hideMasksDuringCrop:!0,preserveMasksAfterCrop:!1,allowRotationOfCropRect:!1},s=t.label||{},a=t.crop||{};this.options={canvasWidth:800,canvasHeight:600,backgroundColor:"transparent",animationDuration:300,minScale:.1,maxScale:5,scaleStep:.05,rotationStep:90,expandCanvasToImage:!0,fitImageToCanvas:!1,coverImageToCanvas:!1,downsampleOnLoad:!0,downsampleMaxWidth:4e3,downsampleMaxHeight:3e3,downsampleQuality:.92,preserveSourceFormat:!0,downsampleMimeType:null,imageLoadTimeoutMs:3e4,exportMultiplier:1,exportImageAreaByDefault:!0,defaultMaskWidth:50,defaultMaskHeight:80,maskRotatable:!1,maskLabelOnSelect:!0,maskLabelOffset:3,maskName:"mask",groupSelection:!1,showPlaceholder:!0,initialImageBase64:null,defaultDownloadFileName:"edited_image.jpg",onError:null,onWarning:null,...t,label:{...e,...s,textOptions:{...e.textOptions,...s.textOptions||{}}},crop:{...i,...a}},this._fabricLoaded=!!R(),this._fabricLoaded||this._reportError("fabric.js is not loaded. Please include fabric.js first. Initialization will be aborted."),this.canvas=null,this.canvasElement=null,this.containerElement=null,this.placeholderElement=null,this.originalImage=null,this.baseImageScale=1,this.currentScale=1,this.currentRotation=0,this.maskCounter=0,this.isAnimating=!1,this._isLoading=!1,this._activeOperationName=null,this._activeOperationToken=null,this.elements={},this.isImageLoadedToCanvas=!1,this.maxHistorySize=50,this._handlersByElementKey={},this._elementCache={},this._elementOriginalPointerEvents=new Map,this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null,this._lastSnapshot=null,this._cropMode=!1,this._cropRect=null,this._cropHandlers=[],this._cropPrevEvented=null,this._prevSelectionSetting=void 0,this._containerOriginalOverflow=null,this._lastContainerViewportSize=null,this._canvasElementOriginalStyle=null,this._visibilityStateByElement=new WeakMap,this._scrollbarSizeCache=null,this._activeAnimationRejectors=new Set,this._disposed=!1,this._initialized=!1,this.onImageLoaded=typeof this.options.onImageLoaded=="function"?this.options.onImageLoaded:null,this.animationQueue=new C,this.historyManager=new I(this.maxHistorySize)}get canvasEl(){return this.canvasElement}set canvasEl(t){this.canvasElement=t}get containerEl(){return this.containerElement}set containerEl(t){this.containerElement=t}get placeholderEl(){return this.placeholderElement}set placeholderEl(t){this.placeholderElement=t}init(t={}){if(!this._fabricLoaded)return;(this._initialized||this.canvas)&&this.dispose(),this._disposed=!1,this._initialized=!0,this.animationQueue=new C,this.historyManager=new I(this.maxHistorySize),this._visibilityStateByElement=new WeakMap,this._activeAnimationRejectors=new Set,this._isLoading=!1,this._activeOperationName=null,this._activeOperationToken=null,this._elementOriginalPointerEvents=new Map,this._containerOriginalOverflow=null,this._lastContainerViewportSize=null,this._canvasElementOriginalStyle=null,this._deprecatedElementKeyWarnings=new Set;let e={canvas:"fabricCanvas",canvasContainer:null,imagePlaceholder:"imagePlaceholder",imgPlaceholder:null,scalePercentageInput:"scalePercentageInput",scaleRate:null,rotateLeftDegreesInput:"rotateLeftDegreesInput",rotationLeftInput:null,rotateRightDegreesInput:"rotateRightDegreesInput",rotationRightInput:null,rotateLeftButton:"rotateLeftButton",rotateLeftBtn:null,rotateRightButton:"rotateRightButton",rotateRightBtn:null,createMaskButton:"createMaskButton",addMaskBtn:null,removeSelectedMaskButton:"removeSelectedMaskButton",removeMaskBtn:null,removeAllMasksButton:"removeAllMasksButton",removeAllMasksBtn:null,mergeMasksButton:"mergeMasksButton",mergeBtn:null,downloadImageButton:"downloadImageButton",downloadBtn:null,maskList:"maskList",zoomInButton:"zoomInButton",zoomInBtn:null,zoomOutButton:"zoomOutButton",zoomOutBtn:null,resetImageTransformButton:"resetImageTransformButton",resetBtn:null,undoButton:"undoButton",undoBtn:null,redoButton:"redoButton",redoBtn:null,imageInput:"imageInput",enterCropModeButton:"enterCropModeButton",cropBtn:null,applyCropButton:"applyCropButton",applyCropBtn:null,cancelCropButton:"cancelCropButton",cancelCropBtn:null};this.elements=this._resolveElementIdMap(t||{},e),this._elementCache={},this._initCanvas(),this._bindEvents(),this._updateInputs(),this._updateMaskList(),this._updateUI(),this.options.initialImageBase64?this.loadImage(this.options.initialImageBase64):this._updatePlaceholderStatus()}_resolveElementIdMap(t,e){let i={...e,...t};return this._resolveElementAliases(i,t,e,"imagePlaceholder",["imgPlaceholder"]),this._resolveElementAliases(i,t,e,"scalePercentageInput",["scaleRate"]),this._resolveElementAliases(i,t,e,"rotateLeftDegreesInput",["rotationLeftInput"]),this._resolveElementAliases(i,t,e,"rotateRightDegreesInput",["rotationRightInput"]),this._resolveElementAlias(i,t,e,"rotateLeftButton","rotateLeftBtn"),this._resolveElementAlias(i,t,e,"rotateRightButton","rotateRightBtn"),this._resolveElementAlias(i,t,e,"createMaskButton","addMaskBtn"),this._resolveElementAliases(i,t,e,"removeSelectedMaskButton",["removeMaskBtn"]),this._resolveElementAlias(i,t,e,"removeAllMasksButton","removeAllMasksBtn"),this._resolveElementAlias(i,t,e,"mergeMasksButton","mergeBtn"),this._resolveElementAliases(i,t,e,"downloadImageButton",["downloadBtn"]),this._resolveElementAlias(i,t,e,"zoomInButton","zoomInBtn"),this._resolveElementAlias(i,t,e,"zoomOutButton","zoomOutBtn"),this._resolveElementAlias(i,t,e,"resetImageTransformButton","resetBtn"),this._resolveElementAlias(i,t,e,"undoButton","undoBtn"),this._resolveElementAlias(i,t,e,"redoButton","redoBtn"),this._resolveElementAliases(i,t,e,"enterCropModeButton",["cropBtn"]),this._resolveElementAlias(i,t,e,"applyCropButton","applyCropBtn"),this._resolveElementAlias(i,t,e,"cancelCropButton","cancelCropBtn"),i}_resolveElementAlias(t,e,i,s,a){this._resolveElementAliases(t,e,i,s,[a])}_resolveElementAliases(t,e,i,s,a){if(Object.prototype.hasOwnProperty.call(e,s)){t[s]=e[s];return}let c,l=!1;for(let r of a)Object.prototype.hasOwnProperty.call(e,r)&&(l||(c=e[r],l=!0),this._warnDeprecatedElementIdKey(r,s));if(l){t[s]=c;return}t[s]=i[s]}_warnDeprecatedElementIdKey(t,e){this._deprecatedElementKeyWarnings||(this._deprecatedElementKeyWarnings=new Set),!this._deprecatedElementKeyWarnings.has(t)&&(this._deprecatedElementKeyWarnings.add(t),this._reportWarning(`ElementIdMap.${t} is deprecated. Use ${e} instead. This alias will be removed in v2.0.0.`))}_reportError(t,e=null){let i=this.options&&this.options.onError;if(typeof i=="function")try{i(e,t)}catch{}}_reportWarning(t,e=null){let i=this.options&&this.options.onWarning;if(typeof i=="function")try{i(e,t)}catch{}}_notifyImageLoaded(){let t=this.options&&this.options.onImageLoaded,e=typeof t=="function"?t:this.onImageLoaded;typeof e=="function"&&e()}_initCanvas(){let t=this._getElement("canvas");if(!t)throw new Error("Canvas is not found: "+this.elements.canvas);if(this.canvasElement=t,this._canvasElementOriginalStyle={display:t.style.display||"",width:t.style.width||"",height:t.style.height||"",maxWidth:t.style.maxWidth||""},this.elements.canvasContainer){let s=this._getElement("canvasContainer");this.containerElement=s||t.parentElement}else this.containerElement=t.parentElement;this.placeholderElement=this._getElement("imagePlaceholder")||null;let e=this.options.canvasWidth,i=this.options.canvasHeight;if(this.containerElement){let s=Math.floor(this.containerElement.clientWidth),a=Math.floor(this.containerElement.clientHeight);s>0&&a>0&&(e=s,i=a,this._lastContainerViewportSize={width:s,height:a})}this.canvas=new _.Canvas(t,{width:e,height:i,backgroundColor:this.options.backgroundColor,selection:this.options.groupSelection,preserveObjectStacking:!0}),this.canvas.on("selection:created",s=>this._handleSelectionChanged(s.selected)),this.canvas.on("selection:updated",s=>this._handleSelectionChanged(s.selected)),this.canvas.on("selection:cleared",()=>this._handleSelectionChanged([])),this.canvas.on("object:moving",s=>{s.target&&s.target.maskId&&this._syncMaskLabel(s.target)}),this.canvas.on("object:scaling",s=>{s.target&&s.target.maskId&&this._syncMaskLabel(s.target)}),this.canvas.on("object:rotating",s=>{s.target&&s.target.maskId&&this._syncMaskLabel(s.target)}),this.canvas.on("object:modified",s=>this._handleObjectModified(s.target)),this.canvasElement.style.display="block"}_getElement(t){let e=this.elements&&this.elements[t];if(!e)return null;if(this._elementCache&&Object.prototype.hasOwnProperty.call(this._elementCache,t))return this._elementCache[t];let i=document.getElementById(e);return this._elementCache&&(this._elementCache[t]=i||null),i||null}_handleObjectModified(t){let e=this._getModifiedMasks(t);e.length&&(e.forEach(i=>{typeof i.setCoords=="function"&&i.setCoords(),this._syncMaskLabel(i)}),this._expandCanvasToFitObjects(e),this.saveState())}_getModifiedMasks(t){if(!t)return[];if(t.maskId)return[t];let e=typeof t.getObjects=="function"?t.getObjects():[];return Array.isArray(e)?e.filter(i=>i&&i.maskId):[]}_syncContainerOverflow(t={}){if(!this.containerElement||!this.containerElement.style)return;this._captureContainerOverflowState();let e=t.preserveScroll===!0;this.options.coverImageToCanvas?(this.containerElement.style.overflow="scroll",e||(this.containerElement.scrollLeft=0,this.containerElement.scrollTop=0)):this.options.fitImageToCanvas?(this.containerElement.style.overflow="auto",e||(this.containerElement.scrollLeft=0,this.containerElement.scrollTop=0)):this._restoreContainerOverflowState()}_captureContainerOverflowState(){!this.containerElement||!this.containerElement.style||this._containerOriginalOverflow||(this._containerOriginalOverflow={overflow:this.containerElement.style.overflow||"",overflowX:this.containerElement.style.overflowX||"",overflowY:this.containerElement.style.overflowY||""})}_restoreContainerOverflowState(){!this.containerElement||!this.containerElement.style||!this._containerOriginalOverflow||(this.containerElement.style.overflow=this._containerOriginalOverflow.overflow,this.containerElement.style.overflowX=this._containerOriginalOverflow.overflowX,this.containerElement.style.overflowY=this._containerOriginalOverflow.overflowY)}_restoreContainerOverflowSnapshot(t){!this.containerElement||!this.containerElement.style||!t||(this.containerElement.style.overflow=t.overflow||"",this.containerElement.style.overflowX=t.overflowX||"",this.containerElement.style.overflowY=t.overflowY||"")}_bindEvents(){this._bindIfExists("uploadArea","click",()=>{let t=this._getElement("uploadArea");this._isElementDisabled(t)||this._getElement("imageInput")?.click()}),this._bindIfExists("imageInput","change",t=>{let e=t.target.files&&t.target.files[0];e&&this._loadImageFile(e).catch(i=>this._reportError("Image file could not be loaded",i)).finally(()=>{t.target.value=""})}),this._bindIfExists("zoomInButton","click",()=>this.scaleImage(this.currentScale+this.options.scaleStep).catch(t=>this._reportError("scaleImage failed",t))),this._bindIfExists("zoomOutButton","click",()=>this.scaleImage(this.currentScale-this.options.scaleStep).catch(t=>this._reportError("scaleImage failed",t))),this._bindIfExists("resetImageTransformButton","click",()=>{this.resetImageTransform().catch(t=>this._reportError("resetImageTransform failed",t))}),this._bindIfExists("createMaskButton","click",()=>this.createMask()),this._bindIfExists("removeSelectedMaskButton","click",()=>this.removeSelectedMask()),this._bindIfExists("removeAllMasksButton","click",()=>this.removeAllMasks()),this._bindIfExists("mergeMasksButton","click",()=>this.mergeMasks().catch(t=>this._reportError("merge error",t))),this._bindIfExists("downloadImageButton","click",()=>this.downloadImage()),this._bindIfExists("undoButton","click",()=>this.undo().catch(t=>this._reportError("undo failed",t))),this._bindIfExists("redoButton","click",()=>this.redo().catch(t=>this._reportError("redo failed",t))),this._bindIfExists("rotateLeftButton","click",()=>{let t=this._getElement("rotateLeftDegreesInput"),e=this.options.rotationStep;if(t){let i=parseFloat(t.value);isNaN(i)||(e=i)}this.rotateImage(this.currentRotation-e).catch(i=>this._reportError("rotateImage failed",i))}),this._bindIfExists("rotateRightButton","click",()=>{let t=this._getElement("rotateRightDegreesInput"),e=this.options.rotationStep;if(t){let i=parseFloat(t.value);isNaN(i)||(e=i)}this.rotateImage(this.currentRotation+e).catch(i=>this._reportError("rotateImage failed",i))}),this._bindIfExists("enterCropModeButton","click",()=>this.enterCropMode()),this._bindIfExists("applyCropButton","click",()=>{this.applyCrop().catch(t=>this._reportError("applyCrop failed",t))}),this._bindIfExists("cancelCropButton","click",()=>this.cancelCrop()),this._bindIfExists("maskList","click",t=>this._handleMaskListClick(t))}_bindIfExists(t,e,i){let s=this._getElement(t);s&&(s.addEventListener(e,i),this._handlersByElementKey=this._handlersByElementKey||{},this._handlersByElementKey[t]||(this._handlersByElementKey[t]=[]),this._handlersByElementKey[t].push({eventName:e,handler:i}))}_loadImageFile(t){if(!this._isSupportedImageFile(t)){let e=new Error("Selected file is not a supported image");return this._reportError("Selected file is not a supported image",e),Promise.reject(e)}return new Promise((e,i)=>{let s=new FileReader;s.onload=a=>{this.loadImage(a.target.result).then(e).catch(i)},s.onerror=a=>{let o=new Error("Image file could not be read");this._reportError("Image file could not be read",a),i(o)},s.readAsDataURL(t)})}_isSupportedImageFile(t){if(!t)return!1;if(typeof t.type=="string"&&t.type.startsWith("image/"))return!0;let e=String(t.name||"");return/\.(avif|bmp|gif|jpe?g|png|webp)$/i.test(e)}_warnOnImageLayoutOptionConflict(){let t=[["fitImageToCanvas",this.options.fitImageToCanvas],["coverImageToCanvas",this.options.coverImageToCanvas],["expandCanvasToImage",this.options.expandCanvasToImage]].filter(([,e])=>!!e).map(([e])=>e);t.length<=1||this._reportWarning(`Only one image layout mode should be enabled. Active modes: ${t.join(", ")}.`)}async loadImage(t,e={}){if(!this._fabricLoaded||!this.canvas||this._disposed||!t||typeof t!="string"||!t.startsWith("data:image/"))return;this._assertIdleForOperation("loadImage",e),this._isLoading=!0,this._updateUI(),this._warnOnImageLayoutOptionConflict();let i=this._captureLoadImageTransaction();try{let s=await this._createImageElement(t);if(this._disposed||!this.canvas)throw new Error("Editor was disposed while loading image");let a=t,o=Number(this.options.downsampleMaxWidth),c=Number(this.options.downsampleMaxHeight);if(this.options.downsampleOnLoad&&o>0&&c>0){if(s.naturalWidth>o||s.naturalHeight>c){let u=Math.min(o/s.naturalWidth,c/s.naturalHeight),m=Math.round(s.naturalWidth*u),f=Math.round(s.naturalHeight*u);a=this._resampleImageToDataURL(s,m,f,this._normalizeQuality(this.options.downsampleQuality),t)}}else this.options.downsampleOnLoad&&this._reportWarning("loadImage: downsample limits must be positive numbers; using the original image");let l=await this._createFabricImageFromURL(a);if(this._disposed||!this.canvas)throw new Error("Editor was disposed while loading image");this.canvas.discardActiveObject(),this._hideAllMaskLabels(),this.canvas.clear(),this.canvas.setBackgroundColor(this.options.backgroundColor,this.canvas.renderAll.bind(this.canvas)),l.set({originX:"left",originY:"top",selectable:!1,evented:!1}),this._setPlaceholderVisible(!1),this._syncContainerOverflow({preserveScroll:e.preserveScroll===!0});let r=l.width,n=l.height,h=this._getContainerViewportSize(),g=h.width,p=h.height;if(this.options.fitImageToCanvas){let d=Math.max(1,g-1),u=Math.max(1,p-1);this._setCanvasSizeInt(d,u);let m=Math.min(d/r,u/n,1);l.set({left:0,top:0}),l.scale(m),this.baseImageScale=l.scaleX||1}else if(this.options.coverImageToCanvas){let d=this._calculateCoverCanvasLayout(r,n);this._setCanvasSizeInt(d.canvasWidth,d.canvasHeight),l.set({left:0,top:0}),l.scale(d.scale),this.baseImageScale=l.scaleX||1}else if(this.options.expandCanvasToImage){let d=Math.max(g,Math.floor(r)),u=Math.max(p,Math.floor(n));this._setCanvasSizeInt(d,u),l.set({left:0,top:0}),l.scale(1),this.baseImageScale=1}else{let d=Math.max(this.options.canvasWidth,g),u=Math.max(this.options.canvasHeight,p);this._setCanvasSizeInt(d,u);let m=Math.min(d/r,u/n,1);l.set({left:0,top:0}),l.scale(m),this.baseImageScale=l.scaleX||1}this.originalImage=l,this.canvas.add(l),this.canvas.sendToBack(l),this._clearMaskPlacementMemory(),e.resetMaskCounter!==!1&&(this.maskCounter=0),this.currentScale=1,this.currentRotation=0,this._updateInputs(),this._updateMaskList(),this.isImageLoadedToCanvas=!0,this._updateUI(),this.canvas.renderAll(),this._lastSnapshot=this._captureCanvasStateOrThrow("loadImage"),this._notifyImageLoaded()}catch(s){throw await this._rollbackLoadImageTransaction(i),s}finally{this._isLoading=!1,!this._disposed&&this.canvas&&this._updateUI()}}isImageLoaded(){let t=R();return!!(this.originalImage&&t&&this.originalImage instanceof t.Image&&this.originalImage.width>0&&this.originalImage.height>0)}isBusy(){return!!(this.isAnimating||this._cropMode||this._isLoading||this._activeOperationToken||this.animationQueue&&this.animationQueue.isBusy())}_createImageElement(t,e=this.options.imageLoadTimeoutMs){return new Promise((i,s)=>{let a=new Image,o=!1,c=Number.isFinite(Number(e))&&Number(e)>0?Number(e):3e4,l,r=n=>{o||(o=!0,clearTimeout(l),a.onload=null,a.onerror=null,n())};l=setTimeout(()=>{r(()=>s(new Error("Image load timed out")));try{a.src=""}catch(n){this._reportWarning("Image timeout cleanup failed",n)}},c),a.onload=()=>r(()=>i(a)),a.onerror=n=>r(()=>s(n)),a.src=t})}_createFabricImageFromURL(t,e=this.options.imageLoadTimeoutMs){return new Promise((i,s)=>{let a=this._getSafeTimeoutMs(e),o=!1,c,l=r=>{o||(o=!0,clearTimeout(c),r())};c=setTimeout(()=>{l(()=>s(new Error("Fabric image load timed out")))},a);try{_.Image.fromURL(t,r=>{l(()=>{if(!r){s(new Error("Image could not be loaded"));return}i(r)})},{crossOrigin:"anonymous"})}catch(r){l(()=>s(r))}})}_getSafeTimeoutMs(t){let e=Number(t);return Number.isFinite(e)&&e>0?e:3e4}_captureLoadImageTransaction(){return{canvasState:this._serializeCanvasState(),baseImageScale:this.baseImageScale,currentScale:this.currentScale,currentRotation:this.currentRotation,maskCounter:this.maskCounter,isImageLoadedToCanvas:this.isImageLoadedToCanvas,lastSnapshot:this._lastSnapshot,lastMask:this._lastMask,lastMaskInitialLeft:this._lastMaskInitialLeft,lastMaskInitialTop:this._lastMaskInitialTop,lastMaskInitialWidth:this._lastMaskInitialWidth,containerOverflow:this.containerElement&&this.containerElement.style?{overflow:this.containerElement.style.overflow||"",overflowX:this.containerElement.style.overflowX||"",overflowY:this.containerElement.style.overflowY||""}:null,scrollLeft:this.containerElement?this.containerElement.scrollLeft:0,scrollTop:this.containerElement?this.containerElement.scrollTop:0,placeholderVisibility:this._captureElementVisibility(this.placeholderElement),canvasVisibility:this._captureElementVisibility(this._getCanvasVisibilityElement())}}async _rollbackLoadImageTransaction(t){if(!t||!this.canvas||this._disposed)return;let e=!1,i=!1;try{t.canvasState&&(await this.loadFromState(t.canvasState),e=!0)}catch(s){this._lastMask=null,i=!0,this._reportError("loadImage rollback failed",s)}i?this._reconcileEditorStateFromCanvas():(this.baseImageScale=t.baseImageScale,this.currentScale=t.currentScale,this.currentRotation=t.currentRotation,this.maskCounter=t.maskCounter,this.isImageLoadedToCanvas=t.isImageLoadedToCanvas,this._lastSnapshot=t.lastSnapshot,e?this._restoreLastMaskReference(t.lastMask):this._lastMask=null,this._lastMaskInitialLeft=t.lastMaskInitialLeft,this._lastMaskInitialTop=t.lastMaskInitialTop,this._lastMaskInitialWidth=t.lastMaskInitialWidth),this._restoreElementVisibility(this.placeholderElement,t.placeholderVisibility),this._restoreElementVisibility(this._getCanvasVisibilityElement(),t.canvasVisibility),this.containerElement&&(this.containerElement.scrollLeft=t.scrollLeft,this.containerElement.scrollTop=t.scrollTop,this._restoreContainerOverflowSnapshot(t.containerOverflow)),this._updateInputs(),this._updateMaskList(),this._updateUI(),this.canvas&&this.canvas.renderAll()}_reconcileEditorStateFromCanvas(){if(!this.canvas){this.originalImage=null,this.baseImageScale=1,this.currentScale=1,this.currentRotation=0,this.maskCounter=0,this.isImageLoadedToCanvas=!1,this._lastSnapshot=null,this._clearMaskPlacementMemory();return}let t=this.canvas.getObjects();if(this.originalImage=t.find(i=>i.type==="image"&&!i.maskId)||null,this.originalImage){let i=Number(this.originalImage.scaleX)||1;this.baseImageScale=i,this.currentScale=1,this.currentRotation=Number(this.originalImage.angle)||0}else this.baseImageScale=1,this.currentScale=1,this.currentRotation=0;let e=t.filter(i=>i.maskId);this.maskCounter=e.reduce((i,s)=>Math.max(i,Number(s.maskId)||0),0),this._lastMask=e[e.length-1]||null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null),this.isImageLoadedToCanvas=!!this.originalImage;try{this._lastSnapshot=this._serializeCanvasState()}catch(i){this._lastSnapshot=null,this._reportWarning("loadImage rollback: failed to reconcile canvas snapshot",i)}}_restoreLastMaskReference(t){if(!this.canvas){this._lastMask=null;return}let e=this.canvas.getObjects().filter(s=>s.maskId),i=t&&t.maskId;this._lastMask=e.find(s=>s.maskId===i)||e[e.length-1]||null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null)}_resampleImageToDataURL(t,e,i,s=.92,a=null){let o=Math.max(1,Number(t&&(t.naturalWidth||t.width))||0),c=Math.max(1,Number(t&&(t.naturalHeight||t.height))||0),l=Math.round(Number(e)),r=Math.round(Number(i));if(!Number.isFinite(l)||!Number.isFinite(r)||l<=0||r<=0)throw new Error("Invalid image resample target dimensions");let n=document.createElement("canvas");n.width=l,n.height=r;let h=n.getContext("2d");if(!h)throw new Error("2D canvas context is unavailable");return h.drawImage(t,0,0,o,c,0,0,l,r),n.toDataURL(this._getDownsampleMimeType(a),s)}_getDataUrlMimeType(t){let e=String(t||"").match(/^data:([^;,]+)[;,]/i);return e?e[1].toLowerCase():""}_getDownsampleMimeType(t){if(this.options.downsampleMimeType)return`image/${this._normalizeImageFormat(this.options.downsampleMimeType)}`;let e=this._getDataUrlMimeType(t);return this.options.preserveSourceFormat!==!1&&(e==="image/png"||e==="image/webp")?e:"image/jpeg"}_captureCanvasStateOrThrow(t){let e=this._serializeCanvasState();if(!e)throw new Error(`${t}: canvas state is unavailable`);return e}_setCanvasSizeInt(t,e){if(!this.canvas)return;let i=Math.max(1,Math.round(Number(t)||1)),s=Math.max(1,Math.round(Number(e)||1));this.canvas.setWidth(i),this.canvas.setHeight(s),typeof this.canvas.calcOffset=="function"&&this.canvas.calcOffset(),this.canvasElement&&(this.canvasElement.style.width=i+"px",this.canvasElement.style.height=s+"px")}_ceilCanvasDimension(t){let e=Number(t)||0,i=Math.round(e);return Math.abs(e-i)<.01?i:Math.ceil(e)}_getContainerViewportSize(){if(!this.containerElement)return{width:Math.max(1,Math.floor(this.options.canvasWidth||1)),height:Math.max(1,Math.floor(this.options.canvasHeight||1))};let t=Math.floor(this.containerElement.clientWidth||0),e=Math.floor(this.containerElement.clientHeight||0),i=Math.max(1,t||this._lastContainerViewportSize?.width||this.options.canvasWidth||1),s=Math.max(1,e||this._lastContainerViewportSize?.height||this.options.canvasHeight||1);if(t>0&&e>0&&(this._lastContainerViewportSize={width:t,height:e}),this._hasFixedContainerScrollbars())return{width:i,height:s};let a=this._getContainerOverflowValues(),o=a.x.some(n=>n==="auto"||n==="scroll"),c=a.y.some(n=>n==="auto"||n==="scroll"),l=o&&this.containerElement.scrollWidth>this.containerElement.clientWidth,r=c&&this.containerElement.scrollHeight>this.containerElement.clientHeight;if(l||r){let n=this._getScrollbarSize();r&&(i+=n.width),l&&(s+=n.height)}return{width:i,height:s}}_getContainerOverflowValues(){if(!this.containerElement)return{x:[],y:[]};let t=this.containerElement.style.overflow,e=this.containerElement.style.overflowX,i=this.containerElement.style.overflowY,s="",a="",o="";if(typeof window<"u"&&typeof window.getComputedStyle=="function"){let c=window.getComputedStyle(this.containerElement);s=c.overflow,a=c.overflowX,o=c.overflowY}return{x:[t,e,s,a],y:[t,i,s,o]}}_hasFixedContainerScrollbars(){if(!this.containerElement)return!1;let t=this._getContainerOverflowValues();return[...t.x,...t.y].some(e=>e==="scroll")}_getScrollbarSize(){if(this._scrollbarSizeCache)return{...this._scrollbarSizeCache};if(typeof document>"u"||!document.createElement||!document.body)return{width:0,height:0};let t=document.createElement("div");t.style.position="absolute",t.style.visibility="hidden",t.style.overflow="scroll",t.style.width="100px",t.style.height="100px",t.style.top="-9999px",document.body.appendChild(t);let e=Math.max(0,t.offsetWidth-t.clientWidth),i=Math.max(0,t.offsetHeight-t.clientHeight);return document.body.removeChild(t),this._scrollbarSizeCache={width:e,height:i},{...this._scrollbarSizeCache}}_getScrollSafetyMargin(){return 2}_getScrollableCanvasSize(t,e,i=this._getContainerViewportSize()){if(this._hasFixedContainerScrollbars()){let r=this._getScrollSafetyMargin(),n=Math.max(1,i.width-r),h=Math.max(1,i.height-r);return{width:t>i.width+.5?this._ceilCanvasDimension(t):n,height:e>i.height+.5?this._ceilCanvasDimension(e):h,viewportWidth:i.width,viewportHeight:i.height,hasHorizontal:!0,hasVertical:!0}}let s=this._getScrollbarSize(),a=!1,o=!1,c,l;for(let r=0;r<4;r+=1){c=Math.max(1,i.width-(a?s.width:0)),l=Math.max(1,i.height-(o?s.height:0));let n=e>l+.5,h=t>c+.5;if(n===a&&h===o)break;a=n,o=h}return c=Math.max(1,i.width-(a?s.width:0)),l=Math.max(1,i.height-(o?s.height:0)),{width:o?this._ceilCanvasDimension(t):c,height:a?this._ceilCanvasDimension(e):l,viewportWidth:c,viewportHeight:l,hasHorizontal:o,hasVertical:a}}_calculateCoverCanvasLayout(t,e){let i=this._getContainerViewportSize();if(this._hasFixedContainerScrollbars()){let p=this._getScrollSafetyMargin(),d=Math.max(1,i.width-p),u=Math.max(1,i.height-p),m=Math.min(1,Math.max(d/t,u/e)),f=t*m,y=e*m,M=this._getScrollableCanvasSize(f,y,i);return{scale:m,canvasWidth:M.width,canvasHeight:M.height}}let s=this._getScrollbarSize(),a=!1,o=!1,c=1,l=t,r=e,n,h;for(let p=0;p<4;p+=1){n=Math.max(1,i.width-(a?s.width:0)),h=Math.max(1,i.height-(o?s.height:0)),c=Math.min(1,Math.max(n/t,h/e)),l=t*c,r=e*c;let d=r>h+.5,u=l>n+.5;if(d===a&&u===o)break;a=d,o=u}let g=this._getScrollableCanvasSize(l,r,i);return{scale:c,canvasWidth:g.width,canvasHeight:g.height}}_getStateProperties(){return["maskId","maskName","maskLabel","isCropRect","originalAlpha","originalStroke","originalStrokeWidth","selectable","evented","hasControls","lockRotation","borderColor","cornerColor","cornerSize","transparentCorners","strokeUniform","strokeDashArray"]}_getMaskNormalStyle(t){let e=Number(t&&t.originalStrokeWidth),i=Number(t&&t.originalAlpha),s={stroke:t&&t.originalStroke||"#ccc",strokeWidth:Number.isFinite(e)?e:1};return Number.isFinite(i)&&(s.opacity=i),s}_withNormalizedMaskStyles(t){if(!this.canvas)return t();let e=this.canvas.getObjects().filter(s=>s.maskId),i=[];try{e.forEach(a=>{let o=this._getMaskNormalStyle(a),c={};Object.keys(o).forEach(n=>{a[n]!==o[n]&&(c[n]=o[n])});let l=Object.keys(c);if(!l.length)return;let r={object:a};l.forEach(n=>{r[n]=a[n]}),i.push(r),a.set(c)});let s=t();if(s&&typeof s.then=="function")throw new Error("_withNormalizedMaskStyles callback must be synchronous");return s}finally{i.forEach(s=>{try{let a={};Object.keys(s).forEach(o=>{o!=="object"&&(a[o]=s[o])}),s.object.set(a)}catch(a){}})}}_restoreMaskControls(t){if(!t)return;let e=Number(t.cornerSize);t.set({selectable:t.selectable!==!1,evented:t.evented!==!1,hasControls:t.hasControls!==!1,lockRotation:typeof t.lockRotation=="boolean"?t.lockRotation:!this.options.maskRotatable,borderColor:t.borderColor||"red",cornerColor:t.cornerColor||"black",cornerSize:Number.isFinite(e)?e:8,transparentCorners:t.transparentCorners===!0,strokeUniform:t.strokeUniform!==!1}),typeof t.setCoords=="function"&&t.setCoords()}_serializeEditorMetadata(){let t=Number(this.baseImageScale),e=Number(this.currentScale),i=Number(this.currentRotation),s=Number(this.maskCounter),a=this.canvas?Number(this.canvas.getWidth()):NaN,o=this.canvas?Number(this.canvas.getHeight()):NaN;return{version:1,baseImageScale:Number.isFinite(t)&&t>0?t:1,currentScale:Number.isFinite(e)&&e>0?e:1,currentRotation:Number.isFinite(i)?i:0,maskCounter:Number.isFinite(s)&&s>0?Math.floor(s):0,canvasWidth:Number.isFinite(a)&&a>0?Math.round(a):1,canvasHeight:Number.isFinite(o)&&o>0?Math.round(o):1}}_serializeCanvasState(){return this.canvas?this._withNormalizedMaskStyles(()=>{let t=this.canvas.toJSON(this._getStateProperties());return Array.isArray(t.objects)&&(t.objects=t.objects.filter(e=>!e.isCropRect&&!e.maskLabel)),t.imageEditorMetadata=this._serializeEditorMetadata(),JSON.stringify(t)}):null}_normalizeQuality(t,e=void 0){let i=e??this.options.downsampleQuality,s=i==null?NaN:Number(i),a=Number.isFinite(s)?Math.max(0,Math.min(1,s)):.92;if(t==null)return a;let o=Number(t);return Number.isFinite(o)?Math.max(0,Math.min(1,o)):a}_normalizeImageFormat(t){return{jpeg:"jpeg",jpg:"jpeg","image/jpeg":"jpeg",png:"png","image/png":"png",webp:"webp","image/webp":"webp"}[String(t||"jpeg").toLowerCase()]||"jpeg"}_getClampedCanvasRegion(t,e={}){let i=Math.max(1,Math.round(this.canvas.getWidth())),s=Math.max(1,Math.round(this.canvas.getHeight())),a=Number(t.left)||0,o=Number(t.top)||0,c=Math.max(0,Number(t.width)||0),l=Math.max(0,Number(t.height)||0),n=e.includePartialPixels!==!1?Math.ceil:Math.floor,h=Math.min(i-1,Math.max(0,Math.floor(a))),g=Math.min(s-1,Math.max(0,Math.floor(o))),p=Math.min(i,Math.max(h+1,n(a+c))),d=Math.min(s,Math.max(g+1,n(o+l)));return{sourceX:h,sourceY:g,sourceWidth:Math.max(1,p-h),sourceHeight:Math.max(1,d-g)}}_hasFractionalCanvasEdge(t){let e=Number(t);return Number.isFinite(e)?Math.abs(e-Math.round(e))>.01:!1}_getPartialExportEdges(t){if(!t)return null;let e=Math.abs((Number(this.originalImage&&this.originalImage.angle)||0)%90);return e<.01||Math.abs(e-90)<.01?{left:this._hasFractionalCanvasEdge(t.left),top:this._hasFractionalCanvasEdge(t.top),right:this._hasFractionalCanvasEdge((Number(t.left)||0)+(Number(t.width)||0)),bottom:this._hasFractionalCanvasEdge((Number(t.top)||0)+(Number(t.height)||0))}:null}async _sealPartialTransparentEdges(t,e){if(!e||!Object.values(e).some(Boolean))return t;let i=await this._createImageElement(t),s=Math.max(1,i.naturalWidth||i.width||1),a=Math.max(1,i.naturalHeight||i.height||1),o=document.createElement("canvas");o.width=s,o.height=a;let c=o.getContext("2d");if(!c)throw new Error("2D canvas context is unavailable");c.drawImage(i,0,0,s,a);let l=c.getImageData(0,0,s,a),r=l.data,n=(h,g,p,d)=>{let u=(g*s+h)*4,m=(d*s+p)*4;r[u+3]===0&&r[m+3]>0&&(r[u]=r[m],r[u+1]=r[m+1],r[u+2]=r[m+2],r[u+3]=r[m+3]),r[u+3]>0&&r[u+3]<255&&(r[u+3]=255)};if(e.left&&s>1)for(let h=0;h<a;h+=1)n(0,h,1,h);if(e.right&&s>1)for(let h=0;h<a;h+=1)n(s-1,h,s-2,h);if(e.top&&a>1)for(let h=0;h<s;h+=1)n(h,0,h,1);if(e.bottom&&a>1)for(let h=0;h<s;h+=1)n(h,a-1,h,a-2);return c.putImageData(l,0,0),o.toDataURL("image/png")}async _exportCanvasRegionToDataURL({sourceX:t,sourceY:e,sourceWidth:i,sourceHeight:s,multiplier:a=1,quality:o=.92,format:c="jpeg",sealPartialEdges:l=null}){let r=Math.max(1,Number(a)||1),n=this._normalizeImageFormat(c),h=n==="jpeg"?"png":n,g=this.canvas.toDataURL({format:h,quality:o,multiplier:r,left:t,top:e,width:i,height:s});return g=await this._sealPartialTransparentEdges(g,l),n!=="jpeg"?g:this._convertDataUrlToOpaqueJpeg(g,o)}async _convertDataUrlToOpaqueJpeg(t,e=.92){let i=await this._createImageElement(t),s=Math.max(1,i.naturalWidth||i.width||1),a=Math.max(1,i.naturalHeight||i.height||1),o=document.createElement("canvas");o.width=s,o.height=a;let c=o.getContext("2d");if(!c)throw new Error("2D canvas context is unavailable");return c.fillStyle=this._getJpegBackgroundColor(),c.fillRect(0,0,s,a),c.drawImage(i,0,0,s,a),o.toDataURL("image/jpeg",this._normalizeQuality(e))}_getJpegBackgroundColor(){let t=String(this.options.backgroundColor||"").trim();return!t||this._isTransparentCssColor(t)?"#ffffff":t}_isTransparentCssColor(t){let e=String(t||"").trim().toLowerCase();if(!e||e==="transparent")return!0;let i=e.match(/^#(?:[0-9a-f]{3}([0-9a-f])|[0-9a-f]{6}([0-9a-f]{2}))$/i);if(i){let o=i[1]||i[2];return o==="0"||o==="00"}let s=e.match(/^(?:rgba?|hsla?)\([^)]*\/\s*([^)]+)\)$/i);if(s)return this._isZeroCssAlpha(s[1]);let a=e.match(/^(?:rgba|hsla)\((.*)\)$/i);if(a){let o=a[1].split(",");if(o.length>=4)return this._isZeroCssAlpha(o[o.length-1])}return!1}_isZeroCssAlpha(t){let e=String(t||"").trim();return e?e.endsWith("%")?Number.parseFloat(e)===0:Number(e)===0:!1}_decodeBase64Payload(t){let e=String(t||"");if(typeof atob=="function")return Uint8Array.from(atob(e),i=>i.charCodeAt(0));if(typeof Buffer<"u"&&typeof Buffer.from=="function")return new Uint8Array(Buffer.from(e,"base64"));throw new Error("Base64 decoding is unavailable")}_getObjectTopLeftPoint(t){if(!t)return{x:0,y:0};t.setCoords();let e=t.getBoundingRect(!0,!0);return{x:e.left,y:e.top}}_getObjectCoordinateTopLeftPoint(t){if(!t)return{x:0,y:0};t.setCoords();let e=typeof t.getCoords=="function"?t.getCoords():null;return e&&e.length?e[0]:this._getObjectTopLeftPoint(t)}_getObjectOriginPoint(t,e,i){return t?typeof t.getPointByOrigin=="function"?t.getPointByOrigin(e,i):this._getObjectTopLeftPoint(t):{x:0,y:0}}_translateObjectByCanvasOffset(t,e,i){if(t){if(typeof t.getCenterPoint=="function"&&typeof t.setPositionByOrigin=="function"){let s=t.getCenterPoint(),a=new _.Point(s.x+e,s.y+i);t.setPositionByOrigin(a,"center","center")}else t.set({left:(t.left||0)+e,top:(t.top||0)+i});t.setCoords()}}_setObjectOriginKeepingPosition(t,e,i,s){!t||!s||!t.setPositionByOrigin||(t.set({originX:e,originY:i}),t.setPositionByOrigin(s,e,i),t.setCoords())}_alignObjectBoundingBoxToCanvasTopLeft(t){if(!t)return;t.setCoords();let e=t.getBoundingRect(!0,!0),i=e.left,s=e.top;t.set({left:(t.left||0)-i,top:(t.top||0)-s}),t.setCoords(),this.canvas.renderAll()}_updateCanvasSizeToImageBounds(){if(!this.originalImage)return;this.originalImage.setCoords();let t=this.originalImage.getBoundingRect(!0,!0),e=this._getScrollableCanvasSize(t.width,t.height);this._setCanvasSizeInt(e.width,e.height)}_shouldResizeCanvasToContentBounds(){return!!(this.options.expandCanvasToImage||this.options.coverImageToCanvas||this.options.fitImageToCanvas)}_expandCanvasToFitObjects(t,e=10){if(!(!this.canvas||!Array.isArray(t)||!t.length||!this._shouldResizeCanvasToContentBounds()))try{let i=this.canvas.getWidth(),s=this.canvas.getHeight(),a=i,o=s;t.forEach(h=>{if(!h)return;typeof h.setCoords=="function"&&h.setCoords();let g=h.getBoundingRect(!0,!0);a=Math.max(a,Math.ceil(g.left+g.width+e)),o=Math.max(o,Math.ceil(g.top+g.height+e))});let c=0,l=0;if(this.containerElement){let h=this._getContainerViewportSize(),g=this._getScrollSafetyMargin();c=Math.max(1,h.width-g),l=Math.max(1,h.height-g)}let r=Math.max(i,c,a),n=Math.max(s,l,o);(r!==i||n!==s)&&this._setCanvasSizeInt(r,n)}catch(i){this._reportWarning("expandCanvasToFitObjects: failed to expand canvas",i)}}_expandCanvasToFitObject(t,e=10){this._expandCanvasToFitObjects([t],e)}scaleImage(t,e={}){try{this._assertCanQueueAnimation("scaleImage",e)}catch(i){return Promise.reject(i)}return this.animationQueue.add(()=>this._scaleImageImpl(t,e)).finally(()=>{!this._disposed&&this.canvas&&this._updateUI()})}_getInternalOperationToken(t){return t&&t[N]}_isOwnInternalOperation(t){let e=this._getInternalOperationToken(t);return!!e&&e===this._activeOperationToken}_beginBusyOperation(t){let e=Symbol(t);return this._activeOperationName=t,this._activeOperationToken=e,this._updateUI(),e}_endBusyOperation(t){t&&t===this._activeOperationToken&&(this._activeOperationName=null,this._activeOperationToken=null,this._updateUI())}_withInternalOperationOptions(t,e={}){return{...e,[N]:t}}_assertEditorAvailable(t){if(this._disposed||!this.canvas)throw new Error(`${t} cannot run after the editor has been disposed`)}_isCropModeAllowedOperation(t){return t==="applyCrop"||t==="cancelCrop"}_assertIdleForOperation(t,e={}){this._assertEditorAvailable(t);let i=this._isOwnInternalOperation(e);if(this._cropMode&&!this._isCropModeAllowedOperation(t)&&!i)throw new Error(`${t} cannot run while crop mode is active`);if(this.isAnimating||this.animationQueue&&this.animationQueue.isBusy())throw new Error(`${t} cannot run while an animation is running`);if(this._isLoading&&!i)throw new Error(`${t} cannot run while an image is loading`);if(this._activeOperationToken&&!i)throw new Error(`${t} cannot run while ${this._activeOperationName||"another operation"} is running`)}_assertCanQueueAnimation(t,e={}){this._assertEditorAvailable(t);let i=this._isOwnInternalOperation(e);if(this._cropMode&&!this._isCropModeAllowedOperation(t)&&!i)throw new Error(`${t} cannot run while crop mode is active`);if(this._isLoading&&!i)throw new Error(`${t} cannot run while an image is loading`);if(this._activeOperationToken&&!i)throw new Error(`${t} cannot run while ${this._activeOperationName||"another operation"} is running`)}_canMutateNow(t,e={}){try{return this._assertIdleForOperation(t,e),!0}catch(i){return this._reportError(`${t} blocked`,i),!1}}_rejectActiveAnimations(t){let e=t instanceof Error?t:new Error(String(t||"Animation cancelled"));this._activeAnimationRejectors.forEach(i=>{try{i(e)}catch(s){}}),this._activeAnimationRejectors.clear()}_animateFabricProperty(t,e,i){return new Promise((s,a)=>{if(this._disposed||!this.canvas||!t){a(new Error("Animation cannot start after editor disposal"));return}let o=!1,c=Math.max(0,Number(this.options.animationDuration)||0),l=Math.max(1e3,c+1e3),r,n=h=>{o||(o=!0,clearTimeout(r),this._activeAnimationRejectors.delete(a),h())};this._activeAnimationRejectors.add(a),r=setTimeout(()=>{n(()=>a(new Error(`Animation timed out while changing ${e}`)))},l);try{t.animate(e,i,{duration:c,onChange:()=>{!this._disposed&&this.canvas&&this.canvas.renderAll()},onComplete:()=>n(s)})}catch(h){n(()=>a(h))}})}async _scaleImageImpl(t,e={}){if(!this.originalImage||this._disposed||this.isAnimating)return;let i=e.saveHistory!==!1,s=!1;try{t=Math.max(this.options.minScale,Math.min(this.options.maxScale,t)),this.currentScale=t,this.isAnimating=!0,s=!0,this._updateUI();let a=this.baseImageScale*t,o=this._getObjectTopLeftPoint(this.originalImage);if(this._setObjectOriginKeepingPosition(this.originalImage,"left","top",o),await Promise.all([this._animateFabricProperty(this.originalImage,"scaleX",a),this._animateFabricProperty(this.originalImage,"scaleY",a)]),this._disposed||!this.canvas||!this.originalImage)throw new Error("Editor was disposed during scale animation");this.originalImage.set({scaleX:a,scaleY:a}),this.originalImage.setCoords(),this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds(),this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage),this.canvas.getObjects().forEach(c=>{c.maskId&&this._syncMaskLabel(c)}),this._updateInputs(),i&&this.saveState()}finally{s&&(this.isAnimating=!1,this._updateInputs(),this._updateUI())}}rotateImage(t,e={}){try{this._assertCanQueueAnimation("rotateImage",e)}catch(i){return Promise.reject(i)}return this.animationQueue.add(()=>this._rotateImageImpl(t,e)).finally(()=>{!this._disposed&&this.canvas&&this._updateUI()})}async _rotateImageImpl(t,e={}){if(!this.originalImage||this._disposed||this.isAnimating||isNaN(t))return;let i=e.saveHistory!==!1,s=this.originalImage,a=s.originX||"left",o=s.originY||"top",c=this._getObjectOriginPoint(s,a,o),l=!1,r=!1;try{this.currentRotation=t,this.isAnimating=!0,l=!0,this._updateUI();let n=s.getCenterPoint();if(this._setObjectOriginKeepingPosition(s,"center","center",n),await this._animateFabricProperty(s,"angle",t),this._disposed||!this.canvas||!this.originalImage)throw new Error("Editor was disposed during rotation animation");this.originalImage.set("angle",t),this.originalImage.setCoords(),this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds(),this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage);let h=this._getObjectCoordinateTopLeftPoint(this.originalImage);this._setObjectOriginKeepingPosition(this.originalImage,"left","top",h),this.canvas.getObjects().forEach(g=>{g.maskId&&this._syncMaskLabel(g)}),this._updateInputs(),i&&this.saveState(),r=!0}finally{!r&&!this._disposed&&s&&this._setObjectOriginKeepingPosition(s,a,o,c),l&&(this.isAnimating=!1,this._updateInputs(),this._updateUI())}}resetImageTransform(){if(!this.originalImage)return Promise.resolve();try{this._assertCanQueueAnimation("resetImageTransform")}catch(t){return Promise.reject(t)}return this.animationQueue.add(async()=>{let t=this._lastSnapshot||this._captureCanvasStateOrThrow("resetImageTransform");try{await this._scaleImageImpl(1,{saveHistory:!1}),await this._rotateImageImpl(0,{saveHistory:!1});let e=this._captureCanvasStateOrThrow("resetImageTransform");this._pushStateTransition(t,e)}catch(e){try{await this.loadFromState(t)}catch(i){this._reportError("resetImageTransform rollback failed",i)}throw e}}).finally(()=>{!this._disposed&&this.canvas&&this._updateUI()}).catch(t=>{throw this._reportError("resetImageTransform() failed",t),t})}reset(){return this.resetImageTransform()}loadFromState(t){return!t||!this.canvas||this._disposed?Promise.resolve():((this._cropMode||this._cropRect)&&(this._removeCropRect(),this._restoreCropObjectState(),this._cropMode=!1,this._prevSelectionSetting!==void 0&&this.canvas&&(this.canvas.selection=!!this._prevSelectionSetting),this._prevSelectionSetting=void 0),new Promise((e,i)=>{try{let s=typeof t=="string"?JSON.parse(t):t,a=s&&s.imageEditorMetadata?s.imageEditorMetadata:null,o=Number(a&&a.canvasWidth),c=Number(a&&a.canvasHeight),l=Number.isFinite(o)&&o>0&&Number.isFinite(c)&&c>0;a&&Object.prototype.hasOwnProperty.call(a,"version")&&Number(a.version)!==1&&this._reportWarning(`loadFromState: unsupported editor metadata version ${a.version}`);let r=async()=>{try{if(this._disposed||!this.canvas){i(new Error("Editor was disposed while loading state"));return}if(await this._waitForFabricImagesReady(this.canvas.getObjects()),this._disposed||!this.canvas){i(new Error("Editor was disposed while loading state"));return}this._hideAllMaskLabels();let n=this.canvas.getObjects();if(this.originalImage=n.find(d=>d.type==="image"&&!d.maskId)||null,this.originalImage){this.originalImage.set({originX:"left",originY:"top",selectable:!1,evented:!1,hasControls:!1,hoverCursor:"default"}),this.canvas.sendToBack(this.originalImage);let d=Number(a&&a.baseImageScale),u=Number(a&&a.currentScale),m=Number(a&&a.currentRotation);if(Number.isFinite(d)&&d>0&&(this.baseImageScale=d),Number.isFinite(u)&&u>0)this.currentScale=u;else{let f=Number(this.baseImageScale)||1,y=Number(this.originalImage.scaleX)||f;this.currentScale=y/f}this.currentRotation=Number.isFinite(m)?m:Number(this.originalImage.angle)||0}else this.baseImageScale=1,this.currentScale=1,this.currentRotation=0;l?this._setCanvasSizeInt(o,c):this.originalImage&&this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds();let h=n.filter(d=>d.maskId);h.forEach(d=>{this._restoreMaskControls(d),this._rebindMaskEvents(d),d.set(this._getMaskNormalStyle(d))});let g=Number(a&&a.maskCounter),p=h.reduce((d,u)=>Math.max(d,u.maskId),0);this.maskCounter=Number.isFinite(g)&&g>=p?Math.floor(g):p,this._lastMask=h.length?h[h.length-1]:null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null),this.isImageLoadedToCanvas=!!this.originalImage,this.canvas.renderAll(),this._updateInputs(),this._updateMaskList(),this._updatePlaceholderStatus(),this._lastSnapshot=this._serializeCanvasState(),this._updateUI(),e()}catch(n){this._reportError("loadFromState() failed",n),i(n)}};this.canvas.loadFromJSON(s,()=>{r()})}catch(s){this._reportError("loadFromState() failed",s),i(s)}}))}async _waitForFabricImagesReady(t){let e=(t||[]).filter(i=>i&&i.type==="image");await Promise.all(e.map(i=>this._waitForImageElementReady(typeof i.getElement=="function"?i.getElement():i._element)))}_waitForImageElementReady(t){return!t||(Number(t.naturalWidth)>0||Number(t.width)>0)&&(Number(t.naturalHeight)>0||Number(t.height)>0)?Promise.resolve():t.complete?Promise.reject(new Error("Image could not be loaded while restoring state")):new Promise((i,s)=>{let a=!1,o,c=n=>{a||(a=!0,clearTimeout(o),typeof t.removeEventListener=="function"?(t.removeEventListener("load",l),t.removeEventListener("error",r)):(t.onload=null,t.onerror=null),n())},l=()=>{let n=(Number(t.naturalWidth)>0||Number(t.width)>0)&&(Number(t.naturalHeight)>0||Number(t.height)>0);c(()=>{n?i():s(new Error("Image could not be loaded while restoring state"))})},r=n=>c(()=>s(n instanceof Error?n:new Error("Image could not be loaded while restoring state")));o=setTimeout(()=>{c(()=>s(new Error("Image load timed out while restoring state")))},this._getSafeTimeoutMs(this.options.imageLoadTimeoutMs)),typeof t.addEventListener=="function"?(t.addEventListener("load",l,{once:!0}),t.addEventListener("error",r,{once:!0})):(t.onload=l,t.onerror=r)})}saveState(){if(this.canvas)try{let t=this._captureCanvasStateOrThrow("saveState"),e=this._lastSnapshot||t;if(t===e)return;let i=!1,s=new k(()=>{if(i)return this.loadFromState(t);i=!0},()=>this.loadFromState(e));this.historyManager.execute(s),this._lastSnapshot=t}catch(t){this._reportWarning("saveState: failed to save canvas snapshot",t)}finally{this._updateUI()}}_pushStateTransition(t,e){if(!t||!e){this._reportWarning("History transition skipped because a canvas snapshot is unavailable");return}if(t===e)return;this.historyManager||(this.historyManager=new I(this.maxHistorySize||50));let i=new k(()=>this.loadFromState(e),()=>this.loadFromState(t));this.historyManager.push(i),this._lastSnapshot=e,this._updateUI()}undo(){return this.historyManager.undo().then(()=>{this._updateUI()}).catch(t=>{throw this._reportError("undo failed",t),t})}redo(){return this.historyManager.redo().then(()=>{this._updateUI()}).catch(t=>{throw this._reportError("redo failed",t),t})}_rebindMaskEvents(t){if(!t)return;this._cleanupMaskEvents(t);let e={};Number.isFinite(Number(t.originalAlpha))||(e.originalAlpha=Number.isFinite(Number(t.opacity))?Number(t.opacity):.5),t.originalStroke||(e.originalStroke=t.stroke||"#ccc"),Number.isFinite(Number(t.originalStrokeWidth))||(e.originalStrokeWidth=Number.isFinite(Number(t.strokeWidth))?Number(t.strokeWidth):1),Object.keys(e).length&&t.set(e);let i=()=>{let a=Number(t.originalAlpha);t.set({stroke:"#ff5500",strokeWidth:2,opacity:Math.min((Number.isFinite(a)?a:.5)+.2,1)}),t.canvas&&t.canvas.requestRenderAll()},s=()=>{t.set(this._getMaskNormalStyle(t)),t.canvas&&t.canvas.requestRenderAll()};t.on("mouseover",i),t.on("mouseout",s),t.__imageEditorMaskHandlers={mouseover:i,mouseout:s}}_cleanupMaskEvents(t){if(!(!t||!t.__imageEditorMaskHandlers)){try{typeof t.off=="function"&&(t.off("mouseover",t.__imageEditorMaskHandlers.mouseover),t.off("mouseout",t.__imageEditorMaskHandlers.mouseout))}catch(e){this._reportWarning("Mask event cleanup failed",e)}try{delete t.__imageEditorMaskHandlers}catch(e){this._reportWarning("Mask event metadata cleanup failed",e)}}}createMask(t={}){if(!this.canvas||!this._canMutateNow("createMask"))return null;let e=t.shape||"rect",i={shape:e,width:this.options.defaultMaskWidth,height:this.options.defaultMaskHeight,color:"rgba(0,0,0,0.5)",alpha:.5,gap:5,left:void 0,top:void 0,angle:0,selectable:!0,...t},s=10,a,o,c=d=>{let u=this.canvas?this.canvas.getWidth():0,m=this.canvas?this.canvas.getHeight():0;return d==="height"?m:d==="min"?Math.min(u,m):u},l=(d,u,m="width")=>{if(typeof d=="function")return d(this.canvas,this.options);if(typeof d=="string"&&d.endsWith("%")){let f=Number.parseFloat(d)/100;return Number.isFinite(f)?Math.floor(c(m)*f):u}return d??u};if(i.left===void 0&&this._lastMask){let d=this._lastMask;typeof d.setCoords=="function"&&d.setCoords();let u=typeof d.getBoundingRect=="function"?d.getBoundingRect(!0,!0):{left:d.left||s,top:d.top||s,width:d.width||0};a=Math.round(u.left+u.width+i.gap),o=Math.round(u.top??s)}else a=l(i.left,s,"width"),o=l(i.top,s,"height");i.width=l(i.width,this.options.defaultMaskWidth,"width"),i.height=l(i.height,this.options.defaultMaskHeight,"height"),i.left=a,i.top=o;let r;if(typeof i.fabricGenerator=="function")r=i.fabricGenerator(i,this.canvas,this.options);else switch(e){case"circle":r=new _.Circle({left:a,top:o,radius:l(i.radius,Math.min(i.width,i.height)/2,"min"),fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break;case"ellipse":r=new _.Ellipse({left:a,top:o,rx:l(i.rx,i.width/2,"width"),ry:l(i.ry,i.height/2,"height"),fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break;case"polygon":{let d=i.points||[];Array.isArray(d)&&d.length&&(d=d.map(u=>Array.isArray(u)?{x:Number(u[0]),y:Number(u[1])}:{x:Number(u.x),y:Number(u.y)})),r=new _.Polygon(d,{left:a,top:o,fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break}default:r=new _.Rect({left:a,top:o,width:l(i.width,this.options.defaultMaskWidth,"width"),height:l(i.height,this.options.defaultMaskHeight,"height"),fill:i.color,opacity:i.alpha,angle:i.angle,rx:i.rx,ry:i.ry,...i.styles})}if(!r||typeof r.set!="function"||typeof r.setCoords!="function")return this._reportWarning("fabricGenerator returned an invalid Fabric object"),null;let n=i.styles||{},h=d=>Object.prototype.hasOwnProperty.call(n,d),g={selectable:i.selectable!==!1,hasControls:"hasControls"in i?i.hasControls:!0,lockRotation:!this.options.maskRotatable,borderColor:"borderColor"in i?i.borderColor:"red",cornerColor:"cornerColor"in i?i.cornerColor:"black",cornerSize:"cornerSize"in i?i.cornerSize:8,transparentCorners:"transparentCorners"in i?i.transparentCorners:!1,stroke:h("stroke")?n.stroke:"#ccc",strokeWidth:h("strokeWidth")?n.strokeWidth:1,opacity:h("opacity")?n.opacity:i.alpha,strokeUniform:"strokeUniform"in i?i.strokeUniform:h("strokeUniform")?n.strokeUniform:!0};h("strokeDashArray")&&(g.strokeDashArray=n.strokeDashArray),r.set(g),r.setCoords(),r.set({originalAlpha:Number.isFinite(Number(r.opacity))?Number(r.opacity):i.alpha,originalStroke:r.stroke||"#ccc",originalStrokeWidth:Number.isFinite(Number(r.strokeWidth))?Number(r.strokeWidth):1}),this._rebindMaskEvents(r),this._expandCanvasToFitObject(r),this._lastMaskInitialLeft=a,this._lastMaskInitialTop=o,this._lastMaskInitialWidth=l(i.width,this.options.defaultMaskWidth,"width");let p=++this.maskCounter;return r.set({maskId:p,maskName:`${this.options.maskName}${p}`}),this._lastMask=r,this.canvas.add(r),this.canvas.bringToFront(r),i.selectable&&this.canvas.setActiveObject(r),this._handleSelectionChanged([r]),this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),this.saveState(),typeof i.onCreate=="function"&&i.onCreate(r,this.canvas),r}addMask(t={}){return this.createMask(t)}removeSelectedMask(){if(!this.canvas||!this._canMutateNow("removeSelectedMask"))return;let t=this.canvas.getActiveObject(),e=this._getModifiedMasks(t);if(!e.length)return;this.canvas.discardActiveObject(),e.forEach(s=>{this._removeLabelForMask(s),this._cleanupMaskEvents(s),this.canvas.remove(s)});let i=this.canvas.getObjects().filter(s=>s.maskId);this._lastMask=i.length?i[i.length-1]:null,this._lastMask||(this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null),this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),this.saveState()}removeAllMasks(t={}){if(!this.canvas||!this._canMutateNow("removeAllMasks",t))return;let e=t.saveHistory!==!1,i=this.canvas.getObjects().filter(s=>s.maskId);i.forEach(s=>this._removeLabelForMask(s)),i.forEach(s=>{this._cleanupMaskEvents(s),this.canvas.remove(s)}),this.canvas.discardActiveObject(),this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null,this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),e&&this.saveState()}_removeLabelForMask(t){if(!(!t||!this.canvas)&&t.__label){try{this.canvas.getObjects().includes(t.__label)&&this.canvas.remove(t.__label)}catch(e){}try{delete t.__label}catch(e){}}}_captureMaskLabelBackups(t){if(!this.canvas)return[];let e=new Set(this.canvas.getObjects());return(t||[]).map(i=>{let s=i&&i.__label?i.__label:null;return{mask:i,label:s,hadLabel:!!s,labelInCanvas:!!s&&e.has(s),visible:s?s.visible:void 0}})}_restoreMaskLabelBackups(t){if(!this.canvas||!Array.isArray(t))return;let e=new Set(this.canvas.getObjects());t.forEach(i=>{if(!(!i||!i.mask))try{if(!i.hadLabel){i.mask.__label&&this._removeLabelForMask(i.mask);return}if(i.mask.__label=i.label,!i.label)return;i.labelInCanvas&&!e.has(i.label)&&(this.canvas.add(i.label),e.add(i.label)),i.visible!==void 0&&i.label.set({visible:i.visible}),i.labelInCanvas&&this.canvas.bringToFront(i.label),this._syncMaskLabel(i.mask)}catch(s){this._reportWarning("restoreMaskLabelBackups: failed to restore mask label",s)}})}_captureActiveObjectBackup(){if(!this.canvas)return null;let t=this.canvas.getActiveObject();if(!t)return null;let e=typeof t.getObjects=="function"?t.getObjects():[t];return{activeObject:t,selectedObjects:e}}_restoreActiveObjectBackup(t){if(!this.canvas||!t||!t.activeObject)return;let e=this.canvas.getObjects(),i=Array.isArray(t.selectedObjects)?t.selectedObjects:[];if(i.length?i.every(a=>e.includes(a)):e.includes(t.activeObject))try{this.canvas.setActiveObject(t.activeObject)}catch(a){}}_captureMaskExportBackups(t){return(t||[]).map(e=>({object:e,visible:e.visible,opacity:e.opacity,fill:e.fill,strokeWidth:e.strokeWidth,stroke:e.stroke,selectable:e.selectable,lockRotation:e.lockRotation}))}_restoreMaskExportBackups(t){(t||[]).forEach(e=>{try{e.object.set({visible:e.visible,opacity:e.opacity,fill:e.fill,strokeWidth:e.strokeWidth,stroke:e.stroke,selectable:e.selectable,lockRotation:e.lockRotation}),e.object.setCoords()}catch(i){}})}_getMaskCreationIndex(t){let e=Number(t&&t.maskId);if(Number.isFinite(e)&&e>0)return Math.floor(e)-1;let i=this.canvas?this.canvas.getObjects().filter(s=>s.maskId):[];return Math.max(0,i.indexOf(t))}_createLabelForMask(t){if(!t||!this.options.maskLabelOnSelect)return;this._removeLabelForMask(t);let e=null;if(this.options.label&&typeof this.options.label.create=="function"&&(e=this.options.label.create(t,_),(!e||typeof e.set!="function")&&(this._reportWarning("label.create() returned an invalid Fabric object; using the default label"),e=null)),!e){let i=t.maskName,s={left:0,top:0,fontSize:12,fill:"#fff",backgroundColor:"rgba(0,0,0,0.7)",selectable:!1,evented:!1,padding:2,originX:"left",originY:"top"};this.options.label&&(typeof this.options.label.getText=="function"&&(i=this.options.label.getText(t,this._getMaskCreationIndex(t))),this.options.label.textOptions&&Object.assign(s,this.options.label.textOptions)),e=new _.Text(i,s)}e.maskLabel=!0,t.__label=e,this.canvas.add(e),this.canvas.bringToFront(e),this._syncMaskLabel(t)}_hideAllMaskLabels(){if(!this.canvas)return;let t=this.canvas.getObjects(),e=new Set(t);t.filter(s=>s.maskLabel).forEach(s=>{try{e.has(s)&&this.canvas.remove(s)}catch(a){}}),t.forEach(s=>{if(s.maskId&&s.__label)try{delete s.__label}catch(a){}})}_syncMaskLabel(t){if(!t||!this.options.maskLabelOnSelect||!t.__label)return;typeof t.setCoords=="function"&&t.setCoords();let e=t.getBoundingRect?t.getBoundingRect(!0,!0):null;if(!e)return;let i={x:e.left,y:e.top},s=t.getCenterPoint(),a=s.x-i.x,o=s.y-i.y,c=Math.sqrt(a*a+o*o)||1,l=a/c,r=o/c,n=Math.max(0,this.options.maskLabelOffset??3),h=i.x+l*n,g=i.y+r*n;t.__label.set({left:Math.round(h),top:Math.round(g),angle:t.angle||0,originX:"left",originY:"top",visible:!0}),t.__label.setCoords(),typeof this.canvas.requestRenderAll=="function"?this.canvas.requestRenderAll():this.canvas.renderAll()}_showLabelForMask(t){t&&this.options.maskLabelOnSelect&&(t.__label||this._createLabelForMask(t),t.__label.set({visible:!0}),this._syncMaskLabel(t))}_handleSelectionChanged(t){let e=(t||[]).find(s=>s.maskId);this.canvas.getObjects().filter(s=>s.maskId).forEach(s=>{if(s!==e){if(s.__label){try{this.canvas.remove(s.__label)}catch(o){}delete s.__label}let a=Number(s.originalStrokeWidth);s.set({stroke:s.originalStroke||"#ccc",strokeWidth:Number.isFinite(a)?a:1})}else s.set({stroke:"#ff0000",strokeWidth:1})}),e&&this._showLabelForMask(e),this._updateMaskListSelection(e),this.canvas.renderAll(),this._updateUI()}_updateMaskList(){let t=this._getElement("maskList");if(!t)return;t.innerHTML="",this.canvas.getObjects().filter(i=>i.maskId).forEach(i=>{let s=document.createElement("li");s.className="list-group-item mask-item",s.textContent=i.maskName,s.dataset.maskId=String(i.maskId),t.appendChild(s)})}_handleMaskListClick(t){if(!this.canvas)return;let e=t.target&&t.target.closest?t.target.closest(".mask-item"):null;if(!e||!e.dataset)return;let i=Number(e.dataset.maskId),s=this.canvas.getObjects().find(a=>Number(a.maskId)===i);s&&(this.canvas.setActiveObject(s),this._handleSelectionChanged([s]))}_updateMaskListSelection(t){let e=this._getElement("maskList");if(!e)return;e.querySelectorAll(".mask-item").forEach(s=>{let a=!!t&&Number(s.dataset.maskId)===Number(t.maskId);s.classList.toggle("active",a),s.classList.toggle("selected",a)})}async mergeMasks(){if(!this.originalImage||(this._assertIdleForOperation("mergeMasks"),!this.canvas.getObjects().filter(s=>s.maskId).length))return;let e=this._serializeCanvasState(),i=this._beginBusyOperation("mergeMasks");this.canvas.discardActiveObject(),this.canvas.renderAll();try{let s=await this.exportImageBase64(this._withInternalOperationOptions(i,{exportImageArea:!0,multiplier:this.options.exportMultiplier,fileType:"png"}));if(this.removeAllMasks(this._withInternalOperationOptions(i,{saveHistory:!1})),this.canvas.getObjects().some(o=>o.maskId))throw new Error("Masks could not be removed during merge");await this.loadImage(s,this._withInternalOperationOptions(i,{preserveScroll:!0,resetMaskCounter:!1}));let a=this._serializeCanvasState();this._pushStateTransition(e,a)}catch(s){this._reportError("merge error",s);try{await this.loadFromState(e)}catch(a){this._reportError("mergeMasks rollback failed",a)}throw s}finally{this._endBusyOperation(i)}}async merge(){return this.mergeMasks()}downloadImage(t=this.options.defaultDownloadFileName){if(!this.originalImage||!this._canMutateNow("downloadImage"))return;let e=this.options.exportImageAreaByDefault;this.exportImageBase64({exportImageArea:e,multiplier:this.options.exportMultiplier}).then(i=>{let s=document.createElement("a");s.download=t,s.href=i,document.body.appendChild(s),s.click(),document.body.removeChild(s)}).catch(i=>this._reportError("download error",i))}async exportImageBase64(t={}){if(!this.originalImage)throw new Error("No image loaded");this._assertIdleForOperation("exportImageBase64",t);let e=typeof t.exportImageArea=="boolean"?t.exportImageArea:this.options.exportImageAreaByDefault,i=t.multiplier||this.options.exportMultiplier||1,s=this._normalizeQuality(t.quality??this.options.downsampleQuality),a=this._normalizeImageFormat(t.fileType||t.format);if(!e){let n=this.canvas.getObjects().filter(m=>m.maskId||m.maskLabel),h=this.canvas.getObjects().filter(m=>m.maskId),g=n.map(m=>({object:m,visible:m.visible})),p=this._captureMaskExportBackups(h),d=this._captureMaskLabelBackups(h),u=this._captureActiveObjectBackup();try{n.forEach(y=>{y.set({visible:!1})}),this.canvas.discardActiveObject(),this.canvas.renderAll(),this.originalImage.setCoords();let m=this.originalImage.getBoundingRect(!0,!0),f=this._getClampedCanvasRegion(m);return await this._exportCanvasRegionToDataURL({...f,multiplier:i,quality:s,format:a,sealPartialEdges:this._getPartialExportEdges(m)})}finally{g.forEach(m=>{try{m.object.set({visible:m.visible})}catch(f){}}),this._restoreMaskExportBackups(p),this._restoreMaskLabelBackups(d),this._restoreActiveObjectBackup(u),this.canvas.renderAll()}}let o=this.canvas.getObjects().filter(n=>n.maskId),c=this._captureMaskExportBackups(o),l=this._captureMaskLabelBackups(o),r=this._captureActiveObjectBackup();try{o.forEach(g=>this._removeLabelForMask(g)),this.canvas.discardActiveObject(),this.canvas.renderAll(),o.forEach(g=>{g.set({opacity:1,fill:"#000000",strokeWidth:0,stroke:null,selectable:!1}),g.setCoords()}),this.canvas.renderAll(),this.originalImage.setCoords();let n=this.originalImage.getBoundingRect(!0,!0),h=this._getClampedCanvasRegion(n);return await this._exportCanvasRegionToDataURL({...h,multiplier:i,quality:s,format:a,sealPartialEdges:this._getPartialExportEdges(n)})}finally{this._restoreMaskExportBackups(c),this._restoreMaskLabelBackups(l),this._restoreActiveObjectBackup(r),this.canvas.renderAll()}}async getImageBase64(t={}){return this.exportImageBase64(t)}async exportImageFile(t={}){if(!this.originalImage)throw new Error("No image loaded");this._assertIdleForOperation("exportImageFile");let{mergeMask:e=!0,fileType:i="jpeg",quality:s=this.options.downsampleQuality??.92,multiplier:a=this.options.exportMultiplier??1,fileName:o=this.options.defaultDownloadFileName??"exported_image.jpg"}=t,c=this._normalizeImageFormat(i),l=this._normalizeQuality(s),r;e?r=await this.exportImageBase64({exportImageArea:!0,multiplier:a,quality:l,fileType:c}):r=await this.exportImageBase64({exportImageArea:!1,multiplier:a,quality:l,fileType:c});let n=r;n.startsWith(`data:image/${c}`)||(n=await new Promise((p,d)=>{let u=new window.Image;u.crossOrigin="Anonymous",u.onload=()=>{try{let m=document.createElement("canvas");m.width=u.width,m.height=u.height;let f=m.getContext("2d");if(!f)throw new Error("Unable to create 2D canvas context for export conversion");f.drawImage(u,0,0);let y=m.toDataURL(`image/${c}`,l);p(y)}catch(m){d(m)}},u.onerror=d,u.src=r}));let h=this._decodeBase64Payload(n.split(",")[1]),g=`image/${c}`;return new File([h],o,{type:g})}_clearMaskPlacementMemory(){this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null}async _restoreStateAfterCropFailure(t,e,i){if(this._reportError(e,i),this._cropRect&&this.canvas&&this._removeCropRect(),this._cropRect=null,this._cropMode=!1,this.canvas&&this._prevSelectionSetting!==void 0&&(this.canvas.selection=!!this._prevSelectionSetting),this._prevSelectionSetting=void 0,t)try{await this.loadFromState(t)}catch(s){this._reportError("applyCrop: rollback failed",s)}this._updateUI(),this.canvas&&this.canvas.renderAll()}_restoreCropObjectState(){Array.isArray(this._cropPrevEvented)&&this._cropPrevEvented.forEach(t=>{try{t.object.set({evented:t.evented,selectable:t.selectable,visible:t.visible})}catch(e){}}),this._cropPrevEvented=null}_removeCropRect(){this._cropHandlers&&this._cropHandlers.length&&this._cropHandlers.forEach(t=>{(t.handlers||[]).forEach(e=>{try{t.target&&typeof t.target.off=="function"&&t.target.off(e.eventName,e.handler)}catch(i){this._reportWarning("Crop handler cleanup failed",i)}})});try{this.canvas&&this._cropRect&&this.canvas.remove(this._cropRect)}catch(t){}this._cropRect=null,this._cropHandlers=[]}enterCropMode(){if(!this.canvas||!this.originalImage||this._cropMode||!this._canMutateNow("enterCropMode")||!this.isImageLoaded())return;this._removeCropRect(),this._cropMode=!0,this._prevSelectionSetting=this.canvas.selection,this.canvas.selection=!1,this.canvas.discardActiveObject(),this.originalImage.setCoords();let t=this.originalImage.getBoundingRect(!0,!0),e=this.options.crop&&this.options.crop.padding?this.options.crop.padding:10,i=Math.max(0,Math.floor(t.left+e)),s=Math.max(0,Math.floor(t.top+e)),a=Math.max(1,Math.floor(t.width-e*2)),o=Math.max(1,Math.floor(t.height-e*2)),c=Math.max(1,Number(this.options.crop.minWidth)||50),l=Math.max(1,Number(this.options.crop.minHeight)||50),r=Math.min(c,a),n=Math.min(l,o),h=r,g=n,p=new _.Rect({left:i,top:s,width:h,height:g,fill:"rgba(0,0,0,0.12)",stroke:"#00aaff",strokeDashArray:[6,4],strokeWidth:1,strokeUniform:!0,selectable:!0,hasRotatingPoint:!!(this.options.crop&&this.options.crop.allowRotationOfCropRect),lockRotation:!(this.options.crop&&this.options.crop.allowRotationOfCropRect),cornerSize:8,objectCaching:!1,originX:"left",originY:"top",lockScalingFlip:!0});this.canvas.add(p),p.isCropRect=!0,this.canvas.bringToFront(p),this.canvas.setActiveObject(p),this._cropRect=p,this._cropPrevEvented=[];let d=!!(this.options.crop&&this.options.crop.hideMasksDuringCrop);this.canvas.getObjects().forEach(m=>{if(m!==p){this._cropPrevEvented.push({object:m,evented:m.evented,selectable:m.selectable,visible:m.visible});try{let f={evented:!1,selectable:!1};d&&(m.maskId||m.maskLabel)&&(f.visible=!1),m.set(f)}catch(f){}}});let u=()=>{try{let m=Math.max(1,Number(p.width)||1),f=Math.max(1,Number(p.height)||1),y=Math.min(a/m,Math.max(r/m,Number(p.scaleX)||1)),M=Math.min(o/f,Math.max(n/f,Number(p.scaleY)||1));p.set({scaleX:y,scaleY:M}),p.setCoords();let v=p.getBoundingRect(!0,!0),x=Number(t.left)||0,O=Number(t.top)||0,L=x+(Number(t.width)||0),T=O+(Number(t.height)||0),w=0,E=0;v.left<x?w=x-v.left:v.left+v.width>L&&(w=L-(v.left+v.width)),v.top<O?E=O-v.top:v.top+v.height>T&&(E=T-(v.top+v.height)),(w||E)&&(p.set({left:(Number(p.left)||0)+w,top:(Number(p.top)||0)+E}),p.setCoords()),this.canvas.requestRenderAll()}catch(m){}};p.on("modified",u),p.on("moving",u),p.on("scaling",u),this._cropHandlers.push({target:p,handlers:[{eventName:"modified",handler:u},{eventName:"moving",handler:u},{eventName:"scaling",handler:u}]}),this._updateUI(),this.canvas.renderAll()}cancelCrop(){!this.canvas||!this._cropMode||(this._removeCropRect(),this._restoreCropObjectState(),this._cropMode=!1,this.canvas.selection=!!this._prevSelectionSetting,this._prevSelectionSetting=void 0,this.canvas.discardActiveObject(),this._updateUI(),this.canvas.renderAll())}async applyCrop(){if(!this.canvas||!this._cropMode||!this._cropRect)return;this._assertIdleForOperation("applyCrop"),this._cropRect.setCoords();let t=this._cropRect.getBoundingRect(!0,!0),e=this._getClampedCanvasRegion(t,{includePartialPixels:!1}),i=!!(this.options.crop&&this.options.crop.preserveMasksAfterCrop);this._restoreCropObjectState();let s;try{s=this._serializeCanvasState()}catch(l){this._reportError("applyCrop: failed to capture rollback state",l),s=null}if(!s){this.cancelCrop();return}let a=[];try{let l=this.canvas.getObjects().filter(r=>r.maskId);l&&l.length&&(l.forEach(r=>{r.setCoords();let n=r.getBoundingRect(!0,!0),h=n.left<e.sourceX+e.sourceWidth&&n.left+n.width>e.sourceX&&n.top<e.sourceY+e.sourceHeight&&n.top+n.height>e.sourceY;this._removeLabelForMask(r),this._cleanupMaskEvents(r),this.canvas.remove(r),i&&h&&(this._translateObjectByCanvasOffset(r,-e.sourceX,-e.sourceY),r.set({visible:!0}),a.push(r))}),this._clearMaskPlacementMemory(),this.canvas.discardActiveObject(),this.canvas.renderAll())}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: failed to prepare masks",l);return}this._removeCropRect(),this._cropMode=!1,this.canvas.selection=!!this._prevSelectionSetting,this._prevSelectionSetting=void 0;let o;try{o=await this._exportCanvasRegionToDataURL({...e,multiplier:1,quality:this._normalizeQuality(this.options.downsampleQuality),format:"jpeg"})}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: failed to create cropped image",l);return}try{await this.loadImage(o,{resetMaskCounter:!1}),a.length&&(a.forEach(l=>{this._rebindMaskEvents(l),this.canvas.add(l),this.canvas.bringToFront(l)}),this._lastMask=a[a.length-1],this.maskCounter=a.reduce((l,r)=>Math.max(l,r.maskId||0),this.maskCounter),this._updateMaskList(),this.canvas.renderAll())}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: loadImage(croppedBase64) failed",l);return}let c;try{c=a.length?this._serializeCanvasState():this._lastSnapshot}catch(l){this._reportWarning("applyCrop: failed to serialize after state",l),c=null}try{this._pushStateTransition(s,c)}catch(l){this._reportWarning("applyCrop: failed to push history command",l)}this._updateUI(),this.canvas.renderAll()}_updateInputs(){let t=this._getElement("scalePercentageInput");t&&(t.value=Math.round(this.currentScale*100))}_updateUI(){if(!this.canvas)return;let t=!!this.originalImage,i=(t?this.canvas.getObjects().filter(h=>h.maskId):[]).length>0,s=this.canvas.getActiveObject(),a=s&&s.maskId,o=this.currentScale===1&&this.currentRotation===0,c=this.historyManager?.canUndo(),l=this.historyManager?.canRedo(),r=!!this._cropMode,n=this.isBusy();if(r){for(let h of Object.keys(this.elements||{}))this._getElement(h)&&(h==="applyCropButton"||h==="cancelCropButton"||h==="applyCropBtn"||h==="cancelCropBtn"?this._setDisabled(h,!1):this._setDisabled(h,!0));return}this._setDisabled("zoomInButton",!t||n||this.currentScale>=this.options.maxScale),this._setDisabled("zoomOutButton",!t||n||this.currentScale<=this.options.minScale),this._setDisabled("rotateLeftButton",!t||n),this._setDisabled("rotateRightButton",!t||n),this._setDisabled("createMaskButton",!t||n),this._setDisabled("removeSelectedMaskButton",!a||n),this._setDisabled("removeAllMasksButton",!i||n),this._setDisabled("mergeMasksButton",!t||!i||n),this._setDisabled("downloadImageButton",!t||n),this._setDisabled("resetImageTransformButton",!t||o||n),this._setDisabled("undoButton",!t||n||!c),this._setDisabled("redoButton",!t||n||!l),this._setDisabled("enterCropModeButton",!t||n),this._setDisabled("applyCropButton",!0),this._setDisabled("cancelCropButton",!0),this._setDisabled("scalePercentageInput",!t||n),this._setDisabled("rotateLeftDegreesInput",!t||n),this._setDisabled("rotateRightDegreesInput",!t||n),this._setDisabled("maskList",!t||n),this._setDisabled("imageInput",n),this._setDisabled("uploadArea",n)}_setDisabled(t,e){let i=this._getElement(t);if(i){if("disabled"in i){i.disabled=!!e;return}this._elementOriginalPointerEvents||(this._elementOriginalPointerEvents=new Map),this._elementOriginalPointerEvents.has(t)||this._elementOriginalPointerEvents.set(t,i.style.pointerEvents||""),e?(i.setAttribute("aria-disabled","true"),i.style.pointerEvents="none"):(i.removeAttribute("aria-disabled"),i.style.pointerEvents=this._elementOriginalPointerEvents.get(t)??"")}}_isElementDisabled(t){return t?"disabled"in t?!!t.disabled:t.getAttribute("aria-disabled")==="true":!1}_updatePlaceholderStatus(){this.options.showPlaceholder&&this._setPlaceholderVisible(!this.originalImage)}_setPlaceholderVisible(t){this.placeholderElement&&this._setElementVisible(this.placeholderElement,t);let e=this._getCanvasVisibilityElement();e&&e!==this.placeholderElement&&this._setElementVisible(e,!t)}_getCanvasVisibilityElement(){let t=this.canvas&&this.canvas.wrapperEl?this.canvas.wrapperEl:null;return this.containerElement&&this.placeholderElement&&(this.containerElement===this.placeholderElement||this.containerElement.contains(this.placeholderElement))?t||this.canvasElement:this.containerElement||t||this.canvasElement}_setElementVisible(t,e){t&&(this._rememberElementVisibility(t),t.hidden=!e,t.setAttribute("aria-hidden",e?"false":"true"),t.classList&&t.classList.toggle("d-none",!e))}_rememberElementVisibility(t){!t||this._visibilityStateByElement.has(t)||this._visibilityStateByElement.set(t,this._captureElementVisibility(t))}_captureElementVisibility(t){return t?{hidden:t.hidden,ariaHidden:t.getAttribute("aria-hidden"),className:t.className}:null}_restoreElementVisibility(t,e){!t||!e||(t.hidden=!!e.hidden,e.ariaHidden===null?t.removeAttribute("aria-hidden"):t.setAttribute("aria-hidden",e.ariaHidden),t.className=e.className||"")}dispose(){this._disposed=!0,this._rejectActiveAnimations(new Error("Editor disposed during animation")),this.animationQueue&&this.animationQueue.cancelAll(new Error("Editor disposed")),this._isLoading=!1,this._activeOperationName=null,this._activeOperationToken=null;try{for(let[t,e]of Object.entries(this._handlersByElementKey||{})){let i=this._getElement(t);i&&e.forEach(s=>{try{i.removeEventListener(s.eventName,s.handler)}catch(a){}})}}catch(t){}if(this._cropRect&&this._removeCropRect(),this.containerElement&&this._containerOriginalOverflow)try{this._restoreContainerOverflowState()}catch(t){}if(this._visibilityStateByElement)try{[this.placeholderElement,this._getCanvasVisibilityElement()].forEach(t=>{let e=t?this._visibilityStateByElement.get(t):null;e&&this._restoreElementVisibility(t,e)})}catch(t){}if(this.canvasElement&&this._canvasElementOriginalStyle)try{this.canvasElement.style.display=this._canvasElementOriginalStyle.display,this.canvasElement.style.width=this._canvasElementOriginalStyle.width,this.canvasElement.style.height=this._canvasElementOriginalStyle.height,this.canvasElement.style.maxWidth=this._canvasElementOriginalStyle.maxWidth}catch(t){}if(this.canvas){try{this.canvas.getObjects().forEach(t=>{t&&t.maskId&&this._cleanupMaskEvents(t)})}catch(t){}try{this.canvas.dispose()}catch(t){}this.canvas=null,this.canvasElement=null,this.isImageLoadedToCanvas=!1}this._handlersByElementKey={},this._elementCache={},this._elementOriginalPointerEvents=new Map,this._clearMaskPlacementMemory(),this.originalImage=null,this.baseImageScale=1,this.currentScale=1,this.currentRotation=0,this.isAnimating=!1,this._isLoading=!1,this._cropMode=!1,this._cropRect=null,this._cropHandlers=[],this._cropPrevEvented=null,this._prevSelectionSetting=void 0,this._lastContainerViewportSize=null,this._initialized=!1}},C=class{constructor(){this.animationTasks=[],this.isRunning=!1,this.currentTask=null,this._generation=0}async add(t){return new Promise((e,i)=>{this.animationTasks.push({animationFn:t,resolve:e,reject:i,isSettled:!1}),this.isRunning||this._drainQueue()})}isBusy(){return this.isRunning||this.animationTasks.length>0}cancelAll(t=new Error("Animation queue cancelled")){this._generation+=1;let e=t instanceof Error?t:new Error(String(t));[...this.currentTask?[this.currentTask]:[],...this.animationTasks.splice(0)].forEach(s=>{!s||s.isSettled||(s.isSettled=!0,s.reject(e))}),this.isRunning=!1,this.currentTask=null}async _drainQueue(){if(this.isRunning)return;let t=this._generation;this.isRunning=!0;try{for(;this.animationTasks.length>0&&t===this._generation;){let e=this.animationTasks.shift();this.currentTask=e;try{let i=await e.animationFn();t===this._generation&&!e.isSettled&&(e.isSettled=!0,e.resolve(i))}catch(i){t===this._generation&&!e.isSettled&&(e.isSettled=!0,e.reject(i))}finally{this.currentTask===e&&(this.currentTask=null)}}}finally{t===this._generation&&(this.isRunning=!1,this.currentTask=null)}}},k=class{constructor(t,e){this.execute=t,this.undo=e}},I=class{constructor(t=50){this.history=[],this.currentIndex=-1,this.maxSize=t,this.pending=Promise.resolve()}enqueue(t){let e=this.pending.then(()=>Promise.resolve().then(t));return this.pending=e.catch(()=>{}),e}execute(t){let e=t.execute();return e&&typeof e.then=="function"?this.enqueue(()=>Promise.resolve(e).then(()=>{this.push(t)})):(this.push(t),e)}push(t){this.currentIndex<this.history.length-1&&(this.history=this.history.slice(0,this.currentIndex+1)),this.history.push(t),this.history.length>this.maxSize&&this.history.shift(),this.currentIndex=this.history.length-1}canUndo(){return this.currentIndex>=0}canRedo(){return this.currentIndex<this.history.length-1}undo(){return this.enqueue(async()=>{if(this.currentIndex>=0){let t=this.currentIndex;await this.history[t].undo(),this.currentIndex=t-1}})}redo(){return this.enqueue(async()=>{if(this.currentIndex<this.history.length-1){let t=this.currentIndex+1;await this.history[t].execute(),this.currentIndex=t}})}};var F=B;var z=S&&(S.fabric||S.default||S);A(z);var U=F;export{F as ImageEditor,U as default};
9
9
  //# sourceMappingURL=image-editor.esm.min.mjs.map