@lancercomet/zoom-pan 0.1.1 → 0.1.2

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/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";function t(t,e,i,s){return new(i||(i=Promise))(function(n,h){function a(t){try{r(s.next(t))}catch(t){h(t)}}function o(t){try{r(s.throw(t))}catch(t){h(t)}}function r(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i(function(t){t(e)})).then(a,o)}r((s=s.apply(t,e||[])).next())})}function e(t,e,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(t):s?s.value:e.get(t)}function i(t,e,i,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,i):n?n.value=i:e.set(t,i),i}"function"==typeof SuppressedError&&SuppressedError;const s=(e,i)=>t(void 0,void 0,void 0,function*(){return new Promise((t,s)=>{const n=new Image;"string"==typeof e?(void 0!==i&&(n.crossOrigin=i),n.src=e):n.src=URL.createObjectURL(e),n.onload=()=>{t(n)},n.onerror=()=>{s(new Error("Image load failed"))}})}),n=(t,e,i)=>Math.min(Math.max(t,e),i);let h=0;class a{constructor(t,e,i="world"){this.space="world",this.visible=!0,this.opacity=1,this.blend="source-over",this.name=t,this.id=`layer_${e}_${++h}`,this.type=e,this.space=i}}class o extends a{beginStroke(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);this._lastX=i,this._lastY=s,this._drawing=!0}stroke(t,e,i,s,n=1,h="brush"){if(!this._drawing)return;const{lx:a,ly:o}=this.toLocalPoint(t,e);this.context.beginPath(),this.context.moveTo(this._lastX,this._lastY),this.context.lineTo(a,o),"eraser"===h?(this.context.globalCompositeOperation="destination-out",this.context.strokeStyle="rgba(0, 0, 0, 1)"):(this.context.globalCompositeOperation="source-over",this.context.strokeStyle=i),this.context.lineWidth=s*n,this.context.lineCap="round",this.context.lineJoin="round",this.context.stroke(),this.context.closePath(),this._lastX=a,this._lastY=o}endStroke(){this._drawing=!1}isDrawing(){return this._drawing}captureSnapshot(t){try{if(t){const{x:e,y:i,width:s,height:n}=t,h=Math.max(0,Math.floor(e)),a=Math.max(0,Math.floor(i)),o=Math.min(this.canvas.width-h,Math.ceil(s)),r=Math.min(this.canvas.height-a,Math.ceil(n));return o<=0||r<=0?null:this.context.getImageData(h,a,o,r)}return this.context.getImageData(0,0,this.canvas.width,this.canvas.height)}catch(t){return null}}restoreSnapshot(t,e){var i,s;const n=null!==(i=null==e?void 0:e.x)&&void 0!==i?i:0,h=null!==(s=null==e?void 0:e.y)&&void 0!==s?s:0;this.context.putImageData(t,n,h)}clearRegion(t){t?this.context.clearRect(t.x,t.y,t.width,t.height):this.context.clearRect(0,0,this.canvas.width,this.canvas.height)}requestRedraw(){var t;null===(t=this._redraw)||void 0===t||t.call(this,this.context,this.canvas)}drawImage(t,e,i,s,n){this.context.drawImage(t,e,i,null!=s?s:t.width,null!=n?n:t.height)}hitTest(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);return i>=0&&i<=this.canvas.width&&s>=0&&s<=this.canvas.height}toLocalPoint(t,e){const i=t-this.x,s=e-this.y,n=Math.cos(-this.rotation),h=Math.sin(-this.rotation),a=i*h+s*n,o=(i*n-s*h)/this.scale,r=a/this.scale;return{lx:o+("center"===this.anchor?this.canvas.width/2:0),ly:r+("center"===this.anchor?this.canvas.height/2:0)}}render(t,e){if(!this.visible)return;const i=this.canvas.width*this.scale,s=this.canvas.height*this.scale,n="center"===this.anchor?-i/2:0,h="center"===this.anchor?-s/2:0;t.save(),t.globalAlpha=this.opacity,t.globalCompositeOperation=this.blend,t.translate(this.x,this.y),t.rotate(this.rotation),t.drawImage(this.canvas,n,h,i,s),t.restore()}cropTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas(),n=Math.min(s.width,e),h=Math.min(s.height,i);this._setCanvasSize(e,i),n>0&&h>0&&this.context.drawImage(s,0,0,n,h,0,0,n,h)}resizeTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas();this._setCanvasSize(e,i),s.width>0&&s.height>0&&this.context.drawImage(s,0,0,s.width,s.height,0,0,e,i)}_cloneCanvas(){const t=document.createElement("canvas");if(t.width=this.canvas.width,t.height=this.canvas.height,0===t.width||0===t.height)return t;const e=t.getContext("2d");if(!e)throw new Error("Offscreen 2D context unavailable");return e.drawImage(this.canvas,0,0),t}_setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,t,e)}destroy(){this.canvas.width=0,this.canvas.height=0}constructor(t){var e,i;super(t.name||"","canvas",null!==(e=t.space)&&void 0!==e?e:"world"),this.x=0,this.y=0,this.scale=1,this.rotation=0,this.anchor="topLeft",this._drawing=!1,this._lastX=0,this._lastY=0,this.canvas=document.createElement("canvas"),this.canvas.width=t.width,this.canvas.height=t.height;const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Offscreen 2D context unavailable");this.context=s,this.x=t.x||0,this.y=t.y||0,this.scale=null!==(i=t.scale)&&void 0!==i?i:1,this.rotation=t.rotation||0,t.anchor&&(this.anchor=t.anchor),this._redraw=t.redraw,this._redraw&&this._redraw(this.context,this.canvas)}}var r;class c extends o{static fromImage(e){return t(this,void 0,void 0,function*(){var t,n,h,a,o,_,l,d;const g=yield s(e.src,e.crossOrigin),m=null!==(t=e.width)&&void 0!==t?t:g.naturalWidth,u=null!==(n=e.height)&&void 0!==n?n:g.naturalHeight,p=new c({name:e.name,space:null!==(h=e.space)&&void 0!==h?h:"world",x:null!==(a=e.x)&&void 0!==a?a:0,y:null!==(o=e.y)&&void 0!==o?o:0,scale:null!==(_=e.scale)&&void 0!==_?_:1,rotation:null!==(l=e.rotation)&&void 0!==l?l:0,anchor:null!==(d=e.anchor)&&void 0!==d?d:"topLeft",width:m,height:u});return p.context.clearRect(0,0,p.canvas.width,p.canvas.height),p.context.drawImage(g,0,0,m,u),"string"!=typeof e.src&&i(p,r,g.src.startsWith("blob:")?g.src:null,"f"),p})}setSource(n,h){return t(this,void 0,void 0,function*(){const t=yield s(n,h);if(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.drawImage(t,0,0),e(this,r,"f")){try{URL.revokeObjectURL(e(this,r,"f"))}catch(t){}i(this,r,null,"f")}"string"!=typeof n&&i(this,r,t.src.startsWith("blob:")?t.src:null,"f")})}paint(t){t(this.context,this.canvas)}getImageData(t=0,e=0,i=this.canvas.width,s=this.canvas.height){return this.context.getImageData(t,e,i,s)}putImageData(t,e=0,i=0){this.context.putImageData(t,e,i)}toDataURL(t="image/png",e){return this.canvas.toDataURL(t,e)}toImageBitmap(t){return createImageBitmap(this.canvas,null!=t?t:{})}destroy(){var t;if(null===(t=super.destroy)||void 0===t||t.call(this),e(this,r,"f")){try{URL.revokeObjectURL(e(this,r,"f"))}catch(t){}i(this,r,null,"f")}}constructor(t){var e,i;super({name:t.name,space:null!==(e=t.space)&&void 0!==e?e:"world",x:t.x,y:t.y,scale:t.scale,rotation:t.rotation,anchor:null!==(i=t.anchor)&&void 0!==i?i:"topLeft",width:t.width,height:t.height}),r.set(this,null),this.type="bitmap"}}r=new WeakMap;class _{constructor(){this._worldLayers=[],this._screenLayers=[]}_renderAllLayersIn(t,e){e.save(),t.applyWorldTransform(e);for(const i of this._worldLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore(),e.save(),t.applyScreenTransform(e);for(const i of this._screenLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore()}addLayer(t,e){const i="world"===t.space?this._worldLayers:this._screenLayers;return"number"==typeof e&&e>=0&&e<i.length?(i.splice(e,0,t),t.id):(i.push(t),t.id)}createImageLayer(e){return t(this,void 0,void 0,function*(){const t=yield c.fromImage(e);return this.addLayer(t),t})}createCanvasLayer(t){const e=new o(t);return this.addLayer(e),e}removeLayer(t){var e,i,s,n;const h=this._worldLayers.findIndex(e=>e.id===t);if(h>=0)return null===(i=(e=this._worldLayers[h]).destroy)||void 0===i||i.call(e),void this._worldLayers.splice(h,1);const a=this._screenLayers.findIndex(e=>e.id===t);a>=0&&(null===(n=(s=this._screenLayers[a]).destroy)||void 0===n||n.call(s),this._screenLayers.splice(a,1))}moveLayer(t,e){const i=this._worldLayers.findIndex(e=>e.id===t);if(i>=0){const[t]=this._worldLayers.splice(i,1),s=Math.max(0,Math.min(e,this._worldLayers.length));return void this._worldLayers.splice(s,0,t)}const s=this._screenLayers.findIndex(e=>e.id===t);if(s>=0){const[t]=this._screenLayers.splice(s,1),i=Math.max(0,Math.min(e,this._screenLayers.length));this._screenLayers.splice(i,0,t)}}getLayer(t){return this._worldLayers.find(e=>e.id===t)||this._screenLayers.find(e=>e.id===t)}getAllLayers(t){return t?("world"===t?this._worldLayers:this._screenLayers).slice():[...this._worldLayers,...this._screenLayers]}hitTest(t,e,i="world"){const s=this.getAllLayers(i);for(let i=s.length-1;i>=0;i--){const n=s[i];if(n.hitTest&&n.hitTest(t,e))return n}}destroy(){var t;for(const e of[...this._worldLayers,...this._screenLayers])null===(t=e.destroy)||void 0===t||t.call(e);this._worldLayers=[],this._screenLayers=[]}}class l{constructor(t){this.name="interaction",this._view=null,this._dragging=!1,this._vx=0,this._vy=0,this._lastMoveTs=0,this._activePointerId=null,this._onDownBound=t=>this._onPointerDown(t),this._onMoveBound=t=>this._onPointerMove(t),this._onUpBound=()=>this._onPointerUp(),this._onWheelBound=t=>this._onWheel(t),this._onUpdate=t=>{if(!this._view)return;const{friction:e,stopSpeed:i}=this._options,s=Math.hypot(this._vx,this._vy)>=i;if(!this._dragging&&this._panEnabled&&s){const s=this._vx*t,n=this._vy*t;this._view.panBy(s,n),this._vx*=e,this._vy*=e,Math.hypot(this._vx,this._vy)<i&&(this._vx=0,this._vy=0)}else this._panEnabled||(this._vx=0,this._vy=0)},this._options=Object.assign({panEnabled:!0,zoomEnabled:!0,friction:.92,stopSpeed:.02,emaAlpha:.25,idleNoInertiaMs:120,wheelSensitivity:.0015},t),this._panEnabled=this._options.panEnabled,this._zoomEnabled=this._options.zoomEnabled}install(t){this._view=t;const e=t.canvas;e.addEventListener("wheel",this._onWheelBound,{passive:!1}),e.addEventListener("pointerdown",this._onDownBound),window.addEventListener("pointermove",this._onMoveBound),window.addEventListener("pointerup",this._onUpBound),t.onUpdate(this._onUpdate)}destroy(){if(!this._view)return;const t=this._view.canvas;t.removeEventListener("wheel",this._onWheelBound),t.removeEventListener("pointerdown",this._onDownBound),window.removeEventListener("pointermove",this._onMoveBound),window.removeEventListener("pointerup",this._onUpBound),this._view.offUpdate(this._onUpdate),this._view=null}isPanEnabled(){return this._panEnabled}isZoomEnabled(){return this._zoomEnabled}setPanEnabled(t){this._panEnabled!==t&&(this._panEnabled=t,t||(this._dragging=!1,this._vx=0,this._vy=0))}setZoomEnabled(t){this._zoomEnabled=t}setWheelSensitivity(t){this._options.wheelSensitivity=t}isDragging(){return this._dragging}_onPointerDown(t){var e;if(0===t.button&&this._panEnabled){this._dragging=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._activePointerId=t.pointerId;try{null===(e=this._view)||void 0===e||e.canvas.setPointerCapture(t.pointerId)}catch(t){}}}_onPointerMove(t){if(!this._dragging||!this._panEnabled||!this._view)return;const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.movementX,n=t.movementY;this._view.panBy(s,n);const h=this._options.emaAlpha,a=s/i,o=n/i;this._vx=(1-h)*this._vx+h*a,this._vy=(1-h)*this._vy+h*o}_onPointerUp(){if(!this._dragging)return;this._dragging=!1;const t=performance.now(),e=this._lastMoveTs?t-this._lastMoveTs:1/0;if(null!=this._activePointerId&&this._view){try{this._view.canvas.releasePointerCapture(this._activePointerId)}catch(t){}this._activePointerId=null}if(e>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,e/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}_getLineHeightPx(){if(!this._view)return 16;const t=getComputedStyle(this._view.canvas).lineHeight;if(!t||"normal"===t)return 16;const e=parseFloat(t);return Number.isFinite(e)?e:16}_normalizeWheelDelta(t){if(!this._view)return 0;let e=t.deltaY;if(1===t.deltaMode)e*=this._getLineHeightPx();else if(2===t.deltaMode){e*=this._view.canvas.clientHeight||window.innerHeight||800}return e}_onWheel(t){if(!this._zoomEnabled||!this._view)return;t.preventDefault(),t.stopPropagation();const e=this._normalizeWheelDelta(t),i=this._view.canvas.getBoundingClientRect(),s=t.clientX-i.left,n=t.clientY-i.top;let h=-e*this._options.wheelSensitivity;t.ctrlKey||t.metaKey?h*=1.6:t.shiftKey&&(h*=.6),this._view.zoomByLogAtScreen(s,n,h)}}class d{constructor(t){var e,i,s,n;this.name="document",this._view=null,this._enabled=!1,this._x=0,this._y=0,this._width=0,this._height=0,this._marginL=0,this._marginR=0,this._marginT=0,this._marginB=0,this._panClampMode="minVisible",this._onUpdate=()=>{this._enabled&&this._view&&this._clampPan()},this._onBeforeRender=t=>{this._enabled&&this._view&&(t.save(),t.beginPath(),t.rect(this._x,this._y,this._width,this._height),t.clip())},this._onAfterRender=t=>{if(this._enabled&&this._view&&(t.restore(),this._options.drawBorder)){const e=this._view.zoom;t.save(),t.lineWidth=1/e,t.strokeStyle="#cfcfcf",t.strokeRect(this._x,this._y,this._width,this._height),t.restore()}},this._options=Object.assign({rect:{x:0,y:0,width:0,height:0},margins:{},drawBorder:!1,minVisiblePx:30,panClampMode:"minVisible"},t),(null==t?void 0:t.rect)&&(this._enabled=!0,this._x=t.rect.x,this._y=t.rect.y,this._width=t.rect.width,this._height=t.rect.height),(null==t?void 0:t.margins)&&(this._marginL=null!==(e=t.margins.left)&&void 0!==e?e:0,this._marginR=null!==(i=t.margins.right)&&void 0!==i?i:0,this._marginT=null!==(s=t.margins.top)&&void 0!==s?s:0,this._marginB=null!==(n=t.margins.bottom)&&void 0!==n?n:0),this._panClampMode=this._options.panClampMode}install(t){this._view=t,t.onUpdate(this._onUpdate),t.onBeforeRender(this._onBeforeRender),t.onAfterRender(this._onAfterRender)}destroy(){this._view&&(this._view.offUpdate(this._onUpdate),this._view.offBeforeRender(this._onBeforeRender),this._view.offAfterRender(this._onAfterRender),this._view=null)}isEnabled(){return this._enabled}getRect(){return{x:this._x,y:this._y,width:this._width,height:this._height}}setRect(t,e,i,s){this._enabled=!0,this._x=t,this._y=e,this._width=i,this._height=s}clearRect(){this._enabled=!1}setMargins(t){var e,i,s,n;this._marginL=null!==(e=t.left)&&void 0!==e?e:this._marginL,this._marginR=null!==(i=t.right)&&void 0!==i?i:this._marginR,this._marginT=null!==(s=t.top)&&void 0!==s?s:this._marginT,this._marginB=null!==(n=t.bottom)&&void 0!==n?n:this._marginB}getMargins(){return{left:this._marginL,right:this._marginR,top:this._marginT,bottom:this._marginB}}setPanClampMode(t){this._panClampMode=t}getPanClampMode(){return this._panClampMode}cropTo(t){this._doResize("crop",t)}resizeTo(t){this._doResize("resize",t)}zoomToFit(t="contain"){if(!this._enabled||!this._view)return;const e=this._view.dpr,i=this._view.canvas.width/e,s=this._view.canvas.height/e,n=Math.max(1,i-(this._marginL+this._marginR)),h=Math.max(1,s-(this._marginT+this._marginB));let a;const o=n/this._width,r=h/this._height;a="contain"===t?Math.min(o,r):"cover"===t?Math.max(o,r):"fitWidth"===t?o:r,a=Math.min(this._view.maxZoom,Math.max(this._view.minZoom,a));const c=this._marginL+(n-a*this._width)/2,_=this._marginT+(h-a*this._height)/2,l=c-a*this._x,d=_-a*this._y;this._view.setTransform(a,l,d)}isPointInDocument(t,e){return!this._enabled||t>=this._x&&t<=this._x+this._width&&e>=this._y&&e<=this._y+this._height}_clampPan(){if(!this._view)return;const{zoom:t,tx:e,ty:i}=this._view.getTransform(),s=t,n=this._view.dpr,h=this._view.canvas.width/n,a=this._view.canvas.height/n,o=this._x,r=this._y,c=this._x+this._width,_=this._y+this._height;let l=e,d=i;if("margin"===this._panClampMode){const t=this._marginL-s*o,n=h-this._marginR-s*c,g=this._marginT-s*r,m=a-this._marginB-s*_,u=Math.max(1,h-(this._marginL+this._marginR)),p=Math.max(1,a-(this._marginT+this._marginB));l=s*this._width<=u?this._marginL+(u-s*this._width)/2-s*this._x:Math.min(t,Math.max(n,e)),d=s*this._height<=p?this._marginT+(p-s*this._height)/2-s*this._y:Math.min(g,Math.max(m,i))}else if("minVisible"===this._panClampMode){const t=s*this._width,n=s*this._height,g=Math.min(this._options.minVisiblePx,t),m=Math.min(this._options.minVisiblePx,n),u=h-g-s*o,p=g-s*c,v=a-m-s*r,w=m-s*_;l=p<=u?Math.min(u,Math.max(p,e)):(p+u)/2,d=w<=v?Math.min(v,Math.max(w,i)):(w+v)/2}l===e&&d===i||this._view.setPan(l,d)}_doResize(t,e){if(!this._view)return;const i=Math.max(1,Math.floor(e.width)),s=Math.max(1,Math.floor(e.height)),n={width:i,height:s},h=this._view.getLayerManagers();for(const e of h){const i=e.getAllLayers("world");for(const e of i){const i=e;"function"==typeof i.cropTo&&"function"==typeof i.resizeTo&&("crop"===t?i.cropTo(n):i.resizeTo(n))}}this._width=i,this._height=s,this._enabled&&this._clampPan()}}class g{constructor(t,e,i,s){this.type="snapshot",this._isExecuted=!0,this._target=t,this._beforeData=e,this._afterData=i,this._region=null==s?void 0:s.region}execute(){if(this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._afterData,t),this._isExecuted=!0}undo(){if(!this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._beforeData,t),this._isExecuted=!1}canMerge(){return!1}merge(){return this}}exports.BitmapLayer=c,exports.CanvasLayer=o,exports.ContentLayerManager=class extends _{constructor(){super(...arguments),this._compositeCache=null,this._compositeCacheCtx=null,this._compositeDirty=!0,this._lastCacheWidth=0,this._lastCacheHeight=0,this._cachedBoundsMinX=0,this._cachedBoundsMinY=0}markDirty(){this._compositeDirty=!0}addLayer(t,e){return this._compositeDirty=!0,super.addLayer(t,e)}removeLayer(t){this._compositeDirty=!0,super.removeLayer(t)}moveLayer(t,e){this._compositeDirty=!0,super.moveLayer(t,e)}renderAllLayersIn(t){const e=t.contentContext,i=this._worldLayers;0!==i.length&&(this._compositeDirty&&this._rebuildCompositeCache(i),this._compositeCache&&this._compositeCacheCtx&&e.drawImage(this._compositeCache,this._cachedBoundsMinX,this._cachedBoundsMinY))}_rebuildCompositeCache(t){let e=0,i=0,s=0,n=0,h=!1;for(const a of t){const t=a,o=t.canvas.width*t.scale,r=t.canvas.height*t.scale,c="center"===t.anchor?-o/2:0,_="center"===t.anchor?-r/2:0,l=Math.cos(t.rotation),d=Math.sin(t.rotation),g=[{x:c,y:_},{x:c+o,y:_},{x:c,y:_+r},{x:c+o,y:_+r}];let m=1/0,u=1/0,p=-1/0,v=-1/0;for(const e of g){const i=e.x*l-e.y*d+t.x,s=e.x*d+e.y*l+t.y;m=Math.min(m,i),u=Math.min(u,s),p=Math.max(p,i),v=Math.max(v,s)}h?(e=Math.min(e,m),i=Math.min(i,u),s=Math.max(s,p),n=Math.max(n,v)):(e=m,i=u,s=p,n=v,h=!0)}if(!h)return void(this._compositeDirty=!1);const a=Math.ceil(s-e),o=Math.ceil(n-i);this._compositeCache||(this._compositeCache=document.createElement("canvas"),this._compositeCacheCtx=this._compositeCache.getContext("2d",{alpha:!0})),this._lastCacheWidth===a&&this._lastCacheHeight===o||(this._compositeCache.width=a,this._compositeCache.height=o,this._lastCacheWidth=a,this._lastCacheHeight=o),this._cachedBoundsMinX=e,this._cachedBoundsMinY=i;const r=this._compositeCacheCtx;r.clearRect(0,0,a,o),r.save(),r.translate(-e,-i);for(const e of t)!e.visible||e.opacity<=0||(r.save(),e.render(r),r.restore());r.restore(),this._compositeDirty=!1}destroy(){super.destroy(),this._compositeCache=null,this._compositeCacheCtx=null}},exports.DocumentPlugin=d,exports.HistoryManager=class{executeCommand(t){t.execute(),this.addCommand(t)}addCommand(t){var e,i;this._redoStack=[];const s=this._undoStack[this._undoStack.length-1];if(s&&(null===(e=s.canMerge)||void 0===e?void 0:e.call(s,t))&&s.merge){const e=null!==(i=s.merge(t))&&void 0!==i?i:s;return void(e!==s&&(this._undoStack[this._undoStack.length-1]=e))}this._undoStack.push(t),this._undoStack.length>this._maxHistorySize&&this._undoStack.shift()}undo(){if(0===this._undoStack.length)return null;const t=this._undoStack.pop();return t.undo(),this._redoStack.push(t),t}redo(){if(0===this._redoStack.length)return null;const t=this._redoStack.pop();return t.execute(),this._undoStack.push(t),t}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}clear(){this._undoStack=[],this._redoStack=[]}setMaxHistorySize(t){this._maxHistorySize=Math.max(1,t),this._undoStack.length>this._maxHistorySize&&(this._undoStack=this._undoStack.slice(-this._maxHistorySize))}constructor(t){var e,i,s;this._undoStack=[],this._redoStack=[],this._maxHistorySize=null!==(e=null==t?void 0:t.maxHistorySize)&&void 0!==e?e:50,this._undoStack=null!==(i=null==t?void 0:t.undoStack)&&void 0!==i?i:[],this._redoStack=null!==(s=null==t?void 0:t.redoStack)&&void 0!==s?s:[]}},exports.InteractionPlugin=l,exports.LayerBase=a,exports.LayerManagerBase=_,exports.SnapshotCommand=g,exports.TopScreenLayerManager=class extends _{renderAllLayersIn(t){const e=t.topScreenContext;this._renderAllLayersIn(t,e)}},exports.ViewManager=class{get zoom(){return Math.exp(this._currentLogZ)}get minZoom(){return this._options.minZoom}get maxZoom(){return this._options.maxZoom}get dpr(){return this._dpr}use(t){return this._plugins.has(t.name)?(console.warn(`Plugin "${t.name}" is already installed.`),t):(this._plugins.set(t.name,t),t.install(this),t)}unuse(t){const e=this._plugins.get(t);e&&(e.destroy(),this._plugins.delete(t))}getPlugin(t){return this._plugins.get(t)}onUpdate(t){this._updateCallbacks.add(t)}offUpdate(t){this._updateCallbacks.delete(t)}onBeforeRender(t){this._beforeRenderCallbacks.add(t)}offBeforeRender(t){this._beforeRenderCallbacks.delete(t)}onAfterRender(t){this._afterRenderCallbacks.add(t)}offAfterRender(t){this._afterRenderCallbacks.delete(t)}requestRender(){this._needsRender=!0}_clampLog(t){return n(t,this.LOG_MIN,this.LOG_MAX)}_setTargetLogZoomAtScreen(t,e,i){Number.isFinite(i)&&(this._anchorX=t,this._anchorY=e,this._targetLogZ=this._clampLog(i),this._needsRender=!0)}zoomToAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,Math.log(i))}zoomToAtScreenRaw(t,e,i){if(!Number.isFinite(i))return;const s=Math.max(1e-8,this._options.minZoom),h=this._options.maxZoom,a=n(i,s,h),o=Math.exp(this._currentLogZ),r=a;if(!Number.isFinite(o)||o<=0)return;if(Math.abs(r-o)<1e-12)return;const c=Math.log(a);this._currentLogZ=c,this._targetLogZ=c;const _=r/o;this._tx=t-(t-this._tx)*_,this._ty=e-(e-this._ty)*_,this._needsRender=!0}zoomToAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomToAtScreen(s,n,i)}zoomByFactorAtScreen(t,e,i){if(i<=0||!Number.isFinite(i))return;const s=Math.log(i);this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+s)}zoomByLogAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+i)}zoomByFactorAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomByFactorAtScreen(s,n,i)}zoomInAtCenter(){const t=this.canvas.getBoundingClientRect(),e=t.width/2,i=t.height/2;this.zoomByFactorAtScreen(e,i,1.2)}zoomOutAtCenter(){const t=this.canvas.getBoundingClientRect(),e=t.width/2,i=t.height/2;this.zoomByFactorAtScreen(e,i,1/1.2)}panBy(t,e){this._tx+=t,this._ty+=e,this._needsRender=!0}setPan(t,e){this._tx=t,this._ty=e,this._needsRender=!0}setTransform(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._currentLogZ=Math.log(s),this._targetLogZ=this._currentLogZ,this._tx=e,this._ty=i,this._needsRender=!0}_ensureOffscreenSizeLike(t,e){t.width===e.width&&t.height===e.height||(t.width=e.width,t.height=e.height)}_loop(){if(this._isResizing)return void(this._raf=requestAnimationFrame(()=>this._loop()));const t=performance.now(),e=Math.max(1,t-this._lastFrameTs);this._lastFrameTs=t;const{approachKZoom:i}=this._options,s=Math.exp(this._currentLogZ),n=this._targetLogZ-this._currentLogZ,h=Math.abs(n)>1e-6;if(h){const t=1-Math.exp(-i*e);this._currentLogZ+=n*t}const a=Math.exp(this._currentLogZ);if(a!==s){const t=this._anchorX,e=this._anchorY,i=a/s;this._tx=t-(t-this._tx)*i,this._ty=e-(e-this._ty)*i}if(this._isResetting){const t=1-Math.exp(-this._options.approachKPan*e);this._tx+=(0-this._tx)*t,this._ty+=(0-this._ty)*t;const i=Math.abs(this._currentLogZ)<.001&&Math.abs(this._targetLogZ)<1e-6,s=Math.abs(this._tx)<.5&&Math.abs(this._ty)<.5;i&&s&&(this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._isResetting=!1)}for(const t of this._updateCallbacks)t(e);if(!(this._needsRender||h||this._isResetting))return void(this._raf=requestAnimationFrame(()=>this._loop()));this._needsRender=!1;const o=this.contentCanvas,r=this.contentContext,c=this.topScreenCanvas,_=this.topScreenContext,l=this.canvas,d=this.context;this._ensureOffscreenSizeLike(o,l),this._ensureOffscreenSizeLike(c,l),r.setTransform(1,0,0,1,0,0),_.setTransform(1,0,0,1,0,0),d.setTransform(1,0,0,1,0,0);const g=this._options.background;"string"==typeof g&&""!==g.trim()&&"transparent"!==g.toLowerCase()?(d.fillStyle=g,d.fillRect(0,0,l.width,l.height)):d.clearRect(0,0,l.width,l.height),r.clearRect(0,0,o.width,o.height),_.clearRect(0,0,c.width,c.height),r.setTransform(this._dpr*a,0,0,this._dpr*a,this._dpr*this._tx,this._dpr*this._ty);for(const t of this._beforeRenderCallbacks)t(r);this._render(this);for(const t of this._afterRenderCallbacks)t(r);d.drawImage(o,0,0),d.drawImage(c,0,0),this._raf=requestAnimationFrame(()=>this._loop())}applyWorldTransform(t){const e=Math.exp(this._currentLogZ);t.setTransform(this._dpr*e,0,0,this._dpr*e,this._dpr*this._tx,this._dpr*this._ty)}applyScreenTransform(t){t.setTransform(this._dpr,0,0,this._dpr,0,0)}getPixelColorAtScreen(t,e){const i=Math.floor(t*this._dpr),s=Math.floor(e*this._dpr);if(i<0||s<0||i>=this.canvas.width||s>=this.canvas.height)return{r:0,g:0,b:0,a:0,rgba:"rgba(0,0,0,0)",hex:"#000000"};const n=this.contentContext.getImageData(i,s,1,1).data,h=n[0],a=n[1],o=n[2],r=n[3]/255,c=t=>t.toString(16).padStart(2,"0"),_=`#${c(h)}${c(a)}${c(o)}`;return{r:h,g:a,b:o,a:r,rgba:`rgba(${h},${a},${o},${r.toFixed(3)})`,hex:_}}getPixelColorAtWorld(t,e){const{x:i,y:s}=this.toScreen(t,e);return this.getPixelColorAtScreen(i,s)}registerLayerManager(t){t&&(this._layerManagers.includes(t)||(this._layerManagers.push(t),this._needsRender=!0))}unregisterLayerManager(t){const e=this._layerManagers.indexOf(t);e>=0&&(this._layerManagers.splice(e,1),this._needsRender=!0)}getLayerManagers(){return[...this._layerManagers]}resetSmooth(){this._isResetting=!0,this._targetLogZ=0,this._needsRender=!0}resetInstant(){this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._needsRender=!0}toWorld(t,e){const i=Math.exp(this._currentLogZ);return{wx:(t-this._tx)/i,wy:(e-this._ty)/i}}toScreen(t,e){const i=Math.exp(this._currentLogZ);return{x:t*i+this._tx,y:e*i+this._ty}}getTransform(){return{zoom:Math.exp(this._currentLogZ),tx:this._tx,ty:this._ty}}getViewportBounds(){const t=Math.exp(this._currentLogZ),e=this.canvas.width/this._dpr,i=this.canvas.height/this._dpr,s=-this._tx/t,n=-this._ty/t,h=(e-this._tx)/t,a=(i-this._ty)/t;return{left:s,top:n,right:h,bottom:a,width:h-s,height:a-n}}setZoomRange(t,e){this._options.minZoom=t,this._options.maxZoom=e,this.LOG_MIN=Math.log(t),this.LOG_MAX=Math.log(e),this._targetLogZ=Math.min(this.LOG_MAX,Math.max(this.LOG_MIN,this._targetLogZ))}resizeToParent(){this._isResizing=!0;const t=(this.canvas.parentElement||this.canvas).getBoundingClientRect();this._dpr=Math.max(1,window.devicePixelRatio||1);const e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.canvas.width=Math.round(e*this._dpr),this.canvas.height=Math.round(i*this._dpr),this.canvas.style.width=`${e}px`,this.canvas.style.height=`${i}px`,this._ensureOffscreenSizeLike(this.contentCanvas,this.canvas),this._ensureOffscreenSizeLike(this.topScreenCanvas,this.canvas),clearTimeout(this._resizeReleaseTimer),this._resizeReleaseTimer=window.setTimeout(()=>{this._isResizing=!1},50)}destroy(){cancelAnimationFrame(this._raf);for(const t of this._plugins.values())t.destroy();this._plugins.clear(),this._resizeObserver&&this._resizeObserver.disconnect(),this._layerManagers=[],this._updateCallbacks.clear(),this._beforeRenderCallbacks.clear(),this._afterRenderCallbacks.clear()}constructor(t,e,i){this._layerManagers=[],this._plugins=new Map,this._isResetting=!1,this._isResizing=!1,this._needsRender=!0,this._raf=0,this._lastFrameTs=performance.now(),this._tx=0,this._ty=0,this._anchorX=0,this._anchorY=0,this._currentLogZ=Math.log(1),this._targetLogZ=Math.log(1),this._updateCallbacks=new Set,this._beforeRenderCallbacks=new Set,this._afterRenderCallbacks=new Set,this._dpr=Math.max(1,window.devicePixelRatio||1);const s=t.getContext("2d",{willReadFrequently:!0,alpha:!0});if(!s)throw new Error("2D context not available");this.canvas=t,this.context=s,this._render=e,this.contentCanvas=document.createElement("canvas"),this.contentCanvas.width=t.width,this.contentCanvas.height=t.height,this.contentContext=this.contentCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),this.topScreenCanvas=document.createElement("canvas"),this.topScreenCanvas.width=t.width,this.topScreenCanvas.height=t.height,this.topScreenContext=this.topScreenCanvas.getContext("2d",{alpha:!0}),this._options=Object.assign({minZoom:.5,maxZoom:10,approachKZoom:.022,approachKPan:.022,autoResize:!0,background:"#fff"},i),this.LOG_MIN=Math.log(this._options.minZoom),this.LOG_MAX=Math.log(this._options.maxZoom),this._options.autoResize&&(this._resizeObserver=new ResizeObserver(()=>this.resizeToParent()),this._resizeObserver.observe(this.canvas.parentElement||this.canvas)),this.resizeToParent(),this._lastFrameTs=performance.now(),this._raf=requestAnimationFrame(()=>this._loop())}},exports.createDocumentPlugin=function(t){return new d(t)},exports.createInteractionPlugin=function(t){return new l(t)},exports.createSnapshotCommand=function(t,e,i,s){return e&&i?new g(t,e,i,s):null};
@@ -0,0 +1 @@
1
+ function t(t,e,i,s){return new(i||(i=Promise))(function(n,h){function a(t){try{r(s.next(t))}catch(t){h(t)}}function o(t){try{r(s.throw(t))}catch(t){h(t)}}function r(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i(function(t){t(e)})).then(a,o)}r((s=s.apply(t,e||[])).next())})}function e(t,e,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(t):s?s.value:e.get(t)}function i(t,e,i,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,i):n?n.value=i:e.set(t,i),i}"function"==typeof SuppressedError&&SuppressedError;const s=(e,i)=>t(void 0,void 0,void 0,function*(){return new Promise((t,s)=>{const n=new Image;"string"==typeof e?(void 0!==i&&(n.crossOrigin=i),n.src=e):n.src=URL.createObjectURL(e),n.onload=()=>{t(n)},n.onerror=()=>{s(new Error("Image load failed"))}})}),n=(t,e,i)=>Math.min(Math.max(t,e),i);class h{get zoom(){return Math.exp(this._currentLogZ)}get minZoom(){return this._options.minZoom}get maxZoom(){return this._options.maxZoom}get dpr(){return this._dpr}use(t){return this._plugins.has(t.name)?(console.warn(`Plugin "${t.name}" is already installed.`),t):(this._plugins.set(t.name,t),t.install(this),t)}unuse(t){const e=this._plugins.get(t);e&&(e.destroy(),this._plugins.delete(t))}getPlugin(t){return this._plugins.get(t)}onUpdate(t){this._updateCallbacks.add(t)}offUpdate(t){this._updateCallbacks.delete(t)}onBeforeRender(t){this._beforeRenderCallbacks.add(t)}offBeforeRender(t){this._beforeRenderCallbacks.delete(t)}onAfterRender(t){this._afterRenderCallbacks.add(t)}offAfterRender(t){this._afterRenderCallbacks.delete(t)}requestRender(){this._needsRender=!0}_clampLog(t){return n(t,this.LOG_MIN,this.LOG_MAX)}_setTargetLogZoomAtScreen(t,e,i){Number.isFinite(i)&&(this._anchorX=t,this._anchorY=e,this._targetLogZ=this._clampLog(i),this._needsRender=!0)}zoomToAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,Math.log(i))}zoomToAtScreenRaw(t,e,i){if(!Number.isFinite(i))return;const s=Math.max(1e-8,this._options.minZoom),h=this._options.maxZoom,a=n(i,s,h),o=Math.exp(this._currentLogZ),r=a;if(!Number.isFinite(o)||o<=0)return;if(Math.abs(r-o)<1e-12)return;const c=Math.log(a);this._currentLogZ=c,this._targetLogZ=c;const _=r/o;this._tx=t-(t-this._tx)*_,this._ty=e-(e-this._ty)*_,this._needsRender=!0}zoomToAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomToAtScreen(s,n,i)}zoomByFactorAtScreen(t,e,i){if(i<=0||!Number.isFinite(i))return;const s=Math.log(i);this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+s)}zoomByLogAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+i)}zoomByFactorAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomByFactorAtScreen(s,n,i)}zoomInAtCenter(){const t=this.canvas.getBoundingClientRect(),e=t.width/2,i=t.height/2;this.zoomByFactorAtScreen(e,i,1.2)}zoomOutAtCenter(){const t=this.canvas.getBoundingClientRect(),e=t.width/2,i=t.height/2;this.zoomByFactorAtScreen(e,i,1/1.2)}panBy(t,e){this._tx+=t,this._ty+=e,this._needsRender=!0}setPan(t,e){this._tx=t,this._ty=e,this._needsRender=!0}setTransform(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._currentLogZ=Math.log(s),this._targetLogZ=this._currentLogZ,this._tx=e,this._ty=i,this._needsRender=!0}_ensureOffscreenSizeLike(t,e){t.width===e.width&&t.height===e.height||(t.width=e.width,t.height=e.height)}_loop(){if(this._isResizing)return void(this._raf=requestAnimationFrame(()=>this._loop()));const t=performance.now(),e=Math.max(1,t-this._lastFrameTs);this._lastFrameTs=t;const{approachKZoom:i}=this._options,s=Math.exp(this._currentLogZ),n=this._targetLogZ-this._currentLogZ,h=Math.abs(n)>1e-6;if(h){const t=1-Math.exp(-i*e);this._currentLogZ+=n*t}const a=Math.exp(this._currentLogZ);if(a!==s){const t=this._anchorX,e=this._anchorY,i=a/s;this._tx=t-(t-this._tx)*i,this._ty=e-(e-this._ty)*i}if(this._isResetting){const t=1-Math.exp(-this._options.approachKPan*e);this._tx+=(0-this._tx)*t,this._ty+=(0-this._ty)*t;const i=Math.abs(this._currentLogZ)<.001&&Math.abs(this._targetLogZ)<1e-6,s=Math.abs(this._tx)<.5&&Math.abs(this._ty)<.5;i&&s&&(this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._isResetting=!1)}for(const t of this._updateCallbacks)t(e);if(!(this._needsRender||h||this._isResetting))return void(this._raf=requestAnimationFrame(()=>this._loop()));this._needsRender=!1;const o=this.contentCanvas,r=this.contentContext,c=this.topScreenCanvas,_=this.topScreenContext,l=this.canvas,d=this.context;this._ensureOffscreenSizeLike(o,l),this._ensureOffscreenSizeLike(c,l),r.setTransform(1,0,0,1,0,0),_.setTransform(1,0,0,1,0,0),d.setTransform(1,0,0,1,0,0);const g=this._options.background;"string"==typeof g&&""!==g.trim()&&"transparent"!==g.toLowerCase()?(d.fillStyle=g,d.fillRect(0,0,l.width,l.height)):d.clearRect(0,0,l.width,l.height),r.clearRect(0,0,o.width,o.height),_.clearRect(0,0,c.width,c.height),r.setTransform(this._dpr*a,0,0,this._dpr*a,this._dpr*this._tx,this._dpr*this._ty);for(const t of this._beforeRenderCallbacks)t(r);this._render(this);for(const t of this._afterRenderCallbacks)t(r);d.drawImage(o,0,0),d.drawImage(c,0,0),this._raf=requestAnimationFrame(()=>this._loop())}applyWorldTransform(t){const e=Math.exp(this._currentLogZ);t.setTransform(this._dpr*e,0,0,this._dpr*e,this._dpr*this._tx,this._dpr*this._ty)}applyScreenTransform(t){t.setTransform(this._dpr,0,0,this._dpr,0,0)}getPixelColorAtScreen(t,e){const i=Math.floor(t*this._dpr),s=Math.floor(e*this._dpr);if(i<0||s<0||i>=this.canvas.width||s>=this.canvas.height)return{r:0,g:0,b:0,a:0,rgba:"rgba(0,0,0,0)",hex:"#000000"};const n=this.contentContext.getImageData(i,s,1,1).data,h=n[0],a=n[1],o=n[2],r=n[3]/255,c=t=>t.toString(16).padStart(2,"0"),_=`#${c(h)}${c(a)}${c(o)}`;return{r:h,g:a,b:o,a:r,rgba:`rgba(${h},${a},${o},${r.toFixed(3)})`,hex:_}}getPixelColorAtWorld(t,e){const{x:i,y:s}=this.toScreen(t,e);return this.getPixelColorAtScreen(i,s)}registerLayerManager(t){t&&(this._layerManagers.includes(t)||(this._layerManagers.push(t),this._needsRender=!0))}unregisterLayerManager(t){const e=this._layerManagers.indexOf(t);e>=0&&(this._layerManagers.splice(e,1),this._needsRender=!0)}getLayerManagers(){return[...this._layerManagers]}resetSmooth(){this._isResetting=!0,this._targetLogZ=0,this._needsRender=!0}resetInstant(){this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._needsRender=!0}toWorld(t,e){const i=Math.exp(this._currentLogZ);return{wx:(t-this._tx)/i,wy:(e-this._ty)/i}}toScreen(t,e){const i=Math.exp(this._currentLogZ);return{x:t*i+this._tx,y:e*i+this._ty}}getTransform(){return{zoom:Math.exp(this._currentLogZ),tx:this._tx,ty:this._ty}}getViewportBounds(){const t=Math.exp(this._currentLogZ),e=this.canvas.width/this._dpr,i=this.canvas.height/this._dpr,s=-this._tx/t,n=-this._ty/t,h=(e-this._tx)/t,a=(i-this._ty)/t;return{left:s,top:n,right:h,bottom:a,width:h-s,height:a-n}}setZoomRange(t,e){this._options.minZoom=t,this._options.maxZoom=e,this.LOG_MIN=Math.log(t),this.LOG_MAX=Math.log(e),this._targetLogZ=Math.min(this.LOG_MAX,Math.max(this.LOG_MIN,this._targetLogZ))}resizeToParent(){this._isResizing=!0;const t=(this.canvas.parentElement||this.canvas).getBoundingClientRect();this._dpr=Math.max(1,window.devicePixelRatio||1);const e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.canvas.width=Math.round(e*this._dpr),this.canvas.height=Math.round(i*this._dpr),this.canvas.style.width=`${e}px`,this.canvas.style.height=`${i}px`,this._ensureOffscreenSizeLike(this.contentCanvas,this.canvas),this._ensureOffscreenSizeLike(this.topScreenCanvas,this.canvas),clearTimeout(this._resizeReleaseTimer),this._resizeReleaseTimer=window.setTimeout(()=>{this._isResizing=!1},50)}destroy(){cancelAnimationFrame(this._raf);for(const t of this._plugins.values())t.destroy();this._plugins.clear(),this._resizeObserver&&this._resizeObserver.disconnect(),this._layerManagers=[],this._updateCallbacks.clear(),this._beforeRenderCallbacks.clear(),this._afterRenderCallbacks.clear()}constructor(t,e,i){this._layerManagers=[],this._plugins=new Map,this._isResetting=!1,this._isResizing=!1,this._needsRender=!0,this._raf=0,this._lastFrameTs=performance.now(),this._tx=0,this._ty=0,this._anchorX=0,this._anchorY=0,this._currentLogZ=Math.log(1),this._targetLogZ=Math.log(1),this._updateCallbacks=new Set,this._beforeRenderCallbacks=new Set,this._afterRenderCallbacks=new Set,this._dpr=Math.max(1,window.devicePixelRatio||1);const s=t.getContext("2d",{willReadFrequently:!0,alpha:!0});if(!s)throw new Error("2D context not available");this.canvas=t,this.context=s,this._render=e,this.contentCanvas=document.createElement("canvas"),this.contentCanvas.width=t.width,this.contentCanvas.height=t.height,this.contentContext=this.contentCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),this.topScreenCanvas=document.createElement("canvas"),this.topScreenCanvas.width=t.width,this.topScreenCanvas.height=t.height,this.topScreenContext=this.topScreenCanvas.getContext("2d",{alpha:!0}),this._options=Object.assign({minZoom:.5,maxZoom:10,approachKZoom:.022,approachKPan:.022,autoResize:!0,background:"#fff"},i),this.LOG_MIN=Math.log(this._options.minZoom),this.LOG_MAX=Math.log(this._options.maxZoom),this._options.autoResize&&(this._resizeObserver=new ResizeObserver(()=>this.resizeToParent()),this._resizeObserver.observe(this.canvas.parentElement||this.canvas)),this.resizeToParent(),this._lastFrameTs=performance.now(),this._raf=requestAnimationFrame(()=>this._loop())}}let a=0;class o{constructor(t,e,i="world"){this.space="world",this.visible=!0,this.opacity=1,this.blend="source-over",this.name=t,this.id=`layer_${e}_${++a}`,this.type=e,this.space=i}}class r extends o{beginStroke(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);this._lastX=i,this._lastY=s,this._drawing=!0}stroke(t,e,i,s,n=1,h="brush"){if(!this._drawing)return;const{lx:a,ly:o}=this.toLocalPoint(t,e);this.context.beginPath(),this.context.moveTo(this._lastX,this._lastY),this.context.lineTo(a,o),"eraser"===h?(this.context.globalCompositeOperation="destination-out",this.context.strokeStyle="rgba(0, 0, 0, 1)"):(this.context.globalCompositeOperation="source-over",this.context.strokeStyle=i),this.context.lineWidth=s*n,this.context.lineCap="round",this.context.lineJoin="round",this.context.stroke(),this.context.closePath(),this._lastX=a,this._lastY=o}endStroke(){this._drawing=!1}isDrawing(){return this._drawing}captureSnapshot(t){try{if(t){const{x:e,y:i,width:s,height:n}=t,h=Math.max(0,Math.floor(e)),a=Math.max(0,Math.floor(i)),o=Math.min(this.canvas.width-h,Math.ceil(s)),r=Math.min(this.canvas.height-a,Math.ceil(n));return o<=0||r<=0?null:this.context.getImageData(h,a,o,r)}return this.context.getImageData(0,0,this.canvas.width,this.canvas.height)}catch(t){return null}}restoreSnapshot(t,e){var i,s;const n=null!==(i=null==e?void 0:e.x)&&void 0!==i?i:0,h=null!==(s=null==e?void 0:e.y)&&void 0!==s?s:0;this.context.putImageData(t,n,h)}clearRegion(t){t?this.context.clearRect(t.x,t.y,t.width,t.height):this.context.clearRect(0,0,this.canvas.width,this.canvas.height)}requestRedraw(){var t;null===(t=this._redraw)||void 0===t||t.call(this,this.context,this.canvas)}drawImage(t,e,i,s,n){this.context.drawImage(t,e,i,null!=s?s:t.width,null!=n?n:t.height)}hitTest(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);return i>=0&&i<=this.canvas.width&&s>=0&&s<=this.canvas.height}toLocalPoint(t,e){const i=t-this.x,s=e-this.y,n=Math.cos(-this.rotation),h=Math.sin(-this.rotation),a=i*h+s*n,o=(i*n-s*h)/this.scale,r=a/this.scale;return{lx:o+("center"===this.anchor?this.canvas.width/2:0),ly:r+("center"===this.anchor?this.canvas.height/2:0)}}render(t,e){if(!this.visible)return;const i=this.canvas.width*this.scale,s=this.canvas.height*this.scale,n="center"===this.anchor?-i/2:0,h="center"===this.anchor?-s/2:0;t.save(),t.globalAlpha=this.opacity,t.globalCompositeOperation=this.blend,t.translate(this.x,this.y),t.rotate(this.rotation),t.drawImage(this.canvas,n,h,i,s),t.restore()}cropTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas(),n=Math.min(s.width,e),h=Math.min(s.height,i);this._setCanvasSize(e,i),n>0&&h>0&&this.context.drawImage(s,0,0,n,h,0,0,n,h)}resizeTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas();this._setCanvasSize(e,i),s.width>0&&s.height>0&&this.context.drawImage(s,0,0,s.width,s.height,0,0,e,i)}_cloneCanvas(){const t=document.createElement("canvas");if(t.width=this.canvas.width,t.height=this.canvas.height,0===t.width||0===t.height)return t;const e=t.getContext("2d");if(!e)throw new Error("Offscreen 2D context unavailable");return e.drawImage(this.canvas,0,0),t}_setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,t,e)}destroy(){this.canvas.width=0,this.canvas.height=0}constructor(t){var e,i;super(t.name||"","canvas",null!==(e=t.space)&&void 0!==e?e:"world"),this.x=0,this.y=0,this.scale=1,this.rotation=0,this.anchor="topLeft",this._drawing=!1,this._lastX=0,this._lastY=0,this.canvas=document.createElement("canvas"),this.canvas.width=t.width,this.canvas.height=t.height;const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Offscreen 2D context unavailable");this.context=s,this.x=t.x||0,this.y=t.y||0,this.scale=null!==(i=t.scale)&&void 0!==i?i:1,this.rotation=t.rotation||0,t.anchor&&(this.anchor=t.anchor),this._redraw=t.redraw,this._redraw&&this._redraw(this.context,this.canvas)}}var c;class _ extends r{static fromImage(e){return t(this,void 0,void 0,function*(){var t,n,h,a,o,r,l,d;const g=yield s(e.src,e.crossOrigin),m=null!==(t=e.width)&&void 0!==t?t:g.naturalWidth,u=null!==(n=e.height)&&void 0!==n?n:g.naturalHeight,p=new _({name:e.name,space:null!==(h=e.space)&&void 0!==h?h:"world",x:null!==(a=e.x)&&void 0!==a?a:0,y:null!==(o=e.y)&&void 0!==o?o:0,scale:null!==(r=e.scale)&&void 0!==r?r:1,rotation:null!==(l=e.rotation)&&void 0!==l?l:0,anchor:null!==(d=e.anchor)&&void 0!==d?d:"topLeft",width:m,height:u});return p.context.clearRect(0,0,p.canvas.width,p.canvas.height),p.context.drawImage(g,0,0,m,u),"string"!=typeof e.src&&i(p,c,g.src.startsWith("blob:")?g.src:null,"f"),p})}setSource(n,h){return t(this,void 0,void 0,function*(){const t=yield s(n,h);if(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.drawImage(t,0,0),e(this,c,"f")){try{URL.revokeObjectURL(e(this,c,"f"))}catch(t){}i(this,c,null,"f")}"string"!=typeof n&&i(this,c,t.src.startsWith("blob:")?t.src:null,"f")})}paint(t){t(this.context,this.canvas)}getImageData(t=0,e=0,i=this.canvas.width,s=this.canvas.height){return this.context.getImageData(t,e,i,s)}putImageData(t,e=0,i=0){this.context.putImageData(t,e,i)}toDataURL(t="image/png",e){return this.canvas.toDataURL(t,e)}toImageBitmap(t){return createImageBitmap(this.canvas,null!=t?t:{})}destroy(){var t;if(null===(t=super.destroy)||void 0===t||t.call(this),e(this,c,"f")){try{URL.revokeObjectURL(e(this,c,"f"))}catch(t){}i(this,c,null,"f")}}constructor(t){var e,i;super({name:t.name,space:null!==(e=t.space)&&void 0!==e?e:"world",x:t.x,y:t.y,scale:t.scale,rotation:t.rotation,anchor:null!==(i=t.anchor)&&void 0!==i?i:"topLeft",width:t.width,height:t.height}),c.set(this,null),this.type="bitmap"}}c=new WeakMap;class l{constructor(){this._worldLayers=[],this._screenLayers=[]}_renderAllLayersIn(t,e){e.save(),t.applyWorldTransform(e);for(const i of this._worldLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore(),e.save(),t.applyScreenTransform(e);for(const i of this._screenLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore()}addLayer(t,e){const i="world"===t.space?this._worldLayers:this._screenLayers;return"number"==typeof e&&e>=0&&e<i.length?(i.splice(e,0,t),t.id):(i.push(t),t.id)}createImageLayer(e){return t(this,void 0,void 0,function*(){const t=yield _.fromImage(e);return this.addLayer(t),t})}createCanvasLayer(t){const e=new r(t);return this.addLayer(e),e}removeLayer(t){var e,i,s,n;const h=this._worldLayers.findIndex(e=>e.id===t);if(h>=0)return null===(i=(e=this._worldLayers[h]).destroy)||void 0===i||i.call(e),void this._worldLayers.splice(h,1);const a=this._screenLayers.findIndex(e=>e.id===t);a>=0&&(null===(n=(s=this._screenLayers[a]).destroy)||void 0===n||n.call(s),this._screenLayers.splice(a,1))}moveLayer(t,e){const i=this._worldLayers.findIndex(e=>e.id===t);if(i>=0){const[t]=this._worldLayers.splice(i,1),s=Math.max(0,Math.min(e,this._worldLayers.length));return void this._worldLayers.splice(s,0,t)}const s=this._screenLayers.findIndex(e=>e.id===t);if(s>=0){const[t]=this._screenLayers.splice(s,1),i=Math.max(0,Math.min(e,this._screenLayers.length));this._screenLayers.splice(i,0,t)}}getLayer(t){return this._worldLayers.find(e=>e.id===t)||this._screenLayers.find(e=>e.id===t)}getAllLayers(t){return t?("world"===t?this._worldLayers:this._screenLayers).slice():[...this._worldLayers,...this._screenLayers]}hitTest(t,e,i="world"){const s=this.getAllLayers(i);for(let i=s.length-1;i>=0;i--){const n=s[i];if(n.hitTest&&n.hitTest(t,e))return n}}destroy(){var t;for(const e of[...this._worldLayers,...this._screenLayers])null===(t=e.destroy)||void 0===t||t.call(e);this._worldLayers=[],this._screenLayers=[]}}class d extends l{constructor(){super(...arguments),this._compositeCache=null,this._compositeCacheCtx=null,this._compositeDirty=!0,this._lastCacheWidth=0,this._lastCacheHeight=0,this._cachedBoundsMinX=0,this._cachedBoundsMinY=0}markDirty(){this._compositeDirty=!0}addLayer(t,e){return this._compositeDirty=!0,super.addLayer(t,e)}removeLayer(t){this._compositeDirty=!0,super.removeLayer(t)}moveLayer(t,e){this._compositeDirty=!0,super.moveLayer(t,e)}renderAllLayersIn(t){const e=t.contentContext,i=this._worldLayers;0!==i.length&&(this._compositeDirty&&this._rebuildCompositeCache(i),this._compositeCache&&this._compositeCacheCtx&&e.drawImage(this._compositeCache,this._cachedBoundsMinX,this._cachedBoundsMinY))}_rebuildCompositeCache(t){let e=0,i=0,s=0,n=0,h=!1;for(const a of t){const t=a,o=t.canvas.width*t.scale,r=t.canvas.height*t.scale,c="center"===t.anchor?-o/2:0,_="center"===t.anchor?-r/2:0,l=Math.cos(t.rotation),d=Math.sin(t.rotation),g=[{x:c,y:_},{x:c+o,y:_},{x:c,y:_+r},{x:c+o,y:_+r}];let m=1/0,u=1/0,p=-1/0,v=-1/0;for(const e of g){const i=e.x*l-e.y*d+t.x,s=e.x*d+e.y*l+t.y;m=Math.min(m,i),u=Math.min(u,s),p=Math.max(p,i),v=Math.max(v,s)}h?(e=Math.min(e,m),i=Math.min(i,u),s=Math.max(s,p),n=Math.max(n,v)):(e=m,i=u,s=p,n=v,h=!0)}if(!h)return void(this._compositeDirty=!1);const a=Math.ceil(s-e),o=Math.ceil(n-i);this._compositeCache||(this._compositeCache=document.createElement("canvas"),this._compositeCacheCtx=this._compositeCache.getContext("2d",{alpha:!0})),this._lastCacheWidth===a&&this._lastCacheHeight===o||(this._compositeCache.width=a,this._compositeCache.height=o,this._lastCacheWidth=a,this._lastCacheHeight=o),this._cachedBoundsMinX=e,this._cachedBoundsMinY=i;const r=this._compositeCacheCtx;r.clearRect(0,0,a,o),r.save(),r.translate(-e,-i);for(const e of t)!e.visible||e.opacity<=0||(r.save(),e.render(r),r.restore());r.restore(),this._compositeDirty=!1}destroy(){super.destroy(),this._compositeCache=null,this._compositeCacheCtx=null}}class g extends l{renderAllLayersIn(t){const e=t.topScreenContext;this._renderAllLayersIn(t,e)}}class m{constructor(t){this.name="interaction",this._view=null,this._dragging=!1,this._vx=0,this._vy=0,this._lastMoveTs=0,this._activePointerId=null,this._onDownBound=t=>this._onPointerDown(t),this._onMoveBound=t=>this._onPointerMove(t),this._onUpBound=()=>this._onPointerUp(),this._onWheelBound=t=>this._onWheel(t),this._onUpdate=t=>{if(!this._view)return;const{friction:e,stopSpeed:i}=this._options,s=Math.hypot(this._vx,this._vy)>=i;if(!this._dragging&&this._panEnabled&&s){const s=this._vx*t,n=this._vy*t;this._view.panBy(s,n),this._vx*=e,this._vy*=e,Math.hypot(this._vx,this._vy)<i&&(this._vx=0,this._vy=0)}else this._panEnabled||(this._vx=0,this._vy=0)},this._options=Object.assign({panEnabled:!0,zoomEnabled:!0,friction:.92,stopSpeed:.02,emaAlpha:.25,idleNoInertiaMs:120,wheelSensitivity:.0015},t),this._panEnabled=this._options.panEnabled,this._zoomEnabled=this._options.zoomEnabled}install(t){this._view=t;const e=t.canvas;e.addEventListener("wheel",this._onWheelBound,{passive:!1}),e.addEventListener("pointerdown",this._onDownBound),window.addEventListener("pointermove",this._onMoveBound),window.addEventListener("pointerup",this._onUpBound),t.onUpdate(this._onUpdate)}destroy(){if(!this._view)return;const t=this._view.canvas;t.removeEventListener("wheel",this._onWheelBound),t.removeEventListener("pointerdown",this._onDownBound),window.removeEventListener("pointermove",this._onMoveBound),window.removeEventListener("pointerup",this._onUpBound),this._view.offUpdate(this._onUpdate),this._view=null}isPanEnabled(){return this._panEnabled}isZoomEnabled(){return this._zoomEnabled}setPanEnabled(t){this._panEnabled!==t&&(this._panEnabled=t,t||(this._dragging=!1,this._vx=0,this._vy=0))}setZoomEnabled(t){this._zoomEnabled=t}setWheelSensitivity(t){this._options.wheelSensitivity=t}isDragging(){return this._dragging}_onPointerDown(t){var e;if(0===t.button&&this._panEnabled){this._dragging=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._activePointerId=t.pointerId;try{null===(e=this._view)||void 0===e||e.canvas.setPointerCapture(t.pointerId)}catch(t){}}}_onPointerMove(t){if(!this._dragging||!this._panEnabled||!this._view)return;const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.movementX,n=t.movementY;this._view.panBy(s,n);const h=this._options.emaAlpha,a=s/i,o=n/i;this._vx=(1-h)*this._vx+h*a,this._vy=(1-h)*this._vy+h*o}_onPointerUp(){if(!this._dragging)return;this._dragging=!1;const t=performance.now(),e=this._lastMoveTs?t-this._lastMoveTs:1/0;if(null!=this._activePointerId&&this._view){try{this._view.canvas.releasePointerCapture(this._activePointerId)}catch(t){}this._activePointerId=null}if(e>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,e/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}_getLineHeightPx(){if(!this._view)return 16;const t=getComputedStyle(this._view.canvas).lineHeight;if(!t||"normal"===t)return 16;const e=parseFloat(t);return Number.isFinite(e)?e:16}_normalizeWheelDelta(t){if(!this._view)return 0;let e=t.deltaY;if(1===t.deltaMode)e*=this._getLineHeightPx();else if(2===t.deltaMode){e*=this._view.canvas.clientHeight||window.innerHeight||800}return e}_onWheel(t){if(!this._zoomEnabled||!this._view)return;t.preventDefault(),t.stopPropagation();const e=this._normalizeWheelDelta(t),i=this._view.canvas.getBoundingClientRect(),s=t.clientX-i.left,n=t.clientY-i.top;let h=-e*this._options.wheelSensitivity;t.ctrlKey||t.metaKey?h*=1.6:t.shiftKey&&(h*=.6),this._view.zoomByLogAtScreen(s,n,h)}}function u(t){return new m(t)}class p{constructor(t){var e,i,s,n;this.name="document",this._view=null,this._enabled=!1,this._x=0,this._y=0,this._width=0,this._height=0,this._marginL=0,this._marginR=0,this._marginT=0,this._marginB=0,this._panClampMode="minVisible",this._onUpdate=()=>{this._enabled&&this._view&&this._clampPan()},this._onBeforeRender=t=>{this._enabled&&this._view&&(t.save(),t.beginPath(),t.rect(this._x,this._y,this._width,this._height),t.clip())},this._onAfterRender=t=>{if(this._enabled&&this._view&&(t.restore(),this._options.drawBorder)){const e=this._view.zoom;t.save(),t.lineWidth=1/e,t.strokeStyle="#cfcfcf",t.strokeRect(this._x,this._y,this._width,this._height),t.restore()}},this._options=Object.assign({rect:{x:0,y:0,width:0,height:0},margins:{},drawBorder:!1,minVisiblePx:30,panClampMode:"minVisible"},t),(null==t?void 0:t.rect)&&(this._enabled=!0,this._x=t.rect.x,this._y=t.rect.y,this._width=t.rect.width,this._height=t.rect.height),(null==t?void 0:t.margins)&&(this._marginL=null!==(e=t.margins.left)&&void 0!==e?e:0,this._marginR=null!==(i=t.margins.right)&&void 0!==i?i:0,this._marginT=null!==(s=t.margins.top)&&void 0!==s?s:0,this._marginB=null!==(n=t.margins.bottom)&&void 0!==n?n:0),this._panClampMode=this._options.panClampMode}install(t){this._view=t,t.onUpdate(this._onUpdate),t.onBeforeRender(this._onBeforeRender),t.onAfterRender(this._onAfterRender)}destroy(){this._view&&(this._view.offUpdate(this._onUpdate),this._view.offBeforeRender(this._onBeforeRender),this._view.offAfterRender(this._onAfterRender),this._view=null)}isEnabled(){return this._enabled}getRect(){return{x:this._x,y:this._y,width:this._width,height:this._height}}setRect(t,e,i,s){this._enabled=!0,this._x=t,this._y=e,this._width=i,this._height=s}clearRect(){this._enabled=!1}setMargins(t){var e,i,s,n;this._marginL=null!==(e=t.left)&&void 0!==e?e:this._marginL,this._marginR=null!==(i=t.right)&&void 0!==i?i:this._marginR,this._marginT=null!==(s=t.top)&&void 0!==s?s:this._marginT,this._marginB=null!==(n=t.bottom)&&void 0!==n?n:this._marginB}getMargins(){return{left:this._marginL,right:this._marginR,top:this._marginT,bottom:this._marginB}}setPanClampMode(t){this._panClampMode=t}getPanClampMode(){return this._panClampMode}cropTo(t){this._doResize("crop",t)}resizeTo(t){this._doResize("resize",t)}zoomToFit(t="contain"){if(!this._enabled||!this._view)return;const e=this._view.dpr,i=this._view.canvas.width/e,s=this._view.canvas.height/e,n=Math.max(1,i-(this._marginL+this._marginR)),h=Math.max(1,s-(this._marginT+this._marginB));let a;const o=n/this._width,r=h/this._height;a="contain"===t?Math.min(o,r):"cover"===t?Math.max(o,r):"fitWidth"===t?o:r,a=Math.min(this._view.maxZoom,Math.max(this._view.minZoom,a));const c=this._marginL+(n-a*this._width)/2,_=this._marginT+(h-a*this._height)/2,l=c-a*this._x,d=_-a*this._y;this._view.setTransform(a,l,d)}isPointInDocument(t,e){return!this._enabled||t>=this._x&&t<=this._x+this._width&&e>=this._y&&e<=this._y+this._height}_clampPan(){if(!this._view)return;const{zoom:t,tx:e,ty:i}=this._view.getTransform(),s=t,n=this._view.dpr,h=this._view.canvas.width/n,a=this._view.canvas.height/n,o=this._x,r=this._y,c=this._x+this._width,_=this._y+this._height;let l=e,d=i;if("margin"===this._panClampMode){const t=this._marginL-s*o,n=h-this._marginR-s*c,g=this._marginT-s*r,m=a-this._marginB-s*_,u=Math.max(1,h-(this._marginL+this._marginR)),p=Math.max(1,a-(this._marginT+this._marginB));l=s*this._width<=u?this._marginL+(u-s*this._width)/2-s*this._x:Math.min(t,Math.max(n,e)),d=s*this._height<=p?this._marginT+(p-s*this._height)/2-s*this._y:Math.min(g,Math.max(m,i))}else if("minVisible"===this._panClampMode){const t=s*this._width,n=s*this._height,g=Math.min(this._options.minVisiblePx,t),m=Math.min(this._options.minVisiblePx,n),u=h-g-s*o,p=g-s*c,v=a-m-s*r,w=m-s*_;l=p<=u?Math.min(u,Math.max(p,e)):(p+u)/2,d=w<=v?Math.min(v,Math.max(w,i)):(w+v)/2}l===e&&d===i||this._view.setPan(l,d)}_doResize(t,e){if(!this._view)return;const i=Math.max(1,Math.floor(e.width)),s=Math.max(1,Math.floor(e.height)),n={width:i,height:s},h=this._view.getLayerManagers();for(const e of h){const i=e.getAllLayers("world");for(const e of i){const i=e;"function"==typeof i.cropTo&&"function"==typeof i.resizeTo&&("crop"===t?i.cropTo(n):i.resizeTo(n))}}this._width=i,this._height=s,this._enabled&&this._clampPan()}}function v(t){return new p(t)}class w{constructor(t,e,i,s){this.type="snapshot",this._isExecuted=!0,this._target=t,this._beforeData=e,this._afterData=i,this._region=null==s?void 0:s.region}execute(){if(this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._afterData,t),this._isExecuted=!0}undo(){if(!this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._beforeData,t),this._isExecuted=!1}canMerge(){return!1}merge(){return this}}function f(t,e,i,s){return e&&i?new w(t,e,i,s):null}class y{executeCommand(t){t.execute(),this.addCommand(t)}addCommand(t){var e,i;this._redoStack=[];const s=this._undoStack[this._undoStack.length-1];if(s&&(null===(e=s.canMerge)||void 0===e?void 0:e.call(s,t))&&s.merge){const e=null!==(i=s.merge(t))&&void 0!==i?i:s;return void(e!==s&&(this._undoStack[this._undoStack.length-1]=e))}this._undoStack.push(t),this._undoStack.length>this._maxHistorySize&&this._undoStack.shift()}undo(){if(0===this._undoStack.length)return null;const t=this._undoStack.pop();return t.undo(),this._redoStack.push(t),t}redo(){if(0===this._redoStack.length)return null;const t=this._redoStack.pop();return t.execute(),this._undoStack.push(t),t}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}clear(){this._undoStack=[],this._redoStack=[]}setMaxHistorySize(t){this._maxHistorySize=Math.max(1,t),this._undoStack.length>this._maxHistorySize&&(this._undoStack=this._undoStack.slice(-this._maxHistorySize))}constructor(t){var e,i,s;this._undoStack=[],this._redoStack=[],this._maxHistorySize=null!==(e=null==t?void 0:t.maxHistorySize)&&void 0!==e?e:50,this._undoStack=null!==(i=null==t?void 0:t.undoStack)&&void 0!==i?i:[],this._redoStack=null!==(s=null==t?void 0:t.redoStack)&&void 0!==s?s:[]}}export{_ as BitmapLayer,r as CanvasLayer,d as ContentLayerManager,p as DocumentPlugin,y as HistoryManager,m as InteractionPlugin,o as LayerBase,l as LayerManagerBase,w as SnapshotCommand,g as TopScreenLayerManager,h as ViewManager,v as createDocumentPlugin,u as createInteractionPlugin,f as createSnapshotCommand};
@@ -0,0 +1,34 @@
1
+ import { ViewManager } from '../core/view-manager';
2
+ import { SpaceType } from '../types';
3
+ import { LayerBase } from './layer.base';
4
+ import { BitmapLayer, ICreateBitmapLayerOptions } from './layer.bitmap';
5
+ import { CanvasLayer, ICreateCanvasLayerOption } from './layer.canvas';
6
+ declare class LayerManagerBase {
7
+ protected _worldLayers: LayerBase[];
8
+ protected _screenLayers: LayerBase[];
9
+ /**
10
+ * Render all layers in target view.
11
+ */
12
+ protected _renderAllLayersIn(view: ViewManager, context: CanvasRenderingContext2D): void;
13
+ addLayer(layer: LayerBase, insertAt?: number): string;
14
+ createImageLayer(option: ICreateBitmapLayerOptions): Promise<BitmapLayer>;
15
+ createCanvasLayer(option: ICreateCanvasLayerOption): CanvasLayer;
16
+ removeLayer(id: string): void;
17
+ /**
18
+ * Move a layer from one index to another.
19
+ * Both indices are relative to the layer's space (world or screen).
20
+ */
21
+ moveLayer(id: string, toIndex: number): void;
22
+ getLayer(id: string): LayerBase | undefined;
23
+ getAllLayers(space?: SpaceType): LayerBase[];
24
+ /**
25
+ * Hit test all layers (top-first).
26
+ *
27
+ * @param x
28
+ * @param y
29
+ * @param space
30
+ */
31
+ hitTest(x: number, y: number, space?: 'world' | 'screen'): LayerBase | undefined;
32
+ destroy(): void;
33
+ }
34
+ export { LayerManagerBase };
@@ -0,0 +1,46 @@
1
+ import { ViewManager } from '../core/view-manager';
2
+ import { LayerManagerBase } from './layer-manager.base';
3
+ /**
4
+ * Content Layer Manager is used to store content bitmaps.
5
+ * Uses a composite cache to avoid re-rendering all layers every frame.
6
+ */
7
+ declare class ContentLayerManager extends LayerManagerBase {
8
+ private _compositeCache;
9
+ private _compositeCacheCtx;
10
+ private _compositeDirty;
11
+ private _lastCacheWidth;
12
+ private _lastCacheHeight;
13
+ private _cachedBoundsMinX;
14
+ private _cachedBoundsMinY;
15
+ /**
16
+ * Mark the composite cache as dirty.
17
+ * Call this when any layer content changes.
18
+ */
19
+ markDirty(): void;
20
+ /**
21
+ * Override addLayer to mark cache dirty.
22
+ */
23
+ addLayer(layer: import('./layer.base').LayerBase, insertAt?: number): string;
24
+ /**
25
+ * Override removeLayer to mark cache dirty.
26
+ */
27
+ removeLayer(id: string): void;
28
+ /**
29
+ * Override moveLayer to mark cache dirty.
30
+ */
31
+ moveLayer(id: string, toIndex: number): void;
32
+ /**
33
+ * Render all layers in target view.
34
+ * Uses composite cache for better performance with many layers.
35
+ */
36
+ renderAllLayersIn(view: ViewManager): void;
37
+ /**
38
+ * Rebuild the composite cache from all world layers.
39
+ */
40
+ private _rebuildCompositeCache;
41
+ /**
42
+ * Override destroy to clean up cache.
43
+ */
44
+ destroy(): void;
45
+ }
46
+ export { ContentLayerManager };
@@ -0,0 +1,13 @@
1
+ import { ViewManager } from '../core/view-manager';
2
+ import { LayerManagerBase } from './layer-manager.base';
3
+ /**
4
+ * Top Screen Layer Manager is used to store top screen overlays.
5
+ * If you have something like UI elements, just put it here.
6
+ */
7
+ declare class TopScreenLayerManager extends LayerManagerBase {
8
+ /**
9
+ * Render all layers in target view.
10
+ */
11
+ renderAllLayersIn(view: ViewManager): void;
12
+ }
13
+ export { TopScreenLayerManager };
@@ -0,0 +1,16 @@
1
+ import type { ViewManager } from '../core/view-manager';
2
+ import { BlendMode, SpaceType } from '../types';
3
+ declare abstract class LayerBase {
4
+ readonly id: string;
5
+ type: string;
6
+ name: string;
7
+ space: SpaceType;
8
+ visible: boolean;
9
+ opacity: number;
10
+ blend: BlendMode;
11
+ abstract render(context: CanvasRenderingContext2D, view?: ViewManager): void;
12
+ abstract destroy(): void;
13
+ abstract hitTest(x: number, y: number, view?: ViewManager): boolean;
14
+ protected constructor(name: string, type: string, space?: SpaceType);
15
+ }
16
+ export { LayerBase };
@@ -0,0 +1,37 @@
1
+ import { AnchorType, SpaceType } from '../types';
2
+ import { CanvasLayer } from './layer.canvas';
3
+ interface ICreateBitmapLayerOptions {
4
+ src: string | File | Blob;
5
+ width?: number;
6
+ height?: number;
7
+ name?: string;
8
+ x?: number;
9
+ y?: number;
10
+ scale?: number;
11
+ rotation?: number;
12
+ anchor?: AnchorType;
13
+ space?: SpaceType;
14
+ crossOrigin?: '' | 'anonymous' | 'use-credentials';
15
+ }
16
+ /**
17
+ * Image is used to load and display an image in world space.
18
+ */
19
+ declare class BitmapLayer extends CanvasLayer {
20
+ #private;
21
+ /** 从图片源创建位图层(会把像素绘入离屏) */
22
+ static fromImage(options: ICreateBitmapLayerOptions): Promise<BitmapLayer>;
23
+ /** 替换图源(尺寸会重配) */
24
+ setSource(src: string | File | Blob, crossOrigin?: '' | 'anonymous' | 'use-credentials'): Promise<void>;
25
+ /** 在位图上作画(提供 ctx) */
26
+ paint(fn: (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement) => void): void;
27
+ /** 读取/写回像素 */
28
+ getImageData(sx?: number, sy?: number, sw?: number, sh?: number): ImageData;
29
+ putImageData(img: ImageData, dx?: number, dy?: number): void;
30
+ /** 导出(PNG dataURL 或 ImageBitmap) */
31
+ toDataURL(type?: string, quality?: number): string;
32
+ toImageBitmap(opts?: ImageBitmapOptions): Promise<ImageBitmap>;
33
+ destroy(): void;
34
+ private constructor();
35
+ }
36
+ export { BitmapLayer };
37
+ export type { ICreateBitmapLayerOptions };
@@ -0,0 +1,116 @@
1
+ import type { ViewManager } from '../core/view-manager';
2
+ import { AnchorType, SpaceType } from '../types';
3
+ import { LayerBase } from './layer.base';
4
+ interface ICreateCanvasLayerOption {
5
+ name?: string;
6
+ width: number;
7
+ height: number;
8
+ /**
9
+ * The space of the layer, either 'world' or 'screen'.
10
+ *
11
+ * @default 'world'
12
+ */
13
+ space?: SpaceType;
14
+ x?: number;
15
+ y?: number;
16
+ scale?: number;
17
+ rotation?: number;
18
+ anchor?: AnchorType;
19
+ redraw?: (context: CanvasRenderingContext2D, canvas: HTMLCanvasElement) => void;
20
+ }
21
+ interface ILayerResizeConfig {
22
+ width: number;
23
+ height: number;
24
+ }
25
+ interface IRect {
26
+ x: number;
27
+ y: number;
28
+ width: number;
29
+ height: number;
30
+ }
31
+ /**
32
+ * CanvasLayer is used to create a layer with an offscreen canvas in either world or screen space.
33
+ * You can draw anything you want on the offscreen canvas, and it will be rendered as a layer.
34
+ */
35
+ declare class CanvasLayer extends LayerBase {
36
+ private readonly _redraw?;
37
+ readonly canvas: HTMLCanvasElement;
38
+ readonly context: CanvasRenderingContext2D;
39
+ x: number;
40
+ y: number;
41
+ scale: number;
42
+ rotation: number;
43
+ anchor: AnchorType;
44
+ private _drawing;
45
+ private _lastX;
46
+ private _lastY;
47
+ /**
48
+ * Begin a stroke at the given world coordinates.
49
+ */
50
+ beginStroke(wx: number, wy: number): void;
51
+ /**
52
+ * Continue a stroke to the given world coordinates.
53
+ */
54
+ stroke(wx: number, wy: number, color: string, size: number, pressure?: number, mode?: 'brush' | 'eraser'): void;
55
+ /**
56
+ * End the current stroke.
57
+ */
58
+ endStroke(): void;
59
+ /**
60
+ * Check if currently drawing.
61
+ */
62
+ isDrawing(): boolean;
63
+ /**
64
+ * Capture a snapshot of the canvas content.
65
+ * If region is provided, only that region is captured (more memory efficient).
66
+ * Returns null if capture fails.
67
+ */
68
+ captureSnapshot(region?: IRect): ImageData | null;
69
+ /**
70
+ * Restore a snapshot to the canvas.
71
+ * If position is provided, the snapshot is placed at that position.
72
+ * Otherwise, it's placed at (0, 0).
73
+ */
74
+ restoreSnapshot(data: ImageData, position?: {
75
+ x: number;
76
+ y: number;
77
+ }): void;
78
+ /**
79
+ * Clear a region of the canvas.
80
+ * If no region is provided, clears the entire canvas.
81
+ */
82
+ clearRegion(region?: IRect): void;
83
+ /**
84
+ * Request a redraw of the offscreen canvas.
85
+ * This will call the redraw function you provided in the constructor.
86
+ */
87
+ requestRedraw(): void;
88
+ /**
89
+ * Draw an image onto the offscreen canvas.
90
+ */
91
+ drawImage(image: HTMLImageElement | HTMLCanvasElement | ImageBitmap, dx: number, dy: number, dw?: number, dh?: number): void;
92
+ /**
93
+ * Hit test the layer.
94
+ * Returns true if the point (wx, wy) in world space is within the layer bounds.
95
+ */
96
+ hitTest(wx: number, wy: number): boolean;
97
+ /**
98
+ * Convert a point from world space to local layer space.
99
+ */
100
+ toLocalPoint(wx: number, wy: number): {
101
+ lx: number;
102
+ ly: number;
103
+ };
104
+ /**
105
+ * Render the layer onto the given context.
106
+ */
107
+ render(ctx: CanvasRenderingContext2D, view?: ViewManager): void;
108
+ cropTo(config: ILayerResizeConfig): void;
109
+ resizeTo(config: ILayerResizeConfig): void;
110
+ private _cloneCanvas;
111
+ private _setCanvasSize;
112
+ destroy(): void;
113
+ constructor(options: ICreateCanvasLayerOption);
114
+ }
115
+ export { CanvasLayer };
116
+ export type { ICreateCanvasLayerOption, ILayerResizeConfig, IRect };
@@ -0,0 +1,109 @@
1
+ import type { ViewManager } from '../../core/view-manager';
2
+ import type { ILayerResizeConfig } from '../../layer/layer.canvas';
3
+ import type { Plugin } from '../types';
4
+ type PanClampMode = 'margin' | 'minVisible';
5
+ interface DocumentPluginOptions {
6
+ /**
7
+ * Initial document rectangle (world coordinates).
8
+ */
9
+ rect?: {
10
+ x: number;
11
+ y: number;
12
+ width: number;
13
+ height: number;
14
+ };
15
+ /**
16
+ * Initial margins (CSS pixels).
17
+ */
18
+ margins?: {
19
+ left?: number;
20
+ right?: number;
21
+ top?: number;
22
+ bottom?: number;
23
+ };
24
+ /**
25
+ * Draw 1px border around document. Default false.
26
+ */
27
+ drawBorder?: boolean;
28
+ /**
29
+ * The min visible edge of the document in px when clamping pan. Default 30.
30
+ */
31
+ minVisiblePx?: number;
32
+ /**
33
+ * Pan clamp mode. Default 'minVisible'.
34
+ */
35
+ panClampMode?: PanClampMode;
36
+ }
37
+ /**
38
+ * Document Plugin
39
+ *
40
+ * Manages document bounds, margins, clipping, and pan clamping.
41
+ */
42
+ declare class DocumentPlugin implements Plugin {
43
+ readonly name = "document";
44
+ private _view;
45
+ private _options;
46
+ private _enabled;
47
+ private _x;
48
+ private _y;
49
+ private _width;
50
+ private _height;
51
+ private _marginL;
52
+ private _marginR;
53
+ private _marginT;
54
+ private _marginB;
55
+ private _panClampMode;
56
+ constructor(options?: DocumentPluginOptions);
57
+ install(view: ViewManager): void;
58
+ destroy(): void;
59
+ isEnabled(): boolean;
60
+ getRect(): {
61
+ x: number;
62
+ y: number;
63
+ width: number;
64
+ height: number;
65
+ };
66
+ setRect(x: number, y: number, width: number, height: number): void;
67
+ clearRect(): void;
68
+ setMargins(margins: {
69
+ left?: number;
70
+ right?: number;
71
+ top?: number;
72
+ bottom?: number;
73
+ }): void;
74
+ getMargins(): {
75
+ left: number;
76
+ right: number;
77
+ top: number;
78
+ bottom: number;
79
+ };
80
+ setPanClampMode(mode: PanClampMode): void;
81
+ getPanClampMode(): PanClampMode;
82
+ /**
83
+ * Crop document and all world layers to the specified size.
84
+ */
85
+ cropTo(config: ILayerResizeConfig): void;
86
+ /**
87
+ * Resize document and all world layers to the specified size.
88
+ */
89
+ resizeTo(config: ILayerResizeConfig): void;
90
+ /**
91
+ * Zoom to fit the document in the viewport.
92
+ */
93
+ zoomToFit(mode?: 'contain' | 'cover' | 'fitWidth' | 'fitHeight'): void;
94
+ /**
95
+ * Check if a world point is inside the document.
96
+ */
97
+ isPointInDocument(wx: number, wy: number): boolean;
98
+ private _onUpdate;
99
+ private _onBeforeRender;
100
+ private _onAfterRender;
101
+ private _clampPan;
102
+ private _doResize;
103
+ }
104
+ /**
105
+ * Create a document plugin instance.
106
+ */
107
+ declare function createDocumentPlugin(options?: DocumentPluginOptions): DocumentPlugin;
108
+ export { DocumentPlugin, createDocumentPlugin };
109
+ export type { DocumentPluginOptions, PanClampMode };
@@ -0,0 +1,68 @@
1
+ import type { ICommand } from './types';
2
+ /**
3
+ * 历史管理器:管理撤销/重做操作的命令栈
4
+ */
5
+ declare class HistoryManager {
6
+ private _maxHistorySize;
7
+ private _undoStack;
8
+ private _redoStack;
9
+ /**
10
+ * 执行命令并记录到历史
11
+ * 用于需要执行+记录的场景(如从外部触发的命令)
12
+ */
13
+ executeCommand(command: ICommand): void;
14
+ /**
15
+ * 将已执行的命令添加到历史记录
16
+ * 用于实时绘制场景(命令已经通过其他方式执行完成)
17
+ */
18
+ addCommand(command: ICommand): void;
19
+ /**
20
+ * 撤销操作
21
+ */
22
+ undo(): ICommand | null;
23
+ /**
24
+ * 重做操作
25
+ */
26
+ redo(): ICommand | null;
27
+ /**
28
+ * 检查是否可以撤销
29
+ */
30
+ canUndo(): boolean;
31
+ /**
32
+ * 检查是否可以重做
33
+ */
34
+ canRedo(): boolean;
35
+ /**
36
+ * 清空所有历史
37
+ */
38
+ clear(): void;
39
+ /**
40
+ * 设置最大历史大小
41
+ */
42
+ setMaxHistorySize(size: number): void;
43
+ constructor(options?: {
44
+ /**
45
+ * Maximum number of commands to keep in history.
46
+ *
47
+ * @default 50
48
+ */
49
+ maxHistorySize?: number;
50
+ /**
51
+ * You can optionally provide initial undo and redo stacks.
52
+ * This is useful in some situations like loading from a saved state,
53
+ * or already having a Vue reactive array to use.
54
+ *
55
+ * @default []
56
+ */
57
+ undoStack?: ICommand[];
58
+ /**
59
+ * You can optionally provide initial undo and redo stacks.
60
+ * This is useful in some situations like loading from a saved state,
61
+ * or already having a Vue reactive array to use.
62
+ *
63
+ * @default []
64
+ */
65
+ redoStack?: ICommand[];
66
+ });
67
+ }
68
+ export { HistoryManager };
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './snapshot-command';
3
+ export * from './history-manager';