@ue-too/board 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -61,7 +61,7 @@ Additional examples in the [`devserver`](https://github.com/niuee/board/tree/mai
61
61
 
62
62
  ## Installation and Usage
63
63
 
64
- ### Package Manager
64
+ ### Installation
65
65
  ```bash
66
66
  npm install @ue-too/board
67
67
  ```
@@ -70,13 +70,6 @@ npm install @ue-too/board
70
70
  import { Board } from "@ue-too/board";
71
71
  ```
72
72
 
73
- ### Import from jsdelivr
74
- ```javascript
75
- import { Board } from "https://cdn.jsdelivr.net/npm/@ue-too/board@latest/index.js";
76
- ```
77
-
78
- > Note: IIFE format is no longer supported.
79
-
80
73
  ## Key Features
81
74
  - Modularity: Use only the components you need (details in the [Under the Hood](#under-the-hood) section)
82
75
  - Comprehensive input support: touch, trackpad (macOS), keyboard, and mouse, with customizable behavior
package/index.js CHANGED
@@ -1,3 +1,5 @@
1
1
  import{PointCal as _Q}from"@ue-too/math";class f{observers=[];subscribe(Q,q){if(this.observers.push(Q),q?.signal){if(q.signal.aborted)return this.observers=this.observers.filter((J)=>J!==Q),()=>{};let $=()=>{this.observers=this.observers.filter((J)=>J!==Q),q.signal?.removeEventListener("abort",$)};q.signal.addEventListener("abort",$)}return()=>{this.observers=this.observers.filter(($)=>$!==Q)}}notify(...Q){this.observers.forEach((q)=>queueMicrotask(()=>q(...Q)))}}class i{observers=[];subscribe(Q,q){if(this.observers.push(Q),q?.signal){if(q.signal.aborted)return this.observers=this.observers.filter((J)=>J!==Q),()=>{};let $=()=>{this.observers=this.observers.filter((J)=>J!==Q),q.signal?.removeEventListener("abort",$)};q.signal.addEventListener("abort",$)}return()=>{this.observers=this.observers.filter(($)=>$!==Q)}}notify(...Q){this.observers.forEach((q)=>q(...Q))}}class RQ{pan;zoom;rotate;all;constructor(){this.pan=new f,this.zoom=new f,this.rotate=new f,this.all=new f}notifyPan(Q,q){this.pan.notify(Q,q),this.all.notify({type:"pan",diff:Q.diff},q)}notifyZoom(Q,q){this.zoom.notify(Q,q),this.all.notify({type:"zoom",deltaZoomAmount:Q.deltaZoomAmount},q)}notifyRotate(Q,q){this.rotate.notify(Q,q),this.all.notify({type:"rotate",deltaRotation:Q.deltaRotation},q)}on(Q,q,$){switch(Q){case"pan":return this.pan.subscribe(q,$);case"zoom":return this.zoom.subscribe(q,$);case"rotate":return this.rotate.subscribe(q,$);case"all":return this.all.subscribe(q,$);default:throw Error(`Invalid event name: ${Q}`)}}}import{PointCal as o}from"@ue-too/math";function Yq(Q,q,$,J){let{a:U,b:K,c:G,d:Y,e:j,f:B}=Q,W=-Math.atan2(K,U),_=Math.sqrt(U*U+K*K)/q,E=[j,B];E=[E[0]/q,E[1]/q],E=[E[0]-$/2,E[1]-J/2];let A=Math.cos(W),I=Math.sin(W);E=[A*E[0]-I*E[1],I*E[0]+A*E[1]],E=[E[0]/_,E[1]/_];let H=-E[0],g=-E[1];return{position:{x:H,y:g},zoom:_,rotation:W}}function i$(Q,q,$,J,U,K){let Y=a({a:J,b:0,c:0,d:J,e:0,f:0},{a:1,b:0,c:0,d:1,e:U/2,f:K/2}),j=Math.cos(-$),B=Math.sin(-$),W=a(Y,{a:j,b:B,c:-B,d:j,e:0,f:0}),F=a(W,{a:q,b:0,c:0,d:q,e:0,f:0});return a(F,{a:1,b:0,c:0,d:1,e:-Q.x,f:-Q.y})}function a(Q,q){let{a:$,b:J,c:U,d:K,e:G,f:Y}=Q,j=q.a,B=q.b,W=q.c,F=q.d,_=q.e,E=q.f;return{a:$*j+U*B,b:J*j+K*B,c:$*W+U*F,d:J*W+K*F,e:$*_+U*E+G,f:J*_+K*E+Y}}function Eq(Q){let{a:q,b:$,c:J,d:U,e:K,f:G}=Q,Y={x:K,y:G},j=q*U-$*J;if(Math.abs(j)<0.0000000001)throw Error("Matrix is singular and cannot be decomposed");let B=Math.atan2($,q),W=Math.cos(B),F=Math.sin(B),_=q*W+$*F,E=J*-F+U*W,A=B,I=_,H=E;if(_<0)I=-_,A+=Math.PI;if(E<0)H=-E,A+=Math.PI;while(A>Math.PI)A-=2*Math.PI;while(A<-Math.PI)A+=2*Math.PI;return{translation:Y,rotation:A,scale:{x:I,y:H}}}function a$(Q,q,$){let J=Math.cos(q),U=Math.sin(q);return{a:$.x*J,b:$.x*U,c:-$.y*U,d:$.y*J,e:Q.x,f:Q.y}}function o$(Q){let{a:q,b:$,c:J,d:U,e:K,f:G}=Q,Y={x:K,y:G},j=q,B=J,W=$,F=U,_=j*j+W*W,E=j*B+W*F,A=E,I=B*B+F*F,H=_+I,g=_*I-E*A,z=H*H-4*g;if(z<0)throw Error("Invalid transformation matrix");let Z=Math.sqrt(z),O=(H+Z)/2,x=(H-Z)/2,y=Math.sqrt(Math.max(0,O)),m=Math.sqrt(Math.max(0,x)),r={x:y,y:m},n=0;if(y>0.0000000001){let p=E,k=O-_,w=x-I,R=A,C=Math.sqrt(p*p+w*w),EQ=Math.sqrt(k*k+R*R);if(C>0.0000000001&&EQ>0.0000000001){let UQ=p/C,kQ=w/C,Gq=k/EQ,Xq=R/EQ,SQ=(j*UQ+B*kQ)/y,wQ=(W*UQ+F*kQ)/y;n=Math.atan2(wQ,SQ)}}return{translation:Y,rotation:n,scale:r}}import{PointCal as jq}from"@ue-too/math";function jQ(Q,q={x:0,y:0},$=!1){let J=jq.subVector(Q,q);if($)J.y=-J.y;return J}function Nq(Q,q={x:0,y:0},$=!1){if($)Q.y=-Q.y;return jq.addVector(Q,q)}import{PointCal as KQ}from"@ue-too/math";function IQ(Q,q,$,J,U=!1){let K=KQ.multiplyVectorByScalar(Q,1/$),G=KQ.rotatePoint(K,J);if(U)G.y=-G.y;return KQ.addVector(G,q)}function yQ(Q,q,$,J,U=!1){let K=KQ.subVector(Q,q);if(U)K.y=-K.y;let G=KQ.multiplyVectorByScalar(K,$);return KQ.rotatePoint(G,-J)}function NQ(Q,q,$,J,U,K){let G=jQ(q,{x:$/2,y:J/2},!1);return IQ(G,Q,U,K,!1)}function N9(Q,q,$,J,U,K){let G=jQ(Q,{x:q/2,y:$/2},!1);return IQ(G,J,U,K,!1)}function l(Q,q,$,J){return IQ(Q,q,$,J,!1)}function HQ(Q,q,$,J){return yQ(Q,q,$,J,!1)}function Y$(Q,q,$,J,U,K){let G=yQ(Q,J,U,K,!1);return Nq(G,{x:q/2,y:$/2},!1)}function F9(Q,q,$,J,U,K){let G=Y$(Q,q,$,J,U,K);if(G.x<0||G.x>q||G.y<0||G.y>$)return!1;return!0}function bQ(Q,q,$){return o.multiplyVectorByScalar(o.rotatePoint(Q,$),1/q)}function _9(Q,q,$){return o.multiplyVectorByScalar(o.rotatePoint(Q,-$),q)}function V9(Q,q,$,J){let U=o.multiplyVectorByScalar(q,1/$),K=o.rotatePoint(U,J);return o.subVector(Q,K)}function B9(Q,q,$){let J=Math.cos($),U=Math.sin($),K=a({a:1,b:0,c:0,d:1,e:Q.x,f:Q.y},{a:J,b:U,c:-U,d:J,e:0,f:0});return a(K,{a:1/q,b:0,c:0,d:1/q,e:0,f:0})}function A9(Q,q){return{x:Q.x*q.a+Q.y*q.c+q.e,y:Q.x*q.b+Q.y*q.d+q.f}}import{PointCal as FQ}from"@ue-too/math";function CQ(Q,q){if(q==null)return!0;let $=!1,J=!1,U=!1,K=!1;if(q.max==null||q.max.x==null||Q.x<=q.max.x)J=!0;if(q.min==null||q.min.x==null||Q.x>=q.min.x)$=!0;if(q.max==null||q.max.y==null||Q.y<=q.max.y)U=!0;if(q.min==null||q.min.y==null||Q.y>=q.min.y)K=!0;return $&&J&&U&&K}function O9(Q){if(Q==null)return!0;let q=Q.min?.x,$=Q.max?.x;if(q!=null&&$!=null&&q>=$)return!1;let J=Q.min?.y,U=Q.max?.y;if(J!=null&&U!=null&&J>=U)return!1;return!0}function fQ(Q){if(Q==null)return!1;if(Q.max==null||Q.min==null)return!1;if(Q.max.x==null||Q.max.y==null||Q.min.x==null||Q.min.y==null)return!1;return!0}function e(Q,q){if(CQ(Q,q)||q==null)return Q;let $={x:Q.x,y:Q.y},J=q.min;if(J!=null){if(J.x!=null)$.x=Math.max($.x,J.x);if(J.y!=null)$.y=Math.max($.y,J.y)}if(J=q.max,J!=null){if(J.x!=null)$.x=Math.min($.x,J.x);if(J.y!=null)$.y=Math.min($.y,J.y)}return $}function t(Q){if(Q==null||Q.min==null||Q.max==null||Q.min.x==null||Q.max.x==null)return;return Q.max.x-Q.min.x}function Fq(Q){let q=t(Q);return q!=null?q/2:void 0}function QQ(Q){if(Q==null||Q.min==null||Q.max==null||Q.min.y==null||Q.max.y==null)return;return Q.max.y-Q.min.y}function _q(Q){let q=QQ(Q);return q!=null?q/2:void 0}function LQ(Q,q,$,J,U,K){if(J==null)return Q;let G=NQ(Q,{x:0,y:$},q,$,U,K),Y=NQ(Q,{x:0,y:0},q,$,U,K),j=NQ(Q,{x:q,y:$},q,$,U,K),B=NQ(Q,{x:q,y:0},q,$,U,K),W=e(G,J),F=e(j,J),_=e(Y,J),E=e(B,J),A=FQ.subVector(W,G),I=FQ.subVector(F,j),H=FQ.subVector(_,Y),g=FQ.subVector(E,B),z=[A,I,H,g],Z=Math.abs(z[0].x),O=Math.abs(z[0].y),x=z[0];return z.forEach((y)=>{if(Math.abs(y.x)>Z)Z=Math.abs(y.x),x.x=y.x;if(Math.abs(y.y)>O)O=Math.abs(y.y),x.y=y.y}),FQ.addVector(Q,x)}function z9(Q){if(Q===void 0)return!0;if(Q.min!==void 0&&Q.max!==void 0&&Q.min>Q.max)return!1;return!0}function GQ(Q,q){if(PQ(Q,q)||q===void 0)return Q;if(q.max)Q=Math.min(q.max,Q);if(q.min)Q=Math.max(q.min,Q);return Q}function PQ(Q,q){if(q===void 0)return!0;if(Q<=0||q!==void 0&&(q.max!==void 0&&q.max<Q||q.min!==void 0&&q.min>Q))return!1;return!0}function YQ(Q,q){if(hQ(Q,q)||q===void 0)return Q;Q=S(Q);let $=XQ(q.start,Q),J=XQ(q.end,Q);if(q.ccw&&($<0||J>0)||!q.ccw&&($>0||J<0)){if(Math.abs($)===Math.abs(J))return q.startAsTieBreaker?q.start:q.end;return Math.abs($)<Math.abs(J)?q.start:q.end}return Q}function hQ(Q,q){if(q===void 0)return!0;if(S(q.start)===S(q.end))return!0;if(S(q.start+0.01)===S(q.end+0.01))return!0;let $=S(Q),J=XQ(q.start,$),U=XQ(q.end,$);if(q.ccw&&(J<0||U>0)||!q.ccw&&(J>0||U<0))return!1;return!0}function Z9(Q,q){if(S(q.start)===S(q.end))return!0;if(S(q.start+0.01)===S(q.end+0.01))return!0;let J=S(Q)-S(q.start);if(J<0)J+=Math.PI*2;if(!q.positiveDirection&&J>0)J=Math.PI*2-J;let U=S(q.end)-S(q.start);if(U<0)U+=Math.PI*2;if(!q.positiveDirection&&U>0)U=Math.PI*2-U;return U>=J}function S(Q){return Q=Q%(Math.PI*2),Q=(Q+Math.PI*2)%(Math.PI*2),Q}function XQ(Q,q){Q=S(Q),q=S(q);let $=q-Q;if($>Math.PI)$=-(Math.PI*2-$);if($<-Math.PI)$+=Math.PI*2;return $}function T9(Q){return Q*Math.PI/180}function S9(Q){return Q*180/Math.PI}import{PointCal as qQ}from"@ue-too/math";class OQ{_position;_rotation;_zoomLevel;currentCachedTransform;currentCachedTRS;_viewPortWidth;_viewPortHeight;_boundaries;_zoomBoundaries;_rotationBoundaries;constructor(Q=1000,q=1000,$={x:0,y:0},J=0,U=1,K={min:{x:-1e4,y:-1e4},max:{x:1e4,y:1e4}},G={min:0.1,max:10},Y=void 0){this._position=$,this._zoomLevel=U,this._rotation=J,this._viewPortHeight=q,this._viewPortWidth=Q,this._zoomBoundaries=G,this._rotationBoundaries=Y,this._boundaries=K}get boundaries(){return this._boundaries}set boundaries(Q){this._boundaries=Q}get viewPortWidth(){return this._viewPortWidth}set viewPortWidth(Q){this._viewPortWidth=Q}get viewPortHeight(){return this._viewPortHeight}set viewPortHeight(Q){this._viewPortHeight=Q}get position(){return{...this._position}}setPosition(Q){if(!CQ(Q,this._boundaries))return!1;let q=qQ.subVector(Q,this._position);if(qQ.magnitude(q)<0.000000001&&qQ.magnitude(q)<1/this._zoomLevel)return!1;return this._position=Q,!0}get zoomLevel(){return this._zoomLevel}get zoomBoundaries(){return this._zoomBoundaries}set zoomBoundaries(Q){let q={...Q};if(q!==void 0&&q.min!==void 0&&q.max!==void 0&&q.min>q.max){let $=q.max;q.max=q.min,q.min=$}this._zoomBoundaries=q}setMaxZoomLevel(Q){if(this._zoomBoundaries==null)this._zoomBoundaries={min:void 0,max:void 0};if(this._zoomBoundaries.min!=null&&this._zoomBoundaries.min>Q||this._zoomLevel>Q)return!1;return this._zoomBoundaries.max=Q,console.trace("setMaxZoomLevel",Q),!0}setMinZoomLevel(Q){if(this._zoomBoundaries==null)this._zoomBoundaries={min:void 0,max:void 0};if(this._zoomBoundaries.max!=null&&this._zoomBoundaries.max<Q)return!1;if(this._zoomBoundaries.min=Q,this._zoomLevel<Q)this._zoomLevel=Q;return console.trace("setMinZoomLevel",Q),!0}setZoomLevel(Q){if(!PQ(Q,this._zoomBoundaries))return!1;if(this._zoomBoundaries!==void 0&&this._zoomBoundaries.max!==void 0&&GQ(Q,this._zoomBoundaries)==this._zoomBoundaries.max&&this._zoomLevel==this._zoomBoundaries.max)return!1;if(this._zoomBoundaries!==void 0&&this._zoomBoundaries.min!==void 0&&GQ(Q,this._zoomBoundaries)==this._zoomBoundaries.min&&this._zoomLevel==this._zoomBoundaries.min)return!1;return this._zoomLevel=Q,!0}get rotation(){return this._rotation}get rotationBoundaries(){return this._rotationBoundaries}set rotationBoundaries(Q){if(Q!==void 0&&Q.start!==void 0&&Q.end!==void 0&&Q.start>Q.end){let q=Q.end;Q.end=Q.start,Q.start=q}this._rotationBoundaries=Q}getTransform(Q=1,q=!0){if(this.currentCachedTransform!==void 0&&this.currentCachedTransform.devicePixelRatio===Q&&this.currentCachedTransform.alignCoorindate===q&&this.currentCachedTransform.position.x===this._position.x&&this.currentCachedTransform.position.y===this._position.y&&this.currentCachedTransform.rotation===this._rotation&&this.currentCachedTransform.zoomLevel===this._zoomLevel&&this.currentCachedTransform.viewPortWidth===this._viewPortWidth&&this.currentCachedTransform.viewPortHeight===this._viewPortHeight)return{...this.currentCachedTransform.transform,cached:!0};let $=Q*this._viewPortWidth/2,J=Q*this._viewPortHeight/2,U=-this._position.x,K=q?-this._position.y:this._position.y,G=Q,Y=this._zoomLevel,j=q?-this._rotation:this._rotation,B=Math.sin(j),W=Math.cos(j),F=Y*G*W,_=Y*G*B,E=-G*Y*B,A=Y*G*W,I=G*Y*W*U-G*Y*B*K+$,H=G*Y*B*U+G*Y*W*K+J;return this.currentCachedTransform={transform:{a:F,b:_,c:E,d:A,e:I,f:H},position:this._position,rotation:this._rotation,zoomLevel:this._zoomLevel,alignCoorindate:q,devicePixelRatio:Q,viewPortWidth:this._viewPortWidth,viewPortHeight:this._viewPortHeight},{a:F,b:_,c:E,d:A,e:I,f:H,cached:!1}}getTRS(Q=1,q=!0){let $=this.getTransform(Q,q);if(this.currentCachedTRS!==void 0&&this.currentCachedTRS.transformMatrix.a===$.a&&this.currentCachedTRS.transformMatrix.b===$.b&&this.currentCachedTRS.transformMatrix.c===$.c&&this.currentCachedTRS.transformMatrix.d===$.d&&this.currentCachedTRS.transformMatrix.e===$.e&&this.currentCachedTRS.transformMatrix.f===$.f)return{scale:this.currentCachedTRS.scale,rotation:this.currentCachedTRS.rotation,translation:this.currentCachedTRS.translation,cached:!0};let J=Eq($);return this.currentCachedTRS={scale:J.scale,rotation:J.rotation,translation:J.translation,transformMatrix:$},{scale:J.scale,rotation:J.rotation,translation:J.translation,cached:!1}}setUsingTransformationMatrix(Q,q=1){let $=Yq(Q,q,this._viewPortWidth,this._viewPortHeight);this.setPosition($.position),this.setRotation($.rotation),this.setZoomLevel($.zoom)}setRotation(Q){if(!hQ(Q,this._rotationBoundaries))return!1;if(Q=S(Q),this._rotationBoundaries!==void 0&&this._rotationBoundaries.end!==void 0&&YQ(Q,this._rotationBoundaries)==this._rotationBoundaries.end&&this._rotation==this._rotationBoundaries.end)return!1;if(this._rotationBoundaries!==void 0&&this._rotationBoundaries.start!==void 0&&YQ(Q,this._rotationBoundaries)==this._rotationBoundaries.start&&this._rotation==this._rotationBoundaries.start)return!1;return this._rotation=Q,!0}getCameraOriginInWindow(Q){return Q}convertFromViewPort2WorldSpace(Q){return l(Q,this._position,this._zoomLevel,this._rotation)}convertFromWorld2ViewPort(Q){return HQ(Q,this._position,this._zoomLevel,this._rotation)}invertFromWorldSpace2ViewPort(Q){let q={x:this.viewPortWidth/2,y:this._viewPortHeight/2},$=qQ.subVector(Q,this._position);return $=qQ.rotatePoint($,-this._rotation),$=qQ.multiplyVectorByScalar($,this._zoomLevel),qQ.addVector(q,$)}setHorizontalBoundaries(Q,q){if(Q>q){let $=q;q=Q,Q=$}if(this._boundaries==null)this._boundaries={min:{x:void 0,y:void 0},max:{x:void 0,y:void 0}};if(this._boundaries.min==null)this._boundaries.min={x:void 0,y:void 0};if(this._boundaries.max==null)this._boundaries.max={x:void 0,y:void 0};this._boundaries.min.x=Q,this._boundaries.max.x=q}setVerticalBoundaries(Q,q){if(Q>q){let $=q;q=Q,Q=$}if(this._boundaries==null)this._boundaries={min:{x:void 0,y:void 0},max:{x:void 0,y:void 0}};if(this._boundaries.min==null)this._boundaries.min={x:void 0,y:void 0};if(this._boundaries.max==null)this._boundaries.max={x:void 0,y:void 0};this._boundaries.min.y=Q,this._boundaries.max.y=q}viewPortInWorldSpace(Q=!0){let q=l({x:-this._viewPortWidth/2,y:Q?-this._viewPortHeight/2:this._viewPortHeight/2},this._position,this._zoomLevel,this._rotation),$=l({x:this._viewPortWidth/2,y:Q?-this._viewPortHeight/2:this._viewPortHeight/2},this._position,this._zoomLevel,this._rotation),J=l({x:-this._viewPortWidth/2,y:Q?this._viewPortHeight/2:-this._viewPortHeight/2},this._position,this._zoomLevel,this._rotation),U=l({x:this._viewPortWidth/2,y:Q?this._viewPortHeight/2:-this._viewPortHeight/2},this._position,this._zoomLevel,this._rotation);return{top:{left:q,right:$},bottom:{left:J,right:U}}}viewPortAABB(Q){let{top:{left:q,right:$},bottom:{left:J,right:U}}=this.viewPortInWorldSpace(Q);return{min:{x:Math.min(q.x,J.x,$.x,U.x),y:Math.min(q.y,J.y,$.y,U.y)},max:{x:Math.max(q.x,J.x,$.x,U.x),y:Math.max(q.y,J.y,$.y,U.y)}}}}var E$=1000,j$=1000,N$={min:0.1,max:10},F$={min:{x:-1e4,y:-1e4},max:{x:1e4,y:1e4}},_$=void 0;class $Q{_baseCamera;_observer;constructor(Q=E$,q=j$,$={x:0,y:0},J=0,U=1,K=F$,G=N$,Y=_$){this._baseCamera=new OQ(Q,q,$,J,U,K,G,Y),this._observer=new RQ}get boundaries(){return this._baseCamera.boundaries}set boundaries(Q){this._baseCamera.boundaries=Q}get viewPortWidth(){return this._baseCamera.viewPortWidth}set viewPortWidth(Q){this._baseCamera.viewPortWidth=Q}get viewPortHeight(){return this._baseCamera.viewPortHeight}set viewPortHeight(Q){this._baseCamera.viewPortHeight=Q}get position(){return this._baseCamera.position}setPosition(Q){let q={...this._baseCamera.position};if(!this._baseCamera.setPosition(Q))return!1;return this._observer.notifyPan({diff:_Q.subVector(Q,q)},{position:this._baseCamera.position,rotation:this._baseCamera.rotation,zoomLevel:this._baseCamera.zoomLevel}),!0}get zoomLevel(){return this._baseCamera.zoomLevel}get zoomBoundaries(){return this._baseCamera.zoomBoundaries}set zoomBoundaries(Q){this._baseCamera.zoomBoundaries=Q}setMaxZoomLevel(Q){let q=this._baseCamera.zoomLevel;if(!this._baseCamera.setMaxZoomLevel(Q))return!1;return this._observer.notifyZoom({deltaZoomAmount:Q-q},{position:this._baseCamera.position,rotation:this._baseCamera.rotation,zoomLevel:this._baseCamera.zoomLevel}),!0}setMinZoomLevel(Q){if(!this._baseCamera.setMinZoomLevel(Q))return!1;return!0}setZoomLevel(Q){let q=this._baseCamera.zoomLevel;if(!this._baseCamera.setZoomLevel(Q))return!1;return this._observer.notifyZoom({deltaZoomAmount:this._baseCamera.zoomLevel-q},{position:this._baseCamera.position,rotation:this._baseCamera.rotation,zoomLevel:this._baseCamera.zoomLevel}),!0}get rotation(){return this._baseCamera.rotation}get rotationBoundaries(){return this._baseCamera.rotationBoundaries}set rotationBoundaries(Q){this._baseCamera.rotationBoundaries=Q}getTransform(Q=1,q=!0){return this._baseCamera.getTransform(Q,q)}setRotation(Q){let q=this._baseCamera.rotation;if(!this._baseCamera.setRotation(Q))return!1;return this._observer.notifyRotate({deltaRotation:Q-q},{position:this._baseCamera.position,rotation:this._baseCamera.rotation,zoomLevel:this._baseCamera.zoomLevel}),!0}getCameraOriginInWindow(Q){return Q}convertFromViewPort2WorldSpace(Q){return l(Q,this._baseCamera.position,this._baseCamera.zoomLevel,this._baseCamera.rotation)}convertFromWorld2ViewPort(Q){return HQ(Q,this._baseCamera.position,this._baseCamera.zoomLevel,this._baseCamera.rotation)}invertFromWorldSpace2ViewPort(Q){let q={x:this._baseCamera.viewPortWidth/2,y:this._baseCamera.viewPortHeight/2},$=_Q.subVector(Q,this._baseCamera.position);return $=_Q.rotatePoint($,-this._baseCamera.rotation),$=_Q.multiplyVectorByScalar($,this._baseCamera.zoomLevel),_Q.addVector(q,$)}setHorizontalBoundaries(Q,q){if(Q>q){let $=q;q=Q,Q=$}if(this._baseCamera.boundaries==null)this._baseCamera.boundaries={min:void 0,max:void 0};if(this._baseCamera.boundaries.min==null)this._baseCamera.boundaries.min={x:void 0,y:void 0};if(this._baseCamera.boundaries.max==null)this._baseCamera.boundaries.max={x:void 0,y:void 0};this._baseCamera.boundaries.min.x=Q,this._baseCamera.boundaries.max.x=q}setVerticalBoundaries(Q,q){if(Q>q){let $=q;q=Q,Q=$}if(this._baseCamera.boundaries==null)this._baseCamera.boundaries={min:void 0,max:void 0};if(this._baseCamera.boundaries.min==null)this._baseCamera.boundaries.min={x:void 0,y:void 0};if(this._baseCamera.boundaries.max==null)this._baseCamera.boundaries.max={x:void 0,y:void 0};this._baseCamera.boundaries.min.y=Q,this._baseCamera.boundaries.max.y=q}on(Q,q,$){return this._observer.on(Q,q,$)}getTRS(Q=1,q=!0){return this._baseCamera.getTRS(Q,q)}setUsingTransformationMatrix(Q,q=1){this._baseCamera.setUsingTransformationMatrix(Q,q)}viewPortInWorldSpace(Q=!0){return this._baseCamera.viewPortInWorldSpace(Q)}viewPortAABB(Q=!0){return this._baseCamera.viewPortAABB(Q)}}class gQ{_disabled=!1;_stateMachine;_orchestrator;_keyfirstPressed;_abortController;_canvas;constructor(Q,q,$){this._canvas=$,this.bindFunctions(),this._abortController=new AbortController,this._stateMachine=Q,this._orchestrator=q,this._keyfirstPressed=new Map}get disabled(){return this._disabled}disable(){this._disabled=!0}enable(){this._disabled=!1}addEventListeners(Q){if(this._canvas==null)return;this._canvas.addEventListener("pointerdown",this.pointerDownHandler,{signal:Q}),this._canvas.addEventListener("pointerup",this.pointerUpHandler,{signal:Q}),this._canvas.addEventListener("pointermove",this.pointerMoveHandler,{signal:Q}),this._canvas.addEventListener("wheel",this.scrollHandler,{signal:Q}),window.addEventListener("keydown",this.keypressHandler,{signal:Q}),window.addEventListener("keyup",this.keyupHandler,{signal:Q})}setUp(){if(this._abortController.signal.aborted)this._abortController=new AbortController;this.addEventListeners(this._abortController.signal)}tearDown(){this._abortController.abort(),this._abortController=new AbortController,this._canvas=void 0}bindFunctions(){this.pointerDownHandler=this.pointerDownHandler.bind(this),this.pointerUpHandler=this.pointerUpHandler.bind(this),this.pointerMoveHandler=this.pointerMoveHandler.bind(this),this.scrollHandler=this.scrollHandler.bind(this),this.keypressHandler=this.keypressHandler.bind(this),this.keyupHandler=this.keyupHandler.bind(this)}processEvent(...Q){let q=this._stateMachine.happens(...Q);if(q.handled&&"output"in q)this._orchestrator.processInputEventOutput(q.output)}pointerDownHandler(Q){if(this._disabled)return;if(Q.button===0&&Q.pointerType==="mouse"){this.processEvent("leftPointerDown",{x:Q.clientX,y:Q.clientY});return}if(Q.button===1&&Q.pointerType==="mouse"){this.processEvent("middlePointerDown",{x:Q.clientX,y:Q.clientY});return}}pointerUpHandler(Q){if(this._disabled)return;if(Q.button===0&&Q.pointerType==="mouse"){this.processEvent("leftPointerUp",{x:Q.clientX,y:Q.clientY});return}if(Q.button===1&&Q.pointerType==="mouse"){this.processEvent("middlePointerUp",{x:Q.clientX,y:Q.clientY});return}}pointerMoveHandler(Q){if(this._disabled)return;if(Q.buttons===1&&Q.pointerType==="mouse"){this.processEvent("leftPointerMove",{x:Q.clientX,y:Q.clientY});return}if(Q.buttons===4&&Q.pointerType==="mouse"){this.processEvent("middlePointerMove",{x:Q.clientX,y:Q.clientY});return}this.processEvent("pointerMove",{x:Q.clientX,y:Q.clientY})}scrollHandler(Q){if(this._disabled)return;if(Q.preventDefault(),Q.ctrlKey)this.processEvent("scrollWithCtrl",{x:Q.clientX,y:Q.clientY,deltaX:Q.deltaX,deltaY:Q.deltaY});else this.processEvent("scroll",{x:Q.clientX,y:Q.clientY,deltaX:Q.deltaX,deltaY:Q.deltaY})}keypressHandler(Q){if(Q.target!==document.body)return;if(this._keyfirstPressed.has(Q.key))return;if(this._keyfirstPressed.set(Q.key,!0),Q.key===" ")this.processEvent("spacebarDown")}keyupHandler(Q){if(this._keyfirstPressed.has(Q.key))this._keyfirstPressed.delete(Q.key);if(Q.key===" ")this.processEvent("spacebarUp")}attach(Q){this.tearDown(),this._canvas=Q,this.setUp()}}class xQ{_canvas;_disabled;_panDisabled=!1;_zoomDisabled=!1;_rotateDisabled=!1;_stateMachine;_orchestrator;_abortController;constructor(Q,q,$){this._canvas=$,this._disabled=!1,this._stateMachine=Q,this._orchestrator=q,this._abortController=new AbortController,this.bindListeners()}get orchestrator(){return this._orchestrator}bindListeners(){this.touchstartHandler=this.touchstartHandler.bind(this),this.touchendHandler=this.touchendHandler.bind(this),this.touchcancelHandler=this.touchcancelHandler.bind(this),this.touchmoveHandler=this.touchmoveHandler.bind(this)}enableStrategy(){this._disabled=!1}disableStrategy(){this._disabled=!0}setUp(){if(this._canvas==null)return;if(this._abortController.signal.aborted)this._abortController=new AbortController;this._canvas.addEventListener("touchstart",this.touchstartHandler,{signal:this._abortController.signal}),this._canvas.addEventListener("touchend",this.touchendHandler,{signal:this._abortController.signal}),this._canvas.addEventListener("touchcancel",this.touchcancelHandler,{signal:this._abortController.signal}),this._canvas.addEventListener("touchmove",this.touchmoveHandler,{signal:this._abortController.signal})}tearDown(){this._abortController.abort(),this._abortController=new AbortController,this._canvas=void 0}get disabled(){return this._disabled}disable(){this._disabled=!0}enable(){this._disabled=!1}processEvent(...Q){let q=this._stateMachine.happens(...Q);if(q.handled&&"output"in q)this._orchestrator.processInputEventOutput(q.output)}touchstartHandler(Q){if(this._disabled)return;let q=[];for(let $=0;$<Q.changedTouches.length;$++)q.push({ident:Q.changedTouches[$].identifier,x:Q.changedTouches[$].clientX,y:Q.changedTouches[$].clientY});this.processEvent("touchstart",{points:q}),Q.preventDefault()}touchcancelHandler(Q){if(this._disabled)return;let q=[];for(let $=0;$<Q.changedTouches.length;$++)q.push({ident:Q.changedTouches[$].identifier,x:Q.changedTouches[$].clientX,y:Q.changedTouches[$].clientY});this.processEvent("touchend",{points:q})}touchendHandler(Q){if(this._disabled)return;let q=[];for(let $=0;$<Q.changedTouches.length;$++)q.push({ident:Q.changedTouches[$].identifier,x:Q.changedTouches[$].clientX,y:Q.changedTouches[$].clientY});this.processEvent("touchend",{points:q})}touchmoveHandler(Q){if(this._disabled)return;Q.preventDefault();let q=[];for(let $=0;$<Q.targetTouches.length;$++)q.push({ident:Q.targetTouches[$].identifier,x:Q.targetTouches[$].clientX,y:Q.targetTouches[$].clientY});this.processEvent("touchmove",{points:q})}attach(Q){this.tearDown(),this._canvas=Q,this.setUp()}}import{PointCal as V$}from"@ue-too/math";function Vq(Q,q){return V$.subVector(Q,q.position)}function J7(Q){let q=Math.cos(Math.PI/6),$=Math.cos(Math.PI/3);return{x:Q.x*q-Q.y*q,y:Q.x*$+Q.y*$+(Q.z??0)}}function Bq(Q,q,$={x:q.width/2,y:q.height/2},J=!1){let U=Vq(Q,q);return jQ(U,$,J)}function VQ(Q){if(Q<=0)return 0;let q=0;if(Q<1){let $=1;while($>Q)$/=10,q--}else{let $=1;while($*10<=Q)$*=10,q++}return q}function d(...Q){let q=Array.isArray(Q[0])?Q[0]:Q;return($,...J)=>{return q.reduce((U,K)=>K(U,...J),$)}}class uQ{lastRect;resizeObserver;intersectionObserver;mutationObserver;scrollHandler;resizeHandler;_observers;constructor(Q){if(this._observers=new i,this.resizeObserver=new ResizeObserver(((q)=>{for(let $ of q){let J=$.target.getBoundingClientRect(),U=M(J,window.getComputedStyle($.target));if(L(this.lastRect,U))this.publishPositionUpdate(U),this.lastRect=U}}).bind(this)),this.intersectionObserver=new IntersectionObserver(((q)=>{if(this.lastRect===void 0)return;for(let $ of q)if($.isIntersecting){let J=$.boundingClientRect,U=M(J,window.getComputedStyle($.target));if(L(this.lastRect,U))this.publishPositionUpdate(U),this.lastRect=U}}).bind(this)),this.attributeCallBack=this.attributeCallBack.bind(this),this.mutationObserver=new MutationObserver(this.attributeCallBack),Q)this.attach(Q)}dispose(){if(this.resizeObserver.disconnect(),this.intersectionObserver.disconnect(),this.mutationObserver.disconnect(),this.scrollHandler)window.removeEventListener("scroll",this.scrollHandler);if(this.resizeHandler)window.removeEventListener("resize",this.resizeHandler)}attach(Q){this.dispose(),this.resizeObserver.observe(Q),this.intersectionObserver.observe(Q),this.mutationObserver.observe(Q,{attributes:!0,attributeFilter:["width","height","style"]});let q=Q.getBoundingClientRect(),$=M(q,window.getComputedStyle(Q));this.lastRect=$,this.scrollHandler=(()=>{if(this.lastRect===void 0)return;let J=Q.getBoundingClientRect(),U=M(J,window.getComputedStyle(Q));if(L(this.lastRect,U))this.publishPositionUpdate(U),this.lastRect=U}).bind(this),this.resizeHandler=(()=>{if(this.lastRect===void 0)return;let J=Q.getBoundingClientRect(),U=M(J,window.getComputedStyle(Q));if(L(this.lastRect,U))this.publishPositionUpdate(U),this.lastRect=U}).bind(this),window.addEventListener("scroll",this.scrollHandler,{passive:!0}),window.addEventListener("resize",this.resizeHandler,{passive:!0})}publishPositionUpdate(Q){this._observers.notify(Q)}onPositionUpdate(Q,q){return this._observers.subscribe(Q,q)}attributeCallBack(Q,q){for(let $ of Q)if($.type==="attributes"){if($.attributeName==="width"){let J=$.target,U=J.getBoundingClientRect(),K=M(U,window.getComputedStyle(J));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}else if($.attributeName==="height"){let J=$.target,U=J.getBoundingClientRect(),K=M(U,window.getComputedStyle(J));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}else if($.attributeName==="style"){let J=$.target,U=J.getBoundingClientRect(),K=M(U,window.getComputedStyle(J));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}}}}class vQ{lastRect;resizeObserver;intersectionObserver;mutationObserver;scrollHandler;resizeHandler;_observers;_abortController;_pixelRatioAbortController;constructor(Q){if(this._abortController=new AbortController,this._pixelRatioAbortController=new AbortController,this._observers=new i,this.resizeObserver=new ResizeObserver(((q)=>{for(let $ of q){let J=$.target.getBoundingClientRect(),U=M(J,window.getComputedStyle($.target));if(L(this.lastRect,U))this.publishPositionUpdate(U),this.lastRect=U}}).bind(this)),this.intersectionObserver=new IntersectionObserver(((q)=>{if(this.lastRect===void 0)return;for(let $ of q)if($.isIntersecting){let J=$.boundingClientRect,U=M(J,window.getComputedStyle($.target));if(L(this.lastRect,U))this.publishPositionUpdate(U),this.lastRect=U}}).bind(this)),this.attributeCallBack=this.attributeCallBack.bind(this),this.mutationObserver=new MutationObserver(this.attributeCallBack),Q)this.attach(Q)}dispose(){this.resizeObserver.disconnect(),this.intersectionObserver.disconnect(),this.mutationObserver.disconnect(),this._abortController.abort(),this._pixelRatioAbortController.abort()}attach(Q){this.dispose(),this._abortController.abort(),this._abortController=new AbortController,this._pixelRatioAbortController.abort(),this._pixelRatioAbortController=new AbortController,this.resizeObserver.observe(Q),this.intersectionObserver.observe(Q),this.mutationObserver.observe(Q,{attributes:!0,attributeFilter:["width","height","style"]});let q=Q.getBoundingClientRect(),$=M(q,window.getComputedStyle(Q));this.publishPositionUpdate($),this.lastRect=$,this.scrollHandler=(()=>{if(this.lastRect===void 0)return;let U=Q.getBoundingClientRect(),K=M(U,window.getComputedStyle(Q));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}).bind(this),this.resizeHandler=(()=>{if(this.lastRect===void 0)return;let U=Q.getBoundingClientRect(),K=M(U,window.getComputedStyle(Q));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}).bind(this),window.addEventListener("scroll",this.scrollHandler,{passive:!0,signal:this._abortController.signal}),window.addEventListener("resize",this.resizeHandler,{passive:!0,signal:this._abortController.signal});let J=(()=>{this._pixelRatioAbortController.abort(),this._pixelRatioAbortController=new AbortController,console.log("updatePixelRatio",window.devicePixelRatio);let U=Q.getBoundingClientRect(),K=M(U,window.getComputedStyle(Q));this.publishPositionUpdate(K);let G=`(resolution: ${window.devicePixelRatio}dppx)`;matchMedia(G).addEventListener("change",J,{signal:this._pixelRatioAbortController.signal})}).bind(this);J()}publishPositionUpdate(Q){this._observers.notify(Q)}onPositionUpdate(Q,q){return this._observers.subscribe(Q,q)}attributeCallBack(Q,q){for(let $ of Q)if($.type==="attributes"){if($.attributeName==="width"){let J=$.target,U=J.getBoundingClientRect(),K=M(U,window.getComputedStyle(J));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}else if($.attributeName==="height"){let J=$.target,U=J.getBoundingClientRect(),K=M(U,window.getComputedStyle(J));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}else if($.attributeName==="style"){let J=$.target,U=J.getBoundingClientRect(),K=M(U,window.getComputedStyle(J));if(L(this.lastRect,K))this.publishPositionUpdate(K),this.lastRect=K}}}}function M(Q,q){let $=parseFloat(q.paddingLeft),J=parseFloat(q.paddingTop),U=parseFloat(q.paddingRight),K=parseFloat(q.paddingBottom),G=parseFloat(q.borderLeftWidth),Y=parseFloat(q.borderTopWidth),j=parseFloat(q.borderRightWidth),B=parseFloat(q.borderBottomWidth),W=Q.left+$+G,F=Q.top+J+Y,_=Q.width-$-U-G-j,E=Q.height-J-K-Y-B;return new DOMRect(W,F,_,E)}function L(Q,q){if(Q===void 0)return!0;return Q.top!==q.top||Q.left!==q.left||Q.width!==q.width||Q.height!==q.height}var Aq={fillRect:[1,3],strokeRect:[1,3],fillText:[2],strokeText:[1],lineTo:[1],moveTo:[1],quadraticCurveTo:[1,3],bezierCurveTo:[1,3,5],arc:[1],drawImage:[2],rect:[1,3],roundRect:[1,3]};function Wq(Q){return new Proxy(Q,{get(q,$,J){let U=Reflect.get(q,$,q);if(typeof $==="string"&&$ in Aq&&typeof U==="function")return function(...K){let G=[...K];if($==="drawImage"&&K.length===9){let Y=B$(K);return U.apply(q,Y)}else{let Y=Aq[$];for(let j of Y)if(j<G.length)G[j]=-G[j];if($==="drawImage"&&K.length===5)G[2]-=G[4]}return U.apply(q,G)};if(typeof U==="function")return function(...K){return U.apply(q,K)};return U},set(q,$,J){return Reflect.set(q,$,J)}})}function B$(Q){if(Q.length!==9)return Q;let q=[...Q],$=Q[0].height;if($!==void 0)q[2]=$-q[2],q[6]=-q[6],q[6]-=q[8],q[4]=-q[4];return q}import{PointCal as V}from"@ue-too/math";function B7(Q,q,$,J,U,K="red"){let G=U/2;if(G=G/$,Q.beginPath(),Q.strokeStyle=K,Q.lineWidth=2/$,J)Q.moveTo(q.x-G,q.y),Q.lineTo(q.x+G,q.y),Q.moveTo(q.x,q.y-G),Q.lineTo(q.x,q.y+G);else Q.moveTo(q.x-G,-q.y),Q.lineTo(q.x+G,-q.y),Q.moveTo(q.x,-q.y-G),Q.lineTo(q.x,-q.y+G);Q.stroke(),Q.lineWidth=3}function A7(Q,q,$){if(!fQ(q))return;let J=t(q),U=QQ(q),K=q==null?void 0:q.min,G=K==null?void 0:K.x,Y=K==null?void 0:K.y;if(G==null||Y==null||J==null||U==null)return;if(Q.beginPath(),Q.strokeStyle="blue",Q.lineWidth=100,$)Q.roundRect(G,Y,J,U,5);else Q.roundRect(G,-Y,J,-U,5);Q.stroke(),Q.lineWidth=3,Q.strokeStyle="black"}function W7(Q,q,$,J){if(!fQ(q))return;let U=t(q),K=QQ(q),G=q==null?void 0:q.min,Y=G==null?void 0:G.x,j=G==null?void 0:G.y;if(Y==null||j==null||U==null||K==null)return;if(Q.lineWidth=1/$,Q.beginPath(),Q.strokeStyle="rgba(87, 173, 72, 0.8)",Q.moveTo(0,0),J)Q.lineTo(0,j+K);else Q.lineTo(0,-j-K);Q.stroke(),Q.beginPath(),Q.strokeStyle="rgba(220, 59, 59, 0.8)",Q.moveTo(0,0),Q.lineTo(Y+U,0),Q.stroke(),Q.strokeStyle="black"}function k7(Q,q,$,J,U,K,G){let Y=V.unitVectorFromA2B(q,$),j=V.unitVectorFromA2B(J,q),B=V.distanceBetweenPoints(q,$),W=V.distanceBetweenPoints(q,J),F=VQ(B),E=Math.pow(10,F)/10,A=Math.ceil(q.x/E)*E,I=Math.floor($.x/E)*E,H=K?Math.floor(q.y/E)*E:Math.ceil(J.y/E)*E,g=K?Math.ceil(J.y/E)*E:Math.floor(q.y/E)*E;for(let z=A;z<=I;z+=E){let Z=V.addVector({x:z,y:q.y},V.multiplyVectorByScalar(Y,E)),O=V.addVector({x:z,y:J.y},V.multiplyVectorByScalar(Y,E));Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=0.5/G,Q.moveTo(Z.x,Z.y),Q.lineTo(O.x,O.y),Q.stroke()}for(let z=H;z<=g;z+=E){let Z=V.addVector({x:q.x,y:z},V.multiplyVectorByScalar(j,E)),O=V.addVector({x:$.x,y:z},V.multiplyVectorByScalar(j,E));Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=0.5/G,Q.moveTo(Z.x,Z.y),Q.lineTo(O.x,O.y),Q.stroke()}}function I7(Q,q,$,J,U,K,G){let Y=V.unitVectorFromA2B(q,$),j=V.unitVectorFromA2B(J,q),B=V.distanceBetweenPoints(q,$),W=VQ(B),F=Math.pow(10,W),_=F/2,E=F/10,A=1;if(W<=0)A=Math.pow(10,-W+1);let I=Math.ceil(q.x/F)*F,H=Math.floor($.x/F)*F,g=K?Math.ceil(q.y/F)*F:Math.floor(J.y/F)*F,z=K?Math.floor(J.y/F)*F:Math.ceil(q.y/F)*F,Z=Math.ceil(q.x/_)*_,O=Math.floor($.x/_)*_,x=K?Math.ceil(q.y/_)*_:Math.floor(J.y/_)*_,y=K?Math.floor(J.y/_)*_:Math.ceil(q.y/_)*_,m=Math.ceil(q.x/E)*E,r=Math.floor($.x/E)*E,n=K?Math.ceil(q.y/E)*E:Math.floor(J.y/E)*E,p=K?Math.floor(J.y/E)*E:Math.ceil(q.y/E)*E,k=F*G,w=_*G,R=E*G;Q.font=`bold ${20/G}px Helvetica`;let C=Q.measureText(`${-(_+Z)}`),EQ=C.fontBoundingBoxAscent+C.fontBoundingBoxDescent,UQ=Q.measureText(`${-(E+m)}`),kQ=UQ.fontBoundingBoxAscent+UQ.fontBoundingBoxDescent,Gq=Math.ceil((H-I)/F);for(let D=0;D<=Gq;D++){let N=I+D*F;Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=5/G;let X=V.addVector({x:N,y:q.y},V.multiplyVectorByScalar(j,50/G));if(!K)Q.moveTo(X.x,-X.y);else Q.moveTo(X.x,X.y);if(X=V.addVector({x:N,y:q.y},V.multiplyVectorByScalar(j,-50/G)),!K)Q.lineTo(X.x,-X.y);else Q.lineTo(X.x,X.y);Q.textAlign="center",Q.textBaseline="middle",Q.font=`bold ${20/G}px Helvetica`;let T=Q.measureText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`),b=T.fontBoundingBoxAscent+T.fontBoundingBoxDescent;if(!K)X=V.addVector(X,{x:0,y:-b/2-b*0.2}),Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,-X.y);else X=V.addVector(X,{x:0,y:b/2+b*0.2}),Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,X.y);Q.stroke()}let Xq=Math.ceil((H-I)/F);for(let D=0;D<=Xq;D++){let N=g+D*F;Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=5/G;let X=V.addVector({x:q.x,y:N},V.multiplyVectorByScalar(Y,-50/G));if(!K)Q.moveTo(X.x,-X.y);else Q.moveTo(X.x,X.y);if(X=V.addVector({x:q.x,y:N},V.multiplyVectorByScalar(Y,50/G)),!K)Q.lineTo(X.x,-X.y);else Q.lineTo(X.x,X.y);Q.textAlign="center",Q.textBaseline="middle",Q.font=`bold ${20/G}px Helvetica`;let T=Q.measureText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`);if(X=V.addVector(X,{x:T.width/2+T.width*0.3,y:0}),!K)Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,-X.y);else Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,X.y);Q.stroke()}let SQ=Math.ceil((O-Z)/_);for(let D=0;D<=SQ;D++){let N=Z+D*_;if(Math.floor(N*A)%Math.floor(F*A)==0)continue;Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=3/G;let X=V.addVector({x:N,y:q.y},V.multiplyVectorByScalar(j,25/G));if(!K)Q.moveTo(X.x,-X.y);else Q.moveTo(X.x,X.y);if(X=V.addVector({x:N,y:q.y},V.multiplyVectorByScalar(j,-25/G)),!K)Q.lineTo(X.x,-X.y);else Q.lineTo(X.x,X.y);Q.font=`${15/G}px Helvetica`;let T=Q.measureText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`);if(w>C.width*2){Q.textAlign="center",Q.textBaseline="middle";let b=T.fontBoundingBoxAscent+T.fontBoundingBoxDescent;if(!K)X=V.addVector(X,{x:0,y:-b/2-b*0.2}),X=V.flipYAxis(X);else X=V.addVector(X,{x:0,y:b/2+b*0.2});Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,X.y)}Q.stroke()}let wQ=Math.ceil((y-x)/_);for(let D=0;D<=wQ;D++){let N=x+D*_;if(Math.floor(N*A)%Math.floor(F*A)==0)continue;Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=3/G;let X=V.addVector({x:q.x,y:N},V.multiplyVectorByScalar(Y,-25/G));if(!K)Q.moveTo(X.x,-X.y);else Q.moveTo(X.x,X.y);if(X=V.addVector({x:q.x,y:N},V.multiplyVectorByScalar(Y,25/G)),!K)Q.lineTo(X.x,-X.y);else Q.lineTo(X.x,X.y);Q.font=`${18/G}px Helvetica`;let T=Q.measureText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`),b=T.fontBoundingBoxAscent+T.fontBoundingBoxDescent;if(w>EQ*2){if(Q.textAlign="center",Q.textBaseline="middle",X=V.addVector(X,{x:T.width/2+T.width*0.3,y:0}),!K)X=V.flipYAxis(X);Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,X.y)}Q.stroke()}let G$=Math.ceil((r-m)/E);for(let D=0;D<=G$;D++){let N=m+D*E;if(Math.floor(N*A)%Math.floor(F*A)==0||Math.floor(N*A)%Math.floor(_*A)==0)continue;Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=1/G;let X=V.addVector({x:N,y:q.y},V.multiplyVectorByScalar(j,12.5/G));if(!K)Q.moveTo(X.x,-X.y);else Q.moveTo(X.x,X.y);if(X=V.addVector({x:N,y:q.y},V.multiplyVectorByScalar(j,-12.5/G)),!K)Q.lineTo(X.x,-X.y);else Q.lineTo(X.x,X.y);Q.font=`${10/G}px Helvetica`;let T=Q.measureText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`);if(R>UQ.width*2){Q.textAlign="center",Q.textBaseline="middle";let b=T.fontBoundingBoxAscent+T.fontBoundingBoxDescent;if(!K)X=V.addVector(X,{x:0,y:-b/2-b*0.2}),X=V.flipYAxis(X);else X=V.addVector(X,{x:0,y:b/2+b*0.2});Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,X.y)}Q.stroke()}let X$=Math.ceil((p-n)/E);for(let D=0;D<=X$;D++){let N=n+D*E;if(Math.floor(N*A)%Math.floor(F*A)==0||Math.floor(N*A)%Math.floor(_*A)==0)continue;Q.beginPath(),Q.strokeStyle="black",Q.fillStyle="black",Q.lineWidth=1/G;let X=V.addVector({x:q.x,y:N},V.multiplyVectorByScalar(Y,-12.5/G));if(!K)Q.moveTo(X.x,-X.y);else Q.moveTo(X.x,X.y);if(X=V.addVector({x:q.x,y:N},V.multiplyVectorByScalar(Y,12.5/G)),!K)Q.lineTo(X.x,-X.y);else Q.lineTo(X.x,X.y);Q.font=`${12/G}px Helvetica`;let T=Q.measureText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`),b=T.fontBoundingBoxAscent+T.fontBoundingBoxDescent;if(R>kQ*2){if(Q.textAlign="center",Q.textBaseline="middle",X=V.addVector(X,{x:T.width/2+T.width*0.3,y:0}),!K)X=V.flipYAxis(X);Q.fillText(`${Math.abs(N)%1==0?N.toFixed(0):N.toFixed(2)}`,X.x,X.y)}Q.stroke()}}function H7(Q,q,$,J,U=20,K="red"){if(U=U/$,Q.font=`${20/$}px Arial`,Q.fillStyle=K,J)Q.fillText(`x: ${q.x.toFixed(2)}, y: ${q.y.toFixed(2)}`,q.x+U,q.y+U);else Q.fillText(`x: ${q.x.toFixed(2)}, y: ${q.y.toFixed(2)}`,q.x+U,-q.y-U);Q.fillStyle="black"}function O7(Q,q,$){if(Q.beginPath(),Q.strokeStyle="rgba(87, 173, 72, 0.8)",$)Q.arc(q.x,q.y,5,0,2*Math.PI);else Q.arc(q.x,-q.y,5,0,2*Math.PI);Q.stroke(),Q.strokeStyle="black"}import{PointCal as s}from"@ue-too/math";function T7(Q,q,$,J,U=1,K=0.3){let G=s.distanceBetweenPoints($,J),Y=10<G*q*0.5?10/q:G*0.5,j=G-Y,B=s.linearInterpolation($,J,j/G);Q.beginPath(),Q.lineWidth=U/q,Q.moveTo($.x,$.y),Q.lineTo(B.x,B.y),Q.stroke();let W=s.rotatePoint(s.unitVectorFromA2B(J,$),Math.PI/2),F=s.addVector(B,s.multiplyVectorByScalar(W,Y*0.5)),_=s.subVector(B,s.multiplyVectorByScalar(W,Y*0.5));Q.beginPath(),Q.moveTo(J.x,J.y),Q.lineTo(F.x,F.y),Q.lineTo(_.x,_.y),Q.closePath(),Q.fill()}var BQ=30,pQ=BQ*0.3,dQ=BQ*0.5,mQ=10,lQ=2.5,kq=20,Iq=10;function S7(Q,q,$,J,U,K){let{minMajorTickValue:G,maxMajorTickValue:Y,majorTickStep:j,minMinTickValue:B,maxMaxTickValue:W,minTickStep:F,minHalfTickValue:_,maxHalfTickValue:E,halfTickStep:A,calibrationMultiplier:I,normalizedOrderOfMagnitude:H}=Hq(q.x,$.x);Q.save(),Q.strokeStyle="red";for(let k=G;k<=Y;k+=j){let w={x:k*I,y:q.y},R=U?BQ/K:-BQ/K,C=U?mQ/K:-mQ/K;cQ(Q,K,w,R,k*I,{textOffset:C,fontSize:kq})}for(let k=B;k<=W;k+=F){if(k%j===0)continue;if(k%A===0)continue;let w={x:k*I,y:q.y},R=U?pQ/K:-pQ/K;cQ(Q,K,w,R,k)}for(let k=_;k<=E;k+=A){if(k%j===0)continue;let w={x:k*I,y:q.y},R=U?dQ/K:-dQ/K,C=U?lQ/K:-lQ/K;cQ(Q,K,w,R,k*I,{textOffset:C,fontSize:Iq,color:"red"})}Q.restore();let{minMajorTickValue:g,maxMajorTickValue:z,majorTickStep:Z,minMinTickValue:O,maxMaxTickValue:x,minTickStep:y,minHalfTickValue:m,maxHalfTickValue:r,halfTickStep:n,calibrationMultiplier:p}=Hq(q.y,J.y,H);Q.save(),Q.strokeStyle="green";for(let k=g;k<=z;k+=Z){let w={x:q.x,y:k*p},R=BQ/K,C=mQ/K;sQ(Q,K,w,R,k,{textOffset:C,fontSize:kq})}for(let k=m;k<=r;k+=n){if(k%Z===0)continue;let w={x:q.x,y:k*p},R=dQ/K,C=lQ/K;sQ(Q,K,w,R,k,{textOffset:C,fontSize:Iq})}for(let k=O;k<=x;k+=y){if(k%Z===0)continue;let w={x:q.x,y:k*p},R=pQ/K;sQ(Q,K,w,R,k)}Q.restore()}function sQ(Q,q,$,J,U,K){let G=K!==void 0;if(Q.save(),Q.lineWidth=1/q,Q.beginPath(),Q.moveTo($.x,$.y),Q.lineTo($.x+J,$.y),Q.stroke(),Q.restore(),!G)return;let Y=K.color??"green";Q.save(),Q.textAlign="left",Q.textBaseline="middle",Q.fillStyle=Y,Q.font=`${K.fontSize/q}px Arial`;let j=U%1==0?U:U.toFixed(2);Q.fillText(`${j}`,$.x+J+K.textOffset,$.y),Q.restore()}function cQ(Q,q,$,J,U,K){let G=K!==void 0;if(Q.save(),Q.lineWidth=1/q,Q.beginPath(),Q.moveTo($.x,$.y),Q.lineTo($.x,$.y+J),Q.stroke(),Q.restore(),!G)return;let Y=K.color??"red";Q.save(),Q.textAlign="center",Q.textBaseline="top",Q.fillStyle=Y,Q.font=`${K.fontSize/q}px Arial`;let j=U%1==0?U:U.toFixed(2);Q.fillText(`${j}`,$.x,$.y+J+K.textOffset),Q.restore()}function Hq(Q,q,$){let J=Math.min(Q,q),U=Math.max(Q,q),K=U-J,G=$?$:VQ(K),Y=Math.max(1,G),j=Math.pow(10,Y-G),W=(Q>0?Math.floor(J*j/Math.pow(10,Y)):Math.ceil(J*j/Math.pow(10,Y)))*Math.pow(10,Y),_=(q>0?Math.floor(U*j/Math.pow(10,Y)):Math.ceil(U*j/Math.pow(10,Y)))*Math.pow(10,Y),E=Math.pow(10,Y),A=Y-1,H=(Q>0?Math.floor(J*j/Math.pow(10,A)):Math.ceil(J*j/Math.pow(10,A)))*Math.pow(10,A),z=(q>0?Math.floor(U*j/Math.pow(10,A)):Math.ceil(U*j/Math.pow(10,A)))*Math.pow(10,A),Z=Math.pow(10,A),O=E/2,y=(Q>0?Math.floor(J*j/O):Math.ceil(J*j/O))*O,r=(q>0?Math.floor(U*j/O):Math.ceil(U*j/O))*O;return{minMajorTickValue:W,maxMajorTickValue:_,majorTickStep:E,minMinTickValue:H,maxMaxTickValue:z,minTickStep:Z,minHalfTickValue:y,maxHalfTickValue:r,halfTickStep:O,calibrationMultiplier:1/j,normalizedOrderOfMagnitude:Y}}function Oq(Q,q,$,J){let U=t(Q),K=QQ(Q);if(U==null||K==null)return;let G=Math.abs(U*Math.cos(J)),Y=Math.abs(K*Math.cos(J)),j=Math.abs(U*Math.sin(J)),B=Math.abs(K*Math.sin(J)),W=q/G,F=q/Y,_=$/j,E=$/B;if(W==1/0)W=0;if(F==1/0)F=0;if(_==1/0)_=0;if(E==1/0)E=0;let A=$/K,I=q/U;return Math.max(A,I,W,F,_,E)}function DQ(Q,q){if(q==null)return!1;if(Q==null)return!0;if(q==1/0)return!1;if(Q!==void 0&&(Q.min==null||q>Q.min))return!0;return!1}function rQ(Q,q,$,J){let U=t(Q);if(U==null)return;let K=Math.abs(U*Math.cos(J)),G=Math.abs(U*Math.sin(J)),Y=q/K,j=$/G;if(Y==1/0)return j;return Math.max(q/K,$/G)}function b7(Q,q,$,J){let U=QQ(Q);if(U==null)return;let K=Math.abs(U*Math.cos(J)),G=Math.abs(U*Math.sin(J)),Y=q/K,j=$/G;if(j==1/0)return Y;return Math.max(Y,j)}import{PointCal as v$}from"@ue-too/math";class zQ{pan;zoom;rotate;all;constructor(){this.pan=new f,this.zoom=new f,this.rotate=new f,this.all=new f}notifyPan(Q){this.pan.notify({diff:Q}),this.all.notify({type:"pan",diff:Q})}notifyZoom(Q,q){this.zoom.notify({deltaZoomAmount:Q,anchorPoint:q}),this.all.notify({type:"zoom",deltaZoomAmount:Q,anchorPoint:q})}notifyRotate(Q){this.rotate.notify({deltaRotation:Q}),this.all.notify({type:"rotate",deltaRotation:Q})}on(Q,q){switch(Q){case"pan":return this.pan.subscribe(q);case"zoom":return this.zoom.subscribe(q);case"rotate":return this.rotate.subscribe(q);case"all":return this.all.subscribe(q);default:throw Error("Invalid raw user input event name")}}}function s7(){return new zQ}class A${pan;zoom;rotate;all;webWorker;constructor(Q){this.pan=new f,this.zoom=new f,this.rotate=new f,this.all=new f,this.webWorker=Q}notifyPan(Q){this.webWorker.postMessage({type:"notifyUserInput",payload:{type:"pan",diff:Q}}),this.pan.notify({diff:Q}),this.all.notify({type:"pan",diff:Q})}notifyZoom(Q,q){this.webWorker.postMessage({type:"notifyUserInput",payload:{type:"zoom",deltaZoomAmount:Q,anchorPoint:q}}),this.zoom.notify({deltaZoomAmount:Q,anchorPoint:q}),this.all.notify({type:"zoom",deltaZoomAmount:Q,anchorPoint:q})}notifyRotate(Q){this.webWorker.postMessage({type:"notifyUserInput",payload:{type:"rotate",deltaRotation:Q}}),this.rotate.notify({deltaRotation:Q}),this.all.notify({type:"rotate",deltaRotation:Q})}on(Q,q){switch(Q){case"pan":return this.pan.subscribe(q);case"zoom":return this.zoom.subscribe(q);case"rotate":return this.rotate.subscribe(q);case"all":return this.all.subscribe(q);default:throw Error("Invalid raw user input event name")}}}class Dq{constructor(){}notifyPanInput(Q){return{allowPassThrough:!0,delta:Q}}notifyZoomInput(Q,q){return{allowPassThrough:!0,delta:Q,anchorPoint:q}}notifyRotationInput(Q){return{allowPassThrough:!0,delta:Q}}}function i7(){return new Dq}import{NO_OP as MQ,TemplateState as nQ,TemplateStateMachine as W$}from"@ue-too/being";class zq extends W${constructor(Q,q,$){super(Q,q,$)}notifyPanInput(Q){return this.happens("userPanByInput",{diff:Q})}notifyPanToAnimationInput(Q){return this.happens("transitionPanToInput",{target:Q})}initateTransition(){return this.happens("initateTransition")}}class Mq extends nQ{constructor(){super()}_eventReactions={userPanByInput:{action:this.userPanByInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},userPanToInput:{action:this.userPanToInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},lockedOnObjectPanByInput:{action:this.lockedOnObjectPanByInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectPanToInput:{action:this.lockedOnObjectPanToInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},initateTransition:{action:MQ,defaultTargetState:"TRANSITION"}};userPanByInputHandler(Q,q){return{type:"panByViewPort",delta:q.diff}}userPanToInputHandler(Q,q){return{type:"panToWorld",target:q.target}}lockedOnObjectPanByInputHandler(Q,q){return{type:"panByViewPort",delta:q.diff}}lockedOnObjectPanToInputHandler(Q,q){return{type:"panToWorld",target:q.target}}}class Zq extends nQ{constructor(){super()}_eventReactions={userPanByInput:{action:this.userPanByInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},userPanToInput:{action:this.userPanToInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},transitionPanByInput:{action:this.transitionPanByInputHandler,defaultTargetState:"TRANSITION"},transitionPanToInput:{action:this.transitionPanToInputHandler,defaultTargetState:"TRANSITION"},lockedOnObjectPanByInput:{action:this.lockedOnObjectPanByInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectPanToInput:{action:this.lockedOnObjectPanToInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"}};userPanByInputHandler(Q,q){return{type:"panByViewPort",delta:q.diff}}userPanToInputHandler(Q,q){return{type:"panToWorld",target:q.target}}transitionPanByInputHandler(Q,q){return{type:"panByViewPort",delta:q.diff}}transitionPanToInputHandler(Q,q){return{type:"panToWorld",target:q.target}}lockedOnObjectPanByInputHandler(Q,q){return{type:"panByViewPort",delta:q.diff}}lockedOnObjectPanToInputHandler(Q,q){return{type:"panToWorld",target:q.target}}}class Tq extends nQ{constructor(){super()}_eventReactions={unlock:{action:MQ,defaultTargetState:"ACCEPTING_USER_INPUT"},lockedOnObjectPanByInput:{action:this.lockedOnObjectPanByInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectPanToInput:{action:this.lockedOnObjectPanToInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"}};lockedOnObjectPanByInputHandler(Q,q){return{type:"panByViewPort",delta:q.diff}}lockedOnObjectPanToInputHandler(Q,q){return{type:"panToWorld",target:q.target}}}function k$(){return{ACCEPTING_USER_INPUT:new Mq,TRANSITION:new Zq,LOCKED_ON_OBJECT:new Tq}}function Sq(Q={setup:MQ,cleanup:MQ}){return new zq(k$(),"ACCEPTING_USER_INPUT",Q)}import{NO_OP as iQ,TemplateState as aQ,TemplateStateMachine as I$}from"@ue-too/being";class wq extends aQ{_eventReactions={userZoomByAtInput:{action:this.userZoomByAtInput,defaultTargetState:"ACCEPTING_USER_INPUT"},userZoomToAtInput:{action:this.userZoomToAtInput,defaultTargetState:"ACCEPTING_USER_INPUT"},initiateTransition:{action:iQ,defaultTargetState:"TRANSITION"}};userZoomByAtInput(Q,q){return{type:"zoomByAt",deltaZoom:q.deltaZoom,anchorPoint:q.anchorPoint}}userZoomToAtInput(Q,q){return{type:"zoomToAt",targetZoom:q.targetZoom,anchorPoint:q.anchorPoint}}}class Rq extends aQ{constructor(){super()}_eventReactions={lockedOnObjectZoomByAtInput:{action:this.lockedOnObjectZoomByAtInput,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectZoomToAtInput:{action:this.lockedOnObjectZoomToAtInput,defaultTargetState:"LOCKED_ON_OBJECT"},transitionZoomByAtInput:{action:this.transitionZoomByAtInput,defaultTargetState:"TRANSITION"},transitionZoomToAtInput:{action:this.transitionZoomToAtInput,defaultTargetState:"TRANSITION"},transitionZoomToAtCenterInput:{action:this.transitionZoomToAtCenterInput,defaultTargetState:"TRANSITION"},transitionZoomToAtWorldInput:{action:this.transitionZoomToAtWorldInput,defaultTargetState:"TRANSITION"},userZoomByAtInput:{action:this.userZoomByAtInput,defaultTargetState:"ACCEPTING_USER_INPUT"},userZoomToAtInput:{action:this.userZoomToAtInput,defaultTargetState:"ACCEPTING_USER_INPUT"}};lockedOnObjectZoomByAtInput(Q,q){return{type:"zoomBy",deltaZoom:q.deltaZoom}}lockedOnObjectZoomToAtInput(Q,q){return{type:"zoomTo",targetZoom:q.targetZoom}}userZoomByAtInput(Q,q){return{type:"zoomByAt",deltaZoom:q.deltaZoom,anchorPoint:q.anchorPoint}}userZoomToAtInput(Q,q){return{type:"zoomToAt",targetZoom:q.targetZoom,anchorPoint:q.anchorPoint}}transitionZoomByAtInput(Q,q){return{type:"zoomByAt",deltaZoom:q.deltaZoom,anchorPoint:q.anchorPoint}}transitionZoomByAtCenterInput(Q,q){return{type:"zoomBy",deltaZoom:q.deltaZoom}}transitionZoomToAtInput(Q,q){return{type:"zoomToAt",targetZoom:q.targetZoom,anchorPoint:q.anchorPoint}}transitionZoomToAtCenterInput(Q,q){return{type:"zoomTo",targetZoom:q.targetZoom}}transitionZoomToAtWorldInput(Q,q){return{type:"zoomToAtWorld",targetZoom:q.targetZoom,anchorPoint:q.anchorPoint}}}class yq extends aQ{constructor(){super()}_eventReactions={lockedOnObjectZoomByAtInput:{action:this.lockedOnObjectZoomByAtInput,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectZoomToAtInput:{action:this.lockedOnObjectZoomToAtInput,defaultTargetState:"LOCKED_ON_OBJECT"},userZoomByAtInput:{action:this.userZoomByAtInput,defaultTargetState:"ACCEPTING_USER_INPUT"},userZoomToAtInput:{action:this.userZoomToAtInput,defaultTargetState:"ACCEPTING_USER_INPUT"}};lockedOnObjectZoomByAtInput(Q,q){return{type:"zoomByAt",deltaZoom:q.deltaZoom,anchorPoint:q.anchorPoint}}lockedOnObjectZoomToAtInput(Q,q){return{type:"zoomToAt",targetZoom:q.targetZoom,anchorPoint:q.anchorPoint}}userZoomByAtInput(Q,q){return{type:"zoomByAt",deltaZoom:q.deltaZoom,anchorPoint:q.anchorPoint}}userZoomToAtInput(Q,q){return{type:"zoomToAt",targetZoom:q.targetZoom,anchorPoint:q.anchorPoint}}}class bq extends I${constructor(Q,q,$){super(Q,q,$)}notifyZoomByAtInput(Q,q){return this.happens("userZoomByAtInput",{deltaZoom:Q,anchorPoint:q})}notifyZoomByAtInputAnimation(Q,q){return this.happens("transitionZoomByAtInput",{deltaZoom:Q,anchorPoint:q})}notifyZoomToAtCenterInput(Q,q){return this.happens("transitionZoomToAtCenterInput",{targetZoom:Q,anchorPoint:q})}notifyZoomToAtWorldInput(Q,q){return this.happens("transitionZoomToAtWorldInput",{targetZoom:Q,anchorPoint:q})}initateTransition(){return this.happens("initiateTransition")}}function H$(){return{ACCEPTING_USER_INPUT:new wq,TRANSITION:new Rq,LOCKED_ON_OBJECT:new yq}}function Cq(Q={setup:iQ,cleanup:iQ}){return new bq(H$(),"ACCEPTING_USER_INPUT",Q)}import{NO_OP as ZQ,TemplateState as oQ,TemplateStateMachine as O$}from"@ue-too/being";class fq extends O${constructor(Q,q,$){super(Q,q,$)}notifyRotateByInput(Q){return this.happens("userRotateByInput",{diff:Q})}notifyRotateToAnimationInput(Q){return this.happens("transitionRotateToInput",{target:Q})}initateTransition(){this.happens("initateTransition")}}class Lq extends oQ{constructor(){super()}_eventReactions={userRotateByInput:{action:this.userRotateByInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},userRotateToInput:{action:this.userRotateToInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},lockedOnObjectRotateByInput:{action:this.lockedOnObjectRotateByInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectRotateToInput:{action:this.lockedOnObjectRotateToInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},initateTransition:{action:ZQ,defaultTargetState:"TRANSITION"}};userRotateByInputHandler(Q,q){return{type:"rotateBy",delta:q.diff}}userRotateToInputHandler(Q,q){return{type:"rotateTo",target:q.target}}lockedOnObjectRotateByInputHandler(Q,q){return{type:"rotateBy",delta:q.diff}}lockedOnObjectRotateToInputHandler(Q,q){return{type:"rotateTo",target:q.target}}}class Pq extends oQ{constructor(){super()}_eventReactions={userRotateByInput:{action:this.userRotateByInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},userRotateToInput:{action:this.userRotateToInputHandler,defaultTargetState:"ACCEPTING_USER_INPUT"},transitionRotateByInput:{action:this.transitionRotateByInputHandler,defaultTargetState:"TRANSITION"},transitionRotateToInput:{action:this.transitionRotateToInputHandler,defaultTargetState:"TRANSITION"},lockedOnObjectRotateByInput:{action:this.lockedOnObjectRotateByInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectRotateToInput:{action:this.lockedOnObjectRotateToInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"}};userRotateByInputHandler(Q,q){return{type:"rotateBy",delta:q.diff}}userRotateToInputHandler(Q,q){return{type:"rotateTo",target:q.target}}transitionRotateByInputHandler(Q,q){return{type:"rotateBy",delta:q.diff}}transitionRotateToInputHandler(Q,q){return{type:"rotateTo",target:q.target}}lockedOnObjectRotateByInputHandler(Q,q){return{type:"rotateBy",delta:q.diff}}lockedOnObjectRotateToInputHandler(Q,q){return{type:"rotateTo",target:q.target}}}class hq extends oQ{constructor(){super()}_eventReactions={unlock:{action:ZQ,defaultTargetState:"ACCEPTING_USER_INPUT"},lockedOnObjectRotateByInput:{action:this.lockedOnObjectRotateByInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"},lockedOnObjectRotateToInput:{action:this.lockedOnObjectRotateToInputHandler,defaultTargetState:"LOCKED_ON_OBJECT"}};lockedOnObjectRotateByInputHandler(Q,q){return{type:"rotateBy",delta:q.diff}}lockedOnObjectRotateToInputHandler(Q,q){return{type:"rotateTo",target:q.target}}}function D$(){return{ACCEPTING_USER_INPUT:new Lq,TRANSITION:new Pq,LOCKED_ON_OBJECT:new hq}}function gq(Q={setup:ZQ,cleanup:ZQ}){return new fq(D$(),"ACCEPTING_USER_INPUT",Q)}class xq{_panStateMachine;_zoomStateMachine;_rotateStateMachine;constructor(Q,q,$){this._panStateMachine=Q,this._zoomStateMachine=q,this._rotateStateMachine=$}notifyPanToAnimationInput(Q){let q=this._panStateMachine.notifyPanToAnimationInput(Q);if(q.handled){let $=q.output;if($!==void 0)switch($.type){case"panByViewPort":return{allowPassThrough:!0,delta:$.delta};case"panToWorld":return{allowPassThrough:!0,delta:$.target};default:return{allowPassThrough:!1}}}return{allowPassThrough:!1}}notifyPanInput(Q){let q=this._panStateMachine.happens("userPanByInput",{diff:Q});if(q.handled&&"output"in q&&q.output){if(q.output.type!=="none")return{allowPassThrough:!0,delta:Q}}return{allowPassThrough:!1}}notifyZoomInput(Q,q){let $=this._zoomStateMachine.happens("userZoomByAtInput",{deltaZoom:Q,anchorPoint:q});if($.handled&&"output"in $&&$.output){if($.output.type!=="none")return{allowPassThrough:!0,delta:Q,anchorPoint:q}}return{allowPassThrough:!1}}notifyRotateByInput(Q){return this._rotateStateMachine.notifyRotateByInput(Q)}notifyRotateToAnimationInput(Q){return this._rotateStateMachine.notifyRotateToAnimationInput(Q)}notifyZoomInputAnimation(Q,q={x:0,y:0}){this._zoomStateMachine.notifyZoomToAtCenterInput(Q,q)}notifyZoomInputAnimationWorld(Q,q={x:0,y:0}){this._zoomStateMachine.notifyZoomToAtWorldInput(Q,q)}notifyRotationInput(Q){let q=this._rotateStateMachine.happens("userRotateByInput",{diff:Q});if(q.handled&&"output"in q&&q.output){if(q.output.type!=="none")return{allowPassThrough:!0,delta:Q}}return{allowPassThrough:!1}}initatePanTransition(){this._panStateMachine.initateTransition()}initateZoomTransition(){this._zoomStateMachine.initateTransition()}initateRotateTransition(){this._rotateStateMachine.initateTransition()}get rotateStateMachine(){return this._rotateStateMachine}get panStateMachine(){return this._panStateMachine}get zoomStateMachine(){return this._zoomStateMachine}}function uq(){let Q=Sq(),q=Cq(),$=gq();return new xq(Q,q,$)}function z$(Q,q,$){if(!$.clampZoom)return Q;return GQ(Q,q.zoomBoundaries)}function M$(Q,q,$){if(!$.clampZoom)return Q;let J=q.zoomLevel+Q;return J=GQ(J,q.zoomBoundaries),Q=J-q.zoomLevel,Q}function Z$(Q,q,$){if($.restrictZoom)return q.zoomLevel;return Q}function T$(Q,q,$){if($.restrictZoom)return 0;return Q}function vq(){return d(z$,Z$)}function pq(){return d(M$,T$)}import{PointCal as P}from"@ue-too/math";function dq(){return d(S$,R$)}function mq(){return d(w$,y$)}function S$(Q,q,$){let J=P.subVector(Q,q.position);if(J=lq(J,q,$),J.x===0&&J.y===0)return Q;return P.addVector(q.position,J)}function w$(Q,q,$){return Q=lq(Q,q,$),Q}function R$(Q,q,$){if(!$.clampTranslation)return Q;let J=e(Q,q.boundaries);if($.limitEntireViewPort)J=LQ(Q,q.viewPortWidth,q.viewPortHeight,q.boundaries,q.zoomLevel,q.rotation);return J}function y$(Q,q,$){if(!$.clampTranslation)return Q;let J=P.subVector(e(P.addVector(q.position,Q),q.boundaries),q.position);if($.limitEntireViewPort)J=P.subVector(LQ(P.addVector(q.position,Q),q.viewPortWidth,q.viewPortHeight,q.boundaries,q.zoomLevel,q.rotation),q.position);return J}function lq(Q,q,$){if($.restrictXTranslation&&$.restrictYTranslation)return{x:0,y:0};if($.restrictRelativeXTranslation&&$.restrictRelativeYTranslation)return{x:0,y:0};if($.restrictXTranslation)Q.x=0;if($.restrictYTranslation)Q.y=0;if($.restrictRelativeXTranslation){let J=P.rotatePoint({x:0,y:1},q.rotation),U=P.dotProduct(J,Q);Q=P.multiplyVectorByScalar(J,U)}if($.restrictRelativeYTranslation){let J=P.rotatePoint({x:1,y:0},q.rotation),U=P.dotProduct(J,Q);Q=P.multiplyVectorByScalar(J,U)}return Q}function R6(Q,q){return P.multiplyVectorByScalar(P.rotatePoint(Q,q.rotation),1/q.zoomLevel)}function b$(Q,q,$){if(!$.clampRotation)return Q;let J=S(q.rotation+Q),U=YQ(J,q.rotationBoundaries);return XQ(q.rotation,U)}function C$(Q,q,$){if($.restrictRotation)return 0;return Q}function f$(Q,q,$){if(!$.clampRotation)return Q;return YQ(Q,q.rotationBoundaries)}function L$(Q,q,$){if($.restrictRotation)return q.rotation;return Q}function sq(){return d(C$,b$)}function cq(){return d(L$,f$)}import{PointCal as u}from"@ue-too/math";class TQ{_panBy;_panTo;_zoomTo;_zoomBy;_rotateBy;_rotateTo;_config;_camera;constructor(Q,q=new $Q){this._panBy=mq(),this._panTo=dq(),this._zoomTo=vq(),this._zoomBy=pq(),this._rotateBy=sq(),this._rotateTo=cq(),this._config={...Q,restrictRotation:!1,clampRotation:!0},this._camera=q}zoomToAt(Q,q){let $=this._camera.convertFromViewPort2WorldSpace(q),J=this._zoomTo(Q,this._camera,this._config);this._camera.setZoomLevel(J);let U=this._camera.convertFromViewPort2WorldSpace(q),K=u.subVector($,U),G=this._panBy(K,this._camera,this._config);this._camera.setPosition(u.addVector(this._camera.position,G))}zoomByAt(Q,q){let $=Q*this._camera.zoomLevel,J=this._camera.convertFromViewPort2WorldSpace(q),U=this._zoomBy($,this._camera,this._config);this._camera.setZoomLevel(this._camera.zoomLevel+U);let K=this._camera.convertFromViewPort2WorldSpace(q),G=u.subVector(J,K),Y=this._panBy(G,this._camera,this._config);this._camera.setPosition(u.addVector(this._camera.position,Y))}zoomTo(Q){let q=this._zoomTo(Q,this._camera,this._config);this._camera.setZoomLevel(q)}zoomBy(Q){let q=this._zoomBy(Q,this._camera,this._config);this._camera.setZoomLevel(this._camera.zoomLevel+q)}zoomToAtWorld(Q,q){let $=this._camera.convertFromWorld2ViewPort(q),J=this._zoomTo(Q,this._camera,this._config);this._camera.setZoomLevel(J);let U=this._camera.convertFromWorld2ViewPort(q),K=u.subVector(U,$),G=bQ(K,this._camera.zoomLevel,this._camera.rotation),Y=this._panBy(G,this._camera,this._config);this._camera.setPosition(u.addVector(this._camera.position,Y))}zoomByAtWorld(Q,q){let $=this._camera.convertFromWorld2ViewPort(q),J=this._zoomBy(Q,this._camera,this._config);this._camera.setZoomLevel(this._camera.zoomLevel+J);let U=this._camera.convertFromWorld2ViewPort(q),K=u.subVector(U,$),G=bQ(K,this._camera.zoomLevel,this._camera.rotation),Y=this._panBy(G,this._camera,this._config);this._camera.setPosition(u.addVector(this._camera.position,Y))}panByViewPort(Q){let q=u.multiplyVectorByScalar(u.rotatePoint(Q,this._camera.rotation),1/this._camera.zoomLevel);this.panByWorld(q)}panByWorld(Q){let q=this._panBy(Q,this._camera,this._config);this._camera.setPosition(u.addVector(this._camera.position,q))}panToWorld(Q){let q=this._panTo(Q,this._camera,this._config);this._camera.setPosition(q)}panToViewPort(Q){let q=this._camera.convertFromViewPort2WorldSpace(Q);this.panToWorld(q)}rotateBy(Q){let q=this._rotateBy(Q,this._camera,this._config);this._camera.setRotation(this._camera.rotation+q)}rotateTo(Q){let q=this._rotateTo(Q,this._camera,this._config);this._camera.setRotation(q)}set limitEntireViewPort(Q){this._config.limitEntireViewPort=Q}get limitEntireViewPort(){return this._config.limitEntireViewPort}get camera(){return this._camera}set camera(Q){this._camera=Q}get config(){return this._config}set config(Q){this._config={...Q}}configure(Q){this._config={...this._config,...Q}}cleanup(){}setup(){}update(){}}function e6(Q){return new TQ({limitEntireViewPort:!0,restrictRelativeXTranslation:!1,restrictRelativeYTranslation:!1,restrictXTranslation:!1,restrictYTranslation:!1,restrictZoom:!1,clampTranslation:!0,clampZoom:!0},Q)}import{NO_OP as AQ}from"@ue-too/being";var rq;((J)=>{J.GRAB="grab";J.DEFAULT="default";J.GRABBING="grabbing"})(rq||={});class nq{width=0;height=0;position={x:0,y:0};setCursor=AQ;dimensions={width:0,height:0,position:{x:0,y:0}};detached=!1;tearDown=AQ}class P${_width;_height;_position;_postMessageFunction;constructor(Q){this._width=0,this._height=0,this._position={x:0,y:0},this._postMessageFunction=Q}get dimensions(){return{width:this._width,height:this._height,position:this._position}}tearDown(){}set width(Q){this._width=Q}set height(Q){this._height=Q}set position(Q){this._position=Q}get width(){return this._width}get height(){return this._height}get position(){return this._position}setCursor(Q){this._postMessageFunction({type:"setCursor",style:Q})}get detached(){return!1}}class eQ{_width=0;_height=0;_position={x:0,y:0};_canvasPositionDimensionPublisher;_canvas;_internalSizeUpdateObservable;constructor(Q){if(this._internalSizeUpdateObservable=new i,Q){let q=Q.getBoundingClientRect(),$=M(q,window.getComputedStyle(Q));this._width=$.width,this._height=$.height,this._position={x:$.left,y:$.top},this._canvas=Q}this._canvasPositionDimensionPublisher=new vQ(Q),this._canvasPositionDimensionPublisher.onPositionUpdate((q)=>{if(this._canvas==null){console.error("is not attached to any canvas should not have getting any updates");return}this._width=q.width,this._height=q.height,this._position={x:q.left,y:q.top},this._internalSizeUpdateObservable.notify({width:this._width,height:this._height,position:this._position})})}subscribe(Q,q){return this._internalSizeUpdateObservable.subscribe(Q,q)}notify(...Q){this._internalSizeUpdateObservable.notify(...Q)}get detached(){return this._canvas===void 0}get dimensions(){return{width:this._width,height:this._height,position:this._position}}get width(){return this._width}setWidth(Q){if(this._canvas)this._canvas.width=Q*window.devicePixelRatio,this._canvas.style.width=Q+"px"}setCanvasWidth(Q){if(this._canvas&&this._canvas.style.width===""&&this._canvas.style.height===""){let q=this._width/this._height;this._canvas.style.aspectRatio=q.toString()}if(this._canvas&&this._canvas.style.width!=="")this._canvas.width=Q*window.devicePixelRatio;else this.setWidth(Q)}setHeight(Q){if(this._canvas)this._canvas.height=Q*window.devicePixelRatio,this._canvas.style.height=Q+"px"}setCanvasHeight(Q){if(this._canvas&&this._canvas.style.width===""&&this._canvas.style.height===""){let q=this._width/this._height;this._canvas.style.aspectRatio=q.toString()}if(this._canvas&&this._canvas.style.height!=="")this._canvas.height=Q*window.devicePixelRatio;else this.setHeight(Q)}get height(){return this._height}get position(){return this._position}setCursor(Q){if(this._canvas)this._canvas.style.cursor=Q}tearDown(){this._canvasPositionDimensionPublisher.dispose(),this._canvas=void 0,this._width=0,this._height=0,this._position={x:0,y:0}}attach(Q){this._canvas=Q,this._canvasPositionDimensionPublisher.attach(Q)}logCanvasTrueSize(){if(this._canvas===void 0)return;console.log("canvas true size"),console.log("style width",this._canvas.style.width),console.log("style height",this._canvas.style.height),console.log("width",this._canvas.width),console.log("height",this._canvas.height),console.log("proxy width",this._width),console.log("proxy height",this._height)}}class h${_width=0;_height=0;_position={x:0,y:0};_svgPositionDimensionPublisher;_svg;_internalSizeUpdateObservable;constructor(Q){if(this._internalSizeUpdateObservable=new i,Q){let q=Q.getBoundingClientRect(),$=M(q,window.getComputedStyle(Q));this._width=$.width,this._height=$.height,this._position={x:$.left,y:$.top},this._svg=Q}this._svgPositionDimensionPublisher=new uQ(Q),this._svgPositionDimensionPublisher.onPositionUpdate((q)=>{if(this._svg==null){console.error("is not attached to any canvas should not have getting any updates");return}this._width=q.width,this._height=q.height,this._position={x:q.left,y:q.top},this._internalSizeUpdateObservable.notify({width:this._width,height:this._height,position:this._position})})}subscribe(Q,q){return this._internalSizeUpdateObservable.subscribe(Q,q)}notify(...Q){this._internalSizeUpdateObservable.notify(...Q)}get detached(){return this._svg===void 0}get dimensions(){return{width:this._width,height:this._height,position:this._position}}get width(){return this._width}setWidth(Q){if(this._svg)this._svg.style.width=Q+"px"}setHeight(Q){if(this._svg)this._svg.style.height=Q+"px"}get height(){return this._height}get position(){return this._position}setCursor(Q){if(this._svg)this._svg.style.cursor=Q}tearDown(){this._svgPositionDimensionPublisher.dispose(),this._svg=void 0,this._width=0,this._height=0,this._position={x:0,y:0}}attach(Q){this._svgPositionDimensionPublisher.attach(Q),this._svg=Q;let q=Q.getBoundingClientRect(),$=M(q,window.getComputedStyle(Q));this._svg.style.width=$.width+"px",this._svg.style.height=$.height+"px",this._width=$.width,this._height=$.height,this._position={x:$.left,y:$.top},this._internalSizeUpdateObservable.notify({width:this._width,height:this._height,position:this._position})}logCanvasTrueSize(){if(this._svg===void 0)return;console.log("canvas true size"),console.log("style width",this._svg.style.width),console.log("style height",this._svg.style.height),console.log("width",this._svg.width),console.log("height",this._svg.height),console.log("proxy width",this._width),console.log("proxy height",this._height)}}class g${_width;_height;_position;_webWorker;_canvas;_canvasDiemsionPublisher;constructor(Q,q,$){let J=Q.getBoundingClientRect();this._canvas=Q,this._webWorker=q;let U=M(J,window.getComputedStyle(Q));this._width=U.width,this._height=U.height,this._position={x:U.left,y:U.top},this._webWorker.postMessage({type:"setCanvasDimensions",width:J.width,height:J.height,position:{x:J.left,y:J.top}}),$.onPositionUpdate((K)=>{this._width=K.width,this._height=K.height,this._position={x:K.left,y:K.top},this._webWorker.postMessage({type:"updateCanvasDimensions",width:K.width,height:K.height,position:{x:K.left,y:K.top}})}),this._canvasDiemsionPublisher=$}get width(){return this._width}get height(){return this._height}tearDown(){this._canvasDiemsionPublisher.dispose()}get position(){return this._position}get dimensions(){return{width:this._width,height:this._height,position:this._position}}get detached(){return!1}setCursor(Q){this._canvas.style.cursor=Q}}class tQ{alignCoordinateSystem=!1;canvas=new nq;initialCursorPosition={x:0,y:0};constructor(){}toggleOnEdgeAutoCameraInput=AQ;toggleOffEdgeAutoCameraInput=AQ;setCursorPosition=AQ;setInitialCursorPosition(Q){}cleanup(){}setup(){}get kmtTrackpadTrackScore(){return 0}subtractKmtTrackpadTrackScore(){}addKmtTrackpadTrackScore(){}setMode(Q){}get mode(){return"kmt"}cancelCurrentAction(){}}class WQ{_alignCoordinateSystem;_canvasOperator;_initialCursorPosition;_kmtTrackpadTrackScore;_mode;_deciding=!0;constructor(Q){this._alignCoordinateSystem=!0,this._canvasOperator=Q,this._initialCursorPosition={x:0,y:0},this._kmtTrackpadTrackScore=0,this._mode="TBD"}get mode(){return this._mode}setMode(Q){this._deciding=!1,this._mode=Q}enableInputModeDetection(){this._deciding=!0,this._kmtTrackpadTrackScore=0}get kmtTrackpadTrackScore(){return this._kmtTrackpadTrackScore}subtractKmtTrackpadTrackScore(){if(!this._deciding)return;if(this._kmtTrackpadTrackScore--,this._kmtTrackpadTrackScore<-5)this._kmtTrackpadTrackScore=0}addKmtTrackpadTrackScore(){if(!this._deciding)return;if(this._kmtTrackpadTrackScore++,this._kmtTrackpadTrackScore>5)this._kmtTrackpadTrackScore=0}get alignCoordinateSystem(){return this._alignCoordinateSystem}get canvas(){return this._canvasOperator}get initialCursorPosition(){return this._initialCursorPosition}set alignCoordinateSystem(Q){this._alignCoordinateSystem=Q}cancelCurrentAction(){this._initialCursorPosition={x:0,y:0}}setInitialCursorPosition(Q){this._initialCursorPosition=Q}cleanup(){}setup(){}}class Qq{_touchPointsMap=new Map;_canvas;_alignCoordinateSystem;constructor(Q){this._canvas=Q,this._alignCoordinateSystem=!0}addTouchPoints(Q){Q.forEach((q)=>{this._touchPointsMap.set(q.ident,{...q})})}removeTouchPoints(Q){Q.forEach((q)=>{if(this._touchPointsMap.has(q))this._touchPointsMap.delete(q)})}getCurrentTouchPointsCount(){return this._touchPointsMap.size}getInitialTouchPointsPositions(Q){let q=[];return Q.forEach(($)=>{if(this._touchPointsMap.has($)){let J=this._touchPointsMap.get($);if(J)q.push(J)}}),q}updateTouchPoints(Q){Q.forEach((q)=>{if(this._touchPointsMap.has(q.ident))this._touchPointsMap.set(q.ident,{...q})})}get alignCoordinateSystem(){return this._alignCoordinateSystem}set alignCoordinateSystem(Q){this._alignCoordinateSystem=Q}get canvas(){return this._canvas}cleanup(){}setup(){}}import{PointCal as h}from"@ue-too/math";import{TemplateState as qq,TemplateStateMachine as x$}from"@ue-too/being";class iq extends qq{_eventReactions={touchstart:{action:this.touchstart,defaultTargetState:"IDLE"},touchend:{action:this.touchend,defaultTargetState:"IDLE"}};_guards={touchPointsCount:((Q)=>{return Q.getCurrentTouchPointsCount()===2}).bind(this)};_eventGuards={touchstart:[{guard:"touchPointsCount",target:"PENDING"}],touchend:[{guard:"touchPointsCount",target:"PENDING"}]};touchstart(Q,q){Q.addTouchPoints(q.points)}touchend(Q,q){Q.removeTouchPoints(q.points.map(($)=>$.ident))}}class aq extends qq{_eventReactions={touchstart:{action:this.touchstart,defaultTargetState:"IDLE"},touchend:{action:this.touchend,defaultTargetState:"IDLE"},touchmove:{action:this.touchmove,defaultTargetState:"IN_PROGRESS"}};touchstart(Q,q){Q.addTouchPoints(q.points)}touchend(Q,q){Q.removeTouchPoints(q.points.map(($)=>$.ident))}touchmove(Q,q){let $=q.points.map((E)=>E.ident),J=Q.getInitialTouchPointsPositions($),U=q.points,K=h.distanceBetweenPoints(J[0],J[1]),G=h.distanceBetweenPoints(U[0],U[1]),Y=h.linearInterpolation(J[0],J[1],0.5),j=h.linearInterpolation(U[0],U[1],0.5),B=h.subVector(Y,j),W={x:Q.canvas.position.x+Q.canvas.width/2,y:Q.canvas.position.y+Q.canvas.height/2},F=h.subVector(Y,W),_=Math.abs(G-K)>h.distanceBetweenPoints(Y,j)?"ZOOMING":"PANNING";switch(Q.updateTouchPoints(U),_){case"ZOOMING":return{type:"zoom",delta:(G-K)*0.005,anchorPointInViewPort:F};case"PANNING":return{type:"pan",delta:B};default:return console.warn("Unknown panZoom state",_),{type:"none"}}}}class oq extends qq{_eventReactions={touchmove:{action:this.touchmove,defaultTargetState:"IN_PROGRESS"},touchend:{action:this.touchend,defaultTargetState:"IDLE"},touchstart:{action:()=>"IDLE",defaultTargetState:"IDLE"}};touchmove(Q,q){let $=q.points.map((E)=>E.ident),J=Q.getInitialTouchPointsPositions($),U=q.points,K=h.distanceBetweenPoints(J[0],J[1]),G=h.distanceBetweenPoints(U[0],U[1]),Y=h.linearInterpolation(J[0],J[1],0.5),j=h.linearInterpolation(U[0],U[1],0.5),B=h.subVector(Y,j),W={x:Q.canvas.position.x+Q.canvas.width/2,y:Q.canvas.position.y+Q.canvas.height/2},F=h.subVector(Y,W),_=Math.abs(G-K)>h.distanceBetweenPoints(Y,j)?"ZOOMING":"PANNING";switch(Q.updateTouchPoints(U),_){case"ZOOMING":if(!Q.alignCoordinateSystem)F.y=-F.y;return{type:"zoom",delta:-(K-G)*0.005,anchorPointInViewPort:F};case"PANNING":if(!Q.alignCoordinateSystem)B.y=-B.y;return{type:"pan",delta:B};default:return console.warn("Unknown panZoom state",_),{type:"none"}}}touchend(Q,q){Q.removeTouchPoints(q.points.map(($)=>$.ident))}}function eq(Q){return new x$({IDLE:new iq,PENDING:new aq,IN_PROGRESS:new oq},"IDLE",Q)}import{TemplateState as c,TemplateStateMachine as tq,NO_OP as v}from"@ue-too/being";class Q$ extends c{constructor(){super()}_guards={isIdle:()=>!0};_eventGuards={};scrollPan=(Q,q)=>{let $={...q};if(!Q.alignCoordinateSystem)$.deltaY=-$.deltaY;return{type:"pan",delta:{x:$.deltaX,y:$.deltaY}}};scrollZoom=(Q,q)=>{let $=0.005;if(Math.abs(q.deltaY)>100)$=0.0005;let J=q.deltaY*$,U={x:q.x,y:q.y},K=Bq(U,Q.canvas,{x:Q.canvas.width/2,y:Q.canvas.height/2},!Q.alignCoordinateSystem);return{type:"zoom",delta:-(J*5),anchorPointInViewPort:K}};scrollHandler=(Q,q)=>{if(q.deltaX===0&&q.deltaY!==0)Q.addKmtTrackpadTrackScore();else if(q.deltaX!==0&&q.deltaY!==0)Q.subtractKmtTrackpadTrackScore();if(Q.mode==="kmt")return this.scrollZoom(Q,q);else return this.scrollPan(Q,q)};scrollWithCtrlHandler=(Q,q)=>{return this.scrollZoom(Q,q)};_eventReactions={spacebarDown:{action:this.spacebarDownHandler,defaultTargetState:"READY_TO_PAN_VIA_SPACEBAR"},scroll:{action:this.scrollHandler,defaultTargetState:"IDLE"},scrollWithCtrl:{action:this.scrollWithCtrlHandler,defaultTargetState:"IDLE"},middlePointerDown:{action:this.middlePointerDownHandler,defaultTargetState:"READY_TO_PAN_VIA_SCROLL_WHEEL"},disable:{action:v,defaultTargetState:"DISABLED"}};uponEnter(Q){Q.canvas.setCursor("default")}spacebarDownHandler(Q,q){return 1}middlePointerDownHandler(Q,q){if(Q.addKmtTrackpadTrackScore(),Q.mode==="TBD")Q.setMode("kmt");Q.setInitialCursorPosition({x:q.x,y:q.y})}}class $q extends c{constructor(){super()}uponEnter(Q){Q.canvas.setCursor("default")}beforeExit(Q){}_eventReactions={enable:{action:v,defaultTargetState:"IDLE"}}}class q$ extends c{constructor(){super()}_eventReactions={spacebarUp:{action:v,defaultTargetState:"IDLE"},leftPointerDown:{action:this.leftPointerDownHandler,defaultTargetState:"INITIAL_PAN"},disable:{action:(Q)=>Q.cancelCurrentAction(),defaultTargetState:"DISABLED"},leftPointerMove:{action:v,defaultTargetState:"READY_TO_PAN_VIA_SPACEBAR"}};uponEnter(Q){Q.canvas.setCursor("grab")}leftPointerDownHandler(Q,q){Q.setInitialCursorPosition({x:q.x,y:q.y})}}class $$ extends c{constructor(){super()}_eventReactions={leftPointerUp:{action:v,defaultTargetState:"READY_TO_PAN_VIA_SPACEBAR"},leftPointerMove:{action:this.leftPointerMoveHandler,defaultTargetState:"PAN"},spacebarUp:{action:()=>"IDLE",defaultTargetState:"IDLE"},leftPointerDown:{action:()=>"PAN",defaultTargetState:"PAN"}};uponEnter(Q){Q.canvas.setCursor("grabbing")}leftPointerMoveHandler(Q,q){let $={x:Q.initialCursorPosition.x-q.x,y:Q.initialCursorPosition.y-q.y};if(!Q.alignCoordinateSystem)$.y=-$.y;return Q.setInitialCursorPosition({x:q.x,y:q.y}),{type:"pan",delta:$}}}class J$ extends c{constructor(){super()}_eventReactions={middlePointerUp:{action:v,defaultTargetState:"IDLE"},middlePointerMove:{action:v,defaultTargetState:"PAN_VIA_SCROLL_WHEEL"}};uponEnter(Q){Q.canvas.setCursor("grabbing")}}class U$ extends c{constructor(){super()}_eventReactions={leftPointerUp:{action:v,defaultTargetState:"READY_TO_PAN_VIA_SPACEBAR"},leftPointerMove:{action:this.leftPointerMoveHandler,defaultTargetState:"PAN"},spacebarUp:{action:v,defaultTargetState:"IDLE"}};uponEnter(Q){Q.canvas.setCursor("grabbing")}beforeExit(Q){Q.canvas.setCursor("default")}leftPointerMoveHandler(Q,q){let $={x:Q.initialCursorPosition.x-q.x,y:Q.initialCursorPosition.y-q.y};if(!Q.alignCoordinateSystem)$.y=-$.y;return Q.setInitialCursorPosition({x:q.x,y:q.y}),{type:"pan",delta:$}}}class K$ extends c{_eventReactions={middlePointerUp:{action:v,defaultTargetState:"IDLE"},middlePointerMove:{action:this.middlePointerMoveHandler,defaultTargetState:"PAN_VIA_SCROLL_WHEEL"}};middlePointerMoveHandler(Q,q){let $={x:Q.initialCursorPosition.x-q.x,y:Q.initialCursorPosition.y-q.y};if(!Q.alignCoordinateSystem)$.y=-$.y;return Q.setInitialCursorPosition({x:q.x,y:q.y}),{type:"pan",delta:$}}uponEnter(Q){Q.canvas.setCursor("grabbing")}}class JQ extends c{constructor(){super()}}function Jq(Q){let q={IDLE:new Q$,READY_TO_PAN_VIA_SPACEBAR:new q$,INITIAL_PAN:new $$,PAN:new U$,READY_TO_PAN_VIA_SCROLL_WHEEL:new J$,PAN_VIA_SCROLL_WHEEL:new K$,DISABLED:new $q};return new tq(q,"IDLE",Q)}function y8(Q){let q=new WQ(Q);return Jq(q)}class u$ extends tq{_webworker;constructor(Q){super({IDLE:new JQ,READY_TO_PAN_VIA_SPACEBAR:new JQ,INITIAL_PAN:new JQ,PAN:new JQ,READY_TO_PAN_VIA_SCROLL_WHEEL:new JQ,PAN_VIA_SCROLL_WHEEL:new JQ,DISABLED:new $q},"IDLE",new tQ);this._webworker=Q}happens(...Q){return this._webworker.postMessage({type:"kmtInputStateMachine",event:Q[0],payload:Q[1]}),{handled:!0,nextState:"IDLE"}}}class Uq{_cameraMux;_cameraRig;_publisher;constructor(Q,q,$){this._cameraMux=Q,this._cameraRig=q,this._publisher=$}processInputEventOutput(Q){if(this.isOutputEvent(Q))this.handleStateMachineOutput(Q);else if(Array.isArray(Q))Q.forEach((q)=>{if(this.isOutputEvent(q))this.handleStateMachineOutput(q)})}processInputEvent(Q){this.handleStateMachineOutput(Q)}isOutputEvent(Q){return Q&&typeof Q==="object"&&"type"in Q}handleStateMachineOutput(Q){switch(Q.type){case"pan":this._publisher?.notifyPan(Q.delta);let q=this._cameraMux.notifyPanInput(Q.delta);this.processPanMuxOutput(q);break;case"zoom":this._publisher?.notifyZoom(Q.delta,Q.anchorPointInViewPort);let $=this._cameraMux.notifyZoomInput(Q.delta,Q.anchorPointInViewPort);this.processZoomMuxOutput($);break;case"rotate":this._publisher?.notifyRotate(Q.deltaRotation);let J=this._cameraMux.notifyRotationInput(Q.deltaRotation);this.processRotateMuxOutput(J);break;case"cursor":break;case"none":break}}processPanMuxOutput(Q){if(Q.allowPassThrough)this._cameraRig.panByViewPort(Q.delta)}processZoomMuxOutput(Q){if(Q.allowPassThrough)this._cameraRig.zoomByAt(Q.delta,Q.anchorPoint)}processRotateMuxOutput(Q){if(Q.allowPassThrough)this._cameraRig.rotateBy(Q.delta)}get publisher(){return this._publisher}get cameraMux(){return this._cameraMux}set cameraMux(Q){this._cameraMux=Q}}class Kq{_context;_reversedContext;_canvasProxy;_kmtParser;_touchParser;_alignCoordinateSystem=!0;_fullScreen=!1;cameraRig;_cameraMux;boardInputPublisher;_observableInputTracker;_touchInputTracker;_inputOrchestrator;_cachedCanvasWidth=0;_cachedCanvasHeight=0;_cachedCanvasPixelRatio=1;lastUpdateTime=0;_canvasElement;constructor(Q,q=!1){let $=new $Q,J=50000;$.boundaries={min:{x:-50000,y:-50000},max:{x:50000,y:50000}},this.bindFunctions(),this._canvasProxy=new eQ(Q),this._canvasProxy.subscribe((G)=>{this.syncViewPortDimensions(G),this.syncCameraZoomLevel(G)}),this.cameraRig=new TQ({limitEntireViewPort:!0,restrictRelativeXTranslation:!1,restrictRelativeYTranslation:!1,restrictXTranslation:!1,restrictYTranslation:!1,restrictZoom:!1,clampTranslation:!0,clampZoom:!0},$),this._cameraMux=uq(),this.boardInputPublisher=new zQ,this._observableInputTracker=new WQ(this._canvasProxy),this._touchInputTracker=new Qq(this._canvasProxy);let U=Jq(this._observableInputTracker),K=eq(this._touchInputTracker);if(this._inputOrchestrator=new Uq(this._cameraMux,this.cameraRig,this.boardInputPublisher),this._kmtParser=new gQ(U,this._inputOrchestrator,Q),this._touchParser=new xQ(K,this._inputOrchestrator,Q),Q!=null)console.log("canvas exists on creation of board"),this.attach(Q,q)}syncViewPortDimensions(Q){this.camera.viewPortHeight=Q.height,this.camera.viewPortWidth=Q.width}attach(Q,q=!1){this._canvasElement=Q;let $=Q.getContext("2d",{willReadFrequently:q});if($==null){console.error("new canvas context is null");return}if(this._kmtParser.attach(Q),this._touchParser.attach(Q),this._canvasProxy.attach(Q),this.limitEntireViewPort)this.syncCameraZoomLevel(this._canvasProxy.dimensions);this._context=$,this._reversedContext=Wq(this._context)}disableEventListeners(){this._kmtParser.tearDown(),this._touchParser.tearDown()}enableEventListeners(){this._kmtParser.setUp(),this._touchParser.setUp()}get inputOrchestrator(){return this._inputOrchestrator}tearDown(){this._kmtParser.tearDown(),this._touchParser.tearDown(),this._canvasProxy.tearDown()}bindFunctions(){this.step=this.step.bind(this)}get width(){return this._canvasProxy.width}get height(){return this._canvasProxy.height}set alignCoordinateSystem(Q){this._alignCoordinateSystem=Q,this._observableInputTracker.alignCoordinateSystem=Q,this._touchInputTracker.alignCoordinateSystem=Q}get alignCoordinateSystem(){return this._alignCoordinateSystem}get fullScreen(){return this._fullScreen}set fullScreen(Q){if(this._fullScreen=Q,this._fullScreen)this._canvasProxy.setWidth(window.innerWidth),this._canvasProxy.setHeight(window.innerHeight)}get context(){if(!this._alignCoordinateSystem)return this._reversedContext;return this._context}set limitEntireViewPort(Q){if(this.cameraRig.config.limitEntireViewPort=Q,this._canvasProxy.detached)return;if(Q)this.syncCameraZoomLevel(this._canvasProxy.dimensions)}get limitEntireViewPort(){return this.cameraRig.config.limitEntireViewPort}set kmtParser(Q){if(this._kmtParser.tearDown(),Q.tearDown(),this._canvasElement!=null)Q.attach(this._canvasElement);Q.setUp(),this._kmtParser=Q}get kmtParser(){return this._kmtParser}set touchParser(Q){if(this._touchParser.tearDown(),Q.tearDown(),this._canvasElement!=null)Q.attach(this._canvasElement);Q.setUp(),this._touchParser=Q}get touchParser(){return this._touchParser}get camera(){return this.cameraRig.camera}set camera(Q){if(!this._canvasProxy.detached)Q.viewPortHeight=this._canvasProxy.height/window.devicePixelRatio,Q.viewPortWidth=this._canvasProxy.width/window.devicePixelRatio;this.cameraRig.camera=Q}get cameraMux(){return this._cameraMux}set cameraMux(Q){this._cameraMux=Q,this._inputOrchestrator.cameraMux=Q}step(Q){if(this._canvasProxy.detached||this._context==null)return;this.cameraRig.update();let q=Q-this.lastUpdateTime;if(this.lastUpdateTime=Q,q=q/1000,this._context.reset(),this._context.clearRect(0,0,this._canvasProxy.width*window.devicePixelRatio,this._canvasProxy.height*window.devicePixelRatio),this._cachedCanvasPixelRatio!==window.devicePixelRatio)this._cachedCanvasPixelRatio=window.devicePixelRatio,this._canvasProxy.setCanvasHeight(this._canvasProxy.height),this._canvasProxy.setCanvasWidth(this._canvasProxy.width);if(this._cachedCanvasHeight!==this._canvasProxy.height)this._cachedCanvasHeight=this._canvasProxy.height,this._canvasProxy.setCanvasHeight(this._canvasProxy.height);if(this._cachedCanvasWidth!==this._canvasProxy.width)this._cachedCanvasWidth=this._canvasProxy.width,this._canvasProxy.setCanvasWidth(this._canvasProxy.width);let $=this.camera.getTransform(window.devicePixelRatio,this._alignCoordinateSystem);this._context.setTransform($.a,$.b,$.c,$.d,$.e,$.f)}convertWindowPoint2WorldCoord(Q){let q=this._canvasProxy.dimensions,$={x:q.position.x+q.width/2,y:q.position.y+q.height/2},J=v$.subVector(Q,$);if(!this._alignCoordinateSystem)J.y=-J.y;return this.camera.convertFromViewPort2WorldSpace(J)}on(Q,q){return this.camera.on(Q,q)}onInput(Q,q){return this.boardInputPublisher.on(Q,q)}get maxHalfTransHeight(){return _q(this.camera.boundaries)}get maxHalfTransWidth(){return Fq(this.camera.boundaries)}syncCameraZoomLevel(Q){if(this.limitEntireViewPort){let q=Oq(this.camera.boundaries,Q.width,Q.height,this.camera.rotation);if(q!=null&&DQ(this.camera.zoomBoundaries,q))this.camera.setMinZoomLevel(q)}}setMaxTransWidthWithFixedMinBoundary(Q){let q=this.camera.boundaries,$=q==null?void 0:q.min,J=$==null?void 0:$.x;if(J==null)this.camera.setHorizontalBoundaries(-Q,Q);else this.camera.setHorizontalBoundaries(J,J+Q*2);if(this.limitEntireViewPort){let U=rQ(this.camera.boundaries,this.camera.viewPortWidth,this.camera.viewPortHeight,this.camera.rotation);if(DQ(this.camera.zoomBoundaries,U))this.camera.setMinZoomLevel(U)}}setMaxTransWidthWithFixedMaxBoundary(Q){let q=this.camera.boundaries,$=q==null?void 0:q.max,J=$==null?void 0:$.x;if(J==null)this.camera.setHorizontalBoundaries(-Q,Q);else this.camera.setHorizontalBoundaries(J-Q*2,J);if(this.limitEntireViewPort){let U=rQ(this.camera.boundaries,this.camera.viewPortWidth,this.camera.viewPortHeight,this.camera.rotation);if(DQ(this.camera.zoomBoundaries,U))this.camera.setMinZoomLevel(U)}}get restrictRelativeXTranslation(){return this.cameraRig.config.restrictRelativeXTranslation}get restrictRelativeYTranslation(){return this.cameraRig.config.restrictRelativeYTranslation}get restrictXTranslation(){return this.cameraRig.config.restrictXTranslation}get restrictYTranslation(){return this.cameraRig.config.restrictYTranslation}set restrictRelativeXTranslation(Q){this.cameraRig.config.restrictRelativeXTranslation=Q}set restrictRelativeYTranslation(Q){this.cameraRig.configure({restrictRelativeYTranslation:Q})}set restrictXTranslation(Q){this.cameraRig.configure({restrictXTranslation:Q})}set restrictYTranslation(Q){this.cameraRig.configure({restrictYTranslation:Q})}get restrictZoom(){return this.cameraRig.config.restrictZoom}set restrictZoom(Q){this.cameraRig.configure({restrictZoom:Q})}get restrictRotation(){return this.cameraRig.config.restrictRotation}set restrictRotation(Q){this.cameraRig.configure({restrictRotation:Q})}get clampTranslation(){return this.cameraRig.config.clampTranslation}set clampTranslation(Q){this.cameraRig.configure({clampTranslation:Q})}get clampZoom(){return this.cameraRig.config.clampZoom}set clampZoom(Q){this.cameraRig.configure({clampZoom:Q})}get clampRotation(){return this.cameraRig.config.clampRotation}set clampRotation(Q){this.cameraRig.configure({clampRotation:Q})}getCameraRig(){return this.cameraRig}setInputMode(Q){this._observableInputTracker.setMode(Q)}onCanvasDimensionChange(Q){return this._canvasProxy.subscribe(Q)}get canvasDimensions(){return this._canvasProxy.dimensions}}import{PointCal as p$}from"@ue-too/math";class d${_cameraMux;_state="idle";_speed=100;_horizontalDirection="none";_verticalDirection="none";constructor(Q){this._cameraMux=Q}toggleOff(){this._state="idle"}toggleOn(){this._state="moving"}setDirection(Q,q){this._horizontalDirection=Q,this._verticalDirection=q}update(Q){if(this._state==="idle")return;let q={x:this._horizontalDirection==="left"?-1:this._horizontalDirection==="right"?1:0,y:this._verticalDirection==="up"?-1:this._verticalDirection==="down"?1:0},$=this._speed*Q,J=p$.multiplyVectorByScalar(q,$);this._cameraMux.notifyPanInput(J)}}export{PQ as zoomLevelWithinLimits,DQ as zoomLevelBoundariesShouldUpdate,CQ as withinBoundaries,t as translationWidthOf,QQ as translationHeightOf,B9 as transformationMatrixFromCamera,hQ as rotationWithinLimits,Z9 as rotationWithinBoundary,Wq as reverseYAxis,Z$ as restrictZoomToHandler,T$ as restrictZoomByHandler,L$ as restrictRotateToHandler,C$ as restrictRotateByHandler,S$ as restrictPanToHandler,w$ as restrictPanByHandler,S9 as rad2deg,F9 as pointIsInViewPort,J7 as pointConversion,S as normalizeAngleZero2TwoPI,a as multiplyMatrix,rQ as minZoomLevelBaseOnWidth,b7 as minZoomLevelBaseOnHeight,Oq as minZoomLevelBaseOnDimensions,z9 as isValidZoomLevelLimits,O9 as isValidBoundaries,B$ as invertYAxisForDrawImageWith9Args,Y$ as invertFromWorldSpace,Fq as halfTranslationWidthOf,_q as halfTranslationHeightOf,M as getTrueRect,I7 as drawRulerLegacy,S7 as drawRuler,O7 as drawReferenceCircle,H7 as drawPositionText,k7 as drawGrid,B7 as drawCrossHair,A7 as drawBoundingBox,W7 as drawAxis,T7 as drawArrow,T9 as deg2rad,o$ as decomposeTRSSVD,Eq as decomposeTRS,Yq as decomposeCameraMatrix,eq as createTouchInputStateMachine,a$ as createTRSMatrix,y8 as createKmtInputStateMachineWithCanvas,Jq as createKmtInputStateMachine,d as createHandlerChain,vq as createDefaultZoomToOnlyHandler,H$ as createDefaultZoomControlStates,Cq as createDefaultZoomControlStateMachine,pq as createDefaultZoomByOnlyHandler,cq as createDefaultRotateToHandler,D$ as createDefaultRotateControlStates,gq as createDefaultRotateControlStateMachine,sq as createDefaultRotateByHandler,s7 as createDefaultRawUserInputPublisher,dq as createDefaultPanToHandler,k$ as createDefaultPanControlStates,Sq as createDefaultPanControlStateMachine,mq as createDefaultPanByHandler,e6 as createDefaultCameraRig,i7 as createDefaultCameraMux,uq as createCameraMuxWithAnimationAndLock,i$ as createCameraMatrix,R6 as convertUserInputDeltaToCameraDelta,Bq as convertFromWindow2ViewPortWithCanvasOperator,lq as convertDeltaToComplyWithRestriction,_9 as convertDeltaInWorldToViewPortSpace,bQ as convertDeltaInViewPortToWorldSpace,A9 as convert2WorldSpaceWithTransformationMatrix,NQ as convert2WorldSpaceWRT,l as convert2WorldSpaceAnchorAtCenter,N9 as convert2WorldSpace,HQ as convert2ViewPortSpaceAnchorAtCenter,z$ as clampZoomToHandler,GQ as clampZoomLevel,M$ as clampZoomByHandler,R$ as clampToHandler,YQ as clampRotation,f$ as clampRotateToHandler,b$ as clampRotateByHandler,LQ as clampPointEntireViewPort,e as clampPoint,y$ as clampByHandler,V9 as cameraPositionToGet,Hq as calculateTickValues,VQ as calculateOrderOfMagnitude,fQ as boundariesFullyDefined,XQ as angleSpan,Rq as ZoomTransitionState,yq as ZoomLockedOnObjectState,bq as ZoomControlStateMachine,wq as ZoomAcceptingUserInputState,g$ as WorkerRelayCanvas,xQ as VanillaTouchEventParser,gQ as VanillaKMTEventParser,Zq as TransitionState,Qq as TouchInputTracker,mQ as TEXT_MAJOR_TICK_OFFSET,kq as TEXT_MAJOR_TICK_FONT_SIZE,lQ as TEXT_HALF_TICK_OFFSET,Iq as TEXT_HALF_TICK_FONT_SIZE,i as SynchronousObservable,h$ as SvgProxy,uQ as SvgPositionDimensionPublisher,Pq as RotationTransitionState,hq as RotationLockedOnObjectState,Lq as RotationAcceptingUserInputState,fq as RotateControlStateMachine,Dq as Relay,q$ as ReadyToPanViaSpaceBarState,J$ as ReadyToPanViaScrollWheelState,A$ as RawUserInputPublisherWithWebWorkerRelay,zQ as RawUserInputPublisher,aq as PendingState,K$ as PanViaScrollWheelState,U$ as PanState,zq as PanControlStateMachine,WQ as ObservableInputTracker,pQ as MINOR_TICK_LENGTH,BQ as MAJOR_TICK_LENGTH,Tq as LockedOnObjectState,u$ as KmtInputStateMachineWebWorkerProxy,Q$ as KmtIdleState,JQ as KmtEmptyState,Uq as InputOrchestrator,$$ as InitialPanState,oq as InProgressState,iq as IdleState,dQ as HALF_TICK_LENGTH,d$ as EdgeAutoCameraInput,tQ as DummyKmtInputContext,nq as DummyCanvas,$q as DisabledState,TQ as DefaultCameraRig,$Q as DefaultBoardCamera,N$ as DEFAULT_BOARD_CAMERA_ZOOM_BOUNDARIES,E$ as DEFAULT_BOARD_CAMERA_VIEWPORT_WIDTH,j$ as DEFAULT_BOARD_CAMERA_VIEWPORT_HEIGHT,_$ as DEFAULT_BOARD_CAMERA_ROTATION_BOUNDARIES,F$ as DEFAULT_BOARD_CAMERA_BOUNDARIES,rq as CursorStyle,eQ as CanvasProxy,vQ as CanvasPositionDimensionPublisher,P$ as CanvasCacheInWebWorker,RQ as CameraUpdatePublisher,xq as CameraMuxWithAnimationAndLock,Kq as Board,f as AsyncObservable,Mq as AcceptingUserInputState};
2
2
 
3
3
  //# debugId=AA86369A6BE56E1864756E2164756E21
4
+
5
+ //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/camera/default-camera.ts", "../src/utils/observable.ts", "../src/camera/update-publisher.ts", "../src/camera/utils/coordinate-conversion.ts", "../src/camera/utils/matrix.ts", "../src/utils/coordinate-conversions/canvas-viewport.ts", "../src/utils/coordinate-conversions/viewport-world.ts", "../src/camera/utils/position.ts", "../src/camera/utils/zoom.ts", "../src/camera/utils/rotation.ts", "../src/camera/base.ts", "../src/input-interpretation/raw-input-parser/vanilla-kmt-event-parser.ts", "../src/input-interpretation/raw-input-parser/vanilla-touch-event-parser.ts", "../src/utils/coordinate-conversions/window-canvas.ts", "../src/utils/coorindate-conversion.ts", "../src/utils/ruler.ts", "../src/utils/handler-pipeline.ts", "../src/utils/canvas-position-dimension.ts", "../src/utils/drawing-utils.ts", "../src/utils/drawing.ts", "../src/utils/zoomlevel-adjustment.ts", "../src/boardify/index.ts", "../src/input-interpretation/raw-input-publisher/raw-input-publisher.ts", "../src/camera/camera-mux/relay.ts", "../src/camera/camera-mux/animation-and-lock/pan-control-state-machine.ts", "../src/camera/camera-mux/animation-and-lock/zoom-control-state-machine.ts", "../src/camera/camera-mux/animation-and-lock/rotation-control-state-machine.ts", "../src/camera/camera-mux/animation-and-lock/animation-and-lock.ts", "../src/camera/camera-rig/zoom-handler.ts", "../src/camera/camera-rig/pan-handler.ts", "../src/camera/camera-rig/rotation-handler.ts", "../src/camera/camera-rig/camera-rig.ts", "../src/input-interpretation/input-state-machine/kmt-input-context.ts", "../src/input-interpretation/input-state-machine/touch-input-context.ts", "../src/input-interpretation/input-state-machine/touch-input-state-machine.ts", "../src/input-interpretation/input-state-machine/kmt-input-state-machine.ts", "../src/input-interpretation/input-orchestrator.ts", "../src/camera/camera-edge-auto-input.ts"],
3
+ "sources": [
4
+ "default-camera.ts",
5
+ "observable.ts",
6
+ "update-publisher.ts",
7
+ "coordinate-conversion.ts",
8
+ "matrix.ts",
9
+ "canvas-viewport.ts",
10
+ "viewport-world.ts",
11
+ "position.ts",
12
+ "zoom.ts",
13
+ "rotation.ts",
14
+ "base.ts",
15
+ "vanilla-kmt-event-parser.ts",
16
+ "vanilla-touch-event-parser.ts",
17
+ "window-canvas.ts",
18
+ "coorindate-conversion.ts",
19
+ "ruler.ts",
20
+ "handler-pipeline.ts",
21
+ "canvas-position-dimension.ts",
22
+ "drawing-utils.ts",
23
+ "drawing.ts",
24
+ "zoomlevel-adjustment.ts",
25
+ "index.ts",
26
+ "raw-input-publisher.ts",
27
+ "relay.ts",
28
+ "pan-control-state-machine.ts",
29
+ "zoom-control-state-machine.ts",
30
+ "rotation-control-state-machine.ts",
31
+ "animation-and-lock.ts",
32
+ "zoom-handler.ts",
33
+ "pan-handler.ts",
34
+ "rotation-handler.ts",
35
+ "camera-rig.ts",
36
+ "kmt-input-context.ts",
37
+ "touch-input-context.ts",
38
+ "touch-input-state-machine.ts",
39
+ "kmt-input-state-machine.ts",
40
+ "input-orchestrator.ts",
41
+ "camera-edge-auto-input.ts"
42
+ ],
4
43
  "sourcesContent": [
5
44
  "import { Point, PointCal } from '@ue-too/math';\nimport { Boundaries } from './utils/position';\nimport { TransformationMatrix } from './utils/matrix';\nimport { CameraUpdatePublisher, UnSubscribe } from './update-publisher';\nimport { ZoomLevelLimits } from './utils/zoom';\nimport { RotationLimits } from './utils/rotation';\nimport { convert2WorldSpaceAnchorAtCenter, convert2ViewPortSpaceAnchorAtCenter } from './utils/coordinate-conversion';\nimport { CameraEventMap, CameraState } from './update-publisher';\nimport { ObservableBoardCamera } from './interface';\nimport BaseCamera from './base';\nimport { SubscriptionOptions } from '../utils/observable';\n\n/** Default viewport width in CSS pixels */\nexport const DEFAULT_BOARD_CAMERA_VIEWPORT_WIDTH = 1000;\n\n/** Default viewport height in CSS pixels */\nexport const DEFAULT_BOARD_CAMERA_VIEWPORT_HEIGHT = 1000;\n\n/** Default zoom level constraints (0.1x to 10x) */\nexport const DEFAULT_BOARD_CAMERA_ZOOM_BOUNDARIES: ZoomLevelLimits = {min: 0.1, max: 10};\n\n/** Default position boundaries (±10000 on both axes) */\nexport const DEFAULT_BOARD_CAMERA_BOUNDARIES: Boundaries = {min: {x: -10000, y: -10000}, max: {x: 10000, y: 10000}};\n\n/** Default rotation boundaries (unrestricted) */\nexport const DEFAULT_BOARD_CAMERA_ROTATION_BOUNDARIES: RotationLimits | undefined = undefined;\n\n/**\n * Observable camera implementation that extends {@link BaseCamera} with event notification.\n * This is the recommended camera class for most applications.\n *\n * @remarks\n * DefaultBoardCamera wraps {@link BaseCamera} and adds an event system via {@link CameraUpdatePublisher}.\n * All camera state changes (pan, zoom, rotate) trigger corresponding events that observers can subscribe to.\n *\n * Use this class when you need to:\n * - React to camera changes in your UI or game logic\n * - Synchronize multiple systems with camera state\n * - Implement camera-dependent features (minimap, LOD, culling)\n *\n * For a non-observable camera without event overhead, use {@link BaseCamera} directly.\n *\n * @example\n * ```typescript\n * const camera = new DefaultBoardCamera(1920, 1080);\n *\n * // Subscribe to camera events\n * camera.on('zoom', (event, state) => {\n * console.log(`Zoomed by ${event.deltaZoomAmount}`);\n * console.log(`New zoom level: ${state.zoomLevel}`);\n * });\n *\n * camera.on('pan', (event, state) => {\n * console.log(`Panned by (${event.diff.x}, ${event.diff.y})`);\n * });\n *\n * // Camera updates trigger events\n * camera.setZoomLevel(2.0);\n * camera.setPosition({ x: 100, y: 200 });\n * ```\n *\n * @category Camera\n * @see {@link BaseCamera} for non-observable camera\n * @see {@link ObservableBoardCamera} for the interface definition\n */\nexport default class DefaultBoardCamera implements ObservableBoardCamera {\n\n private _baseCamera: BaseCamera;\n private _observer: CameraUpdatePublisher;\n /**\n * Creates a new observable camera with event notification capabilities.\n *\n * @param viewPortWidth - Width of the viewport in CSS pixels (default: 1000)\n * @param viewPortHeight - Height of the viewport in CSS pixels (default: 1000)\n * @param position - Initial camera position in world coordinates (default: {x: 0, y: 0})\n * @param rotation - Initial rotation in radians (default: 0)\n * @param zoomLevel - Initial zoom level (default: 1.0)\n * @param boundaries - Position constraints (default: ±10000 on both axes)\n * @param zoomLevelBoundaries - Zoom constraints (default: 0.1 to 10)\n * @param rotationBoundaries - Optional rotation constraints (default: unrestricted)\n *\n * @example\n * ```typescript\n * // Camera with default settings\n * const camera1 = new DefaultBoardCamera();\n *\n * // Camera with custom viewport\n * const camera2 = new DefaultBoardCamera(1920, 1080);\n *\n * // Camera with all options\n * const camera3 = new DefaultBoardCamera(\n * 1920, 1080,\n * { x: 0, y: 0 },\n * 0,\n * 1.0,\n * { min: { x: -5000, y: -5000 }, max: { x: 5000, y: 5000 } },\n * { min: 0.5, max: 4 },\n * { start: 0, end: Math.PI * 2 }\n * );\n * ```\n */\n constructor(viewPortWidth: number = DEFAULT_BOARD_CAMERA_VIEWPORT_WIDTH, viewPortHeight: number = DEFAULT_BOARD_CAMERA_VIEWPORT_HEIGHT, position: Point = {x: 0, y: 0}, rotation: number = 0, zoomLevel: number = 1, boundaries: Boundaries = DEFAULT_BOARD_CAMERA_BOUNDARIES, zoomLevelBoundaries: ZoomLevelLimits = DEFAULT_BOARD_CAMERA_ZOOM_BOUNDARIES, rotationBoundaries: RotationLimits | undefined = DEFAULT_BOARD_CAMERA_ROTATION_BOUNDARIES){\n this._baseCamera = new BaseCamera(viewPortWidth, viewPortHeight, position, rotation, zoomLevel, boundaries, zoomLevelBoundaries, rotationBoundaries);\n this._observer = new CameraUpdatePublisher();\n }\n\n /**\n * @description The boundaries of the camera in the world coordinate system.\n * \n * @category Camera\n */\n get boundaries(): Boundaries | undefined{\n return this._baseCamera.boundaries;\n }\n\n set boundaries(boundaries: Boundaries | undefined){\n this._baseCamera.boundaries = boundaries;\n }\n\n /**\n * @description The width of the viewport. (The width of the canvas in css pixels)\n * \n * @category Camera\n */\n get viewPortWidth(): number{\n return this._baseCamera.viewPortWidth;\n }\n\n set viewPortWidth(width: number){\n this._baseCamera.viewPortWidth = width;\n }\n\n /**\n * @description The height of the viewport. (The height of the canvas in css pixels)\n * \n * @category Camera\n */\n get viewPortHeight(): number{\n return this._baseCamera.viewPortHeight;\n }\n\n set viewPortHeight(height: number){\n this._baseCamera.viewPortHeight = height;\n }\n\n /**\n * @description The position of the camera in the world coordinate system.\n * \n * @category Camera\n */\n get position(): Point{\n return this._baseCamera.position;\n }\n\n /**\n * Sets the camera position and notifies observers if successful.\n *\n * @param destination - Target position in world coordinates\n * @returns True if position was updated, false if rejected by boundaries or negligible change\n *\n * @remarks\n * If the position changes, a 'pan' event is triggered with the position delta and new camera state.\n * All 'pan' and 'all' event subscribers will be notified.\n *\n * @example\n * ```typescript\n * camera.on('pan', (event, state) => {\n * console.log(`Camera moved by (${event.diff.x}, ${event.diff.y})`);\n * });\n *\n * camera.setPosition({ x: 100, y: 200 }); // Triggers pan event\n * ```\n */\n setPosition(destination: Point){\n const currentPosition = {...this._baseCamera.position};\n if(!this._baseCamera.setPosition(destination)){\n return false;\n }\n this._observer.notifyPan({diff: PointCal.subVector(destination, currentPosition)}, {position: this._baseCamera.position, rotation: this._baseCamera.rotation, zoomLevel: this._baseCamera.zoomLevel});\n return true;\n }\n\n /**\n * @description The zoom level of the camera.\n * \n * @category Camera\n */\n get zoomLevel(): number{\n return this._baseCamera.zoomLevel;\n }\n\n /**\n * @description The boundaries of the zoom level of the camera.\n * \n * @category Camera\n */\n get zoomBoundaries(): ZoomLevelLimits | undefined{\n return this._baseCamera.zoomBoundaries;\n }\n\n set zoomBoundaries(zoomBoundaries: ZoomLevelLimits | undefined){\n this._baseCamera.zoomBoundaries = zoomBoundaries;\n }\n\n setMaxZoomLevel(maxZoomLevel: number){\n const currentZoomLevel = this._baseCamera.zoomLevel;\n if(!this._baseCamera.setMaxZoomLevel(maxZoomLevel)){\n return false;\n }\n this._observer.notifyZoom({deltaZoomAmount: maxZoomLevel - currentZoomLevel}, {position: this._baseCamera.position, rotation: this._baseCamera.rotation, zoomLevel: this._baseCamera.zoomLevel});\n return true;\n }\n\n setMinZoomLevel(minZoomLevel: number){\n if(!this._baseCamera.setMinZoomLevel(minZoomLevel)){\n return false;\n }\n return true;\n }\n\n /**\n * Sets the camera zoom level and notifies observers if successful.\n *\n * @param zoomLevel - Target zoom level (1.0 = 100%, 2.0 = 200%, etc.)\n * @returns True if zoom was updated, false if outside boundaries or already at limit\n *\n * @remarks\n * If the zoom changes, a 'zoom' event is triggered with the zoom delta and new camera state.\n * All 'zoom' and 'all' event subscribers will be notified.\n *\n * @example\n * ```typescript\n * camera.on('zoom', (event, state) => {\n * console.log(`Zoom changed by ${event.deltaZoomAmount}`);\n * console.log(`New zoom: ${state.zoomLevel}`);\n * });\n *\n * camera.setZoomLevel(2.0); // Triggers zoom event\n * ```\n */\n setZoomLevel(zoomLevel: number){\n const currentZoomLevel = this._baseCamera.zoomLevel;\n if(!this._baseCamera.setZoomLevel(zoomLevel)){\n return false;\n }\n this._observer.notifyZoom({deltaZoomAmount: this._baseCamera.zoomLevel - currentZoomLevel}, {position: this._baseCamera.position, rotation: this._baseCamera.rotation, zoomLevel: this._baseCamera.zoomLevel});\n return true;\n }\n\n /**\n * Gets the current camera rotation in radians.\n *\n * @returns Current rotation angle (0 to 2π)\n */\n get rotation(): number{\n return this._baseCamera.rotation;\n }\n\n /**\n * @description The boundaries of the rotation of the camera.\n * \n * @category Camera\n */\n get rotationBoundaries(): RotationLimits | undefined{\n return this._baseCamera.rotationBoundaries;\n }\n\n set rotationBoundaries(rotationBoundaries: RotationLimits | undefined){\n this._baseCamera.rotationBoundaries = rotationBoundaries;\n }\n\n /**\n * @description The order of the transformation is as follows:\n * 1. Scale (scale the context using the device pixel ratio)\n * 2. Translation (move the origin of the context to the center of the canvas)\n * 3. Rotation (rotate the context negatively the rotation of the camera)\n * 4. Zoom (scale the context using the zoom level of the camera)\n * 5. Translation (move the origin of the context to the position of the camera in the context coordinate system)\n * \n * @param devicePixelRatio The device pixel ratio of the canvas\n * @param alignCoorindate Whether to align the coordinate system to the camera's position\n * @returns The transformation matrix\n */\n getTransform(devicePixelRatio: number = 1, alignCoorindate: boolean = true): TransformationMatrix {\n return this._baseCamera.getTransform(devicePixelRatio, alignCoorindate);\n }\n\n /**\n * Sets the camera rotation and notifies observers if successful.\n *\n * @param rotation - Target rotation in radians\n * @returns True if rotation was updated, false if outside boundaries or already at limit\n *\n * @remarks\n * If the rotation changes, a 'rotate' event is triggered with the rotation delta and new camera state.\n * All 'rotate' and 'all' event subscribers will be notified.\n * Rotation is automatically normalized to 0-2π range.\n *\n * @example\n * ```typescript\n * camera.on('rotate', (event, state) => {\n * console.log(`Camera rotated by ${event.deltaRotation} radians`);\n * });\n *\n * camera.setRotation(Math.PI / 4); // Triggers rotate event\n * ```\n */\n setRotation(rotation: number){\n const currentRotation = this._baseCamera.rotation;\n if(!this._baseCamera.setRotation(rotation)){\n return false;\n }\n this._observer.notifyRotate({deltaRotation: rotation - currentRotation}, {position: this._baseCamera.position, rotation: this._baseCamera.rotation, zoomLevel: this._baseCamera.zoomLevel});\n return true;\n }\n\n /**\n * @description The origin of the camera in the window coordinate system.\n * @deprecated\n * \n * @param centerInWindow The center of the camera in the window coordinate system.\n * @returns The origin of the camera in the window coordinate system.\n */\n getCameraOriginInWindow(centerInWindow: Point): Point{\n return centerInWindow;\n }\n\n /**\n * @description Converts a point from the viewport coordinate system to the world coordinate system.\n * \n * @param point The point in the viewport coordinate system.\n * @returns The point in the world coordinate system.\n */\n convertFromViewPort2WorldSpace(point: Point): Point{\n return convert2WorldSpaceAnchorAtCenter(point, this._baseCamera.position, this._baseCamera.zoomLevel, this._baseCamera.rotation);\n }\n\n /**\n * @description Converts a point from the world coordinate system to the viewport coordinate system.\n * \n * @param point The point in the world coordinate system.\n * @returns The point in the viewport coordinate system.\n */\n convertFromWorld2ViewPort(point: Point): Point{\n return convert2ViewPortSpaceAnchorAtCenter(point, this._baseCamera.position, this._baseCamera.zoomLevel, this._baseCamera.rotation);\n }\n\n /**\n * @description Inverts a point from the world coordinate system to the viewport coordinate system.\n * \n * @param point The point in the world coordinate system.\n * @returns The point in the viewport coordinate system.\n */\n invertFromWorldSpace2ViewPort(point: Point): Point{\n let cameraFrameCenter = {x: this._baseCamera.viewPortWidth / 2, y: this._baseCamera.viewPortHeight / 2};\n let delta2Point = PointCal.subVector(point, this._baseCamera.position);\n delta2Point = PointCal.rotatePoint(delta2Point, -this._baseCamera.rotation);\n delta2Point = PointCal.multiplyVectorByScalar(delta2Point, this._baseCamera.zoomLevel);\n return PointCal.addVector(cameraFrameCenter, delta2Point);\n }\n\n setHorizontalBoundaries(min: number, max: number){\n if (min > max){\n let temp = max;\n max = min;\n min = temp;\n }\n if(this._baseCamera.boundaries == undefined){\n this._baseCamera.boundaries = {min: undefined, max: undefined};\n }\n if(this._baseCamera.boundaries.min == undefined){\n this._baseCamera.boundaries.min = {x: undefined, y: undefined};\n }\n if(this._baseCamera.boundaries.max == undefined){\n this._baseCamera.boundaries.max = {x: undefined, y: undefined};\n }\n this._baseCamera.boundaries.min.x = min;\n this._baseCamera.boundaries.max.x = max;\n //NOTE leave for future optimization when setting the boundaries if the camera lies outside the boundaries clamp the position of the camera\n // if(!this.withinBoundaries(this.position)){\n // this.position = this.clampPoint(this.position);\n // }\n }\n\n setVerticalBoundaries(min: number, max: number){\n if (min > max){\n let temp = max;\n max = min;\n min = temp;\n }\n if(this._baseCamera.boundaries == undefined){\n this._baseCamera.boundaries = {min: undefined, max: undefined};\n }\n if(this._baseCamera.boundaries.min == undefined){\n this._baseCamera.boundaries.min = {x: undefined, y: undefined};\n }\n if(this._baseCamera.boundaries.max == undefined){\n this._baseCamera.boundaries.max = {x: undefined, y: undefined};\n }\n this._baseCamera.boundaries.min.y = min;\n this._baseCamera.boundaries.max.y = max;\n }\n\n /**\n * Subscribes to camera events with optional AbortController for cancellation.\n *\n * @typeParam K - The event type key from CameraEventMap\n * @param eventName - Event type to listen for: 'pan', 'zoom', 'rotate', or 'all'\n * @param callback - Function called when event occurs, receives event data and camera state\n * @param options - Optional subscription configuration including AbortController signal\n * @returns Function to unsubscribe from this event\n *\n * @remarks\n * Available events:\n * - 'pan': Triggered when camera position changes\n * - 'zoom': Triggered when zoom level changes\n * - 'rotate': Triggered when rotation changes\n * - 'all': Triggered for any camera change (pan, zoom, or rotate)\n *\n * Use the AbortController pattern to manage multiple subscriptions:\n *\n * @example\n * ```typescript\n * // Basic subscription\n * const unsubscribe = camera.on('pan', (event, state) => {\n * console.log(`Panned by (${event.diff.x}, ${event.diff.y})`);\n * console.log(`New position: (${state.position.x}, ${state.position.y})`);\n * });\n *\n * // Later: unsubscribe\n * unsubscribe();\n *\n * // Subscribe to all events\n * camera.on('all', (event, state) => {\n * if (event.type === 'pan') {\n * console.log('Pan event:', event.diff);\n * } else if (event.type === 'zoom') {\n * console.log('Zoom event:', event.deltaZoomAmount);\n * } else if (event.type === 'rotate') {\n * console.log('Rotate event:', event.deltaRotation);\n * }\n * });\n *\n * // Using AbortController for batch unsubscribe\n * const controller = new AbortController();\n * camera.on('pan', handlePan, { signal: controller.signal });\n * camera.on('zoom', handleZoom, { signal: controller.signal });\n * camera.on('rotate', handleRotate, { signal: controller.signal });\n *\n * // Unsubscribe all at once\n * controller.abort();\n * ```\n */\n on<K extends keyof CameraEventMap>(eventName: K, callback: (event: CameraEventMap[K], cameraState: CameraState)=>void, options?: SubscriptionOptions): UnSubscribe {\n return this._observer.on(eventName, callback, options);\n }\n\n getTRS(devicePixelRatio: number = 1, alignCoordinateSystem: boolean = true): {scale: {x: number, y: number}, rotation: number, translation: {x: number, y: number}, cached: boolean} {\n return this._baseCamera.getTRS(devicePixelRatio, alignCoordinateSystem);\n }\n\n setUsingTransformationMatrix(transformationMatrix: TransformationMatrix, devicePixelRatio: number = 1){\n this._baseCamera.setUsingTransformationMatrix(transformationMatrix, devicePixelRatio);\n }\n\n viewPortInWorldSpace(alignCoordinate: boolean = true): {top: {left: Point, right: Point}, bottom: {left: Point, right: Point}}{\n return this._baseCamera.viewPortInWorldSpace(alignCoordinate);\n }\n\n viewPortAABB(alignCoordinate: boolean = true): {min: Point, max: Point}{\n return this._baseCamera.viewPortAABB(alignCoordinate);\n }\n}\n",
6
45
  "/**\n * Type definition for an observer callback function.\n *\n * @typeParam T - Tuple type of arguments passed to the observer\n *\n * @remarks\n * Observers are callbacks that get notified when an Observable emits data.\n * The generic type T is a tuple representing the arguments passed to the callback.\n *\n * @example\n * ```typescript\n * // Observer that receives a single string\n * const stringObserver: Observer<[string]> = (message) => {\n * console.log(message);\n * };\n *\n * // Observer that receives multiple arguments\n * const multiObserver: Observer<[number, string, boolean]> = (num, str, flag) => {\n * console.log(num, str, flag);\n * };\n * ```\n *\n * @category Observable Pattern\n */\nexport type Observer<T extends any[]> = (...data: T) => void;\n\n/**\n * Options for subscribing to an Observable.\n *\n * @property signal - Optional AbortSignal for automatic unsubscription\n *\n * @remarks\n * Subscription options allow for automatic cleanup of subscriptions using\n * the AbortController API. When the signal is aborted, the subscription\n * is automatically removed.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n *\n * observable.subscribe(\n * (data) => console.log(data),\n * { signal: controller.signal }\n * );\n *\n * // Later, abort to unsubscribe\n * controller.abort();\n * ```\n *\n * @category Observable Pattern\n */\nexport interface SubscriptionOptions {\n signal?: AbortSignal;\n}\n\n/**\n * Interface for the Observable pattern implementation.\n *\n * @typeParam T - Tuple type of data emitted to observers\n *\n * @remarks\n * Observables allow multiple observers to subscribe and receive notifications\n * when data is emitted. This is the pub-sub pattern for event handling.\n *\n * Implementations can be synchronous or asynchronous:\n * - {@link SynchronousObservable}: Notifies observers immediately\n * - {@link AsyncObservable}: Notifies observers via microtasks\n *\n * @category Observable Pattern\n */\nexport interface Observable<T extends any[]> {\n subscribe(observer: Observer<T>, options?: SubscriptionOptions): () => void;\n notify(...data: T): void;\n}\n\n/**\n * Asynchronous Observable implementation that notifies observers via microtasks.\n *\n * @typeParam T - Tuple type of data emitted to observers\n *\n * @remarks\n * This Observable uses `queueMicrotask` to defer observer notifications,\n * ensuring they execute after the current execution context completes but\n * before the next task. This prevents recursive notification issues and\n * allows the notifier to complete before observers run.\n *\n * Use AsyncObservable when:\n * - You want to prevent recursion issues in notifications\n * - Observer execution should not block the notifier\n * - You need guaranteed async behavior\n *\n * @example\n * ```typescript\n * const observable = new AsyncObservable<[string]>();\n *\n * observable.subscribe((message) => {\n * console.log('Observer received:', message);\n * });\n *\n * console.log('Before notify');\n * observable.notify('Hello');\n * console.log('After notify');\n *\n * // Output:\n * // Before notify\n * // After notify\n * // Observer received: Hello\n * ```\n *\n * @category Observable Pattern\n * @see {@link SynchronousObservable} for synchronous notifications\n */\nexport class AsyncObservable<T extends any[]> implements Observable<T> {\n private observers: Observer<T>[] = [];\n\n /**\n * Subscribes an observer to receive notifications.\n *\n * @param observer - The callback function to be notified\n * @param options - Optional subscription options including AbortSignal\n * @returns Unsubscribe function to remove this observer\n *\n * @remarks\n * If an AbortSignal is provided and is already aborted, the observer\n * is not added and the returned unsubscribe function is a no-op.\n */\n subscribe(observer: Observer<T>, options?: SubscriptionOptions): () => void {\n this.observers.push(observer);\n\n // Handle AbortSignal\n if (options?.signal) {\n // If signal is already aborted, don't add the observer\n if (options.signal.aborted) {\n this.observers = this.observers.filter(o => o !== observer);\n return () => {};\n }\n\n // Add abort handler\n const abortHandler = () => {\n this.observers = this.observers.filter(o => o !== observer);\n options.signal?.removeEventListener('abort', abortHandler);\n };\n\n options.signal.addEventListener('abort', abortHandler);\n }\n\n // Return unsubscribe function\n return () => {\n this.observers = this.observers.filter(o => o !== observer);\n };\n }\n\n /**\n * Notifies all observers with the provided data asynchronously.\n *\n * @param data - The data to pass to all observers\n *\n * @remarks\n * Each observer is called via `queueMicrotask`, ensuring async execution.\n * This method returns immediately; observers run later in the event loop.\n */\n notify(...data: T): void {\n this.observers.forEach(observer => queueMicrotask(() => observer(...data)));\n }\n}\n\n/**\n * Synchronous Observable implementation that notifies observers immediately.\n *\n * @typeParam T - Tuple type of data emitted to observers\n *\n * @remarks\n * This Observable calls all observers synchronously and immediately when\n * `notify()` is called. The notify method doesn't return until all observers\n * have executed.\n *\n * Use SynchronousObservable when:\n * - You need immediate, guaranteed execution of observers\n * - Observer execution order matters and must be predictable\n * - You're in a performance-critical path (no async overhead)\n *\n * Caution: Can lead to recursion issues if observers trigger notifications.\n *\n * @example\n * ```typescript\n * const observable = new SynchronousObservable<[string]>();\n *\n * observable.subscribe((message) => {\n * console.log('Observer received:', message);\n * });\n *\n * console.log('Before notify');\n * observable.notify('Hello');\n * console.log('After notify');\n *\n * // Output:\n * // Before notify\n * // Observer received: Hello\n * // After notify\n * ```\n *\n * @category Observable Pattern\n * @see {@link AsyncObservable} for asynchronous notifications\n */\nexport class SynchronousObservable<T extends any[]> implements Observable<T> {\n private observers: Observer<T>[] = [];\n\n /**\n * Subscribes an observer to receive notifications.\n *\n * @param observer - The callback function to be notified\n * @param options - Optional subscription options including AbortSignal\n * @returns Unsubscribe function to remove this observer\n *\n * @remarks\n * If an AbortSignal is provided and is already aborted, the observer\n * is not added and the returned unsubscribe function is a no-op.\n */\n subscribe(observer: Observer<T>, options?: SubscriptionOptions): () => void {\n this.observers.push(observer);\n\n // Handle AbortSignal\n if (options?.signal) {\n // If signal is already aborted, don't add the observer\n if (options.signal.aborted) {\n this.observers = this.observers.filter(o => o !== observer);\n return () => {};\n }\n\n // Add abort handler\n const abortHandler = () => {\n this.observers = this.observers.filter(o => o !== observer);\n options.signal?.removeEventListener('abort', abortHandler);\n };\n\n options.signal.addEventListener('abort', abortHandler);\n }\n\n // Return unsubscribe function\n return () => {\n this.observers = this.observers.filter(o => o !== observer);\n };\n }\n\n /**\n * Notifies all observers with the provided data synchronously.\n *\n * @param data - The data to pass to all observers\n *\n * @remarks\n * Each observer is called immediately in order. This method blocks until\n * all observers have completed execution.\n */\n notify(...data: T): void {\n this.observers.forEach(observer => observer(...data));\n }\n}\n\n// Usage example\n// const observable = new Observable<[string]>();\n\n// Create an AbortController\n// const controller = new AbortController();\n\n// Subscribe with AbortSignal\n// const unsubscribe = observable.subscribe(\n// (data) => console.log('Received:', data),\n// { signal: controller.signal }\n// );\n\n// Example notifications\n// observable.notify('Hello!'); // Observer will receive this\n\n// Abort the subscription\n// controller.abort();\n\n// Observer won't receive this notification\n// observable.notify('World!');\n\n// Alternative way to unsubscribe using the returned function\n// unsubscribe();\n",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ue-too/board",
3
3
  "type": "module",
4
- "version": "0.13.0",
4
+ "version": "0.14.0",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./index.d.ts",
@@ -14,8 +14,8 @@
14
14
  "types": "./index.d.ts",
15
15
  "module": "./index.js",
16
16
  "dependencies": {
17
- "@ue-too/being": "^0.13.0",
18
- "@ue-too/math": "^0.13.0"
17
+ "@ue-too/being": "^0.14.0",
18
+ "@ue-too/math": "^0.14.0"
19
19
  },
20
20
  "repository": {
21
21
  "type": "git",