@bensitu/image-editor 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/image-editor.esm.js +946 -542
- package/dist/image-editor.esm.js.map +2 -2
- package/dist/image-editor.esm.min.js +3 -3
- package/dist/image-editor.esm.min.js.map +3 -3
- package/dist/image-editor.esm.min.mjs +3 -3
- package/dist/image-editor.esm.min.mjs.map +3 -3
- package/dist/image-editor.esm.mjs +946 -542
- package/dist/image-editor.esm.mjs.map +2 -2
- package/dist/image-editor.js +946 -542
- package/dist/image-editor.js.map +2 -2
- package/dist/image-editor.min.js +2 -2
- package/dist/image-editor.min.js.map +3 -3
- package/image-editor.d.ts +2 -0
- package/package.json +9 -4
- package/src/image-editor.js +899 -358
package/dist/image-editor.min.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
(()=>{/**
|
|
2
2
|
* @file image-editor.js
|
|
3
3
|
* @module image-editor
|
|
4
|
-
* @version 1.
|
|
4
|
+
* @version 1.4.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 v=null;function O(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:null}function W(){let _=O();return _&&_.fabric?_.fabric:null}function B(_){return v=_||W(),v}function L(){return v||B(),v}var E=class{constructor(t={}){let i={getText:l=>l.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"}},e={minWidth:100,minHeight:100,padding:10,hideMasksDuringCrop:!0,preserveMasksAfterCrop:!1,allowRotationOfCropRect:!1},s=t.label||{},o=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,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:{...i,...s,textOptions:{...i.textOptions,...s.textOptions||{}}},crop:{...e,...o}},this._fabricLoaded=!!L(),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.elements={},this.isImageLoadedToCanvas=!1,this.maxHistorySize=50,this._handlersByElementKey={},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=void 0,this._scrollbarSizeCache=null,this.onImageLoaded=typeof t.onImageLoaded=="function"?t.onImageLoaded:null,this.animationQueue=new w,this.historyManager=new C(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;let i={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={...i,...t},this._initCanvas(),this._bindEvents(),this._updateInputs(),this._updateMaskList(),this._updateUI(),this.options.initialImageBase64?this.loadImage(this.options.initialImageBase64):this._updatePlaceholderStatus()}_reportError(t,i=null){let e=this.options&&this.options.onError;if(typeof e=="function")try{e(i,t)}catch{}}_reportWarning(t,i=null){let e=this.options&&this.options.onWarning;if(typeof e=="function")try{e(i,t)}catch{}}_initCanvas(){let t=document.getElementById(this.elements.canvas);if(!t)throw new Error("Canvas is not found: "+this.elements.canvas);if(this.canvasElement=t,this.elements.canvasContainer){let s=document.getElementById(this.elements.canvasContainer);this.containerElement=s||t.parentElement}else this.containerElement=t.parentElement;this.placeholderElement=document.getElementById(this.elements.imgPlaceholder)||null;let i=this.options.canvasWidth,e=this.options.canvasHeight;if(this.containerElement){let s=Math.floor(this.containerElement.clientWidth),o=Math.floor(this.containerElement.clientHeight);s>0&&o>0&&(i=s,e=o)}this.canvas=new v.Canvas(t,{width:i,height:e,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"}_handleObjectModified(t){let i=this._getModifiedMasks(t);i.length&&(i.forEach(e=>{typeof e.setCoords=="function"&&e.setCoords(),this._syncMaskLabel(e)}),this._expandCanvasToFitObjects(i),this.saveState())}_getModifiedMasks(t){if(!t)return[];if(t.maskId)return[t];let i=typeof t.getObjects=="function"?t.getObjects():[];return Array.isArray(i)?i.filter(e=>e&&e.maskId):[]}_syncContainerOverflow(t={}){if(!this.containerElement||!this.containerElement.style)return;this._containerOriginalOverflow===void 0&&(this._containerOriginalOverflow=this.containerElement.style.overflow||"");let i=t.preserveScroll===!0;this.options.coverImageToCanvas?(this.containerElement.style.overflow="scroll",i||(this.containerElement.scrollLeft=0,this.containerElement.scrollTop=0)):this.options.fitImageToCanvas?(this.containerElement.style.overflow="auto",i||(this.containerElement.scrollLeft=0,this.containerElement.scrollTop=0)):this.containerElement.style.overflow=this._containerOriginalOverflow}_bindEvents(){this._bindIfExists("uploadArea","click",()=>{let t=document.getElementById(this.elements.uploadArea);this._isElementDisabled(t)||document.getElementById(this.elements.imageInput)?.click()}),this._bindIfExists("imageInput","change",t=>{let i=t.target.files&&t.target.files[0];i&&this._loadImageFile(i)}),this._bindIfExists("zoomInBtn","click",()=>this.scaleImage(this.currentScale+this.options.scaleStep)),this._bindIfExists("zoomOutBtn","click",()=>this.scaleImage(this.currentScale-this.options.scaleStep)),this._bindIfExists("resetBtn","click",()=>{this.resetImageTransform()}),this._bindIfExists("addMaskBtn","click",()=>this.createMask()),this._bindIfExists("removeMaskBtn","click",()=>this.removeSelectedMask()),this._bindIfExists("removeAllMasksBtn","click",()=>this.removeAllMasks()),this._bindIfExists("mergeBtn","click",()=>this.mergeMasks()),this._bindIfExists("downloadBtn","click",()=>this.downloadImage()),this._bindIfExists("undoBtn","click",()=>this.undo()),this._bindIfExists("redoBtn","click",()=>this.redo()),this._bindIfExists("rotateLeftBtn","click",()=>{let t=document.getElementById(this.elements.rotationLeftInput),i=this.options.rotationStep;if(t){let e=parseFloat(t.value);isNaN(e)||(i=e)}this.rotateImage(this.currentRotation-i)}),this._bindIfExists("rotateRightBtn","click",()=>{let t=document.getElementById(this.elements.rotationRightInput),i=this.options.rotationStep;if(t){let e=parseFloat(t.value);isNaN(e)||(i=e)}this.rotateImage(this.currentRotation+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())}_bindIfExists(t,i,e){let s=document.getElementById(this.elements[t]);s&&(s.addEventListener(i,e),this._handlersByElementKey=this._handlersByElementKey||{},this._handlersByElementKey[t]||(this._handlersByElementKey[t]=[]),this._handlersByElementKey[t].push({eventName:i,handler:e}))}_loadImageFile(t){if(!t||!t.type.startsWith("image/"))return;let i=new FileReader;i.onload=e=>this.loadImage(e.target.result),i.onerror=e=>{this._reportError("Image file could not be read",e)},i.readAsDataURL(t)}_warnOnImageLayoutOptionConflict(){let t=[["fitImageToCanvas",this.options.fitImageToCanvas],["coverImageToCanvas",this.options.coverImageToCanvas],["expandCanvasToImage",this.options.expandCanvasToImage]].filter(([,i])=>!!i).map(([i])=>i);t.length<=1||this._reportWarning(`Only one image layout mode should be enabled. Active modes: ${t.join(", ")}.`)}async loadImage(t,i={}){if(!this._fabricLoaded||!this.canvas||!t||typeof t!="string"||!t.startsWith("data:image/"))return;this._warnOnImageLayoutOptionConflict(),this._setPlaceholderVisible(!1),this._syncContainerOverflow({preserveScroll:i.preserveScroll===!0});let e=await this._createImageElement(t),s=t;if(this.options.downsampleOnLoad&&(e.naturalWidth>this.options.downsampleMaxWidth||e.naturalHeight>this.options.downsampleMaxHeight)){let l=Math.min(this.options.downsampleMaxWidth/e.naturalWidth,this.options.downsampleMaxHeight/e.naturalHeight),r=Math.round(e.naturalWidth*l),a=Math.round(e.naturalHeight*l);s=this._resampleImageToDataURL(e,r,a,this.options.downsampleQuality)}return new Promise((o,l)=>{v.Image.fromURL(s,r=>{try{if(!r)throw new Error("Image could not be loaded");this.canvas.discardActiveObject(),this._hideAllMaskLabels(),this.canvas.clear(),this.canvas.setBackgroundColor(this.options.backgroundColor,this.canvas.renderAll.bind(this.canvas)),r.set({originX:"left",originY:"top",selectable:!1,evented:!1});let a=r.width,n=r.height,h=this._getContainerViewportSize(),d=h.width,u=h.height;if(this.options.fitImageToCanvas){let c=Math.max(1,d-1),m=Math.max(1,u-1);this._setCanvasSizeInt(c,m);let f=Math.min(c/a,m/n,1);r.set({left:0,top:0}),r.scale(f),this.baseImageScale=r.scaleX||1}else if(this.options.coverImageToCanvas){let c=this._calculateCoverCanvasLayout(a,n);this._setCanvasSizeInt(c.canvasWidth,c.canvasHeight),r.set({left:0,top:0}),r.scale(c.scale),this.baseImageScale=r.scaleX||1}else if(this.options.expandCanvasToImage){let c=Math.max(d,Math.floor(a)),m=Math.max(u,Math.floor(n));this._setCanvasSizeInt(c,m),r.set({left:0,top:0}),r.scale(1),this.baseImageScale=1}else{let c=Math.max(this.options.canvasWidth,d),m=Math.max(this.options.canvasHeight,u);this._setCanvasSizeInt(c,m);let f=Math.min(c/a,m/n,1);r.set({left:0,top:0}),r.scale(f),this.baseImageScale=r.scaleX||1}this.originalImage=r,this.canvas.add(r),this.canvas.sendToBack(r),this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null,this.maskCounter=0,this.currentScale=1,this.currentRotation=0,this._updateInputs(),this._updateMaskList(),this.isImageLoadedToCanvas=!0,this._updateUI(),this.canvas.renderAll();try{this._lastSnapshot=this._serializeCanvasState()}catch(c){this._reportWarning("loadImage: failed to capture initial canvas snapshot",c)}typeof this.onImageLoaded=="function"&&this.onImageLoaded(),o()}catch(a){l(a)}},{crossOrigin:"anonymous"})})}isImageLoaded(){let t=L();return!!(this.originalImage&&t&&this.originalImage instanceof t.Image&&this.originalImage.width>0&&this.originalImage.height>0)}_createImageElement(t,i=this.options.imageLoadTimeoutMs){return new Promise((e,s)=>{let o=new Image,l=!1,r=Number.isFinite(Number(i))&&Number(i)>0?Number(i):3e4,a,n=h=>{l||(l=!0,clearTimeout(a),o.onload=null,o.onerror=null,h())};a=setTimeout(()=>{n(()=>s(new Error("Image load timed out")));try{o.src=""}catch(h){}},r),o.onload=()=>n(()=>e(o)),o.onerror=h=>n(()=>s(h)),o.src=t})}_resampleImageToDataURL(t,i,e,s=.92){let o=document.createElement("canvas");o.width=i,o.height=e;let l=o.getContext("2d");if(!l)throw new Error("2D canvas context is unavailable");return l.drawImage(t,0,0,t.naturalWidth,t.naturalHeight,0,0,i,e),o.toDataURL("image/jpeg",s)}_setCanvasSizeInt(t,i){let e=Math.max(1,Math.round(Number(t)||1)),s=Math.max(1,Math.round(Number(i)||1));this.canvas.setWidth(e),this.canvas.setHeight(s),typeof this.canvas.calcOffset=="function"&&this.canvas.calcOffset(),this.canvasElement&&(this.canvasElement.style.width=e+"px",this.canvasElement.style.height=s+"px",this.canvasElement.style.maxWidth="none")}_ceilCanvasDimension(t){let i=Number(t)||0,e=Math.round(i);return Math.abs(i-e)<.01?e:Math.ceil(i)}_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))};if(this._hasFixedContainerScrollbars())return{width:Math.max(1,Math.floor(this.containerElement.clientWidth||this.options.canvasWidth||1)),height:Math.max(1,Math.floor(this.containerElement.clientHeight||this.options.canvasHeight||1))};let t=Math.max(1,Math.floor(this.containerElement.clientWidth||this.options.canvasWidth||1)),i=Math.max(1,Math.floor(this.containerElement.clientHeight||this.options.canvasHeight||1));return{width:t,height:i}}_hasFixedContainerScrollbars(){if(!this.containerElement)return!1;let t=this.containerElement.style.overflow,i=this.containerElement.style.overflowX,e=this.containerElement.style.overflowY,s="",o="",l="";if(typeof window<"u"&&typeof window.getComputedStyle=="function"){let r=window.getComputedStyle(this.containerElement);s=r.overflow,o=r.overflowX,l=r.overflowY}return[t,i,e,s,o,l].some(r=>r==="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 i=Math.max(0,t.offsetWidth-t.clientWidth),e=Math.max(0,t.offsetHeight-t.clientHeight);return document.body.removeChild(t),this._scrollbarSizeCache={width:i,height:e},{...this._scrollbarSizeCache}}_getScrollSafetyMargin(){return 2}_getScrollableCanvasSize(t,i,e=this._getContainerViewportSize()){if(this._hasFixedContainerScrollbars()){let n=this._getScrollSafetyMargin(),h=Math.max(1,e.width-n),d=Math.max(1,e.height-n);return{width:t>e.width+.5?this._ceilCanvasDimension(t):h,height:i>e.height+.5?this._ceilCanvasDimension(i):d,viewportWidth:e.width,viewportHeight:e.height,hasHorizontal:!0,hasVertical:!0}}let s=this._getScrollbarSize(),o=!1,l=!1,r=e.width,a=e.height;for(let n=0;n<4;n+=1){r=Math.max(1,e.width-(o?s.width:0)),a=Math.max(1,e.height-(l?s.height:0));let h=i>a+.5,d=t>r+.5;if(h===o&&d===l)break;o=h,l=d}return r=Math.max(1,e.width-(o?s.width:0)),a=Math.max(1,e.height-(l?s.height:0)),{width:l?this._ceilCanvasDimension(t):r,height:o?this._ceilCanvasDimension(i):a,viewportWidth:r,viewportHeight:a,hasHorizontal:l,hasVertical:o}}_calculateCoverCanvasLayout(t,i){let e=this._getContainerViewportSize();if(this._hasFixedContainerScrollbars()){let c=this._getScrollSafetyMargin(),m=Math.max(1,e.width-c),f=Math.max(1,e.height-c),g=Math.min(1,Math.max(m/t,f/i)),p=t*g,y=i*g,b=this._getScrollableCanvasSize(p,y,e);return{scale:g,canvasWidth:b.width,canvasHeight:b.height}}let s=this._getScrollbarSize(),o=!1,l=!1,r=1,a=t,n=i,h=e.width,d=e.height;for(let c=0;c<4;c+=1){h=Math.max(1,e.width-(o?s.width:0)),d=Math.max(1,e.height-(l?s.height:0)),r=Math.min(1,Math.max(h/t,d/i)),a=t*r,n=i*r;let m=n>d+.5,f=a>h+.5;if(m===o&&f===l)break;o=m,l=f}let u=this._getScrollableCanvasSize(a,n,e);return{scale:r,canvasWidth:u.width,canvasHeight:u.height}}_getStateProperties(){return["maskId","maskName","maskLabel","isCropRect","originalAlpha","originalStroke","originalStrokeWidth","selectable","evented","hasControls","lockRotation","borderColor","cornerColor","cornerSize","transparentCorners","strokeUniform","strokeDashArray"]}_getMaskNormalStyle(t){let i=Number(t&&t.originalStrokeWidth),e=Number(t&&t.originalAlpha),s={stroke:t&&t.originalStroke||"#ccc",strokeWidth:Number.isFinite(i)?i:1};return Number.isFinite(e)&&(s.opacity=e),s}_withNormalizedMaskStyles(t){if(!this.canvas)return t();let i=this.canvas.getObjects().filter(s=>s.maskId),e=i.map(s=>({object:s,stroke:s.stroke,strokeWidth:s.strokeWidth,opacity:s.opacity}));try{return i.forEach(s=>{s.set(this._getMaskNormalStyle(s))}),t()}finally{e.forEach(s=>{try{s.object.set({stroke:s.stroke,strokeWidth:s.strokeWidth,opacity:s.opacity})}catch(o){}})}}_restoreMaskControls(t){if(!t)return;let i=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(i)?i:8,transparentCorners:t.transparentCorners===!0,strokeUniform:t.strokeUniform!==!1}),typeof t.setCoords=="function"&&t.setCoords()}_serializeEditorMetadata(){let t=Number(this.baseImageScale),i=Number(this.currentScale),e=Number(this.currentRotation),s=Number(this.maskCounter);return{version:1,baseImageScale:Number.isFinite(t)&&t>0?t:1,currentScale:Number.isFinite(i)&&i>0?i:1,currentRotation:Number.isFinite(e)?e: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(i=>!i.isCropRect&&!i.maskLabel)),t.imageEditorMetadata=this._serializeEditorMetadata(),JSON.stringify(t)}):null}_normalizeQuality(t){let i=Number(t);return Number.isFinite(i)?Math.max(0,Math.min(1,i)):this.options.downsampleQuality??.92}_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,i={}){let e=Math.max(1,Math.round(this.canvas.getWidth())),s=Math.max(1,Math.round(this.canvas.getHeight())),o=Number(t.left)||0,l=Number(t.top)||0,r=Math.max(0,Number(t.width)||0),a=Math.max(0,Number(t.height)||0),h=i.includePartialPixels!==!1?Math.ceil:Math.floor,d=Math.min(e-1,Math.max(0,Math.floor(o))),u=Math.min(s-1,Math.max(0,Math.floor(l))),c=Math.min(e,Math.max(d+1,h(o+r))),m=Math.min(s,Math.max(u+1,h(l+a)));return{sourceX:d,sourceY:u,sourceWidth:Math.max(1,c-d),sourceHeight:Math.max(1,m-u)}}async _cropDataUrl(t,i,e,s,o,l,r="jpeg",a=.92){return new Promise((n,h)=>{let d=new Image,u=!1,c=Number(this.options.imageLoadTimeoutMs),m=Number.isFinite(c)&&c>0?c:3e4,f,g=p=>{u||(u=!0,clearTimeout(f),d.onload=null,d.onerror=null,p())};f=setTimeout(()=>{g(()=>h(new Error("Image crop load timed out")));try{d.src=""}catch(p){}},m),d.onload=()=>{try{let p=Math.max(1,Number(l)||1),y=Math.round(i*p),b=Math.round(e*p),S=Math.max(1,Math.round(s*p)),x=Math.max(1,Math.round(o*p)),M=document.createElement("canvas");M.width=S,M.height=x;let A=M.getContext("2d");if(!A)throw new Error("2D canvas context is unavailable");A.drawImage(d,y,b,S,x,0,0,S,x),g(()=>n(M.toDataURL(`image/${r}`,a)))}catch(p){g(()=>h(p))}},d.onerror=p=>g(()=>h(p)),d.src=t})}async _exportCanvasRegionToDataURL({sourceX:t,sourceY:i,sourceWidth:e,sourceHeight:s,multiplier:o=1,quality:l=.92,format:r="jpeg"}){let a=Math.max(1,Number(o)||1),n=this.canvas.toDataURL({format:r,quality:l,multiplier:a});return this._cropDataUrl(n,t,i,e,s,a,r,l)}_getObjectTopLeftPoint(t){if(!t)return{x:0,y:0};t.setCoords();let i=typeof t.getCoords=="function"?t.getCoords():null;if(i&&i.length)return i[0];let e=t.getBoundingRect(!0,!0);return{x:e.left,y:e.top}}_setObjectOriginKeepingPosition(t,i,e,s){!t||!s||!t.setPositionByOrigin||(t.set({originX:i,originY:e}),t.setPositionByOrigin(s,i,e),t.setCoords())}_alignObjectBoundingBoxToCanvasTopLeft(t){if(!t)return;t.setCoords();let i=t.getBoundingRect(!0,!0),e=i.left,s=i.top;t.set({left:(t.left||0)-e,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),i=this._getScrollableCanvasSize(t.width,t.height);this._setCanvasSizeInt(i.width,i.height)}_shouldResizeCanvasToContentBounds(){return!!(this.options.expandCanvasToImage||this.options.coverImageToCanvas||this.options.fitImageToCanvas)}_expandCanvasToFitObjects(t,i=10){if(!(!this.canvas||!Array.isArray(t)||!t.length||!this._shouldResizeCanvasToContentBounds()))try{let e=this.canvas.getWidth(),s=this.canvas.getHeight();t.forEach(n=>{if(!n)return;typeof n.setCoords=="function"&&n.setCoords();let h=n.getBoundingRect(!0,!0);e=Math.max(e,Math.ceil(h.left+h.width+i)),s=Math.max(s,Math.ceil(h.top+h.height+i))});let o=this.containerElement?Math.floor(this.containerElement.clientWidth||0):0,l=this.containerElement?Math.floor(this.containerElement.clientHeight||0):0,r=Math.max(this.canvas.getWidth(),o,e),a=Math.max(this.canvas.getHeight(),l,s);(r!==this.canvas.getWidth()||a!==this.canvas.getHeight())&&this._setCanvasSizeInt(r,a)}catch(e){this._reportWarning("expandCanvasToFitObjects: failed to expand canvas",e)}}_expandCanvasToFitObject(t,i=10){this._expandCanvasToFitObjects([t],i)}scaleImage(t,i={}){return this.animationQueue.add(()=>this._scaleImageImpl(t,i))}_scaleImageImpl(t,i={}){if(!this.originalImage||this.isAnimating)return Promise.resolve();let e=i.saveHistory!==!1;t=Math.max(this.options.minScale,Math.min(this.options.maxScale,t)),this.currentScale=t,this.isAnimating=!0,this._updateUI();let s=this.baseImageScale*t,o=this._getObjectTopLeftPoint(this.originalImage);this._setObjectOriginKeepingPosition(this.originalImage,"left","top",o);let l=new Promise(a=>{this.originalImage.animate("scaleX",s,{duration:this.options.animationDuration,onChange:this.canvas.renderAll.bind(this.canvas),onComplete:a})}),r=new Promise(a=>{this.originalImage.animate("scaleY",s,{duration:this.options.animationDuration,onChange:this.canvas.renderAll.bind(this.canvas),onComplete:a})});return Promise.all([l,r]).then(()=>{this.originalImage.set({scaleX:s,scaleY:s}),this.originalImage.setCoords(),this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds(),this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage),this.canvas.getObjects().forEach(a=>{a.maskId&&this._syncMaskLabel(a)}),this.isAnimating=!1,this._updateInputs(),this._updateUI(),e&&this.saveState()}).catch(()=>{this.isAnimating=!1,this._updateUI()})}rotateImage(t,i={}){return this.animationQueue.add(()=>this._rotateImageImpl(t,i))}_rotateImageImpl(t,i={}){if(!this.originalImage||this.isAnimating||isNaN(t))return Promise.resolve();let e=i.saveHistory!==!1;this.currentRotation=t,this.isAnimating=!0,this._updateUI();let s=this.originalImage.getCenterPoint();return this._setObjectOriginKeepingPosition(this.originalImage,"center","center",s),new Promise(l=>{this.originalImage.animate("angle",t,{duration:this.options.animationDuration,onChange:this.canvas.renderAll.bind(this.canvas),onComplete:l})}).then(()=>{this.originalImage.set("angle",t),this.originalImage.setCoords(),this._shouldResizeCanvasToContentBounds()&&this._updateCanvasSizeToImageBounds(),this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage);let l=this._getObjectTopLeftPoint(this.originalImage);this._setObjectOriginKeepingPosition(this.originalImage,"left","top",l),this.canvas.getObjects().forEach(r=>{r.maskId&&this._syncMaskLabel(r)}),this.isAnimating=!1,this._updateInputs(),this._updateUI(),e&&this.saveState()}).catch(()=>{this.isAnimating=!1,this._updateUI()})}resetImageTransform(){return this.originalImage?this.animationQueue.add(async()=>{let t=this._lastSnapshot||this._serializeCanvasState();await this._scaleImageImpl(1,{saveHistory:!1}),await this._rotateImageImpl(0,{saveHistory:!1});let i=this._serializeCanvasState();this._pushStateTransition(t,i)}).catch(t=>{this._reportError("resetImageTransform() failed",t)}):Promise.resolve()}reset(){return this.resetImageTransform()}loadFromState(t){return!t||!this.canvas?Promise.resolve():new Promise(i=>{try{let e=typeof t=="string"?JSON.parse(t):t,s=e&&e.imageEditorMetadata?e.imageEditorMetadata:null;this.canvas.loadFromJSON(e,()=>{try{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(s&&s.baseImageScale),h=Number(s&&s.currentScale),d=Number(s&&s.currentRotation);if(Number.isFinite(n)&&n>0&&(this.baseImageScale=n),Number.isFinite(h)&&h>0)this.currentScale=h;else{let u=Number(this.baseImageScale)||1,c=Number(this.originalImage.scaleX)||u;this.currentScale=c/u}this.currentRotation=Number.isFinite(d)?d:Number(this.originalImage.angle)||0}else this.baseImageScale=1,this.currentScale=1,this.currentRotation=0;let l=o.filter(n=>n.maskId);l.forEach(n=>{this._restoreMaskControls(n),this._rebindMaskEvents(n),n.set(this._getMaskNormalStyle(n))});let r=Number(s&&s.maskCounter),a=l.reduce((n,h)=>Math.max(n,h.maskId),0);this.maskCounter=Number.isFinite(r)&&r>=a?Math.floor(r):a,this._lastMask=l.length?l[l.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()}catch(o){this._reportError("loadFromState() failed",o)}finally{i()}})}catch(e){this._reportError("loadFromState() failed",e),i()}})}saveState(){if(!this.canvas)return;let t=this.canvas.getActiveObject();try{let i=this._serializeCanvasState(),e=this._lastSnapshot||i;if(i===e)return;let s=!1,o=new I(()=>{if(s)return this.loadFromState(i);s=!0},()=>this.loadFromState(e));this.historyManager.execute(o),this._lastSnapshot=i}catch(i){this._reportWarning("saveState: failed to save canvas snapshot",i)}finally{t&&t.maskId&&!t.__label&&this.canvas.getObjects().includes(t)&&this._handleSelectionChanged([t]),this._updateUI()}}_pushStateTransition(t,i){if(!t||!i||t===i)return;this.historyManager||(this.historyManager=new C(this.maxHistorySize||50));let e=new I(()=>this.loadFromState(i),()=>this.loadFromState(t));this.historyManager.push(e),this._lastSnapshot=i,this._updateUI()}undo(){return this.historyManager.undo().then(()=>{this._updateUI()}).catch(t=>{this._reportError("undo failed",t)})}redo(){return this.historyManager.redo().then(()=>{this._updateUI()}).catch(t=>{this._reportError("redo failed",t)})}_rebindMaskEvents(t){if(!t)return;if(t.__imageEditorMaskHandlers)try{t.off("mouseover",t.__imageEditorMaskHandlers.mouseover),t.off("mouseout",t.__imageEditorMaskHandlers.mouseout)}catch(r){}let i={};Number.isFinite(Number(t.originalAlpha))||(i.originalAlpha=Number.isFinite(Number(t.opacity))?Number(t.opacity):.5),t.originalStroke||(i.originalStroke=t.stroke||"#ccc"),Number.isFinite(Number(t.originalStrokeWidth))||(i.originalStrokeWidth=Number.isFinite(Number(t.strokeWidth))?Number(t.strokeWidth):1),Object.keys(i).length&&t.set(i);let e={stroke:t.originalStroke||"#ccc",strokeWidth:t.originalStrokeWidth,opacity:t.originalAlpha},s={stroke:"#ff5500",strokeWidth:2,opacity:Math.min(t.originalAlpha+.2,1)},o=()=>{t.set(s),t.canvas&&t.canvas.requestRenderAll()},l=()=>{t.set(e),t.canvas&&t.canvas.requestRenderAll()};t.on("mouseover",o),t.on("mouseout",l),t.__imageEditorMaskHandlers={mouseover:o,mouseout:l}}createMask(t={}){if(!this.canvas)return null;let i=t.shape||"rect",e={shape:i,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,o=s,l=s,r=(c,m)=>{if(typeof c=="function")return c(this.canvas,this.options);if(typeof c=="string"&&c.endsWith("%")){let f=parseFloat(c)/100;return Math.floor((this.canvas?this.canvas.getWidth():0)*f)}return c??m};if(e.left===void 0&&this._lastMask){let c=this._lastMask,m=c.left;c.getScaledWidth?m+=c.getScaledWidth():c.width&&(m+=c.width*(c.scaleX??1)),o=Math.round(m+e.gap),l=c.top??s}else o=r(e.left,s),l=r(e.top,s);e.width=r(e.width,this.options.defaultMaskWidth),e.height=r(e.height,this.options.defaultMaskHeight),e.left=o,e.top=l;let a;if(typeof e.fabricGenerator=="function")a=e.fabricGenerator(e,this.canvas,this.options);else switch(i){case"circle":a=new v.Circle({left:o,top:l,radius:r(e.radius,Math.min(e.width,e.height)/2),fill:e.color,opacity:e.alpha,angle:e.angle,...e.styles});break;case"ellipse":a=new v.Ellipse({left:o,top:l,rx:r(e.rx,e.width/2),ry:r(e.ry,e.height/2),fill:e.color,opacity:e.alpha,angle:e.angle,...e.styles});break;case"polygon":{let c=e.points||[];Array.isArray(c)&&c.length&&(c=c.map(m=>Array.isArray(m)?{x:Number(m[0]),y:Number(m[1])}:{x:Number(m.x),y:Number(m.y)})),a=new v.Polygon(c,{left:o,top:l,fill:e.color,opacity:e.alpha,angle:e.angle,...e.styles});break}case"rect":default:a=new v.Rect({left:o,top:l,width:r(e.width,this.options.defaultMaskWidth),height:r(e.height,this.options.defaultMaskHeight),fill:e.color,opacity:e.alpha,angle:e.angle,rx:e.rx,ry:e.ry,...e.styles})}let n=e.styles||{},h=c=>Object.prototype.hasOwnProperty.call(n,c),d={selectable:e.selectable!==!1,hasControls:"hasControls"in e?e.hasControls:!0,lockRotation:!this.options.maskRotatable,borderColor:"borderColor"in e?e.borderColor:"red",cornerColor:"cornerColor"in e?e.cornerColor:"black",cornerSize:"cornerSize"in e?e.cornerSize:8,transparentCorners:"transparentCorners"in e?e.transparentCorners:!1,stroke:h("stroke")?n.stroke:"#ccc",strokeWidth:h("strokeWidth")?n.strokeWidth:1,opacity:h("opacity")?n.opacity:e.alpha,strokeUniform:"strokeUniform"in e?e.strokeUniform:h("strokeUniform")?n.strokeUniform:!0};h("strokeDashArray")&&(d.strokeDashArray=n.strokeDashArray),a.set(d),a.setCoords(),a.set({originalAlpha:Number.isFinite(Number(a.opacity))?Number(a.opacity):e.alpha,originalStroke:a.stroke||"#ccc",originalStrokeWidth:Number.isFinite(Number(a.strokeWidth))?Number(a.strokeWidth):1}),this._rebindMaskEvents(a),this._expandCanvasToFitObject(a),this._lastMaskInitialLeft=o,this._lastMaskInitialTop=l,this._lastMaskInitialWidth=r(e.width,this.options.defaultMaskWidth);let u=++this.maskCounter;return a.set({maskId:u,maskName:`${this.options.maskName}${u}`}),this._lastMask=a,this.canvas.add(a),this.canvas.bringToFront(a),e.selectable&&this.canvas.setActiveObject(a),this._handleSelectionChanged([a]),this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),this.saveState(),typeof e.onCreate=="function"&&e.onCreate(a,this.canvas),a}addMask(t={}){return this.createMask(t)}removeSelectedMask(){let t=this.canvas.getActiveObject(),i=this._getModifiedMasks(t);if(!i.length)return;this.canvas.discardActiveObject(),i.forEach(s=>{this._removeLabelForMask(s),this.canvas.remove(s)});let e=this.canvas.getObjects().filter(s=>s.maskId);this._lastMask=e.length?e[e.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={}){let i=t.saveHistory!==!1,e=this.canvas.getObjects().filter(s=>s.maskId);e.forEach(s=>this._removeLabelForMask(s)),e.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(),i&&this.saveState()}_removeLabelForMask(t){if(!(!t||!this.canvas)&&t.__label){try{this.canvas.getObjects().includes(t.__label)&&this.canvas.remove(t.__label)}catch(i){}try{delete t.__label}catch(i){}}}_getMaskCreationIndex(t){let i=Number(t&&t.maskId);if(Number.isFinite(i)&&i>0)return Math.floor(i)-1;let e=this.canvas?this.canvas.getObjects().filter(s=>s.maskId):[];return Math.max(0,e.indexOf(t))}_createLabelForMask(t){if(!t||!this.options.maskLabelOnSelect)return;this._removeLabelForMask(t);let i=null;if(this.options.label&&typeof this.options.label.create=="function"&&(i=this.options.label.create(t,v)),!i){let e=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"&&(e=this.options.label.getText(t,this._getMaskCreationIndex(t))),this.options.label.textOptions&&Object.assign(s,this.options.label.textOptions)),i=new v.Text(e,s)}i.maskLabel=!0,t.__label=i,this.canvas.add(i),this.canvas.bringToFront(i),this._syncMaskLabel(t)}_hideAllMaskLabels(){if(!this.canvas)return;let t=this.canvas.getObjects();t.filter(e=>e.maskLabel).forEach(e=>{try{t.includes(e)&&this.canvas.remove(e)}catch(s){}}),t.forEach(e=>{if(e.maskId&&e.__label)try{delete e.__label}catch(s){}})}_syncMaskLabel(t){if(!t||!this.options.maskLabelOnSelect||!t.__label)return;let i=t.getCoords?t.getCoords():null;if(!i||i.length<4)return;let e=i[0],s=t.getCenterPoint(),o=s.x-e.x,l=s.y-e.y,r=Math.sqrt(o*o+l*l)||1,a=o/r,n=l/r,h=Math.max(0,this.options.maskLabelOffset??3),d=e.x+a*h,u=e.y+n*h;t.__label.set({left:Math.round(d),top:Math.round(u),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 i=(t||[]).find(s=>s.maskId);this.canvas.getObjects().filter(s=>s.maskId).forEach(s=>{if(s!==i){if(s.__label){try{this.canvas.remove(s.__label)}catch(l){}delete s.__label}let o=Number(s.originalStrokeWidth);s.set({stroke:s.originalStroke||"#ccc",strokeWidth:Number.isFinite(o)?o:1})}else s.set({stroke:"#ff0000",strokeWidth:1})}),i&&this._showLabelForMask(i),this._updateMaskListSelection(i),this.canvas.renderAll(),this._updateUI()}_updateMaskList(){let t=document.getElementById(this.elements.maskList);if(!t)return;t.innerHTML="",this.canvas.getObjects().filter(e=>e.maskId).forEach(e=>{let s=document.createElement("li");s.className="list-group-item mask-item",s.textContent=e.maskName,s.onclick=()=>{this.canvas.setActiveObject(e),this._handleSelectionChanged([e])},t.appendChild(s)})}_updateMaskListSelection(t){let i=document.getElementById(this.elements.maskList);if(!i)return;i.querySelectorAll(".mask-item").forEach(s=>{let o=!!t&&s.textContent===t.maskName;s.classList.toggle("active",o)})}async mergeMasks(){if(!(!this.originalImage||!this.canvas.getObjects().filter(i=>i.maskId).length)){this.canvas.discardActiveObject(),this.canvas.renderAll();try{let i=this._serializeCanvasState(),e=await this.exportImageBase64({exportImageArea:!0,multiplier:this.options.exportMultiplier});this.removeAllMasks({saveHistory:!1}),await this.loadImage(e,{preserveScroll:!0});let s=this._serializeCanvasState();this._pushStateTransition(i,s)}catch(i){this._reportError("merge error",i)}}}async merge(){return this.mergeMasks()}downloadImage(t=this.options.defaultDownloadFileName){if(!this.originalImage)return;let i=this.options.exportImageAreaByDefault;this.exportImageBase64({exportImageArea:i,multiplier:this.options.exportMultiplier}).then(e=>{let s=document.createElement("a");s.download=t,s.href=e,document.body.appendChild(s),s.click(),document.body.removeChild(s)}).catch(e=>this._reportError("download error",e))}async exportImageBase64(t={}){if(!this.originalImage)throw new Error("No image loaded");let i=typeof t.exportImageArea=="boolean"?t.exportImageArea:this.options.exportImageAreaByDefault,e=t.multiplier||this.options.exportMultiplier||1,s=this._normalizeQuality(t.quality??this.options.downsampleQuality),o=this._normalizeImageFormat(t.fileType||t.format);if(!i){let n=this.canvas.getObjects().filter(d=>d.maskId||d.maskLabel),h=n.map(d=>({object:d,visible:d.visible}));try{n.forEach(c=>{c.set({visible:!1})}),this.canvas.discardActiveObject(),this.canvas.renderAll(),this.originalImage.setCoords();let d=this.originalImage.getBoundingRect(!0,!0),u=this._getClampedCanvasRegion(d,{includePartialPixels:!1});return await this._exportCanvasRegionToDataURL({...u,multiplier:e,quality:s,format:o})}finally{h.forEach(d=>{try{d.object.set({visible:d.visible})}catch(u){}}),this.canvas.renderAll()}}let l=this.canvas.getObjects().filter(n=>n.maskId),r=l.map(n=>({object:n,opacity:n.opacity,fill:n.fill,strokeWidth:n.strokeWidth,stroke:n.stroke,selectable:n.selectable,lockRotation:n.lockRotation})),a;try{l.forEach(d=>this._removeLabelForMask(d)),this.canvas.discardActiveObject(),this.canvas.renderAll(),l.forEach(d=>{d.set({opacity:1,fill:"#000000",strokeWidth:0,stroke:null,selectable:!1}),d.setCoords()}),this.canvas.renderAll(),this.originalImage.setCoords();let n=this.originalImage.getBoundingRect(!0,!0),h=this._getClampedCanvasRegion(n,{includePartialPixels:!1});a=await this._exportCanvasRegionToDataURL({...h,multiplier:e,quality:s,format:o})}finally{r.forEach(n=>{try{n.object.set({opacity:n.opacity,fill:n.fill,strokeWidth:n.strokeWidth,stroke:n.stroke,selectable:n.selectable,lockRotation:n.lockRotation}),n.object.setCoords()}catch(h){}}),this.canvas.renderAll()}return a}async getImageBase64(t={}){return this.exportImageBase64(t)}async exportImageFile(t={}){if(!this.originalImage)throw new Error("No image loaded");let{mergeMask:i=!0,fileType:e="jpeg",quality:s=this.options.downsampleQuality??.92,multiplier:o=this.options.exportMultiplier??1,fileName:l=this.options.defaultDownloadFileName??"exported_image.jpg"}=t,r=this._normalizeImageFormat(e),a;i?a=await this.exportImageBase64({exportImageArea:!0,multiplier:o,quality:s,fileType:r}):a=await this.exportImageBase64({exportImageArea:!1,multiplier:o,quality:s,fileType:r});let n=a;n.startsWith(`data:image/${r}`)||(n=await new Promise((m,f)=>{let g=new window.Image;g.crossOrigin="Anonymous",g.onload=()=>{try{let p=document.createElement("canvas");p.width=g.width,p.height=g.height,p.getContext("2d").drawImage(g,0,0);let b=p.toDataURL(`image/${r}`,s);m(b)}catch(p){f(p)}},g.onerror=f,g.src=a}));let h=atob(n.split(",")[1]),d=`image/${r}`,u=h.length,c=new Uint8Array(u);for(;u--;)c[u]=h.charCodeAt(u);return new File([c],l,{type:d})}_clearMaskPlacementMemory(){this._lastMask=null,this._lastMaskInitialLeft=null,this._lastMaskInitialTop=null,this._lastMaskInitialWidth=null}async _restoreStateAfterCropFailure(t,i,e){if(this._reportError(i,e),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(i){}}),this._cropPrevEvented=null}_removeCropRect(){if(this._cropRect){try{this._cropHandlers&&this._cropHandlers.length&&this._cropHandlers.forEach(t=>{t.handlers.forEach(i=>{t.target.off(i.eventName,i.handler)})})}catch(t){}try{this.canvas.remove(this._cropRect)}catch(t){}this._cropRect=null,this._cropHandlers=[]}}enterCropMode(){if(!this.canvas||!this.originalImage||this._cropMode||!this.isImageLoaded())return;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),i=this.options.crop&&this.options.crop.padding?this.options.crop.padding:10,e=Math.max(0,Math.floor(t.left+i)),s=Math.max(0,Math.floor(t.top+i)),o=Math.max(1,Math.floor(t.width-i*2)),l=Math.max(1,Math.floor(t.height-i*2)),r=Math.max(1,Number(this.options.crop.minWidth)||50),a=Math.max(1,Number(this.options.crop.minHeight)||50),n=Math.min(r,o),h=Math.min(a,l),d=n,u=h,c=new v.Rect({left:e,top:s,width:d,height:u,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(c),c.isCropRect=!0,this.canvas.bringToFront(c),this.canvas.setActiveObject(c),this._cropRect=c,this._cropPrevEvented=[];let m=!!(this.options.crop&&this.options.crop.hideMasksDuringCrop);this.canvas.getObjects().forEach(g=>{if(g!==c){this._cropPrevEvented.push({object:g,evented:g.evented,selectable:g.selectable,visible:g.visible});try{let p={evented:!1,selectable:!1};m&&(g.maskId||g.maskLabel)&&(p.visible=!1),g.set(p)}catch(p){}}});let f=()=>{try{let g=Math.max(1,Number(c.width)||1),p=Math.max(1,Number(c.height)||1),y=Math.min(o/g,Math.max(n/g,Number(c.scaleX)||1)),b=Math.min(l/p,Math.max(h/p,Number(c.scaleY)||1));c.set({scaleX:y,scaleY:b}),c.setCoords(),this.canvas.requestRenderAll()}catch(g){}};c.on("modified",f),c.on("moving",f),c.on("scaling",f),this._cropHandlers.push({target:c,handlers:[{eventName:"modified",handler:f},{eventName:"moving",handler:f},{eventName:"scaling",handler:f}]}),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._cropRect.setCoords();let t=this._cropRect.getBoundingRect(!0,!0),i=this._getClampedCanvasRegion(t),e=!!(this.options.crop&&this.options.crop.preserveMasksAfterCrop);this._restoreCropObjectState();let s=null;try{s=this._serializeCanvasState()}catch(a){this._reportWarning("applyCrop: could not serialize before state",a),s=null}let o=[];try{let a=this.canvas.getObjects().filter(n=>n.maskId);a&&a.length&&(a.forEach(n=>{try{n.setCoords();let h=n.getBoundingRect(!0,!0),d=h.left<i.sourceX+i.sourceWidth&&h.left+h.width>i.sourceX&&h.top<i.sourceY+i.sourceHeight&&h.top+h.height>i.sourceY;this._removeLabelForMask(n),this.canvas.remove(n),e&&d&&(n.set({left:(n.left||0)-i.sourceX,top:(n.top||0)-i.sourceY,visible:!0}),n.setCoords(),o.push(n))}catch(h){this._reportWarning("applyCrop: failed to remove mask",h)}}),this._clearMaskPlacementMemory(),this.canvas.discardActiveObject(),this.canvas.renderAll())}catch(a){this._reportWarning("applyCrop: error while removing masks",a)}this._removeCropRect(),this._cropMode=!1,this.canvas.selection=!!this._prevSelectionSetting,this._prevSelectionSetting=void 0;let l;try{l=await this._exportCanvasRegionToDataURL({...i,multiplier:1,quality:this._normalizeQuality(this.options.downsampleQuality),format:"jpeg"})}catch(a){await this._restoreStateAfterCropFailure(s,"applyCrop: failed to create cropped image",a);return}try{await this.loadImage(l),o.length&&(o.forEach(a=>{this._rebindMaskEvents(a),this.canvas.add(a),this.canvas.bringToFront(a)}),this._lastMask=o[o.length-1],this.maskCounter=o.reduce((a,n)=>Math.max(a,n.maskId||0),this.maskCounter),this._updateMaskList(),this.canvas.renderAll())}catch(a){await this._restoreStateAfterCropFailure(s,"applyCrop: loadImage(croppedBase64) failed",a);return}let r=null;try{r=this._serializeCanvasState()}catch(a){this._reportWarning("applyCrop: failed to serialize after state",a),r=null}try{this._pushStateTransition(s,r)}catch(a){this._reportWarning("applyCrop: failed to push history command",a)}this._updateUI(),this.canvas.renderAll()}_updateInputs(){let t=document.getElementById(this.elements.scaleRate);t&&(t.value=Math.round(this.currentScale*100))}_updateUI(){let t=!!this.originalImage,e=(t?this.canvas.getObjects().filter(h=>h.maskId):[]).length>0,s=this.canvas.getActiveObject(),o=s&&s.maskId,l=this.currentScale===1&&this.currentRotation===0,r=this.historyManager?.canUndo(),a=this.historyManager?.canRedo();if(!!this._cropMode){for(let h of Object.keys(this.elements||{}))document.getElementById(this.elements[h])&&(h==="applyCropBtn"||h==="cancelCropBtn"?this._setDisabled(h,!1):this._setDisabled(h,!0));return}this._setDisabled("zoomInBtn",!t||this.isAnimating||this.currentScale>=this.options.maxScale),this._setDisabled("zoomOutBtn",!t||this.isAnimating||this.currentScale<=this.options.minScale),this._setDisabled("rotateLeftBtn",!t||this.isAnimating),this._setDisabled("rotateRightBtn",!t||this.isAnimating),this._setDisabled("addMaskBtn",!t||this.isAnimating),this._setDisabled("removeMaskBtn",!o||this.isAnimating),this._setDisabled("removeAllMasksBtn",!e||this.isAnimating),this._setDisabled("mergeBtn",!t||!e||this.isAnimating),this._setDisabled("downloadBtn",!t||this.isAnimating),this._setDisabled("resetBtn",!t||l||this.isAnimating),this._setDisabled("undoBtn",!t||this.isAnimating||!r),this._setDisabled("redoBtn",!t||this.isAnimating||!a),this._setDisabled("cropBtn",!t||this.isAnimating),this._setDisabled("applyCropBtn",!0),this._setDisabled("cancelCropBtn",!0),this._setDisabled("imageInput",this.isAnimating),this._setDisabled("uploadArea",this.isAnimating)}_setDisabled(t,i){let e=document.getElementById(this.elements[t]);if(e){if("disabled"in e){e.disabled=!!i;return}i?(e.setAttribute("aria-disabled","true"),e.style.pointerEvents="none"):(e.removeAttribute("aria-disabled"),e.style.pointerEvents="")}}_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.containerElement||(t?(this.placeholderElement.classList.remove("d-none"),this.placeholderElement.classList.add("d-flex"),this.containerElement.classList.add("d-none")):(this.placeholderElement.classList.remove("d-flex"),this.placeholderElement.classList.add("d-none"),this.containerElement.classList.remove("d-none")))}dispose(){try{for(let t in this._handlersByElementKey||{}){let i=this._handlersByElementKey[t]||[],e=document.getElementById(this.elements[t]);e&&i.forEach(s=>{try{e.removeEventListener(s.eventName,s.handler)}catch(o){}})}}catch(t){}if(this._cropRect){try{this.canvas.remove(this._cropRect)}catch(t){}this._cropRect=null}if(this.containerElement&&this._containerOriginalOverflow!==void 0)try{this.containerElement.style.overflow=this._containerOriginalOverflow}catch(t){}if(this.canvas){try{this.canvas.dispose()}catch(t){}this.canvas=null,this.canvasElement=null,this.isImageLoadedToCanvas=!1}this._handlersByElementKey={}}},w=class{constructor(){this.animationTasks=[],this.isRunning=!1}async add(t){return new Promise((i,e)=>{this.animationTasks.push({animationFn:t,resolve:i,reject:e}),this.isRunning||this._drainQueue()})}async _drainQueue(){if(this.animationTasks.length===0){this.isRunning=!1;return}this.isRunning=!0;let{animationFn:t,resolve:i,reject:e}=this.animationTasks.shift();try{let s=await t();i(s)}catch(s){e(s)}await this._drainQueue()}},I=class{constructor(t,i){this.execute=t,this.undo=i}},C=class{constructor(t=50){this.history=[],this.currentIndex=-1,this.maxSize=t,this.pending=Promise.resolve()}enqueue(t){let i=this.pending.then(t,t),e,s=()=>{this.pending===e&&(this.pending=Promise.resolve())};return e=i.then(s,s),this.pending=e,i}execute(t){t.execute(),this.push(t)}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++}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 R=E;var k=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:null;B(k&&k.fabric);k&&(k.ImageEditor=R);})();
|
|
8
|
+
*/var v=null;function L(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:null}function B(){let _=L();return _&&_.fabric?_.fabric:null}function O(_){return v=_||B(),v}function A(){return v||O(),v}var x=class{constructor(t={}){let e={getText:r=>r.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=!!A(),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.elements={},this.isImageLoadedToCanvas=!1,this.maxHistorySize=50,this._handlersByElementKey={},this._elementCache={},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 w,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 w,this.historyManager=new I(this.maxHistorySize),this._visibilityStateByElement=new WeakMap,this._activeAnimationRejectors=new Set,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 v.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)}_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 r=new Error("Image file could not be read");this._reportError("Image file could not be read",a),i(r)},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"),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;if(this.options.downsampleOnLoad&&(s.naturalWidth>this.options.downsampleMaxWidth||s.naturalHeight>this.options.downsampleMaxHeight)){let d=Math.min(this.options.downsampleMaxWidth/s.naturalWidth,this.options.downsampleMaxHeight/s.naturalHeight),m=Math.round(s.naturalWidth*d),g=Math.round(s.naturalHeight*d);a=this._resampleImageToDataURL(s,m,g,this.options.downsampleQuality,t)}let r=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)),r.set({originX:"left",originY:"top",selectable:!1,evented:!1}),this._setPlaceholderVisible(!1),this._syncContainerOverflow({preserveScroll:e.preserveScroll===!0});let h=r.width,l=r.height,n=this._getContainerViewportSize(),o=n.width,c=n.height;if(this.options.fitImageToCanvas){let u=Math.max(1,o-1),d=Math.max(1,c-1);this._setCanvasSizeInt(u,d);let m=Math.min(u/h,d/l,1);r.set({left:0,top:0}),r.scale(m),this.baseImageScale=r.scaleX||1}else if(this.options.coverImageToCanvas){let u=this._calculateCoverCanvasLayout(h,l);this._setCanvasSizeInt(u.canvasWidth,u.canvasHeight),r.set({left:0,top:0}),r.scale(u.scale),this.baseImageScale=r.scaleX||1}else if(this.options.expandCanvasToImage){let u=Math.max(o,Math.floor(h)),d=Math.max(c,Math.floor(l));this._setCanvasSizeInt(u,d),r.set({left:0,top:0}),r.scale(1),this.baseImageScale=1}else{let u=Math.max(this.options.canvasWidth,o),d=Math.max(this.options.canvasHeight,c);this._setCanvasSizeInt(u,d);let m=Math.min(u/h,d/l,1);r.set({left:0,top:0}),r.scale(m),this.baseImageScale=r.scaleX||1}this.originalImage=r,this.canvas.add(r),this.canvas.sendToBack(r),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}}isImageLoaded(){let t=A();return!!(this.originalImage&&t&&this.originalImage instanceof t.Image&&this.originalImage.width>0&&this.originalImage.height>0)}_createImageElement(t,e=this.options.imageLoadTimeoutMs){return new Promise((i,s)=>{let a=new Image,r=!1,h=Number.isFinite(Number(e))&&Number(e)>0?Number(e):3e4,l,n=o=>{r||(r=!0,clearTimeout(l),a.onload=null,a.onerror=null,o())};l=setTimeout(()=>{n(()=>s(new Error("Image load timed out")));try{a.src=""}catch(o){}},h),a.onload=()=>n(()=>i(a)),a.onerror=o=>n(()=>s(o)),a.src=t})}_createFabricImageFromURL(t,e=this.options.imageLoadTimeoutMs){return new Promise((i,s)=>{let a=this._getSafeTimeoutMs(e),r=!1,h,l=n=>{r||(r=!0,clearTimeout(h),n())};h=setTimeout(()=>{l(()=>s(new Error("Fabric image load timed out")))},a);try{v.Image.fromURL(t,n=>{l(()=>{if(!n){s(new Error("Image could not be loaded"));return}i(n)})},{crossOrigin:"anonymous"})}catch(n){l(()=>s(n))}})}_getSafeTimeoutMs(t){let e=Number(t);return Number.isFinite(e)&&e>0?e:3e4}_captureLoadImageTransaction(){return{canvasState:this._serializeCanvasState(),originalImage:this.originalImage,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)){try{t.canvasState&&await this.loadFromState(t.canvasState)}catch(e){this._reportError("loadImage rollback failed",e)}this.baseImageScale=t.baseImageScale,this.currentScale=t.currentScale,this.currentRotation=t.currentRotation,this.maskCounter=t.maskCounter,this.isImageLoadedToCanvas=t.isImageLoadedToCanvas,this._lastSnapshot=t.lastSnapshot,this._lastMaskInitialLeft=t.lastMaskInitialLeft,this._lastMaskInitialTop=t.lastMaskInitialTop,this._lastMaskInitialWidth=t.lastMaskInitialWidth,this._containerOriginalOverflow=t.containerOverflow,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._restoreContainerOverflowState()),this._updateInputs(),this._updateMaskList(),this._updateUI(),this.canvas&&this.canvas.renderAll()}}_resampleImageToDataURL(t,e,i,s=.92,a=null){let r=document.createElement("canvas");r.width=e,r.height=i;let h=r.getContext("2d");if(!h)throw new Error("2D canvas context is unavailable");return h.drawImage(t,0,0,t.naturalWidth,t.naturalHeight,0,0,e,i),r.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(),r=a.x.some(o=>o==="auto"||o==="scroll"),h=a.y.some(o=>o==="auto"||o==="scroll"),l=r&&this.containerElement.scrollWidth>this.containerElement.clientWidth,n=h&&this.containerElement.scrollHeight>this.containerElement.clientHeight;if(l||n){let o=this._getScrollbarSize();n&&(i+=o.width),l&&(s+=o.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="",r="";if(typeof window<"u"&&typeof window.getComputedStyle=="function"){let h=window.getComputedStyle(this.containerElement);s=h.overflow,a=h.overflowX,r=h.overflowY}return{x:[t,e,s,a],y:[t,i,s,r]}}_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 n=this._getScrollSafetyMargin(),o=Math.max(1,i.width-n),c=Math.max(1,i.height-n);return{width:t>i.width+.5?this._ceilCanvasDimension(t):o,height:e>i.height+.5?this._ceilCanvasDimension(e):c,viewportWidth:i.width,viewportHeight:i.height,hasHorizontal:!0,hasVertical:!0}}let s=this._getScrollbarSize(),a=!1,r=!1,h,l;for(let n=0;n<4;n+=1){h=Math.max(1,i.width-(a?s.width:0)),l=Math.max(1,i.height-(r?s.height:0));let o=e>l+.5,c=t>h+.5;if(o===a&&c===r)break;a=o,r=c}return h=Math.max(1,i.width-(a?s.width:0)),l=Math.max(1,i.height-(r?s.height:0)),{width:r?this._ceilCanvasDimension(t):h,height:a?this._ceilCanvasDimension(e):l,viewportWidth:h,viewportHeight:l,hasHorizontal:r,hasVertical:a}}_calculateCoverCanvasLayout(t,e){let i=this._getContainerViewportSize();if(this._hasFixedContainerScrollbars()){let d=this._getScrollSafetyMargin(),m=Math.max(1,i.width-d),g=Math.max(1,i.height-d),p=Math.min(1,Math.max(m/t,g/e)),f=t*p,y=e*p,b=this._getScrollableCanvasSize(f,y,i);return{scale:p,canvasWidth:b.width,canvasHeight:b.height}}let s=this._getScrollbarSize(),a=!1,r=!1,h=1,l=t,n=e,o,c;for(let d=0;d<4;d+=1){o=Math.max(1,i.width-(a?s.width:0)),c=Math.max(1,i.height-(r?s.height:0)),h=Math.min(1,Math.max(o/t,c/e)),l=t*h,n=e*h;let m=n>c+.5,g=l>o+.5;if(m===a&&g===r)break;a=m,r=g}let u=this._getScrollableCanvasSize(l,n,i);return{scale:h,canvasWidth:u.width,canvasHeight:u.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{return e.forEach(s=>{let a=this._getMaskNormalStyle(s),r={};Object.keys(a).forEach(n=>{s[n]!==a[n]&&(r[n]=a[n])});let h=Object.keys(r);if(!h.length)return;let l={object:s};h.forEach(n=>{l[n]=s[n]}),i.push(l),s.set(r)}),t()}finally{i.forEach(s=>{try{let a={};Object.keys(s).forEach(r=>{r!=="object"&&(a[r]=s[r])}),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){let e=Number(t);return Number.isFinite(e)?Math.max(0,Math.min(1,e)):this.options.downsampleQuality??.92}_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,r=Number(t.top)||0,h=Math.max(0,Number(t.width)||0),l=Math.max(0,Number(t.height)||0),o=e.includePartialPixels!==!1?Math.ceil:Math.floor,c=Math.min(i-1,Math.max(0,Math.floor(a))),u=Math.min(s-1,Math.max(0,Math.floor(r))),d=Math.min(i,Math.max(c+1,o(a+h))),m=Math.min(s,Math.max(u+1,o(r+l)));return{sourceX:c,sourceY:u,sourceWidth:Math.max(1,d-c),sourceHeight:Math.max(1,m-u)}}async _cropDataUrl(t,e,i,s,a,r,h="jpeg",l=.92){return new Promise((n,o)=>{let c=new Image,u=!1,d=Number(this.options.imageLoadTimeoutMs),m=Number.isFinite(d)&&d>0?d:3e4,g,p=f=>{u||(u=!0,clearTimeout(g),c.onload=null,c.onerror=null,f())};g=setTimeout(()=>{p(()=>o(new Error("Image crop load timed out")));try{c.src=""}catch(f){}},m),c.onload=()=>{try{let f=Math.max(1,Number(r)||1),y=Math.round(e*f),b=Math.round(i*f),E=Math.max(1,Math.round(s*f)),k=Math.max(1,Math.round(a*f)),M=document.createElement("canvas");M.width=E,M.height=k;let T=M.getContext("2d");if(!T)throw new Error("2D canvas context is unavailable");T.drawImage(c,y,b,E,k,0,0,E,k),p(()=>n(M.toDataURL(`image/${h}`,l)))}catch(f){p(()=>o(f))}},c.onerror=f=>p(()=>o(f)),c.src=t})}_exportCanvasRegionToDataURL({sourceX:t,sourceY:e,sourceWidth:i,sourceHeight:s,multiplier:a=1,quality:r=.92,format:h="jpeg"}){let l=Math.max(1,Number(a)||1);return this.canvas.toDataURL({format:h,quality:r,multiplier:l,left:t,top:e,width:i,height:s})}_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 v.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,r=s;t.forEach(u=>{if(!u)return;typeof u.setCoords=="function"&&u.setCoords();let d=u.getBoundingRect(!0,!0);a=Math.max(a,Math.ceil(d.left+d.width+e)),r=Math.max(r,Math.ceil(d.top+d.height+e))});let h=this.options.fitImageToCanvas||this.options.coverImageToCanvas,l=0,n=0;if(h){let u=this._getContainerViewportSize(),d=this._getScrollSafetyMargin();l=Math.max(1,u.width-d),n=Math.max(1,u.height-d)}else this.containerElement&&(l=Math.floor(this.containerElement.clientWidth||0),n=Math.floor(this.containerElement.clientHeight||0));let o=Math.max(i,l,a),c=Math.max(s,n,r);(o!==i||c!==s)&&this._setCanvasSizeInt(o,c)}catch(i){this._reportWarning("expandCanvasToFitObjects: failed to expand canvas",i)}}_expandCanvasToFitObject(t,e=10){this._expandCanvasToFitObjects([t],e)}scaleImage(t,e={}){return this.animationQueue.add(()=>this._scaleImageImpl(t,e))}_assertIdleForOperation(t){if(this._disposed||!this.canvas)throw new Error(`${t} cannot run after the editor has been disposed`);if(this.isAnimating||this.animationQueue&&this.animationQueue.isBusy())throw new Error(`${t} cannot run while an animation is running`)}_canMutateNow(t){try{return this._assertIdleForOperation(t),!0}catch(e){return this._reportError(`${t} blocked`,e),!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 r=!1,h=Math.max(0,Number(this.options.animationDuration)||0),l=Math.max(1e3,h+1e3),n,o=c=>{r||(r=!0,clearTimeout(n),this._activeAnimationRejectors.delete(a),c())};this._activeAnimationRejectors.add(a),n=setTimeout(()=>{o(()=>a(new Error(`Animation timed out while changing ${e}`)))},l);try{t.animate(e,i,{duration:h,onChange:()=>{!this._disposed&&this.canvas&&this.canvas.renderAll()},onComplete:()=>o(s)})}catch(c){o(()=>a(c))}})}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,r=this._getObjectTopLeftPoint(this.originalImage);if(this._setObjectOriginKeepingPosition(this.originalImage,"left","top",r),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(h=>{h.maskId&&this._syncMaskLabel(h)}),this._updateInputs(),i&&this.saveState()}finally{s&&(this.isAnimating=!1,this._updateInputs(),this._updateUI())}}rotateImage(t,e={}){return this.animationQueue.add(()=>this._rotateImageImpl(t,e))}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",r=s.originY||"top",h=this._getObjectOriginPoint(s,a,r),l=!1,n=!1;try{this.currentRotation=t,this.isAnimating=!0,l=!0,this._updateUI();let o=s.getCenterPoint();if(this._setObjectOriginKeepingPosition(s,"center","center",o),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 c=this._getObjectCoordinateTopLeftPoint(this.originalImage);this._setObjectOriginKeepingPosition(this.originalImage,"left","top",c),this.canvas.getObjects().forEach(u=>{u.maskId&&this._syncMaskLabel(u)}),this._updateInputs(),i&&this.saveState(),n=!0}finally{!n&&!this._disposed&&s&&this._setObjectOriginKeepingPosition(s,a,r,h),l&&(this.isAnimating=!1,this._updateInputs(),this._updateUI())}}resetImageTransform(){return this.originalImage?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)}).catch(t=>{throw this._reportError("resetImageTransform() failed",t),t}):Promise.resolve()}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;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 r=this.canvas.getObjects();if(this.originalImage=r.find(o=>o.type==="image"&&!o.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 o=Number(a&&a.baseImageScale),c=Number(a&&a.currentScale),u=Number(a&&a.currentRotation);if(Number.isFinite(o)&&o>0&&(this.baseImageScale=o),Number.isFinite(c)&&c>0)this.currentScale=c;else{let d=Number(this.baseImageScale)||1,m=Number(this.originalImage.scaleX)||d;this.currentScale=m/d}this.currentRotation=Number.isFinite(u)?u:Number(this.originalImage.angle)||0}else this.baseImageScale=1,this.currentScale=1,this.currentRotation=0;let h=r.filter(o=>o.maskId);h.forEach(o=>{this._restoreMaskControls(o),this._rebindMaskEvents(o),o.set(this._getMaskNormalStyle(o))});let l=Number(a&&a.maskCounter),n=h.reduce((o,c)=>Math.max(o,c.maskId),0);this.maskCounter=Number.isFinite(l)&&l>=n?Math.floor(l):n,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(r){this._reportError("loadFromState() failed",r),i(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||t.complete||t.naturalWidth>0||t.width>0?Promise.resolve():new Promise((e,i)=>{let s=!1,a=setTimeout(()=>{r(()=>i(new Error("Image load timed out while restoring state")))},this._getSafeTimeoutMs(this.options.imageLoadTimeoutMs)),r=h=>{s||(s=!0,clearTimeout(a),t.onload=null,t.onerror=null,h())};t.onload=()=>r(e),t.onerror=h=>r(()=>i(h))})}saveState(){if(this.canvas)try{let t=this._captureCanvasStateOrThrow("saveState"),e=this._lastSnapshot||t;if(t===e)return;let i=!1,s=new S(()=>{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 S(()=>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,r,h=m=>{let g=this.canvas?this.canvas.getWidth():0,p=this.canvas?this.canvas.getHeight():0;return m==="height"?p:m==="min"?Math.min(g,p):g},l=(m,g,p="width")=>{if(typeof m=="function")return m(this.canvas,this.options);if(typeof m=="string"&&m.endsWith("%")){let f=Number.parseFloat(m)/100;return Number.isFinite(f)?Math.floor(h(p)*f):g}return m??g};if(i.left===void 0&&this._lastMask){let m=this._lastMask;typeof m.setCoords=="function"&&m.setCoords();let g=typeof m.getBoundingRect=="function"?m.getBoundingRect(!0,!0):{left:m.left||s,top:m.top||s,width:m.width||0};a=Math.round(g.left+g.width+i.gap),r=Math.round(g.top??s)}else a=l(i.left,s,"width"),r=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=r;let n;if(typeof i.fabricGenerator=="function")n=i.fabricGenerator(i,this.canvas,this.options);else switch(e){case"circle":n=new v.Circle({left:a,top:r,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":n=new v.Ellipse({left:a,top:r,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 m=i.points||[];Array.isArray(m)&&m.length&&(m=m.map(g=>Array.isArray(g)?{x:Number(g[0]),y:Number(g[1])}:{x:Number(g.x),y:Number(g.y)})),n=new v.Polygon(m,{left:a,top:r,fill:i.color,opacity:i.alpha,angle:i.angle,...i.styles});break}default:n=new v.Rect({left:a,top:r,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})}let o=i.styles||{},c=m=>Object.prototype.hasOwnProperty.call(o,m),u={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:c("stroke")?o.stroke:"#ccc",strokeWidth:c("strokeWidth")?o.strokeWidth:1,opacity:c("opacity")?o.opacity:i.alpha,strokeUniform:"strokeUniform"in i?i.strokeUniform:c("strokeUniform")?o.strokeUniform:!0};c("strokeDashArray")&&(u.strokeDashArray=o.strokeDashArray),n.set(u),n.setCoords(),n.set({originalAlpha:Number.isFinite(Number(n.opacity))?Number(n.opacity):i.alpha,originalStroke:n.stroke||"#ccc",originalStrokeWidth:Number.isFinite(Number(n.strokeWidth))?Number(n.strokeWidth):1}),this._rebindMaskEvents(n),this._expandCanvasToFitObject(n),this._lastMaskInitialLeft=a,this._lastMaskInitialTop=r,this._lastMaskInitialWidth=l(i.width,this.options.defaultMaskWidth,"width");let d=++this.maskCounter;return n.set({maskId:d,maskName:`${this.options.maskName}${d}`}),this._lastMask=n,this.canvas.add(n),this.canvas.bringToFront(n),i.selectable&&this.canvas.setActiveObject(n),this._handleSelectionChanged([n]),this._updateMaskList(),this._updateUI(),this.canvas.renderAll(),this.saveState(),typeof i.onCreate=="function"&&i.onCreate(n,this.canvas),n}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"))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){}}}_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,v),(!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 v.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();t.filter(i=>i.maskLabel).forEach(i=>{try{t.includes(i)&&this.canvas.remove(i)}catch(s){}}),t.forEach(i=>{if(i.maskId&&i.__label)try{delete i.__label}catch(s){}})}_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,r=s.y-i.y,h=Math.sqrt(a*a+r*r)||1,l=a/h,n=r/h,o=Math.max(0,this.options.maskLabelOffset??3),c=i.x+l*o,u=i.y+n*o;t.__label.set({left:Math.round(c),top:Math.round(u),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(r){}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(e=>e.maskId).length))){this.canvas.discardActiveObject(),this.canvas.renderAll();try{let e=this._serializeCanvasState(),i=await this.exportImageBase64({exportImageArea:!0,multiplier:this.options.exportMultiplier});this.removeAllMasks({saveHistory:!1}),await this.loadImage(i,{preserveScroll:!0,resetMaskCounter:!1});let s=this._serializeCanvasState();this._pushStateTransition(e,s)}catch(e){throw this._reportError("merge error",e),e}}}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");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(c=>c.maskId||c.maskLabel),o=n.map(c=>({object:c,visible:c.visible}));try{n.forEach(d=>{d.set({visible:!1})}),this.canvas.discardActiveObject(),this.canvas.renderAll(),this.originalImage.setCoords();let c=this.originalImage.getBoundingRect(!0,!0),u=this._getClampedCanvasRegion(c,{includePartialPixels:!1});return this._exportCanvasRegionToDataURL({...u,multiplier:i,quality:s,format:a})}finally{o.forEach(c=>{try{c.object.set({visible:c.visible})}catch(u){}}),this.canvas.renderAll()}}let r=this.canvas.getObjects().filter(n=>n.maskId),h=r.map(n=>({object:n,opacity:n.opacity,fill:n.fill,strokeWidth:n.strokeWidth,stroke:n.stroke,selectable:n.selectable,lockRotation:n.lockRotation})),l;try{r.forEach(c=>this._removeLabelForMask(c)),this.canvas.discardActiveObject(),this.canvas.renderAll(),r.forEach(c=>{c.set({opacity:1,fill:"#000000",strokeWidth:0,stroke:null,selectable:!1}),c.setCoords()}),this.canvas.renderAll(),this.originalImage.setCoords();let n=this.originalImage.getBoundingRect(!0,!0),o=this._getClampedCanvasRegion(n,{includePartialPixels:!1});l=this._exportCanvasRegionToDataURL({...o,multiplier:i,quality:s,format:a})}finally{h.forEach(n=>{try{n.object.set({opacity:n.opacity,fill:n.fill,strokeWidth:n.strokeWidth,stroke:n.stroke,selectable:n.selectable,lockRotation:n.lockRotation}),n.object.setCoords()}catch(o){}}),this.canvas.renderAll()}return l}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:r=this.options.defaultDownloadFileName??"exported_image.jpg"}=t,h=this._normalizeImageFormat(i),l;e?l=await this.exportImageBase64({exportImageArea:!0,multiplier:a,quality:s,fileType:h}):l=await this.exportImageBase64({exportImageArea:!1,multiplier:a,quality:s,fileType:h});let n=l;n.startsWith(`data:image/${h}`)||(n=await new Promise((m,g)=>{let p=new window.Image;p.crossOrigin="Anonymous",p.onload=()=>{try{let f=document.createElement("canvas");f.width=p.width,f.height=p.height;let y=f.getContext("2d");if(!y)throw new Error("Unable to create 2D canvas context for export conversion");y.drawImage(p,0,0);let b=f.toDataURL(`image/${h}`,s);m(b)}catch(f){g(f)}},p.onerror=g,p.src=l}));let o=atob(n.split(",")[1]),c=`image/${h}`,u=o.length,d=new Uint8Array(u);for(;u--;)d[u]=o.charCodeAt(u);return new File([d],r,{type:c})}_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)),r=Math.max(1,Math.floor(t.height-e*2)),h=Math.max(1,Number(this.options.crop.minWidth)||50),l=Math.max(1,Number(this.options.crop.minHeight)||50),n=Math.min(h,a),o=Math.min(l,r),c=n,u=o,d=new v.Rect({left:i,top:s,width:c,height:u,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 m=!!(this.options.crop&&this.options.crop.hideMasksDuringCrop);this.canvas.getObjects().forEach(p=>{if(p!==d){this._cropPrevEvented.push({object:p,evented:p.evented,selectable:p.selectable,visible:p.visible});try{let f={evented:!1,selectable:!1};m&&(p.maskId||p.maskLabel)&&(f.visible=!1),p.set(f)}catch(f){}}});let g=()=>{try{let p=Math.max(1,Number(d.width)||1),f=Math.max(1,Number(d.height)||1),y=Math.min(a/p,Math.max(n/p,Number(d.scaleX)||1)),b=Math.min(r/f,Math.max(o/f,Number(d.scaleY)||1));d.set({scaleX:y,scaleY:b}),d.setCoords(),this.canvas.requestRenderAll()}catch(p){}};d.on("modified",g),d.on("moving",g),d.on("scaling",g),this._cropHandlers.push({target:d,handlers:[{eventName:"modified",handler:g},{eventName:"moving",handler:g},{eventName:"scaling",handler:g}]}),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(n=>n.maskId);l&&l.length&&(l.forEach(n=>{try{n.setCoords();let o=n.getBoundingRect(!0,!0),c=o.left<e.sourceX+e.sourceWidth&&o.left+o.width>e.sourceX&&o.top<e.sourceY+e.sourceHeight&&o.top+o.height>e.sourceY;this._removeLabelForMask(n),this.canvas.remove(n),i&&c&&(this._translateObjectByCanvasOffset(n,-e.sourceX,-e.sourceY),n.set({visible:!0}),a.push(n))}catch(o){this._reportWarning("applyCrop: failed to remove mask",o)}}),this._clearMaskPlacementMemory(),this.canvas.discardActiveObject(),this.canvas.renderAll())}catch(l){this._reportWarning("applyCrop: error while removing masks",l)}this._removeCropRect(),this._cropMode=!1,this.canvas.selection=!!this._prevSelectionSetting,this._prevSelectionSetting=void 0;let r;try{r=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(r,{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,n)=>Math.max(l,n.maskId||0),this.maskCounter),this._updateMaskList(),this.canvas.renderAll())}catch(l){await this._restoreStateAfterCropFailure(s,"applyCrop: loadImage(croppedBase64) failed",l);return}let h;try{h=a.length?this._serializeCanvasState():this._lastSnapshot}catch(l){this._reportWarning("applyCrop: failed to serialize after state",l),h=null}try{this._pushStateTransition(s,h)}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(o=>o.maskId):[]).length>0,s=this.canvas.getActiveObject(),a=s&&s.maskId,r=this.currentScale===1&&this.currentRotation===0,h=this.historyManager?.canUndo(),l=this.historyManager?.canRedo();if(!!this._cropMode){for(let o of Object.keys(this.elements||{}))this._getElement(o)&&(o==="applyCropBtn"||o==="cancelCropBtn"?this._setDisabled(o,!1):this._setDisabled(o,!0));return}this._setDisabled("zoomInBtn",!t||this.isAnimating||this.currentScale>=this.options.maxScale),this._setDisabled("zoomOutBtn",!t||this.isAnimating||this.currentScale<=this.options.minScale),this._setDisabled("rotateLeftBtn",!t||this.isAnimating),this._setDisabled("rotateRightBtn",!t||this.isAnimating),this._setDisabled("addMaskBtn",!t||this.isAnimating),this._setDisabled("removeMaskBtn",!a||this.isAnimating),this._setDisabled("removeAllMasksBtn",!i||this.isAnimating),this._setDisabled("mergeBtn",!t||!i||this.isAnimating),this._setDisabled("downloadBtn",!t||this.isAnimating),this._setDisabled("resetBtn",!t||r||this.isAnimating),this._setDisabled("undoBtn",!t||this.isAnimating||!h),this._setDisabled("redoBtn",!t||this.isAnimating||!l),this._setDisabled("cropBtn",!t||this.isAnimating),this._setDisabled("applyCropBtn",!0),this._setDisabled("cancelCropBtn",!0),this._setDisabled("imageInput",this.isAnimating),this._setDisabled("uploadArea",this.isAnimating)}_setDisabled(t,e){let i=this._getElement(t);if(i){if("disabled"in i){i.disabled=!!e;return}e?(i.setAttribute("aria-disabled","true"),i.style.pointerEvents="none"):(i.removeAttribute("aria-disabled"),i.style.pointerEvents="")}}_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"));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._clearMaskPlacementMemory(),this.originalImage=null,this.baseImageScale=1,this.currentScale=1,this.currentRotation=0,this.isAnimating=!1,this._cropMode=!1,this._cropRect=null,this._cropHandlers=[],this._cropPrevEvented=null,this._prevSelectionSetting=void 0,this._initialized=!1}},w=class{constructor(){this.animationTasks=[],this.isRunning=!1,this.currentTask=null}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")){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){for(this.isRunning=!0;this.animationTasks.length>0;){let t=this.animationTasks.shift();this.currentTask=t;try{let e=await t.animationFn();t.isSettled||(t.isSettled=!0,t.resolve(e))}catch(e){t.isSettled||(t.isSettled=!0,t.reject(e))}finally{this.currentTask===t&&(this.currentTask=null)}}this.isRunning=!1}}},S=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"?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 R=x;var C=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:null;O(C&&C.fabric);C&&(C.ImageEditor=R);})();
|
|
9
9
|
//# sourceMappingURL=image-editor.min.js.map
|