@reffy/infinite-canvas 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +536 -532
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +8 -8
- package/dist/index.umd.js.map +1 -1
- package/esm/Canvas.d.ts.map +1 -1
- package/esm/Canvas.js +4 -1
- package/esm/Canvas.js.map +1 -1
- package/esm/Component.d.ts.map +1 -1
- package/esm/Component.js +7 -2
- package/esm/Component.js.map +1 -1
- package/lib/Canvas.d.ts.map +1 -1
- package/lib/Canvas.js +4 -1
- package/lib/Canvas.js.map +1 -1
- package/lib/Component.d.ts.map +1 -1
- package/lib/Component.js +7 -2
- package/lib/Component.js.map +1 -1
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(w,
|
|
1
|
+
(function(w,p){typeof exports=="object"&&typeof module<"u"?p(exports,require("mobx"),require("lit"),require("dexie"),require("uuid"),require("eventemitter3"),require("stats.js")):typeof define=="function"&&define.amd?define(["exports","mobx","lit","dexie","uuid","eventemitter3","stats.js"],p):(w=typeof globalThis<"u"?globalThis:w||self,p(w.ReffyInfiniteCanvas={},w.mobx,w.Lit,w.Dexie,w.uuid,w.EventEmitter3,w.Stats))})(this,(function(w,p,z,k,Xe,Ne,He){"use strict";var Fe=w=>{throw TypeError(w)};var Ge=(w,p,z)=>p.has(w)||Fe("Cannot "+z);var f=(w,p,z)=>(Ge(w,p,"read from private field"),z?z.call(w):p.get(w)),B=(w,p,z)=>p.has(w)?Fe("Cannot add the same private member more than once"):p instanceof WeakSet?p.add(w):p.set(w,z),A=(w,p,z,k)=>(Ge(w,p,"write to private field"),k?k.call(w,z):p.set(w,z),z);var G,H,et,ct,v,Y,dt,it,$,Z,P,lt,Ft,ut;const ft=["TOP","BOTTOM","LEFT","RIGHT"],St=["TOPLEFT","TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"],ee={TOPLEFT:"TOPRIGHT",TOPRIGHT:"TOPLEFT",BOTTOMLEFT:"BOTTOMRIGHT",BOTTOMRIGHT:"BOTTOMLEFT"};function ie(s){return ee[s]?ee[s]:s}const se=8,Xt=2,b={identity:function(){return[1,0,0,0,1,0,0,0,1]},translation:function(s,t){return[1,0,0,0,1,0,s,t,1]},rotation:function(s){var t=Math.cos(s),e=Math.sin(s);return[t,-e,0,e,t,0,0,0,1]},scaling:function(s,t){return[s,0,0,0,t,0,0,0,1]},multiply:function(s,t){var e=s[0],i=s[1],r=s[2],n=s[3],a=s[4],o=s[5],h=s[6],c=s[7],l=s[8],u=t[0],m=t[1],g=t[2],C=t[3],x=t[4],E=t[5],S=t[6],L=t[7],R=t[8];return[u*e+m*n+g*h,u*i+m*a+g*c,u*r+m*o+g*l,C*e+x*n+E*h,C*i+x*a+E*c,C*r+x*o+E*l,S*e+L*n+R*h,S*i+L*a+R*c,S*r+L*o+R*l]},inverse(s){const t=[9],e=s[0],i=s[1],r=s[2],n=s[3],a=s[4],o=s[5],h=s[6],c=s[7],l=s[8],u=l*a-o*c,m=-l*n+o*h,g=c*n-a*h,x=1/(e*u+i*m+r*g);return t[0]=u*x,t[1]=(-l*i+r*c)*x,t[2]=(o*i-r*a)*x,t[3]=m*x,t[4]=(l*e-r*h)*x,t[5]=(-o*e+r*n)*x,t[6]=g*x,t[7]=(-c*e+i*h)*x,t[8]=(a*e-i*n)*x,t},projection(s,t){const e=[9];return e[0]=2/s,e[1]=0,e[2]=0,e[3]=0,e[4]=-2/t,e[5]=0,e[6]=-1,e[7]=1,e[8]=1,e},transformPoint(s,t){var e=t[0],i=t[1],r=e*s[2]+i*s[5]+s[8];return[(e*s[0]+i*s[3]+s[6])/r,(e*s[1]+i*s[4]+s[7])/r]}};function Nt(s,t,e){const i=re(s,s.VERTEX_SHADER,t),r=re(s,s.FRAGMENT_SHADER,e),n=s.createProgram();if(s.attachShader(n,i),s.attachShader(n,r),s.linkProgram(n),!s.getProgramParameter(n,s.LINK_STATUS))throw s.deleteProgram(n),s.deleteShader(i),s.deleteShader(r),new Error("Program was not created or the link to shaders was not successful.");return s.detachShader(n,i),s.detachShader(n,r),n}function re(s,t,e){const i=s.createShader(t);if(s.shaderSource(i,e),s.compileShader(i),s.getShaderParameter(i,s.COMPILE_STATUS))return i;throw s.deleteShader(i),new Error("Shader was not created.")}function Ye(s,t,e,i,r,n){const a=r.getBoundingClientRect(),o=window.devicePixelRatio||1,h=(s-a.left)*o,c=(t-a.top)*o,l=h/e*2-1,u=c/i*-2+1,m=b.projection(e,i),g=b.multiply(m,n),C=b.inverse(g),[x,E]=b.transformPoint(C,[l,u]);return[x,E]}function K(s,t,e){const{gl:i,canvas:r}=e;return Ye(s,t,i.canvas.width,i.canvas.height,r,e.worldMatrix)}function U(s,t,e){const i=t??0,r=e??0;return[s[0]*i+s[3]*r+s[6],s[1]*i+s[4]*r+s[7]]}function $e(s){return Math.hypot(s[0],s[1])}function je(s){return Math.hypot(s[3],s[4])}function Q(s){return[$e(s),je(s)]}function ne(s){return s/Math.abs(s)}function bt(s){return[ne(s[0]),ne(s[4])]}const Mt=(s,t)=>Math.abs(s)<t?0:Math.sign(s),Et=(s,t,e)=>{const i=s*t;return Mt(s,e)!==Mt(i,e)};async function Ve(s){return new Promise((t,e)=>{let i=new FileReader;i.onload=r=>{t(r.target.result)},i.onerror=e,i.readAsDataURL(s)})}const qe=["image/webp","image/png","image/jpeg","image/jpg","image/svg+xml","image/avif","image/gif","image/apng"];function Ze(s){return qe.includes(s)}async function Ht(s){const e=new TextEncoder().encode(s),i=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(i)).map(n=>n.toString(16).padStart(2,"0")).join("")}function Ke(s){const t=/^data:([^;]+);base64,/.exec(s);return t?t[1]:void 0}async function Qe(s,t){const e=[];if(s.length>0)for(let i=0;i<s.length;i++){const r=s[i];if(Ze(r.type))try{const n=await Ve(r);typeof n=="string"?e.push(await t(n)):console.error("Image not added")}catch{console.error("Failed to copy image.")}}return e}function Je(s,t){const e=JSON.stringify(t,null,2),i=new Blob([e],{type:"application/json"}),r=URL.createObjectURL(i),n=document.createElement("a");n.href=r,n.download=s,document.body.appendChild(n),n.click(),n.remove(),URL.revokeObjectURL(r)}async function ti(s){const t=await s.text();return JSON.parse(t)}function ae(s,t=1){return new Promise((e,i)=>{const r=new Image;r.onload=()=>{const n=document.createElement("canvas");n.width=r.width,n.height=r.height;const a=n.getContext("2d");a.clearRect(0,0,n.width,n.height),a.drawImage(r,0,0);const o=n.toDataURL("image/png",t);e(o)},r.onerror=i,r.src=s})}const st=[.33,.6,.95,1],Tt=[.33,.6,.95,.6],ei=[.33,.6,.95,.4];function _t(s,t,e="Add Child"){return{label:e,do(){for(const i of t)s.appendChild(i)},undo(){for(const i of t)s.removeChild(i)}}}function ii(s,t,e="Remove Child"){let i=-1;return{label:e,do(){i=s.children.indexOf(t),i>=0&&s.children.splice(i,1)},undo(){if(i<0){s.children.push(t);return}s.children.splice(i,0,t)}}}function si(s,t,e="Remove Children"){let i=[];return{label:e,do(){const r=new Set(t);i=[],s.children.forEach((n,a)=>{r.has(n)&&i.push({child:n,idx:a})}),i.slice().sort((n,a)=>a.idx-n.idx).forEach(({child:n})=>{s.removeChild(n)})},undo(){i.slice().sort((r,n)=>r.idx-n.idx).forEach(({child:r,idx:n})=>{s.children.includes(r)||(s.children.splice(Math.min(n,s.children.length),0,r),r.addParent(s))}),s.markOrderDirty()}}}const ri=["image/","text/plain"],ni=()=>"clipboard"in navigator&&"writeText"in navigator.clipboard;async function oe(s,t){const e={type:"infinite_canvas",elements:s.map(n=>({src:n.src,x:n.x,y:n.y,sx:n.sx,sy:n.sy}))},i=JSON.stringify(e),r=new ClipboardItem({"text/plain":new Blob([i],{type:"text/plain"})});if(ni())try{await navigator.clipboard.write([r]);return}catch(n){console.error(n)}if(!ai(i))throw new Error("Error copying to clipboard.")}function ai(s){s||(s=" ");const t=document.documentElement.getAttribute("dir")==="rtl",e=document.createElement("textarea");e.style.border="0",e.style.padding="0",e.style.margin="0",e.style.position="absolute",e.style[t?"right":"left"]="-9999px";const i=window.pageYOffset||document.documentElement.scrollTop;e.style.top=`${i}px`,e.style.fontSize="12pt",e.setAttribute("readonly",""),e.value=s,document.body.appendChild(e);let r=!1;try{e.select(),e.setSelectionRange(0,e.value.length),r=document.execCommand("copy")}catch(n){console.error(n)}return e.remove(),r}async function he(s,t,e,i,r=!0){const n=await navigator.clipboard.read(),a=n[0].types,[o,h]=r?[s,t]:K(s,t,e);for(const c of a){if(!ri.find(g=>g.endsWith("/")?c.startsWith(g):c===g))continue;const u=await n[0].getType(c);try{if(c==="text/plain"){const g=JSON.parse(await u.text());if(g.elements.length===0)return;let C=1/0,x=1/0;for(const S of g.elements)S.x<C&&(C=S.x),S.y<x&&(x=S.y);const E=await Promise.all(g.elements.map(S=>e.addImageToCanvas(S.src,o+S.x-C,h+S.y-x,S.sx,S.sy)));i.push(_t(e,E));return}}catch(g){console.error("Failed to parse clipboard data",g);continue}let m;if(c.startsWith("image/svg"))try{const g=await u.text();m=await ae(`data:image/svg+xml;base64,${btoa(g)}`)}catch(g){console.error("SVG conversion failed",g);continue}else try{m=await new Promise((g,C)=>{const x=new FileReader;x.onloadend=()=>g(x.result),x.onerror=C,x.readAsDataURL(u)})}catch(g){console.error("Image read failed",g);continue}try{const g=await e.addImageToCanvas(m,o,h);i.push(_t(e,[g]));return}catch(g){console.error("Failed to add image to canvas",g);continue}}}const X={Open:"opencontextmenu",Close:"closecontextmenu"},N={Save:"save",Change:"statechange"},rt={start:"startloading",done:"completeloading"},nt={Save:"save",SaveCompleted:"savecompleted",SaveFailed:"savefailed"},oi=`
|
|
2
2
|
attribute vec2 a_position;
|
|
3
3
|
|
|
4
4
|
uniform vec2 u_resolution;
|
|
@@ -16,14 +16,14 @@ void main() {
|
|
|
16
16
|
|
|
17
17
|
gl_Position = vec4(clipSpace * vec2(1, -1), z, 1);
|
|
18
18
|
}
|
|
19
|
-
`,
|
|
19
|
+
`,hi=`
|
|
20
20
|
precision mediump float;
|
|
21
21
|
uniform vec4 u_color;
|
|
22
22
|
|
|
23
23
|
void main() {
|
|
24
24
|
gl_FragColor = u_color;
|
|
25
25
|
}
|
|
26
|
-
`,
|
|
26
|
+
`,ci=`
|
|
27
27
|
#extension GL_OES_standard_derivatives : enable
|
|
28
28
|
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
29
29
|
precision highp float;
|
|
@@ -51,7 +51,7 @@ void main() {
|
|
|
51
51
|
float z = mix(1.0, -1.0, u_z);
|
|
52
52
|
gl_Position = vec4(a_Position, z, 1.0);
|
|
53
53
|
}
|
|
54
|
-
`,
|
|
54
|
+
`,di=`
|
|
55
55
|
#extension GL_OES_standard_derivatives : enable
|
|
56
56
|
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
57
57
|
precision highp float;
|
|
@@ -109,7 +109,7 @@ vec4 render_grid_checkerboard(vec2 coord) {
|
|
|
109
109
|
void main() {
|
|
110
110
|
gl_FragColor = render_grid_checkerboard(v_Position);
|
|
111
111
|
}
|
|
112
|
-
`,
|
|
112
|
+
`,li=`
|
|
113
113
|
attribute vec2 a_position;
|
|
114
114
|
attribute vec2 a_texCoord;
|
|
115
115
|
|
|
@@ -130,7 +130,7 @@ void main() {
|
|
|
130
130
|
|
|
131
131
|
v_texCoord = a_texCoord;
|
|
132
132
|
}
|
|
133
|
-
`,
|
|
133
|
+
`,ui=`
|
|
134
134
|
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
135
135
|
precision highp float;
|
|
136
136
|
#else
|
|
@@ -144,7 +144,7 @@ varying vec2 v_texCoord;
|
|
|
144
144
|
void main() {
|
|
145
145
|
gl_FragColor = texture2D(u_image, v_texCoord);
|
|
146
146
|
}
|
|
147
|
-
`;var W=(s=>(s[s.ACTIVE=0]="ACTIVE",s[s.PASSIVE=1]="PASSIVE",s))(W||{});class he{constructor(t,e){this.sides=new Map,this.corners=new Map,this.borderSize=0,this.boxSize=0,this.mode=W.ACTIVE,this.target=t,this.setDimension(),this.mode=e??W.ACTIVE,this.borderSize=Gt,this.boxSize=ie/2,this.addSides(),this.mode===W.ACTIVE&&this.addCorners()}setDimension(){const t=this.target.getEdge();this.width=t.maxX-t.minX,this.height=t.maxY-t.minY}getSidesInScreenSpace(t,e){const[i,r]=e?K(e):[1,1],{width:n,height:a,borderSize:o}=this,[h,c]=U(e),[u,f]=St(e);return{TOP:{x:u>0?h:h-n*i,y:c,width:n*i,height:o},BOTTOM:{x:u>0?h:h-n*i,y:c+a*r*f,width:n*i,height:o},LEFT:{x:h,y:f>0?c:c-a*r,width:o,height:a*r},RIGHT:{x:h+n*i*u,y:f>0?c:c-a*r,width:o,height:a*r}}[t]}getCornersInScreenSpace(t,e){const[i,r]=e?K(e):[1,1],{width:n,height:a,boxSize:o}=this,[h,c]=U(e),[u,f]=St(e);return{TOPLEFT:{x:h-o,y:c-o,width:o*2,height:o*2},TOPRIGHT:{x:h-o+n*i*u,y:c-o,width:o*2,height:o*2},BOTTOMLEFT:{x:h-o,y:c-o+a*r*f,width:o*2,height:o*2},BOTTOMRIGHT:{x:h-o+n*i*u,y:c-o+a*r*f,width:o*2,height:o*2}}[t]}setPassive(){this.mode=W.PASSIVE,this.removeCorners()}setActive(){this.mode=W.ACTIVE,this.addCorners()}getPositions(){return this.target.getPositions()}hitTest(t,e,i){if(this.mode===W.PASSIVE)return;const[r,n]=K(this.target.worldMatrix),[a,o]=St(this.target.worldMatrix),[h,c]=U(i,t,e),u=4;for(const R of Ct){const E=this.getCornersInScreenSpace(R,this.target.worldMatrix);if(h>=E.x-u&&h<=E.x+E.width+u&&c>=E.y-u&&c<=E.y+E.height+u)return R}for(const R of ut){const E=this.getSidesInScreenSpace(R,this.target.worldMatrix);if(h>=E.x-u&&h<=E.x+E.width+u&&c>=E.y-u&&c<=E.y+E.height+u)return R}const[f,p]=U(this.target.worldMatrix),g=this.width*r*a,C=this.height*n*o,x=Math.min(f,f+g),M=Math.max(f,f+g),S=Math.min(p,p+C),L=Math.max(p,p+C);if(h>=x&&h<=M&&c>=S&&c<=L)return"CENTER"}update(){this.updateSides(),this.updateCorners()}render(t,e){this.update();for(const[i,r]of this.sides.entries())r.render(t,e);for(const[i,r]of this.corners.entries())r.render(t,e)}destroy(){for(const[t,e]of this.sides.entries())e.destroy();for(const[t,e]of this.corners.entries())e.destroy()}move(t,e){this.target.updateTranslation(t,e)}resize(t,e,i){if(this.target instanceof j){const r=Math.abs(this.width),n=Math.abs(this.height),a=r/n,o=this.target.sx,h=this.target.sy,c=1e-6,u=Math.abs(r*o)<c?c*bt(r*o||1,c):r*o,f=Math.abs(n*h)<c?c*bt(n*h||1,c):n*h,p=t/u,g=e/f,C=c,x=i==="LEFT"||i==="BOTTOMLEFT"||i==="TOPLEFT"?1-p:i==="RIGHT"||i==="BOTTOMRIGHT"||i==="TOPRIGHT"?1+p:i==="TOP"?1-g:1+g;if(Mt(o,x,C)||Mt(h,x,C))return;const M=r*o*x,S=n*h*x;if(Math.abs(M)<C||Math.abs(S)<C)return;if(this.target.updateScale(x,x),i==="LEFT"){const L=n*h,R=n*this.target.sy;this.target.updateTranslation(t,(L-R)/2)}else if(i==="RIGHT"){const L=n*h,R=n*this.target.sy;this.target.updateTranslation(0,(L-R)/2)}else if(i==="TOP"){const L=r*o,R=r*this.target.sx;this.target.updateTranslation((L-R)/2,e)}else if(i==="BOTTOM"){const L=r*o,R=r*this.target.sx;this.target.updateTranslation((L-R)/2,0)}else i==="BOTTOMLEFT"?this.target.updateTranslation(t,0):i==="TOPLEFT"?this.target.updateTranslation(t,t/a*Math.sign(this.target.sx)):i==="TOPRIGHT"&&this.target.updateTranslation(0,-t/a*Math.sign(this.target.sx))}}reset(){this.target.setScale(1,1)}flip(t){const{x:e,y:i,sx:r,sy:n}=this.target;return t==="vertical"?this.target.flipVertical(this.height):this.target.flipHorizontal(this.width),{ref:this.target,start:{x:e,y:i,sx:r,sy:n},end:{x:this.target.x,y:this.target.y,sx:this.target.sx,sy:this.target.sy}}}addCorners(){for(const t of Ct){const e=new j(this.getCornersInScreenSpace(t,this.target.worldMatrix));e.color=this.mode===W.ACTIVE?et:Et,this.corners.set(t,e)}}removeCorners(){this.corners.clear()}updateCorners(){for(const t of Ct){const e=this.getCornersInScreenSpace(t,this.target.worldMatrix),i=this.corners.get(t);i&&(i.setTranslation(e.x,e.y),i.width=e.width,i.height=e.height,i.color=this.mode===W.ACTIVE?et:Et)}}addSides(){for(const t of ut){const e=new j(this.getSidesInScreenSpace(t,this.target.worldMatrix));e.color=this.mode===W.ACTIVE?et:Et,this.sides.set(t,e)}}updateSides(){for(const t of ut){const e=this.getSidesInScreenSpace(t,this.target.worldMatrix),i=this.sides.get(t);i&&(i.setTranslation(e.x,e.y),i.width=e.width,i.height=e.height,i.color=this.mode===W.ACTIVE?et:Et)}}}const Ht=[...Ct,...ut];class ui{constructor(t){this.targets=[],this.handles=new Map,this.borderSize=0,this.boxSize=0,this.scale=[1,1],t&&t.forEach(e=>this.add(e)),this.addHandles()}add(t){this.targets.includes(t)||this.targets.push(t)}remove(t){const e=this.targets.indexOf(t);e!=-1&&this.targets.splice(e,1)}render(t,e){this.update();for(const[i,r]of this.handles.entries())r.render(t,e)}update(){this.borderSize=Gt,this.boxSize=ie/2,this.recalculateBounds(),this.updateHandles()}destroy(){for(const[t,e]of this.handles.entries())e.destroy()}move(t,e){for(const i of this.targets)i.updateTranslation(t,e)}resize(t,e,i,r){const n=this.width,a=this.height,o=i.includes("TOP"),h=i.includes("BOTTOM"),c=i.includes("LEFT"),u=i.includes("RIGHT"),f=c?this.x+n:u?this.x:this.x+n/2,p=o?this.y+a:h?this.y:this.y+a/2,g=1e-6,C=Math.abs(n)<g?n<0?-g:g:n,x=Math.abs(a)<g?a<0?-g:g:a,[M,S]=K(r),L=t*M/C,R=e*S/x,E=i.includes("LEFT")?1-L:i.includes("RIGHT")?1+L:i==="TOP"?1-R:1+R;if(Mt(this.scale[0],E,g)||Mt(this.scale[1],E,g))return;const hs=n*E,cs=a*E;if(!(Math.abs(hs)<g||Math.abs(cs)<g))for(const Ft of this.targets){const ds=Ft.x,ls=Ft.y,[ke,Ue]=U(r,ds,ls),us=f+(ke-f)*E,fs=p+(Ue-p)*E,gs=us-ke,ms=fs-Ue,ps=Math.abs(M)<g?M<0?-g:g:M,ys=Math.abs(S)<g?S<0?-g:g:S,xs=gs/ps,ws=ms/ys;Ft.updateScale(E,E),Ft.updateTranslation(xs,ws)}}flip(t,e,i){K(t);const r=[],[n,a]=i(this.x,this.y);for(const o of this.targets){const h={ref:o,start:{x:o.x,y:o.y,sx:o.sx,sy:o.sy}};if(e==="vertical"){const c=o.height*o.sy;o.setTranslation(o.x,-o.y-c),o.flipVertical(o.height)}else{const c=o.width*o.sx;o.setTranslation(-o.x-c,o.y),o.flipHorizontal(o.width)}h.end={x:o.x,y:o.y,sx:o.sx,sy:o.sy},r.push(h)}return r}align(t){if(this.targets.length<=1)return;const e=[],i=[t==="top"?1:t==="bottom"?-1:0,t==="left"?1:t==="right"?-1:0];let r=i[0]!==0?1/0*i[0]:1/0*i[1];for(const[n,a]of this.targets.entries()){const o=a.getBoundingBox();r=t==="top"||t==="left"?Math.min(t==="top"?o.minY:o.minX,r):Math.max(t==="bottom"?o.maxY:o.maxX,r)}for(const n of this.targets){const a={ref:n,start:{x:n.x,y:n.y,sx:n.sx,sy:n.sy}},o=n.getBoundingBox();n.updateTranslation(t==="top"||t==="bottom"?0:r-(t==="left"?o.minX:o.maxX),t==="top"||t==="bottom"?r-(t==="top"?o.minY:o.maxY):0),a.end={x:n.x,y:n.y,sx:n.sx,sy:n.sy},e.push(a)}return e}normalize(t,e){const i=[],r=this.targets[0],n=t==="height"?e==="first"?r.height*r.sy:this.targets.reduce((a,o)=>a+Math.abs(o.height*o.sy),0)/this.targets.length:t==="width"?e==="first"?r.width*r.sx:this.targets.reduce((a,o)=>a+Math.abs(o.width*o.sx),0)/this.targets.length:t==="scale"?e==="first"?r.sx:this.targets.reduce((a,o)=>a+Math.abs(o.sx),0)/this.targets.length:e==="first"?r.width*r.height*r.sx*r.sy:this.targets.reduce((a,o)=>a+Math.abs(o.sx*o.width*o.height*o.sy),0)/this.targets.length;for(const a of this.targets){const o={ref:a,start:{x:a.x,y:a.y,sx:a.sx,sy:a.sy}},h=[(a.x+a.width*a.sx)/2,(a.y+a.height*a.sy)/2];if(t==="height"){const u=a.height*a.sy,f=Math.abs(n/u);a.updateScale(f,f)}else if(t==="width"){const u=a.width*a.sx,f=Math.abs(n/u);a.updateScale(f,f)}else if(t==="scale"){const u=Math.sign(a.sx),f=Math.sign(a.sy);a.setScale(n*u,n*f)}else if(t==="size"){const u=a.width*a.height*a.sx*a.sy,f=Math.sqrt(Math.abs(n/u));a.updateScale(f,f)}const c=[(a.x+a.width*a.sx)/2,(a.y+a.height*a.sy)/2];a.updateTranslation(h[0]-c[0],h[1]-c[1]),o.end={x:a.x,y:a.y,sx:a.sx,sy:a.sy},i.push(o)}return i}getPositions(){return[this.x,this.y,this.x+this.width,this.y,this.x+this.width,this.y+this.height,this.x,this.y+this.height]}hitTest(t,e,i){const[r,n]=U(i,t,e),a=4;for(const f of Ht){const p=this.getHandleConfig(f);if(r>=p.x-a&&r<=p.x+p.width+a&&n>=p.y-a&&n<=p.y+p.height+a)return f}const o=Math.min(this.x,this.x+this.width),h=Math.max(this.x,this.x+this.width),c=Math.min(this.y,this.y+this.height),u=Math.max(this.y,this.y+this.height);if(r>=o&&r<=h&&n>=c&&n<=u)return"CENTER"}getBounds(){const t=Array.from(this.targets);let e=1/0,i=1/0,r=-1/0,n=-1/0;for(const a of t){const[o,h]=U(a.worldMatrix),[c,u]=U(a.worldMatrix,a.width,a.height);e=Math.min(e,a.sx<0?c:o),i=Math.min(i,a.sy<0?u:h),r=Math.max(r,a.sx<0?o:c),n=Math.max(n,a.sy<0?h:u)}return{minX:e,minY:i,maxX:r,maxY:n}}recalculateBounds(){const{minX:t,minY:e,maxX:i,maxY:r}=this.getBounds();this.x=this.scale[0]<0?i:t,this.y=this.scale[1]<0?r:e,this.width=this.scale[0]*(i-t),this.height=this.scale[1]*(r-e)}addHandles(){for(const t of Ht){const e=this.getHandleConfig(t),i=new j(e);i.color=et,this.handles.set(t,i)}}updateHandles(){for(const t of Ht){const e=this.handles.get(t),i=this.getHandleConfig(t);e&&(e.setTranslation(i.x,i.y),e.width=i.width,e.height=i.height)}}getHandleConfig(t){let{x:e,y:i,width:r,height:n,borderSize:a,boxSize:o}=this;return{TOP:{x:e,y:i,width:r,height:a},BOTTOM:{x:e,y:i+n,width:r,height:a},LEFT:{x:e,y:i,width:a,height:n},RIGHT:{x:e+r,y:i,width:a,height:n},TOPLEFT:{x:e-o,y:i-o,width:o*2,height:o*2},TOPRIGHT:{x:e-o+r,y:i-o,width:o*2,height:o*2},BOTTOMLEFT:{x:e-o,y:i-o+n,width:o*2,height:o*2},BOTTOMRIGHT:{x:e-o+r,y:i-o+n,width:o*2,height:o*2}}[t]}}class rt{constructor(t,e,i,r){this.minX=t,this.minY=e,this.maxX=i,this.maxY=r}getArea(){return(this.maxY-this.minY)*(this.maxX-this.minX)}static isColliding(t,e){return t.minX<=e.maxX&&t.maxX>=e.minX&&t.minY<=e.maxY&&t.maxY>=e.minY}}const ce=["CENTER",...ut];class fi{constructor(t,e,i){this.width=0,this.height=0,this.rects=new Map,this.borderSize=0;const[r,n]=U(i,t,e);this.x=r,this.y=n,this.addRects()}getRectConfig(t){let{x:e,y:i,width:r,height:n,borderSize:a}=this;return{TOP:{x:e,y:i,width:r<0?r:r+a,height:a},BOTTOM:{x:e,y:i+n,width:r<0?r:r+a,height:a},LEFT:{x:n<0&&r<0?e-a:e,y:i,width:a,height:n<0&&r<0?n:n+a},RIGHT:{x:e+r,y:i,width:a,height:n<0?n:n+a},CENTER:{x:e,y:i,width:r,height:n}}[t]}render(t,e){this.update();for(const[i,r]of this.rects.entries())r.render(t,e)}update(){this.borderSize=Gt,this.updateRects()}destroy(){for(const[t,e]of this.rects.entries())e.destroy()}getBoundingBox(t){const[e,i]=t(this.x,this.y),[r,n]=t(this.x+this.width,this.y+this.height),a=Math.min(e,r),o=Math.max(e,r),h=Math.min(i,n),c=Math.max(i,n);return new rt(a,h,o,c)}resize(t,e,i){const[r,n]=K(i);this.width+=t*r,this.height+=e*n}addRects(){for(const t of ce){const e=this.getRectConfig(t),i=new j(e);i.color=et,this.rects.set(t,i)}}updateRects(){for(const t of ce){const e=this.rects.get(t),i=this.getRectConfig(t);e&&(e.setTranslation(i.x,i.y),e.width=i.width,e.height=i.height,t==="CENTER"&&(e.color=ti))}}}class gi{constructor(t={}){const{x:e=0,y:i=0,width:r=0,height:n=0,rotation:a=0,zoom:o=1}=t;this.x=e,this.y=i,this.width=r,this.height=n,this.rotation=a,this.zoom=o,m.makeObservable(this,{x:m.observable,y:m.observable,width:m.observable,height:m.observable,rotation:m.observable,zoom:m.observable,setX:m.action,setY:m.action,setPosition:m.action,incrementPosition:m.action,setWidth:m.action,setHeight:m.action,setSize:m.action,setZoom:m.action,setRotation:m.action,stateVector:m.computed})}setX(t){this.x=t}setY(t){this.y=t}setPosition(t,e){this.x=t,this.y=e}incrementPosition(t,e){this.x+=t,this.y+=e}setWidth(t){this.width=t}setHeight(t){this.height=t}setSize(t,e){this.width=t,this.height=e}setZoom(t){this.zoom=t}setRotation(t){this.rotation=t}get dimension(){return[this.width,this.height]}get position(){return[this.x,this.y]}get stateVector(){return[this.x,this.y,this.width,this.height,this.rotation,this.zoom]}get translationMatrix(){return b.translation(this.x,this.y)}get rotationMatrix(){return b.rotation(this.rotation)}get scaleMatrix(){return b.scaling(this.zoom,this.zoom)}get cameraMatrix(){const t=b.multiply(this.translationMatrix,this.rotationMatrix);return b.multiply(t,this.scaleMatrix)}get canvasMatrix(){return b.inverse(this.cameraMatrix)}}function de(s,t){s.setTranslation(t.x,t.y),s.setScale(t.sx,t.sy)}function le(s,t,e){return{label:"Flip",do(){for(const i of s)de(i.ref,i.end);e&&(e.scale[t==="horizontal"?0:1]*=-1)},undo(){for(const i of s)de(i.ref,i.start);e&&(e.scale[t==="horizontal"?0:1]*=-1)}}}function ue(s,t){s.setTranslation(t.x,t.y),s.setScale(t.sx,t.sy)}function Yt(s,t="Transform"){return{label:t,do(){for(const e of s)ue(e.ref,e.end)},undo(){for(const e of s)ue(e.ref,e.start)}}}class mi{#s;#i=new Set;#e=new Set;#t;#r;#a;get multiBoundingBox(){return this.#t}get boundingBoxes(){return this.#e}#o=!0;#n;#h;get selected(){return Array.from(this.#i)}set selected(t){this.#i.clear(),t.forEach(e=>{this.#i.add(e),this.#e.add(new he(e))})}get marqueeBox(){return this.#r}set marqueeBox(t){this.#r=new fi(t.x,t.y,this.getWorldMatrix())}constructor(t,e,i,r,n,a,o,h){this.#n=i,this.#h=r,this.#s=t,this.#a=e,this.getWorldMatrix=n,this.getCanvasChildren=a,this.getWorldCoords=o,this.getMarqueeCoords=h;const c=Object.getPrototypeOf(this);for(const u of Object.getOwnPropertyNames(c)){const f=this[u];typeof f=="function"&&u!=="constructor"&&(this[u]=f.bind(this))}}add(t){t.forEach(e=>{this.#i.has(e)||(this.#i.add(e),this.#e.add(new he(e)))}),this.#e.size>1&&(this.#e.forEach(e=>e.setPassive()),this.#t||(this.#t=new ui([])),this.selected.forEach(e=>this.#t.add(e)))}remove(t){t.forEach(e=>{if(!this.#i.has(e))return;this.#i.delete(e);const i=Array.from(this.#e.values()).find(r=>r.target===e);i?this.#e.delete(i):console.error("No matching bounding box found"),this.#t&&this.#t.remove(e)}),this.#e.size<=1&&(this.#e.forEach(e=>e.setActive()),this.#t=null)}deleteSelected(t){const e=[...this.#i];this.remove(e);for(const i of e)i.destroy();this.#s.push(ii(t,e))}hitTest(t,e){if(this.#t){const i=this.#t.hitTest(t,e,this.getWorldMatrix());if(i)return i}for(const i of this.#e.values()){const r=i.hitTest(t,e,this.getWorldMatrix());if(r)return r}return null}isMultiBoundingBoxHit(t,e){return this.#t&&this.#t.hitTest(t,e,this.getWorldMatrix())}isBoundingBoxHit(t,e){return this.#e.size===1&&Array.from(this.#e)[0].hitTest(t,e,this.getWorldMatrix())}hitTestAdjustedCorner(t,e){if(this.#t){const i=this.#t.hitTest(t,e,this.getWorldMatrix());if(i)return this.#t.scale[0]*this.#t.scale[1]<0?ee(i):i}for(const i of this.#e.values()){const r=i.hitTest(t,e,this.getWorldMatrix());if(r)return i.target.sx*i.target.sy<0?ee(r):r}}update(){this.#e.forEach(t=>t.update()),this.#t&&this.#t.update()}render(t){if(!this.#r&&!this.#t&&this.#e.size===0)return;this.#n.useProgram(t);const e=this.#n.getUniformLocation(t,"u_z");e&&this.#n.uniform1f(e,1),this.#o&&this.#e.forEach(i=>i.render(this.#n,t)),this.#t&&this.#t.render(this.#n,t),this.#r&&this.#r.render(this.#n,t)}isRectSelected(t){return this.#i.has(t)}clear(){this.#i.clear(),this.#e.clear(),this.#t=null}clearMarquee(){this.#r&&(this.#r=null)}move(t,e){if(this.#t)this.#t.move(t,e);else for(const i of this.#e)i.move(t,e);this.#a.emit(N.Change)}resize(t,e,i){this.multiBoundingBox&&this.multiBoundingBox.resize(t,e,i,this.getWorldMatrix());for(const r of this.boundingBoxes)this.multiBoundingBox?r.update():r.resize(t,e,i);this.#a.emit(N.Change)}flip(t){if(this.multiBoundingBox){const e=this.multiBoundingBox.flip(this.getWorldMatrix(),t,this.getWorldCoords);this.#s.push(le(e,t,this.multiBoundingBox))}else{const e=[];for(const i of this.boundingBoxes)e.push(i.flip(t));this.#s.push(le(e,t))}this.#a.emit(N.Change)}alignSelection(t){if(!this.multiBoundingBox)return;const e=this.multiBoundingBox.align(t);this.#s.push(Yt(e)),this.#a.emit(N.Change)}normalize(t,e="first"){if(!this.multiBoundingBox)return;const i=this.multiBoundingBox.normalize(t,e);this.#s.push(Yt(i)),this.#a.emit(N.Change)}onPointerMove(t,e,i,r,n,a,o,h){if(a())o(t,e);else if(n&&n!=="CENTER")this.resize(i,r,n);else if(this.marqueeBox){this.marqueeBox.resize(i,r,h());const c=this.getCanvasChildren(),u=this.marqueeBox.getBoundingBox(this.getMarqueeCoords);for(const f of c){const p=f.getBoundingBox();rt.isColliding(p,u)&&!this.#i.has(f)?this.add([f]):!rt.isColliding(p,u)&&this.#i.has(f)&&this.remove([f])}}else this.move(i,r)}onSelectionPointerDown(t,e,i,r){e?(t||this.clear(),this.add([e])):(this.clear(),this.marqueeBox?this.clearMarquee():this.marqueeBox={x:i,y:r})}}var gt=(s=>(s[s.SELECT=0]="SELECT",s[s.PAN=1]="PAN",s))(gt||{});const pi={TOP:"ns-resize",BOTTOM:"ns-resize",LEFT:"ew-resize",RIGHT:"ew-resize",TOPLEFT:"nwse-resize",BOTTOMRIGHT:"nwse-resize",TOPRIGHT:"nesw-resize",BOTTOMLEFT:"nesw-resize",CENTER:"grab"};class yi{constructor(t){for(const e in t)e in t&&t[e]!==void 0&&(this[e]=t[e]);this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMoveWhileDown=this.onPointerMoveWhileDown.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.addOnPointerMove(),this.addOnWheel(t.onWheel),this.addOnPointerDown(),window.addEventListener("copy",async e=>{e.preventDefault(),!this.isContextMenuActive()&&await ae(this.getSelected())}),window.addEventListener("paste",async e=>{e.preventDefault(),!this.isContextMenuActive()&&await t.paste(this.state.lastPointerPos.x,this.state.lastPointerPos.y)})}changeMode(){this.state.toggleMode()}addOnPointerDown(){this.assignEventListener("pointerdown",this.onPointerDown)}addOnPointerMove(){this.assignEventListener("pointermove",t=>{[this.state.lastPointerPos.x,this.state.lastPointerPos.y]=this.getWorldCoords(t.clientX,t.clientY);let e=this.hitTestAdjustedCorner(this.state.lastPointerPos.x,this.state.lastPointerPos.y);this.setCursorStyle(pi[e]||"default")})}addOnWheel(t){this.assignEventListener("wheel",e=>{this.isContextMenuActive()||t(e)},{passive:!1})}onPointerDown(t){t.stopPropagation(),t.preventDefault(),this.eventHub.emit(X.Close);const[e,i]=this.getWorldCoords(t.clientX,t.clientY);this.state.initialize(e,i),this.currentTransform=void 0,this.state.mode===1?this.handlePanPointerDown():this.state.mode===0&&this.handleSelectPointerDown(t,e,i),document.addEventListener("pointermove",this.onPointerMoveWhileDown),document.addEventListener("pointerup",this.onPointerUp)}handlePanPointerDown(){this.setCanvasGlobalClick(!0),this.clearSelection()}handleSelectPointerDown(t,e,i){this.setCanvasGlobalClick(!1);const r=this.checkCollidingChild(e,i),n=this.checkIfSelectionHit(e,i);if(t.button===2)n||this.clearSelection(),r&&!this.isSelection(r)&&this.addSelection([r]);else{n?this.state.resizingDirection=n:this.onSelectionPointerDown(t.shiftKey,r,e,i);const a=this.getSelected();a.length&&(this.currentTransform={targets:a.map(o=>({ref:o,start:{x:o.x,y:o.y,sx:o.sx,sy:o.sy}}))})}}onPointerMoveWhileDown(t){if(t.buttons===2)return;const[e,i]=this.getWorldCoords(t.clientX,t.clientY),r=e-this.state.lastWorldX,n=i-this.state.lastWorldY;this.selectionPointerMove(this.state.startWorldX-e,this.state.startWorldY-i,r,n,this.state.resizingDirection),this.state.updateLastWorldCoord(e,i),this.setCursorStyle("grabbing")}onPointerUp(){if(document.removeEventListener("pointermove",this.onPointerMoveWhileDown),document.removeEventListener("pointerup",this.onPointerUp),this.setCanvasGlobalClick(!0),this.setCursorStyle("default"),this.currentTransform){const t=this.currentTransform.targets.map(e=>({ref:e.ref,start:e.start,end:{x:e.ref.x,y:e.ref.y,sx:e.ref.sx,sy:e.ref.sy}})).filter(e=>e.start.x!==e.end.x||e.start.y!==e.end.y||e.start.sx!==e.end.sx||e.start.sy!==e.end.sy);t.length&&this.history.push(Yt(t))}this.currentTransform=void 0,this.state.resizingDirection=null,this.closeMarquee(),this.eventHub.emit("save")}checkCollidingChild(t,e){const i=this.getChildren();for(let r=i.length-1;r>=0;r--){const n=i[r];if(n instanceof nt&&n.hitTest&&n.hitTest(t,e))return n}return null}}class xi{constructor(t,e,i,r){this.history=t,this.deleteSelected=i,this.save=()=>e.emit(N.Save),this.assignEventListener=r,this.onKeyPressed=this.onKeyPressed.bind(this),this.addOnKeyPressed()}addOnKeyPressed(){document.addEventListener("keydown",this.onKeyPressed)}onKeyPressed(t){if(this.isCtrlZ(t)){t.preventDefault(),this.history.undo();return}if(this.isCtrlY(t)){t.preventDefault(),this.history.redo();return}if(this.isDelete(t)){this.deleteSelected();return}if(this.isSave(t)){t.preventDefault(),this.save();return}}isCtrlZ(t){return t.key.toLowerCase()==="z"&&(t.ctrlKey||t.metaKey)&&!t.shiftKey}isCtrlY(t){return t.key.toLowerCase()==="y"&&(t.ctrlKey||t.metaKey)&&!t.shiftKey}isDelete(t){return t.key==="Delete"}isSave(t){return t.key.toLowerCase()==="s"&&t.ctrlKey}}class wi{#s=!1;get isActive(){return this.#s}constructor(t,e,i,r,n){this.customContextMenu=a=>{a.preventDefault(),a.stopPropagation();const[o,h]=r(a.clientX,a.clientY);e(o,h)?t.emit(X.Open,a.clientX,a.clientY,"multi"):i(o,h)?t.emit(X.Open,a.clientX,a.clientY):t.emit(X.Open,a.clientX,a.clientY,"canvas")},t.on(X.Open,()=>{this.#s=!0}),t.on(X.Close,()=>{this.#s=!1}),n("contextmenu",this.customContextMenu)}}function fe(s,t){s.renderOrder=t.renderOrder}function vi(s,t="Order"){return{label:t,do(){for(const e of s)fe(e.ref,e.end)},undo(){for(const e of s)fe(e.ref,e.start)}}}class Ci{constructor(t=gt.SELECT){this.lastPointerPos={x:0,y:0},this.startWorldX=0,this.startWorldY=0,this.lastWorldX=0,this.lastWorldY=0,this.resizingDirection=null,this.mode=t}get isResizing(){return this.resizingDirection!==null}get dragDXFromStart(){return this.lastWorldX-this.startWorldX}get dragDYFromStart(){return this.lastWorldY-this.startWorldY}setMode(t){this.mode=t}toggleMode(){this.mode=this.mode===gt.PAN?gt.SELECT:gt.PAN}setResizingDirection(t){this.resizingDirection=t}clearResizingDirection(){this.resizingDirection=null}initialize(t,e){this.startWorldX=t,this.startWorldY=e,this.lastWorldX=t,this.lastWorldY=e,this.resizingDirection=null}updateLastWorldCoord(t,e){this.lastWorldX=t,this.lastWorldY=e}}class Si{constructor(){this.translation=[0,0],this.angleRadians=0,this.scale=[1,1],this.localMatrix=b.identity(),this.worldMatrix=b.identity(),this.children=[],this.parent=null,this.renderDirtyFlag=!0,m.makeObservable(this,{translation:m.observable.struct,angleRadians:m.observable,scale:m.observable.struct,localMatrix:m.observable.ref,worldMatrix:m.observable.ref,children:m.observable.shallow,parent:m.observable.ref,renderDirtyFlag:m.observable,x:m.computed,y:m.computed,scaleX:m.computed,scaleY:m.computed,dirty:m.computed,setTranslation:m.action,setScale:m.action,flipVertical:m.action,setAngle:m.action,getChild:m.action,appendChild:m.action,appendChildren:m.action,removeChild:m.action,clearChildren:m.action,setParent:m.action,markDirty:m.action,clearDirty:m.action,updateLocalMatrix:m.action,updateWorldMatrix:m.action,setWorldMatrix:m.action}),this.updateLocalMatrix(),this.updateWorldMatrix()}get x(){return this.translation[0]}get y(){return this.translation[1]}get scaleX(){return this.scale[0]}get scaleY(){return this.scale[1]}get dirty(){return this.renderDirtyFlag}setTranslation(t,e){this.translation[0]=t,this.translation[1]=e,this.markDirty()}updateTranslation(t,e){this.translation[0]+=t,this.translation[1]+=e,this.markDirty()}setScale(t,e){t===this.scale[0]&&e===this.scale[1]||(this.scale[0]=t,this.scale[1]=e,this.markDirty())}updateScale(t,e){this.scale[0]*=t,this.scale[1]*=e,this.markDirty()}flipVertical(t){this.translation[1]+=this.scale[1]*t,this.scale[1]*=-1,this.markDirty()}flipHorizontal(t){this.translation[0]+=this.scale[0]*t,this.scale[0]*=-1,this.markDirty()}setAngle(t){const i=(360-t)*Math.PI/180;i!==this.angleRadians&&(this.angleRadians=i,this.markDirty())}getChild(t){return this.children[t]}appendChild(t){this.children.includes(t)||(this.children.push(t),this.markDirty())}appendChildren(t){for(const e of t){if(this.children.includes(e))return;this.children.push(e)}this.markDirty()}removeChild(t){const e=this.children.indexOf(t);if(e<0)return;const i=this.children.splice(e,1);return t.state.setParent(null),this.markDirty(),i[0]}clearChildren(){if(this.children){for(const t of this.children)t.destroy();this.children=[],this.markDirty()}}setParent(t){this.parent!==t&&(this.parent=t,this.markDirty())}markDirty(){this.renderDirtyFlag||(this.renderDirtyFlag=!0,this.updateLocalMatrix())}clearDirty(){this.renderDirtyFlag&&(this.renderDirtyFlag=!1,this.updateLocalMatrix())}updateLocalMatrix(){const t=b.translation(this.translation[0],this.translation[1]),e=b.rotation(this.angleRadians),i=b.scaling(this.scale[0],this.scale[1]);this.localMatrix=b.multiply(b.multiply(t,e),i)}updateWorldMatrix(t){this.worldMatrix=t?b.multiply(t,this.localMatrix):this.localMatrix.slice();const e=this.worldMatrix;this.children.forEach(i=>{i.updateWorldMatrix(e)})}setWorldMatrix(t){this.worldMatrix=t}}class ge{get x(){return this.state.x}get y(){return this.state.y}get sx(){return this.state.scaleX}get sy(){return this.state.scaleY}get dirty(){return this.state.dirty}get localMatrix(){return this.state.localMatrix}get worldMatrix(){return this.state.worldMatrix}get children(){return this.state.children}get parent(){return this.state.parent}get angleRadians(){return this.state.angleRadians}updateTranslation(t,e){this.state.updateTranslation(t,e)}setTranslation(t,e){this.state.setTranslation(t,e)}updateScale(t,e){this.state.updateScale(t,e)}setScale(t,e){this.state.setScale(t,e)}setAngle(t){return this.state.setAngle(t)}flipVertical(t){this.state.flipVertical(t)}flipHorizontal(t){this.state.flipHorizontal(t)}markDirty(){this.state.markDirty()}clearDirty(){this.state.clearDirty()}updateLocalMatrix(){this.state.updateLocalMatrix()}setWorldMatrix(t){this.state.setWorldMatrix(t)}addChild(t){this.state.appendChild(t)}addParent(t){return this.state.setParent(t)}clearChildren(){return this.state.clearChildren()}constructor(){this.state=new Si,this.setWorldMatrix=this.setWorldMatrix.bind(this),this.updateWorldMatrix=this.updateWorldMatrix.bind(this)}appendChild(t){return t.setParent(this),!t._emitter&&this._emitter&&(t._emitter=this._emitter),t}setParent(t){if(this.parent){const e=this.parent.children.indexOf(this);e>=0&&this.parent.children.splice(e,1)}t&&t.addChild(this),this.addParent(t)}updateWorldMatrix(t){this.updateLocalMatrix(),this.state.updateWorldMatrix(t)}addEventListener(t,e,i){const r=typeof e=="function"?e:e.handleEvent.bind(e);this._emitter.on(t,r)}removeEventListener(t,e,i){}dispatchEvent(t){return this._emitter.emit(t.type,t),!t.defaultPrevented}}class me extends ge{constructor(){super(...arguments),this.initialized=!1}updateVertexData(t){const e=this.getPositions();(!this.vertexArray||this.vertexArray.length!==e.length)&&(this.vertexArray=new Float32Array(e.length)),this.vertexArray.set(e),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.vertexArray,t.STATIC_DRAW)}setUpVertexData(t,e){this.positionBuffer||(this.positionBuffer=t.createBuffer()),this.attributeLocation=t.getAttribLocation(e,"a_position")}setUpUniforms(t,e){this.resolutionLocation=t.getUniformLocation(e,"u_resolution"),this.matrixLocation=t.getUniformLocation(e,"u_matrix")}updateUniforms(t){t.uniform2f(this.resolutionLocation,t.canvas.width,t.canvas.height),t.uniformMatrix3fv(this.matrixLocation,!1,this.worldMatrix)}}const Ut=class Ut extends me{constructor(t,e,i=1,r=1){super(),this._seq=Ut._seqCounter++,this.culled=!1,this._renderOrder=0,this.color=[1,0,.5,1],this.setTranslation(t,e),this.setScale(i,r)}get renderOrder(){return this._renderOrder}set renderOrder(t){this._renderOrder!==t&&(this._renderOrder=t,this.markDirty())}get seq(){return this._seq}getZ(){const e=this.renderOrder*1e-4+.5;return Math.max(0,Math.min(1,e))}render(t,e){this.updateWorldMatrix(this.parent?this.parent.worldMatrix:void 0),t.useProgram(e),this.dirty&&!this.culled&&(this.initialized||(this.setUpVertexData(t,e),this.setUpUniforms(t,e),this.initialized=!0),this.updateVertexData(t),this.clearDirty()),this.updateUniforms(t);const i=t.getUniformLocation(e,"u_color");i&&t.uniform4fv(i,this.color),this.culled||this.draw(t)}draw(t){t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer);const e=2,i=t.FLOAT;t.vertexAttribPointer(this.attributeLocation,e,i,!1,0,0),t.enableVertexAttribArray(this.attributeLocation),t.drawArrays(t.TRIANGLES,0,this.getVertexCount()),t.bindBuffer(t.ARRAY_BUFFER,null),t.disableVertexAttribArray(this.attributeLocation)}destroy(){this.positionBuffer&&(this.positionBuffer=void 0),this.initialized=!1}};Ut._seqCounter=0;let nt=Ut;class j extends nt{constructor(t){super(t.x,t.y,t.sx,t.sy),this._width=t.width??100,this._height=t.height??100}get width(){return this._width}set width(t){this._width!==t&&(this._width=t,this.markDirty())}get height(){return this._height}set height(t){this._height!==t&&(this._height=t,this.markDirty())}getVertexCount(){return 6}getPositions(){const i=this.width,r=this.height;return[0,0,0,r,i,0,i,0,0,r,i,r]}getBoundingBox(){const t=this.state.translation[0],e=t+this.width*this.state.scaleX,i=this.state.translation[1],r=i+this.height*this.state.scaleY,n=Math.min(t,e),a=Math.max(t,e),o=Math.min(i,r),h=Math.max(i,r);return this.AABB=new rt(n,o,a,h),this.AABB}getEdge(){const t=this.x,e=this.y;return{minX:Math.min(t,t+this.width),maxX:Math.max(t,t+this.width),minY:Math.min(e,e+this.height),maxY:Math.max(e,e+this.height)}}hitTest(t,e){const[i,r]=K(this.worldMatrix),[n,a]=St(this.worldMatrix),[o,h]=U(this.parent.worldMatrix,t,e),[c,u]=U(this.worldMatrix),f=this.width*i*n,p=this.height*r*a,g=Math.min(c,c+f),C=Math.max(c,c+f),x=Math.min(u,u+p),M=Math.max(u,u+p);return o>=g&&o<=C&&h>=x&&h<=M}}class mt extends j{constructor(t){super(t),this.texCoordArray=new Float32Array([0,0,0,1,1,0,1,0,0,1,1,1]),this.useLowRes=!1,this.lowResNeedsRefresh=!0,this._src=t.src,this.loadImage(t.src,t.width,t.height)}get src(){return this._src}set src(t){this._src!==t&&(this._src=t,this.updateImageTexture(t),this.markDirty())}get fileId(){return this._fileId}set fileId(t){this._fileId=t}determineIfLowRes(t,e,i=.1){const r=t.getArea();return this.getBoundingBox().getArea()/r<i/e}async setUseLowRes(t,e){this.useLowRes===t&&!this.lowResNeedsRefresh||(this.useLowRes=t,(t&&e||this.lowResNeedsRefresh)&&await this.ensureLowResUploaded(e),this.markDirty(),this.lowResNeedsRefresh=!1)}loadImage(t,e,i){this.culled||this.updateImageTexture(t,e,i)}updateImageTexture(t,e,i){this._image=new Image,this._image.crossOrigin="anonymous",this._image.onload=async()=>{this.width=e??this._image.naturalWidth,this.height=i??this._image.naturalHeight;try{if(this.bitmap){try{this.bitmap.close()}catch{}this.bitmap=void 0}typeof createImageBitmap=="function"&&(this.bitmap=await createImageBitmap(this._image))}catch(r){console.warn("createImageBitmap failed, falling back to HTMLImageElement",r),this.bitmap=void 0}if(this.gl&&this.program)try{this.texture&&this.gl&&(this.gl.deleteTexture(this.texture),this.texture=void 0),this.initialiseTexture(),this.initialized=!0,this.markDirty()}catch(r){console.error("Failed to initialise texture on image load",r)}this.lowResNeedsRefresh=!0},this._image.onerror=r=>{console.error("Failed to load image:",t,r)},this._image.src=t}async ensureLowResUploaded(t){if(!(this.lowResTexture&&!this.lowResNeedsRefresh)&&!(!this._image||!this._image.complete))try{const i=this._image.naturalWidth,r=this._image.naturalHeight,n=Math.min(1,256/Math.max(1,Math.max(i,r))),a=Math.max(1,Math.round(i*n)),o=Math.max(1,Math.round(r*n));let h;typeof OffscreenCanvas<"u"?h=new OffscreenCanvas(a,o):(h=document.createElement("canvas"),h.width=a,h.height=o);const c=h.getContext("2d");c.clearRect(0,0,a,o);const u=Math.min(a/i,o/r),f=Math.round(i*u),p=Math.round(r*u),g=Math.round((a-f)/2),C=Math.round((o-p)/2);c.drawImage(this._image,0,0,i,r,g,C,f,p),this.lowResBitmap=await createImageBitmap(h),this.setLowResTextureFromBitmap(t,this.lowResBitmap)}catch(e){console.error("Failed to create/upload low-res image",e)}}setLowResTextureFromBitmap(t,e){if(this.lowResTexture){try{t.deleteTexture(this.lowResTexture)}catch{}this.lowResTexture=void 0}this.lowResTexture=t.createTexture(),t.bindTexture(t.TEXTURE_2D,this.lowResTexture),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),t.bindTexture(t.TEXTURE_2D,null),this.markDirty()}initialiseTexture(){!this.gl||!this.program||!this._image||!this._image.complete||this._image.naturalWidth===0||(this.setUpVertexData(this.gl,this.program),this.setUpTexData(this.gl,this.program),this.setTexture(this.gl),super.setUpUniforms(this.gl,this.program),this.samplerLocation=this.gl.getUniformLocation(this.program,"u_image"),this.samplerLocation&&this.gl.uniform1i(this.samplerLocation,0))}setUpTexData(t,e){this.texcoordBuffer||(this.texcoordBuffer=t.createBuffer()),this.texcoordLocation=t.getAttribLocation(e,"a_texCoord")}setTexture(t){if(this.texture){try{try{t.deleteTexture(this.texture)}catch{}}catch{}this.texture=void 0}this.texture=t.createTexture(),t.bindTexture(t.TEXTURE_2D,this.texture),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR);const e=this.bitmap??this._image;e&&t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),t.bindTexture(t.TEXTURE_2D,null)}updateVertexData(t){super.updateVertexData(t),t.bindBuffer(t.ARRAY_BUFFER,this.texcoordBuffer),t.bufferData(t.ARRAY_BUFFER,this.texCoordArray,t.STATIC_DRAW)}getVertexCount(){return 6}render(t,e){if(this.dirty&&!this.culled){if(this.updateWorldMatrix(this.parent?this.parent.worldMatrix:void 0),!this.initialized)if(this.gl=t,this.program=e,this.initialiseTexture(),this._image.complete&&this._image.naturalWidth>0)this.initialized=!0;else return;this.updateVertexData(t),this.clearDirty()}super.updateUniforms(t),this.culled||this.draw(t)}draw(t){t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer);const e=2,i=t.FLOAT,r=!1,n=0,a=0;t.vertexAttribPointer(this.attributeLocation,e,i,r,n,a),t.enableVertexAttribArray(this.attributeLocation),t.bindBuffer(t.ARRAY_BUFFER,this.texcoordBuffer),t.vertexAttribPointer(this.texcoordLocation,e,i,r,n,a),t.enableVertexAttribArray(this.texcoordLocation),t.activeTexture(t.TEXTURE0);try{const o=this.useLowRes&&this.lowResTexture?this.lowResTexture:this.texture;t.bindTexture(t.TEXTURE_2D,o),t.drawArrays(t.TRIANGLES,0,this.getVertexCount()),t.bindBuffer(t.ARRAY_BUFFER,null),t.disableVertexAttribArray(this.attributeLocation),t.disableVertexAttribArray(this.texcoordLocation)}catch(o){console.error(o)}}destroy(){if(this.texcoordBuffer){try{this.gl.deleteBuffer(this.texcoordBuffer)}catch{}this.texcoordBuffer=void 0}if(this.texture){try{this.gl.deleteTexture(this.texture)}catch{}this.texture=void 0}if(this.lowResTexture){try{this.gl.deleteTexture(this.lowResTexture)}catch{}this.lowResTexture=void 0}if(this.bitmap){try{this.bitmap.close()}catch{}this.bitmap=void 0}if(this.lowResBitmap){try{this.lowResBitmap.close()}catch{}this.lowResBitmap=void 0}this.texcoordLocation=void 0,this.samplerLocation=void 0;try{super.destroy()}catch{}}}var _t=(s=>(s[s.NONE=0]="NONE",s[s.GRID=1]="GRID",s))(_t||{});class pe extends me{constructor(){super(...arguments),this.buffer=null,this.vertexCount=0,this.gridType=1,this.zoom=1}getPositions(){return new Float32Array([-1,-1,3,-1,-1,3])}changeGridType(t){this.gridType=t}render(t,e){if(this.buffer)t.bindBuffer(t.ARRAY_BUFFER,this.buffer);else{if(this.buffer=t.createBuffer(),!this.buffer)throw new Error("Failed to create grid buffer");const c=this.getPositions();this.vertexCount=c.length/2,t.bindBuffer(t.ARRAY_BUFFER,this.buffer),t.bufferData(t.ARRAY_BUFFER,c,t.STATIC_DRAW)}this.initialized||(this.setUpVertexData(t,e),this.setUpUniforms(t,e),this.initialized=!0);const i=t.drawingBufferWidth,r=t.drawingBufferHeight,n=b.inverse(b.projection(i,r)),a=b.inverse(this.worldMatrix),o=b.multiply(a,n);this.viewProjectionInvLocation&&t.uniformMatrix3fv(this.viewProjectionInvLocation,!1,new Float32Array(o)),this.zoomScaleLocation&&t.uniform1f(this.zoomScaleLocation,this.zoom),this.checkboardStyleLocation&&t.uniform1f(this.checkboardStyleLocation,this.gridType);const h=t.getAttribLocation(e,"a_Position");if(h===-1)throw new Error("Attribute a_Position not found in grid program");t.vertexAttribPointer(h,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(h),t.drawArrays(t.TRIANGLES,0,this.vertexCount),t.bindBuffer(t.ARRAY_BUFFER,null),t.disableVertexAttribArray(h)}destroy(){this.buffer&&(this.buffer=null)}hitTest(t,e){return!1}setUpUniforms(t,e){const i=new Float32Array([1,0,0,0,1,0,0,0,1]);this.viewProjectionInvLocation=t.getUniformLocation(e,"u_ViewProjectionInvMatrix"),this.zoomScaleLocation=t.getUniformLocation(e,"u_ZoomScale"),this.checkboardStyleLocation=t.getUniformLocation(e,"u_CheckboardStyle"),t.uniformMatrix3fv(this.viewProjectionInvLocation,!1,i),t.uniform1f(this.zoomScaleLocation,this.zoom),t.uniform1f(this.checkboardStyleLocation,1)}}const ye=.02,xe=20;class we{constructor(t,e,i,r){this.viewportX=0,this.viewportY=0,this.state=t,this.updateCameraPos=this.updateCameraPos.bind(this),this.updateZoom=this.updateZoom.bind(this),this.onWheel=this.onWheel.bind(this),this.worldToCamera=this.worldToCamera.bind(this),this.getWorldCoords=r,this.setWorldMatrix=e,this.updateWorldMatrix=i,this.updateReaction=m.reaction(()=>this.state.stateVector,()=>this.updateViewMatrix()),this.updateViewMatrix()}updateViewMatrix(){this.setWorldMatrix(this.state.canvasMatrix),this.updateWorldMatrix()}setViewPortDimension(t,e){this.state.width!==t&&this.state.setWidth(t),this.state.height!==e&&this.state.setHeight(e)}getBoundingBox(){const[t,e]=this.getWorldCoords(this.viewportX,this.viewportY),[i,r]=this.getWorldCoords(this.state.width+this.viewportX,this.state.height+this.viewportY);return new rt(t,e,i,r)}onWheel(t){t.preventDefault();const i=Math.exp(-t.deltaY*.003);this.updateZoom(t.clientX,t.clientY,i)}updateCameraPos(t,e){this.state.incrementPosition(t,e)}updateZoom(t,e,i){const[r,n]=this.getWorldCoords(t,e);this.state.setZoom(Math.min(xe,Math.max(ye,this.state.zoom*i)));const[a,o]=this.getWorldCoords(t,e);this.state.incrementPosition(r-a,n-o)}worldToCamera(t,e){const i=this.state.cameraMatrix,r=i[0]*t+i[1]*e+i[2],n=i[3]*t+i[4]*e+i[5];return[r,n]}dispose(){this.updateReaction&&(this.updateReaction(),this.updateReaction=void 0)}}const ve="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSIjYjNiM2IzIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjUgNmEyLjI1IDIuMjUgMCAwIDEgMi4yNS0yLjI1aDE2LjVBMi4yNSAyLjI1IDAgMCAxIDIyLjUgNnYxMmEyLjI1IDIuMjUgMCAwIDEtMi4yNSAyLjI1SDMuNzVBMi4yNSAyLjI1IDAgMCAxIDEuNSAxOHpNMyAxNi4wNlYxOGMwIC40MTQuMzM2Ljc1Ljc1Ljc1aDE2LjVBLjc1Ljc1IDAgMCAwIDIxIDE4di0xLjk0bC0yLjY5LTIuNjg5YTEuNSAxLjUgMCAwIDAtMi4xMiAwbC0uODguODc5bC45Ny45N2EuNzUuNzUgMCAxIDEtMS4wNiAxLjA2bC01LjE2LTUuMTU5YTEuNSAxLjUgMCAwIDAtMi4xMiAwem0xMC4xMjUtNy44MWExLjEyNSAxLjEyNSAwIDEgMSAyLjI1IDBhMS4xMjUgMS4xMjUgMCAwIDEtMi4yNSAwIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=",at=240;function Ce(s){return{x:s.x??0,y:s.y??0,sx:s.sx??1,sy:s.sy??1}}function $t(s){return s.children.map(Se)}function Se(s){return s instanceof mt?{type:"Img",id:s.seq,renderOrder:s.renderOrder,transform:Ce(s),width:s.width,height:s.height,fileId:s.fileId,children:s.children?.length?$t(s):void 0}:s instanceof j?{type:"Rect",id:s.seq,renderOrder:s.renderOrder,transform:Ce(s),width:s.width,height:s.height,color:s.color,children:s.children?.length?$t(s):void 0}:s instanceof pe?{type:"Grid",style:s.gridType}:{type:"Renderable",children:s.children?.length?$t(s):void 0}}function jt(s,t){const{gl:e}=s;return{version:1,canvas:{width:e.canvas.width,height:e.canvas.height,dpr:window.devicePixelRatio||1},camera:{x:s.camera.state.x,y:s.camera.state.y,zoom:s.camera.state.zoom},root:Se(s),files:t}}async function Vt(s,t,e,i){t.children.length=0,s.camera&&(t.camera.state.setZoom(s.camera.zoom),t.camera.state.setX(s.camera.x),t.camera.state.setY(s.camera.y));async function r(n,a){let o;switch(n.type){case"Rect":o=new j({x:n.transform.x,y:n.transform.y,width:n.width,height:n.height}),o.setScale(n.transform.sx,n.transform.sy),t.appendChild(o);break;case"Img":let h;try{h=s.files&&Array.isArray(s.files)?s.files.find(g=>g.id===n.fileId)?.dataURL??ve:ve,i&&i(h);const c=n.width,u=n.height,f=await Mi(h,c*n.transform.sx,u*n.transform.sy);o=new mt({x:n.transform.x,y:n.transform.y,src:f,width:c,height:u}),e(n.fileId).then(p=>{o.src=p.dataURL}).catch(p=>console.error("Image not loaded",p)),o.fileId=n.fileId??await Nt(h),o.setScale(n.transform.sx,n.transform.sy),t.appendChild(o),typeof n.renderOrder=="number"&&(o.renderOrder=n.renderOrder)}catch{console.error(`Failed to match image to restore with source: ${h}`)}finally{break}case"Grid":a instanceof pt&&(a.grid.gridType=n.style);break}if(n.children)for(const h of n.children)await r(h,o)}return await r(s.root,t),t}async function bi(s){const t=new Image;return t.crossOrigin="anonymous",new Promise((e,i)=>{t.onload=()=>e(t),t.onerror=r=>i(r),t.src=s})}async function Mi(s,t,e,i="#d6d6d6ff"){let r=null,n;s instanceof Blob?(r=URL.createObjectURL(s),n=r):n=s;try{let a=null;try{a=await bi(n)}catch{}const o=t&&t>0?t:a?.naturalWidth??at,h=e&&e>0?e:a?.naturalHeight??at,c=document.createElement("canvas");c.width=o,c.height=h;const u=c.getContext("2d");if(u.fillStyle=i,u.fillRect(0,0,o,h),a){const f=Math.min(o/a.naturalWidth,h/a.naturalHeight),p=a.naturalHeight*f,g=a.naturalWidth*f;let C=at,x=at;(at>p||at>g)&&(C=g,x=p);const M=Math.round((o-C)/2),S=Math.round((h-x)/2);u.drawImage(a,0,0,a.naturalWidth,a.naturalHeight,M,S,C,x)}return c.toDataURL("image/png")}finally{r&&URL.revokeObjectURL(r)}}const I=class I extends ge{constructor(e,i,r,n,a,o){super();D(this,G);D(this,H);D(this,J);D(this,ht);D(this,v);D(this,Y);D(this,ct);D(this,tt);D(this,$);D(this,Z);D(this,P);D(this,dt);D(this,Wt);D(this,lt);A(this,Z,!0),this.orderDirty=!0,this.renderList=[],A(this,G,e),A(this,H,r),A(this,J,i),A(this,$,new pe),A(this,v,e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1})),l(this,v).enable(l(this,v).BLEND),l(this,v).blendFunc(l(this,v).SRC_ALPHA,l(this,v).ONE_MINUS_SRC_ALPHA),l(this,v).getExtension("OES_standard_derivatives"),l(this,v).enable(l(this,v).DEPTH_TEST),l(this,v).depthFunc(l(this,v).LEQUAL),A(this,Y,Xt(l(this,v),ai,oi)),A(this,ct,Xt(l(this,v),di,li)),A(this,tt,Xt(l(this,v),hi,ci)),this.writeToStorage=n,this.saveImgFileToStorage=a,this.getContainerDimension=o,this.engine=this.engine.bind(this),this.getBoundingClientRect=this.getBoundingClientRect.bind(this),this.appendChild=this.appendChild.bind(this),this.addImageToCanvas=this.addImageToCanvas.bind(this),this.setShapeZOrder=this.setShapeZOrder.bind(this),this.toggleGrid=this.toggleGrid.bind(this),this.changeMode=this.changeMode.bind(this),this.getSelected=this.getSelected.bind(this),this.updateZoomByFixedAmount=this.updateZoomByFixedAmount.bind(this),this.assignEventListener=this.assignEventListener.bind(this),this.getWorldsCoordsFromCanvas=(p,g)=>ft(p,g,this);const h=(p,g)=>ft(p+this.camera.viewportX,g+this.camera.viewportY,this);this.exportState=this.exportState.bind(this),this.importState=this.importState.bind(this),this.clearChildren=this.clearChildren.bind(this),A(this,P,new mi(i,r,this.gl,l(this,Y),()=>this.worldMatrix,()=>this.children,this.getWorldsCoordsFromCanvas,h));const c=new gi({});A(this,ht,new we(c,this.setWorldMatrix,this.updateWorldMatrix,this.getWorldsCoordsFromCanvas)),A(this,Wt,new xi(i,r,()=>this.selectionManager.deleteSelected(this),this.assignEventListener)),A(this,lt,new wi(r,this.selectionManager.isMultiBoundingBoxHit,this.selectionManager.isBoundingBoxHit,this.getWorldsCoordsFromCanvas,this.assignEventListener));const u=new Ci,f={history:i,eventHub:r,state:u,isContextMenuActive:()=>l(this,lt).isActive,getSelected:()=>l(this,P).selected,getChildren:()=>this.children,getWorldMatrix:()=>this.worldMatrix,getCanvasGlobalClick:()=>this.isGlobalClick,setCanvasGlobalClick:p=>this.isGlobalClick=p,getWorldCoords:this.getWorldsCoordsFromCanvas,updateCameraPos:this.camera.updateCameraPos,onWheel:this.camera.onWheel,setCursorStyle:p=>e.style.cursor=p,paste:(p,g)=>oe(p,g,this,i),assignEventListener:this.assignEventListener,closeMarquee:l(this,P).clearMarquee,selectionPointerMove:(p,g,C,x,M)=>l(this,P).onPointerMove(p,g,C,x,M,()=>this.isGlobalClick,this.camera.updateCameraPos,()=>this.worldMatrix),onSelectionPointerDown:this.selectionManager.onSelectionPointerDown,checkIfSelectionHit:this.selectionManager.hitTest,addSelection:this.selectionManager.add,clearSelection:this.selectionManager.clear,isSelection:this.selectionManager.isRectSelected,hitTestAdjustedCorner:this.selectionManager.hitTestAdjustedCorner};A(this,dt,new yi(f)),l(this,H).on("save",this.writeToStorage)}markOrderDirty(){this.orderDirty=!0}get gl(){return l(this,v)}get grid(){return l(this,$)}get history(){return l(this,J)}get eventHub(){return l(this,H)}get pointerEventManager(){return l(this,dt)}get selectionManager(){return l(this,P)}get contextMenuManager(){return l(this,lt)}get canvas(){return l(this,G)}get camera(){return l(this,ht)}get isGlobalClick(){return l(this,Z)}set isGlobalClick(e){A(this,Z,e)}get basicShapeProgram(){return l(this,Y)}engine(){return this}get totalNumberOfChildren(){return this.children.length}get numberOfChildrenRendered(){return this.renderList.length}appendChild(e){if(super.appendChild(e),e instanceof nt){const i=this.children.map(n=>n.renderOrder),r=i.length?Math.max(...i):0;e.renderOrder=r+1}return this.markOrderDirty(),e}removeChild(e){this.state.removeChild(e),l(this,P)&&l(this,P).remove([e]),e.destroy(),this.markOrderDirty()}getChild(e){return this.state.getChild(e)}updateWorldMatrix(){l(this,$).updateWorldMatrix(this.worldMatrix),this.children.forEach(e=>{e.updateWorldMatrix(this.worldMatrix)}),l(this,P).update()}render(){l(this,v).clearColor(0,0,0,0),l(this,v).clear(l(this,v).COLOR_BUFFER_BIT|l(this,v).DEPTH_BUFFER_BIT),l(this,v).viewport(0,0,l(this,v).canvas.width,l(this,v).canvas.height);const e=this.canvas.parentElement.getBoundingClientRect();this.camera.setViewPortDimension(e.width,e.height),l(this,v).useProgram(l(this,tt));const i=l(this,v).getUniformLocation(l(this,tt),"u_z");l(this,v).uniform1f(i,0),l(this,$).render(l(this,v),l(this,tt));const r=this.camera.getBoundingBox();this.renderList=[];for(const n of this.children)rt.isColliding(r,n.getBoundingBox())?(this.renderList.push(n),n.culled=!1):n.culled=!0;this.renderList.forEach(n=>{if(n instanceof mt){const a=n.determineIfLowRes(r,this.camera.state.zoom);n.setUseLowRes(a,this.gl)}});for(const n of this.renderList){let a;n instanceof mt?a=l(this,ct):n instanceof nt&&(a=l(this,Y)),l(this,v).useProgram(a);const o=l(this,v).getUniformLocation(a,"u_z");l(this,v).uniform1f(o,n.getZ()),n.render(l(this,v),a)}l(this,P).render(l(this,Y))}destroy(){l(this,v).deleteProgram(l(this,Y)),l(this,v).deleteProgram(l(this,ct)),this.children.forEach(e=>{"destroy"in e&&e.destroy()}),this.clearChildren()}getDOM(){return l(this,G)}assignEventListener(e,i,r){l(this,G).addEventListener(e,i,r)}hitTest(e,i){return A(this,Z,!0),l(this,Z)}async addImageToCanvas(e,i,r,n=1,a=1,o=!1){const h=new mt({x:i,y:r,src:e,sx:n,sy:a});if(this.saveImgFileToStorage(e).then(c=>h.fileId=c),o){const c=new Image;c.src=e.startsWith("data:image/png")?e:await ne(e),c.onload=()=>{const u=c.naturalWidth||c.width||0,f=c.naturalHeight||c.height||0;(u||f)&&h.updateTranslation(-u/2,-f/2),h.src=c.src,this.appendChild(h)}}return l(this,H).emit("save"),l(this,H).emit(N.Change),h}exportState(){return jt(this)}async importState(e,i){return await Vt(e,this,i)}clearChildren(){this.selectionManager.clear(),this.state.clearChildren(),l(this,J).clear()}toggleGrid(){l(this,$).changeGridType(l(this,$).gridType===_t.GRID?_t.NONE:_t.GRID)}getSelected(){return l(this,P).selected}setShapeZOrder(e=!0){if(l(this,P).multiBoundingBox||l(this,P).boundingBoxes.size!=1)return;const i=Array.from(l(this,P).boundingBoxes)[0].target,r={ref:i,start:{renderOrder:i.renderOrder}},n=this.children.map(h=>h.renderOrder);if(n.length===0)throw new Error("Order unexpected missing.");const a=Math.max(...n),o=Math.min(...n);i.renderOrder=e?a+1:o-1,r.end={renderOrder:i.renderOrder},this.markOrderDirty(),l(this,J).push(vi([r])),l(this,H).emit(N.Change)}changeMode(){l(this,dt).changeMode(),l(this,P).clear()}updateZoomByFixedAmount(e=1){l(this,ht).updateZoom(l(this,G).width/2,l(this,G).height/2,Math.exp(.5*.3*e))}getBoundingClientRect(){return l(this,G).getBoundingClientRect()}wrapWebGLContext(e){const i=e.createTexture.bind(e);e.createTexture=()=>(I.webglStats.texturesCreated++,console.log(`Textures created: ${I.webglStats.texturesCreated}`),i());const r=e.deleteTexture.bind(e);e.deleteTexture=o=>(o&&(I.webglStats.texturesDeleted++,console.log(`Textures deleted: ${I.webglStats.texturesDeleted}`)),r(o));const n=e.createShader.bind(e);e.createShader=o=>(I.webglStats.shadersCreated++,console.log(`Shaders created: ${I.webglStats.shadersCreated}`),n(o));const a=e.deleteShader.bind(e);return e.deleteShader=o=>(o&&(I.webglStats.shadersDeleted++,console.log(`Shaders deleted: ${I.webglStats.shadersDeleted}`)),a(o)),e}static getWebGLStats(){return{...I.webglStats,buffersLeaked:I.webglStats.buffersCreated-I.webglStats.buffersDeleted,programsLeaked:I.webglStats.programsCreated-I.webglStats.programsDeleted,texturesLeaked:I.webglStats.texturesCreated-I.webglStats.texturesDeleted,shadersLeaked:I.webglStats.shadersCreated-I.webglStats.shadersDeleted}}};G=new WeakMap,H=new WeakMap,J=new WeakMap,ht=new WeakMap,v=new WeakMap,Y=new WeakMap,ct=new WeakMap,tt=new WeakMap,$=new WeakMap,Z=new WeakMap,P=new WeakMap,dt=new WeakMap,Wt=new WeakMap,lt=new WeakMap,I.webglStats={buffersCreated:0,buffersDeleted:0,programsCreated:0,programsDeleted:0,texturesCreated:0,texturesDeleted:0,shadersCreated:0,shadersDeleted:0};let pt=I;const be=25;class Ei{constructor(){this._undoStack=[],this._redoStack=[],this._openGroup=null}get undoStack(){return this._undoStack}begin(t){if(this._openGroup)throw new Error("History group already open");this._openGroup=[],this._openLabel=t}push(t){if(this._openGroup)this._openGroup.push(t);else{for(;this._undoStack.length>=be;)this._undoStack.shift();this._undoStack.push([t]),t.do(),this._redoStack.length=0}}commit(){if(!this._openGroup)return;const t=this._openGroup;this._openGroup=null;for(const e of t)e.do();for(;this._undoStack.length>=be;)this._undoStack.shift();this._undoStack.push(t),this._redoStack.length=0,this._openLabel=void 0}cancel(){this._openGroup=null,this._openLabel=void 0}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}undo(){const t=this._undoStack.pop();if(t){for(let e=t.length-1;e>=0;e--)t[e].undo();this._redoStack.push(t)}}redo(){const t=this._redoStack.pop();if(t){for(const e of t)e.do();this._undoStack.push(t)}}clear(){this._undoStack.length=0,this._redoStack.length=0,this._openGroup=null,this._openLabel=void 0}}const Ti=s=>(t,e)=>{e!==void 0?e.addInitializer((()=>{customElements.define(s,t)})):customElements.define(s,t)};const It=globalThis,qt=It.ShadowRoot&&(It.ShadyCSS===void 0||It.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Me=Symbol(),Ee=new WeakMap;let _i=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==Me)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(qt&&t===void 0){const i=e!==void 0&&e.length===1;i&&(t=Ee.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&Ee.set(e,t))}return t}toString(){return this.cssText}};const Ii=s=>new _i(typeof s=="string"?s:s+"",void 0,Me),Ri=(s,t)=>{if(qt)s.adoptedStyleSheets=t.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet));else for(const e of t){const i=document.createElement("style"),r=It.litNonce;r!==void 0&&i.setAttribute("nonce",r),i.textContent=e.cssText,s.appendChild(i)}},Te=qt?s=>s:s=>s instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return Ii(e)})(s):s;const{is:Pi,defineProperty:Ai,getOwnPropertyDescriptor:Oi,getOwnPropertyNames:Li,getOwnPropertySymbols:Di,getPrototypeOf:Bi}=Object,Rt=globalThis,_e=Rt.trustedTypes,zi=_e?_e.emptyScript:"",ki=Rt.reactiveElementPolyfillSupport,yt=(s,t)=>s,Zt={toAttribute(s,t){switch(t){case Boolean:s=s?zi:null;break;case Object:case Array:s=s==null?s:JSON.stringify(s)}return s},fromAttribute(s,t){let e=s;switch(t){case Boolean:e=s!==null;break;case Number:e=s===null?null:Number(s);break;case Object:case Array:try{e=JSON.parse(s)}catch{e=null}}return e}},Ie=(s,t)=>!Pi(s,t),Re={attribute:!0,type:String,converter:Zt,reflect:!1,useDefault:!1,hasChanged:Ie};Symbol.metadata??=Symbol("metadata"),Rt.litPropertyMetadata??=new WeakMap;class xt extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=Re){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),r=this.getPropertyDescriptor(t,i,e);r!==void 0&&Ai(this.prototype,t,r)}}static getPropertyDescriptor(t,e,i){const{get:r,set:n}=Oi(this.prototype,t)??{get(){return this[e]},set(a){this[e]=a}};return{get:r,set(a){const o=r?.call(this);n?.call(this,a),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??Re}static _$Ei(){if(this.hasOwnProperty(yt("elementProperties")))return;const t=Bi(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(yt("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(yt("properties"))){const e=this.properties,i=[...Li(e),...Di(e)];for(const r of i)this.createProperty(r,e[r])}const t=this[Symbol.metadata];if(t!==null){const e=litPropertyMetadata.get(t);if(e!==void 0)for(const[i,r]of e)this.elementProperties.set(i,r)}this._$Eh=new Map;for(const[e,i]of this.elementProperties){const r=this._$Eu(e,i);r!==void 0&&this._$Eh.set(r,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const r of i)e.unshift(Te(r))}else t!==void 0&&e.push(Te(t));return e}static _$Eu(t,e){const i=e.attribute;return i===!1?void 0:typeof i=="string"?i:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Ri(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((t=>t.hostConnected?.()))}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),r=this.constructor._$Eu(t,i);if(r!==void 0&&i.reflect===!0){const n=(i.converter?.toAttribute!==void 0?i.converter:Zt).toAttribute(e,i.type);this._$Em=t,n==null?this.removeAttribute(r):this.setAttribute(r,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,r=i._$Eh.get(t);if(r!==void 0&&this._$Em!==r){const n=i.getPropertyOptions(r),a=typeof n.converter=="function"?{fromAttribute:n.converter}:n.converter?.fromAttribute!==void 0?n.converter:Zt;this._$Em=r;const o=a.fromAttribute(e,n.type);this[r]=o??this._$Ej?.get(r)??o,this._$Em=null}}requestUpdate(t,e,i){if(t!==void 0){const r=this.constructor,n=this[t];if(i??=r.getPropertyOptions(t),!((i.hasChanged??Ie)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,e,i)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:r,wrapped:n},a){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,a??e??this[t]),n!==!0||a!==void 0)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),r===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[r,n]of this._$Ep)this[r]=n;this._$Ep=void 0}const i=this.constructor.elementProperties;if(i.size>0)for(const[r,n]of i){const{wrapped:a}=n,o=this[r];a!==!0||this._$AL.has(r)||o===void 0||this.C(r,void 0,n,o)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach((i=>i.hostUpdate?.())),this.update(e)):this._$EM()}catch(i){throw t=!1,this._$EM(),i}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach((e=>e.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach((e=>this._$ET(e,this[e]))),this._$EM()}updated(t){}firstUpdated(t){}}xt.elementStyles=[],xt.shadowRootOptions={mode:"open"},xt[yt("elementProperties")]=new Map,xt[yt("finalized")]=new Map,ki?.({ReactiveElement:xt}),(Rt.reactiveElementVersions??=[]).push("2.1.1");class Pe{constructor(t,e){this.options=[],this.rootNode=e,this._el=document.createElement("div"),this._el.classList.add("context-menu"),t.options.forEach((i,r)=>{this.createOptionGroup(i),r!==t.options.length-1&&this.addDivider()}),this._el.addEventListener("contextmenu",i=>{i.preventDefault()})}get el(){return this._el}attachToParent(t){t.appendChild(this.el)}createOptionGroup(t){const e=new Ui(t,this.rootNode);this.options.push(e),this.el.appendChild(e.el)}addDivider(){const t=document.createElement("hr");t.classList.add("context-menu-divider"),this.el.appendChild(t)}}class Ui{constructor(t,e){this.childOptions=[],this.rootNode=e,this._el=document.createElement("div"),this.createOptionElement=this.createOptionElement.bind(this),t.childOptions.forEach(i=>this.createOptionElement(i))}get el(){return this._el}attachToParent(t){t.appendChild(this.el)}createOptionElement(t){t.parent=this;const e=new Wi(t,this.rootNode);this.childOptions.push(e)}}class Wi{get el(){return this._el}constructor(t,e){this.displayText=t.text,this.rootNode=e,this.parent=t.parent,this._el=document.createElement("button"),this._el.textContent=t.text,this._el.classList.add("context-menu-option"),this.parent.el.appendChild(this._el),"onClick"in t&&this._el.addEventListener("click",t.onClick),this._el.addEventListener("pointerenter",i=>Fi(i,t,this._el,this.rootNode)),this._el.addEventListener("contextmenu",i=>{i.preventDefault()})}}function Fi(s,t,e,i){if(!i)return;const r=i.querySelector(".sub-context-menu");if(r&&r.remove(),t.subMenu){const n=new Pe(t.subMenu,this);i.appendChild(n.el),n.el.id=`${t.text}-context-menu`,n.el.classList.add("sub-context-menu");const a=i.getBoundingClientRect(),o=e.getBoundingClientRect(),h=n.el.getBoundingClientRect(),c=a.right-a.left,u=a.bottom-a.top,f=o.right+h.width;o.top+h.height>u?n._el.style.top=`${o.bottom-h.height}px`:n._el.style.top=`${o.top}px`,f>c?n._el.style.left=`${o.left-h.width}px`:n._el.style.left=`${o.right}px`}}const Pt=5;function At(s){const t=this;return function(...e){const i=s.apply(t,e);return t.clearContextMenu(),i}}function Gi(s,t,e="single"){const i=new Pe(e==="single"?this.singleImageMenuOptions:e==="multi"?this.multiImageMenuOptions:this.canvasImageMenuOptions,this.rootDiv);if(!this.rootDiv){console.error("Can't add to parent div");return}i.attachToParent(this.rootDiv);const r=this.getBoundingClientRect(),n=s-r.left,a=t-r.top,o=r.right-r.left,h=r.bottom-r.top,c=i.el.getBoundingClientRect(),u=[n+c.width>o?1:0,a+c.height>h?1:0],f=c.height*u[1],p=c.width*u[0];if(f>h){const g=h-2*Pt;i._el.style.height=`${g}px`,i._el.style.top=`${Pt}px`}else i._el.style.top=`${a-f}px`;p>o?(i._el.style.width=`${o-2*Pt}px`,i._el.style.left=`${Pt}px`):i._el.style.left=`${n-p}px`}function Xi(){const s=this.renderRoot.querySelector(".context-menu");s&&(s.remove(),this.eventHub.emit(X.Close))}function Ni(){return this.renderRoot.querySelector(".context-menu")!==null}function Hi(){const s=At.bind(this);return{options:[{childOptions:[{text:"Cut",onClick:async()=>{await this.copyImage.bind(this)(),s(this.deleteSelectedImages.bind(this))()}},{text:"Copy",onClick:s(this.copyImage.bind(this))},{text:"Paste",onClick:t=>s(this.pasteImage.bind(this))(t)},{text:"Delete",onClick:s(this.deleteSelectedImages.bind(this))}]},{childOptions:[{text:"Flip Horizontal",onClick:s(this.flipHorizontal.bind(this))},{text:"Flip Vertical",onClick:s(this.flipVertical.bind(this))}]}]}}function Yi(s){const t=At.bind(this);return{options:[...s??[],{childOptions:[{text:"Send to Front",onClick:()=>t(this.sendShapeToNewZOrder.bind(this))(!0)},{text:"Send to Back",onClick:()=>t(this.sendShapeToNewZOrder.bind(this))(!1)}]}]}}function $i(s){const t=At.bind(this);return{options:[...s??[],{childOptions:[{text:"Align",onHover:()=>{},subMenu:{options:[{childOptions:[{text:"Align Left",onClick:()=>t(this.align.bind(this))("left")},{text:"Align Right",onClick:()=>t(this.align.bind(this))("right")},{text:"Align Top",onClick:()=>t(this.align.bind(this))("top")},{text:"Align Bottom",onClick:()=>t(this.align.bind(this))("bottom")}]}]}},{text:"Normalize by First",onHover:()=>{},subMenu:{options:[{childOptions:[{text:"Height",onClick:()=>t(this.normalizeSelection.bind(this))("height","first")},{text:"Width",onClick:()=>t(this.normalizeSelection.bind(this))("width","first")},{text:"Size",onClick:()=>t(this.normalizeSelection.bind(this))("size","first")},{text:"Scale",onClick:()=>t(this.normalizeSelection.bind(this))("scale","first")}]}]}},{text:"Normalize by Average",onHover:()=>{},subMenu:{options:[{childOptions:[{text:"Height",onClick:()=>t(this.normalizeSelection.bind(this))("height","average")},{text:"Width",onClick:()=>t(this.normalizeSelection.bind(this))("width","average")},{text:"Size",onClick:()=>t(this.normalizeSelection.bind(this))("size","average")},{text:"Scale",onClick:()=>t(this.normalizeSelection.bind(this))("scale","average")}]}]}}]}]}}function ji(s){const t=At.bind(this);return{options:[...s??[],{childOptions:[{text:"Change mode",onClick:()=>t(this.togglePointerMode.bind(this))()},{text:"Toggle Grid",onClick:()=>t(this.toggleGrid.bind(this))()}]},{childOptions:[{text:"Save",onClick:()=>t(this.saveToCanvasStorage.bind(this))()},{text:"Paste",onClick:e=>t(this.pasteImage.bind(this))(e)}]}]}}class Kt{_touch(){this._lastRetrieved=Date.now()}get id(){return this._touch(),this._id}get dataURL(){return this._touch(),this._dataURL}get mimetype(){return this._touch(),this._mimetype}get created(){return this._touch(),this._created}get lastRetrieved(){return this._lastRetrieved}constructor(t){this._dataURL=t,this._mimetype=Ze(t),this._created=Date.now(),this._lastRetrieved=Date.now()}static async create(t){const e=new Kt(t);return e._id=await Nt(t),e}}class Vi{}class qi{}function Ae(s){s.Version.prototype._parseStoresSpec=k.override(s.Version.prototype._parseStoresSpec,Zi),s.open=k.override(s.open,Qi(s))}function Zi(s){return function(t,e){s.call(this,t,e),Object.keys(e).forEach(function(i){let r=e[i];r.primKey.name.indexOf("$$")===0&&(r.primKey.uuid=!0,r.primKey.name=r.primKey.name.substr(2),r.primKey.keyPath=r.primKey.keyPath.substr(2))})}}function Ki(s){return function(e,i){let r;return e===void 0&&s.schema.primKey.uuid&&(e=r=Ge.v4(),s.schema.primKey.keyPath&&k.setByKeyPath(i,s.schema.primKey.keyPath,e)),r}}function Qi(s){return function(e){return function(){return Object.keys(s._allTables).forEach(i=>{let r=s._allTables[i];r.hook("creating").subscribe(Ki(r))}),e.apply(this,arguments)}}}k.UUIDPrimaryKey=Ae,k.addons.push(Ae),k.UUIDPrimaryKey;const Ji={files:"$$id, mimetype, created, lastRetrieved"},Oe={MAX_IMAGE_ENTRIES:1e3};class Ot extends Vi{constructor(){super(),this.dbQueue=new De,this.cache=new Map,this.CACHE_LIMIT=500,this.dbQueue=new De,this.dbPromise=this.initDb()}async initDb(){return V(async()=>{let t=new k("InfiniteCanvas");return k.UUIDPrimaryKey(t),t.version(1).stores(Ji),await t.open(),t})}async getIndexDb(){return this.dbPromise}async write(t){const e=await Kt.create(t),i=is(e.dataURL);return this.dbQueue.add(()=>V(async()=>{const r=await this.getIndexDb();return await r.transaction("rw",r.files,async()=>(await es(r),await r.files.add({id:e.id,blob:i,dataURL:e.dataURL,mimetype:e.mimetype,created:e.created,lastRetrieved:e.lastRetrieved}))).catch(n=>{throw console.error("Failed to save image blob to local DB:",n),n})}))}async readAll(){return V(async()=>await(await this.getIndexDb()).files.toArray())}async readPage(t,e){return V(async()=>await(await this.getIndexDb()).files.offset(t).limit(e).toArray())}async read(t){return V(async()=>{const e=await this.getIndexDb();if(this.cache.has(t))return this.cache.get(t);const i=await e.files.get(t);if(!i)return null;if(this.dbQueue.add(async()=>{try{await e.files.update(t,{lastRetrieved:Date.now()})}catch(r){console.error("Failed to update lastRetrieved",r)}}).catch(()=>{}),this.cache.set(t,i),this.cache.size>this.CACHE_LIMIT){const r=this.cache.keys().next().value;this.cache.delete(r)}return i})}async delete(t){return this.dbQueue.add(()=>V(async()=>{const e=await this.getIndexDb();return await e.transaction("rw",e.files,async()=>{const i=await e.files.where("id").equals(t).first();return await e.files.delete(i.id),i}).catch(i=>{throw console.error("Failed to save image blob to local DB:",i),i})}))}async update(t){return this.dbQueue.add(()=>V(async()=>{const e=await this.getIndexDb();return await e.transaction("rw",e.files,async()=>{await e.files.update(t.id,{dataURL:t.dataURL,mimetype:t.mimetype,lastRetrieved:Date.now()})}),await e.files.where("id").equals(t.id).first()}))}async checkIfImageStored(t){return V(async()=>{const i=await(await this.getIndexDb()).files.where("id").equals(t).first();return i?i.id:null})}}class Qt extends qi{constructor(t){super(),this.key="infinite_canvas",this.key=t}async write(t){return new Promise((e,i)=>{try{localStorage.setItem(this.key,JSON.stringify(t)),e()}catch(r){i(r)}})}async read(){return new Promise((t,e)=>{try{t(localStorage.getItem(this.key))}catch(i){e(i)}})}async delete(){return new Promise((t,e)=>{try{localStorage.removeItem(this.key),t()}catch(i){e(i)}})}async update(t){return this.write(t)}}class Le extends Error{constructor(t){super(t),this.name="QuotaExceededError"}}class ts extends Error{constructor(t){super(t),this.name="DatabaseLimitError"}}class De{constructor(){this.queue=Promise.resolve()}async add(t){const e=this.queue.then(()=>t());return this.queue=e.catch(()=>{}),e}}const V=async s=>{try{return await s()}catch(t){throw t instanceof DOMException&&t.name==="QuotaExceededError"?new Le("Storage quota exceeded. Please free up space."):t instanceof k.QuotaExceededError?new Le("Database quota exceeded. Please free up space."):t}};async function es(s){if(await s.files.count()>=Oe.MAX_IMAGE_ENTRIES)throw new ts(`Cannot save image: limit of ${Oe.MAX_IMAGE_ENTRIES} reached`)}function is(s){const t=s.split(","),e=t[0],i=t[1],r=e.match(/:(.*?);/),n=r?r[1]:"application/octet-stream",a=atob(i),o=a.length,h=new Uint8Array(o);for(let c=0;c<o;c++)h[c]=a.charCodeAt(c);return new Blob([h],{type:n})}class ss{get el(){return this._el}constructor(t){this.type=t.type,this.message=t.message,this._el=document.createElement("div"),this._el.classList.add("canvas-loader"),this.render()}render(){if(this._el.innerHTML="",this.type==="spinner"){const t=document.createElement("div");if(t.classList.add("canvas-loader-spinner"),this._el.appendChild(t),this.message){const e=document.createElement("div");e.classList.add("canvas-loader-message"),e.textContent=this.message,this._el.appendChild(e)}}else if(this.type==="message"){const t=document.createElement("div");t.classList.add("canvas-loader-message"),t.textContent=this.message??"",this._el.appendChild(t)}}setMessage(t){this.message=t,this.render()}setProgress(t){this.progress=t,this.render()}attachToParent(t){t.appendChild(this.el)}remove(){this._el.parentNode&&this._el.parentNode.removeChild(this._el)}}function rs(s,t){const e=new ss({type:s,message:t});e.attachToParent(this.renderRoot);const i=this.getBoundingClientRect();return e.el.style.width=`${i.right}px`,e.el.style.height=`${i.bottom}px`,e._el.style.top=`${-i.bottom}px`,e}function ns(){const s=this.renderRoot.querySelector(".canvas-loader");s&&s.remove()}var as=Object.getOwnPropertyDescriptor,Be=s=>{throw TypeError(s)},os=(s,t,e,i)=>{for(var r=i>1?void 0:i?as(t,e):t,n=s.length-1,a;n>=0;n--)(a=s[n])&&(r=a(r)||r);return r},ze=(s,t,e)=>t.has(s)||Be("Cannot "+e),d=(s,t,e)=>(ze(s,t,"read from private field"),e?e.call(s):t.get(s)),B=(s,t,e)=>t.has(s)?Be("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),T=(s,t,e,i)=>(ze(s,t,"write to private field"),t.set(s,e),e),y,_,Lt,q,O,F,wt,Dt,vt,Q,ot,Bt,zt,kt;w.InfiniteCanvasElement=class extends z.LitElement{constructor(){super(...arguments),this.name="Reffy",this.displayMode="fullscreen",B(this,y),B(this,_),B(this,Lt),B(this,q),B(this,O),B(this,F),B(this,wt,3e5),B(this,Dt),B(this,vt),B(this,Q),B(this,ot),B(this,Bt),B(this,zt),B(this,kt),this.handleGlobalPointerDown=t=>{!this.contains(t.target)&&!this.renderRoot.contains(t.target)&&this.clearContextMenu()}}get singleImageMenuOptions(){return d(this,Bt)}get multiImageMenuOptions(){return d(this,zt)}get canvasImageMenuOptions(){return d(this,kt)}get canvas(){return d(this,y)}get onCanvasChange(){return d(this,ot)}set onCanvasChange(t){T(this,ot,t)}get eventHub(){return d(this,_)}get rootDiv(){return d(this,Q)}connectedCallback(){super.connectedCallback(),this.handleGlobalPointerDown=this.handleGlobalPointerDown.bind(this),document.addEventListener("pointerdown",this.handleGlobalPointerDown,!0)}disconnectedCallback(){document.removeEventListener("pointerdown",this.handleGlobalPointerDown,!0),d(this,Lt)?.disconnect(),T(this,Lt,void 0),d(this,y).destroy(),super.disconnectedCallback()}firstUpdated(t){try{this.initCanvas()}catch(e){throw console.error(e),e}}updated(t){if(!(t.has("width")||t.has("height")||t.has("displayMode")))return;const i=d(this,Q),r=this.renderRoot.querySelector("canvas");i&&r&&this.resizeCanvas(i,r)}async initCanvas(){await this.warmUpStorage(),T(this,q,new Ei),T(this,_,new Xe);const t=document.createElement("div");t.style.overflow="hidden",this.renderRoot.appendChild(t),T(this,Q,t);const e=document.createElement("canvas");this.assignFileStorage=this.assignFileStorage.bind(this),this.getImageFileMetadata=this.getImageFileMetadata.bind(this),this.getAllImageFileMetdata=this.getAllImageFileMetdata.bind(this),this.saveImageFileMetadata=this.saveImageFileMetadata.bind(this),this.restoreStateFromCanvasStorage=this.restoreStateFromCanvasStorage.bind(this),this.assignCanvasStorage=this.assignCanvasStorage.bind(this),this.saveToCanvasStorage=this.saveToCanvasStorage.bind(this),this.debounceSaveToCanvasStorage=this.debounceSaveToCanvasStorage.bind(this),this.importCanvas=this.importCanvas.bind(this),this.exportCanvas=this.exportCanvas.bind(this),this.addContextMenu=Gi.bind(this),this.clearContextMenu=Xi.bind(this),this.isContextMenuActive=Ni.bind(this),this.getContainerSize=this.getContainerSize.bind(this),t.contains(e)||t.appendChild(e),this.registerSignal(),T(this,y,new pt(e,d(this,q),d(this,_),this.debounceSaveToCanvasStorage,this.saveImageFileMetadata,this.getContainerSize));try{await this.restoreStateFromCanvasStorage()}catch{console.error("Failed to restore canvas")}this.resizeCanvas(t,e);const i=Hi.bind(this)();T(this,Bt,Yi.bind(this)(i.options)),T(this,kt,ji.bind(this)()),T(this,zt,$i.bind(this)(i.options)),this.dispatchEvent(new Event("load"));const r=new Ne;r.showPanel(0),this.renderRoot.contains(r.dom)||this.renderRoot.appendChild(r.dom);const n=()=>{r&&r.update(),d(this,y).render(),requestAnimationFrame(n)};n()}normalizeCssSize(t){if(!t)return t;const e=String(t).trim();return/^\d+$/.test(e)?`${e}px`:e}resizeCanvas(t,e){t.style.width=this.displayMode==="fullscreen"?"100vw":this.normalizeCssSize(this.width),t.style.height=this.displayMode==="fullscreen"?"100vh":this.normalizeCssSize(this.height),t.style.overflow="hidden";const i=window.devicePixelRatio||1;let r=window.screen.width,n=window.screen.height;const a=Math.round(r*i),o=Math.round(n*i);(e.width!==a||e.height!==o)&&(e.width=a,e.height=o),e.style.width=`${r}px`,e.style.height=`${n}px`;const h=t.getBoundingClientRect();this.canvas.camera.viewportX=h.x,this.canvas.camera.viewportY=h.y,this.canvas.camera.state.setHeight(h.height),this.canvas.camera.state.setWidth(h.width)}registerSignal(){d(this,_).on(it.start,rs.bind(this),"spinner"),d(this,_).on(it.done,ns.bind(this)),d(this,_).on(X.Open,this.addContextMenu),d(this,_).on(X.Close,this.clearContextMenu),d(this,_).on(N.Change,()=>{d(this,ot)&&d(this,ot).call(this)}),d(this,_).on(st.Save,this.saveToCanvasStorage),d(this,_).on(st.SaveCompleted,()=>{}),d(this,_).on(st.SaveFailed,()=>console.error("Failed to Save!"))}async warmUpStorage(){d(this,O)||T(this,O,new Ot);try{await d(this,O).readAll()}catch(t){console.error("Storage warm-up failed",t)}}getContainerSize(){if(!d(this,Q))return;const t=d(this,Q).getBoundingClientRect();return[t.width,t.height]}assignCanvasStorage(t,e=d(this,wt)){T(this,F,t),T(this,wt,e),d(this,vt)&&clearInterval(d(this,vt)),T(this,vt,setInterval(this.saveToCanvasStorage,d(this,wt)))}assignFileStorage(t){T(this,O,t)}async saveImageFileMetadata(t){d(this,O)||T(this,O,new Ot);try{const e=await Nt(t);return await d(this,O).checkIfImageStored(e)?e:await d(this,O).write(t)}catch(e){console.error(e)}}async getImageFileMetadata(t){d(this,O)||T(this,O,new Ot);try{return await d(this,O).read(t)}catch(e){console.error(e)}}async getAllImageFileMetdata(){d(this,O)||T(this,O,new Ot);try{return await d(this,O).readAll()}catch(t){console.error(t)}}debounceSaveToCanvasStorage(t=1e3){d(this,F)||T(this,F,new Qt(this.name)),clearTimeout(d(this,Dt)),T(this,Dt,setTimeout(this.saveToCanvasStorage,t))}async saveToCanvasStorage(){d(this,F)||T(this,F,new Qt(this.name)),d(this,F).write(jt(d(this,y))).then(()=>d(this,_).emit(st.SaveCompleted)).catch(()=>d(this,_).emit(st.SaveFailed))}async restoreStateFromCanvasStorage(){d(this,F)||T(this,F,new Qt(this.name));const t=await d(this,F).read(),e=JSON.parse(t);e&&await Vt(e,d(this,y),this.getImageFileMetadata)}togglePointerMode(){d(this,y)&&d(this,y).changeMode()}toggleGrid(){d(this,y)&&d(this,y).toggleGrid()}zoomIn(){d(this,y)&&d(this,y).updateZoomByFixedAmount(-1)}zoomOut(){d(this,y)&&d(this,y).updateZoomByFixedAmount()}async addImages(t){if(!d(this,y))return;const e=d(this,y).getBoundingClientRect(),i=e.left+e.width/2,r=e.top+e.height/2,[n,a]=ft(i,r,d(this,y)),o=await Ke(t,h=>d(this,y).addImageToCanvas(h,n,a,1,1,!0));d(this,q).push(Tt(d(this,y),o))}async removeImage(t){if(!d(this,y))return;const e=d(this,y).getChild(t);d(this,y).removeChild(e),d(this,q).push(ei(d(this,y),e))}async addImageFromUrl(t){if(!d(this,y))return;const e=d(this,y).getBoundingClientRect(),i=e.left+e.width/2,r=e.top+e.height/2,[n,a]=ft(i,r,d(this,y)),o=await d(this,y).addImageToCanvas(t,n,a,1,1,!0);d(this,q).push(Tt(d(this,y),[o]))}async copyImage(){d(this,y)&&await ae(d(this,y).getSelected())}async pasteImage(t){d(this,y)&&await oe(t.clientX,t.clientY,d(this,y),d(this,q),!1)}flipVertical(){d(this,y)&&d(this,y).selectionManager.flip("vertical")}flipHorizontal(){d(this,y)&&d(this,y).selectionManager.flip("horizontal")}align(t){d(this,y)&&d(this,y).selectionManager.alignSelection(t)}normalizeSelection(t,e){d(this,y)&&d(this,y).selectionManager.normalize(t,e)}sendShapeToNewZOrder(t){d(this,y)&&d(this,y).setShapeZOrder(t)}deleteSelectedImages(){d(this,y)&&d(this,y).selectionManager.deleteSelected(d(this,y))}async exportCanvas(t="infinite-canvas.json"){if(!d(this,y))return;d(this,_).emit(it.start,"spinner");const e=await this.getAllImageFileMetdata(),i=jt(d(this,y),e);Qe(t,i),d(this,_).emit(it.done)}async importCanvas(t){if(d(this,_).emit(it.start,"spinner"),!d(this,y)||!t||t.length!==1)return;const e=t[0];if(!e.type||!e.type.includes("json")&&!e.name.toLowerCase().endsWith(".json"))return;const i=await Je(e);await Vt(i,d(this,y),this.getImageFileMetadata,this.saveImageFileMetadata),d(this,_).emit(st.Save),d(this,_).emit(it.done)}clearCanvas(){d(this,y)&&d(this,y).clearChildren()}getTotalNumberOfChildren(){if(d(this,y))return d(this,y).totalNumberOfChildren}getNumberOfChildrenRendered(){if(d(this,y))return d(this,y).numberOfChildrenRendered}},y=new WeakMap,_=new WeakMap,Lt=new WeakMap,q=new WeakMap,O=new WeakMap,F=new WeakMap,wt=new WeakMap,Dt=new WeakMap,vt=new WeakMap,Q=new WeakMap,ot=new WeakMap,Bt=new WeakMap,zt=new WeakMap,kt=new WeakMap,w.InfiniteCanvasElement.properties={name:{type:String,reflect:!0},width:{type:String,reflect:!0},height:{type:String,reflect:!0},displayMode:{type:String,reflect:!0}},w.InfiniteCanvasElement.styles=z.css`
|
|
147
|
+
`;var W=(s=>(s[s.ACTIVE=0]="ACTIVE",s[s.PASSIVE=1]="PASSIVE",s))(W||{});class ce{constructor(t,e){this.sides=new Map,this.corners=new Map,this.borderSize=0,this.boxSize=0,this.mode=W.ACTIVE,this.target=t,this.setDimension(),this.mode=e??W.ACTIVE,this.borderSize=Xt,this.boxSize=se/2,this.addSides(),this.mode===W.ACTIVE&&this.addCorners()}setDimension(){const t=this.target.getEdge();this.width=t.maxX-t.minX,this.height=t.maxY-t.minY}getSidesInScreenSpace(t,e){const[i,r]=e?Q(e):[1,1],{width:n,height:a,borderSize:o}=this,[h,c]=U(e),[l,u]=bt(e);return{TOP:{x:l>0?h:h-n*i,y:c,width:n*i,height:o},BOTTOM:{x:l>0?h:h-n*i,y:c+a*r*u,width:n*i,height:o},LEFT:{x:h,y:u>0?c:c-a*r,width:o,height:a*r},RIGHT:{x:h+n*i*l,y:u>0?c:c-a*r,width:o,height:a*r}}[t]}getCornersInScreenSpace(t,e){const[i,r]=e?Q(e):[1,1],{width:n,height:a,boxSize:o}=this,[h,c]=U(e),[l,u]=bt(e);return{TOPLEFT:{x:h-o,y:c-o,width:o*2,height:o*2},TOPRIGHT:{x:h-o+n*i*l,y:c-o,width:o*2,height:o*2},BOTTOMLEFT:{x:h-o,y:c-o+a*r*u,width:o*2,height:o*2},BOTTOMRIGHT:{x:h-o+n*i*l,y:c-o+a*r*u,width:o*2,height:o*2}}[t]}setPassive(){this.mode=W.PASSIVE,this.removeCorners()}setActive(){this.mode=W.ACTIVE,this.addCorners()}getPositions(){return this.target.getPositions()}hitTest(t,e,i){if(this.mode===W.PASSIVE)return;const[r,n]=Q(this.target.worldMatrix),[a,o]=bt(this.target.worldMatrix),[h,c]=U(i,t,e),l=4;for(const R of St){const T=this.getCornersInScreenSpace(R,this.target.worldMatrix);if(h>=T.x-l&&h<=T.x+T.width+l&&c>=T.y-l&&c<=T.y+T.height+l)return R}for(const R of ft){const T=this.getSidesInScreenSpace(R,this.target.worldMatrix);if(h>=T.x-l&&h<=T.x+T.width+l&&c>=T.y-l&&c<=T.y+T.height+l)return R}const[u,m]=U(this.target.worldMatrix),g=this.width*r*a,C=this.height*n*o,x=Math.min(u,u+g),E=Math.max(u,u+g),S=Math.min(m,m+C),L=Math.max(m,m+C);if(h>=x&&h<=E&&c>=S&&c<=L)return"CENTER"}update(){this.updateSides(),this.updateCorners()}render(t,e){this.update();for(const[i,r]of this.sides.entries())r.render(t,e);for(const[i,r]of this.corners.entries())r.render(t,e)}destroy(){for(const[t,e]of this.sides.entries())e.destroy();for(const[t,e]of this.corners.entries())e.destroy()}move(t,e){this.target.updateTranslation(t,e)}resize(t,e,i){if(this.target instanceof j){const r=Math.abs(this.width),n=Math.abs(this.height),a=r/n,o=this.target.sx,h=this.target.sy,c=1e-6,l=Math.abs(r*o)<c?c*Mt(r*o||1,c):r*o,u=Math.abs(n*h)<c?c*Mt(n*h||1,c):n*h,m=t/l,g=e/u,C=c,x=i==="LEFT"||i==="BOTTOMLEFT"||i==="TOPLEFT"?1-m:i==="RIGHT"||i==="BOTTOMRIGHT"||i==="TOPRIGHT"?1+m:i==="TOP"?1-g:1+g;if(Et(o,x,C)||Et(h,x,C))return;const E=r*o*x,S=n*h*x;if(Math.abs(E)<C||Math.abs(S)<C)return;if(this.target.updateScale(x,x),i==="LEFT"){const L=n*h,R=n*this.target.sy;this.target.updateTranslation(t,(L-R)/2)}else if(i==="RIGHT"){const L=n*h,R=n*this.target.sy;this.target.updateTranslation(0,(L-R)/2)}else if(i==="TOP"){const L=r*o,R=r*this.target.sx;this.target.updateTranslation((L-R)/2,e)}else if(i==="BOTTOM"){const L=r*o,R=r*this.target.sx;this.target.updateTranslation((L-R)/2,0)}else i==="BOTTOMLEFT"?this.target.updateTranslation(t,0):i==="TOPLEFT"?this.target.updateTranslation(t,t/a*Math.sign(this.target.sx)):i==="TOPRIGHT"&&this.target.updateTranslation(0,-t/a*Math.sign(this.target.sx))}}reset(){this.target.setScale(1,1)}flip(t){const{x:e,y:i,sx:r,sy:n}=this.target;return t==="vertical"?this.target.flipVertical(this.height):this.target.flipHorizontal(this.width),{ref:this.target,start:{x:e,y:i,sx:r,sy:n},end:{x:this.target.x,y:this.target.y,sx:this.target.sx,sy:this.target.sy}}}addCorners(){for(const t of St){const e=new j(this.getCornersInScreenSpace(t,this.target.worldMatrix));e.color=this.mode===W.ACTIVE?st:Tt,this.corners.set(t,e)}}removeCorners(){this.corners.clear()}updateCorners(){for(const t of St){const e=this.getCornersInScreenSpace(t,this.target.worldMatrix),i=this.corners.get(t);i&&(i.setTranslation(e.x,e.y),i.width=e.width,i.height=e.height,i.color=this.mode===W.ACTIVE?st:Tt)}}addSides(){for(const t of ft){const e=new j(this.getSidesInScreenSpace(t,this.target.worldMatrix));e.color=this.mode===W.ACTIVE?st:Tt,this.sides.set(t,e)}}updateSides(){for(const t of ft){const e=this.getSidesInScreenSpace(t,this.target.worldMatrix),i=this.sides.get(t);i&&(i.setTranslation(e.x,e.y),i.width=e.width,i.height=e.height,i.color=this.mode===W.ACTIVE?st:Tt)}}}const Yt=[...St,...ft];class fi{constructor(t){this.targets=[],this.handles=new Map,this.borderSize=0,this.boxSize=0,this.scale=[1,1],t&&t.forEach(e=>this.add(e)),this.addHandles()}add(t){this.targets.includes(t)||this.targets.push(t)}remove(t){const e=this.targets.indexOf(t);e!=-1&&this.targets.splice(e,1)}render(t,e){this.update();for(const[i,r]of this.handles.entries())r.render(t,e)}update(){this.borderSize=Xt,this.boxSize=se/2,this.recalculateBounds(),this.updateHandles()}destroy(){for(const[t,e]of this.handles.entries())e.destroy()}move(t,e){for(const i of this.targets)i.updateTranslation(t,e)}resize(t,e,i,r){const n=this.width,a=this.height,o=i.includes("TOP"),h=i.includes("BOTTOM"),c=i.includes("LEFT"),l=i.includes("RIGHT"),u=c?this.x+n:l?this.x:this.x+n/2,m=o?this.y+a:h?this.y:this.y+a/2,g=1e-6,C=Math.abs(n)<g?n<0?-g:g:n,x=Math.abs(a)<g?a<0?-g:g:a,[E,S]=Q(r),L=t*E/C,R=e*S/x,T=i.includes("LEFT")?1-L:i.includes("RIGHT")?1+L:i==="TOP"?1-R:1+R;if(Et(this.scale[0],T,g)||Et(this.scale[1],T,g))return;const cs=n*T,ds=a*T;if(!(Math.abs(cs)<g||Math.abs(ds)<g))for(const Gt of this.targets){const ls=Gt.x,us=Gt.y,[Ue,We]=U(r,ls,us),fs=u+(Ue-u)*T,gs=m+(We-m)*T,ms=fs-Ue,ps=gs-We,ys=Math.abs(E)<g?E<0?-g:g:E,xs=Math.abs(S)<g?S<0?-g:g:S,ws=ms/ys,vs=ps/xs;Gt.updateScale(T,T),Gt.updateTranslation(ws,vs)}}flip(t,e,i){Q(t);const r=[],[n,a]=i(this.x,this.y);for(const o of this.targets){const h={ref:o,start:{x:o.x,y:o.y,sx:o.sx,sy:o.sy}};if(e==="vertical"){const c=o.height*o.sy;o.setTranslation(o.x,-o.y-c),o.flipVertical(o.height)}else{const c=o.width*o.sx;o.setTranslation(-o.x-c,o.y),o.flipHorizontal(o.width)}h.end={x:o.x,y:o.y,sx:o.sx,sy:o.sy},r.push(h)}return r}align(t){if(this.targets.length<=1)return;const e=[],i=[t==="top"?1:t==="bottom"?-1:0,t==="left"?1:t==="right"?-1:0];let r=i[0]!==0?1/0*i[0]:1/0*i[1];for(const[n,a]of this.targets.entries()){const o=a.getBoundingBox();r=t==="top"||t==="left"?Math.min(t==="top"?o.minY:o.minX,r):Math.max(t==="bottom"?o.maxY:o.maxX,r)}for(const n of this.targets){const a={ref:n,start:{x:n.x,y:n.y,sx:n.sx,sy:n.sy}},o=n.getBoundingBox();n.updateTranslation(t==="top"||t==="bottom"?0:r-(t==="left"?o.minX:o.maxX),t==="top"||t==="bottom"?r-(t==="top"?o.minY:o.maxY):0),a.end={x:n.x,y:n.y,sx:n.sx,sy:n.sy},e.push(a)}return e}normalize(t,e){const i=[],r=this.targets[0],n=t==="height"?e==="first"?r.height*r.sy:this.targets.reduce((a,o)=>a+Math.abs(o.height*o.sy),0)/this.targets.length:t==="width"?e==="first"?r.width*r.sx:this.targets.reduce((a,o)=>a+Math.abs(o.width*o.sx),0)/this.targets.length:t==="scale"?e==="first"?r.sx:this.targets.reduce((a,o)=>a+Math.abs(o.sx),0)/this.targets.length:e==="first"?r.width*r.height*r.sx*r.sy:this.targets.reduce((a,o)=>a+Math.abs(o.sx*o.width*o.height*o.sy),0)/this.targets.length;for(const a of this.targets){const o={ref:a,start:{x:a.x,y:a.y,sx:a.sx,sy:a.sy}},h=[(a.x+a.width*a.sx)/2,(a.y+a.height*a.sy)/2];if(t==="height"){const l=a.height*a.sy,u=Math.abs(n/l);a.updateScale(u,u)}else if(t==="width"){const l=a.width*a.sx,u=Math.abs(n/l);a.updateScale(u,u)}else if(t==="scale"){const l=Math.sign(a.sx),u=Math.sign(a.sy);a.setScale(n*l,n*u)}else if(t==="size"){const l=a.width*a.height*a.sx*a.sy,u=Math.sqrt(Math.abs(n/l));a.updateScale(u,u)}const c=[(a.x+a.width*a.sx)/2,(a.y+a.height*a.sy)/2];a.updateTranslation(h[0]-c[0],h[1]-c[1]),o.end={x:a.x,y:a.y,sx:a.sx,sy:a.sy},i.push(o)}return i}getPositions(){return[this.x,this.y,this.x+this.width,this.y,this.x+this.width,this.y+this.height,this.x,this.y+this.height]}hitTest(t,e,i){const[r,n]=U(i,t,e),a=4;for(const u of Yt){const m=this.getHandleConfig(u);if(r>=m.x-a&&r<=m.x+m.width+a&&n>=m.y-a&&n<=m.y+m.height+a)return u}const o=Math.min(this.x,this.x+this.width),h=Math.max(this.x,this.x+this.width),c=Math.min(this.y,this.y+this.height),l=Math.max(this.y,this.y+this.height);if(r>=o&&r<=h&&n>=c&&n<=l)return"CENTER"}getBounds(){const t=Array.from(this.targets);let e=1/0,i=1/0,r=-1/0,n=-1/0;for(const a of t){const[o,h]=U(a.worldMatrix),[c,l]=U(a.worldMatrix,a.width,a.height);e=Math.min(e,a.sx<0?c:o),i=Math.min(i,a.sy<0?l:h),r=Math.max(r,a.sx<0?o:c),n=Math.max(n,a.sy<0?h:l)}return{minX:e,minY:i,maxX:r,maxY:n}}recalculateBounds(){const{minX:t,minY:e,maxX:i,maxY:r}=this.getBounds();this.x=this.scale[0]<0?i:t,this.y=this.scale[1]<0?r:e,this.width=this.scale[0]*(i-t),this.height=this.scale[1]*(r-e)}addHandles(){for(const t of Yt){const e=this.getHandleConfig(t),i=new j(e);i.color=st,this.handles.set(t,i)}}updateHandles(){for(const t of Yt){const e=this.handles.get(t),i=this.getHandleConfig(t);e&&(e.setTranslation(i.x,i.y),e.width=i.width,e.height=i.height)}}getHandleConfig(t){let{x:e,y:i,width:r,height:n,borderSize:a,boxSize:o}=this;return{TOP:{x:e,y:i,width:r,height:a},BOTTOM:{x:e,y:i+n,width:r,height:a},LEFT:{x:e,y:i,width:a,height:n},RIGHT:{x:e+r,y:i,width:a,height:n},TOPLEFT:{x:e-o,y:i-o,width:o*2,height:o*2},TOPRIGHT:{x:e-o+r,y:i-o,width:o*2,height:o*2},BOTTOMLEFT:{x:e-o,y:i-o+n,width:o*2,height:o*2},BOTTOMRIGHT:{x:e-o+r,y:i-o+n,width:o*2,height:o*2}}[t]}}class J{constructor(t,e,i,r){this.minX=t,this.minY=e,this.maxX=i,this.maxY=r}getArea(){return(this.maxY-this.minY)*(this.maxX-this.minX)}static isColliding(t,e){return t.minX<=e.maxX&&t.maxX>=e.minX&&t.minY<=e.maxY&&t.maxY>=e.minY}}const de=["CENTER",...ft];class gi{constructor(t,e,i){this.width=0,this.height=0,this.rects=new Map,this.borderSize=0;const[r,n]=U(i,t,e);this.x=r,this.y=n,this.addRects()}getRectConfig(t){let{x:e,y:i,width:r,height:n,borderSize:a}=this;return{TOP:{x:e,y:i,width:r<0?r:r+a,height:a},BOTTOM:{x:e,y:i+n,width:r<0?r:r+a,height:a},LEFT:{x:n<0&&r<0?e-a:e,y:i,width:a,height:n<0&&r<0?n:n+a},RIGHT:{x:e+r,y:i,width:a,height:n<0?n:n+a},CENTER:{x:e,y:i,width:r,height:n}}[t]}render(t,e){this.update();for(const[i,r]of this.rects.entries())r.render(t,e)}update(){this.borderSize=Xt,this.updateRects()}destroy(){for(const[t,e]of this.rects.entries())e.destroy()}getBoundingBox(t){const[e,i]=t(this.x,this.y),[r,n]=t(this.x+this.width,this.y+this.height),a=Math.min(e,r),o=Math.max(e,r),h=Math.min(i,n),c=Math.max(i,n);return new J(a,h,o,c)}resize(t,e,i){const[r,n]=Q(i);this.width+=t*r,this.height+=e*n}addRects(){for(const t of de){const e=this.getRectConfig(t),i=new j(e);i.color=st,this.rects.set(t,i)}}updateRects(){for(const t of de){const e=this.rects.get(t),i=this.getRectConfig(t);e&&(e.setTranslation(i.x,i.y),e.width=i.width,e.height=i.height,t==="CENTER"&&(e.color=ei))}}}class mi{constructor(t={}){const{x:e=0,y:i=0,width:r=0,height:n=0,rotation:a=0,zoom:o=1}=t;this.x=e,this.y=i,this.width=r,this.height=n,this.rotation=a,this.zoom=o,p.makeObservable(this,{x:p.observable,y:p.observable,width:p.observable,height:p.observable,rotation:p.observable,zoom:p.observable,setX:p.action,setY:p.action,setPosition:p.action,incrementPosition:p.action,setWidth:p.action,setHeight:p.action,setSize:p.action,setZoom:p.action,setRotation:p.action,stateVector:p.computed})}setX(t){this.x=t}setY(t){this.y=t}setPosition(t,e){this.x=t,this.y=e}incrementPosition(t,e){this.x+=t,this.y+=e}setWidth(t){this.width=t}setHeight(t){this.height=t}setSize(t,e){this.width=t,this.height=e}setZoom(t){this.zoom=t}setRotation(t){this.rotation=t}get dimension(){return[this.width,this.height]}get position(){return[this.x,this.y]}get stateVector(){return[this.x,this.y,this.width,this.height,this.rotation,this.zoom]}get translationMatrix(){return b.translation(this.x,this.y)}get rotationMatrix(){return b.rotation(this.rotation)}get scaleMatrix(){return b.scaling(this.zoom,this.zoom)}get cameraMatrix(){const t=b.multiply(this.translationMatrix,this.rotationMatrix);return b.multiply(t,this.scaleMatrix)}get canvasMatrix(){return b.inverse(this.cameraMatrix)}}function le(s,t){s.setTranslation(t.x,t.y),s.setScale(t.sx,t.sy)}function ue(s,t,e){return{label:"Flip",do(){for(const i of s)le(i.ref,i.end);e&&(e.scale[t==="horizontal"?0:1]*=-1)},undo(){for(const i of s)le(i.ref,i.start);e&&(e.scale[t==="horizontal"?0:1]*=-1)}}}function fe(s,t){s.setTranslation(t.x,t.y),s.setScale(t.sx,t.sy)}function $t(s,t="Transform"){return{label:t,do(){for(const e of s)fe(e.ref,e.end)},undo(){for(const e of s)fe(e.ref,e.start)}}}class pi{#s;#i=new Set;#e=new Set;#t;#r;#a;get multiBoundingBox(){return this.#t}get boundingBoxes(){return this.#e}#o=!0;#n;#h;get selected(){return Array.from(this.#i)}set selected(t){this.#i.clear(),t.forEach(e=>{this.#i.add(e),this.#e.add(new ce(e))})}get marqueeBox(){return this.#r}set marqueeBox(t){this.#r=new gi(t.x,t.y,this.getWorldMatrix())}constructor(t,e,i,r,n,a,o,h){this.#n=i,this.#h=r,this.#s=t,this.#a=e,this.getWorldMatrix=n,this.getCanvasChildren=a,this.getWorldCoords=o,this.getMarqueeCoords=h;const c=Object.getPrototypeOf(this);for(const l of Object.getOwnPropertyNames(c)){const u=this[l];typeof u=="function"&&l!=="constructor"&&(this[l]=u.bind(this))}}add(t){t.forEach(e=>{this.#i.has(e)||(this.#i.add(e),this.#e.add(new ce(e)))}),this.#e.size>1&&(this.#e.forEach(e=>e.setPassive()),this.#t||(this.#t=new fi([])),this.selected.forEach(e=>this.#t.add(e)))}remove(t){t.forEach(e=>{if(!this.#i.has(e))return;this.#i.delete(e);const i=Array.from(this.#e.values()).find(r=>r.target===e);i?this.#e.delete(i):console.error("No matching bounding box found"),this.#t&&this.#t.remove(e)}),this.#e.size<=1&&(this.#e.forEach(e=>e.setActive()),this.#t=null)}deleteSelected(t){const e=[...this.#i];this.remove(e);for(const i of e)i.destroy();this.#s.push(si(t,e))}hitTest(t,e){if(this.#t){const i=this.#t.hitTest(t,e,this.getWorldMatrix());if(i)return i}for(const i of this.#e.values()){const r=i.hitTest(t,e,this.getWorldMatrix());if(r)return r}return null}isMultiBoundingBoxHit(t,e){return this.#t&&this.#t.hitTest(t,e,this.getWorldMatrix())}isBoundingBoxHit(t,e){return this.#e.size===1&&Array.from(this.#e)[0].hitTest(t,e,this.getWorldMatrix())}hitTestAdjustedCorner(t,e){if(this.#t){const i=this.#t.hitTest(t,e,this.getWorldMatrix());if(i)return this.#t.scale[0]*this.#t.scale[1]<0?ie(i):i}for(const i of this.#e.values()){const r=i.hitTest(t,e,this.getWorldMatrix());if(r)return i.target.sx*i.target.sy<0?ie(r):r}}update(){this.#e.forEach(t=>t.update()),this.#t&&this.#t.update()}render(t){if(!this.#r&&!this.#t&&this.#e.size===0)return;this.#n.useProgram(t);const e=this.#n.getUniformLocation(t,"u_z");e&&this.#n.uniform1f(e,1),this.#o&&this.#e.forEach(i=>i.render(this.#n,t)),this.#t&&this.#t.render(this.#n,t),this.#r&&this.#r.render(this.#n,t)}isRectSelected(t){return this.#i.has(t)}clear(){this.#i.clear(),this.#e.clear(),this.#t=null}clearMarquee(){this.#r&&(this.#r=null)}move(t,e){if(this.#t)this.#t.move(t,e);else for(const i of this.#e)i.move(t,e);this.#a.emit(N.Change)}resize(t,e,i){this.multiBoundingBox&&this.multiBoundingBox.resize(t,e,i,this.getWorldMatrix());for(const r of this.boundingBoxes)this.multiBoundingBox?r.update():r.resize(t,e,i);this.#a.emit(N.Change)}flip(t){if(this.multiBoundingBox){const e=this.multiBoundingBox.flip(this.getWorldMatrix(),t,this.getWorldCoords);this.#s.push(ue(e,t,this.multiBoundingBox))}else{const e=[];for(const i of this.boundingBoxes)e.push(i.flip(t));this.#s.push(ue(e,t))}this.#a.emit(N.Change)}alignSelection(t){if(!this.multiBoundingBox)return;const e=this.multiBoundingBox.align(t);this.#s.push($t(e)),this.#a.emit(N.Change)}normalize(t,e="first"){if(!this.multiBoundingBox)return;const i=this.multiBoundingBox.normalize(t,e);this.#s.push($t(i)),this.#a.emit(N.Change)}onPointerMove(t,e,i,r,n,a,o,h){if(a())o(t,e);else if(n&&n!=="CENTER")this.resize(i,r,n);else if(this.marqueeBox){this.marqueeBox.resize(i,r,h());const c=this.getCanvasChildren(),l=this.marqueeBox.getBoundingBox(this.getMarqueeCoords);for(const u of c){const m=u.getBoundingBox();J.isColliding(m,l)&&!this.#i.has(u)?this.add([u]):!J.isColliding(m,l)&&this.#i.has(u)&&this.remove([u])}}else this.move(i,r)}onSelectionPointerDown(t,e,i,r){e?(t||this.clear(),this.add([e])):(this.clear(),this.marqueeBox?this.clearMarquee():this.marqueeBox={x:i,y:r})}}var gt=(s=>(s[s.SELECT=0]="SELECT",s[s.PAN=1]="PAN",s))(gt||{});const yi={TOP:"ns-resize",BOTTOM:"ns-resize",LEFT:"ew-resize",RIGHT:"ew-resize",TOPLEFT:"nwse-resize",BOTTOMRIGHT:"nwse-resize",TOPRIGHT:"nesw-resize",BOTTOMLEFT:"nesw-resize",CENTER:"grab"};class xi{constructor(t){for(const e in t)e in t&&t[e]!==void 0&&(this[e]=t[e]);this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMoveWhileDown=this.onPointerMoveWhileDown.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.addOnPointerMove(),this.addOnWheel(t.onWheel),this.addOnPointerDown(),window.addEventListener("copy",async e=>{e.preventDefault(),!this.isContextMenuActive()&&await oe(this.getSelected())}),window.addEventListener("paste",async e=>{e.preventDefault(),!this.isContextMenuActive()&&await t.paste(this.state.lastPointerPos.x,this.state.lastPointerPos.y)})}changeMode(){this.state.toggleMode()}addOnPointerDown(){this.assignEventListener("pointerdown",this.onPointerDown)}addOnPointerMove(){this.assignEventListener("pointermove",t=>{[this.state.lastPointerPos.x,this.state.lastPointerPos.y]=this.getWorldCoords(t.clientX,t.clientY);let e=this.hitTestAdjustedCorner(this.state.lastPointerPos.x,this.state.lastPointerPos.y);this.setCursorStyle(yi[e]||"default")})}addOnWheel(t){this.assignEventListener("wheel",e=>{this.isContextMenuActive()||t(e)},{passive:!1})}onPointerDown(t){t.stopPropagation(),t.preventDefault(),this.eventHub.emit(X.Close);const[e,i]=this.getWorldCoords(t.clientX,t.clientY);this.state.initialize(e,i),this.currentTransform=void 0,this.state.mode===1?this.handlePanPointerDown():this.state.mode===0&&this.handleSelectPointerDown(t,e,i),document.addEventListener("pointermove",this.onPointerMoveWhileDown),document.addEventListener("pointerup",this.onPointerUp)}handlePanPointerDown(){this.setCanvasGlobalClick(!0),this.clearSelection()}handleSelectPointerDown(t,e,i){this.setCanvasGlobalClick(!1);const r=this.checkCollidingChild(e,i),n=this.checkIfSelectionHit(e,i);if(t.button===2)n||this.clearSelection(),r&&!this.isSelection(r)&&this.addSelection([r]);else{n?this.state.resizingDirection=n:this.onSelectionPointerDown(t.shiftKey,r,e,i);const a=this.getSelected();a.length&&(this.currentTransform={targets:a.map(o=>({ref:o,start:{x:o.x,y:o.y,sx:o.sx,sy:o.sy}}))})}}onPointerMoveWhileDown(t){if(t.buttons===2)return;const[e,i]=this.getWorldCoords(t.clientX,t.clientY),r=e-this.state.lastWorldX,n=i-this.state.lastWorldY;this.selectionPointerMove(this.state.startWorldX-e,this.state.startWorldY-i,r,n,this.state.resizingDirection),this.state.updateLastWorldCoord(e,i),this.setCursorStyle("grabbing")}onPointerUp(){if(document.removeEventListener("pointermove",this.onPointerMoveWhileDown),document.removeEventListener("pointerup",this.onPointerUp),this.setCanvasGlobalClick(!0),this.setCursorStyle("default"),this.currentTransform){const t=this.currentTransform.targets.map(e=>({ref:e.ref,start:e.start,end:{x:e.ref.x,y:e.ref.y,sx:e.ref.sx,sy:e.ref.sy}})).filter(e=>e.start.x!==e.end.x||e.start.y!==e.end.y||e.start.sx!==e.end.sx||e.start.sy!==e.end.sy);t.length&&this.history.push($t(t))}this.currentTransform=void 0,this.state.resizingDirection=null,this.closeMarquee(),this.eventHub.emit("save")}checkCollidingChild(t,e){const i=this.getChildren();for(let r=i.length-1;r>=0;r--){const n=i[r];if(n instanceof at&&n.hitTest&&n.hitTest(t,e))return n}return null}}class wi{constructor(t,e,i,r){this.history=t,this.deleteSelected=i,this.save=()=>e.emit(N.Save),this.assignEventListener=r,this.onKeyPressed=this.onKeyPressed.bind(this),this.addOnKeyPressed()}addOnKeyPressed(){document.addEventListener("keydown",this.onKeyPressed)}onKeyPressed(t){if(this.isCtrlZ(t)){t.preventDefault(),this.history.undo();return}if(this.isCtrlY(t)){t.preventDefault(),this.history.redo();return}if(this.isDelete(t)){this.deleteSelected();return}if(this.isSave(t)){t.preventDefault(),this.save();return}}isCtrlZ(t){return t.key.toLowerCase()==="z"&&(t.ctrlKey||t.metaKey)&&!t.shiftKey}isCtrlY(t){return t.key.toLowerCase()==="y"&&(t.ctrlKey||t.metaKey)&&!t.shiftKey}isDelete(t){return t.key==="Delete"}isSave(t){return t.key.toLowerCase()==="s"&&t.ctrlKey}}class vi{#s=!1;get isActive(){return this.#s}constructor(t,e,i,r,n){this.customContextMenu=a=>{a.preventDefault(),a.stopPropagation();const[o,h]=r(a.clientX,a.clientY);e(o,h)?t.emit(X.Open,a.clientX,a.clientY,"multi"):i(o,h)?t.emit(X.Open,a.clientX,a.clientY):t.emit(X.Open,a.clientX,a.clientY,"canvas")},t.on(X.Open,()=>{this.#s=!0}),t.on(X.Close,()=>{this.#s=!1}),n("contextmenu",this.customContextMenu)}}function ge(s,t){s.renderOrder=t.renderOrder}function Ci(s,t="Order"){return{label:t,do(){for(const e of s)ge(e.ref,e.end)},undo(){for(const e of s)ge(e.ref,e.start)}}}class Si{constructor(t=gt.SELECT){this.lastPointerPos={x:0,y:0},this.startWorldX=0,this.startWorldY=0,this.lastWorldX=0,this.lastWorldY=0,this.resizingDirection=null,this.mode=t}get isResizing(){return this.resizingDirection!==null}get dragDXFromStart(){return this.lastWorldX-this.startWorldX}get dragDYFromStart(){return this.lastWorldY-this.startWorldY}setMode(t){this.mode=t}toggleMode(){this.mode=this.mode===gt.PAN?gt.SELECT:gt.PAN}setResizingDirection(t){this.resizingDirection=t}clearResizingDirection(){this.resizingDirection=null}initialize(t,e){this.startWorldX=t,this.startWorldY=e,this.lastWorldX=t,this.lastWorldY=e,this.resizingDirection=null}updateLastWorldCoord(t,e){this.lastWorldX=t,this.lastWorldY=e}}class bi{constructor(){this.translation=[0,0],this.angleRadians=0,this.scale=[1,1],this.localMatrix=b.identity(),this.worldMatrix=b.identity(),this.children=[],this.parent=null,this.renderDirtyFlag=!0,p.makeObservable(this,{translation:p.observable.struct,angleRadians:p.observable,scale:p.observable.struct,localMatrix:p.observable.ref,worldMatrix:p.observable.ref,children:p.observable.shallow,parent:p.observable.ref,renderDirtyFlag:p.observable,x:p.computed,y:p.computed,scaleX:p.computed,scaleY:p.computed,dirty:p.computed,setTranslation:p.action,setScale:p.action,flipVertical:p.action,setAngle:p.action,getChild:p.action,appendChild:p.action,appendChildren:p.action,removeChild:p.action,clearChildren:p.action,setParent:p.action,markDirty:p.action,clearDirty:p.action,updateLocalMatrix:p.action,updateWorldMatrix:p.action,setWorldMatrix:p.action}),this.updateLocalMatrix(),this.updateWorldMatrix()}get x(){return this.translation[0]}get y(){return this.translation[1]}get scaleX(){return this.scale[0]}get scaleY(){return this.scale[1]}get dirty(){return this.renderDirtyFlag}setTranslation(t,e){this.translation[0]=t,this.translation[1]=e,this.markDirty()}updateTranslation(t,e){this.translation[0]+=t,this.translation[1]+=e,this.markDirty()}setScale(t,e){t===this.scale[0]&&e===this.scale[1]||(this.scale[0]=t,this.scale[1]=e,this.markDirty())}updateScale(t,e){this.scale[0]*=t,this.scale[1]*=e,this.markDirty()}flipVertical(t){this.translation[1]+=this.scale[1]*t,this.scale[1]*=-1,this.markDirty()}flipHorizontal(t){this.translation[0]+=this.scale[0]*t,this.scale[0]*=-1,this.markDirty()}setAngle(t){const i=(360-t)*Math.PI/180;i!==this.angleRadians&&(this.angleRadians=i,this.markDirty())}getChild(t){return this.children[t]}appendChild(t){this.children.includes(t)||(this.children.push(t),this.markDirty())}appendChildren(t){for(const e of t){if(this.children.includes(e))return;this.children.push(e)}this.markDirty()}removeChild(t){const e=this.children.indexOf(t);if(e<0)return;const i=this.children.splice(e,1);return t.state.setParent(null),this.markDirty(),i[0]}clearChildren(){if(this.children){for(const t of this.children)t.destroy();this.children=[],this.markDirty()}}setParent(t){this.parent!==t&&(this.parent=t,this.markDirty())}markDirty(){this.renderDirtyFlag||(this.renderDirtyFlag=!0,this.updateLocalMatrix())}clearDirty(){this.renderDirtyFlag&&(this.renderDirtyFlag=!1,this.updateLocalMatrix())}updateLocalMatrix(){const t=b.translation(this.translation[0],this.translation[1]),e=b.rotation(this.angleRadians),i=b.scaling(this.scale[0],this.scale[1]);this.localMatrix=b.multiply(b.multiply(t,e),i)}updateWorldMatrix(t){this.worldMatrix=t?b.multiply(t,this.localMatrix):this.localMatrix.slice();const e=this.worldMatrix;this.children.forEach(i=>{i.updateWorldMatrix(e)})}setWorldMatrix(t){this.worldMatrix=t}}class me{get x(){return this.state.x}get y(){return this.state.y}get sx(){return this.state.scaleX}get sy(){return this.state.scaleY}get dirty(){return this.state.dirty}get localMatrix(){return this.state.localMatrix}get worldMatrix(){return this.state.worldMatrix}get children(){return this.state.children}get parent(){return this.state.parent}get angleRadians(){return this.state.angleRadians}updateTranslation(t,e){this.state.updateTranslation(t,e)}setTranslation(t,e){this.state.setTranslation(t,e)}updateScale(t,e){this.state.updateScale(t,e)}setScale(t,e){this.state.setScale(t,e)}setAngle(t){return this.state.setAngle(t)}flipVertical(t){this.state.flipVertical(t)}flipHorizontal(t){this.state.flipHorizontal(t)}markDirty(){this.state.markDirty()}clearDirty(){this.state.clearDirty()}updateLocalMatrix(){this.state.updateLocalMatrix()}setWorldMatrix(t){this.state.setWorldMatrix(t)}addChild(t){this.state.appendChild(t)}addParent(t){return this.state.setParent(t)}clearChildren(){return this.state.clearChildren()}constructor(){this.state=new bi,this.setWorldMatrix=this.setWorldMatrix.bind(this),this.updateWorldMatrix=this.updateWorldMatrix.bind(this)}appendChild(t){return t.setParent(this),!t._emitter&&this._emitter&&(t._emitter=this._emitter),t}setParent(t){if(this.parent){const e=this.parent.children.indexOf(this);e>=0&&this.parent.children.splice(e,1)}t&&t.addChild(this),this.addParent(t)}updateWorldMatrix(t){this.updateLocalMatrix(),this.state.updateWorldMatrix(t)}addEventListener(t,e,i){const r=typeof e=="function"?e:e.handleEvent.bind(e);this._emitter.on(t,r)}removeEventListener(t,e,i){}dispatchEvent(t){return this._emitter.emit(t.type,t),!t.defaultPrevented}}class pe extends me{constructor(){super(...arguments),this.initialized=!1}updateVertexData(t){const e=this.getPositions();(!this.vertexArray||this.vertexArray.length!==e.length)&&(this.vertexArray=new Float32Array(e.length)),this.vertexArray.set(e),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.vertexArray,t.STATIC_DRAW)}setUpVertexData(t,e){this.positionBuffer||(this.positionBuffer=t.createBuffer()),this.attributeLocation=t.getAttribLocation(e,"a_position")}setUpUniforms(t,e){this.resolutionLocation=t.getUniformLocation(e,"u_resolution"),this.matrixLocation=t.getUniformLocation(e,"u_matrix")}updateUniforms(t){t.uniform2f(this.resolutionLocation,t.canvas.width,t.canvas.height),t.uniformMatrix3fv(this.matrixLocation,!1,this.worldMatrix)}}const Wt=class Wt extends pe{constructor(t,e,i=1,r=1){super(),this._seq=Wt._seqCounter++,this.culled=!1,this._renderOrder=0,this.color=[1,0,.5,1],this.setTranslation(t,e),this.setScale(i,r)}get renderOrder(){return this._renderOrder}set renderOrder(t){this._renderOrder!==t&&(this._renderOrder=t,this.markDirty())}get seq(){return this._seq}getZ(){const e=this.renderOrder*1e-4+.5;return Math.max(0,Math.min(1,e))}render(t,e){this.updateWorldMatrix(this.parent?this.parent.worldMatrix:void 0),t.useProgram(e),this.dirty&&!this.culled&&(this.initialized||(this.setUpVertexData(t,e),this.setUpUniforms(t,e),this.initialized=!0),this.updateVertexData(t),this.clearDirty()),this.updateUniforms(t);const i=t.getUniformLocation(e,"u_color");i&&t.uniform4fv(i,this.color),this.culled||this.draw(t)}draw(t){t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer);const e=2,i=t.FLOAT;t.vertexAttribPointer(this.attributeLocation,e,i,!1,0,0),t.enableVertexAttribArray(this.attributeLocation),t.drawArrays(t.TRIANGLES,0,this.getVertexCount()),t.bindBuffer(t.ARRAY_BUFFER,null),t.disableVertexAttribArray(this.attributeLocation)}destroy(){this.positionBuffer&&(this.positionBuffer=void 0),this.initialized=!1}};Wt._seqCounter=0;let at=Wt;class j extends at{constructor(t){super(t.x,t.y,t.sx,t.sy),this._width=t.width??100,this._height=t.height??100}get width(){return this._width}set width(t){this._width!==t&&(this._width=t,this.markDirty())}get height(){return this._height}set height(t){this._height!==t&&(this._height=t,this.markDirty())}getVertexCount(){return 6}getPositions(){const i=this.width,r=this.height;return[0,0,0,r,i,0,i,0,0,r,i,r]}getBoundingBox(){const t=this.state.translation[0],e=t+this.width*this.state.scaleX,i=this.state.translation[1],r=i+this.height*this.state.scaleY,n=Math.min(t,e),a=Math.max(t,e),o=Math.min(i,r),h=Math.max(i,r);return this.AABB=new J(n,o,a,h),this.AABB}getEdge(){const t=this.x,e=this.y;return{minX:Math.min(t,t+this.width),maxX:Math.max(t,t+this.width),minY:Math.min(e,e+this.height),maxY:Math.max(e,e+this.height)}}hitTest(t,e){const[i,r]=Q(this.worldMatrix),[n,a]=bt(this.worldMatrix),[o,h]=U(this.parent.worldMatrix,t,e),[c,l]=U(this.worldMatrix),u=this.width*i*n,m=this.height*r*a,g=Math.min(c,c+u),C=Math.max(c,c+u),x=Math.min(l,l+m),E=Math.max(l,l+m);return o>=g&&o<=C&&h>=x&&h<=E}}class mt extends j{constructor(t){super(t),this.texCoordArray=new Float32Array([0,0,0,1,1,0,1,0,0,1,1,1]),this.useLowRes=!1,this.lowResNeedsRefresh=!0,this._src=t.src,this.loadImage(t.src,t.width,t.height)}get src(){return this._src}set src(t){this._src!==t&&(this._src=t,this.updateImageTexture(t),this.markDirty())}get fileId(){return this._fileId}set fileId(t){this._fileId=t}determineIfLowRes(t,e,i=.1){const r=t.getArea();return this.getBoundingBox().getArea()/r<i/e}async setUseLowRes(t,e){this.useLowRes===t&&!this.lowResNeedsRefresh||(this.useLowRes=t,(t&&e||this.lowResNeedsRefresh)&&await this.ensureLowResUploaded(e),this.markDirty(),this.lowResNeedsRefresh=!1)}loadImage(t,e,i){this.culled||this.updateImageTexture(t,e,i)}updateImageTexture(t,e,i){this._image=new Image,this._image.crossOrigin="anonymous",this._image.onload=async()=>{this.width=e??this._image.naturalWidth,this.height=i??this._image.naturalHeight;try{if(this.bitmap){try{this.bitmap.close()}catch{}this.bitmap=void 0}typeof createImageBitmap=="function"&&(this.bitmap=await createImageBitmap(this._image))}catch(r){console.warn("createImageBitmap failed, falling back to HTMLImageElement",r),this.bitmap=void 0}if(this.gl&&this.program)try{this.texture&&this.gl&&(this.gl.deleteTexture(this.texture),this.texture=void 0),this.initialiseTexture(),this.initialized=!0,this.markDirty()}catch(r){console.error("Failed to initialise texture on image load",r)}this.lowResNeedsRefresh=!0},this._image.onerror=r=>{console.error("Failed to load image:",t,r)},this._image.src=t}async ensureLowResUploaded(t){if(!(this.lowResTexture&&!this.lowResNeedsRefresh)&&!(!this._image||!this._image.complete))try{const i=this._image.naturalWidth,r=this._image.naturalHeight,n=Math.min(1,256/Math.max(1,Math.max(i,r))),a=Math.max(1,Math.round(i*n)),o=Math.max(1,Math.round(r*n));let h;typeof OffscreenCanvas<"u"?h=new OffscreenCanvas(a,o):(h=document.createElement("canvas"),h.width=a,h.height=o);const c=h.getContext("2d");c.clearRect(0,0,a,o);const l=Math.min(a/i,o/r),u=Math.round(i*l),m=Math.round(r*l),g=Math.round((a-u)/2),C=Math.round((o-m)/2);c.drawImage(this._image,0,0,i,r,g,C,u,m),this.lowResBitmap=await createImageBitmap(h),this.setLowResTextureFromBitmap(t,this.lowResBitmap)}catch(e){console.error("Failed to create/upload low-res image",e)}}setLowResTextureFromBitmap(t,e){if(this.lowResTexture){try{t.deleteTexture(this.lowResTexture)}catch{}this.lowResTexture=void 0}this.lowResTexture=t.createTexture(),t.bindTexture(t.TEXTURE_2D,this.lowResTexture),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),t.bindTexture(t.TEXTURE_2D,null),this.markDirty()}initialiseTexture(){!this.gl||!this.program||!this._image||!this._image.complete||this._image.naturalWidth===0||(this.setUpVertexData(this.gl,this.program),this.setUpTexData(this.gl,this.program),this.setTexture(this.gl),super.setUpUniforms(this.gl,this.program),this.samplerLocation=this.gl.getUniformLocation(this.program,"u_image"),this.samplerLocation&&this.gl.uniform1i(this.samplerLocation,0))}setUpTexData(t,e){this.texcoordBuffer||(this.texcoordBuffer=t.createBuffer()),this.texcoordLocation=t.getAttribLocation(e,"a_texCoord")}setTexture(t){if(this.texture){try{try{t.deleteTexture(this.texture)}catch{}}catch{}this.texture=void 0}this.texture=t.createTexture(),t.bindTexture(t.TEXTURE_2D,this.texture),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR);const e=this.bitmap??this._image;e&&t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),t.bindTexture(t.TEXTURE_2D,null)}updateVertexData(t){super.updateVertexData(t),t.bindBuffer(t.ARRAY_BUFFER,this.texcoordBuffer),t.bufferData(t.ARRAY_BUFFER,this.texCoordArray,t.STATIC_DRAW)}getVertexCount(){return 6}render(t,e){if(this.dirty&&!this.culled){if(this.updateWorldMatrix(this.parent?this.parent.worldMatrix:void 0),!this.initialized)if(this.gl=t,this.program=e,this.initialiseTexture(),this._image.complete&&this._image.naturalWidth>0)this.initialized=!0;else return;this.updateVertexData(t),this.clearDirty()}super.updateUniforms(t),this.culled||this.draw(t)}draw(t){t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer);const e=2,i=t.FLOAT,r=!1,n=0,a=0;t.vertexAttribPointer(this.attributeLocation,e,i,r,n,a),t.enableVertexAttribArray(this.attributeLocation),t.bindBuffer(t.ARRAY_BUFFER,this.texcoordBuffer),t.vertexAttribPointer(this.texcoordLocation,e,i,r,n,a),t.enableVertexAttribArray(this.texcoordLocation),t.activeTexture(t.TEXTURE0);try{const o=this.useLowRes&&this.lowResTexture?this.lowResTexture:this.texture;t.bindTexture(t.TEXTURE_2D,o),t.drawArrays(t.TRIANGLES,0,this.getVertexCount()),t.bindBuffer(t.ARRAY_BUFFER,null),t.disableVertexAttribArray(this.attributeLocation),t.disableVertexAttribArray(this.texcoordLocation)}catch(o){console.error(o)}}destroy(){if(this.texcoordBuffer){try{this.gl.deleteBuffer(this.texcoordBuffer)}catch{}this.texcoordBuffer=void 0}if(this.texture){try{this.gl.deleteTexture(this.texture)}catch{}this.texture=void 0}if(this.lowResTexture){try{this.gl.deleteTexture(this.lowResTexture)}catch{}this.lowResTexture=void 0}if(this.bitmap){try{this.bitmap.close()}catch{}this.bitmap=void 0}if(this.lowResBitmap){try{this.lowResBitmap.close()}catch{}this.lowResBitmap=void 0}this.texcoordLocation=void 0,this.samplerLocation=void 0;try{super.destroy()}catch{}}}var It=(s=>(s[s.NONE=0]="NONE",s[s.GRID=1]="GRID",s))(It||{});class ye extends pe{constructor(){super(...arguments),this.buffer=null,this.vertexCount=0,this.gridType=1,this.zoom=1}getPositions(){return new Float32Array([-1,-1,3,-1,-1,3])}changeGridType(t){this.gridType=t}render(t,e){if(this.buffer)t.bindBuffer(t.ARRAY_BUFFER,this.buffer);else{if(this.buffer=t.createBuffer(),!this.buffer)throw new Error("Failed to create grid buffer");const c=this.getPositions();this.vertexCount=c.length/2,t.bindBuffer(t.ARRAY_BUFFER,this.buffer),t.bufferData(t.ARRAY_BUFFER,c,t.STATIC_DRAW)}this.initialized||(this.setUpVertexData(t,e),this.setUpUniforms(t,e),this.initialized=!0);const i=t.drawingBufferWidth,r=t.drawingBufferHeight,n=b.inverse(b.projection(i,r)),a=b.inverse(this.worldMatrix),o=b.multiply(a,n);this.viewProjectionInvLocation&&t.uniformMatrix3fv(this.viewProjectionInvLocation,!1,new Float32Array(o)),this.zoomScaleLocation&&t.uniform1f(this.zoomScaleLocation,this.zoom),this.checkboardStyleLocation&&t.uniform1f(this.checkboardStyleLocation,this.gridType);const h=t.getAttribLocation(e,"a_Position");if(h===-1)throw new Error("Attribute a_Position not found in grid program");t.vertexAttribPointer(h,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(h),t.drawArrays(t.TRIANGLES,0,this.vertexCount),t.bindBuffer(t.ARRAY_BUFFER,null),t.disableVertexAttribArray(h)}destroy(){this.buffer&&(this.buffer=null)}hitTest(t,e){return!1}setUpUniforms(t,e){const i=new Float32Array([1,0,0,0,1,0,0,0,1]);this.viewProjectionInvLocation=t.getUniformLocation(e,"u_ViewProjectionInvMatrix"),this.zoomScaleLocation=t.getUniformLocation(e,"u_ZoomScale"),this.checkboardStyleLocation=t.getUniformLocation(e,"u_CheckboardStyle"),t.uniformMatrix3fv(this.viewProjectionInvLocation,!1,i),t.uniform1f(this.zoomScaleLocation,this.zoom),t.uniform1f(this.checkboardStyleLocation,1)}}const xe=.02,we=20;class ve{constructor(t,e,i,r){this.viewportX=0,this.viewportY=0,this.state=t,this.updateCameraPos=this.updateCameraPos.bind(this),this.updateZoom=this.updateZoom.bind(this),this.onWheel=this.onWheel.bind(this),this.worldToCamera=this.worldToCamera.bind(this),this.getWorldCoords=r,this.setWorldMatrix=e,this.updateWorldMatrix=i,this.updateReaction=p.reaction(()=>this.state.stateVector,()=>this.updateViewMatrix()),this.updateViewMatrix()}updateViewMatrix(){this.setWorldMatrix(this.state.canvasMatrix),this.updateWorldMatrix()}setViewPortDimension(t,e){this.state.width!==t&&this.state.setWidth(t),this.state.height!==e&&this.state.setHeight(e)}getBoundingBox(){const[t,e]=this.getWorldCoords(this.viewportX,this.viewportY),[i,r]=this.getWorldCoords(this.state.width+this.viewportX,this.state.height+this.viewportY);return new J(t,e,i,r)}onWheel(t){t.preventDefault();const i=Math.exp(-t.deltaY*.003);this.updateZoom(t.clientX,t.clientY,i)}updateCameraPos(t,e){this.state.incrementPosition(t,e)}updateZoom(t,e,i){const[r,n]=this.getWorldCoords(t,e);this.state.setZoom(Math.min(we,Math.max(xe,this.state.zoom*i)));const[a,o]=this.getWorldCoords(t,e);this.state.incrementPosition(r-a,n-o)}worldToCamera(t,e){const i=this.state.cameraMatrix,r=i[0]*t+i[1]*e+i[2],n=i[3]*t+i[4]*e+i[5];return[r,n]}dispose(){this.updateReaction&&(this.updateReaction(),this.updateReaction=void 0)}}const Ce="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSIjYjNiM2IzIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjUgNmEyLjI1IDIuMjUgMCAwIDEgMi4yNS0yLjI1aDE2LjVBMi4yNSAyLjI1IDAgMCAxIDIyLjUgNnYxMmEyLjI1IDIuMjUgMCAwIDEtMi4yNSAyLjI1SDMuNzVBMi4yNSAyLjI1IDAgMCAxIDEuNSAxOHpNMyAxNi4wNlYxOGMwIC40MTQuMzM2Ljc1Ljc1Ljc1aDE2LjVBLjc1Ljc1IDAgMCAwIDIxIDE4di0xLjk0bC0yLjY5LTIuNjg5YTEuNSAxLjUgMCAwIDAtMi4xMiAwbC0uODguODc5bC45Ny45N2EuNzUuNzUgMCAxIDEtMS4wNiAxLjA2bC01LjE2LTUuMTU5YTEuNSAxLjUgMCAwIDAtMi4xMiAwem0xMC4xMjUtNy44MWExLjEyNSAxLjEyNSAwIDEgMSAyLjI1IDBhMS4xMjUgMS4xMjUgMCAwIDEtMi4yNSAwIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=",ot=240;function Se(s){return{x:s.x??0,y:s.y??0,sx:s.sx??1,sy:s.sy??1}}function jt(s){return s.children.map(be)}function be(s){return s instanceof mt?{type:"Img",id:s.seq,renderOrder:s.renderOrder,transform:Se(s),width:s.width,height:s.height,fileId:s.fileId,children:s.children?.length?jt(s):void 0}:s instanceof j?{type:"Rect",id:s.seq,renderOrder:s.renderOrder,transform:Se(s),width:s.width,height:s.height,color:s.color,children:s.children?.length?jt(s):void 0}:s instanceof ye?{type:"Grid",style:s.gridType}:{type:"Renderable",children:s.children?.length?jt(s):void 0}}function Vt(s,t){const{gl:e}=s;return{version:1,canvas:{width:e.canvas.width,height:e.canvas.height,dpr:window.devicePixelRatio||1},camera:{x:s.camera.state.x,y:s.camera.state.y,zoom:s.camera.state.zoom},root:be(s),files:t}}async function qt(s,t,e,i){t.children.length=0,s.camera&&(t.camera.state.setZoom(s.camera.zoom),t.camera.state.setX(s.camera.x),t.camera.state.setY(s.camera.y));async function r(n,a){let o;switch(n.type){case"Rect":o=new j({x:n.transform.x,y:n.transform.y,width:n.width,height:n.height}),o.setScale(n.transform.sx,n.transform.sy),t.appendChild(o);break;case"Img":let h;try{h=s.files&&Array.isArray(s.files)?s.files.find(g=>g.id===n.fileId)?.dataURL??Ce:Ce,i&&i(h);const c=n.width,l=n.height,u=await Ei(h,c*n.transform.sx,l*n.transform.sy);o=new mt({x:n.transform.x,y:n.transform.y,src:u,width:c,height:l}),e(n.fileId).then(m=>{o.src=m.dataURL}).catch(m=>console.error("Image not loaded",m)),o.fileId=n.fileId??await Ht(h),o.setScale(n.transform.sx,n.transform.sy),t.appendChild(o),typeof n.renderOrder=="number"&&(o.renderOrder=n.renderOrder)}catch{console.error(`Failed to match image to restore with source: ${h}`)}finally{break}case"Grid":a instanceof pt&&(a.grid.gridType=n.style);break}if(n.children)for(const h of n.children)await r(h,o)}return await r(s.root,t),t}async function Mi(s){const t=new Image;return t.crossOrigin="anonymous",new Promise((e,i)=>{t.onload=()=>e(t),t.onerror=r=>i(r),t.src=s})}async function Ei(s,t,e,i="#d6d6d6ff"){let r=null,n;s instanceof Blob?(r=URL.createObjectURL(s),n=r):n=s;try{let a=null;try{a=await Mi(n)}catch{}const o=t&&t>0?t:a?.naturalWidth??ot,h=e&&e>0?e:a?.naturalHeight??ot,c=document.createElement("canvas");c.width=o,c.height=h;const l=c.getContext("2d");if(l.fillStyle=i,l.fillRect(0,0,o,h),a){const u=Math.min(o/a.naturalWidth,h/a.naturalHeight),m=a.naturalHeight*u,g=a.naturalWidth*u;let C=ot,x=ot;(ot>m||ot>g)&&(C=g,x=m);const E=Math.round((o-C)/2),S=Math.round((h-x)/2);l.drawImage(a,0,0,a.naturalWidth,a.naturalHeight,E,S,C,x)}return c.toDataURL("image/png")}finally{r&&URL.revokeObjectURL(r)}}const I=class I extends me{constructor(e,i,r,n,a,o){super();B(this,G);B(this,H);B(this,et);B(this,ct);B(this,v);B(this,Y);B(this,dt);B(this,it);B(this,$);B(this,Z);B(this,P);B(this,lt);B(this,Ft);B(this,ut);A(this,Z,!0),this.orderDirty=!0,this.renderList=[],A(this,G,e),A(this,H,r),A(this,et,i),A(this,$,new ye),A(this,v,e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1})),f(this,v).enable(f(this,v).BLEND),f(this,v).blendFunc(f(this,v).SRC_ALPHA,f(this,v).ONE_MINUS_SRC_ALPHA),f(this,v).getExtension("OES_standard_derivatives"),f(this,v).enable(f(this,v).DEPTH_TEST),f(this,v).depthFunc(f(this,v).LEQUAL),A(this,Y,Nt(f(this,v),oi,hi)),A(this,dt,Nt(f(this,v),li,ui)),A(this,it,Nt(f(this,v),ci,di)),this.writeToStorage=n,this.saveImgFileToStorage=a,this.getContainerDimension=o,this.engine=this.engine.bind(this),this.getBoundingClientRect=this.getBoundingClientRect.bind(this),this.appendChild=this.appendChild.bind(this),this.addImageToCanvas=this.addImageToCanvas.bind(this),this.setShapeZOrder=this.setShapeZOrder.bind(this),this.toggleGrid=this.toggleGrid.bind(this),this.changeMode=this.changeMode.bind(this),this.getSelected=this.getSelected.bind(this),this.updateZoomByFixedAmount=this.updateZoomByFixedAmount.bind(this),this.assignEventListener=this.assignEventListener.bind(this),this.getWorldsCoordsFromCanvas=(m,g)=>K(m,g,this);const h=(m,g)=>K(m+this.camera.viewportX,g+this.camera.viewportY,this);this.exportState=this.exportState.bind(this),this.importState=this.importState.bind(this),this.clearChildren=this.clearChildren.bind(this),A(this,P,new pi(i,r,this.gl,f(this,Y),()=>this.worldMatrix,()=>this.children,this.getWorldsCoordsFromCanvas,h));const c=new mi({});A(this,ct,new ve(c,this.setWorldMatrix,this.updateWorldMatrix,this.getWorldsCoordsFromCanvas)),A(this,Ft,new wi(i,r,()=>this.selectionManager.deleteSelected(this),this.assignEventListener)),A(this,ut,new vi(r,this.selectionManager.isMultiBoundingBoxHit,this.selectionManager.isBoundingBoxHit,this.getWorldsCoordsFromCanvas,this.assignEventListener));const l=new Si,u={history:i,eventHub:r,state:l,isContextMenuActive:()=>f(this,ut).isActive,getSelected:()=>f(this,P).selected,getChildren:()=>this.children,getWorldMatrix:()=>this.worldMatrix,getCanvasGlobalClick:()=>this.isGlobalClick,setCanvasGlobalClick:m=>this.isGlobalClick=m,getWorldCoords:this.getWorldsCoordsFromCanvas,updateCameraPos:this.camera.updateCameraPos,onWheel:this.camera.onWheel,setCursorStyle:m=>e.style.cursor=m,paste:(m,g)=>he(m,g,this,i),assignEventListener:this.assignEventListener,closeMarquee:f(this,P).clearMarquee,selectionPointerMove:(m,g,C,x,E)=>f(this,P).onPointerMove(m,g,C,x,E,()=>this.isGlobalClick,this.camera.updateCameraPos,()=>this.worldMatrix),onSelectionPointerDown:this.selectionManager.onSelectionPointerDown,checkIfSelectionHit:this.selectionManager.hitTest,addSelection:this.selectionManager.add,clearSelection:this.selectionManager.clear,isSelection:this.selectionManager.isRectSelected,hitTestAdjustedCorner:this.selectionManager.hitTestAdjustedCorner};A(this,lt,new xi(u)),f(this,H).on("save",this.writeToStorage)}markOrderDirty(){this.orderDirty=!0}get gl(){return f(this,v)}get grid(){return f(this,$)}get history(){return f(this,et)}get eventHub(){return f(this,H)}get pointerEventManager(){return f(this,lt)}get selectionManager(){return f(this,P)}get contextMenuManager(){return f(this,ut)}get canvas(){return f(this,G)}get camera(){return f(this,ct)}get isGlobalClick(){return f(this,Z)}set isGlobalClick(e){A(this,Z,e)}get basicShapeProgram(){return f(this,Y)}engine(){return this}get totalNumberOfChildren(){return this.children.length}get numberOfChildrenRendered(){return this.renderList.length}appendChild(e){if(super.appendChild(e),e instanceof at){const i=this.children.map(n=>n.renderOrder),r=i.length?Math.max(...i):0;e.renderOrder=r+1}return this.markOrderDirty(),e}removeChild(e){this.state.removeChild(e),f(this,P)&&f(this,P).remove([e]),e.destroy(),this.markOrderDirty()}getChild(e){return this.state.getChild(e)}updateWorldMatrix(){f(this,$).updateWorldMatrix(this.worldMatrix),this.children.forEach(e=>{e.updateWorldMatrix(this.worldMatrix)}),f(this,P).update()}render(){f(this,v).clearColor(0,0,0,0),f(this,v).clear(f(this,v).COLOR_BUFFER_BIT|f(this,v).DEPTH_BUFFER_BIT),f(this,v).viewport(0,0,f(this,v).canvas.width,f(this,v).canvas.height);const e=this.canvas.parentElement.getBoundingClientRect();this.camera.setViewPortDimension(e.width,e.height),f(this,v).useProgram(f(this,it));const i=f(this,v).getUniformLocation(f(this,it),"u_z");f(this,v).uniform1f(i,0),f(this,$).render(f(this,v),f(this,it));const r=this.camera.getBoundingBox();this.renderList=[];for(const l of this.children)J.isColliding(r,l.getBoundingBox())?(this.renderList.push(l),l.culled=!1):l.culled=!0;const[n,a]=K(0,0,this),[o,h]=K(window.screen.width,window.screen.height,this),c=new J(n,a,o,h);this.renderList.forEach(l=>{if(l instanceof mt){const u=l.determineIfLowRes(c,this.camera.state.zoom);l.setUseLowRes(u,this.gl)}});for(const l of this.renderList){let u;l instanceof mt?u=f(this,dt):l instanceof at&&(u=f(this,Y)),f(this,v).useProgram(u);const m=f(this,v).getUniformLocation(u,"u_z");f(this,v).uniform1f(m,l.getZ()),l.render(f(this,v),u)}f(this,P).render(f(this,Y))}destroy(){f(this,v).deleteProgram(f(this,Y)),f(this,v).deleteProgram(f(this,dt)),this.children.forEach(e=>{"destroy"in e&&e.destroy()}),this.clearChildren()}getDOM(){return f(this,G)}assignEventListener(e,i,r){f(this,G).addEventListener(e,i,r)}hitTest(e,i){return A(this,Z,!0),f(this,Z)}async addImageToCanvas(e,i,r,n=1,a=1,o=!1){const h=new mt({x:i,y:r,src:e,sx:n,sy:a});if(this.saveImgFileToStorage(e).then(c=>h.fileId=c),o){const c=new Image;c.src=e.startsWith("data:image/png")?e:await ae(e),c.onload=()=>{const l=c.naturalWidth||c.width||0,u=c.naturalHeight||c.height||0;(l||u)&&h.updateTranslation(-l/2,-u/2),h.src=c.src,this.appendChild(h)}}return f(this,H).emit("save"),f(this,H).emit(N.Change),h}exportState(){return Vt(this)}async importState(e,i){return await qt(e,this,i)}clearChildren(){this.selectionManager.clear(),this.state.clearChildren(),f(this,et).clear()}toggleGrid(){f(this,$).changeGridType(f(this,$).gridType===It.GRID?It.NONE:It.GRID)}getSelected(){return f(this,P).selected}setShapeZOrder(e=!0){if(f(this,P).multiBoundingBox||f(this,P).boundingBoxes.size!=1)return;const i=Array.from(f(this,P).boundingBoxes)[0].target,r={ref:i,start:{renderOrder:i.renderOrder}},n=this.children.map(h=>h.renderOrder);if(n.length===0)throw new Error("Order unexpected missing.");const a=Math.max(...n),o=Math.min(...n);i.renderOrder=e?a+1:o-1,r.end={renderOrder:i.renderOrder},this.markOrderDirty(),f(this,et).push(Ci([r])),f(this,H).emit(N.Change)}changeMode(){f(this,lt).changeMode(),f(this,P).clear()}updateZoomByFixedAmount(e=1){f(this,ct).updateZoom(f(this,G).width/2,f(this,G).height/2,Math.exp(.5*.3*e))}getBoundingClientRect(){return f(this,G).getBoundingClientRect()}wrapWebGLContext(e){const i=e.createTexture.bind(e);e.createTexture=()=>(I.webglStats.texturesCreated++,console.log(`Textures created: ${I.webglStats.texturesCreated}`),i());const r=e.deleteTexture.bind(e);e.deleteTexture=o=>(o&&(I.webglStats.texturesDeleted++,console.log(`Textures deleted: ${I.webglStats.texturesDeleted}`)),r(o));const n=e.createShader.bind(e);e.createShader=o=>(I.webglStats.shadersCreated++,console.log(`Shaders created: ${I.webglStats.shadersCreated}`),n(o));const a=e.deleteShader.bind(e);return e.deleteShader=o=>(o&&(I.webglStats.shadersDeleted++,console.log(`Shaders deleted: ${I.webglStats.shadersDeleted}`)),a(o)),e}static getWebGLStats(){return{...I.webglStats,buffersLeaked:I.webglStats.buffersCreated-I.webglStats.buffersDeleted,programsLeaked:I.webglStats.programsCreated-I.webglStats.programsDeleted,texturesLeaked:I.webglStats.texturesCreated-I.webglStats.texturesDeleted,shadersLeaked:I.webglStats.shadersCreated-I.webglStats.shadersDeleted}}};G=new WeakMap,H=new WeakMap,et=new WeakMap,ct=new WeakMap,v=new WeakMap,Y=new WeakMap,dt=new WeakMap,it=new WeakMap,$=new WeakMap,Z=new WeakMap,P=new WeakMap,lt=new WeakMap,Ft=new WeakMap,ut=new WeakMap,I.webglStats={buffersCreated:0,buffersDeleted:0,programsCreated:0,programsDeleted:0,texturesCreated:0,texturesDeleted:0,shadersCreated:0,shadersDeleted:0};let pt=I;const Me=25;class Ti{constructor(){this._undoStack=[],this._redoStack=[],this._openGroup=null}get undoStack(){return this._undoStack}begin(t){if(this._openGroup)throw new Error("History group already open");this._openGroup=[],this._openLabel=t}push(t){if(this._openGroup)this._openGroup.push(t);else{for(;this._undoStack.length>=Me;)this._undoStack.shift();this._undoStack.push([t]),t.do(),this._redoStack.length=0}}commit(){if(!this._openGroup)return;const t=this._openGroup;this._openGroup=null;for(const e of t)e.do();for(;this._undoStack.length>=Me;)this._undoStack.shift();this._undoStack.push(t),this._redoStack.length=0,this._openLabel=void 0}cancel(){this._openGroup=null,this._openLabel=void 0}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}undo(){const t=this._undoStack.pop();if(t){for(let e=t.length-1;e>=0;e--)t[e].undo();this._redoStack.push(t)}}redo(){const t=this._redoStack.pop();if(t){for(const e of t)e.do();this._undoStack.push(t)}}clear(){this._undoStack.length=0,this._redoStack.length=0,this._openGroup=null,this._openLabel=void 0}}const _i=s=>(t,e)=>{e!==void 0?e.addInitializer((()=>{customElements.define(s,t)})):customElements.define(s,t)};const Rt=globalThis,Zt=Rt.ShadowRoot&&(Rt.ShadyCSS===void 0||Rt.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Ee=Symbol(),Te=new WeakMap;let Ii=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==Ee)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(Zt&&t===void 0){const i=e!==void 0&&e.length===1;i&&(t=Te.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&Te.set(e,t))}return t}toString(){return this.cssText}};const Ri=s=>new Ii(typeof s=="string"?s:s+"",void 0,Ee),Pi=(s,t)=>{if(Zt)s.adoptedStyleSheets=t.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet));else for(const e of t){const i=document.createElement("style"),r=Rt.litNonce;r!==void 0&&i.setAttribute("nonce",r),i.textContent=e.cssText,s.appendChild(i)}},_e=Zt?s=>s:s=>s instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return Ri(e)})(s):s;const{is:Ai,defineProperty:Oi,getOwnPropertyDescriptor:Li,getOwnPropertyNames:Di,getOwnPropertySymbols:Bi,getPrototypeOf:zi}=Object,Pt=globalThis,Ie=Pt.trustedTypes,ki=Ie?Ie.emptyScript:"",Ui=Pt.reactiveElementPolyfillSupport,yt=(s,t)=>s,Kt={toAttribute(s,t){switch(t){case Boolean:s=s?ki:null;break;case Object:case Array:s=s==null?s:JSON.stringify(s)}return s},fromAttribute(s,t){let e=s;switch(t){case Boolean:e=s!==null;break;case Number:e=s===null?null:Number(s);break;case Object:case Array:try{e=JSON.parse(s)}catch{e=null}}return e}},Re=(s,t)=>!Ai(s,t),Pe={attribute:!0,type:String,converter:Kt,reflect:!1,useDefault:!1,hasChanged:Re};Symbol.metadata??=Symbol("metadata"),Pt.litPropertyMetadata??=new WeakMap;class xt extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=Pe){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),r=this.getPropertyDescriptor(t,i,e);r!==void 0&&Oi(this.prototype,t,r)}}static getPropertyDescriptor(t,e,i){const{get:r,set:n}=Li(this.prototype,t)??{get(){return this[e]},set(a){this[e]=a}};return{get:r,set(a){const o=r?.call(this);n?.call(this,a),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??Pe}static _$Ei(){if(this.hasOwnProperty(yt("elementProperties")))return;const t=zi(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(yt("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(yt("properties"))){const e=this.properties,i=[...Di(e),...Bi(e)];for(const r of i)this.createProperty(r,e[r])}const t=this[Symbol.metadata];if(t!==null){const e=litPropertyMetadata.get(t);if(e!==void 0)for(const[i,r]of e)this.elementProperties.set(i,r)}this._$Eh=new Map;for(const[e,i]of this.elementProperties){const r=this._$Eu(e,i);r!==void 0&&this._$Eh.set(r,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const r of i)e.unshift(_e(r))}else t!==void 0&&e.push(_e(t));return e}static _$Eu(t,e){const i=e.attribute;return i===!1?void 0:typeof i=="string"?i:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Pi(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((t=>t.hostConnected?.()))}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),r=this.constructor._$Eu(t,i);if(r!==void 0&&i.reflect===!0){const n=(i.converter?.toAttribute!==void 0?i.converter:Kt).toAttribute(e,i.type);this._$Em=t,n==null?this.removeAttribute(r):this.setAttribute(r,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,r=i._$Eh.get(t);if(r!==void 0&&this._$Em!==r){const n=i.getPropertyOptions(r),a=typeof n.converter=="function"?{fromAttribute:n.converter}:n.converter?.fromAttribute!==void 0?n.converter:Kt;this._$Em=r;const o=a.fromAttribute(e,n.type);this[r]=o??this._$Ej?.get(r)??o,this._$Em=null}}requestUpdate(t,e,i){if(t!==void 0){const r=this.constructor,n=this[t];if(i??=r.getPropertyOptions(t),!((i.hasChanged??Re)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,e,i)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:r,wrapped:n},a){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,a??e??this[t]),n!==!0||a!==void 0)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),r===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[r,n]of this._$Ep)this[r]=n;this._$Ep=void 0}const i=this.constructor.elementProperties;if(i.size>0)for(const[r,n]of i){const{wrapped:a}=n,o=this[r];a!==!0||this._$AL.has(r)||o===void 0||this.C(r,void 0,n,o)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach((i=>i.hostUpdate?.())),this.update(e)):this._$EM()}catch(i){throw t=!1,this._$EM(),i}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach((e=>e.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach((e=>this._$ET(e,this[e]))),this._$EM()}updated(t){}firstUpdated(t){}}xt.elementStyles=[],xt.shadowRootOptions={mode:"open"},xt[yt("elementProperties")]=new Map,xt[yt("finalized")]=new Map,Ui?.({ReactiveElement:xt}),(Pt.reactiveElementVersions??=[]).push("2.1.1");class Ae{constructor(t,e){this.options=[],this.rootNode=e,this._el=document.createElement("div"),this._el.classList.add("context-menu"),t.options.forEach((i,r)=>{this.createOptionGroup(i),r!==t.options.length-1&&this.addDivider()}),this._el.addEventListener("contextmenu",i=>{i.preventDefault()})}get el(){return this._el}attachToParent(t){t.appendChild(this.el)}createOptionGroup(t){const e=new Wi(t,this.rootNode);this.options.push(e),this.el.appendChild(e.el)}addDivider(){const t=document.createElement("hr");t.classList.add("context-menu-divider"),this.el.appendChild(t)}}class Wi{constructor(t,e){this.childOptions=[],this.rootNode=e,this._el=document.createElement("div"),this.createOptionElement=this.createOptionElement.bind(this),t.childOptions.forEach(i=>this.createOptionElement(i))}get el(){return this._el}attachToParent(t){t.appendChild(this.el)}createOptionElement(t){t.parent=this;const e=new Fi(t,this.rootNode);this.childOptions.push(e)}}class Fi{get el(){return this._el}constructor(t,e){this.displayText=t.text,this.rootNode=e,this.parent=t.parent,this._el=document.createElement("button"),this._el.textContent=t.text,this._el.classList.add("context-menu-option"),this.parent.el.appendChild(this._el),"onClick"in t&&this._el.addEventListener("click",t.onClick),this._el.addEventListener("pointerenter",i=>Gi(i,t,this._el,this.rootNode)),this._el.addEventListener("contextmenu",i=>{i.preventDefault()})}}function Gi(s,t,e,i){if(!i)return;const r=i.querySelector(".sub-context-menu");if(r&&r.remove(),t.subMenu){const n=new Ae(t.subMenu,this);i.appendChild(n.el),n.el.id=`${t.text}-context-menu`,n.el.classList.add("sub-context-menu");const a=i.getBoundingClientRect(),o=e.getBoundingClientRect(),h=n.el.getBoundingClientRect(),c=a.right-a.left,l=a.bottom-a.top,u=o.right+h.width;o.top+h.height>l?n._el.style.top=`${o.bottom-h.height}px`:n._el.style.top=`${o.top}px`,u>c?n._el.style.left=`${o.left-h.width}px`:n._el.style.left=`${o.right}px`}}const At=5;function Ot(s){const t=this;return function(...e){const i=s.apply(t,e);return t.clearContextMenu(),i}}function Xi(s,t,e="single"){const i=new Ae(e==="single"?this.singleImageMenuOptions:e==="multi"?this.multiImageMenuOptions:this.canvasImageMenuOptions,this.rootDiv);if(!this.rootDiv){console.error("Can't add to parent div");return}i.attachToParent(this.rootDiv);const r=this.getBoundingClientRect(),n=s-r.left,a=t-r.top,o=r.right-r.left,h=r.bottom-r.top,c=i.el.getBoundingClientRect(),l=[n+c.width>o?1:0,a+c.height>h?1:0],u=c.height*l[1],m=c.width*l[0];if(u>h){const g=h-2*At;i._el.style.height=`${g}px`,i._el.style.top=`${At}px`}else i._el.style.top=`${a-u}px`;m>o?(i._el.style.width=`${o-2*At}px`,i._el.style.left=`${At}px`):i._el.style.left=`${n-m}px`}function Ni(){const s=this.renderRoot.querySelector(".context-menu");s&&(s.remove(),this.eventHub.emit(X.Close))}function Hi(){return this.renderRoot.querySelector(".context-menu")!==null}function Yi(){const s=Ot.bind(this);return{options:[{childOptions:[{text:"Cut",onClick:async()=>{await this.copyImage.bind(this)(),s(this.deleteSelectedImages.bind(this))()}},{text:"Copy",onClick:s(this.copyImage.bind(this))},{text:"Paste",onClick:t=>s(this.pasteImage.bind(this))(t)},{text:"Delete",onClick:s(this.deleteSelectedImages.bind(this))}]},{childOptions:[{text:"Flip Horizontal",onClick:s(this.flipHorizontal.bind(this))},{text:"Flip Vertical",onClick:s(this.flipVertical.bind(this))}]}]}}function $i(s){const t=Ot.bind(this);return{options:[...s??[],{childOptions:[{text:"Send to Front",onClick:()=>t(this.sendShapeToNewZOrder.bind(this))(!0)},{text:"Send to Back",onClick:()=>t(this.sendShapeToNewZOrder.bind(this))(!1)}]}]}}function ji(s){const t=Ot.bind(this);return{options:[...s??[],{childOptions:[{text:"Align",onHover:()=>{},subMenu:{options:[{childOptions:[{text:"Align Left",onClick:()=>t(this.align.bind(this))("left")},{text:"Align Right",onClick:()=>t(this.align.bind(this))("right")},{text:"Align Top",onClick:()=>t(this.align.bind(this))("top")},{text:"Align Bottom",onClick:()=>t(this.align.bind(this))("bottom")}]}]}},{text:"Normalize by First",onHover:()=>{},subMenu:{options:[{childOptions:[{text:"Height",onClick:()=>t(this.normalizeSelection.bind(this))("height","first")},{text:"Width",onClick:()=>t(this.normalizeSelection.bind(this))("width","first")},{text:"Size",onClick:()=>t(this.normalizeSelection.bind(this))("size","first")},{text:"Scale",onClick:()=>t(this.normalizeSelection.bind(this))("scale","first")}]}]}},{text:"Normalize by Average",onHover:()=>{},subMenu:{options:[{childOptions:[{text:"Height",onClick:()=>t(this.normalizeSelection.bind(this))("height","average")},{text:"Width",onClick:()=>t(this.normalizeSelection.bind(this))("width","average")},{text:"Size",onClick:()=>t(this.normalizeSelection.bind(this))("size","average")},{text:"Scale",onClick:()=>t(this.normalizeSelection.bind(this))("scale","average")}]}]}}]}]}}function Vi(s){const t=Ot.bind(this);return{options:[...s??[],{childOptions:[{text:"Change mode",onClick:()=>t(this.togglePointerMode.bind(this))()},{text:"Toggle Grid",onClick:()=>t(this.toggleGrid.bind(this))()}]},{childOptions:[{text:"Save",onClick:()=>t(this.saveToCanvasStorage.bind(this))()},{text:"Paste",onClick:e=>t(this.pasteImage.bind(this))(e)}]}]}}class Qt{_touch(){this._lastRetrieved=Date.now()}get id(){return this._touch(),this._id}get dataURL(){return this._touch(),this._dataURL}get mimetype(){return this._touch(),this._mimetype}get created(){return this._touch(),this._created}get lastRetrieved(){return this._lastRetrieved}constructor(t){this._dataURL=t,this._mimetype=Ke(t),this._created=Date.now(),this._lastRetrieved=Date.now()}static async create(t){const e=new Qt(t);return e._id=await Ht(t),e}}class qi{}class Zi{}function Oe(s){s.Version.prototype._parseStoresSpec=k.override(s.Version.prototype._parseStoresSpec,Ki),s.open=k.override(s.open,Ji(s))}function Ki(s){return function(t,e){s.call(this,t,e),Object.keys(e).forEach(function(i){let r=e[i];r.primKey.name.indexOf("$$")===0&&(r.primKey.uuid=!0,r.primKey.name=r.primKey.name.substr(2),r.primKey.keyPath=r.primKey.keyPath.substr(2))})}}function Qi(s){return function(e,i){let r;return e===void 0&&s.schema.primKey.uuid&&(e=r=Xe.v4(),s.schema.primKey.keyPath&&k.setByKeyPath(i,s.schema.primKey.keyPath,e)),r}}function Ji(s){return function(e){return function(){return Object.keys(s._allTables).forEach(i=>{let r=s._allTables[i];r.hook("creating").subscribe(Qi(r))}),e.apply(this,arguments)}}}k.UUIDPrimaryKey=Oe,k.addons.push(Oe),k.UUIDPrimaryKey;const ts={files:"$$id, mimetype, created, lastRetrieved"},Le={MAX_IMAGE_ENTRIES:1e3};class Lt extends qi{constructor(){super(),this.dbQueue=new Be,this.cache=new Map,this.CACHE_LIMIT=500,this.dbQueue=new Be,this.dbPromise=this.initDb()}async initDb(){return V(async()=>{let t=new k("InfiniteCanvas");return k.UUIDPrimaryKey(t),t.version(1).stores(ts),await t.open(),t})}async getIndexDb(){return this.dbPromise}async write(t){const e=await Qt.create(t),i=ss(e.dataURL);return this.dbQueue.add(()=>V(async()=>{const r=await this.getIndexDb();return await r.transaction("rw",r.files,async()=>(await is(r),await r.files.add({id:e.id,blob:i,dataURL:e.dataURL,mimetype:e.mimetype,created:e.created,lastRetrieved:e.lastRetrieved}))).catch(n=>{throw console.error("Failed to save image blob to local DB:",n),n})}))}async readAll(){return V(async()=>await(await this.getIndexDb()).files.toArray())}async readPage(t,e){return V(async()=>await(await this.getIndexDb()).files.offset(t).limit(e).toArray())}async read(t){return V(async()=>{const e=await this.getIndexDb();if(this.cache.has(t))return this.cache.get(t);const i=await e.files.get(t);if(!i)return null;if(this.dbQueue.add(async()=>{try{await e.files.update(t,{lastRetrieved:Date.now()})}catch(r){console.error("Failed to update lastRetrieved",r)}}).catch(()=>{}),this.cache.set(t,i),this.cache.size>this.CACHE_LIMIT){const r=this.cache.keys().next().value;this.cache.delete(r)}return i})}async delete(t){return this.dbQueue.add(()=>V(async()=>{const e=await this.getIndexDb();return await e.transaction("rw",e.files,async()=>{const i=await e.files.where("id").equals(t).first();return await e.files.delete(i.id),i}).catch(i=>{throw console.error("Failed to save image blob to local DB:",i),i})}))}async update(t){return this.dbQueue.add(()=>V(async()=>{const e=await this.getIndexDb();return await e.transaction("rw",e.files,async()=>{await e.files.update(t.id,{dataURL:t.dataURL,mimetype:t.mimetype,lastRetrieved:Date.now()})}),await e.files.where("id").equals(t.id).first()}))}async checkIfImageStored(t){return V(async()=>{const i=await(await this.getIndexDb()).files.where("id").equals(t).first();return i?i.id:null})}}class Jt extends Zi{constructor(t){super(),this.key="infinite_canvas",this.key=t}async write(t){return new Promise((e,i)=>{try{localStorage.setItem(this.key,JSON.stringify(t)),e()}catch(r){i(r)}})}async read(){return new Promise((t,e)=>{try{t(localStorage.getItem(this.key))}catch(i){e(i)}})}async delete(){return new Promise((t,e)=>{try{localStorage.removeItem(this.key),t()}catch(i){e(i)}})}async update(t){return this.write(t)}}class De extends Error{constructor(t){super(t),this.name="QuotaExceededError"}}class es extends Error{constructor(t){super(t),this.name="DatabaseLimitError"}}class Be{constructor(){this.queue=Promise.resolve()}async add(t){const e=this.queue.then(()=>t());return this.queue=e.catch(()=>{}),e}}const V=async s=>{try{return await s()}catch(t){throw t instanceof DOMException&&t.name==="QuotaExceededError"?new De("Storage quota exceeded. Please free up space."):t instanceof k.QuotaExceededError?new De("Database quota exceeded. Please free up space."):t}};async function is(s){if(await s.files.count()>=Le.MAX_IMAGE_ENTRIES)throw new es(`Cannot save image: limit of ${Le.MAX_IMAGE_ENTRIES} reached`)}function ss(s){const t=s.split(","),e=t[0],i=t[1],r=e.match(/:(.*?);/),n=r?r[1]:"application/octet-stream",a=atob(i),o=a.length,h=new Uint8Array(o);for(let c=0;c<o;c++)h[c]=a.charCodeAt(c);return new Blob([h],{type:n})}class rs{get el(){return this._el}constructor(t){this.type=t.type,this.message=t.message,this._el=document.createElement("div"),this._el.classList.add("canvas-loader"),this.render()}render(){if(this._el.innerHTML="",this.type==="spinner"){const t=document.createElement("div");if(t.classList.add("canvas-loader-spinner"),this._el.appendChild(t),this.message){const e=document.createElement("div");e.classList.add("canvas-loader-message"),e.textContent=this.message,this._el.appendChild(e)}}else if(this.type==="message"){const t=document.createElement("div");t.classList.add("canvas-loader-message"),t.textContent=this.message??"",this._el.appendChild(t)}}setMessage(t){this.message=t,this.render()}setProgress(t){this.progress=t,this.render()}attachToParent(t){t.appendChild(this.el)}remove(){this._el.parentNode&&this._el.parentNode.removeChild(this._el)}}function ns(s,t){const e=new rs({type:s,message:t});e.attachToParent(this.renderRoot);const i=this.getBoundingClientRect();return e.el.style.width=`${i.right}px`,e.el.style.height=`${i.bottom}px`,e._el.style.top=`${-i.bottom}px`,e}function as(){const s=this.renderRoot.querySelector(".canvas-loader");s&&s.remove()}var os=Object.getOwnPropertyDescriptor,ze=s=>{throw TypeError(s)},hs=(s,t,e,i)=>{for(var r=i>1?void 0:i?os(t,e):t,n=s.length-1,a;n>=0;n--)(a=s[n])&&(r=a(r)||r);return r},ke=(s,t,e)=>t.has(s)||ze("Cannot "+e),d=(s,t,e)=>(ke(s,t,"read from private field"),e?e.call(s):t.get(s)),D=(s,t,e)=>t.has(s)?ze("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),M=(s,t,e,i)=>(ke(s,t,"write to private field"),t.set(s,e),e),y,_,Dt,q,O,F,wt,Bt,vt,Ct,tt,ht,zt,kt,Ut;w.InfiniteCanvasElement=class extends z.LitElement{constructor(){super(...arguments),this.name="Reffy",this.displayMode="fullscreen",D(this,y),D(this,_),D(this,Dt),D(this,q),D(this,O),D(this,F),D(this,wt,3e5),D(this,Bt),D(this,vt),D(this,Ct),D(this,tt),D(this,ht),D(this,zt),D(this,kt),D(this,Ut),this.handleGlobalPointerDown=t=>{!this.contains(t.target)&&!this.renderRoot.contains(t.target)&&this.clearContextMenu()}}get singleImageMenuOptions(){return d(this,zt)}get multiImageMenuOptions(){return d(this,kt)}get canvasImageMenuOptions(){return d(this,Ut)}get canvas(){return d(this,y)}get onCanvasChange(){return d(this,ht)}set onCanvasChange(t){M(this,ht,t)}get eventHub(){return d(this,_)}get rootDiv(){return d(this,tt)}connectedCallback(){super.connectedCallback(),this.handleGlobalPointerDown=this.handleGlobalPointerDown.bind(this),document.addEventListener("pointerdown",this.handleGlobalPointerDown,!0)}disconnectedCallback(){document.removeEventListener("pointerdown",this.handleGlobalPointerDown,!0),window.removeEventListener("resize",d(this,Ct)),d(this,Dt)?.disconnect(),M(this,Dt,void 0),d(this,y).destroy(),super.disconnectedCallback()}firstUpdated(t){try{this.initCanvas()}catch(e){throw console.error(e),e}}updated(t){if(!(t.has("width")||t.has("height")||t.has("displayMode")))return;const i=d(this,tt),r=this.renderRoot.querySelector("canvas");i&&r&&this.resizeCanvas(i,r)}async initCanvas(){await this.warmUpStorage(),M(this,q,new Ti),M(this,_,new Ne);const t=document.createElement("div");t.style.overflow="hidden",this.renderRoot.appendChild(t),M(this,tt,t);const e=document.createElement("canvas");this.assignFileStorage=this.assignFileStorage.bind(this),this.getImageFileMetadata=this.getImageFileMetadata.bind(this),this.getAllImageFileMetdata=this.getAllImageFileMetdata.bind(this),this.saveImageFileMetadata=this.saveImageFileMetadata.bind(this),this.restoreStateFromCanvasStorage=this.restoreStateFromCanvasStorage.bind(this),this.assignCanvasStorage=this.assignCanvasStorage.bind(this),this.saveToCanvasStorage=this.saveToCanvasStorage.bind(this),this.debounceSaveToCanvasStorage=this.debounceSaveToCanvasStorage.bind(this),this.importCanvas=this.importCanvas.bind(this),this.exportCanvas=this.exportCanvas.bind(this),this.addContextMenu=Xi.bind(this),this.clearContextMenu=Ni.bind(this),this.isContextMenuActive=Hi.bind(this),this.getContainerSize=this.getContainerSize.bind(this),t.contains(e)||t.appendChild(e),this.registerSignal(),M(this,y,new pt(e,d(this,q),d(this,_),this.debounceSaveToCanvasStorage,this.saveImageFileMetadata,this.getContainerSize));try{await this.restoreStateFromCanvasStorage()}catch{console.error("Failed to restore canvas")}this.resizeCanvas(t,e),M(this,Ct,()=>this.resizeCanvas(t,e)),window.addEventListener("resize",d(this,Ct));const i=Yi.bind(this)();M(this,zt,$i.bind(this)(i.options)),M(this,Ut,Vi.bind(this)()),M(this,kt,ji.bind(this)(i.options)),this.dispatchEvent(new Event("load"));const r=new He;r.showPanel(0),this.renderRoot.contains(r.dom)||this.renderRoot.appendChild(r.dom);const n=()=>{r&&r.update(),d(this,y).render(),requestAnimationFrame(n)};n()}normalizeCssSize(t){if(!t)return t;const e=String(t).trim();return/^\d+$/.test(e)?`${e}px`:e}resizeCanvas(t,e){t.style.width=this.displayMode==="fullscreen"?"100vw":this.normalizeCssSize(this.width),t.style.height=this.displayMode==="fullscreen"?"100vh":this.normalizeCssSize(this.height),t.style.overflow="hidden";const i=window.devicePixelRatio||1;let r=window.screen.width,n=window.screen.height;const a=t.getBoundingClientRect(),o=Math.round(r*i),h=Math.round(n*i);(e.width!==o||e.height!==h)&&(e.width=o,e.height=h),e.style.width=`${r}px`,e.style.height=`${n}px`,this.canvas.camera.viewportX=a.x,this.canvas.camera.viewportY=a.y,this.canvas.camera.state.setHeight(a.height),this.canvas.camera.state.setWidth(a.width)}registerSignal(){d(this,_).on(rt.start,ns.bind(this),"spinner"),d(this,_).on(rt.done,as.bind(this)),d(this,_).on(X.Open,this.addContextMenu),d(this,_).on(X.Close,this.clearContextMenu),d(this,_).on(N.Change,()=>{d(this,ht)&&d(this,ht).call(this)}),d(this,_).on(nt.Save,this.saveToCanvasStorage),d(this,_).on(nt.SaveCompleted,()=>{}),d(this,_).on(nt.SaveFailed,()=>console.error("Failed to Save!"))}async warmUpStorage(){d(this,O)||M(this,O,new Lt);try{await d(this,O).readAll()}catch(t){console.error("Storage warm-up failed",t)}}getContainerSize(){if(!d(this,tt))return;const t=d(this,tt).getBoundingClientRect();return[t.width,t.height]}assignCanvasStorage(t,e=d(this,wt)){M(this,F,t),M(this,wt,e),d(this,vt)&&clearInterval(d(this,vt)),M(this,vt,setInterval(this.saveToCanvasStorage,d(this,wt)))}assignFileStorage(t){M(this,O,t)}async saveImageFileMetadata(t){d(this,O)||M(this,O,new Lt);try{const e=await Ht(t);return await d(this,O).checkIfImageStored(e)?e:await d(this,O).write(t)}catch(e){console.error(e)}}async getImageFileMetadata(t){d(this,O)||M(this,O,new Lt);try{return await d(this,O).read(t)}catch(e){console.error(e)}}async getAllImageFileMetdata(){d(this,O)||M(this,O,new Lt);try{return await d(this,O).readAll()}catch(t){console.error(t)}}debounceSaveToCanvasStorage(t=1e3){d(this,F)||M(this,F,new Jt(this.name)),clearTimeout(d(this,Bt)),M(this,Bt,setTimeout(this.saveToCanvasStorage,t))}async saveToCanvasStorage(){d(this,F)||M(this,F,new Jt(this.name)),d(this,F).write(Vt(d(this,y))).then(()=>d(this,_).emit(nt.SaveCompleted)).catch(()=>d(this,_).emit(nt.SaveFailed))}async restoreStateFromCanvasStorage(){d(this,F)||M(this,F,new Jt(this.name));const t=await d(this,F).read(),e=JSON.parse(t);e&&await qt(e,d(this,y),this.getImageFileMetadata)}togglePointerMode(){d(this,y)&&d(this,y).changeMode()}toggleGrid(){d(this,y)&&d(this,y).toggleGrid()}zoomIn(){d(this,y)&&d(this,y).updateZoomByFixedAmount(-1)}zoomOut(){d(this,y)&&d(this,y).updateZoomByFixedAmount()}async addImages(t){if(!d(this,y))return;const e=d(this,y).getBoundingClientRect(),i=e.left+e.width/2,r=e.top+e.height/2,[n,a]=K(i,r,d(this,y)),o=await Qe(t,h=>d(this,y).addImageToCanvas(h,n,a,1,1,!0));d(this,q).push(_t(d(this,y),o))}async removeImage(t){if(!d(this,y))return;const e=d(this,y).getChild(t);d(this,y).removeChild(e),d(this,q).push(ii(d(this,y),e))}async addImageFromUrl(t){if(!d(this,y))return;const e=d(this,y).getBoundingClientRect(),i=e.left+e.width/2,r=e.top+e.height/2,[n,a]=K(i,r,d(this,y)),o=await d(this,y).addImageToCanvas(t,n,a,1,1,!0);d(this,q).push(_t(d(this,y),[o]))}async copyImage(){d(this,y)&&await oe(d(this,y).getSelected())}async pasteImage(t){d(this,y)&&await he(t.clientX,t.clientY,d(this,y),d(this,q),!1)}flipVertical(){d(this,y)&&d(this,y).selectionManager.flip("vertical")}flipHorizontal(){d(this,y)&&d(this,y).selectionManager.flip("horizontal")}align(t){d(this,y)&&d(this,y).selectionManager.alignSelection(t)}normalizeSelection(t,e){d(this,y)&&d(this,y).selectionManager.normalize(t,e)}sendShapeToNewZOrder(t){d(this,y)&&d(this,y).setShapeZOrder(t)}deleteSelectedImages(){d(this,y)&&d(this,y).selectionManager.deleteSelected(d(this,y))}async exportCanvas(t="infinite-canvas.json"){if(!d(this,y))return;d(this,_).emit(rt.start,"spinner");const e=await this.getAllImageFileMetdata(),i=Vt(d(this,y),e);Je(t,i),d(this,_).emit(rt.done)}async importCanvas(t){if(d(this,_).emit(rt.start,"spinner"),!d(this,y)||!t||t.length!==1)return;const e=t[0];if(!e.type||!e.type.includes("json")&&!e.name.toLowerCase().endsWith(".json"))return;const i=await ti(e);await qt(i,d(this,y),this.getImageFileMetadata,this.saveImageFileMetadata),d(this,_).emit(nt.Save),d(this,_).emit(rt.done)}clearCanvas(){d(this,y)&&d(this,y).clearChildren()}getTotalNumberOfChildren(){if(d(this,y))return d(this,y).totalNumberOfChildren}getNumberOfChildrenRendered(){if(d(this,y))return d(this,y).numberOfChildrenRendered}},y=new WeakMap,_=new WeakMap,Dt=new WeakMap,q=new WeakMap,O=new WeakMap,F=new WeakMap,wt=new WeakMap,Bt=new WeakMap,vt=new WeakMap,Ct=new WeakMap,tt=new WeakMap,ht=new WeakMap,zt=new WeakMap,kt=new WeakMap,Ut=new WeakMap,w.InfiniteCanvasElement.properties={name:{type:String,reflect:!0},width:{type:String,reflect:!0},height:{type:String,reflect:!0},displayMode:{type:String,reflect:!0}},w.InfiniteCanvasElement.styles=z.css`
|
|
148
148
|
:host {
|
|
149
149
|
position: relative;
|
|
150
150
|
overflow: hidden;
|
|
@@ -272,5 +272,5 @@ void main() {
|
|
|
272
272
|
max-width: 80%;
|
|
273
273
|
word-break: break-word;
|
|
274
274
|
}
|
|
275
|
-
`,w.InfiniteCanvasElement=
|
|
275
|
+
`,w.InfiniteCanvasElement=hs([_i("infinite-canvas")],w.InfiniteCanvasElement);class te{constructor(t){if(!t)throw new Error("InfiniteCanvasElement is required");this.el=t,this.assignCanvasStorage=this.assignCanvasStorage.bind(this),this.zoomIn=this.zoomIn.bind(this),this.zoomOut=this.zoomOut.bind(this),this.toggleMode=this.toggleMode.bind(this),this.addImageFromLocal=this.addImageFromLocal.bind(this),this.exportCanvas=this.exportCanvas.bind(this),this.importCanvas=this.importCanvas.bind(this),this.clearCanvas=this.clearCanvas.bind(this)}static async forElement(t){let e;if(typeof t=="string"?(await customElements.whenDefined("infinite-canvas"),e=document.querySelector(t)):e=t,!e)throw new Error("infinite-canvas element not found");return e.canvas||await new Promise(i=>e.addEventListener("load",()=>i(),{once:!0})),new te(e)}assignCanvasStorage(t,e=3e3){return this.el.assignCanvasStorage(t,e),this}async zoomIn(){console.log("zooming"),this.el.zoomIn()}async zoomOut(){this.el.zoomOut()}async toggleMode(){this.el.togglePointerMode()}async addImageFromLocal(t){if(!(!t||t.length===0)){for(let e=0;e<t.length;e++){const i=t[e];if(!i||!i.type||!i.type.startsWith("image/"))throw new Error("Only specific image files are supported. Please select image files only.")}await this.el.addImages(t)}}async exportCanvas(t){this.el.exportCanvas(t)}async importCanvas(t){!t||t.length!==1||await this.el.importCanvas(t)}async clearCanvas(){this.el.clearCanvas()}}w.Camera=ve,w.Canvas=pt,w.InfiniteCanvasAPI=te,w.ZOOM_MAX=we,w.ZOOM_MIN=xe,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})}));
|
|
276
276
|
//# sourceMappingURL=index.umd.js.map
|