dytools-canvas-engine 1.0.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/LICENSE +3 -0
- package/dist/index.cjs +7 -0
- package/dist/index.js +7 -0
- package/package.json +18 -0
package/LICENSE
ADDED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";var Q=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ae=Object.prototype.hasOwnProperty;var re=(b,e)=>{for(var t in e)Q(b,t,{get:e[t],enumerable:!0})},le=(b,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of oe(e))!ae.call(b,i)&&i!==t&&Q(b,i,{get:()=>e[i],enumerable:!(s=se(e,i))||s.enumerable});return b};var ce=b=>le(Q({},"__esModule",{value:!0}),b);var de={};re(de,{ApiTool:()=>q,CanvasEngine:()=>te,CircleObject:()=>Y,ClickGestureRecognizer:()=>$,DomEventSource:()=>B,DragGestureRecognizer:()=>N,DrawingTool:()=>F,EngineEventType:()=>g,HoverTool:()=>H,LassoTool:()=>W,MoveTool:()=>A,Point:()=>h,Polygon:()=>M,PolygonObject:()=>U,Rectangle:()=>E,ResizeTool:()=>V,SelectTool:()=>L,Size:()=>w,ToolLockManager:()=>D,Vector:()=>f,Zone:()=>X});module.exports=ce(de);var Z=class Z{constructor(e,t,s,i,n,r,o,a,l,c){this._name=null;this._showName=!1;this._nameAnchor="TopLeft";this._visible=!0;if(this._id=e,t instanceof E){let d=t,p=s??"#000000",v=i??!1,z=n??!1,I=r??!1,_=o??0;this._rect=d,this._color=p,this._selectable=v,this._movable=z,this._resizable=I,this._zIndex=_}else{let d=t,p=s,v=i,z=n,I=r??"#000000",_=o??!1,R=a??!1,O=l??!1,S=c??0;this._rect=new E(new h(d,p),new w(v,z)),this._color=I,this._selectable=_,this._movable=R,this._resizable=O,this._zIndex=S}}get id(){return this._id}set id(e){this._id=e}get rect(){return this._rect.normalized()}get name(){return this._name}set name(e){this._name=e}get showName(){return this._showName}set showName(e){this._showName=e}get nameAnchor(){return this._nameAnchor}set nameAnchor(e){this._nameAnchor=e}get zIndex(){return this._zIndex}set zIndex(e){this._zIndex=e}get visible(){return this._visible??!1}set visible(e){this._visible=e}get color(){return this._color}set color(e){this._color=e}get selectable(){return this._selectable}set selectable(e){this._selectable=e}get movable(){return this._movable}set movable(e){this._movable=e}get resizable(){return this._resizable}set resizable(e){this._resizable=e}getBounds(){return this._rect}getOuterBounds(){let e=this._rect,t=this.getResizeHandles();return t.length===0||t.forEach(s=>{e=e.expand(s.rect)}),e}getEventInteractions(e){let t=[];if(this._resizable&&this.getResizeHandles().forEach(i=>{(e===null||i.rect.contains(e))&&t.push({eventTypePrefix:"resize",handleIndex:i.handleIndex})}),this._movable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"move"})}if(this._selectable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"select"})}return t}getResizeHandles(){let e=this._rect.origin.x,t=this._rect.origin.y,s=this._rect.size.width,i=this._rect.size.height,n=Z.HANDLE_SIZE,r=n*10,o=n*6,a=1;s>=r&&i>=r?a=-1:s>=o&&i>=o&&(a=0);let l=s<o,c=i<o;return[{rect:new E(new h(e-a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:0},l?null:{rect:new E(new h(e+s/2-n,t-a*n-n),new w(n*2,n*2)),handleIndex:1},{rect:new E(new h(e+s+a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:2},c?null:{rect:new E(new h(e+s+a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:3},{rect:new E(new h(e+s+a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:4},l?null:{rect:new E(new h(e+s/2-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:5},{rect:new E(new h(e-a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:6},c?null:{rect:new E(new h(e-a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:7}].filter(p=>p!==null)}handleEvent(e,t){let s=e.data||{};if(e.type==="setcolor"&&this._color!==s.color){let n=this._color;this._color=s.color,t(g.ObjectColorChanged,{object:this,oldColor:n,newColor:this._color});return}if(e.type==="setzindex"&&this._zIndex!==s.zIndex){let n=this._zIndex;this._zIndex=s.zIndex,t(g.ObjectZIndexChanged,{object:this,oldZIndex:n,newZIndex:this._zIndex});return}if(e.type==="setselectable"&&this._selectable!==s.isSelectable){let n=this._selectable;this._selectable=s.isSelectable,t(g.ObjectSelectableChanged,{object:this,oldSelectable:n,newSelectable:this._selectable});return}if(e.type==="setmovable"&&this._movable!==s.isMovable){let n=this._movable;this._movable=s.isMovable,t(g.ObjectMovableChanged,{object:this,oldMovable:n,newMovable:this._movable});return}if(e.type==="setresizable"&&this._resizable!==s.isResizable){let n=this._resizable;this._resizable=s.isResizable,t(g.ObjectResizableChanged,{object:this,oldResizable:n,newResizable:this._resizable});return}if(e.type==="setvisible"&&this._visible!==s.isVisible){let n=this._visible??!0;this._visible=s.isVisible,t(g.ObjectVisibleChanged,{object:this,oldVisible:n,newVisible:this._visible??!0});return}let i=s.delta;if(e.type==="resize"){let n=this._rect.clone(),r=s.handleIndex;if(i==null||r==null){console.warn("Resize event missing required data:",e);return}let o=-1/0,a=i.x,l=i.y;if(a===0&&l===0)return;switch(r){case 0:a=Math.min(a,this._rect.size.width-o),l=Math.min(l,this._rect.size.height-o),this._rect.origin.x+=a,this._rect.origin.y+=l,this._rect.size.width-=a,this._rect.size.height-=l;break;case 1:l=Math.min(l,this._rect.size.height-o),this._rect.origin.y+=l,this._rect.size.height-=l;break;case 2:a=Math.max(a,o-this._rect.size.width),l=Math.min(l,this._rect.size.height-o),this._rect.origin.y+=l,this._rect.size.width+=a,this._rect.size.height-=l;break;case 3:a=Math.max(a,o-this._rect.size.width),this._rect.size.width+=a;break;case 4:a=Math.max(a,o-this._rect.size.width),l=Math.max(l,o-this._rect.size.height),this._rect.size.width+=a,this._rect.size.height+=l;break;case 5:l=Math.max(l,o-this._rect.size.height),this._rect.size.height+=l;break;case 6:a=Math.min(a,this._rect.size.width-o),l=Math.max(l,o-this._rect.size.height),this._rect.origin.x+=a,this._rect.size.width-=a,this._rect.size.height+=l;break;case 7:a=Math.min(a,this._rect.size.width-o),this._rect.origin.x+=a,this._rect.size.width-=a;break}t(g.ObjectResized,{object:this,oldSize:n.size,newSize:this._rect.clone().size}),t(g.ObjectPositionChanged,{object:this,oldPosition:n,newPosition:this._rect.clone()})}else e.type==="resizeend"&&this._rect.normalize();if(e.type.startsWith("move")){if(i==null){console.warn("Move event missing required data:",e);return}if(i.x===0&&i.y===0)return;let n=this._rect.clone();this._rect=this._rect.move(i),t(g.ObjectMoved,{object:this,oldPoint:n.origin,newPoint:this._rect.clone().origin}),t(g.ObjectPositionChanged,{object:this,oldPosition:n,newPosition:this._rect})}}render(e,t){let s=t.has("selected"),i=t.has("hovered"),n=t.has("hoversibling"),o=e.getTransform().a,a=u=>u/o,l=a(4),c=a(2),d=a(3),p=a(4),v=this._rect,z=v.origin.x,I=v.origin.y,_=v.size.width,R=v.size.height,O=(u,m,j,y,P)=>{let x=Math.max(0,Math.min(P,Math.min(j,y)/2)),T=new Path2D;return T.moveTo(u+x,m),T.lineTo(u+j-x,m),T.arcTo(u+j,m,u+j,m+x,x),T.lineTo(u+j,m+y-x),T.arcTo(u+j,m+y,u+j-x,m+y,x),T.lineTo(u+x,m+y),T.arcTo(u,m+y,u,m+y-x,x),T.lineTo(u,m+x),T.arcTo(u,m,u+x,m,x),T.closePath(),T},S=O(z,I,_,R,l);e.save(),e.strokeStyle=this._color;let C=e.strokeStyle;if(e.fillStyle=this.withAlpha(C,.06),e.fill(S),e.lineWidth=c,e.stroke(S),e.restore(),s){let u=z-p,m=I-p,j=_+p*2,y=R+p*2,P=O(u,m,j,y,l+p);e.save(),e.setLineDash([a(8),a(6)]),e.lineDashOffset=0,e.strokeStyle="rgba(0,0,0,0.4)",e.lineWidth=d,e.stroke(P),e.restore()}if(this._showName&&this._name){e.save(),e.font="12px sans-serif",e.fillStyle=this._color,e.textBaseline="top";let u=2,{x:m,y:j}=this._rect.origin,{width:y,height:P}=this._rect.size,x=m+u,T=j+u;switch(this._nameAnchor){case"TopLeft":x=m+u,T=j+u;break;case"TopRight":x=m+y-e.measureText(this._name).width-u,T=j+u;break;case"BottomLeft":x=m+u,T=j+P-14-u;break;case"BottomRight":x=m+y-e.measureText(this._name).width-u,T=j+P-14-u;break;case"Center":x=m+(y-e.measureText(this._name).width)/2,T=j+(P-12)/2;break}e.fillText(this._name,x,T),e.restore()}if(this._resizable&&i){e.save(),e.lineWidth=a(n?.5:1),e.strokeStyle=C,e.fillStyle=n?"transparent":"white",e.globalAlpha=n?.75:1;for(let u of this.getResizeHandles()||[]){if(!u)continue;let{x:m,y:j}=u.rect.origin,{width:y,height:P}=u.rect.size,x=a(4),T=O(m,j,y,P,x);e.fill(T),e.stroke(T)}e.restore()}}withAlpha(e,t){let s=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\s*\)/i);if(s){let i=parseInt(s[1]??"0",10),n=parseInt(s[2]??"0",10),r=parseInt(s[3]??"0",10);return`rgba(${i},${n},${r},${t})`}if(e.startsWith("#")){let i=e.slice(1);if(i.length===3&&(i=i.split("").map(n=>n+n).join("")),i.length===6||i.length===8){let n=parseInt(i.slice(0,2),16),r=parseInt(i.slice(2,4),16),o=parseInt(i.slice(4,6),16);return`rgba(${n},${r},${o},${t})`}}return e}};Z.HANDLE_SIZE=6;var X=Z,K=class K{constructor(e,t,s,i,n,r,o,a,l){this._name=null;this._showName=!1;this._visible=!0;if(this._id=e,t instanceof h){let c=t,d=s,p=i??"#000000",v=n??!1,z=r??!1,I=o??!1,_=a??0;this._center=c,this._radius=d,this._color=p,this._selectable=v,this._movable=z,this._resizable=I,this._zIndex=_}else{let c=t,d=s,p=i,v=n??"#000000",z=r??!1,I=o??!1,_=a??!1,R=l??0;this._center=new h(c,d),this._radius=p,this._color=v,this._selectable=z,this._movable=I,this._resizable=_,this._zIndex=R}}get id(){return this._id}set id(e){this._id=e}get center(){return this._center}get name(){return this._name}set name(e){this._name=e}get showName(){return this._showName}set showName(e){this._showName=e}get zIndex(){return this._zIndex}set zIndex(e){this._zIndex=e}get visible(){return this._visible??!1}set visible(e){this._visible=e}get color(){return this._color}set color(e){this._color=e}get selectable(){return this._selectable}set selectable(e){this._selectable=e}get movable(){return this._movable}set movable(e){this._movable=e}get resizable(){return this._resizable}set resizable(e){this._resizable=e}getBounds(){return new E(this.center.x-this._radius,this.center.y-this._radius,2*this._radius,2*this._radius)}getOuterBounds(){let e=this.getBounds(),t=this.getResizeHandles();return t.length===0||t.forEach(s=>{e=e.expand(s.rect)}),e}getEventInteractions(e){let t=[];if(this._resizable&&this.getResizeHandles().forEach(i=>{(e===null||i.rect.contains(e))&&t.push({eventTypePrefix:"resize",handleIndex:i.handleIndex})}),this._movable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"move"})}if(this._selectable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"select"})}return t}getResizeHandles(){let e=this.getBounds().origin.x,t=this.getBounds().origin.y,s=this.getBounds().size.width,i=this.getBounds().size.height,n=K.HANDLE_SIZE,r=n*10,o=n*6,a=1;s>=r&&i>=r?a=-1:s>=o&&i>=o&&(a=0);let l=s<o,c=i<o;return[{rect:new E(new h(e-a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:0},l?null:{rect:new E(new h(e+s/2-n,t-a*n-n),new w(n*2,n*2)),handleIndex:1},{rect:new E(new h(e+s+a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:2},c?null:{rect:new E(new h(e+s+a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:3},{rect:new E(new h(e+s+a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:4},l?null:{rect:new E(new h(e+s/2-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:5},{rect:new E(new h(e-a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:6},c?null:{rect:new E(new h(e-a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:7}].filter(p=>p!==null)}handleEvent(e,t){let s=e.data||{};if(e.type==="setcolor"){let i=this._color;this._color=s.color,t(g.ObjectColorChanged,{object:this,oldColor:i,newColor:this._color});return}if(e.type==="setzindex"){let i=this._zIndex;this._zIndex=s.zIndex,t(g.ObjectZIndexChanged,{object:this,oldZIndex:i,newZIndex:this._zIndex});return}if(e.type==="setselectable"){let i=this._selectable;this._selectable=s.isSelectable,t(g.ObjectSelectableChanged,{object:this,oldSelectable:i,newSelectable:this._selectable});return}if(e.type==="setmovable"){let i=this._movable;this._movable=s.isMovable,t(g.ObjectMovableChanged,{object:this,oldMovable:i,newMovable:this._movable});return}if(e.type==="setresizable"){let i=this._resizable;this._resizable=s.isResizable,t(g.ObjectResizableChanged,{object:this,oldResizable:i,newResizable:this._resizable});return}if(e.type==="setvisible"){let i=this._visible??!0;this._visible=s.isVisible,t(g.ObjectVisibleChanged,{object:this,oldVisible:i,newVisible:this._visible??!0});return}}render(e,t){let s=t.has("selected"),i=t.has("hovered"),n=t.has("hoversibling"),o=e.getTransform().a,a=O=>O/o,l=this._center.x,c=this._center.y,d=this._radius,p=a(4),v=a(2),z=a(3),I=a(4),_=this.color,R=this.withAlpha(_,.06);if(e.save(),e.beginPath(),e.arc(l,c,d,0,Math.PI*2),e.fillStyle=R,e.strokeStyle=_,e.lineWidth=v,e.fill(),e.stroke(),e.restore(),s&&(e.save(),e.beginPath(),e.arc(l,c,d+I,0,Math.PI*2),e.setLineDash([a(8),a(6)]),e.strokeStyle="rgba(0,0,0,0.4)",e.lineWidth=z,e.stroke(),e.restore()),this._resizable&&i){let O=this.getResizeHandles?.()??[];e.save(),e.lineWidth=a(n?.5:1),e.strokeStyle=_,e.fillStyle=n?"transparent":"white",e.globalAlpha=n?.75:1;for(let S of O){let C=S.rect.origin.x,u=S.rect.origin.y,m=S.rect.size.width,j=S.rect.size.height,y=a(4),P=new Path2D;P.moveTo(C+y,u),P.lineTo(C+m-y,u),P.arcTo(C+m,u,C+m,u+y,y),P.lineTo(C+m,u+j-y),P.arcTo(C+m,u+j,C+m-y,u+j,y),P.lineTo(C+y,u+j),P.arcTo(C,u+j,C,u+j-y,y),P.lineTo(C,u+y),P.arcTo(C,u,C+y,u,y),P.closePath(),e.fill(P),e.stroke(P)}e.restore()}}withAlpha(e,t){let s=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\s*\)/i);if(s){let i=parseInt(s[1]??"0",10),n=parseInt(s[2]??"0",10),r=parseInt(s[3]??"0",10);return`rgba(${i},${n},${r},${t})`}if(e.startsWith("#")){let i=e.slice(1);if(i.length===3&&(i=i.split("").map(n=>n+n).join("")),i.length===6||i.length===8){let n=parseInt(i.slice(0,2),16),r=parseInt(i.slice(2,4),16),o=parseInt(i.slice(4,6),16);return`rgba(${n},${r},${o},${t})`}}return e}};K.HANDLE_SIZE=6;var Y=K,U=class{constructor(e,t,s,i,n,r){this.visible=!0;this.id=e,this._points=t?t.slice():[],this.color=s??"#000000",this.selectable=i??!1,this.movable=n??!1,this.zIndex=r??0}get points(){return this._points}getBounds(){if(!this._points||this._points.length===0)return new E(new h(0,0),new w(0,0));let e=this._points[0].x,t=this._points[0].x,s=this._points[0].y,i=this._points[0].y;for(let n of this._points)n.x<e&&(e=n.x),n.x>t&&(t=n.x),n.y<s&&(s=n.y),n.y>i&&(i=n.y);return new E(new h(e,s),new w(t-e,i-s))}getOuterBounds(){return this.getBounds()}getEventInteractions(e){let t=[],s=this.getBounds();return this.movable&&(e===null||s.contains(e))&&t.push({eventTypePrefix:"move"}),this.selectable&&(e===null||s.contains(e))&&t.push({eventTypePrefix:"select"}),t}handleEvent(e,t){let s=e.data||{};if(e.type==="setcolor"){let i=this.color;this.color=s.color,t(g.ObjectColorChanged,{object:this,oldColor:i,newColor:this.color});return}if(e.type==="setzindex"){let i=this.zIndex;this.zIndex=s.zIndex,t(g.ObjectZIndexChanged,{object:this,oldZIndex:i,newZIndex:this.zIndex});return}if(e.type==="setselectable"){let i=this.selectable;this.selectable=s.isSelectable,t(g.ObjectSelectableChanged,{object:this,oldSelectable:i,newSelectable:this.selectable});return}if(e.type==="setmovable"){let i=this.movable;this.movable=s.isMovable,t(g.ObjectMovableChanged,{object:this,oldMovable:i,newMovable:this.movable});return}if(e.type==="setvisible"){let i=this.visible;this.visible=s.isVisible,t(g.ObjectVisibleChanged,{object:this,oldVisible:i,newVisible:this.visible});return}if(e.type.startsWith("move")){let i=s.delta;if(i==null){console.warn("Move event missing required data:",e);return}let n=this.getBounds();for(let o of this._points)o.x+=i.x,o.y+=i.y;let r=this.getBounds();t(g.ObjectMoved,{object:this,oldPoint:n.origin,newPoint:r.origin}),t(g.ObjectPositionChanged,{object:this,oldPosition:n,newPosition:r});return}}render(e,t){let s=t.has("selected"),i=t.has("hovered"),r=e.getTransform().a,o=p=>p/r,l=(()=>{if(!this._points||this._points.length===0)return null;let p=new Path2D;p.moveTo(this._points[0].x,this._points[0].y);for(let v=1;v<this._points.length;++v)p.lineTo(this._points[v].x,this._points[v].y);return p.closePath(),p})();if(!l)return;let c=this.getBounds();e.save(),e.strokeStyle=this.color;let d=e.strokeStyle;if(e.fillStyle=this.withAlpha(d,.06),e.lineWidth=o(2),e.fill(l),e.stroke(l),e.restore(),s){let p=o(3),v=o(4),z=c.origin.x-v,I=c.origin.y-v,_=c.size.width+v*2,R=c.size.height+v*2;e.save(),e.setLineDash([o(8),o(6)]),e.lineDashOffset=0,e.strokeStyle="rgba(0,0,0,0.4)",e.lineWidth=p,e.strokeRect(z,I,_,R),e.restore()}}withAlpha(e,t){let s=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\s*\)/i);if(s){let i=parseInt(s[1]??"0",10),n=parseInt(s[2]??"0",10),r=parseInt(s[3]??"0",10);return`rgba(${i},${n},${r},${t})`}if(e.startsWith("#")){let i=e.slice(1);if(i.length===3&&(i=i.split("").map(n=>n+n).join("")),i.length===6||i.length===8){let n=parseInt(i.slice(0,2),16),r=parseInt(i.slice(2,4),16),o=parseInt(i.slice(4,6),16);return`rgba(${n},${r},${o},${t})`}}return e}},G=class{constructor(e=1e3){this.intervalId=null;this.interval=e,this.intervalId=null}attach(e,t){this.start(e)}detach(){this.stop()}start(e){this.intervalId=window.setInterval(()=>{e({type:"tick",data:{}})},this.interval)}stop(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null)}},B=class{constructor(e){this.listeners=[];this.canvas=e}attach(e,t){let s=(i,n,r)=>{typeof n=="string"&&(n=[n]);for(let o of n)i.addEventListener(o,r),this.listeners.push({target:i,type:o,handler:r})};s(this.canvas,"pointerdown",i=>{let n=i,r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointerdown",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,"pointermove",i=>{let n=i;n.preventDefault();let r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointermove",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,"pointerup",i=>{let n=i;n.preventDefault();let r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointerup",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,"pointercancel",i=>{let n=i;if(n.pointerType==="touch")return;n.preventDefault();let r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointercancel",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,["touchstart","touchmove","touchend","touchcancel"],i=>{let n=i;n.preventDefault();let r=o=>Array.from(o).map(a=>{let l=this.canvas.getBoundingClientRect();(l.top!=0||l.left!=0)&&console.warn("Canvas rect is not at 0,0, this may cause issues with touch coordinates.");let c=new h(a.clientX,a.clientY),d=t.screenToWorld(c);return{identifier:a.identifier,point:d,originalTouch:a}});e({type:i.type,data:{touches:r(n.touches),targetTouches:r(n.targetTouches),changedTouches:r(n.changedTouches),originalEvent:n}})}),s(this.canvas,"wheel",i=>{i.preventDefault();let n=i,r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=new f(n.deltaX,n.deltaY);e({type:"wheel",data:{delta:a,point:o,originalEvent:n}})}),s(window,"resize",()=>{let i=new w(window.innerWidth,window.innerHeight);e({type:"windowresize",data:{size:i}})})}detach(){this.listeners.forEach(({target:e,type:t,handler:s})=>{e.removeEventListener(t,s)}),this.listeners=[]}},k=class{constructor(e){this.id=crypto.randomUUID();this.visible=!0;this.zIndex=-1/0;this.selectable=!1;this.img=e}get width(){return this.img.naturalWidth}get height(){return this.img.naturalHeight}getEventInteractions(e){return[{eventTypePrefix:"drag"}]}getBounds(){return new E(new h(0,0),new w(this.img.width,this.img.height))}getOuterBounds(){return this.getBounds()}render(e,t){e.drawImage(this.img,0,0)}},J=class{constructor(){this.listeners=new Map}on(e,t,s){this.listeners.has(e)||this.listeners.set(e,new Set);let i=s?.once?(n=>{this.off(e,i),t(n)}):t;this.listeners.get(e).add(i)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){e!==g.EngineRenderStarted&&e!==g.EngineRenderCompleted&&console.log("CanvasEvent:",e,t),this.listeners.get(e)?.forEach(s=>s(t))}},g={ObjectPositionChanged:"object:positionchanged",ObjectResized:"object:resized",ObjectMoved:"object:moved",ObjectColorChanged:"object:colorchanged",ObjectZIndexChanged:"object:zindexchanged",ObjectSelectableChanged:"object:selectablechanged",ObjectMovableChanged:"object:movablechanged",ObjectResizableChanged:"object:resizablechanged",ObjectVisibleChanged:"object:visiblechanged",ObjectChanged:"object:changed",ObjectSelected:"object:selected",ObjectDeselected:"object:deselected",ObjectFlagsAdded:"object:flagsadded",ObjectFlagsRemoved:"object:flagsremoved",ObjectAdded:"object:added",ObjectRemoved:"object:removed",ViewportChanged:"viewport:changed",DrawingCompleted:"drawing:completed",EngineStarted:"engine:started",EngineError:"engine:error",EngineBackgroundChanged:"engine:backgroundchanged",EngineRenderStarted:"engine:renderstarted",EngineRenderCompleted:"engine:rendercompleted"},ee=class{constructor(e,t){this.engine=t,this.config=e}processToolEvent(e,t){this.config?.handleEvent&&this.config.handleEvent(e,this.engine)}},te=class{constructor(e,t={}){this.defaultBackgroundImage=`<svg xmlns="http://www.w3.org/2000/svg" width="816" height="1056">
|
|
2
|
+
<rect width="100%" height="100%" fill="#FFF"/>
|
|
3
|
+
<text x="50%" y="50%" text-anchor="middle" fill="#888"
|
|
4
|
+
font-family="monospace" font-size="24">
|
|
5
|
+
Sample Page
|
|
6
|
+
</text>
|
|
7
|
+
</svg>`;this.document=new Blob([this.defaultBackgroundImage],{type:"image/svg+xml;charset=utf-8"});this.emitter=new J;this.toolLockManager=new D;this.eventSources=[];this.recognizers=[];this.tools=[];this.manualRenderers=[];this.modeRenderers=[];this.eventQueue=[];this.processingQueue=!1;this.renderScheduled=!1;this.flags=new Map;this.objects=[];this.needsRender=!1;this.toolRegistry=new Map;this.modes={};this.currentMode="";this.defaultOptions={initialZoom:1,initialPan:{x:10,y:10},defaultMode:"default",addTimerEventSource:!1,proxyObjectsForEvents:!0};this._pan=new f(0,0);this._zoom=1;this.on=this.emitter.on.bind(this.emitter);this.off=this.emitter.off.bind(this.emitter);this.emitExternal=this.emitter.emit.bind(this.emitter);this.options=this.createOptions(t);let s=document.querySelector(e);if(!s)throw new Error(`Container ${e} not found`);this.container=s,this.canvas=document.createElement("canvas"),this.canvas.width=this.container.clientWidth*10,this.canvas.height=this.container.clientHeight*10,this.container.appendChild(this.canvas),this.ctx=this.canvas.getContext("2d"),this.setupDefaultEventSources(),this.setupDefaultTools(),this.setupDefaultRecognizers(),this.setupDefaultModes(),this.setupRenderNodes(),this._zoom=this.options.initialZoom,this._pan=new f(this.options.initialPan.x,this.options.initialPan.y),this.switchMode(this.options.defaultMode),this.emitExternal(g.EngineStarted,{}),this.emitExternal(g.ViewportChanged,{oldPan:new f(0,0),newPan:this.pan,oldZoom:1,newZoom:this.zoom}),this.setBackgroundImage(this.document).then()}get pan(){return this._pan.clone()}get zoom(){return this._zoom}screenToWorld(e){return new h((e.x-this.pan.x)/this.zoom,(e.y-this.pan.y)/this.zoom)}worldToScreen(e){return new h(e.x*this.zoom+this.pan.x,e.y*this.zoom+this.pan.y)}processToolEvent(e,t,s,i,n){e.type.startsWith("windowresize")||(this.canvas.width=this.container.clientWidth,this.canvas.height=this.container.clientHeight)}createOptions(e){return{...this.defaultOptions,...e}}setupDefaultEventSources(){this.options.addTimerEventSource&&this.register(new G),this.register(new B(this.canvas))}setupDefaultRecognizers(){this.register(new N),this.register(new $)}setupDefaultTools(){this.registerTool("hover",()=>new H,!0),this.registerTool("select",()=>new L,!0),this.registerTool("drawing",()=>new F,!0),this.registerTool("move",()=>new A,!0),this.registerTool("resize",()=>new V,!0),this.registerTool("lasso",()=>new W,!0),this.registerTool("pan",()=>new ie,!0),this.registerTool("zoom",()=>new ne,!0),this.registerTool("api",()=>new q,!0)}setupDefaultModes(){this.defineMode("default",{tools:["hover","select","resize","move","pan","zoom","api"]}),this.defineMode("move",{tools:["hover","select","resize","move","pan","zoom","api"]}),this.defineMode("create",{tools:["hover","drawing","zoom","api"],handleEvent(e,t){e.type===g.DrawingCompleted&&t.switchMode("default")}}),this.defineMode("lasso",{tools:["hover","select","lasso","zoom","api"],handleEvent(e,t){e.type==="lassoselected"&&t.switchMode("default")}})}setupRenderNodes(){}wrapInteractiveObject(e){let t=this;return new Proxy(e,{set(s,i,n){let r=s[i],o=Reflect.set(s,i,n);return typeof i=="string"&&i.startsWith("_")||r!==n&&t.emitExternal(g.ObjectChanged,{object:s,property:i.toString(),oldValue:r,newValue:n}),o}})}registerTool(e,t,s=!0){if(this.toolRegistry.has(e))throw new Error(`Tool '${e}' already registered.`);this.toolRegistry.set(e,{factory:t,singleton:s})}resolveTool(e){let t=this.toolRegistry.get(e);if(!t)throw new Error(`Unknown tool '${e}'`);return t.singleton?("instance"in t||(t.instance=t.factory()),t.instance):t.factory()}defineMode(e,t){if(this.modes[e])throw new Error(`Mode '${e}' already defined.`);this.modes[e]=t}get mode(){return this.currentMode}switchMode(e){if(!this.modes[e])throw new Error(`Unknown mode '${e}'`);if(this.toolLockManager.isLocked){console.warn("Cannot switch modes while tools are locked. Please release all locks first.");return}if(this.currentMode===e){console.warn(`Already in mode '${e}', no switch needed.`);return}this.currentMode=e;let t=this.modes[e];if(t.tools==null||t.tools.length==0)return;let s=t.tools;this.tools=[...new Set(s.map(i=>this.resolveTool(i)))],this.modeRenderers=t.renderers||[],t.handleEvent&&this.tools.push(new ee(t,this)),console.log(`Switched to mode '${e}'`)}get renderers(){var e=this.tools.filter(t=>typeof t=="object"&&t!==null&&("renderBeforeAll"in t||"renderBeforeObject"in t||"renderAfterObject"in t||"renderAfterAll"in t)&&(typeof t.renderBeforeAll=="function"||typeof t.renderBeforeObject=="function"||typeof t.renderAfterObject=="function"||typeof t.renderAfterAll=="function")).map(t=>t);return[...new Set([...this.manualRenderers,...this.modeRenderers,...e])]}get width(){let e=this.getObjectsWithFlag("canvas-background").filter(s=>typeof s=="object"&&s instanceof k),t;return e.length==0?this.canvas.width:(e.length>=1&&(t=e[0]),t.width)}get height(){let e=this.getObjectsWithFlag("canvas-background").filter(s=>typeof s=="object"&&s instanceof k),t;return e.length==0?this.canvas.height:(e.length>=1&&(t=e[0]),t.height)}get documentBlob(){return this.document}async setBackgroundImage(e){let t=this.width,s=this.height,i;e instanceof File||e instanceof Blob?i=e:i=await this.loadImageFromUrl(e),this.document=i;let n=URL.createObjectURL(i),r=await this.loadImage(n),o=this.getObjectsWithFlag("canvas-background");if(o.length>0){let a=o.find(l=>l instanceof k);a&&(a.img=r)}else{let a=new k(r);this.objects.push(a),this.setFlag(a.id,"canvas-background")}this.emitExternal(g.EngineBackgroundChanged,{newImage:r,newWidth:r.width,newHeight:r.height,oldWidth:t,oldHeight:s})}async loadImageFromUrl(e){let t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch image: ${t.status} ${t.statusText}`);return await t.blob()}loadImage(e){return new Promise((t,s)=>{if(e instanceof HTMLImageElement){e.complete&&e.naturalWidth!==0?t(e):(e.onload=()=>t(e),e.onerror=s);return}let i=new Image;i.onload=()=>t(i),i.onerror=s,i.src=e})}getObject(e){return this.objects.find(s=>s.id===e)}addObject(e){if(this.objects.find(s=>s.id===e.id))throw new Error(`Object with id '${e.id}' already exists.`);this.objects.push(e),this.enqueue({type:"redraw",data:{}}),this.emitExternal(g.ObjectAdded,{object:this.options.proxyObjectsForEvents?this.wrapInteractiveObject(e):e})}removeObject(e){let t=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!t)throw new Error(`Object not found: ${e}`);let s=this.objects.indexOf(t);if(s!==-1){this.objects.splice(s,1);let i=typeof e=="string"?e:e.id;this.flags.delete(i),this.emitExternal(g.ObjectRemoved,{object:t})}else console.warn("Attempted to remove an object that does not exist in the engine:",t);this.redraw()}moveObjectToPoint(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.x,r=typeof t=="number"?s??0:t.y;this.enqueue({type:"api:moveto",data:{x:n,y:r},targets:[i]})}moveObjectByVector(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.x,r=typeof t=="number"?s??0:t.y;this.enqueue({type:"api:moveby",data:{dx:n,dy:r},targets:[i]})}resizeObjectToSize(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.width,r=typeof t=="number"?s??0:t.height;this.enqueue({type:"api:resizeto",data:{width:n,height:r},targets:[i]})}resizeObjectByVector(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.x,r=typeof t=="number"?s??0:t.y;this.enqueue({type:"api:resizeby",data:{dw:n,dh:r},targets:[i]})}setObjectColor(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setcolor",data:{color:t},targets:[s]})}setObjectZIndex(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setzindex",data:{zIndex:t},targets:[s]})}updateObjectSelectability(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setselectable",data:{isSelectable:t},targets:[s]})}updateObjectMovability(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setmovable",data:{isMovable:t},targets:[s]})}updateObjectResizeability(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setresizable",data:{isResizable:t},targets:[s]})}updateObjectVisibility(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setvisible",data:{visible:t},targets:[s]})}setFlag(e,t){let s=typeof e=="string"?this.objects.find(r=>r.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);let i=typeof e=="string"?e:e.id;if(this.flags.has(i)||this.flags.set(i,new Set),t=="selected"&&!s.selectable)return console.warn(`Cannot set flag '${t}' on non-selectable object`,s);let n=this.flags.get(i);n.has(t)||(n.add(t),this.emitExternal(g.ObjectFlagsAdded,{object:s,addedFlags:[t],currentFlags:[...this.flags.get(i)]}),t==="selected"&&this.emitExternal(g.ObjectSelected,{object:s}),this.ensureEventLoop())}clearFlag(e,t){let s=typeof e=="string"?this.objects.find(n=>n.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);let i=typeof e=="string"?e:e.id;this.flags.get(i)?.delete(t),this.emitExternal(g.ObjectFlagsRemoved,{object:s,removedFlags:[t],currentFlags:[...this.flags.get(i)||[]]}),t==="selected"&&this.emitExternal(g.ObjectDeselected,{object:s}),this.ensureEventLoop()}hasFlag(e,t){let s=typeof e=="string"?e:e.id;return this.flags.get(s)?.has(t)??!1}clearAllFlags(e){for(let[t,s]of this.flags.entries()){let i=this.objects.find(n=>n.id===t)??null;if(!i)throw new Error(`Object not found: ${t}`);s.delete(e),this.emitExternal(g.ObjectFlagsRemoved,{object:i,removedFlags:[e],currentFlags:[...this.flags.get(t)||[]]}),e==="selected"&&this.emitExternal(g.ObjectDeselected,{object:i})}this.ensureEventLoop()}getObjectsWithFlag(e){return[...this.flags.entries()].filter(([t,s])=>s.has(e)).filter(([t,s])=>{let i=this.objects.find(n=>n.id===t)??null;if(!i)throw new Error(`Object not found: ${t}`);return e==="selected"?i.selectable:!0}).map(([t])=>this.objects.find(s=>s.id===t))}setZoom(e,t){if(e<=0){console.warn("Zoom must be greater than 0, ignoring.");return}let s=this.zoom,i=new f(this.pan.x,this.pan.y);if(this._zoom=e,t){let n=t.x-(t.x-this.pan.x)*(e/s),r=t.y-(t.y-this.pan.y)*(e/s);this._pan=new f(n,r)}this.emitExternal(g.ViewportChanged,{oldPan:i,newPan:this.pan,oldZoom:s,newZoom:this.zoom}),this.ensureEventLoop()}setPan(e,t){let s=this.pan.clone();typeof e=="number"?this._pan=new f(e,t??0):this._pan=e.clone(),this.emitExternal(g.ViewportChanged,{oldPan:s,newPan:this.pan,oldZoom:this.zoom,newZoom:this.zoom}),this.ensureEventLoop()}setSelectedObjects(e){let t=e.map(r=>typeof r=="string"?this.objects.find(o=>o.id===r):r),s=this.getSelectedObjects(),i=s.filter(r=>!t.includes(r)),n=t.filter(r=>!s.includes(r));i.forEach(r=>this.clearFlag(r,"selected")),n.forEach(r=>this.setFlag(r,"selected")),this.ensureEventLoop()}getSelectedObjects(){return this.getObjectsWithFlag("selected").filter(e=>e.selectable)}getAllObjects(){let e=this.getObjectsWithFlag("canvas-background").filter(t=>typeof t=="object"&&t instanceof k);return[...this.objects].filter(t=>e.includes(t)==!1)}getTopMostInteractionPerEventType(e){let t=new Map,s=[...this.objects].sort((i,n)=>(i.zIndex??0)-(n.zIndex??0));for(let i=s.length-1;i>=0;i--){let n=s[i];if(!n)continue;n.getEventInteractions(e).forEach(o=>{let a=o.eventTypePrefix;if(!t.has(a)){let l={object:n,interaction:o};t.set(a,l)}})}return t}enqueue(e){this.eventQueue.push(e),this.ensureEventLoop()}ensureEventLoop(){this.processingQueue||(this.processingQueue=!0,setTimeout(()=>this.processQueue(),0))}processQueue(){for(;this.eventQueue.length;){let e=this.eventQueue.shift();if(!e.stopPropagation&&(this.recognizers.forEach(t=>{e.stopPropagation||t.process(e,s=>this.eventQueue.push(s))}),!e.stopPropagation&&(this.tools.forEach(t=>{e.stopPropagation||t.processToolEvent(e,s=>this.eventQueue.push(s),this.emitExternal,this,this.toolLockManager.getToolLock(t))}),!e.stopPropagation&&(this.processToolEvent(e,t=>this.eventQueue.push(t),this.emitExternal,this,this.toolLockManager.getToolLock(this)),e.type.startsWith("pointer")==!1,e.targets&&e.targets.length>0)))){let t=e.targets;for(let s of t)s.handleEvent&&s.handleEvent(e,this.emitExternal)}}this.processingQueue=!1,this.requestRender()}addEventSource(e){this.eventSources.push(e),e.attach(t=>this.enqueue(t),this)}removeEventSource(e){this.eventSources=this.eventSources.filter(t=>t!==e),e.detach?.()}addRecognizer(e){this.recognizers.push(e)}addRenderNode(e){this.renderers.push(e)}register(e){typeof e=="object"&&e!==null&&"attach"in e&&typeof e.attach=="function"&&this.addEventSource(e),typeof e=="object"&&e!==null&&"process"in e&&typeof e.process=="function"&&this.addRecognizer(e),typeof e=="object"&&e!==null&&("renderBeforeAll"in e||"renderBeforeObject"in e||"renderAfterObject"in e||"renderAfterAll"in e)&&(typeof e.renderBeforeAll=="function"||typeof e.renderBeforeObject=="function"||typeof e.renderAfterObject=="function"||typeof e.renderAfterAll=="function")&&this.addRenderNode(e)}redraw(){this.requestRender()}requestRender(){this.needsRender=!0,this.renderScheduled||(this.renderScheduled=!0,requestAnimationFrame(()=>{this.needsRender&&(this.doRender(this.ctx),this.needsRender=!1),this.renderScheduled=!1}))}doRender(e){e.save(),e.setTransform(this.zoom,0,0,this.zoom,this.pan.x,this.pan.y),e.clearRect(-this.pan.x/this.zoom,-this.pan.y/this.zoom,this.canvas.width/this.zoom,this.canvas.height/this.zoom),this.emitExternal(g.EngineRenderStarted,{}),this.renderers.forEach(t=>t.renderBeforeAll?.(e,this));for(let t of this.objects.filter(s=>s.visible).sort((s,i)=>s.zIndex-i.zIndex))this.renderers.forEach(s=>s.renderBeforeObject?.(e,this,t)),t.render(e,this.flags.get(t.id)??new Set),this.renderers.forEach(s=>s.renderAfterObject?.(e,this,t));this.renderers.forEach(t=>t.renderAfterAll?.(e,this)),this.emitExternal(g.EngineRenderCompleted,{}),e.restore()}dispose(){this.eventSources.forEach(e=>e.detach?.())}},D=class{constructor(){this.currentTool=null}get isLocked(){return this.currentTool!==null}getToolLock(e){return{hasLock:()=>this.currentTool===e,acquire:()=>this.currentTool===null||this.currentTool===e?(this.currentTool=e,!0):!1,release:()=>this.currentTool===null||this.currentTool===e?(this.currentTool=null,!0):(console.warn("Tool lock released by a tool that does not own it:",e),!1)}}},ne=class{constructor(){this.passive=!1;this.zoomFactor=1.1;this.pinchZoomFactor=.5;this.minZoom=.1;this.maxZoom=10}processToolEvent(e,t,s,i,n){switch(e.type){case"wheel":this.handleWheelZoom(e,i,n);break;case"gesture":this.handlePinchZoom(e,i,n);break;case"keyZoomIn":break;case"keyZoomOut":break}}handleWheelZoom(e,t,s){let i=e.data||{},n=i.delta||new f(0,0),r=i.point||new h(0,0),o=n.y<0?this.zoomFactor:1/this.zoomFactor;this.applyZoom(t,o,r.x*t.zoom+t.pan.x,r.y*t.zoom+t.pan.y,s)}handlePinchZoom(e,t,s){let i=e.data||{},n=i.scaleDelta,r=i.clientX,o=i.clientY,a=1+n*this.pinchZoomFactor;this.applyZoom(t,a,r,o,s)}applyZoom(e,t,s,i,n){let r=e.zoom,o=Math.min(Math.max(r*t,this.minZoom),this.maxZoom);o!==r&&n.acquire()&&(e.pan.x=s-(s-e.pan.x)*(o/r),e.pan.y=i-(i-e.pan.y)*(o/r),e.setZoom(o,new h(s,i)),n.release())}},ie=class{constructor(){this.priority=-1/0;this.active=!1;this.startClient=new h(0,0);this.origPan=new f(0,0)}processToolEvent(e,t,s,i,n){if(!e.type.startsWith("drag"))return!1;let o=(e.data||{}).point,a=i.worldToScreen(o);if(o!==null){var l=i.getTopMostInteractionPerEventType(o);if(l&&l.has("drag")){var c=l.get("drag");if(c&&i.hasFlag(c.object,"canvas-background")){if(e.type==="dragstart"){if(!n.acquire())return;this.startClient=a,this.origPan=i.pan.clone(),this.active=!0}if(e.type==="dragend"||e.type==="dragcancel"){this.active=!1,this.startClient=new h(0,0),this.origPan=new f(0,0),n.release();return}if(this.active==!1)return;n.hasLock()&&i.setPan(this.origPan.add(a.getDeltaFromPoint(this.startClient)))}}}}},A=class{constructor(){this.objectsBeingMoved=[];this.lastDelta=null}processToolEvent(e,t,s,i,n){let r=e.data||{},o=r.point,a=r.delta,l=this.lastDelta==null?a:this.lastDelta,c=this.lastDelta==null?a:a?.subtract(l);switch(e.type){case"dragstart":if(!o)return;let p=i.getTopMostInteractionPerEventType(o).get("move");if(p){if(!n.acquire())return;let v=i.getSelectedObjects();v.length===0||v.some(z=>z===p.object)===!1?this.objectsBeingMoved=[p.object]:this.objectsBeingMoved=v}break;case"drag":if(!a||this.objectsBeingMoved==null||this.objectsBeingMoved.length===0)return;this.lastDelta=a,t({type:"move",data:{delta:c,point:o},targets:this.objectsBeingMoved});break;case"dragend":if(!a||this.objectsBeingMoved==null||this.objectsBeingMoved.length===0){this.lastDelta=null,this.objectsBeingMoved=[];return}t({type:"move",data:{origin,delta:c,point:o},targets:this.objectsBeingMoved}),this.lastDelta=null,this.objectsBeingMoved=[],n.release();break;case"dragcancel":(!a||this.objectsBeingMoved==null||this.objectsBeingMoved.length===0)&&(this.lastDelta=null,this.objectsBeingMoved=[]),t({type:"move",data:{origin,delta:l?.subtract(a)||new f(0,0),point:origin},targets:this.objectsBeingMoved}),this.lastDelta=null,this.objectsBeingMoved=[],n.release();break}}},L=class{constructor(){this.priority=100}processToolEvent(e,t,s,i,n){if(e.type!=="click")return;let r=e.data||{},o=r.point;if(!o)return;let l=i.getTopMostInteractionPerEventType(o).get("select"),c=i.getSelectedObjects(),d=r.metaHeld||r.ctrlHeld||r.shiftHeld;if(l){let p=c.some(z=>z===l.object);if(!(c.length===1&&p)){if(!n.acquire())return;d?i.setSelectedObjects([...c,l.object]):i.setSelectedObjects([l.object]),n.release()}}else i.setSelectedObjects([])}},H=class{constructor(){this.priority=-100}processToolEvent(e,t,s,i,n){if(e.type!=="pointermove")return;let o=(e.data||{}).point;if(!o)return;for(let l of i.getObjectsWithFlag("hoversibling"))i.clearFlag(l,"hoversibling"),i.setFlag(l,"hovered");for(let l of i.getObjectsWithFlag("hovered"))l.getOuterBounds().contains(o)||i.clearFlag(l,"hovered");for(let l of i.getAllObjects())l.getBounds().contains(o)&&i.setFlag(l,"hovered");let a=!1;for(let l of i.getSelectedObjects())i.hasFlag(l,"hovered")&&(a=!0);if(a)for(let l of i.getSelectedObjects())i.hasFlag(l,"hovered")||(i.setFlag(l,"hovered"),i.setFlag(l,"hoversibling"))}},V=class{constructor(){this.activeHandleIndex=null;this.objectsBeingResized=[];this.lastDelta=null}processToolEvent(e,t,s,i,n){let r=e.data||{},o=r.point,a=r.delta,l=r.origin,c=this.lastDelta==null?a:this.lastDelta,d=this.lastDelta==null?a:a?.subtract(c);switch(e.type){case"dragstart":if(!o)return;let v=i.getTopMostInteractionPerEventType(o).get("resize");if(v&&v.interaction.handleIndex!=null){if(!n.acquire())return;let z=i.getSelectedObjects();z.length===0||z.some(I=>I===v.object)===!1?this.objectsBeingResized=[v.object]:this.objectsBeingResized=z,this.activeHandleIndex=v.interaction.handleIndex,t({type:"resizestart",data:{handleIndex:this.activeHandleIndex,point:o},targets:this.objectsBeingResized})}break;case"drag":if(this.activeHandleIndex==null||!a||this.objectsBeingResized==null||this.objectsBeingResized.length===0)return;this.lastDelta=a,t({type:"resize",data:{handleIndex:this.activeHandleIndex,delta:d,point:o},targets:this.objectsBeingResized});break;case"dragend":if(this.activeHandleIndex==null||!a||this.objectsBeingResized==null||this.objectsBeingResized.length===0){this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[];return}t({type:"resize",data:{handleIndex:this.activeHandleIndex,origin:l,delta:d,point:o},targets:this.objectsBeingResized}),t({type:"resizeend",data:{handleIndex:this.activeHandleIndex,delta:d,point:o},targets:this.objectsBeingResized}),this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[],n.release();break;case"dragcancel":(this.activeHandleIndex==null||!a||this.objectsBeingResized==null||this.objectsBeingResized.length===0)&&(this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[]),t({type:"resize",data:{handleIndex:this.activeHandleIndex,origin:l,delta:c?.subtract(a)||new f(0,0),point:l},targets:this.objectsBeingResized}),this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[],n.release();break}}},F=class{constructor(e="black"){this.drawing=!1;this.startPt=null;this.currentPt=null;this.defaultColor="black";this.defaultColor=e}processToolEvent(e,t,s,i,n){let o=(e.data||{}).point;switch(e.type){case"dragstart":if(!o||!n.acquire())return;this.drawing=!0,this.startPt=o,this.currentPt=o;break;case"drag":if(!this.drawing||!n.hasLock()||!o)return;this.currentPt=o;break;case"dragend":if(this.drawing&&n.hasLock()&&this.startPt&&o){this.currentPt=o;let a=Math.min(this.startPt.x,this.currentPt.x),l=Math.min(this.startPt.y,this.currentPt.y),c=Math.abs(this.currentPt.x-this.startPt.x),d=Math.abs(this.currentPt.y-this.startPt.y),p=new E(a,l,c,d),v=i.getAllObjects().reduce((z,I)=>Math.max(z,I.zIndex),0);this.drawing=!1,n.release(),s(g.DrawingCompleted,{rect:p,maxZ:v})}case"dragcancel":this.drawing&&n.hasLock()&&(this.drawing=!1,this.startPt=null,this.currentPt=null,n.release());break}}renderAfterAll(e,t){if(!this.drawing||!this.startPt||!this.currentPt)return;let s=Math.min(this.startPt.x,this.currentPt.x),i=Math.min(this.startPt.y,this.currentPt.y),n=Math.abs(this.currentPt.x-this.startPt.x),r=Math.abs(this.currentPt.y-this.startPt.y);e.save(),e.strokeStyle=this.defaultColor,e.lineWidth=2/e.getTransform().a,e.setLineDash([4/e.getTransform().a,2/e.getTransform().a]),e.strokeRect(s,i,n,r),e.setLineDash([]),e.restore()}},W=class{constructor(){this.lassoing=!1;this.points=[]}processToolEvent(e,t,s,i,n){let o=(e.data||{}).point;switch(e.type){case"dragstart":if(!o||!n.acquire())return;this.lassoing=!0,this.points=[o];break;case"drag":if(!this.lassoing||!n.hasLock()||!o)return;this.points.push(o);break;case"dragend":if(this.lassoing&&n.hasLock()&&o){this.points.push(o);let a=new M(this.points),l=[];for(let c of i.getAllObjects()){let d=c.getBounds();if(a.containsRect(d)){l.push(c);continue}}i.setSelectedObjects(l),t({type:"lassoselected",data:{polygon:a,selectedObjects:l}})}case"dragcancel":this.lassoing&&n.hasLock()&&(this.lassoing=!1,this.points=[],n.release());break}}renderAfterAll(e,t){if(!(!this.lassoing||this.points.length===0)){e.save(),e.strokeStyle="black",e.lineWidth=1/e.getTransform().a,e.setLineDash([4/e.getTransform().a,2/e.getTransform().a]),e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(let s=1;s<this.points.length;s++)e.lineTo(this.points[s].x,this.points[s].y);e.stroke(),e.restore()}}},q=class{processToolEvent(e,t,s,i,n){if(!e.type.startsWith("api:"))return;e.stopPropagation=!0;let r=e.targets;if(!r||r.length===0)return;let o=r[0];if(!o){console.warn("API event has no target object:",e);return}if(!i.getAllObjects().includes(o)){console.warn("API event targets an object not in the engine:",o);return}switch(e.type){case"api:moveto":{if(!n.acquire())return;let{x:a,y:l}=e.data,d=o.getBounds().origin,p=new f(a-d.x,l-d.y);t({type:"move",data:{delta:p,origin:d,point:d},targets:[o]}),n.release();break}case"api:moveby":{if(!n.acquire())return;let{dx:a,dy:l}=e.data;t({type:"move",data:{delta:new f(a,l)},targets:[o]}),n.release();break}case"api:resizeto":{if(!n.acquire())return;let{width:a,height:l}=e.data,c=o.getBounds(),d=c.origin,p=a-c.size.width,v=l-c.size.height;t({type:"resizestart",data:{handleIndex:4,origin:d,point:d},targets:[o]}),t({type:"resize",data:{handleIndex:4,delta:new f(p,v),point:d},targets:[o]}),t({type:"resizeend",data:{handleIndex:4,delta:new f(p,v),point:d},targets:[o]}),n.release();break}case"api:resizeby":{if(!n.acquire())return;let{dW:a,dH:l}=e.data,d=o.getBounds().origin;t({type:"resizestart",data:{handleIndex:4,origin:d,point:d},targets:[o]}),t({type:"resize",data:{handleIndex:4,delta:new f(a,l),point:d},targets:[o]}),t({type:"resizeend",data:{handleIndex:4,delta:new f(a,l),point:d},targets:[o]}),n.release();break}case"api:setcolor":{let{color:a}=e.data;t({type:"setcolor",data:{color:a},targets:[o]});break}case"api:setzindex":{let{zIndex:a}=e.data;t({type:"setzindex",data:{zIndex:a},targets:[o]});break}case"api:setselectable":{let{isSelectable:a}=e.data;t({type:"setselectable",data:{isSelectable:a},targets:[o]});break}case"api:setmovable":{if(!n.acquire())return;let{isMovable:a}=e.data;t({type:"setmovable",data:{isMovable:a},targets:[o]}),n.release();break}case"api:setresizable":{if(!n.acquire())return;let{isResizable:a}=e.data;t({type:"setresizable",data:{isResizable:a},targets:[o]}),n.release();break}case"api:setvisible":{let{visible:a}=e.data;t({type:"setvisible",data:{isVisible:a},targets:[o]});break}}}},N=class{constructor(e=5){this.activePointerIds=new Set;this.isDragging=!1;this.buttonStart=null;this.origin=new h(0,0);this.moveThreshold=e}process(e,t){let{type:s,data:i={}}=e;switch(s){case"pointerdown":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=i.button;this.handleStart(r,i.pointerType,n,o,t)}break;case"touchstart":{let n=this.getTouches(e);if(n.length===1){let r=n[0],o=r.point,a=r.identifier;this.handleStart(a,"touch",o,null,t)}break}case"pointermove":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new f(0,0),a=i.button;this.handleMove(r,i.pointerType,n,o,a,t)}break;case"touchmove":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new f(0,0);this.handleMove(o,"touch",r,a,null,t)}break}case"pointerup":case"pointercancel":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new f(0,0),a=i.button;this.handleEnd(r,i.pointerType,n,o,a,t)}break;case"touchend":case"touchcancel":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new f(0,0);this.handleEnd(o,"touch",r,a,null,t)}break}}}handleStart(e,t,s,i,n){this.isDragging||e==null||s==null||s.x==null||s.y==null||n==null||(this.activePointerIds.add(e),this.origin=s,this.buttonStart=i??null,n({type:"dragpotential",data:{identifier:e,pointerType:t,point:origin}}))}handleMove(e,t,s,i,n,r){if(!(e==null||s==null||i==null||!this.activePointerIds.has(e)||r==null)){var o=s.subtract(i);!this.isDragging&&(this.buttonStart==null||this.buttonStart==0)&&(i.length()>=this.moveThreshold?(this.activePointerIds.clear(),this.activePointerIds.add(e),this.isDragging=!0,r({type:"dragstart",data:{identifier:e,pointerType:t,point:o}})):r({type:"dragpotentialmove",data:{identifier:e,pointerType:t,origin:o,delta:i,point:s}})),this.isDragging&&r({type:"drag",data:{identifier:e,pointerType:t,origin:o,delta:i,point:s}})}}handleEnd(e,t,s,i,n,r){if(!this.isDragging||e==null||s==null||i==null||!this.activePointerIds.has(e)||r==null){this.activePointerIds.clear();return}var o=s.add(i);r({type:"dragend",data:{identifier:e,pointerType:t,origin:o,point:s,delta:i}}),this.activePointerIds.clear(),this.isDragging=!1,this.buttonStart=null}getTouches(e){return e.data?.changedTouches??[]}findActiveTouch(e){return this.getTouches(e).find(t=>this.activePointerIds.has(t.identifier))}},$=class{constructor(e=5){this.activePointerIds=new Set;this.origin=new h(0,0);this.moveThreshold=e}process(e,t){let{type:s,data:i={}}=e;switch(s){case"pointerdown":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier;this.handleStart(r,n)}break;case"touchstart":{let n=this.getTouches(e);if(n.length===1){let r=n[0],o=r.point,a=r.identifier;this.handleStart(a,o)}break}case"pointermove":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new f(0,0);this.handleMove(r,n,o)}break;case"touchmove":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new f(0,0);this.handleMove(o,r,a)}break}case"pointerup":case"pointercancel":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new f(0,0),a=e.data?.shiftHeld??!1,l=e.data?.metaHeld??!1,c=e.data?.ctrlHeld??!1,d=e.data?.altHeld??!1;this.handleEnd(r,i.pointerType,n,o,{shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d},t)}break;case"touchend":case"touchcancel":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new f(0,0);this.handleEnd(o,"touch",r,a,t)}break}}}handleStart(e,t){e==null||t==null||t.x==null||t.y==null||(this.activePointerIds.add(e),this.origin=t)}handleMove(e,t,s){e==null||t==null||s==null||!this.activePointerIds.has(e)||s.length()>=this.moveThreshold&&this.activePointerIds.clear()}handleEnd(e,t,s,i,n,r){if(!(e==null||s==null||i==null||!this.activePointerIds.has(e)||r==null)){if(i.length()>=this.moveThreshold){this.activePointerIds.clear();return}var o={identifier:e,pointerType:t,point:s};n&&(o={...o,...n}),r({type:"click",data:o}),this.activePointerIds.clear()}}getTouches(e){return e.data?.changedTouches??[]}findActiveTouch(e){return this.getTouches(e).find(t=>this.activePointerIds.has(t.identifier))}},h=class b{constructor(e,t){this.x=e,this.y=t}equals(e){return this.x===e.x&&this.y===e.y}static equals(e,t){return e.x===t.x&&e.y===t.y}getDeltaFromPoint(e){return new f(this.x-e.x,this.y-e.y)}getDeltaToPoint(e){return new f(this.x+e.x,this.y+e.y)}add(e){return new b(this.x+e.x,this.y+e.y)}asVector(){return new f(this.x,this.y)}subtract(e){return new b(this.x-e.x,this.y-e.y)}isInside(e){return e.contains(this)}clone(){return new b(this.x,this.y)}isInPolygon(e){return e.containsPoint(this)}},w=class b{constructor(e,t){this.width=e,this.height=t}equals(e){return this.width===e.width&&this.height===e.height}static equals(e,t){return e.width===t.width&&e.height===t.height}clone(){return new b(this.width,this.height)}},E=class b{constructor(e,t,s,i){let n=typeof e=="number"&&typeof t=="number"?new h(e,t):e,r=typeof t=="number"&&typeof s=="number"&&typeof i=="number"?new w(s,i):t;this.origin=n,this.size=r}equals(e){return this.origin.equals(e.origin)&&this.size.equals(e.size)}static equals(e,t){return e.origin.equals(t.origin)&&e.size.equals(t.size)}contains(e){return e.x>=this.origin.x&&e.x<=this.origin.x+this.size.width&&e.y>=this.origin.y&&e.y<=this.origin.y+this.size.height}clone(){return new b(new h(this.origin.x,this.origin.y),new w(this.size.width,this.size.height))}center(){return new h(this.origin.x+this.size.width/2,this.origin.y+this.size.height/2)}normalized(){if(this.isNormalized())return this;let e=this.clone();return e.normalize(),e}isNormalized(){return this.size.width>=0&&this.size.height>=0}normalize(){this.size.width<0&&(this.origin.x+=this.size.width,this.size.width=-this.size.width),this.size.height<0&&(this.origin.y+=this.size.height,this.size.height=-this.size.height)}expand(e){let t=new h(Math.min(this.origin.x,e.origin.x),Math.min(this.origin.y,e.origin.y)),s=Math.max(this.origin.x+this.size.width,e.origin.x+e.size.width)-t.x,i=Math.max(this.origin.y+this.size.height,e.origin.y+e.size.height)-t.y;return new b(t,new w(s,i))}move(e){return new b(new h(this.origin.x+e.x,this.origin.y+e.y),new w(this.size.width,this.size.height))}toPolygon(){return new M([new h(this.origin.x,this.origin.y),new h(this.origin.x+this.size.width,this.origin.y),new h(this.origin.x+this.size.width,this.origin.y+this.size.height),new h(this.origin.x,this.origin.y+this.size.height)])}},f=class b{constructor(e,t){this.x=e,this.y=t}equals(e){return this.x===e.x&&this.y===e.y}static equals(e,t){return e.x===t.x&&e.y===t.y}add(e){return new b(this.x+e.x,this.y+e.y)}subtract(e){return new b(this.x-e.x,this.y-e.y)}scale(e){return new b(this.x*e,this.y*e)}length(){return Math.hypot(this.x,this.y)}normalize(){let e=this.length();return e===0?new b(0,0):new b(this.x/e,this.y/e)}clone(){return new b(this.x,this.y)}},M=class{constructor(e){this.points=e}equals(e){if(this.points.length!==e.points.length)return!1;for(let t=0;t<this.points.length;t++)if(!this.points[t].equals(e.points[t]))return!1;return!0}static equals(e,t){return e.equals(t)}containsPoint(e){let t=this.points,s=!1;for(let i=0,n=t.length-1;i<t.length;n=i++){let r=t[i].x,o=t[i].y,a=t[n].x,l=t[n].y;o>e.y!=l>e.y&&e.x<(a-r)*(e.y-o)/(l-o)+r&&(s=!s)}return s}containsRect(e){return this.containsPoint(e.origin)&&this.containsPoint(new h(e.origin.x+e.size.width,e.origin.y+e.size.height))&&this.containsPoint(new h(e.origin.x+e.size.width,e.origin.y))&&this.containsPoint(new h(e.origin.x,e.origin.y+e.size.height))}};0&&(module.exports={ApiTool,CanvasEngine,CircleObject,ClickGestureRecognizer,DomEventSource,DragGestureRecognizer,DrawingTool,EngineEventType,HoverTool,LassoTool,MoveTool,Point,Polygon,PolygonObject,Rectangle,ResizeTool,SelectTool,Size,ToolLockManager,Vector,Zone});
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var B=class B{constructor(e,t,s,i,n,r,o,a,l,c){this._name=null;this._showName=!1;this._nameAnchor="TopLeft";this._visible=!0;if(this._id=e,t instanceof j){let d=t,g=s??"#000000",p=i??!1,z=n??!1,I=r??!1,_=o??0;this._rect=d,this._color=g,this._selectable=p,this._movable=z,this._resizable=I,this._zIndex=_}else{let d=t,g=s,p=i,z=n,I=r??"#000000",_=o??!1,R=a??!1,O=l??!1,S=c??0;this._rect=new j(new h(d,g),new w(p,z)),this._color=I,this._selectable=_,this._movable=R,this._resizable=O,this._zIndex=S}}get id(){return this._id}set id(e){this._id=e}get rect(){return this._rect.normalized()}get name(){return this._name}set name(e){this._name=e}get showName(){return this._showName}set showName(e){this._showName=e}get nameAnchor(){return this._nameAnchor}set nameAnchor(e){this._nameAnchor=e}get zIndex(){return this._zIndex}set zIndex(e){this._zIndex=e}get visible(){return this._visible??!1}set visible(e){this._visible=e}get color(){return this._color}set color(e){this._color=e}get selectable(){return this._selectable}set selectable(e){this._selectable=e}get movable(){return this._movable}set movable(e){this._movable=e}get resizable(){return this._resizable}set resizable(e){this._resizable=e}getBounds(){return this._rect}getOuterBounds(){let e=this._rect,t=this.getResizeHandles();return t.length===0||t.forEach(s=>{e=e.expand(s.rect)}),e}getEventInteractions(e){let t=[];if(this._resizable&&this.getResizeHandles().forEach(i=>{(e===null||i.rect.contains(e))&&t.push({eventTypePrefix:"resize",handleIndex:i.handleIndex})}),this._movable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"move"})}if(this._selectable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"select"})}return t}getResizeHandles(){let e=this._rect.origin.x,t=this._rect.origin.y,s=this._rect.size.width,i=this._rect.size.height,n=B.HANDLE_SIZE,r=n*10,o=n*6,a=1;s>=r&&i>=r?a=-1:s>=o&&i>=o&&(a=0);let l=s<o,c=i<o;return[{rect:new j(new h(e-a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:0},l?null:{rect:new j(new h(e+s/2-n,t-a*n-n),new w(n*2,n*2)),handleIndex:1},{rect:new j(new h(e+s+a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:2},c?null:{rect:new j(new h(e+s+a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:3},{rect:new j(new h(e+s+a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:4},l?null:{rect:new j(new h(e+s/2-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:5},{rect:new j(new h(e-a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:6},c?null:{rect:new j(new h(e-a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:7}].filter(g=>g!==null)}handleEvent(e,t){let s=e.data||{};if(e.type==="setcolor"&&this._color!==s.color){let n=this._color;this._color=s.color,t(b.ObjectColorChanged,{object:this,oldColor:n,newColor:this._color});return}if(e.type==="setzindex"&&this._zIndex!==s.zIndex){let n=this._zIndex;this._zIndex=s.zIndex,t(b.ObjectZIndexChanged,{object:this,oldZIndex:n,newZIndex:this._zIndex});return}if(e.type==="setselectable"&&this._selectable!==s.isSelectable){let n=this._selectable;this._selectable=s.isSelectable,t(b.ObjectSelectableChanged,{object:this,oldSelectable:n,newSelectable:this._selectable});return}if(e.type==="setmovable"&&this._movable!==s.isMovable){let n=this._movable;this._movable=s.isMovable,t(b.ObjectMovableChanged,{object:this,oldMovable:n,newMovable:this._movable});return}if(e.type==="setresizable"&&this._resizable!==s.isResizable){let n=this._resizable;this._resizable=s.isResizable,t(b.ObjectResizableChanged,{object:this,oldResizable:n,newResizable:this._resizable});return}if(e.type==="setvisible"&&this._visible!==s.isVisible){let n=this._visible??!0;this._visible=s.isVisible,t(b.ObjectVisibleChanged,{object:this,oldVisible:n,newVisible:this._visible??!0});return}let i=s.delta;if(e.type==="resize"){let n=this._rect.clone(),r=s.handleIndex;if(i==null||r==null){console.warn("Resize event missing required data:",e);return}let o=-1/0,a=i.x,l=i.y;if(a===0&&l===0)return;switch(r){case 0:a=Math.min(a,this._rect.size.width-o),l=Math.min(l,this._rect.size.height-o),this._rect.origin.x+=a,this._rect.origin.y+=l,this._rect.size.width-=a,this._rect.size.height-=l;break;case 1:l=Math.min(l,this._rect.size.height-o),this._rect.origin.y+=l,this._rect.size.height-=l;break;case 2:a=Math.max(a,o-this._rect.size.width),l=Math.min(l,this._rect.size.height-o),this._rect.origin.y+=l,this._rect.size.width+=a,this._rect.size.height-=l;break;case 3:a=Math.max(a,o-this._rect.size.width),this._rect.size.width+=a;break;case 4:a=Math.max(a,o-this._rect.size.width),l=Math.max(l,o-this._rect.size.height),this._rect.size.width+=a,this._rect.size.height+=l;break;case 5:l=Math.max(l,o-this._rect.size.height),this._rect.size.height+=l;break;case 6:a=Math.min(a,this._rect.size.width-o),l=Math.max(l,o-this._rect.size.height),this._rect.origin.x+=a,this._rect.size.width-=a,this._rect.size.height+=l;break;case 7:a=Math.min(a,this._rect.size.width-o),this._rect.origin.x+=a,this._rect.size.width-=a;break}t(b.ObjectResized,{object:this,oldSize:n.size,newSize:this._rect.clone().size}),t(b.ObjectPositionChanged,{object:this,oldPosition:n,newPosition:this._rect.clone()})}else e.type==="resizeend"&&this._rect.normalize();if(e.type.startsWith("move")){if(i==null){console.warn("Move event missing required data:",e);return}if(i.x===0&&i.y===0)return;let n=this._rect.clone();this._rect=this._rect.move(i),t(b.ObjectMoved,{object:this,oldPoint:n.origin,newPoint:this._rect.clone().origin}),t(b.ObjectPositionChanged,{object:this,oldPosition:n,newPosition:this._rect})}}render(e,t){let s=t.has("selected"),i=t.has("hovered"),n=t.has("hoversibling"),o=e.getTransform().a,a=u=>u/o,l=a(4),c=a(2),d=a(3),g=a(4),p=this._rect,z=p.origin.x,I=p.origin.y,_=p.size.width,R=p.size.height,O=(u,f,E,y,P)=>{let x=Math.max(0,Math.min(P,Math.min(E,y)/2)),T=new Path2D;return T.moveTo(u+x,f),T.lineTo(u+E-x,f),T.arcTo(u+E,f,u+E,f+x,x),T.lineTo(u+E,f+y-x),T.arcTo(u+E,f+y,u+E-x,f+y,x),T.lineTo(u+x,f+y),T.arcTo(u,f+y,u,f+y-x,x),T.lineTo(u,f+x),T.arcTo(u,f,u+x,f,x),T.closePath(),T},S=O(z,I,_,R,l);e.save(),e.strokeStyle=this._color;let C=e.strokeStyle;if(e.fillStyle=this.withAlpha(C,.06),e.fill(S),e.lineWidth=c,e.stroke(S),e.restore(),s){let u=z-g,f=I-g,E=_+g*2,y=R+g*2,P=O(u,f,E,y,l+g);e.save(),e.setLineDash([a(8),a(6)]),e.lineDashOffset=0,e.strokeStyle="rgba(0,0,0,0.4)",e.lineWidth=d,e.stroke(P),e.restore()}if(this._showName&&this._name){e.save(),e.font="12px sans-serif",e.fillStyle=this._color,e.textBaseline="top";let u=2,{x:f,y:E}=this._rect.origin,{width:y,height:P}=this._rect.size,x=f+u,T=E+u;switch(this._nameAnchor){case"TopLeft":x=f+u,T=E+u;break;case"TopRight":x=f+y-e.measureText(this._name).width-u,T=E+u;break;case"BottomLeft":x=f+u,T=E+P-14-u;break;case"BottomRight":x=f+y-e.measureText(this._name).width-u,T=E+P-14-u;break;case"Center":x=f+(y-e.measureText(this._name).width)/2,T=E+(P-12)/2;break}e.fillText(this._name,x,T),e.restore()}if(this._resizable&&i){e.save(),e.lineWidth=a(n?.5:1),e.strokeStyle=C,e.fillStyle=n?"transparent":"white",e.globalAlpha=n?.75:1;for(let u of this.getResizeHandles()||[]){if(!u)continue;let{x:f,y:E}=u.rect.origin,{width:y,height:P}=u.rect.size,x=a(4),T=O(f,E,y,P,x);e.fill(T),e.stroke(T)}e.restore()}}withAlpha(e,t){let s=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\s*\)/i);if(s){let i=parseInt(s[1]??"0",10),n=parseInt(s[2]??"0",10),r=parseInt(s[3]??"0",10);return`rgba(${i},${n},${r},${t})`}if(e.startsWith("#")){let i=e.slice(1);if(i.length===3&&(i=i.split("").map(n=>n+n).join("")),i.length===6||i.length===8){let n=parseInt(i.slice(0,2),16),r=parseInt(i.slice(2,4),16),o=parseInt(i.slice(4,6),16);return`rgba(${n},${r},${o},${t})`}}return e}};B.HANDLE_SIZE=6;var J=B,D=class D{constructor(e,t,s,i,n,r,o,a,l){this._name=null;this._showName=!1;this._visible=!0;if(this._id=e,t instanceof h){let c=t,d=s,g=i??"#000000",p=n??!1,z=r??!1,I=o??!1,_=a??0;this._center=c,this._radius=d,this._color=g,this._selectable=p,this._movable=z,this._resizable=I,this._zIndex=_}else{let c=t,d=s,g=i,p=n??"#000000",z=r??!1,I=o??!1,_=a??!1,R=l??0;this._center=new h(c,d),this._radius=g,this._color=p,this._selectable=z,this._movable=I,this._resizable=_,this._zIndex=R}}get id(){return this._id}set id(e){this._id=e}get center(){return this._center}get name(){return this._name}set name(e){this._name=e}get showName(){return this._showName}set showName(e){this._showName=e}get zIndex(){return this._zIndex}set zIndex(e){this._zIndex=e}get visible(){return this._visible??!1}set visible(e){this._visible=e}get color(){return this._color}set color(e){this._color=e}get selectable(){return this._selectable}set selectable(e){this._selectable=e}get movable(){return this._movable}set movable(e){this._movable=e}get resizable(){return this._resizable}set resizable(e){this._resizable=e}getBounds(){return new j(this.center.x-this._radius,this.center.y-this._radius,2*this._radius,2*this._radius)}getOuterBounds(){let e=this.getBounds(),t=this.getResizeHandles();return t.length===0||t.forEach(s=>{e=e.expand(s.rect)}),e}getEventInteractions(e){let t=[];if(this._resizable&&this.getResizeHandles().forEach(i=>{(e===null||i.rect.contains(e))&&t.push({eventTypePrefix:"resize",handleIndex:i.handleIndex})}),this._movable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"move"})}if(this._selectable){let s=this.getBounds();(e===null||s.contains(e))&&t.push({eventTypePrefix:"select"})}return t}getResizeHandles(){let e=this.getBounds().origin.x,t=this.getBounds().origin.y,s=this.getBounds().size.width,i=this.getBounds().size.height,n=D.HANDLE_SIZE,r=n*10,o=n*6,a=1;s>=r&&i>=r?a=-1:s>=o&&i>=o&&(a=0);let l=s<o,c=i<o;return[{rect:new j(new h(e-a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:0},l?null:{rect:new j(new h(e+s/2-n,t-a*n-n),new w(n*2,n*2)),handleIndex:1},{rect:new j(new h(e+s+a*n-n,t-a*n-n),new w(n*2,n*2)),handleIndex:2},c?null:{rect:new j(new h(e+s+a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:3},{rect:new j(new h(e+s+a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:4},l?null:{rect:new j(new h(e+s/2-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:5},{rect:new j(new h(e-a*n-n,t+i+a*n-n),new w(n*2,n*2)),handleIndex:6},c?null:{rect:new j(new h(e-a*n-n,t+i/2-n),new w(n*2,n*2)),handleIndex:7}].filter(g=>g!==null)}handleEvent(e,t){let s=e.data||{};if(e.type==="setcolor"){let i=this._color;this._color=s.color,t(b.ObjectColorChanged,{object:this,oldColor:i,newColor:this._color});return}if(e.type==="setzindex"){let i=this._zIndex;this._zIndex=s.zIndex,t(b.ObjectZIndexChanged,{object:this,oldZIndex:i,newZIndex:this._zIndex});return}if(e.type==="setselectable"){let i=this._selectable;this._selectable=s.isSelectable,t(b.ObjectSelectableChanged,{object:this,oldSelectable:i,newSelectable:this._selectable});return}if(e.type==="setmovable"){let i=this._movable;this._movable=s.isMovable,t(b.ObjectMovableChanged,{object:this,oldMovable:i,newMovable:this._movable});return}if(e.type==="setresizable"){let i=this._resizable;this._resizable=s.isResizable,t(b.ObjectResizableChanged,{object:this,oldResizable:i,newResizable:this._resizable});return}if(e.type==="setvisible"){let i=this._visible??!0;this._visible=s.isVisible,t(b.ObjectVisibleChanged,{object:this,oldVisible:i,newVisible:this._visible??!0});return}}render(e,t){let s=t.has("selected"),i=t.has("hovered"),n=t.has("hoversibling"),o=e.getTransform().a,a=O=>O/o,l=this._center.x,c=this._center.y,d=this._radius,g=a(4),p=a(2),z=a(3),I=a(4),_=this.color,R=this.withAlpha(_,.06);if(e.save(),e.beginPath(),e.arc(l,c,d,0,Math.PI*2),e.fillStyle=R,e.strokeStyle=_,e.lineWidth=p,e.fill(),e.stroke(),e.restore(),s&&(e.save(),e.beginPath(),e.arc(l,c,d+I,0,Math.PI*2),e.setLineDash([a(8),a(6)]),e.strokeStyle="rgba(0,0,0,0.4)",e.lineWidth=z,e.stroke(),e.restore()),this._resizable&&i){let O=this.getResizeHandles?.()??[];e.save(),e.lineWidth=a(n?.5:1),e.strokeStyle=_,e.fillStyle=n?"transparent":"white",e.globalAlpha=n?.75:1;for(let S of O){let C=S.rect.origin.x,u=S.rect.origin.y,f=S.rect.size.width,E=S.rect.size.height,y=a(4),P=new Path2D;P.moveTo(C+y,u),P.lineTo(C+f-y,u),P.arcTo(C+f,u,C+f,u+y,y),P.lineTo(C+f,u+E-y),P.arcTo(C+f,u+E,C+f-y,u+E,y),P.lineTo(C+y,u+E),P.arcTo(C,u+E,C,u+E-y,y),P.lineTo(C,u+y),P.arcTo(C,u,C+y,u,y),P.closePath(),e.fill(P),e.stroke(P)}e.restore()}}withAlpha(e,t){let s=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\s*\)/i);if(s){let i=parseInt(s[1]??"0",10),n=parseInt(s[2]??"0",10),r=parseInt(s[3]??"0",10);return`rgba(${i},${n},${r},${t})`}if(e.startsWith("#")){let i=e.slice(1);if(i.length===3&&(i=i.split("").map(n=>n+n).join("")),i.length===6||i.length===8){let n=parseInt(i.slice(0,2),16),r=parseInt(i.slice(2,4),16),o=parseInt(i.slice(4,6),16);return`rgba(${n},${r},${o},${t})`}}return e}};D.HANDLE_SIZE=6;var ee=D,te=class{constructor(e,t,s,i,n,r){this.visible=!0;this.id=e,this._points=t?t.slice():[],this.color=s??"#000000",this.selectable=i??!1,this.movable=n??!1,this.zIndex=r??0}get points(){return this._points}getBounds(){if(!this._points||this._points.length===0)return new j(new h(0,0),new w(0,0));let e=this._points[0].x,t=this._points[0].x,s=this._points[0].y,i=this._points[0].y;for(let n of this._points)n.x<e&&(e=n.x),n.x>t&&(t=n.x),n.y<s&&(s=n.y),n.y>i&&(i=n.y);return new j(new h(e,s),new w(t-e,i-s))}getOuterBounds(){return this.getBounds()}getEventInteractions(e){let t=[],s=this.getBounds();return this.movable&&(e===null||s.contains(e))&&t.push({eventTypePrefix:"move"}),this.selectable&&(e===null||s.contains(e))&&t.push({eventTypePrefix:"select"}),t}handleEvent(e,t){let s=e.data||{};if(e.type==="setcolor"){let i=this.color;this.color=s.color,t(b.ObjectColorChanged,{object:this,oldColor:i,newColor:this.color});return}if(e.type==="setzindex"){let i=this.zIndex;this.zIndex=s.zIndex,t(b.ObjectZIndexChanged,{object:this,oldZIndex:i,newZIndex:this.zIndex});return}if(e.type==="setselectable"){let i=this.selectable;this.selectable=s.isSelectable,t(b.ObjectSelectableChanged,{object:this,oldSelectable:i,newSelectable:this.selectable});return}if(e.type==="setmovable"){let i=this.movable;this.movable=s.isMovable,t(b.ObjectMovableChanged,{object:this,oldMovable:i,newMovable:this.movable});return}if(e.type==="setvisible"){let i=this.visible;this.visible=s.isVisible,t(b.ObjectVisibleChanged,{object:this,oldVisible:i,newVisible:this.visible});return}if(e.type.startsWith("move")){let i=s.delta;if(i==null){console.warn("Move event missing required data:",e);return}let n=this.getBounds();for(let o of this._points)o.x+=i.x,o.y+=i.y;let r=this.getBounds();t(b.ObjectMoved,{object:this,oldPoint:n.origin,newPoint:r.origin}),t(b.ObjectPositionChanged,{object:this,oldPosition:n,newPosition:r});return}}render(e,t){let s=t.has("selected"),i=t.has("hovered"),r=e.getTransform().a,o=g=>g/r,l=(()=>{if(!this._points||this._points.length===0)return null;let g=new Path2D;g.moveTo(this._points[0].x,this._points[0].y);for(let p=1;p<this._points.length;++p)g.lineTo(this._points[p].x,this._points[p].y);return g.closePath(),g})();if(!l)return;let c=this.getBounds();e.save(),e.strokeStyle=this.color;let d=e.strokeStyle;if(e.fillStyle=this.withAlpha(d,.06),e.lineWidth=o(2),e.fill(l),e.stroke(l),e.restore(),s){let g=o(3),p=o(4),z=c.origin.x-p,I=c.origin.y-p,_=c.size.width+p*2,R=c.size.height+p*2;e.save(),e.setLineDash([o(8),o(6)]),e.lineDashOffset=0,e.strokeStyle="rgba(0,0,0,0.4)",e.lineWidth=g,e.strokeRect(z,I,_,R),e.restore()}}withAlpha(e,t){let s=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([0-9.]+))?\s*\)/i);if(s){let i=parseInt(s[1]??"0",10),n=parseInt(s[2]??"0",10),r=parseInt(s[3]??"0",10);return`rgba(${i},${n},${r},${t})`}if(e.startsWith("#")){let i=e.slice(1);if(i.length===3&&(i=i.split("").map(n=>n+n).join("")),i.length===6||i.length===8){let n=parseInt(i.slice(0,2),16),r=parseInt(i.slice(2,4),16),o=parseInt(i.slice(4,6),16);return`rgba(${n},${r},${o},${t})`}}return e}},A=class{constructor(e=1e3){this.intervalId=null;this.interval=e,this.intervalId=null}attach(e,t){this.start(e)}detach(){this.stop()}start(e){this.intervalId=window.setInterval(()=>{e({type:"tick",data:{}})},this.interval)}stop(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null)}},L=class{constructor(e){this.listeners=[];this.canvas=e}attach(e,t){let s=(i,n,r)=>{typeof n=="string"&&(n=[n]);for(let o of n)i.addEventListener(o,r),this.listeners.push({target:i,type:o,handler:r})};s(this.canvas,"pointerdown",i=>{let n=i,r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointerdown",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,"pointermove",i=>{let n=i;n.preventDefault();let r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointermove",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,"pointerup",i=>{let n=i;n.preventDefault();let r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointerup",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,"pointercancel",i=>{let n=i;if(n.pointerType==="touch")return;n.preventDefault();let r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=!!n.shiftKey,l=!!n.metaKey,c=!!n.ctrlKey,d=!!n.altKey;e({type:"pointercancel",data:{point:o,identifier:n.pointerId,pointerType:n.pointerType,originalEvent:n,button:n.button,shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d}})}),s(this.canvas,["touchstart","touchmove","touchend","touchcancel"],i=>{let n=i;n.preventDefault();let r=o=>Array.from(o).map(a=>{let l=this.canvas.getBoundingClientRect();(l.top!=0||l.left!=0)&&console.warn("Canvas rect is not at 0,0, this may cause issues with touch coordinates.");let c=new h(a.clientX,a.clientY),d=t.screenToWorld(c);return{identifier:a.identifier,point:d,originalTouch:a}});e({type:i.type,data:{touches:r(n.touches),targetTouches:r(n.targetTouches),changedTouches:r(n.changedTouches),originalEvent:n}})}),s(this.canvas,"wheel",i=>{i.preventDefault();let n=i,r=new h(n.offsetX,n.offsetY),o=t.screenToWorld(r),a=new m(n.deltaX,n.deltaY);e({type:"wheel",data:{delta:a,point:o,originalEvent:n}})}),s(window,"resize",()=>{let i=new w(window.innerWidth,window.innerHeight);e({type:"windowresize",data:{size:i}})})}detach(){this.listeners.forEach(({target:e,type:t,handler:s})=>{e.removeEventListener(t,s)}),this.listeners=[]}},k=class{constructor(e){this.id=crypto.randomUUID();this.visible=!0;this.zIndex=-1/0;this.selectable=!1;this.img=e}get width(){return this.img.naturalWidth}get height(){return this.img.naturalHeight}getEventInteractions(e){return[{eventTypePrefix:"drag"}]}getBounds(){return new j(new h(0,0),new w(this.img.width,this.img.height))}getOuterBounds(){return this.getBounds()}render(e,t){e.drawImage(this.img,0,0)}},H=class{constructor(){this.listeners=new Map}on(e,t,s){this.listeners.has(e)||this.listeners.set(e,new Set);let i=s?.once?(n=>{this.off(e,i),t(n)}):t;this.listeners.get(e).add(i)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){e!==b.EngineRenderStarted&&e!==b.EngineRenderCompleted&&console.log("CanvasEvent:",e,t),this.listeners.get(e)?.forEach(s=>s(t))}},b={ObjectPositionChanged:"object:positionchanged",ObjectResized:"object:resized",ObjectMoved:"object:moved",ObjectColorChanged:"object:colorchanged",ObjectZIndexChanged:"object:zindexchanged",ObjectSelectableChanged:"object:selectablechanged",ObjectMovableChanged:"object:movablechanged",ObjectResizableChanged:"object:resizablechanged",ObjectVisibleChanged:"object:visiblechanged",ObjectChanged:"object:changed",ObjectSelected:"object:selected",ObjectDeselected:"object:deselected",ObjectFlagsAdded:"object:flagsadded",ObjectFlagsRemoved:"object:flagsremoved",ObjectAdded:"object:added",ObjectRemoved:"object:removed",ViewportChanged:"viewport:changed",DrawingCompleted:"drawing:completed",EngineStarted:"engine:started",EngineError:"engine:error",EngineBackgroundChanged:"engine:backgroundchanged",EngineRenderStarted:"engine:renderstarted",EngineRenderCompleted:"engine:rendercompleted"},V=class{constructor(e,t){this.engine=t,this.config=e}processToolEvent(e,t){this.config?.handleEvent&&this.config.handleEvent(e,this.engine)}},ne=class{constructor(e,t={}){this.defaultBackgroundImage=`<svg xmlns="http://www.w3.org/2000/svg" width="816" height="1056">
|
|
2
|
+
<rect width="100%" height="100%" fill="#FFF"/>
|
|
3
|
+
<text x="50%" y="50%" text-anchor="middle" fill="#888"
|
|
4
|
+
font-family="monospace" font-size="24">
|
|
5
|
+
Sample Page
|
|
6
|
+
</text>
|
|
7
|
+
</svg>`;this.document=new Blob([this.defaultBackgroundImage],{type:"image/svg+xml;charset=utf-8"});this.emitter=new H;this.toolLockManager=new F;this.eventSources=[];this.recognizers=[];this.tools=[];this.manualRenderers=[];this.modeRenderers=[];this.eventQueue=[];this.processingQueue=!1;this.renderScheduled=!1;this.flags=new Map;this.objects=[];this.needsRender=!1;this.toolRegistry=new Map;this.modes={};this.currentMode="";this.defaultOptions={initialZoom:1,initialPan:{x:10,y:10},defaultMode:"default",addTimerEventSource:!1,proxyObjectsForEvents:!0};this._pan=new m(0,0);this._zoom=1;this.on=this.emitter.on.bind(this.emitter);this.off=this.emitter.off.bind(this.emitter);this.emitExternal=this.emitter.emit.bind(this.emitter);this.options=this.createOptions(t);let s=document.querySelector(e);if(!s)throw new Error(`Container ${e} not found`);this.container=s,this.canvas=document.createElement("canvas"),this.canvas.width=this.container.clientWidth*10,this.canvas.height=this.container.clientHeight*10,this.container.appendChild(this.canvas),this.ctx=this.canvas.getContext("2d"),this.setupDefaultEventSources(),this.setupDefaultTools(),this.setupDefaultRecognizers(),this.setupDefaultModes(),this.setupRenderNodes(),this._zoom=this.options.initialZoom,this._pan=new m(this.options.initialPan.x,this.options.initialPan.y),this.switchMode(this.options.defaultMode),this.emitExternal(b.EngineStarted,{}),this.emitExternal(b.ViewportChanged,{oldPan:new m(0,0),newPan:this.pan,oldZoom:1,newZoom:this.zoom}),this.setBackgroundImage(this.document).then()}get pan(){return this._pan.clone()}get zoom(){return this._zoom}screenToWorld(e){return new h((e.x-this.pan.x)/this.zoom,(e.y-this.pan.y)/this.zoom)}worldToScreen(e){return new h(e.x*this.zoom+this.pan.x,e.y*this.zoom+this.pan.y)}processToolEvent(e,t,s,i,n){e.type.startsWith("windowresize")||(this.canvas.width=this.container.clientWidth,this.canvas.height=this.container.clientHeight)}createOptions(e){return{...this.defaultOptions,...e}}setupDefaultEventSources(){this.options.addTimerEventSource&&this.register(new A),this.register(new L(this.canvas))}setupDefaultRecognizers(){this.register(new U),this.register(new G)}setupDefaultTools(){this.registerTool("hover",()=>new Z,!0),this.registerTool("select",()=>new $,!0),this.registerTool("drawing",()=>new Q,!0),this.registerTool("move",()=>new N,!0),this.registerTool("resize",()=>new K,!0),this.registerTool("lasso",()=>new X,!0),this.registerTool("pan",()=>new q,!0),this.registerTool("zoom",()=>new W,!0),this.registerTool("api",()=>new Y,!0)}setupDefaultModes(){this.defineMode("default",{tools:["hover","select","resize","move","pan","zoom","api"]}),this.defineMode("move",{tools:["hover","select","resize","move","pan","zoom","api"]}),this.defineMode("create",{tools:["hover","drawing","zoom","api"],handleEvent(e,t){e.type===b.DrawingCompleted&&t.switchMode("default")}}),this.defineMode("lasso",{tools:["hover","select","lasso","zoom","api"],handleEvent(e,t){e.type==="lassoselected"&&t.switchMode("default")}})}setupRenderNodes(){}wrapInteractiveObject(e){let t=this;return new Proxy(e,{set(s,i,n){let r=s[i],o=Reflect.set(s,i,n);return typeof i=="string"&&i.startsWith("_")||r!==n&&t.emitExternal(b.ObjectChanged,{object:s,property:i.toString(),oldValue:r,newValue:n}),o}})}registerTool(e,t,s=!0){if(this.toolRegistry.has(e))throw new Error(`Tool '${e}' already registered.`);this.toolRegistry.set(e,{factory:t,singleton:s})}resolveTool(e){let t=this.toolRegistry.get(e);if(!t)throw new Error(`Unknown tool '${e}'`);return t.singleton?("instance"in t||(t.instance=t.factory()),t.instance):t.factory()}defineMode(e,t){if(this.modes[e])throw new Error(`Mode '${e}' already defined.`);this.modes[e]=t}get mode(){return this.currentMode}switchMode(e){if(!this.modes[e])throw new Error(`Unknown mode '${e}'`);if(this.toolLockManager.isLocked){console.warn("Cannot switch modes while tools are locked. Please release all locks first.");return}if(this.currentMode===e){console.warn(`Already in mode '${e}', no switch needed.`);return}this.currentMode=e;let t=this.modes[e];if(t.tools==null||t.tools.length==0)return;let s=t.tools;this.tools=[...new Set(s.map(i=>this.resolveTool(i)))],this.modeRenderers=t.renderers||[],t.handleEvent&&this.tools.push(new V(t,this)),console.log(`Switched to mode '${e}'`)}get renderers(){var e=this.tools.filter(t=>typeof t=="object"&&t!==null&&("renderBeforeAll"in t||"renderBeforeObject"in t||"renderAfterObject"in t||"renderAfterAll"in t)&&(typeof t.renderBeforeAll=="function"||typeof t.renderBeforeObject=="function"||typeof t.renderAfterObject=="function"||typeof t.renderAfterAll=="function")).map(t=>t);return[...new Set([...this.manualRenderers,...this.modeRenderers,...e])]}get width(){let e=this.getObjectsWithFlag("canvas-background").filter(s=>typeof s=="object"&&s instanceof k),t;return e.length==0?this.canvas.width:(e.length>=1&&(t=e[0]),t.width)}get height(){let e=this.getObjectsWithFlag("canvas-background").filter(s=>typeof s=="object"&&s instanceof k),t;return e.length==0?this.canvas.height:(e.length>=1&&(t=e[0]),t.height)}get documentBlob(){return this.document}async setBackgroundImage(e){let t=this.width,s=this.height,i;e instanceof File||e instanceof Blob?i=e:i=await this.loadImageFromUrl(e),this.document=i;let n=URL.createObjectURL(i),r=await this.loadImage(n),o=this.getObjectsWithFlag("canvas-background");if(o.length>0){let a=o.find(l=>l instanceof k);a&&(a.img=r)}else{let a=new k(r);this.objects.push(a),this.setFlag(a.id,"canvas-background")}this.emitExternal(b.EngineBackgroundChanged,{newImage:r,newWidth:r.width,newHeight:r.height,oldWidth:t,oldHeight:s})}async loadImageFromUrl(e){let t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch image: ${t.status} ${t.statusText}`);return await t.blob()}loadImage(e){return new Promise((t,s)=>{if(e instanceof HTMLImageElement){e.complete&&e.naturalWidth!==0?t(e):(e.onload=()=>t(e),e.onerror=s);return}let i=new Image;i.onload=()=>t(i),i.onerror=s,i.src=e})}getObject(e){return this.objects.find(s=>s.id===e)}addObject(e){if(this.objects.find(s=>s.id===e.id))throw new Error(`Object with id '${e.id}' already exists.`);this.objects.push(e),this.enqueue({type:"redraw",data:{}}),this.emitExternal(b.ObjectAdded,{object:this.options.proxyObjectsForEvents?this.wrapInteractiveObject(e):e})}removeObject(e){let t=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!t)throw new Error(`Object not found: ${e}`);let s=this.objects.indexOf(t);if(s!==-1){this.objects.splice(s,1);let i=typeof e=="string"?e:e.id;this.flags.delete(i),this.emitExternal(b.ObjectRemoved,{object:t})}else console.warn("Attempted to remove an object that does not exist in the engine:",t);this.redraw()}moveObjectToPoint(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.x,r=typeof t=="number"?s??0:t.y;this.enqueue({type:"api:moveto",data:{x:n,y:r},targets:[i]})}moveObjectByVector(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.x,r=typeof t=="number"?s??0:t.y;this.enqueue({type:"api:moveby",data:{dx:n,dy:r},targets:[i]})}resizeObjectToSize(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.width,r=typeof t=="number"?s??0:t.height;this.enqueue({type:"api:resizeto",data:{width:n,height:r},targets:[i]})}resizeObjectByVector(e,t,s){let i=typeof e=="string"?this.objects.find(o=>o.id===e):e;if(!i)throw new Error(`Object not found: ${e}`);let n=typeof t=="number"?t:t.x,r=typeof t=="number"?s??0:t.y;this.enqueue({type:"api:resizeby",data:{dw:n,dh:r},targets:[i]})}setObjectColor(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setcolor",data:{color:t},targets:[s]})}setObjectZIndex(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setzindex",data:{zIndex:t},targets:[s]})}updateObjectSelectability(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setselectable",data:{isSelectable:t},targets:[s]})}updateObjectMovability(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setmovable",data:{isMovable:t},targets:[s]})}updateObjectResizeability(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setresizable",data:{isResizable:t},targets:[s]})}updateObjectVisibility(e,t){let s=typeof e=="string"?this.objects.find(i=>i.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);this.enqueue({type:"api:setvisible",data:{visible:t},targets:[s]})}setFlag(e,t){let s=typeof e=="string"?this.objects.find(r=>r.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);let i=typeof e=="string"?e:e.id;if(this.flags.has(i)||this.flags.set(i,new Set),t=="selected"&&!s.selectable)return console.warn(`Cannot set flag '${t}' on non-selectable object`,s);let n=this.flags.get(i);n.has(t)||(n.add(t),this.emitExternal(b.ObjectFlagsAdded,{object:s,addedFlags:[t],currentFlags:[...this.flags.get(i)]}),t==="selected"&&this.emitExternal(b.ObjectSelected,{object:s}),this.ensureEventLoop())}clearFlag(e,t){let s=typeof e=="string"?this.objects.find(n=>n.id===e):e;if(!s)throw new Error(`Object not found: ${e}`);let i=typeof e=="string"?e:e.id;this.flags.get(i)?.delete(t),this.emitExternal(b.ObjectFlagsRemoved,{object:s,removedFlags:[t],currentFlags:[...this.flags.get(i)||[]]}),t==="selected"&&this.emitExternal(b.ObjectDeselected,{object:s}),this.ensureEventLoop()}hasFlag(e,t){let s=typeof e=="string"?e:e.id;return this.flags.get(s)?.has(t)??!1}clearAllFlags(e){for(let[t,s]of this.flags.entries()){let i=this.objects.find(n=>n.id===t)??null;if(!i)throw new Error(`Object not found: ${t}`);s.delete(e),this.emitExternal(b.ObjectFlagsRemoved,{object:i,removedFlags:[e],currentFlags:[...this.flags.get(t)||[]]}),e==="selected"&&this.emitExternal(b.ObjectDeselected,{object:i})}this.ensureEventLoop()}getObjectsWithFlag(e){return[...this.flags.entries()].filter(([t,s])=>s.has(e)).filter(([t,s])=>{let i=this.objects.find(n=>n.id===t)??null;if(!i)throw new Error(`Object not found: ${t}`);return e==="selected"?i.selectable:!0}).map(([t])=>this.objects.find(s=>s.id===t))}setZoom(e,t){if(e<=0){console.warn("Zoom must be greater than 0, ignoring.");return}let s=this.zoom,i=new m(this.pan.x,this.pan.y);if(this._zoom=e,t){let n=t.x-(t.x-this.pan.x)*(e/s),r=t.y-(t.y-this.pan.y)*(e/s);this._pan=new m(n,r)}this.emitExternal(b.ViewportChanged,{oldPan:i,newPan:this.pan,oldZoom:s,newZoom:this.zoom}),this.ensureEventLoop()}setPan(e,t){let s=this.pan.clone();typeof e=="number"?this._pan=new m(e,t??0):this._pan=e.clone(),this.emitExternal(b.ViewportChanged,{oldPan:s,newPan:this.pan,oldZoom:this.zoom,newZoom:this.zoom}),this.ensureEventLoop()}setSelectedObjects(e){let t=e.map(r=>typeof r=="string"?this.objects.find(o=>o.id===r):r),s=this.getSelectedObjects(),i=s.filter(r=>!t.includes(r)),n=t.filter(r=>!s.includes(r));i.forEach(r=>this.clearFlag(r,"selected")),n.forEach(r=>this.setFlag(r,"selected")),this.ensureEventLoop()}getSelectedObjects(){return this.getObjectsWithFlag("selected").filter(e=>e.selectable)}getAllObjects(){let e=this.getObjectsWithFlag("canvas-background").filter(t=>typeof t=="object"&&t instanceof k);return[...this.objects].filter(t=>e.includes(t)==!1)}getTopMostInteractionPerEventType(e){let t=new Map,s=[...this.objects].sort((i,n)=>(i.zIndex??0)-(n.zIndex??0));for(let i=s.length-1;i>=0;i--){let n=s[i];if(!n)continue;n.getEventInteractions(e).forEach(o=>{let a=o.eventTypePrefix;if(!t.has(a)){let l={object:n,interaction:o};t.set(a,l)}})}return t}enqueue(e){this.eventQueue.push(e),this.ensureEventLoop()}ensureEventLoop(){this.processingQueue||(this.processingQueue=!0,setTimeout(()=>this.processQueue(),0))}processQueue(){for(;this.eventQueue.length;){let e=this.eventQueue.shift();if(!e.stopPropagation&&(this.recognizers.forEach(t=>{e.stopPropagation||t.process(e,s=>this.eventQueue.push(s))}),!e.stopPropagation&&(this.tools.forEach(t=>{e.stopPropagation||t.processToolEvent(e,s=>this.eventQueue.push(s),this.emitExternal,this,this.toolLockManager.getToolLock(t))}),!e.stopPropagation&&(this.processToolEvent(e,t=>this.eventQueue.push(t),this.emitExternal,this,this.toolLockManager.getToolLock(this)),e.type.startsWith("pointer")==!1,e.targets&&e.targets.length>0)))){let t=e.targets;for(let s of t)s.handleEvent&&s.handleEvent(e,this.emitExternal)}}this.processingQueue=!1,this.requestRender()}addEventSource(e){this.eventSources.push(e),e.attach(t=>this.enqueue(t),this)}removeEventSource(e){this.eventSources=this.eventSources.filter(t=>t!==e),e.detach?.()}addRecognizer(e){this.recognizers.push(e)}addRenderNode(e){this.renderers.push(e)}register(e){typeof e=="object"&&e!==null&&"attach"in e&&typeof e.attach=="function"&&this.addEventSource(e),typeof e=="object"&&e!==null&&"process"in e&&typeof e.process=="function"&&this.addRecognizer(e),typeof e=="object"&&e!==null&&("renderBeforeAll"in e||"renderBeforeObject"in e||"renderAfterObject"in e||"renderAfterAll"in e)&&(typeof e.renderBeforeAll=="function"||typeof e.renderBeforeObject=="function"||typeof e.renderAfterObject=="function"||typeof e.renderAfterAll=="function")&&this.addRenderNode(e)}redraw(){this.requestRender()}requestRender(){this.needsRender=!0,this.renderScheduled||(this.renderScheduled=!0,requestAnimationFrame(()=>{this.needsRender&&(this.doRender(this.ctx),this.needsRender=!1),this.renderScheduled=!1}))}doRender(e){e.save(),e.setTransform(this.zoom,0,0,this.zoom,this.pan.x,this.pan.y),e.clearRect(-this.pan.x/this.zoom,-this.pan.y/this.zoom,this.canvas.width/this.zoom,this.canvas.height/this.zoom),this.emitExternal(b.EngineRenderStarted,{}),this.renderers.forEach(t=>t.renderBeforeAll?.(e,this));for(let t of this.objects.filter(s=>s.visible).sort((s,i)=>s.zIndex-i.zIndex))this.renderers.forEach(s=>s.renderBeforeObject?.(e,this,t)),t.render(e,this.flags.get(t.id)??new Set),this.renderers.forEach(s=>s.renderAfterObject?.(e,this,t));this.renderers.forEach(t=>t.renderAfterAll?.(e,this)),this.emitExternal(b.EngineRenderCompleted,{}),e.restore()}dispose(){this.eventSources.forEach(e=>e.detach?.())}},F=class{constructor(){this.currentTool=null}get isLocked(){return this.currentTool!==null}getToolLock(e){return{hasLock:()=>this.currentTool===e,acquire:()=>this.currentTool===null||this.currentTool===e?(this.currentTool=e,!0):!1,release:()=>this.currentTool===null||this.currentTool===e?(this.currentTool=null,!0):(console.warn("Tool lock released by a tool that does not own it:",e),!1)}}},W=class{constructor(){this.passive=!1;this.zoomFactor=1.1;this.pinchZoomFactor=.5;this.minZoom=.1;this.maxZoom=10}processToolEvent(e,t,s,i,n){switch(e.type){case"wheel":this.handleWheelZoom(e,i,n);break;case"gesture":this.handlePinchZoom(e,i,n);break;case"keyZoomIn":break;case"keyZoomOut":break}}handleWheelZoom(e,t,s){let i=e.data||{},n=i.delta||new m(0,0),r=i.point||new h(0,0),o=n.y<0?this.zoomFactor:1/this.zoomFactor;this.applyZoom(t,o,r.x*t.zoom+t.pan.x,r.y*t.zoom+t.pan.y,s)}handlePinchZoom(e,t,s){let i=e.data||{},n=i.scaleDelta,r=i.clientX,o=i.clientY,a=1+n*this.pinchZoomFactor;this.applyZoom(t,a,r,o,s)}applyZoom(e,t,s,i,n){let r=e.zoom,o=Math.min(Math.max(r*t,this.minZoom),this.maxZoom);o!==r&&n.acquire()&&(e.pan.x=s-(s-e.pan.x)*(o/r),e.pan.y=i-(i-e.pan.y)*(o/r),e.setZoom(o,new h(s,i)),n.release())}},q=class{constructor(){this.priority=-1/0;this.active=!1;this.startClient=new h(0,0);this.origPan=new m(0,0)}processToolEvent(e,t,s,i,n){if(!e.type.startsWith("drag"))return!1;let o=(e.data||{}).point,a=i.worldToScreen(o);if(o!==null){var l=i.getTopMostInteractionPerEventType(o);if(l&&l.has("drag")){var c=l.get("drag");if(c&&i.hasFlag(c.object,"canvas-background")){if(e.type==="dragstart"){if(!n.acquire())return;this.startClient=a,this.origPan=i.pan.clone(),this.active=!0}if(e.type==="dragend"||e.type==="dragcancel"){this.active=!1,this.startClient=new h(0,0),this.origPan=new m(0,0),n.release();return}if(this.active==!1)return;n.hasLock()&&i.setPan(this.origPan.add(a.getDeltaFromPoint(this.startClient)))}}}}},N=class{constructor(){this.objectsBeingMoved=[];this.lastDelta=null}processToolEvent(e,t,s,i,n){let r=e.data||{},o=r.point,a=r.delta,l=this.lastDelta==null?a:this.lastDelta,c=this.lastDelta==null?a:a?.subtract(l);switch(e.type){case"dragstart":if(!o)return;let g=i.getTopMostInteractionPerEventType(o).get("move");if(g){if(!n.acquire())return;let p=i.getSelectedObjects();p.length===0||p.some(z=>z===g.object)===!1?this.objectsBeingMoved=[g.object]:this.objectsBeingMoved=p}break;case"drag":if(!a||this.objectsBeingMoved==null||this.objectsBeingMoved.length===0)return;this.lastDelta=a,t({type:"move",data:{delta:c,point:o},targets:this.objectsBeingMoved});break;case"dragend":if(!a||this.objectsBeingMoved==null||this.objectsBeingMoved.length===0){this.lastDelta=null,this.objectsBeingMoved=[];return}t({type:"move",data:{origin,delta:c,point:o},targets:this.objectsBeingMoved}),this.lastDelta=null,this.objectsBeingMoved=[],n.release();break;case"dragcancel":(!a||this.objectsBeingMoved==null||this.objectsBeingMoved.length===0)&&(this.lastDelta=null,this.objectsBeingMoved=[]),t({type:"move",data:{origin,delta:l?.subtract(a)||new m(0,0),point:origin},targets:this.objectsBeingMoved}),this.lastDelta=null,this.objectsBeingMoved=[],n.release();break}}},$=class{constructor(){this.priority=100}processToolEvent(e,t,s,i,n){if(e.type!=="click")return;let r=e.data||{},o=r.point;if(!o)return;let l=i.getTopMostInteractionPerEventType(o).get("select"),c=i.getSelectedObjects(),d=r.metaHeld||r.ctrlHeld||r.shiftHeld;if(l){let g=c.some(z=>z===l.object);if(!(c.length===1&&g)){if(!n.acquire())return;d?i.setSelectedObjects([...c,l.object]):i.setSelectedObjects([l.object]),n.release()}}else i.setSelectedObjects([])}},Z=class{constructor(){this.priority=-100}processToolEvent(e,t,s,i,n){if(e.type!=="pointermove")return;let o=(e.data||{}).point;if(!o)return;for(let l of i.getObjectsWithFlag("hoversibling"))i.clearFlag(l,"hoversibling"),i.setFlag(l,"hovered");for(let l of i.getObjectsWithFlag("hovered"))l.getOuterBounds().contains(o)||i.clearFlag(l,"hovered");for(let l of i.getAllObjects())l.getBounds().contains(o)&&i.setFlag(l,"hovered");let a=!1;for(let l of i.getSelectedObjects())i.hasFlag(l,"hovered")&&(a=!0);if(a)for(let l of i.getSelectedObjects())i.hasFlag(l,"hovered")||(i.setFlag(l,"hovered"),i.setFlag(l,"hoversibling"))}},K=class{constructor(){this.activeHandleIndex=null;this.objectsBeingResized=[];this.lastDelta=null}processToolEvent(e,t,s,i,n){let r=e.data||{},o=r.point,a=r.delta,l=r.origin,c=this.lastDelta==null?a:this.lastDelta,d=this.lastDelta==null?a:a?.subtract(c);switch(e.type){case"dragstart":if(!o)return;let p=i.getTopMostInteractionPerEventType(o).get("resize");if(p&&p.interaction.handleIndex!=null){if(!n.acquire())return;let z=i.getSelectedObjects();z.length===0||z.some(I=>I===p.object)===!1?this.objectsBeingResized=[p.object]:this.objectsBeingResized=z,this.activeHandleIndex=p.interaction.handleIndex,t({type:"resizestart",data:{handleIndex:this.activeHandleIndex,point:o},targets:this.objectsBeingResized})}break;case"drag":if(this.activeHandleIndex==null||!a||this.objectsBeingResized==null||this.objectsBeingResized.length===0)return;this.lastDelta=a,t({type:"resize",data:{handleIndex:this.activeHandleIndex,delta:d,point:o},targets:this.objectsBeingResized});break;case"dragend":if(this.activeHandleIndex==null||!a||this.objectsBeingResized==null||this.objectsBeingResized.length===0){this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[];return}t({type:"resize",data:{handleIndex:this.activeHandleIndex,origin:l,delta:d,point:o},targets:this.objectsBeingResized}),t({type:"resizeend",data:{handleIndex:this.activeHandleIndex,delta:d,point:o},targets:this.objectsBeingResized}),this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[],n.release();break;case"dragcancel":(this.activeHandleIndex==null||!a||this.objectsBeingResized==null||this.objectsBeingResized.length===0)&&(this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[]),t({type:"resize",data:{handleIndex:this.activeHandleIndex,origin:l,delta:c?.subtract(a)||new m(0,0),point:l},targets:this.objectsBeingResized}),this.activeHandleIndex=null,this.lastDelta=null,this.objectsBeingResized=[],n.release();break}}},Q=class{constructor(e="black"){this.drawing=!1;this.startPt=null;this.currentPt=null;this.defaultColor="black";this.defaultColor=e}processToolEvent(e,t,s,i,n){let o=(e.data||{}).point;switch(e.type){case"dragstart":if(!o||!n.acquire())return;this.drawing=!0,this.startPt=o,this.currentPt=o;break;case"drag":if(!this.drawing||!n.hasLock()||!o)return;this.currentPt=o;break;case"dragend":if(this.drawing&&n.hasLock()&&this.startPt&&o){this.currentPt=o;let a=Math.min(this.startPt.x,this.currentPt.x),l=Math.min(this.startPt.y,this.currentPt.y),c=Math.abs(this.currentPt.x-this.startPt.x),d=Math.abs(this.currentPt.y-this.startPt.y),g=new j(a,l,c,d),p=i.getAllObjects().reduce((z,I)=>Math.max(z,I.zIndex),0);this.drawing=!1,n.release(),s(b.DrawingCompleted,{rect:g,maxZ:p})}case"dragcancel":this.drawing&&n.hasLock()&&(this.drawing=!1,this.startPt=null,this.currentPt=null,n.release());break}}renderAfterAll(e,t){if(!this.drawing||!this.startPt||!this.currentPt)return;let s=Math.min(this.startPt.x,this.currentPt.x),i=Math.min(this.startPt.y,this.currentPt.y),n=Math.abs(this.currentPt.x-this.startPt.x),r=Math.abs(this.currentPt.y-this.startPt.y);e.save(),e.strokeStyle=this.defaultColor,e.lineWidth=2/e.getTransform().a,e.setLineDash([4/e.getTransform().a,2/e.getTransform().a]),e.strokeRect(s,i,n,r),e.setLineDash([]),e.restore()}},X=class{constructor(){this.lassoing=!1;this.points=[]}processToolEvent(e,t,s,i,n){let o=(e.data||{}).point;switch(e.type){case"dragstart":if(!o||!n.acquire())return;this.lassoing=!0,this.points=[o];break;case"drag":if(!this.lassoing||!n.hasLock()||!o)return;this.points.push(o);break;case"dragend":if(this.lassoing&&n.hasLock()&&o){this.points.push(o);let a=new M(this.points),l=[];for(let c of i.getAllObjects()){let d=c.getBounds();if(a.containsRect(d)){l.push(c);continue}}i.setSelectedObjects(l),t({type:"lassoselected",data:{polygon:a,selectedObjects:l}})}case"dragcancel":this.lassoing&&n.hasLock()&&(this.lassoing=!1,this.points=[],n.release());break}}renderAfterAll(e,t){if(!(!this.lassoing||this.points.length===0)){e.save(),e.strokeStyle="black",e.lineWidth=1/e.getTransform().a,e.setLineDash([4/e.getTransform().a,2/e.getTransform().a]),e.beginPath(),e.moveTo(this.points[0].x,this.points[0].y);for(let s=1;s<this.points.length;s++)e.lineTo(this.points[s].x,this.points[s].y);e.stroke(),e.restore()}}},Y=class{processToolEvent(e,t,s,i,n){if(!e.type.startsWith("api:"))return;e.stopPropagation=!0;let r=e.targets;if(!r||r.length===0)return;let o=r[0];if(!o){console.warn("API event has no target object:",e);return}if(!i.getAllObjects().includes(o)){console.warn("API event targets an object not in the engine:",o);return}switch(e.type){case"api:moveto":{if(!n.acquire())return;let{x:a,y:l}=e.data,d=o.getBounds().origin,g=new m(a-d.x,l-d.y);t({type:"move",data:{delta:g,origin:d,point:d},targets:[o]}),n.release();break}case"api:moveby":{if(!n.acquire())return;let{dx:a,dy:l}=e.data;t({type:"move",data:{delta:new m(a,l)},targets:[o]}),n.release();break}case"api:resizeto":{if(!n.acquire())return;let{width:a,height:l}=e.data,c=o.getBounds(),d=c.origin,g=a-c.size.width,p=l-c.size.height;t({type:"resizestart",data:{handleIndex:4,origin:d,point:d},targets:[o]}),t({type:"resize",data:{handleIndex:4,delta:new m(g,p),point:d},targets:[o]}),t({type:"resizeend",data:{handleIndex:4,delta:new m(g,p),point:d},targets:[o]}),n.release();break}case"api:resizeby":{if(!n.acquire())return;let{dW:a,dH:l}=e.data,d=o.getBounds().origin;t({type:"resizestart",data:{handleIndex:4,origin:d,point:d},targets:[o]}),t({type:"resize",data:{handleIndex:4,delta:new m(a,l),point:d},targets:[o]}),t({type:"resizeend",data:{handleIndex:4,delta:new m(a,l),point:d},targets:[o]}),n.release();break}case"api:setcolor":{let{color:a}=e.data;t({type:"setcolor",data:{color:a},targets:[o]});break}case"api:setzindex":{let{zIndex:a}=e.data;t({type:"setzindex",data:{zIndex:a},targets:[o]});break}case"api:setselectable":{let{isSelectable:a}=e.data;t({type:"setselectable",data:{isSelectable:a},targets:[o]});break}case"api:setmovable":{if(!n.acquire())return;let{isMovable:a}=e.data;t({type:"setmovable",data:{isMovable:a},targets:[o]}),n.release();break}case"api:setresizable":{if(!n.acquire())return;let{isResizable:a}=e.data;t({type:"setresizable",data:{isResizable:a},targets:[o]}),n.release();break}case"api:setvisible":{let{visible:a}=e.data;t({type:"setvisible",data:{isVisible:a},targets:[o]});break}}}},U=class{constructor(e=5){this.activePointerIds=new Set;this.isDragging=!1;this.buttonStart=null;this.origin=new h(0,0);this.moveThreshold=e}process(e,t){let{type:s,data:i={}}=e;switch(s){case"pointerdown":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=i.button;this.handleStart(r,i.pointerType,n,o,t)}break;case"touchstart":{let n=this.getTouches(e);if(n.length===1){let r=n[0],o=r.point,a=r.identifier;this.handleStart(a,"touch",o,null,t)}break}case"pointermove":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new m(0,0),a=i.button;this.handleMove(r,i.pointerType,n,o,a,t)}break;case"touchmove":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new m(0,0);this.handleMove(o,"touch",r,a,null,t)}break}case"pointerup":case"pointercancel":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new m(0,0),a=i.button;this.handleEnd(r,i.pointerType,n,o,a,t)}break;case"touchend":case"touchcancel":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new m(0,0);this.handleEnd(o,"touch",r,a,null,t)}break}}}handleStart(e,t,s,i,n){this.isDragging||e==null||s==null||s.x==null||s.y==null||n==null||(this.activePointerIds.add(e),this.origin=s,this.buttonStart=i??null,n({type:"dragpotential",data:{identifier:e,pointerType:t,point:origin}}))}handleMove(e,t,s,i,n,r){if(!(e==null||s==null||i==null||!this.activePointerIds.has(e)||r==null)){var o=s.subtract(i);!this.isDragging&&(this.buttonStart==null||this.buttonStart==0)&&(i.length()>=this.moveThreshold?(this.activePointerIds.clear(),this.activePointerIds.add(e),this.isDragging=!0,r({type:"dragstart",data:{identifier:e,pointerType:t,point:o}})):r({type:"dragpotentialmove",data:{identifier:e,pointerType:t,origin:o,delta:i,point:s}})),this.isDragging&&r({type:"drag",data:{identifier:e,pointerType:t,origin:o,delta:i,point:s}})}}handleEnd(e,t,s,i,n,r){if(!this.isDragging||e==null||s==null||i==null||!this.activePointerIds.has(e)||r==null){this.activePointerIds.clear();return}var o=s.add(i);r({type:"dragend",data:{identifier:e,pointerType:t,origin:o,point:s,delta:i}}),this.activePointerIds.clear(),this.isDragging=!1,this.buttonStart=null}getTouches(e){return e.data?.changedTouches??[]}findActiveTouch(e){return this.getTouches(e).find(t=>this.activePointerIds.has(t.identifier))}},G=class{constructor(e=5){this.activePointerIds=new Set;this.origin=new h(0,0);this.moveThreshold=e}process(e,t){let{type:s,data:i={}}=e;switch(s){case"pointerdown":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier;this.handleStart(r,n)}break;case"touchstart":{let n=this.getTouches(e);if(n.length===1){let r=n[0],o=r.point,a=r.identifier;this.handleStart(a,o)}break}case"pointermove":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new m(0,0);this.handleMove(r,n,o)}break;case"touchmove":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new m(0,0);this.handleMove(o,r,a)}break}case"pointerup":case"pointercancel":if(i.pointerType!=="touch"){let n=i.point,r=e.data?.identifier,o=n?.getDeltaFromPoint(this.origin)||new m(0,0),a=e.data?.shiftHeld??!1,l=e.data?.metaHeld??!1,c=e.data?.ctrlHeld??!1,d=e.data?.altHeld??!1;this.handleEnd(r,i.pointerType,n,o,{shiftHeld:a,metaHeld:l,ctrlHeld:c,altHeld:d},t)}break;case"touchend":case"touchcancel":{let n=this.findActiveTouch(e);if(n){let r=n.point,o=n.identifier,a=r?.getDeltaFromPoint(this.origin)||new m(0,0);this.handleEnd(o,"touch",r,a,t)}break}}}handleStart(e,t){e==null||t==null||t.x==null||t.y==null||(this.activePointerIds.add(e),this.origin=t)}handleMove(e,t,s){e==null||t==null||s==null||!this.activePointerIds.has(e)||s.length()>=this.moveThreshold&&this.activePointerIds.clear()}handleEnd(e,t,s,i,n,r){if(!(e==null||s==null||i==null||!this.activePointerIds.has(e)||r==null)){if(i.length()>=this.moveThreshold){this.activePointerIds.clear();return}var o={identifier:e,pointerType:t,point:s};n&&(o={...o,...n}),r({type:"click",data:o}),this.activePointerIds.clear()}}getTouches(e){return e.data?.changedTouches??[]}findActiveTouch(e){return this.getTouches(e).find(t=>this.activePointerIds.has(t.identifier))}},h=class v{constructor(e,t){this.x=e,this.y=t}equals(e){return this.x===e.x&&this.y===e.y}static equals(e,t){return e.x===t.x&&e.y===t.y}getDeltaFromPoint(e){return new m(this.x-e.x,this.y-e.y)}getDeltaToPoint(e){return new m(this.x+e.x,this.y+e.y)}add(e){return new v(this.x+e.x,this.y+e.y)}asVector(){return new m(this.x,this.y)}subtract(e){return new v(this.x-e.x,this.y-e.y)}isInside(e){return e.contains(this)}clone(){return new v(this.x,this.y)}isInPolygon(e){return e.containsPoint(this)}},w=class v{constructor(e,t){this.width=e,this.height=t}equals(e){return this.width===e.width&&this.height===e.height}static equals(e,t){return e.width===t.width&&e.height===t.height}clone(){return new v(this.width,this.height)}},j=class v{constructor(e,t,s,i){let n=typeof e=="number"&&typeof t=="number"?new h(e,t):e,r=typeof t=="number"&&typeof s=="number"&&typeof i=="number"?new w(s,i):t;this.origin=n,this.size=r}equals(e){return this.origin.equals(e.origin)&&this.size.equals(e.size)}static equals(e,t){return e.origin.equals(t.origin)&&e.size.equals(t.size)}contains(e){return e.x>=this.origin.x&&e.x<=this.origin.x+this.size.width&&e.y>=this.origin.y&&e.y<=this.origin.y+this.size.height}clone(){return new v(new h(this.origin.x,this.origin.y),new w(this.size.width,this.size.height))}center(){return new h(this.origin.x+this.size.width/2,this.origin.y+this.size.height/2)}normalized(){if(this.isNormalized())return this;let e=this.clone();return e.normalize(),e}isNormalized(){return this.size.width>=0&&this.size.height>=0}normalize(){this.size.width<0&&(this.origin.x+=this.size.width,this.size.width=-this.size.width),this.size.height<0&&(this.origin.y+=this.size.height,this.size.height=-this.size.height)}expand(e){let t=new h(Math.min(this.origin.x,e.origin.x),Math.min(this.origin.y,e.origin.y)),s=Math.max(this.origin.x+this.size.width,e.origin.x+e.size.width)-t.x,i=Math.max(this.origin.y+this.size.height,e.origin.y+e.size.height)-t.y;return new v(t,new w(s,i))}move(e){return new v(new h(this.origin.x+e.x,this.origin.y+e.y),new w(this.size.width,this.size.height))}toPolygon(){return new M([new h(this.origin.x,this.origin.y),new h(this.origin.x+this.size.width,this.origin.y),new h(this.origin.x+this.size.width,this.origin.y+this.size.height),new h(this.origin.x,this.origin.y+this.size.height)])}},m=class v{constructor(e,t){this.x=e,this.y=t}equals(e){return this.x===e.x&&this.y===e.y}static equals(e,t){return e.x===t.x&&e.y===t.y}add(e){return new v(this.x+e.x,this.y+e.y)}subtract(e){return new v(this.x-e.x,this.y-e.y)}scale(e){return new v(this.x*e,this.y*e)}length(){return Math.hypot(this.x,this.y)}normalize(){let e=this.length();return e===0?new v(0,0):new v(this.x/e,this.y/e)}clone(){return new v(this.x,this.y)}},M=class{constructor(e){this.points=e}equals(e){if(this.points.length!==e.points.length)return!1;for(let t=0;t<this.points.length;t++)if(!this.points[t].equals(e.points[t]))return!1;return!0}static equals(e,t){return e.equals(t)}containsPoint(e){let t=this.points,s=!1;for(let i=0,n=t.length-1;i<t.length;n=i++){let r=t[i].x,o=t[i].y,a=t[n].x,l=t[n].y;o>e.y!=l>e.y&&e.x<(a-r)*(e.y-o)/(l-o)+r&&(s=!s)}return s}containsRect(e){return this.containsPoint(e.origin)&&this.containsPoint(new h(e.origin.x+e.size.width,e.origin.y+e.size.height))&&this.containsPoint(new h(e.origin.x+e.size.width,e.origin.y))&&this.containsPoint(new h(e.origin.x,e.origin.y+e.size.height))}};export{Y as ApiTool,ne as CanvasEngine,ee as CircleObject,G as ClickGestureRecognizer,L as DomEventSource,U as DragGestureRecognizer,Q as DrawingTool,b as EngineEventType,Z as HoverTool,X as LassoTool,N as MoveTool,h as Point,M as Polygon,te as PolygonObject,j as Rectangle,K as ResizeTool,$ as SelectTool,w as Size,F as ToolLockManager,m as Vector,J as Zone};
|
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dytools-canvas-engine",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.cjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup src/index.ts --format esm,cjs --minify --no-sourcemap false --clean"
|
|
17
|
+
}
|
|
18
|
+
}
|