@jucie.io/engine-painter 1.0.58 → 1.0.60

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/main.js CHANGED
@@ -1,2 +1,2 @@
1
- var u={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var m=class{#e=new Map;register(t,s){if(!t)throw new Error("Hit area must have an id");return this.#e.set(t,{id:t,...s}),()=>this.unregister(t)}unregister(t){this.#e.delete(t)}get(t){return this.#e.get(t)}has(t){return this.#e.has(t)}get areas(){return Array.from(this.#e.values())}clear(){this.#e.clear()}};import{ServiceProvider as T}from"@jucie.io/engine";var p=class extends T{#e=null;#l=null;#r=null;#n=null;#S=new Set;#g=new Set;#d=null;#f=null;#w=!1;#i=new Set;#t={isPressed:!1,button:null,dragStartX:null,dragStartY:null,isDragging:!1,dragThreshold:5,prevX:null,prevY:null,lastClickTime:null,lastClickX:null,lastClickY:null,doubleClickThreshold:300,doubleClickDistanceThreshold:5,isExternalDragOver:!1,externalDragData:null};static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:t=>this.setCanvas(t),subscribe:t=>this.subscribe(t),onResize:t=>this.onResize(t),transferControlToOffscreen:()=>this.transferControlToOffscreen(),onFileDrop:t=>this.#x(t)}}setCanvas(t){this.#e&&this.#p(),this.#e=t,this.#a(),this.#m()}subscribe(t){return this.#S.add(t),()=>this.#S.delete(t)}onResize(t){return this.#g.add(t),()=>this.#g.delete(t)}transferControlToOffscreen(){if(!this.#e)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#w)throw new Error("Control has already been transferred to offscreen");return this.#l=this.#e.transferControlToOffscreen(),this.#w=!0,this.#l.width=this.#r.width,this.#l.height=this.#r.height,this.#L({width:this.#e.width,height:this.#e.height}),this.#l}#x(t){return this.#i.add(t),()=>this.#i.delete(t)}#C(...t){for(let s of this.#i)s(...t)}#a(){this.#e&&(this.#r=this.#e.getBoundingClientRect())}#m(){this.#e&&(this.#a(),this.#n=new ResizeObserver(t=>{for(let s of t){if(s.target!==this.#e)continue;let{width:i,height:r}=s.contentRect;this.#L({width:i,height:r})}this.#a()}),this.#n.observe(this.#e),this.#e.addEventListener("wheel",this.#u,{passive:!1}),this.#e.addEventListener("pointerdown",this.#E),this.#e.addEventListener("dragenter",this.#P),this.#e.addEventListener("dragover",this.#k),this.#e.addEventListener("dragleave",this.#D),this.#e.addEventListener("drop",this.#T),document.addEventListener("pointermove",this.#b),document.addEventListener("pointerup",this.#y),document.addEventListener("pointercancel",this.#R))}#p(){this.#n&&(this.#n.disconnect(),this.#n=null),this.#e&&(this.#e.removeEventListener("wheel",this.#u),this.#e.removeEventListener("pointerdown",this.#E),this.#e.removeEventListener("dragenter",this.#P),this.#e.removeEventListener("dragover",this.#k),this.#e.removeEventListener("dragleave",this.#D),this.#e.removeEventListener("drop",this.#T)),document.removeEventListener("pointermove",this.#b),document.removeEventListener("pointerup",this.#y),document.removeEventListener("pointercancel",this.#R)}#u=t=>{if(t.preventDefault(),t.stopPropagation(),t.ctrlKey){let s=this.#h(t,"zoom");this.#o(s)}else{let s=this.#h(t,"scroll");this.#o(s)}};#b=t=>{this.#d=t,!this.#f&&(this.#f=requestAnimationFrame(()=>{if(this.#d){let s=this.#d;this.#d=null;let i="move",r=this.#v(s);if(this.#t.isPressed&&!this.#t.isDragging){let n=r.x-this.#t.dragStartX,o=r.y-this.#t.dragStartY;Math.sqrt(n*n+o*o)>this.#t.dragThreshold&&(this.#t.isDragging=!0,i="dragstart")}else this.#t.isDragging&&(i="drag");let a=this.#h(s,i);this.#o(a)}this.#f=null}))};#E=t=>{let s=this.#v(t);this.#t.isPressed=!0,this.#t.button=t.button??null,this.#t.dragStartX=s.x,this.#t.dragStartY=s.y,this.#t.isDragging=!1;try{this.#e.setPointerCapture(t.pointerId)}catch(r){console.warn("Failed to capture pointer:",r)}let i=this.#h(t,"down");this.#o(i)};#y=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let i=this.#h(t,"dragend");this.#o(i)}if(!this.#t.isDragging){let i=this.#v(t),r=Date.now();if(this.#t.lastClickTime!==null){let a=r-this.#t.lastClickTime,n=i.x-this.#t.lastClickX,o=i.y-this.#t.lastClickY,h=Math.sqrt(n*n+o*o);if(a<this.#t.doubleClickThreshold&&h<this.#t.doubleClickDistanceThreshold){let l=this.#h(t,"dblclick");this.#o(l),this.#t.lastClickTime=null,this.#t.lastClickX=null,this.#t.lastClickY=null}else this.#t.lastClickTime=r,this.#t.lastClickX=i.x,this.#t.lastClickY=i.y}else this.#t.lastClickTime=r,this.#t.lastClickX=i.x,this.#t.lastClickY=i.y}let s=this.#h(t,"up");this.#o(s),this.#t.isPressed=!1,this.#t.isDragging=!1,this.#t.dragStartX=null,this.#t.dragStartY=null};#R=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let i=this.#h(t,"dragend");this.#o(i)}let s=this.#h(t,"cancel");this.#o(s),this.#t.isPressed=!1,this.#t.isDragging=!1,this.#t.dragStartX=null,this.#t.dragStartY=null};#P=t=>{t.preventDefault(),this.#t.isExternalDragOver=!0,this.#t.externalDragData=this.#A(t.dataTransfer);let s=this.#h(t,"dragenter");this.#o(s)};#k=t=>{t.preventDefault(),t.dataTransfer.dropEffect=this.#t.externalDragData?.hasFiles?"copy":"move";let s=this.#h(t,"dragover");this.#o(s)};#D=t=>{t.preventDefault();let s=this.#e.getBoundingClientRect();if(t.clientX<s.left||t.clientX>=s.right||t.clientY<s.top||t.clientY>=s.bottom){this.#t.isExternalDragOver=!1,this.#t.externalDragData=null;let r=this.#h(t,"dragleave");this.#o(r)}};#T=t=>{t.preventDefault(),this.#t.isExternalDragOver=!1,this.#t.externalDragData=this.#A(t.dataTransfer);let s=this.#h(t,"drop"),i=this.#O(t.dataTransfer);this.#C(i,s),this.#o(s),this.#t.externalDragData=null};#O(t){let s=[];if(t?.items){console.log("\u{1F4E6} Processing",t.items.length,"items");for(let i of e.dataTransfer.items)if(i.kind==="file"){let r=i.getAsFile();r&&s.push(r)}}if(s.length===0&&t?.files){console.log("\u{1F4E6} Fallback to DataTransfer.files:",t.files.length,"files");for(let i=0;i<t.files.length;i++){let r=t.files[i];r&&s.push(r)}}return s}#A(t){return t?{types:Array.from(t.types),hasFiles:t.types.includes("Files"),fileCount:t.items?.length||0,effectAllowed:t.effectAllowed}:null}#o(t){for(let s of this.#S)s(t)}#L(t){for(let s of this.#g)s(t)}#v(t){let s=t.target===this.#e,i,r;return s?(i=t.offsetX,r=t.offsetY):this.#r?(i=t.clientX-this.#r.left,r=t.clientY-this.#r.top):(i=t.clientX,r=t.clientY),{x:i,y:r,isOverCanvas:s}}#h(t,s){let{x:i,y:r,isOverCanvas:a}=this.#v(t),n=a||this.#r&&i>=0&&i<=this.#r.width&&r>=0&&r<=this.#r.height,o=0,h=0,l=0,c=0;s==="scroll"?(o=t.deltaX,h=t.deltaY,l=t.deltaZ,c=t.deltaMode):s==="zoom"?(o=0,h=t.deltaY,l=0):(s==="move"||s==="drag"||s==="dragstart")&&this.#t.prevX!==null&&this.#t.prevY!==null&&(o=i-this.#t.prevX,h=r-this.#t.prevY);let x=0;if(this.#t.isDragging&&this.#t.dragStartX!==null&&this.#t.dragStartY!==null){let g=i-this.#t.dragStartX,E=r-this.#t.dragStartY;x=Math.sqrt(g*g+E*E)}let C={x:i,y:r,clientX:t.clientX,clientY:t.clientY,prevX:this.#t.prevX,prevY:this.#t.prevY,type:s,timestamp:Date.now(),isOverCanvas:a,isWithinBounds:n,deltaX:o,deltaY:h,deltaZ:l,deltaMode:c,button:t.button??this.#t.button,buttons:t.buttons??0,isPressed:this.#t.isPressed,isDragging:this.#t.isDragging,dragStartX:this.#t.dragStartX,dragStartY:this.#t.dragStartY,dragDistance:x,shiftKey:t.shiftKey||!1,ctrlKey:t.ctrlKey||!1,altKey:t.altKey||!1,metaKey:t.metaKey||!1,isExternalDragOver:this.#t.isExternalDragOver,externalDragData:this.#t.externalDragData};return s==="drop"&&t.dataTransfer&&(C.dataTransfer={items:Array.from(t.dataTransfer.items).map(g=>({kind:g.kind,type:g.type})),types:Array.from(t.dataTransfer.types)}),this.#t.prevX=i,this.#t.prevY=r,C}destroy(){this.#f&&(cancelAnimationFrame(this.#f),this.#f=null),this.#p(),this.#e=null,this.#l=null,this.#r=null,this.#S.clear(),this.#g.clear(),this.#w=!1,this.#t.isPressed=!1,this.#t.button=null,this.#t.dragStartX=null,this.#t.dragStartY=null,this.#t.isDragging=!1,this.#t.prevX=null,this.#t.prevY=null,this.#t.lastClickTime=null,this.#t.lastClickX=null,this.#t.lastClickY=null,this.#t.isExternalDragOver=!1,this.#t.externalDragData=null}};import{defineSurface as P}from"@jucie.io/reactive";var y=P(d=>{let t=d.signal(null),s=d.signal(null),i=d.signal(null),r=d.action((h,l)=>{t(l)}),a=d.action((h,l)=>{s(l)}),n=d.action((h,l)=>{i(l)}),o=d.action(()=>{t(null),s(null),i(null)});return{event:t,hoveredArea:s,activeArea:i,handleEvent:r,setHoveredArea:a,setActiveArea:n,reset:o}});import{ServiceProvider as k}from"@jucie.io/engine";import{createComputed as A,destroyComputed as S,addEffect as L}from"@jucie.io/reactive";import{createDefinition as b,definitionType as v}from"@jucie.io/engine";var f={BRUSH:"BRUSH",LAYER:"LAYER",SUBSCRIPTION:"SUBSCRIPTION",SUBSCRIPTIONS:"SUBSCRIPTIONS"},R="GLOBAL_LAYER",O=b(f.BRUSH,[Object]),D=b(f.LAYER,[Object]),Y=b(f.SUBSCRIPTION,[Function]),B=b(f.SUBSCRIPTIONS,[Object]),w=class extends k{#e=new Map;#l=new Map;#r=null;#n=new Map;#S=new Map;#g=!1;#d=null;#f=!1;#w=!1;#i={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#t={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#x={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#C=new m;#a=y();#m=null;#p=null;#u=null;#b=new Map;#E=!1;static manifest={name:"Painter",namespace:"painter",version:"1.0.0",defaults:{targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}}};getters(){return{pointer:()=>this.#a}}initialize(){this.#y(D(R,()=>({context:u["2D"]})))}actions(){return this.config&&Object.assign(this.#i,this.config),{addLayer:t=>this.#y(t),addLayers:(...t)=>{for(let s of t)this.#y(s)},use:(...t)=>this.use(t),updateCanvas:t=>this.updateCanvas(t),setCanvas:t=>this.setCanvas(t),setOffscreenCanvas:t=>this.setOffscreenCanvas(t),setAssets:t=>this.setAssets(t),removeLayer:t=>this.#D(t),start:()=>this.start(),stop:()=>this.stop(),render:()=>this.render(),setTargetFPS:t=>this.setTargetFPS(t),setTimeScale:t=>this.setTimeScale(t),setFixedTimeStep:t=>this.setFixedTimeStep(t),setDebug:t=>this.setDebug(t),getMetrics:()=>this.getMetrics(),handleResize:(t,s)=>this.handleResize(t,s),subscribe:(t,s)=>this.subscribe(t,s),handlePointerEvent:t=>this.handlePointerEvent(t),subscribeToPointer:t=>this.#a.$subscribe(t),bindPointer:t=>this.#a.$bind(t),_testEmitPointerEvent:t=>this._testEmitPointerEvent(t)}}use(t){for(let s of t){let i=v(s);switch(i){case f.BRUSH:this.#R(R,s);break;case f.LAYER:this.#y(s);break;case f.SUBSCRIPTION:this.#P(s);break;case f.SUBSCRIPTIONS:this.#k(s);break;default:throw new Error(`Invalid factory type: ${i}`)}}return this}setCanvas(t){let s=t,i=t.transferControlToOffscreen();i.width=s.width,i.height=s.height,this.#r=i,Object.values(u).forEach(r=>{try{let a=i.getContext(r);a&&this.#n.set(r,a)}catch{console.warn(`Context type ${r} not supported`)}}),this.#m||(this.#m=new p),this.#m.setCanvas(s),this.#u&&this.#u.disconnect(),this.#u=new ResizeObserver(r=>{let a=r[0];a&&a.target===s&&(i.width=s.width,i.height=s.height,this.handleResize(s.width,s.height))}),this.#u.observe(s),this.#p&&this.#p(),this.#p=this.#m.subscribe(r=>{this.handlePointerEvent(r)})}setOffscreenCanvas(t){this.#r=t,Object.values(u).forEach(s=>{try{let i=t.getContext(s);i&&this.#n.set(s,i)}catch{console.warn(`Context type ${s} not supported`)}})}updateCanvas(t){let s=t(this.#r);s&&(this.#r=s)}setAssets(t){this.#S=t}start(){this.#g||(this.#g=!0,this.#T())}stop(){this.#g&&(this.#g=!1,this.#d&&(cancelAnimationFrame(this.#d),this.#d=null))}#y(t){if(v(t)!=="LAYER")throw new Error("Invalid layer definition");let s=t._name,i=t(this.useContext,this.#C),r={...i,name:s,context:this.#n.get(i.context||"2d")};if(i.data&&(r.dataReactor=this.#v(i.data,()=>this.#a)),i.when&&(r.whenReactor=this.#v(i.when,()=>r?.dataReactor?.computed()||void 0)),i.children&&i.children.length>0)for(let a of i.children)v(a)==="BRUSH"&&this.#R(s,a),v(a)==="LAYER"&&this.#y(a);if(this.#e.set(s,r),r.lifecycle?.onMount)try{r.lifecycle.onMount(r.context)}catch(a){console.error(`Error in layer "${s}" onMount:`,a)}return r}#R(t,s){let i=s._name,r=s(this.useContext,this.#C),a={name:i,...r};if(r.data&&(a.dataReactor=this.#v(r.data,()=>this.#a)),r.when&&(a.whenReactor=this.#v(r.when,()=>a?.dataReactor?.computed()||void 0)),a.lifecycle?.onMount)try{a.lifecycle.onMount(this.#n.get(a.context||this.#e.get(t)?.context))}catch(n){console.error(`Error in brush "${a.name}" onMount:`,n)}return this.#l.has(t)||this.#l.set(t,[]),this.#l.get(t).push(a),a}#P(t){let s=t._name,i=t(this.useContext);this.subscribe(s,i)}#k(t){let s=t._name,i=t(this.useContext);for(let[r,a]of Object.entries(i)){let n=s?`${s}:${r}`:r;this.subscribe(n,a)}}#D(t){let s=this.#e.get(t);if(!s)return;if(s.lifecycle?.onUnmount)try{s.lifecycle.onUnmount(s.context)}catch(r){console.error(`Error in layer "${t}" onUnmount:`,r)}let i=this.#l.get(t)||[];this.#l.delete(t);for(let r of i){if(r.lifecycle?.onUnmount)try{r.lifecycle.onUnmount(this.#n.get(r.context||s.context))}catch(a){console.error(`Error in brush "${r.name}" onUnmount:`,a)}r.whenReactor&&S(r.whenReactor),r.dataReactor&&(r.dataReactor?.unsubscribe(),r.dataReactor?.computed&&S(r.dataReactor.computed))}s.whenReactor&&(s.whenReactor?.unsubscribe(),s.whenReactor?.computed&&S(s.whenReactor.computed)),this.#e.delete(t)}#T(){this.#w||this.#f||(this.#w=!0,this.#d=requestAnimationFrame(()=>{this.#w=!1,this.#d=null,this.#O()}))}async#O(){if(this.#r){this.#f=!0;try{this.#C.clear();let t=this.#i.debug?.enabled?performance.now():0;this.#n.forEach(s=>{s.clearRect(0,0,this.#r.width,this.#r.height)});for(let s of this.#e.values()){let i=this.#i.debug?.enabled?performance.now():0;if(s.whenReactor&&!s.whenReactor.computed())continue;let r=s.context;if(!r)continue;if(s.lifecycle?.beforeRender)try{s.lifecycle.beforeRender(r,this.#t)}catch(n){console.error(`Error in layer "${s.name}" beforeRender:`,n),s.lifecycle?.onError&&s.lifecycle.onError(n)}r.save(),s.settings&&Object.entries(s.settings).forEach(([n,o])=>{typeof r[n]=="function"?r[n](...Array.isArray(o)?o:[o]):r[n]=o});let a=this.#l.get(s.name)||[];for(let n of a){let o=this.#i.debug?.enabled?performance.now():0;if(n.whenReactor&&!n.whenReactor.computed())continue;let h=n.context?this.#n.get(n.context):r;if(h){if(n.lifecycle?.beforeRender)try{n.lifecycle.beforeRender(h,this.#t)}catch(l){console.error(`Error in brush "${n.name}" beforeRender:`,l),n.lifecycle?.onError&&n.lifecycle.onError(l);continue}h.save(),n.settings&&Object.entries(n.settings).forEach(([l,c])=>{typeof h[l]=="function"?h[l](...Array.isArray(c)?c:[c]):h[l]=c});try{let l={};if(n.assets)for(let c of n.assets)l[c]=this.#S.get(c);if(n.render(h,n.dataReactor?n.dataReactor.computed():void 0,l,this.#t),n.lifecycle?.afterRender&&n.lifecycle.afterRender(h,this.#t),this.#i.debug?.enabled){let c=performance.now()-o;this.#x.brushTimes.set(n.name,c),this.#i.debug?.showBounds&&this.#A(h,n)}}catch(l){console.error(`Error in brush "${n.name}":`,l),n.lifecycle?.onError&&n.lifecycle.onError(l)}finally{h.restore()}}}if(r.restore(),s.lifecycle?.afterRender)try{s.lifecycle.afterRender(r,this.#t)}catch(n){console.error(`Error in layer "${s.name}" afterRender:`,n),s.lifecycle?.onError&&s.lifecycle.onError(n)}if(this.#i.debug?.enabled){let n=performance.now()-i;this.#x.layerTimes.set(s.name,n),this.#i.debug?.showBounds&&this.#o(r,s)}}this.#i.debug?.enabled&&this.#L()}finally{this.#f=!1}}}#A(t,s){t.save(),t.strokeStyle="rgba(0, 255, 0, 0.5)",t.lineWidth=1,t.strokeRect(0,0,t.canvas.width,t.canvas.height),t.restore()}#o(t,s){t.save(),t.strokeStyle="rgba(255, 0, 0, 0.5)",t.lineWidth=2,t.strokeRect(0,0,t.canvas.width,t.canvas.height),t.restore()}#L(){let t=this.#n.get(u["2D"]);if(!t)return;t.save(),t.resetTransform(),t.font="12px monospace",t.fillStyle="white",t.strokeStyle="black",t.lineWidth=3;let s=20,i=15;if(this.#i.debug?.showFPS){let r=`FPS: ${Math.round(this.#x.fps)} (${this.#t.deltaTime.toFixed(2)}ms)`;t.strokeText(r,10,s),t.fillText(r,10,s),s+=i}if(this.#i.debug?.showLayerTiming){t.fillText("Layer Times:",10,s),s+=i;for(let[r,a]of this.#x.layerTimes){let n=` ${r}: ${a.toFixed(2)}ms`;t.strokeText(n,10,s),t.fillText(n,10,s),s+=i}t.fillText(this.state.get(["_transitions","pointer","currentState"]),10,s)}t.restore()}handleResize(t,s){for(let i of this.#e.values())if(i.lifecycle?.onResize)try{i.lifecycle.onResize(t,s,i.context)}catch(r){console.error(`Error in layer "${i.name}" onResize:`,r),i.lifecycle?.onError&&i.lifecycle.onError(r)}}#v(t,s=()=>{}){if(!t)return null;let i=A(t,{immediate:!0,context:s}),r=L(i,()=>this.#T());return{computed:i,unsubscribe:r}}destroy(){this.stop(),this.#p&&(this.#p(),this.#p=null),this.#m&&(this.#m.destroy(),this.#m=null),this.#u&&(this.#u.disconnect(),this.#u=null),this.#a&&this.#a.$destroy();for(let t of this.#e.keys())this.#D(t)}setTargetFPS(t){this.#i.targetFPS=t,this.#i.fixedTimeStep=1e3/t}setTimeScale(t){this.#i.timeScale=Math.max(0,t)}setFixedTimeStep(t){this.#i.fixedTimeStep=t}setDebug(t={}){this.#i.debug||(this.#i.debug={}),Object.assign(this.#i.debug,t)}getMetrics(){return{...this.#x,deltaTime:this.#t.deltaTime,elapsedTime:this.#t.elapsedTime,frameCount:this.#t.frameCount}}handlePointerEvent(t){this.#a.handleEvent(t),this.#B(t),this.#h(t)}#h(t){let{type:s}=t,i=this.#a,r=i.event;switch(s){case"down":this.#s("pointer:down",i);break;case"up":this.#s("pointer:up",i),r&&!r.isDragging&&this.#s("pointer:click",i);break;case"move":this.#s("pointer:move",i);break;case"dragstart":this.#s("pointer:drag:start",i);break;case"drag":this.#s("pointer:drag:move",i);break;case"dragend":this.#s("pointer:drag:end",i);break;case"scroll":this.#s("pointer:scroll",i);break;case"zoom":this.#s("pointer:zoom",i);break;case"dblclick":this.#s("pointer:dblclick",i);break}let a=this.#E,n=r?.isOverCanvas||!1;n&&!a?this.#s("pointer:enter",i):!n&&a&&this.#s("pointer:leave",i),this.#E=n}#B(t){let{type:s,x:i,y:r}=t,a=this.#a;switch(s){case"down":{let o=this.#Y(i,r);if(a.setActiveArea(o),o?.onPointerDown?.handler){let h=this.#c(o);o.onPointerDown.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"up":{let o=a.activeArea;if(o?.onPointerUp?.handler){let h=this.#c(o);o.onPointerUp.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"move":{let o=this.#Y(i,r),h=a.hoveredArea;if(o?.onPointerMove?.handler&&!t.isDragging){let l=this.#c(o);o.onPointerMove.handler({event:t,ctx:l,emit:this.#s.bind(this)})}if(o?.id!==h?.id){if(h?.onPointerLeave?.handler){let l=this.#c(h);h.onPointerLeave.handler({event:t,ctx:l,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let l=this.#c(o);o.onPointerEnter.handler({event:t,ctx:l,emit:this.#s.bind(this)})}a.setHoveredArea(o)}break}case"dragstart":{let o=a.activeArea;if(o?.onDragStart?.handler){let h=this.#c(o);o.onDragStart.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"drag":{let o=this.#Y(i,r),h=a.hoveredArea;if(o?.id!==h?.id){if(h?.onPointerLeave?.handler){let c=this.#c(h);h.onPointerLeave.handler({event:t,ctx:c,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let c=this.#c(o);o.onPointerEnter.handler({event:t,ctx:c,emit:this.#s.bind(this)})}a.setHoveredArea(o)}let l=a.activeArea;if(l?.onDragMove?.handler){let c=this.#c(l);l.onDragMove.handler({event:t,ctx:c,emit:this.#s.bind(this)})}break}case"dragend":{let o=a.activeArea;if(o?.onDragEnd?.handler){let h=this.#c(o);o.onDragEnd.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"dblclick":let n=a.activeArea;if(n?.onPointerDblClick?.handler){let o=this.#c(n);n.onPointerDblClick.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}}#c(t){return t?t.context?this.#n.get(t.context):this.#n.get(u["2D"]):null}subscribe(t,s){return this.#b.has(t)||this.#b.set(t,new Set),this.#b.get(t).add(s),()=>{let i=this.#b.get(t);i&&(i.delete(s),i.size===0&&this.#b.delete(t))}}#Y(t,s){let i=this.#C.areas.sort((r,a)=>(a.priority||0)-(r.priority||0));for(let r of i)if(this.#M(t,s,r.bounds))return r;return null}#M(t,s,i){return t>=i.x&&t<=i.x+i.width&&s>=i.y&&s<=i.y+i.height}#s(t,s){let i=this.#b.get(t);if(i)for(let r of i)r(s)}_testEmitPointerEvent(t){this.#a.handleEvent(t),this.#B(t)}};export{p as CanvasEvents,m as HitRegistry,w as Painter,O as defineBrush,D as defineLayer,Y as defineSubscription,B as defineSubscriptions,y as usePointerSurface};
1
+ var u={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var m=class{#e=new Map;register(t,s){if(!t)throw new Error("Hit area must have an id");return this.#e.set(t,{id:t,...s}),()=>this.unregister(t)}unregister(t){this.#e.delete(t)}get(t){return this.#e.get(t)}has(t){return this.#e.has(t)}get areas(){return Array.from(this.#e.values())}clear(){this.#e.clear()}};import{ServiceProvider as T}from"@jucie.io/engine";var p=class extends T{#e=null;#l=null;#r=null;#n=null;#S=new Set;#g=new Set;#d=null;#f=null;#w=!1;#i=new Set;#t={isPressed:!1,button:null,dragStartX:null,dragStartY:null,isDragging:!1,dragThreshold:5,prevX:null,prevY:null,lastClickTime:null,lastClickX:null,lastClickY:null,doubleClickThreshold:300,doubleClickDistanceThreshold:5,isExternalDragOver:!1,externalDragData:null};static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:t=>this.setCanvas(t),subscribe:t=>this.subscribe(t),onResize:t=>this.onResize(t),transferControlToOffscreen:()=>this.transferControlToOffscreen(),onFileDrop:t=>this.#x(t)}}setCanvas(t){this.#e&&this.#p(),this.#e=t,this.#a(),this.#m()}subscribe(t){return this.#S.add(t),()=>this.#S.delete(t)}onResize(t){return this.#g.add(t),()=>this.#g.delete(t)}transferControlToOffscreen(){if(!this.#e)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#w)throw new Error("Control has already been transferred to offscreen");return this.#l=this.#e.transferControlToOffscreen(),this.#w=!0,this.#l.width=this.#r.width,this.#l.height=this.#r.height,this.#L({width:this.#e.width,height:this.#e.height}),this.#l}#x(t){return this.#i.add(t),()=>this.#i.delete(t)}#C(...t){for(let s of this.#i)s(...t)}#a(){this.#e&&(this.#r=this.#e.getBoundingClientRect())}#m(){this.#e&&(this.#a(),this.#n=new ResizeObserver(t=>{for(let s of t){if(s.target!==this.#e)continue;let{width:i,height:r}=s.contentRect;this.#L({width:i,height:r})}this.#a()}),this.#n.observe(this.#e),this.#e.addEventListener("wheel",this.#u,{passive:!1}),this.#e.addEventListener("pointerdown",this.#E),this.#e.addEventListener("dragenter",this.#P),this.#e.addEventListener("dragover",this.#k),this.#e.addEventListener("dragleave",this.#D),this.#e.addEventListener("drop",this.#T),document.addEventListener("pointermove",this.#b),document.addEventListener("pointerup",this.#y),document.addEventListener("pointercancel",this.#R))}#p(){this.#n&&(this.#n.disconnect(),this.#n=null),this.#e&&(this.#e.removeEventListener("wheel",this.#u),this.#e.removeEventListener("pointerdown",this.#E),this.#e.removeEventListener("dragenter",this.#P),this.#e.removeEventListener("dragover",this.#k),this.#e.removeEventListener("dragleave",this.#D),this.#e.removeEventListener("drop",this.#T)),document.removeEventListener("pointermove",this.#b),document.removeEventListener("pointerup",this.#y),document.removeEventListener("pointercancel",this.#R)}#u=t=>{if(t.preventDefault(),t.stopPropagation(),t.ctrlKey){let s=this.#h(t,"zoom");this.#o(s)}else{let s=this.#h(t,"scroll");this.#o(s)}};#b=t=>{this.#d=t,!this.#f&&(this.#f=requestAnimationFrame(()=>{if(this.#d){let s=this.#d;this.#d=null;let i="move",r=this.#v(s);if(this.#t.isPressed&&!this.#t.isDragging){let n=r.x-this.#t.dragStartX,o=r.y-this.#t.dragStartY;Math.sqrt(n*n+o*o)>this.#t.dragThreshold&&(this.#t.isDragging=!0,i="dragstart")}else this.#t.isDragging&&(i="drag");let a=this.#h(s,i);this.#o(a)}this.#f=null}))};#E=t=>{let s=this.#v(t);this.#t.isPressed=!0,this.#t.button=t.button??null,this.#t.dragStartX=s.x,this.#t.dragStartY=s.y,this.#t.isDragging=!1;try{this.#e.setPointerCapture(t.pointerId)}catch(r){console.warn("Failed to capture pointer:",r)}let i=this.#h(t,"down");this.#o(i)};#y=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let i=this.#h(t,"dragend");this.#o(i)}if(!this.#t.isDragging){let i=this.#v(t),r=Date.now();if(this.#t.lastClickTime!==null){let a=r-this.#t.lastClickTime,n=i.x-this.#t.lastClickX,o=i.y-this.#t.lastClickY,h=Math.sqrt(n*n+o*o);if(a<this.#t.doubleClickThreshold&&h<this.#t.doubleClickDistanceThreshold){let l=this.#h(t,"dblclick");this.#o(l),this.#t.lastClickTime=null,this.#t.lastClickX=null,this.#t.lastClickY=null}else this.#t.lastClickTime=r,this.#t.lastClickX=i.x,this.#t.lastClickY=i.y}else this.#t.lastClickTime=r,this.#t.lastClickX=i.x,this.#t.lastClickY=i.y}let s=this.#h(t,"up");this.#o(s),this.#t.isPressed=!1,this.#t.isDragging=!1,this.#t.dragStartX=null,this.#t.dragStartY=null};#R=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let i=this.#h(t,"dragend");this.#o(i)}let s=this.#h(t,"cancel");this.#o(s),this.#t.isPressed=!1,this.#t.isDragging=!1,this.#t.dragStartX=null,this.#t.dragStartY=null};#P=t=>{t.preventDefault(),this.#t.isExternalDragOver=!0,this.#t.externalDragData=this.#A(t.dataTransfer);let s=this.#h(t,"dragenter");this.#o(s)};#k=t=>{t.preventDefault(),t.dataTransfer.dropEffect=this.#t.externalDragData?.hasFiles?"copy":"move";let s=this.#h(t,"dragover");this.#o(s)};#D=t=>{t.preventDefault();let s=this.#e.getBoundingClientRect();if(t.clientX<s.left||t.clientX>=s.right||t.clientY<s.top||t.clientY>=s.bottom){this.#t.isExternalDragOver=!1,this.#t.externalDragData=null;let r=this.#h(t,"dragleave");this.#o(r)}};#T=t=>{t.preventDefault(),this.#t.isExternalDragOver=!1,this.#t.externalDragData=this.#A(t.dataTransfer);let s=this.#h(t,"drop"),i=this.#O(t.dataTransfer);this.#C(i,s),this.#o(s),this.#t.externalDragData=null};#O(t){let s=[];if(t?.items){console.log("\u{1F4E6} Processing",t.items.length,"items");for(let i of e.dataTransfer.items)if(i.kind==="file"){let r=i.getAsFile();r&&s.push(r)}}if(s.length===0&&t?.files){console.log("\u{1F4E6} Fallback to DataTransfer.files:",t.files.length,"files");for(let i=0;i<t.files.length;i++){let r=t.files[i];r&&s.push(r)}}return s}#A(t){return t?{types:Array.from(t.types),hasFiles:t.types.includes("Files"),fileCount:t.items?.length||0,effectAllowed:t.effectAllowed}:null}#o(t){for(let s of this.#S)s(t)}#L(t){for(let s of this.#g)s(t)}#v(t){let s=t.target===this.#e,i,r;return s?(i=t.offsetX,r=t.offsetY):this.#r?(i=t.clientX-this.#r.left,r=t.clientY-this.#r.top):(i=t.clientX,r=t.clientY),{x:i,y:r,isOverCanvas:s}}#h(t,s){let{x:i,y:r,isOverCanvas:a}=this.#v(t),n=a||this.#r&&i>=0&&i<=this.#r.width&&r>=0&&r<=this.#r.height,o=0,h=0,l=0,c=0;s==="scroll"?(o=t.deltaX,h=t.deltaY,l=t.deltaZ,c=t.deltaMode):s==="zoom"?(o=0,h=t.deltaY,l=0):(s==="move"||s==="drag"||s==="dragstart")&&this.#t.prevX!==null&&this.#t.prevY!==null&&(o=i-this.#t.prevX,h=r-this.#t.prevY);let x=0;if(this.#t.isDragging&&this.#t.dragStartX!==null&&this.#t.dragStartY!==null){let g=i-this.#t.dragStartX,E=r-this.#t.dragStartY;x=Math.sqrt(g*g+E*E)}let C={x:i,y:r,clientX:t.clientX,clientY:t.clientY,prevX:this.#t.prevX,prevY:this.#t.prevY,type:s,timestamp:Date.now(),isOverCanvas:a,isWithinBounds:n,deltaX:o,deltaY:h,deltaZ:l,deltaMode:c,button:t.button??this.#t.button,buttons:t.buttons??0,isPressed:this.#t.isPressed,isDragging:this.#t.isDragging,dragStartX:this.#t.dragStartX,dragStartY:this.#t.dragStartY,dragDistance:x,shiftKey:t.shiftKey||!1,ctrlKey:t.ctrlKey||!1,altKey:t.altKey||!1,metaKey:t.metaKey||!1,isExternalDragOver:this.#t.isExternalDragOver,externalDragData:this.#t.externalDragData};return s==="drop"&&t.dataTransfer&&(C.dataTransfer={items:Array.from(t.dataTransfer.items).map(g=>({kind:g.kind,type:g.type})),types:Array.from(t.dataTransfer.types)}),this.#t.prevX=i,this.#t.prevY=r,C}destroy(){this.#f&&(cancelAnimationFrame(this.#f),this.#f=null),this.#p(),this.#e=null,this.#l=null,this.#r=null,this.#S.clear(),this.#g.clear(),this.#w=!1,this.#t.isPressed=!1,this.#t.button=null,this.#t.dragStartX=null,this.#t.dragStartY=null,this.#t.isDragging=!1,this.#t.prevX=null,this.#t.prevY=null,this.#t.lastClickTime=null,this.#t.lastClickX=null,this.#t.lastClickY=null,this.#t.isExternalDragOver=!1,this.#t.externalDragData=null}};import{defineSurface as P}from"@jucie.io/reactive";var y=P(d=>{let t=d.signal(null),s=d.signal(null),i=d.signal(null),r=d.action((h,l)=>{t(l)}),a=d.action((h,l)=>{s(l)}),n=d.action((h,l)=>{i(l)}),o=d.action(()=>{t(null),s(null),i(null)});return{event:t,hoveredArea:s,activeArea:i,handleEvent:r,setHoveredArea:a,setActiveArea:n,reset:o}});import{ServiceProvider as k}from"@jucie.io/engine";import{createComputed as A,destroyComputed as S,addEffect as L}from"@jucie.io/reactive";import{createDefinition as b,definitionType as v}from"@jucie.io/engine";var f={BRUSH:"BRUSH",LAYER:"LAYER",SUBSCRIPTION:"SUBSCRIPTION",SUBSCRIPTIONS:"SUBSCRIPTIONS"},R="GLOBAL_LAYER",O=b(f.BRUSH,[Object]),D=b(f.LAYER,[Object]),Y=b(f.SUBSCRIPTION,[Function]),B=b(f.SUBSCRIPTIONS,[Object]),w=class extends k{#e=new Map;#l=new Map;#r=null;#n=new Map;#S=new Map;#g=!1;#d=null;#f=!1;#w=!1;#i={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#t={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#x={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#C=new m;#a=y();#m=null;#p=null;#u=null;#b=new Map;#E=!1;static manifest={name:"Painter",namespace:"painter",version:"1.0.0",defaults:{targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}}};getters(){return{pointer:()=>this.#a}}initialize(){this.#y(D(R,()=>({context:u["2D"]})))}actions(){return this.config&&Object.assign(this.#i,this.config),{addLayer:t=>this.#y(t),addLayers:(...t)=>{for(let s of t)this.#y(s)},use:(...t)=>this.use(t),updateCanvas:t=>this.updateCanvas(t),setCanvas:t=>this.setCanvas(t),setOffscreenCanvas:t=>this.setOffscreenCanvas(t),setAssets:t=>this.setAssets(t),removeLayer:t=>this.#D(t),start:()=>this.start(),stop:()=>this.stop(),render:()=>this.render(),setTargetFPS:t=>this.setTargetFPS(t),setTimeScale:t=>this.setTimeScale(t),setFixedTimeStep:t=>this.setFixedTimeStep(t),setDebug:t=>this.setDebug(t),getMetrics:()=>this.getMetrics(),handleResize:(t,s)=>this.handleResize(t,s),subscribe:(t,s)=>this.subscribe(t,s),handlePointerEvent:t=>this.handlePointerEvent(t),subscribeToPointer:t=>this.#a.$subscribe(t),bindPointer:t=>this.#a.$bind(t),_testEmitPointerEvent:t=>this._testEmitPointerEvent(t)}}use(t){for(let s of t){let i=v(s);switch(i){case f.BRUSH:this.#R(R,s);break;case f.LAYER:this.#y(s);break;case f.SUBSCRIPTION:this.#P(s);break;case f.SUBSCRIPTIONS:this.#k(s);break;default:throw new Error(`Invalid factory type: ${i}`)}}return this}setCanvas(t){let s=t,i=t.transferControlToOffscreen();i.width=s.width,i.height=s.height,this.#r=i,Object.values(u).forEach(r=>{try{let a=i.getContext(r);a&&this.#n.set(r,a)}catch{console.warn(`Context type ${r} not supported`)}}),this.#m||(this.#m=new p),this.#m.setCanvas(s),this.#u&&this.#u.disconnect(),this.#u=new ResizeObserver(r=>{let a=r[0];a&&a.target===s&&(i.width=s.width,i.height=s.height,this.handleResize(s.width,s.height))}),this.#u.observe(s),this.#p&&this.#p(),this.#p=this.#m.subscribe(r=>{this.handlePointerEvent(r)})}setOffscreenCanvas(t){this.#r=t,Object.values(u).forEach(s=>{try{let i=t.getContext(s);i&&this.#n.set(s,i)}catch{console.warn(`Context type ${s} not supported`)}})}updateCanvas(t){let s=t(this.#r);s&&(this.#r=s)}setAssets(t){this.#S=t}start(){this.#g||(this.#g=!0,this.#T())}stop(){this.#g&&(this.#g=!1,this.#d&&(cancelAnimationFrame(this.#d),this.#d=null))}#y(t){if(v(t)!=="LAYER")throw new Error("Invalid layer definition");let s=t._name,i=t(this.useContext,this.#C),r={...i,name:s,context:this.#n.get(i.context||"2d")};if(i.data&&(r.dataReactor=this.#v(i.data,()=>this.#a)),i.when&&(r.whenReactor=this.#v(i.when,()=>r?.dataReactor?.computed()||void 0)),i.children&&i.children.length>0)for(let a of i.children)v(a)==="BRUSH"&&this.#R(s,a),v(a)==="LAYER"&&this.#y(a);if(this.#e.set(s,r),r.lifecycle?.onMount)try{r.lifecycle.onMount(r.context)}catch(a){console.error(`Error in layer "${s}" onMount:`,a)}return r}#R(t,s){let i=s._name,r=s(this.useContext,this.#C),a={name:i,...r};if(r.data&&(a.dataReactor=this.#v(r.data,()=>this.#a)),r.when&&(a.whenReactor=this.#v(r.when,()=>a?.dataReactor?.computed()||void 0)),a.lifecycle?.onMount)try{a.lifecycle.onMount(this.#n.get(a.context||this.#e.get(t)?.context))}catch(n){console.error(`Error in brush "${a.name}" onMount:`,n)}return this.#l.has(t)||this.#l.set(t,[]),this.#l.get(t).push(a),a}#P(t){let s=t._name,i=t(this.useContext);this.subscribe(s,i)}#k(t){let s=t._name,i=t(this.useContext);for(let[r,a]of Object.entries(i)){let n=s?`${s}:${r}`:r;this.subscribe(n,a)}}#D(t){let s=this.#e.get(t);if(!s)return;if(s.lifecycle?.onUnmount)try{s.lifecycle.onUnmount(s.context)}catch(r){console.error(`Error in layer "${t}" onUnmount:`,r)}let i=this.#l.get(t)||[];this.#l.delete(t);for(let r of i){if(r.lifecycle?.onUnmount)try{r.lifecycle.onUnmount(this.#n.get(r.context||s.context))}catch(a){console.error(`Error in brush "${r.name}" onUnmount:`,a)}r.whenReactor&&S(r.whenReactor),r.dataReactor&&(r.dataReactor?.unsubscribe(),r.dataReactor?.computed&&S(r.dataReactor.computed))}s.whenReactor&&(s.whenReactor?.unsubscribe(),s.whenReactor?.computed&&S(s.whenReactor.computed)),this.#e.delete(t)}#T(){this.#w||this.#f||(this.#w=!0,this.#d=requestAnimationFrame(()=>{this.#w=!1,this.#d=null,this.#O()}))}async#O(){if(this.#r){this.#f=!0;try{this.#C.clear();let t=this.#i.debug?.enabled?performance.now():0;this.#n.forEach(s=>{s.clearRect(0,0,this.#r.width,this.#r.height)});for(let s of this.#e.values()){let i=this.#i.debug?.enabled?performance.now():0;if(s.whenReactor&&!s.whenReactor.computed())continue;let r=s.context;if(!r)continue;if(s.lifecycle?.beforeRender)try{s.lifecycle.beforeRender(r,this.#t)}catch(n){console.error(`Error in layer "${s.name}" beforeRender:`,n),s.lifecycle?.onError&&s.lifecycle.onError(n)}r.save(),s.settings&&Object.entries(s.settings).forEach(([n,o])=>{typeof r[n]=="function"?r[n](...Array.isArray(o)?o:[o]):r[n]=o});let a=this.#l.get(s.name)||[];for(let n of a){let o=this.#i.debug?.enabled?performance.now():0;if(n.whenReactor&&!n.whenReactor.computed())continue;let h=n.context?this.#n.get(n.context):r;if(h){if(n.lifecycle?.beforeRender)try{n.lifecycle.beforeRender(h,this.#t)}catch(l){console.error(`Error in brush "${n.name}" beforeRender:`,l),n.lifecycle?.onError&&n.lifecycle.onError(l);continue}h.save(),n.settings&&Object.entries(n.settings).forEach(([l,c])=>{typeof h[l]=="function"?h[l](...Array.isArray(c)?c:[c]):h[l]=c});try{let l={};if(n.assets)for(let c of n.assets)l[c]=this.#S.get(c);if(n.render(h,n.dataReactor?n.dataReactor.computed():void 0,l,this.#t),n.lifecycle?.afterRender&&n.lifecycle.afterRender(h,this.#t),this.#i.debug?.enabled){let c=performance.now()-o;this.#x.brushTimes.set(n.name,c),this.#i.debug?.showBounds&&this.#A(h,n)}}catch(l){console.error(`Error in brush "${n.name}":`,l),n.lifecycle?.onError&&n.lifecycle.onError(l)}finally{h.restore()}}}if(r.restore(),s.lifecycle?.afterRender)try{s.lifecycle.afterRender(r,this.#t)}catch(n){console.error(`Error in layer "${s.name}" afterRender:`,n),s.lifecycle?.onError&&s.lifecycle.onError(n)}if(this.#i.debug?.enabled){let n=performance.now()-i;this.#x.layerTimes.set(s.name,n),this.#i.debug?.showBounds&&this.#o(r,s)}}this.#i.debug?.enabled&&this.#L()}finally{this.#f=!1}}}#A(t,s){t.save(),t.strokeStyle="rgba(0, 255, 0, 0.5)",t.lineWidth=1,t.strokeRect(0,0,t.canvas.width,t.canvas.height),t.restore()}#o(t,s){t.save(),t.strokeStyle="rgba(255, 0, 0, 0.5)",t.lineWidth=2,t.strokeRect(0,0,t.canvas.width,t.canvas.height),t.restore()}#L(){let t=this.#n.get(u["2D"]);if(!t)return;t.save(),t.resetTransform(),t.font="12px monospace",t.fillStyle="white",t.strokeStyle="black",t.lineWidth=3;let s=20,i=15;if(this.#i.debug?.showFPS){let r=`FPS: ${Math.round(this.#x.fps)} (${this.#t.deltaTime.toFixed(2)}ms)`;t.strokeText(r,10,s),t.fillText(r,10,s),s+=i}if(this.#i.debug?.showLayerTiming){t.fillText("Layer Times:",10,s),s+=i;for(let[r,a]of this.#x.layerTimes){let n=` ${r}: ${a.toFixed(2)}ms`;t.strokeText(n,10,s),t.fillText(n,10,s),s+=i}t.fillText(this.state.get(["_transitions","pointer","currentState"]),10,s)}t.restore()}handleResize(t,s){for(let i of this.#e.values())if(i.lifecycle?.onResize)try{i.lifecycle.onResize(t,s,i.context)}catch(r){console.error(`Error in layer "${i.name}" onResize:`,r),i.lifecycle?.onError&&i.lifecycle.onError(r)}}#v(t,s=()=>{}){if(!t)return null;let i=A(t,{immediate:!0,context:s}),r=L(i,()=>this.#T());return{computed:i,unsubscribe:r}}destroy(){this.stop(),this.#p&&(this.#p(),this.#p=null),this.#m&&(this.#m.destroy(),this.#m=null),this.#u&&(this.#u.disconnect(),this.#u=null),this.#a&&this.#a.$destroy();for(let t of this.#e.keys())this.#D(t)}setTargetFPS(t){this.#i.targetFPS=t,this.#i.fixedTimeStep=1e3/t}setTimeScale(t){this.#i.timeScale=Math.max(0,t)}setFixedTimeStep(t){this.#i.fixedTimeStep=t}setDebug(t={}){this.#i.debug||(this.#i.debug={}),Object.assign(this.#i.debug,t)}getMetrics(){return{...this.#x,deltaTime:this.#t.deltaTime,elapsedTime:this.#t.elapsedTime,frameCount:this.#t.frameCount}}handlePointerEvent(t){this.#a.handleEvent(t),this.#B(t),this.#h(t)}#h(t){let{type:s}=t,i=this.#a,r=i.event;switch(s){case"down":this.#s("pointer:down",i);break;case"up":this.#s("pointer:up",i),r&&!r.isDragging&&this.#s("pointer:click",i);break;case"move":this.#s("pointer:move",i);break;case"dragstart":this.#s("pointer:drag:start",i);break;case"drag":this.#s("pointer:drag:move",i);break;case"dragend":this.#s("pointer:drag:end",i);break;case"scroll":this.#s("pointer:scroll",i);break;case"zoom":this.#s("pointer:zoom",i);break;case"dblclick":this.#s("pointer:dblclick",i);break;case"drop":this.#s("pointer:drop",i);break;case"dragenter":this.#s("pointer:dragenter",i);break;case"dragover":this.#s("pointer:dragover",i);break}let a=this.#E,n=r?.isOverCanvas||!1;n&&!a?this.#s("pointer:enter",i):!n&&a&&this.#s("pointer:leave",i),this.#E=n}#B(t){let{type:s,x:i,y:r}=t,a=this.#a;switch(s){case"down":{let o=this.#Y(i,r);if(a.setActiveArea(o),o?.onPointerDown?.handler){let h=this.#c(o);o.onPointerDown.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"up":{let o=a.activeArea;if(o?.onPointerUp?.handler){let h=this.#c(o);o.onPointerUp.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"move":{let o=this.#Y(i,r),h=a.hoveredArea;if(o?.onPointerMove?.handler&&!t.isDragging){let l=this.#c(o);o.onPointerMove.handler({event:t,ctx:l,emit:this.#s.bind(this)})}if(o?.id!==h?.id){if(h?.onPointerLeave?.handler){let l=this.#c(h);h.onPointerLeave.handler({event:t,ctx:l,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let l=this.#c(o);o.onPointerEnter.handler({event:t,ctx:l,emit:this.#s.bind(this)})}a.setHoveredArea(o)}break}case"dragstart":{let o=a.activeArea;if(o?.onDragStart?.handler){let h=this.#c(o);o.onDragStart.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"drag":{let o=this.#Y(i,r),h=a.hoveredArea;if(o?.id!==h?.id){if(h?.onPointerLeave?.handler){let c=this.#c(h);h.onPointerLeave.handler({event:t,ctx:c,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let c=this.#c(o);o.onPointerEnter.handler({event:t,ctx:c,emit:this.#s.bind(this)})}a.setHoveredArea(o)}let l=a.activeArea;if(l?.onDragMove?.handler){let c=this.#c(l);l.onDragMove.handler({event:t,ctx:c,emit:this.#s.bind(this)})}break}case"dragend":{let o=a.activeArea;if(o?.onDragEnd?.handler){let h=this.#c(o);o.onDragEnd.handler({event:t,ctx:h,emit:this.#s.bind(this)})}break}case"dblclick":let n=a.activeArea;if(n?.onPointerDblClick?.handler){let o=this.#c(n);n.onPointerDblClick.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}}#c(t){return t?t.context?this.#n.get(t.context):this.#n.get(u["2D"]):null}subscribe(t,s){return this.#b.has(t)||this.#b.set(t,new Set),this.#b.get(t).add(s),()=>{let i=this.#b.get(t);i&&(i.delete(s),i.size===0&&this.#b.delete(t))}}#Y(t,s){let i=this.#C.areas.sort((r,a)=>(a.priority||0)-(r.priority||0));for(let r of i)if(this.#M(t,s,r.bounds))return r;return null}#M(t,s,i){return t>=i.x&&t<=i.x+i.width&&s>=i.y&&s<=i.y+i.height}#s(t,s){let i=this.#b.get(t);if(i)for(let r of i)r(s)}_testEmitPointerEvent(t){this.#a.handleEvent(t),this.#B(t)}};export{p as CanvasEvents,m as HitRegistry,w as Painter,O as defineBrush,D as defineLayer,Y as defineSubscription,B as defineSubscriptions,y as usePointerSurface};
2
2
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/ContextTypes.js", "../src/HitRegistry.js", "../src/CanvasEvents.js", "../src/usePointerSurface.js", "../src/Painter.js"],
4
- "sourcesContent": ["export const ContextTypes = {\n '2D': '2d',\n 'WEBGL': 'webgl',\n 'WEBGL2': 'webgl2',\n 'BITMAPRENDERER': 'bitmaprenderer'\n};", "export class HitRegistry {\n #areas = new Map();\n\n register(id, area) {\n if (!id) {\n throw new Error('Hit area must have an id');\n }\n this.#areas.set(id, { id, ...area });\n return () => this.unregister(id);\n }\n\n unregister(id) {\n this.#areas.delete(id);\n }\n\n get(id) {\n return this.#areas.get(id);\n }\n\n has(id) {\n return this.#areas.has(id);\n }\n\n get areas() {\n return Array.from(this.#areas.values());\n }\n\n clear() {\n this.#areas.clear();\n }\n}", "import { ServiceProvider } from '@jucie.io/engine';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #offscreenCanvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #resizeSubscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n #hasTransferredControl = false;\n #dropSubscribers = new Set();\n // Internal state for semantic event interpretation\n #state = {\n isPressed: false,\n button: null,\n dragStartX: null,\n dragStartY: null,\n isDragging: false,\n dragThreshold: 5,\n prevX: null,\n prevY: null,\n // Double click detection\n lastClickTime: null,\n lastClickX: null,\n lastClickY: null,\n doubleClickThreshold: 300, // ms\n doubleClickDistanceThreshold: 5, // pixels\n // External drag-and-drop state (for file/data drops)\n isExternalDragOver: false,\n externalDragData: null\n };\n\n static manifest = {\n name: 'CanvasEvents',\n namespace: 'canvasEvents',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n onResize: (listener) => this.onResize(listener),\n transferControlToOffscreen: () => this.transferControlToOffscreen(),\n onFileDrop: (listener) => this.#addDropSubscriber(listener)\n };\n }\n\n setCanvas(canvas) {\n if (this.#canvas) {\n this.#removeListeners();\n }\n \n this.#canvas = canvas;\n this.#updateCachedRect();\n this.#initializeListeners();\n }\n\n subscribe(subscriber) {\n this.#subscribers.add(subscriber);\n return () => this.#subscribers.delete(subscriber);\n }\n\n onResize(subscriber) {\n this.#resizeSubscribers.add(subscriber);\n return () => this.#resizeSubscribers.delete(subscriber);\n }\n\n transferControlToOffscreen() {\n if (!this.#canvas) {\n throw new Error('Canvas must be set before transferring control to offscreen');\n }\n\n if (this.#hasTransferredControl) {\n throw new Error('Control has already been transferred to offscreen');\n }\n\n // Transfer control\n this.#offscreenCanvas = this.#canvas.transferControlToOffscreen();\n this.#hasTransferredControl = true;\n\n\n\n // Set initial dimensions on offscreen canvas\n this.#offscreenCanvas.width = this.#cachedRect.width;\n this.#offscreenCanvas.height = this.#cachedRect.height;\n\n // Emit initial resize event with actual canvas dimensions\n this.#emitResize({\n width: this.#canvas.width,\n height: this.#canvas.height\n });\n\n return this.#offscreenCanvas;\n }\n\n #addDropSubscriber(listener) {\n this.#dropSubscribers.add(listener);\n return () => this.#dropSubscribers.delete(listener);\n }\n\n #callDropSubscribers(...args) {\n for (const subscriber of this.#dropSubscribers) {\n subscriber(...args);\n }\n }\n\n #updateCachedRect() {\n if (this.#canvas) {\n this.#cachedRect = this.#canvas.getBoundingClientRect();\n }\n }\n\n #initializeListeners() {\n if (!this.#canvas) return;\n\n this.#updateCachedRect();\n\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target !== this.#canvas) {\n continue;\n }\n const { width, height } = entry.contentRect;\n this.#emitResize({\n width: width,\n height: height\n });\n }\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n // Canvas-specific events\n this.#canvas.addEventListener('wheel', this.#handleScroll, { passive: false });\n this.#canvas.addEventListener('pointerdown', this.#handleDown);\n \n // HTML5 Drag-and-Drop events (for external file/data drops)\n this.#canvas.addEventListener('dragenter', this.#handleDragEnter);\n this.#canvas.addEventListener('dragover', this.#handleDragOver);\n this.#canvas.addEventListener('dragleave', this.#handleDragLeave);\n this.#canvas.addEventListener('drop', this.#handleDrop);\n \n // Document-level events (for when pointer is captured)\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleCancel);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n if (this.#canvas) {\n this.#canvas.removeEventListener('wheel', this.#handleScroll);\n this.#canvas.removeEventListener('pointerdown', this.#handleDown);\n this.#canvas.removeEventListener('dragenter', this.#handleDragEnter);\n this.#canvas.removeEventListener('dragover', this.#handleDragOver);\n this.#canvas.removeEventListener('dragleave', this.#handleDragLeave);\n this.#canvas.removeEventListener('drop', this.#handleDrop);\n }\n\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleCancel);\n }\n\n #handleScroll = (event) => {\n event.preventDefault();\n event.stopPropagation();\n \n if (event.ctrlKey) {\n const normalized = this.#normalizeEvent(event, 'zoom');\n this.#emit(normalized);\n } else {\n const normalized = this.#normalizeEvent(event, 'scroll');\n this.#emit(normalized);\n }\n }\n\n #handleMove = (event) => {\n // Store latest raw event and throttle with RAF\n this.#pendingMove = event;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n const rawEvent = this.#pendingMove;\n this.#pendingMove = null;\n \n // Determine event type based on state\n let type = 'move';\n const position = this.#getPosition(rawEvent);\n \n // Check for drag start\n if (this.#state.isPressed && !this.#state.isDragging) {\n const dx = position.x - this.#state.dragStartX;\n const dy = position.y - this.#state.dragStartY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance > this.#state.dragThreshold) {\n this.#state.isDragging = true;\n type = 'dragstart';\n }\n } else if (this.#state.isDragging) {\n type = 'drag';\n }\n \n const normalized = this.#normalizeEvent(rawEvent, type);\n this.#emit(normalized);\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n const position = this.#getPosition(event);\n \n // Update state\n this.#state.isPressed = true;\n this.#state.button = event.button ?? null;\n this.#state.dragStartX = position.x;\n this.#state.dragStartY = position.y;\n this.#state.isDragging = false;\n \n // Capture the pointer to ensure we receive all subsequent events\n // even if the pointer moves outside the canvas\n try {\n this.#canvas.setPointerCapture(event.pointerId);\n } catch (e) {\n // Pointer capture might fail in some scenarios (e.g., already captured)\n // Continue anyway as document-level listeners will still work\n console.warn('Failed to capture pointer:', e);\n }\n \n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n\n #handleUp = (event) => {\n // Release pointer capture\n if (this.#canvas && this.#state.isPressed) {\n try {\n this.#canvas.releasePointerCapture(event.pointerId);\n } catch (e) {\n // Capture might have already been released, ignore\n }\n }\n \n // Emit dragend if we were dragging\n if (this.#state.isDragging) {\n const dragend = this.#normalizeEvent(event, 'dragend');\n this.#emit(dragend);\n }\n \n // Detect double click if this was a clean click (not a drag)\n if (!this.#state.isDragging) {\n const position = this.#getPosition(event);\n const now = Date.now();\n \n if (this.#state.lastClickTime !== null) {\n const timeDiff = now - this.#state.lastClickTime;\n const dx = position.x - this.#state.lastClickX;\n const dy = position.y - this.#state.lastClickY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n // Check if this qualifies as a double click\n if (\n timeDiff < this.#state.doubleClickThreshold &&\n distance < this.#state.doubleClickDistanceThreshold\n ) {\n // Emit double click event\n const dblclickEvent = this.#normalizeEvent(event, 'dblclick');\n this.#emit(dblclickEvent);\n \n // Reset double click tracking to prevent triple-click\n this.#state.lastClickTime = null;\n this.#state.lastClickX = null;\n this.#state.lastClickY = null;\n } else {\n // Update for potential next click\n this.#state.lastClickTime = now;\n this.#state.lastClickX = position.x;\n this.#state.lastClickY = position.y;\n }\n } else {\n // First click, start tracking\n this.#state.lastClickTime = now;\n this.#state.lastClickX = position.x;\n this.#state.lastClickY = position.y;\n }\n }\n \n // Always emit up event\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.isDragging = false;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n }\n\n #handleCancel = (event) => {\n // Release pointer capture\n if (this.#canvas && this.#state.isPressed) {\n try {\n this.#canvas.releasePointerCapture(event.pointerId);\n } catch (e) {\n // Capture might have already been released, ignore\n }\n }\n \n // Emit dragend if we were dragging (interaction was interrupted)\n if (this.#state.isDragging) {\n const dragend = this.#normalizeEvent(event, 'dragend');\n this.#emit(dragend);\n }\n \n // Emit cancel event (distinct from up - signals interrupted interaction)\n const normalized = this.#normalizeEvent(event, 'cancel');\n this.#emit(normalized);\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.isDragging = false;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n }\n\n #handleDragEnter = (event) => {\n event.preventDefault();\n \n this.#state.isExternalDragOver = true;\n this.#state.externalDragData = this.#extractDragData(event.dataTransfer);\n \n const normalized = this.#normalizeEvent(event, 'dragenter');\n this.#emit(normalized);\n }\n\n #handleDragOver = (event) => {\n event.preventDefault();\n \n // Set the drop effect (copy for files, move for internal drags)\n event.dataTransfer.dropEffect = this.#state.externalDragData?.hasFiles ? 'copy' : 'move';\n \n const normalized = this.#normalizeEvent(event, 'dragover');\n this.#emit(normalized);\n }\n\n #handleDragLeave = (event) => {\n event.preventDefault();\n \n // Only emit dragleave if we're actually leaving the canvas\n // (not just moving between child elements)\n const rect = this.#canvas.getBoundingClientRect();\n const isOutside = (\n event.clientX < rect.left ||\n event.clientX >= rect.right ||\n event.clientY < rect.top ||\n event.clientY >= rect.bottom\n );\n \n if (isOutside) {\n this.#state.isExternalDragOver = false;\n this.#state.externalDragData = null;\n \n const normalized = this.#normalizeEvent(event, 'dragleave');\n this.#emit(normalized);\n }\n }\n\n #handleDrop = (event) => {\n event.preventDefault();\n \n this.#state.isExternalDragOver = false;\n this.#state.externalDragData = this.#extractDragData(event.dataTransfer);\n \n const normalized = this.#normalizeEvent(event, 'drop');\n const files = this.#extractFiles(event.dataTransfer);\n this.#callDropSubscribers(files, normalized);\n this.#emit(normalized);\n \n // Reset state after drop\n this.#state.externalDragData = null;\n }\n\n #extractFiles(dataTransfer) {\n const files = [];\n if (dataTransfer?.items) {\n console.log('\uD83D\uDCE6 Processing', dataTransfer.items.length, 'items');\n for (const item of e.dataTransfer.items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n files.push(file);\n }\n }\n }\n }\n \n // Fallback to DataTransfer.files if items is empty or not available\n if (files.length === 0 && dataTransfer?.files) {\n console.log('\uD83D\uDCE6 Fallback to DataTransfer.files:',dataTransfer.files.length, 'files');\n for (let i = 0; i < dataTransfer.files.length; i++) {\n const file = dataTransfer.files[i];\n if (file) {\n files.push(file);\n }\n }\n }\n return files;\n }\n\n #extractDragData(dataTransfer) {\n if (!dataTransfer) return null;\n \n return {\n types: Array.from(dataTransfer.types),\n hasFiles: dataTransfer.types.includes('Files'),\n fileCount: dataTransfer.items?.length || 0,\n // Note: Can't access files/data until drop event due to security\n effectAllowed: dataTransfer.effectAllowed\n };\n }\n\n #emit(event) {\n for (const subscriber of this.#subscribers) {\n subscriber(event);\n }\n }\n\n #emitResize(resizeData) {\n for (const subscriber of this.#resizeSubscribers) {\n subscriber(resizeData);\n }\n }\n\n #getPosition(event) {\n const isOverCanvas = event.target === this.#canvas;\n \n let x, y;\n if (isOverCanvas) {\n x = event.offsetX;\n y = event.offsetY;\n } else if (this.#cachedRect) {\n x = event.clientX - this.#cachedRect.left;\n y = event.clientY - this.#cachedRect.top;\n } else {\n x = event.clientX;\n y = event.clientY;\n }\n \n return { x, y, isOverCanvas };\n }\n\n #normalizeEvent(event, type) {\n const { x, y, isOverCanvas } = this.#getPosition(event);\n\n const isWithinBounds = isOverCanvas || (\n this.#cachedRect &&\n x >= 0 && \n x <= this.#cachedRect.width && \n y >= 0 && \n y <= this.#cachedRect.height\n );\n \n // Calculate deltas based on event type\n let deltaX = 0;\n let deltaY = 0;\n let deltaZ = 0;\n let deltaMode = 0;\n \n if (type === 'scroll') {\n // Scroll events use wheel deltas\n deltaX = event.deltaX;\n deltaY = event.deltaY;\n deltaZ = event.deltaZ;\n deltaMode = event.deltaMode;\n } else if (type === 'zoom') {\n // Zoom uses simplified delta\n deltaX = 0;\n deltaY = event.deltaY;\n deltaZ = 0;\n } else if (type === 'move' || type === 'drag' || type === 'dragstart') {\n // Position-based events calculate deltas from previous position\n if (this.#state.prevX !== null && this.#state.prevY !== null) {\n deltaX = x - this.#state.prevX;\n deltaY = y - this.#state.prevY;\n }\n }\n \n // Calculate drag distance if dragging\n let dragDistance = 0;\n if (this.#state.isDragging && this.#state.dragStartX !== null && this.#state.dragStartY !== null) {\n const dx = x - this.#state.dragStartX;\n const dy = y - this.#state.dragStartY;\n dragDistance = Math.sqrt(dx * dx + dy * dy);\n }\n\n const normalized = {\n // Position\n x,\n y,\n clientX: event.clientX,\n clientY: event.clientY,\n prevX: this.#state.prevX,\n prevY: this.#state.prevY,\n \n // Event metadata\n type,\n timestamp: Date.now(),\n isOverCanvas,\n isWithinBounds,\n \n // Deltas (appropriate to event type)\n deltaX,\n deltaY,\n deltaZ,\n deltaMode,\n \n // Button state\n button: event.button ?? this.#state.button,\n buttons: event.buttons ?? 0,\n isPressed: this.#state.isPressed,\n \n // Drag state\n isDragging: this.#state.isDragging,\n dragStartX: this.#state.dragStartX,\n dragStartY: this.#state.dragStartY,\n dragDistance,\n \n // Modifiers\n shiftKey: event.shiftKey || false,\n ctrlKey: event.ctrlKey || false,\n altKey: event.altKey || false,\n metaKey: event.metaKey || false,\n \n // External drag-and-drop state (for file/data drops)\n isExternalDragOver: this.#state.isExternalDragOver,\n externalDragData: this.#state.externalDragData\n };\n \n // Add DataTransfer for drop events (only available on drop, not dragover)\n if (type === 'drop' && event.dataTransfer) {\n normalized.dataTransfer = {\n items: Array.from(event.dataTransfer.items).map(item => ({\n kind: item.kind,\n type: item.type\n })),\n types: Array.from(event.dataTransfer.types)\n };\n }\n \n // Update previous position for next delta calculation\n this.#state.prevX = x;\n this.#state.prevY = y;\n\n return normalized;\n }\n\n destroy() {\n if (this.#rafId) {\n cancelAnimationFrame(this.#rafId);\n this.#rafId = null;\n }\n this.#removeListeners();\n this.#canvas = null;\n this.#offscreenCanvas = null;\n this.#cachedRect = null;\n this.#subscribers.clear();\n this.#resizeSubscribers.clear();\n this.#hasTransferredControl = false;\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.button = null;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n this.#state.isDragging = false;\n this.#state.prevX = null;\n this.#state.prevY = null;\n this.#state.lastClickTime = null;\n this.#state.lastClickX = null;\n this.#state.lastClickY = null;\n this.#state.isExternalDragOver = false;\n this.#state.externalDragData = null;\n }\n}\n", "import { defineSurface } from '@jucie.io/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // Current normalized event from CanvasEvents\n const event = setup.signal(null);\n \n // Hit registry integration (still managed here)\n const hoveredArea = setup.signal(null);\n const activeArea = setup.signal(null);\n \n // Main handler - just stores the event\n const handleEvent = setup.action((_, normalizedEvent) => {\n event(normalizedEvent);\n });\n \n const setHoveredArea = setup.action((_, area) => {\n hoveredArea(area);\n });\n \n const setActiveArea = setup.action((_, area) => {\n activeArea(area);\n });\n \n const reset = setup.action(() => {\n event(null);\n hoveredArea(null);\n activeArea(null);\n });\n \n return {\n // Signals\n event,\n hoveredArea,\n activeArea,\n\n // Actions\n handleEvent,\n setHoveredArea,\n setActiveArea,\n reset\n };\n});\n", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nconst DEFINITIONS_TYPES = {\n BRUSH: 'BRUSH',\n LAYER: 'LAYER',\n SUBSCRIPTION: 'SUBSCRIPTION',\n SUBSCRIPTIONS: 'SUBSCRIPTIONS'\n};\n\nconst GLOBAL_LAYER_NAME = 'GLOBAL_LAYER';\n\nexport const defineBrush = createDefinition(DEFINITIONS_TYPES.BRUSH, [Object]);\nexport const defineLayer = createDefinition(DEFINITIONS_TYPES.LAYER, [Object]);\nexport const defineSubscription = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTION, [Function]);\nexport const defineSubscriptions = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTIONS, [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #brushes = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #assets = new Map();\n #isRunning = false;\n #frameId = null;\n #isRendering = false;\n #renderScheduled = false;\n\n // Mutable runtime config (separate from frozen config)\n #runtimeConfig = {\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n };\n\n // Timing state\n #timing = {\n lastFrameTime: 0,\n deltaTime: 0,\n elapsedTime: 0,\n frameCount: 0\n };\n\n // Debug metrics\n #metrics = {\n fps: 0,\n frameTime: 0,\n layerTimes: new Map(),\n brushTimes: new Map(),\n skippedFrames: 0\n };\n\n // Hit detection state\n #hitRegistry = new HitRegistry();\n #pointerSurface = usePointerSurface();\n #canvasEvents = null; // Only created in main thread mode\n #pointerUnsubscribe = null;\n #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasOverCanvas = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface,\n };\n }\n \n initialize () {\n this.#addLayer(defineLayer(GLOBAL_LAYER_NAME, () => ({\n context: ContextTypes['2D']\n })));\n }\n\n actions() {\n // Initialize runtime config from frozen config\n if (this.config) {\n Object.assign(this.#runtimeConfig, this.config);\n }\n \n return {\n addLayer: (layerDef) => this.#addLayer(layerDef),\n addLayers: (...layers) => {\n for (const layer of layers) {\n this.#addLayer(layer);\n }\n },\n use: (...factories) => this.use(factories),\n updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\n setOffscreenCanvas: (offscreenCanvas) => this.setOffscreenCanvas(offscreenCanvas),\n setAssets: (assets) => this.setAssets(assets),\n removeLayer: (name) => this.#removeLayer(name),\n start: () => this.start(),\n stop: () => this.stop(),\n render: () => this.render(),\n setTargetFPS: (fps) => this.setTargetFPS(fps),\n setTimeScale: (scale) => this.setTimeScale(scale),\n setFixedTimeStep: (step) => this.setFixedTimeStep(step),\n setDebug: (options) => this.setDebug(options),\n getMetrics: () => this.getMetrics(),\n handleResize: (width, height) => this.handleResize(width, height),\n subscribe: (event, callback) => this.subscribe(event, callback),\n // Pointer API - receives normalized events from main thread\n handlePointerEvent: (normalizedEvent) => this.handlePointerEvent(normalizedEvent),\n subscribeToPointer: (callback) => this.#pointerSurface.$subscribe(callback),\n bindPointer: (path) => this.#pointerSurface.$bind(path),\n // Test helper - only for testing\n _testEmitPointerEvent: (normalizedEvent) => this._testEmitPointerEvent(normalizedEvent)\n };\n }\n\n use(factories) {\n for (const factory of factories) {\n const type = definitionType(factory);\n switch (type) {\n case DEFINITIONS_TYPES.BRUSH:\n this.#addBrush(GLOBAL_LAYER_NAME, factory);\n break;\n case DEFINITIONS_TYPES.LAYER:\n this.#addLayer(factory);\n break;\n case DEFINITIONS_TYPES.SUBSCRIPTION:\n this.#addSubscription(factory);\n break;\n\n case DEFINITIONS_TYPES.SUBSCRIPTIONS:\n this.#addSubscriptions(factory);\n break;\n\n default:\n throw new Error(`Invalid factory type: ${type}`);\n }\n }\n return this;\n }\n\n // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n #addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n\n const layer = {...config, name, context: this.#contexts.get(config.context || '2d') };\n \n // Set up layer computed if it has data paths\n if (config.data) {\n layer.dataReactor = this.#createReactor(config.data, () => this.#pointerSurface);\n }\n\n // Set up when reactor if layer has condition\n if (config.when) {\n layer.whenReactor = this.#createReactor(config.when, () => (layer?.dataReactor?.computed() || undefined));\n }\n\n // Set up brush reactors and structure\n if (config.children && config.children.length > 0) {\n for (const child of config.children) {\n if (definitionType(child) === 'BRUSH') {\n this.#addBrush(name, child);\n }\n if (definitionType(child) === 'LAYER') {\n this.#addLayer(child);\n }\n }\n }\n\n this.#layers.set(name, layer);\n\n // Call layer mount hook\n if (layer.lifecycle?.onMount) {\n try {\n layer.lifecycle.onMount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onMount:`, error);\n }\n }\n\n return layer;\n }\n\n #addBrush(layerName, brushFactory) {\n const name = brushFactory._name;\n const brushConfig = brushFactory(this.useContext, this.#hitRegistry);\n const brush = {\n name,\n ...brushConfig\n };\n\n if (brushConfig.data) {\n brush.dataReactor = this.#createReactor(brushConfig.data, () => this.#pointerSurface);\n }\n\n if (brushConfig.when) {\n brush.whenReactor = this.#createReactor(brushConfig.when, () => (brush?.dataReactor?.computed() || undefined));\n }\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || this.#layers.get(layerName)?.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n if (!this.#brushes.has(layerName)) {\n this.#brushes.set(layerName, []);\n }\n\n this.#brushes.get(layerName).push(brush);\n\n return brush;\n }\n\n #addSubscription(subscriptionFactory) {\n const name = subscriptionFactory._name;\n const subscriptionConfig = subscriptionFactory(this.useContext);\n this.subscribe(name, subscriptionConfig);\n }\n\n #addSubscriptions(subscriptionsFactory) {\n const prefix = subscriptionsFactory._name;\n const subscriptions = subscriptionsFactory(this.useContext);\n for (const [event, handler] of Object.entries(subscriptions)) {\n const finalEvent = prefix ? `${prefix}:${event}` : event;\n this.subscribe(finalEvent, handler);\n }\n }\n\n #removeLayer(name) {\n const layer = this.#layers.get(name);\n if (!layer) return;\n\n // Call layer unmount hook\n if (layer.lifecycle?.onUnmount) {\n try {\n layer.lifecycle.onUnmount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onUnmount:`, error);\n }\n }\n\n const brushes = this.#brushes.get(name) || [];\n this.#brushes.delete(name);\n\n // Call brush unmount hooks and clean up reactors\n\n for (const brush of brushes) {\n if (brush.lifecycle?.onUnmount) {\n try {\n brush.lifecycle.onUnmount(\n this.#contexts.get(brush.context || layer.context)\n );\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onUnmount:`, error);\n }\n }\n // Clean up brush when reactor\n if (brush.whenReactor) {\n destroyComputed(brush.whenReactor);\n }\n // Clean up brush computed and subscription\n if (brush.dataReactor) {\n brush.dataReactor?.unsubscribe();\n if (brush.dataReactor?.computed) {\n destroyComputed(brush.dataReactor.computed);\n }\n }\n }\n\n // Clean up layer when reactor\n if (layer.whenReactor) {\n layer.whenReactor?.unsubscribe();\n if (layer.whenReactor?.computed) {\n destroyComputed(layer.whenReactor.computed);\n }\n }\n\n this.#layers.delete(name);\n }\n\n #scheduleRender() {\n if (this.#renderScheduled || this.#isRendering) return;\n \n this.#renderScheduled = true;\n \n this.#frameId = requestAnimationFrame(() => {\n this.#renderScheduled = false;\n this.#frameId = null;\n this.#render();\n });\n }\n\n async #render() {\n if (!this.#canvas) return;\n this.#isRendering = true;\n \n try {\n // Clear hit registry at start of render\n this.#hitRegistry.clear();\n \n const renderStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Clear all contexts\n this.#contexts.forEach(ctx => {\n ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n });\n\n // Render layers in order\n for (const layer of this.#layers.values()) {\n const layerStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Check layer condition\n if (layer.whenReactor && !layer.whenReactor.computed()) continue;\n\n const ctx = layer.context;\n\n if (!ctx) continue;\n\n // Layer beforeRender hook\n if (layer.lifecycle?.beforeRender) {\n try {\n layer.lifecycle.beforeRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" beforeRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n // Apply layer settings\n ctx.save();\n if (layer.settings) {\n Object.entries(layer.settings).forEach(([key, value]) => {\n if (typeof ctx[key] === 'function') {\n ctx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n ctx[key] = value;\n }\n });\n }\n\n const brushes = this.#brushes.get(layer.name) || [];\n\n // Render brushes\n for (const brush of brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor.computed()) continue;\n\n\n const brushCtx = brush.context ? \n this.#contexts.get(brush.context) : \n ctx;\n\n if (!brushCtx) continue;\n\n // Brush beforeRender hook\n if (brush.lifecycle?.beforeRender) {\n try {\n brush.lifecycle.beforeRender(brushCtx, this.#timing);\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" beforeRender:`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n continue;\n }\n }\n\n brushCtx.save();\n \n if (brush.settings) {\n Object.entries(brush.settings).forEach(([key, value]) => {\n if (typeof brushCtx[key] === 'function') {\n brushCtx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n brushCtx[key] = value;\n }\n });\n }\n \n try {\n const requiredAssets = {};\n if (brush.assets) {\n for (const key of brush.assets) {\n requiredAssets[key] = this.#assets.get(key);\n }\n }\n brush.render(brushCtx, (brush.dataReactor ? brush.dataReactor.computed() : undefined), requiredAssets, this.#timing);\n\n // Brush afterRender hook\n if (brush.lifecycle?.afterRender) {\n brush.lifecycle.afterRender(brushCtx, this.#timing);\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const brushTime = performance.now() - brushStart;\n this.#metrics.brushTimes.set(brush.name, brushTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderBrushBounds(brushCtx, brush);\n }\n }\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\":`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n } finally {\n brushCtx.restore();\n }\n }\n\n ctx.restore();\n\n // Layer afterRender hook\n if (layer.lifecycle?.afterRender) {\n try {\n layer.lifecycle.afterRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" afterRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const layerTime = performance.now() - layerStart;\n this.#metrics.layerTimes.set(layer.name, layerTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderLayerBounds(ctx, layer);\n }\n }\n }\n\n // Render debug overlay if enabled\n if (this.#runtimeConfig.debug?.enabled) {\n this.#renderDebugOverlay();\n }\n \n } finally {\n this.#isRendering = false;\n }\n }\n\n #renderBrushBounds(ctx, brush) {\n ctx.save();\n ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';\n ctx.lineWidth = 1;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderLayerBounds(ctx, layer) {\n ctx.save();\n ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';\n ctx.lineWidth = 2;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderDebugOverlay() {\n const ctx = this.#contexts.get(ContextTypes['2D']);\n if (!ctx) return;\n\n ctx.save();\n ctx.resetTransform();\n ctx.font = '12px monospace';\n ctx.fillStyle = 'white';\n ctx.strokeStyle = 'black';\n ctx.lineWidth = 3;\n\n let y = 20;\n const lineHeight = 15;\n\n if (this.#runtimeConfig.debug?.showFPS) {\n const text = `FPS: ${Math.round(this.#metrics.fps)} (${this.#timing.deltaTime.toFixed(2)}ms)`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n if (this.#runtimeConfig.debug?.showLayerTiming) {\n ctx.fillText('Layer Times:', 10, y);\n y += lineHeight;\n\n for (const [name, time] of this.#metrics.layerTimes) {\n const text = ` ${name}: ${time.toFixed(2)}ms`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n ctx.fillText(this.state.get(['_transitions', 'pointer', 'currentState']), 10, y);\n }\n\n ctx.restore();\n }\n\n handleResize(width, height) {\n // Call onResize hooks for all layers\n for (const layer of this.#layers.values()) {\n if (layer.lifecycle?.onResize) {\n try {\n layer.lifecycle.onResize(width, height, layer.context);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" onResize:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n }\n }\n\n #createReactor(fn, context = () => undefined) {\n if (!fn) return null;\n \n const computed = createComputed(fn, {\n immediate: true,\n context\n });\n \n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n \n return {computed, unsubscribe};\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.#removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n const event = pointer.event;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer);\n \n // Emit click if it wasn't a drag\n if (event && !event.isDragging) {\n this.#emit('pointer:click', pointer);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer);\n break;\n \n case 'dragstart':\n this.#emit('pointer:drag:start', pointer);\n break;\n \n case 'drag':\n this.#emit('pointer:drag:move', pointer);\n break;\n \n case 'dragend':\n this.#emit('pointer:drag:end', pointer);\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer);\n break;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = event?.isOverCanvas || false;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n }\n\n #handlePointerInteraction(normalizedEvent) {\n const { type, x, y } = normalizedEvent;\n const pointer = this.#pointerSurface;\n\n switch (type) {\n case 'down': {\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDown?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDown.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'up': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerUp?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerUp.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'move': {\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle pointer move on hovered area (only when NOT dragging)\n if (hitArea?.onPointerMove?.handler && !normalizedEvent.isDragging) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n // Handle hover changes\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'dragstart': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragStart?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragStart.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'drag': {\n // Perform hit test to detect drop targets while dragging\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle hover changes (for drop target detection)\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n\n // Call drag move handler on the active area (dragged element)\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragMove?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dragend': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragEnd?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragEnd.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dblclick':\n // Use active area from the last down event instead of a new hit test\n // This prevents issues when the hit registry is cleared during re-render\n const activeArea = pointer.activeArea;\n\n if (activeArea?.onPointerDblClick?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerDblClick.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n }\n\n #getContextForArea(area) {\n if (!area) return null;\n return area.context \n ? this.#contexts.get(area.context) \n : this.#contexts.get(ContextTypes['2D']);\n }\n\n subscribe(event, callback) {\n if (!this.#subscribers.has(event)) {\n this.#subscribers.set(event, new Set());\n }\n this.#subscribers.get(event).add(callback);\n \n return () => {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.#subscribers.delete(event);\n }\n }\n };\n }\n\n #hitTest(x, y) {\n // Sort by priority (highest first) and test\n const sorted = this.#hitRegistry.areas.sort((a, b) => \n (b.priority || 0) - (a.priority || 0)\n );\n \n for (const area of sorted) {\n if (this.#isPointInBounds(x, y, area.bounds)) {\n return area;\n }\n }\n return null;\n }\n\n #isPointInBounds(x, y, bounds) {\n return x >= bounds.x && \n x <= bounds.x + bounds.width &&\n y >= bounds.y && \n y <= bounds.y + bounds.height;\n }\n\n #emit(event, data) {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n for (const callback of callbacks) {\n callback(data);\n }\n }\n }\n\n // Test helper - only for testing, simulates normalized pointer events\n _testEmitPointerEvent(normalizedEvent) {\n this.#pointerSurface.handleEvent(normalizedEvent);\n this.#handlePointerInteraction(normalizedEvent);\n }\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export const ContextTypes = {\n '2D': '2d',\n 'WEBGL': 'webgl',\n 'WEBGL2': 'webgl2',\n 'BITMAPRENDERER': 'bitmaprenderer'\n};", "export class HitRegistry {\n #areas = new Map();\n\n register(id, area) {\n if (!id) {\n throw new Error('Hit area must have an id');\n }\n this.#areas.set(id, { id, ...area });\n return () => this.unregister(id);\n }\n\n unregister(id) {\n this.#areas.delete(id);\n }\n\n get(id) {\n return this.#areas.get(id);\n }\n\n has(id) {\n return this.#areas.has(id);\n }\n\n get areas() {\n return Array.from(this.#areas.values());\n }\n\n clear() {\n this.#areas.clear();\n }\n}", "import { ServiceProvider } from '@jucie.io/engine';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #offscreenCanvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #resizeSubscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n #hasTransferredControl = false;\n #dropSubscribers = new Set();\n // Internal state for semantic event interpretation\n #state = {\n isPressed: false,\n button: null,\n dragStartX: null,\n dragStartY: null,\n isDragging: false,\n dragThreshold: 5,\n prevX: null,\n prevY: null,\n // Double click detection\n lastClickTime: null,\n lastClickX: null,\n lastClickY: null,\n doubleClickThreshold: 300, // ms\n doubleClickDistanceThreshold: 5, // pixels\n // External drag-and-drop state (for file/data drops)\n isExternalDragOver: false,\n externalDragData: null\n };\n\n static manifest = {\n name: 'CanvasEvents',\n namespace: 'canvasEvents',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n onResize: (listener) => this.onResize(listener),\n transferControlToOffscreen: () => this.transferControlToOffscreen(),\n onFileDrop: (listener) => this.#addDropSubscriber(listener)\n };\n }\n\n setCanvas(canvas) {\n if (this.#canvas) {\n this.#removeListeners();\n }\n \n this.#canvas = canvas;\n this.#updateCachedRect();\n this.#initializeListeners();\n }\n\n subscribe(subscriber) {\n this.#subscribers.add(subscriber);\n return () => this.#subscribers.delete(subscriber);\n }\n\n onResize(subscriber) {\n this.#resizeSubscribers.add(subscriber);\n return () => this.#resizeSubscribers.delete(subscriber);\n }\n\n transferControlToOffscreen() {\n if (!this.#canvas) {\n throw new Error('Canvas must be set before transferring control to offscreen');\n }\n\n if (this.#hasTransferredControl) {\n throw new Error('Control has already been transferred to offscreen');\n }\n\n // Transfer control\n this.#offscreenCanvas = this.#canvas.transferControlToOffscreen();\n this.#hasTransferredControl = true;\n\n\n\n // Set initial dimensions on offscreen canvas\n this.#offscreenCanvas.width = this.#cachedRect.width;\n this.#offscreenCanvas.height = this.#cachedRect.height;\n\n // Emit initial resize event with actual canvas dimensions\n this.#emitResize({\n width: this.#canvas.width,\n height: this.#canvas.height\n });\n\n return this.#offscreenCanvas;\n }\n\n #addDropSubscriber(listener) {\n this.#dropSubscribers.add(listener);\n return () => this.#dropSubscribers.delete(listener);\n }\n\n #callDropSubscribers(...args) {\n for (const subscriber of this.#dropSubscribers) {\n subscriber(...args);\n }\n }\n\n #updateCachedRect() {\n if (this.#canvas) {\n this.#cachedRect = this.#canvas.getBoundingClientRect();\n }\n }\n\n #initializeListeners() {\n if (!this.#canvas) return;\n\n this.#updateCachedRect();\n\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target !== this.#canvas) {\n continue;\n }\n const { width, height } = entry.contentRect;\n this.#emitResize({\n width: width,\n height: height\n });\n }\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n // Canvas-specific events\n this.#canvas.addEventListener('wheel', this.#handleScroll, { passive: false });\n this.#canvas.addEventListener('pointerdown', this.#handleDown);\n \n // HTML5 Drag-and-Drop events (for external file/data drops)\n this.#canvas.addEventListener('dragenter', this.#handleDragEnter);\n this.#canvas.addEventListener('dragover', this.#handleDragOver);\n this.#canvas.addEventListener('dragleave', this.#handleDragLeave);\n this.#canvas.addEventListener('drop', this.#handleDrop);\n \n // Document-level events (for when pointer is captured)\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleCancel);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n if (this.#canvas) {\n this.#canvas.removeEventListener('wheel', this.#handleScroll);\n this.#canvas.removeEventListener('pointerdown', this.#handleDown);\n this.#canvas.removeEventListener('dragenter', this.#handleDragEnter);\n this.#canvas.removeEventListener('dragover', this.#handleDragOver);\n this.#canvas.removeEventListener('dragleave', this.#handleDragLeave);\n this.#canvas.removeEventListener('drop', this.#handleDrop);\n }\n\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleCancel);\n }\n\n #handleScroll = (event) => {\n event.preventDefault();\n event.stopPropagation();\n \n if (event.ctrlKey) {\n const normalized = this.#normalizeEvent(event, 'zoom');\n this.#emit(normalized);\n } else {\n const normalized = this.#normalizeEvent(event, 'scroll');\n this.#emit(normalized);\n }\n }\n\n #handleMove = (event) => {\n // Store latest raw event and throttle with RAF\n this.#pendingMove = event;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n const rawEvent = this.#pendingMove;\n this.#pendingMove = null;\n \n // Determine event type based on state\n let type = 'move';\n const position = this.#getPosition(rawEvent);\n \n // Check for drag start\n if (this.#state.isPressed && !this.#state.isDragging) {\n const dx = position.x - this.#state.dragStartX;\n const dy = position.y - this.#state.dragStartY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance > this.#state.dragThreshold) {\n this.#state.isDragging = true;\n type = 'dragstart';\n }\n } else if (this.#state.isDragging) {\n type = 'drag';\n }\n \n const normalized = this.#normalizeEvent(rawEvent, type);\n this.#emit(normalized);\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n const position = this.#getPosition(event);\n \n // Update state\n this.#state.isPressed = true;\n this.#state.button = event.button ?? null;\n this.#state.dragStartX = position.x;\n this.#state.dragStartY = position.y;\n this.#state.isDragging = false;\n \n // Capture the pointer to ensure we receive all subsequent events\n // even if the pointer moves outside the canvas\n try {\n this.#canvas.setPointerCapture(event.pointerId);\n } catch (e) {\n // Pointer capture might fail in some scenarios (e.g., already captured)\n // Continue anyway as document-level listeners will still work\n console.warn('Failed to capture pointer:', e);\n }\n \n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n\n #handleUp = (event) => {\n // Release pointer capture\n if (this.#canvas && this.#state.isPressed) {\n try {\n this.#canvas.releasePointerCapture(event.pointerId);\n } catch (e) {\n // Capture might have already been released, ignore\n }\n }\n \n // Emit dragend if we were dragging\n if (this.#state.isDragging) {\n const dragend = this.#normalizeEvent(event, 'dragend');\n this.#emit(dragend);\n }\n \n // Detect double click if this was a clean click (not a drag)\n if (!this.#state.isDragging) {\n const position = this.#getPosition(event);\n const now = Date.now();\n \n if (this.#state.lastClickTime !== null) {\n const timeDiff = now - this.#state.lastClickTime;\n const dx = position.x - this.#state.lastClickX;\n const dy = position.y - this.#state.lastClickY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n // Check if this qualifies as a double click\n if (\n timeDiff < this.#state.doubleClickThreshold &&\n distance < this.#state.doubleClickDistanceThreshold\n ) {\n // Emit double click event\n const dblclickEvent = this.#normalizeEvent(event, 'dblclick');\n this.#emit(dblclickEvent);\n \n // Reset double click tracking to prevent triple-click\n this.#state.lastClickTime = null;\n this.#state.lastClickX = null;\n this.#state.lastClickY = null;\n } else {\n // Update for potential next click\n this.#state.lastClickTime = now;\n this.#state.lastClickX = position.x;\n this.#state.lastClickY = position.y;\n }\n } else {\n // First click, start tracking\n this.#state.lastClickTime = now;\n this.#state.lastClickX = position.x;\n this.#state.lastClickY = position.y;\n }\n }\n \n // Always emit up event\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.isDragging = false;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n }\n\n #handleCancel = (event) => {\n // Release pointer capture\n if (this.#canvas && this.#state.isPressed) {\n try {\n this.#canvas.releasePointerCapture(event.pointerId);\n } catch (e) {\n // Capture might have already been released, ignore\n }\n }\n \n // Emit dragend if we were dragging (interaction was interrupted)\n if (this.#state.isDragging) {\n const dragend = this.#normalizeEvent(event, 'dragend');\n this.#emit(dragend);\n }\n \n // Emit cancel event (distinct from up - signals interrupted interaction)\n const normalized = this.#normalizeEvent(event, 'cancel');\n this.#emit(normalized);\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.isDragging = false;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n }\n\n #handleDragEnter = (event) => {\n event.preventDefault();\n \n this.#state.isExternalDragOver = true;\n this.#state.externalDragData = this.#extractDragData(event.dataTransfer);\n \n const normalized = this.#normalizeEvent(event, 'dragenter');\n this.#emit(normalized);\n }\n\n #handleDragOver = (event) => {\n event.preventDefault();\n \n // Set the drop effect (copy for files, move for internal drags)\n event.dataTransfer.dropEffect = this.#state.externalDragData?.hasFiles ? 'copy' : 'move';\n \n const normalized = this.#normalizeEvent(event, 'dragover');\n this.#emit(normalized);\n }\n\n #handleDragLeave = (event) => {\n event.preventDefault();\n \n // Only emit dragleave if we're actually leaving the canvas\n // (not just moving between child elements)\n const rect = this.#canvas.getBoundingClientRect();\n const isOutside = (\n event.clientX < rect.left ||\n event.clientX >= rect.right ||\n event.clientY < rect.top ||\n event.clientY >= rect.bottom\n );\n \n if (isOutside) {\n this.#state.isExternalDragOver = false;\n this.#state.externalDragData = null;\n \n const normalized = this.#normalizeEvent(event, 'dragleave');\n this.#emit(normalized);\n }\n }\n\n #handleDrop = (event) => {\n event.preventDefault();\n \n this.#state.isExternalDragOver = false;\n this.#state.externalDragData = this.#extractDragData(event.dataTransfer);\n \n const normalized = this.#normalizeEvent(event, 'drop');\n const files = this.#extractFiles(event.dataTransfer);\n this.#callDropSubscribers(files, normalized);\n this.#emit(normalized);\n \n // Reset state after drop\n this.#state.externalDragData = null;\n }\n\n #extractFiles(dataTransfer) {\n const files = [];\n if (dataTransfer?.items) {\n console.log('\uD83D\uDCE6 Processing', dataTransfer.items.length, 'items');\n for (const item of e.dataTransfer.items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n files.push(file);\n }\n }\n }\n }\n \n // Fallback to DataTransfer.files if items is empty or not available\n if (files.length === 0 && dataTransfer?.files) {\n console.log('\uD83D\uDCE6 Fallback to DataTransfer.files:',dataTransfer.files.length, 'files');\n for (let i = 0; i < dataTransfer.files.length; i++) {\n const file = dataTransfer.files[i];\n if (file) {\n files.push(file);\n }\n }\n }\n return files;\n }\n\n #extractDragData(dataTransfer) {\n if (!dataTransfer) return null;\n \n return {\n types: Array.from(dataTransfer.types),\n hasFiles: dataTransfer.types.includes('Files'),\n fileCount: dataTransfer.items?.length || 0,\n // Note: Can't access files/data until drop event due to security\n effectAllowed: dataTransfer.effectAllowed\n };\n }\n\n #emit(event) {\n for (const subscriber of this.#subscribers) {\n subscriber(event);\n }\n }\n\n #emitResize(resizeData) {\n for (const subscriber of this.#resizeSubscribers) {\n subscriber(resizeData);\n }\n }\n\n #getPosition(event) {\n const isOverCanvas = event.target === this.#canvas;\n \n let x, y;\n if (isOverCanvas) {\n x = event.offsetX;\n y = event.offsetY;\n } else if (this.#cachedRect) {\n x = event.clientX - this.#cachedRect.left;\n y = event.clientY - this.#cachedRect.top;\n } else {\n x = event.clientX;\n y = event.clientY;\n }\n \n return { x, y, isOverCanvas };\n }\n\n #normalizeEvent(event, type) {\n const { x, y, isOverCanvas } = this.#getPosition(event);\n\n const isWithinBounds = isOverCanvas || (\n this.#cachedRect &&\n x >= 0 && \n x <= this.#cachedRect.width && \n y >= 0 && \n y <= this.#cachedRect.height\n );\n \n // Calculate deltas based on event type\n let deltaX = 0;\n let deltaY = 0;\n let deltaZ = 0;\n let deltaMode = 0;\n \n if (type === 'scroll') {\n // Scroll events use wheel deltas\n deltaX = event.deltaX;\n deltaY = event.deltaY;\n deltaZ = event.deltaZ;\n deltaMode = event.deltaMode;\n } else if (type === 'zoom') {\n // Zoom uses simplified delta\n deltaX = 0;\n deltaY = event.deltaY;\n deltaZ = 0;\n } else if (type === 'move' || type === 'drag' || type === 'dragstart') {\n // Position-based events calculate deltas from previous position\n if (this.#state.prevX !== null && this.#state.prevY !== null) {\n deltaX = x - this.#state.prevX;\n deltaY = y - this.#state.prevY;\n }\n }\n \n // Calculate drag distance if dragging\n let dragDistance = 0;\n if (this.#state.isDragging && this.#state.dragStartX !== null && this.#state.dragStartY !== null) {\n const dx = x - this.#state.dragStartX;\n const dy = y - this.#state.dragStartY;\n dragDistance = Math.sqrt(dx * dx + dy * dy);\n }\n\n const normalized = {\n // Position\n x,\n y,\n clientX: event.clientX,\n clientY: event.clientY,\n prevX: this.#state.prevX,\n prevY: this.#state.prevY,\n \n // Event metadata\n type,\n timestamp: Date.now(),\n isOverCanvas,\n isWithinBounds,\n \n // Deltas (appropriate to event type)\n deltaX,\n deltaY,\n deltaZ,\n deltaMode,\n \n // Button state\n button: event.button ?? this.#state.button,\n buttons: event.buttons ?? 0,\n isPressed: this.#state.isPressed,\n \n // Drag state\n isDragging: this.#state.isDragging,\n dragStartX: this.#state.dragStartX,\n dragStartY: this.#state.dragStartY,\n dragDistance,\n \n // Modifiers\n shiftKey: event.shiftKey || false,\n ctrlKey: event.ctrlKey || false,\n altKey: event.altKey || false,\n metaKey: event.metaKey || false,\n \n // External drag-and-drop state (for file/data drops)\n isExternalDragOver: this.#state.isExternalDragOver,\n externalDragData: this.#state.externalDragData\n };\n \n // Add DataTransfer for drop events (only available on drop, not dragover)\n if (type === 'drop' && event.dataTransfer) {\n normalized.dataTransfer = {\n items: Array.from(event.dataTransfer.items).map(item => ({\n kind: item.kind,\n type: item.type\n })),\n types: Array.from(event.dataTransfer.types)\n };\n }\n \n // Update previous position for next delta calculation\n this.#state.prevX = x;\n this.#state.prevY = y;\n\n return normalized;\n }\n\n destroy() {\n if (this.#rafId) {\n cancelAnimationFrame(this.#rafId);\n this.#rafId = null;\n }\n this.#removeListeners();\n this.#canvas = null;\n this.#offscreenCanvas = null;\n this.#cachedRect = null;\n this.#subscribers.clear();\n this.#resizeSubscribers.clear();\n this.#hasTransferredControl = false;\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.button = null;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n this.#state.isDragging = false;\n this.#state.prevX = null;\n this.#state.prevY = null;\n this.#state.lastClickTime = null;\n this.#state.lastClickX = null;\n this.#state.lastClickY = null;\n this.#state.isExternalDragOver = false;\n this.#state.externalDragData = null;\n }\n}\n", "import { defineSurface } from '@jucie.io/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // Current normalized event from CanvasEvents\n const event = setup.signal(null);\n \n // Hit registry integration (still managed here)\n const hoveredArea = setup.signal(null);\n const activeArea = setup.signal(null);\n \n // Main handler - just stores the event\n const handleEvent = setup.action((_, normalizedEvent) => {\n event(normalizedEvent);\n });\n \n const setHoveredArea = setup.action((_, area) => {\n hoveredArea(area);\n });\n \n const setActiveArea = setup.action((_, area) => {\n activeArea(area);\n });\n \n const reset = setup.action(() => {\n event(null);\n hoveredArea(null);\n activeArea(null);\n });\n \n return {\n // Signals\n event,\n hoveredArea,\n activeArea,\n\n // Actions\n handleEvent,\n setHoveredArea,\n setActiveArea,\n reset\n };\n});\n", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nconst DEFINITIONS_TYPES = {\n BRUSH: 'BRUSH',\n LAYER: 'LAYER',\n SUBSCRIPTION: 'SUBSCRIPTION',\n SUBSCRIPTIONS: 'SUBSCRIPTIONS'\n};\n\nconst GLOBAL_LAYER_NAME = 'GLOBAL_LAYER';\n\nexport const defineBrush = createDefinition(DEFINITIONS_TYPES.BRUSH, [Object]);\nexport const defineLayer = createDefinition(DEFINITIONS_TYPES.LAYER, [Object]);\nexport const defineSubscription = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTION, [Function]);\nexport const defineSubscriptions = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTIONS, [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #brushes = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #assets = new Map();\n #isRunning = false;\n #frameId = null;\n #isRendering = false;\n #renderScheduled = false;\n\n // Mutable runtime config (separate from frozen config)\n #runtimeConfig = {\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n };\n\n // Timing state\n #timing = {\n lastFrameTime: 0,\n deltaTime: 0,\n elapsedTime: 0,\n frameCount: 0\n };\n\n // Debug metrics\n #metrics = {\n fps: 0,\n frameTime: 0,\n layerTimes: new Map(),\n brushTimes: new Map(),\n skippedFrames: 0\n };\n\n // Hit detection state\n #hitRegistry = new HitRegistry();\n #pointerSurface = usePointerSurface();\n #canvasEvents = null; // Only created in main thread mode\n #pointerUnsubscribe = null;\n #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasOverCanvas = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface,\n };\n }\n \n initialize () {\n this.#addLayer(defineLayer(GLOBAL_LAYER_NAME, () => ({\n context: ContextTypes['2D']\n })));\n }\n\n actions() {\n // Initialize runtime config from frozen config\n if (this.config) {\n Object.assign(this.#runtimeConfig, this.config);\n }\n \n return {\n addLayer: (layerDef) => this.#addLayer(layerDef),\n addLayers: (...layers) => {\n for (const layer of layers) {\n this.#addLayer(layer);\n }\n },\n use: (...factories) => this.use(factories),\n updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\n setOffscreenCanvas: (offscreenCanvas) => this.setOffscreenCanvas(offscreenCanvas),\n setAssets: (assets) => this.setAssets(assets),\n removeLayer: (name) => this.#removeLayer(name),\n start: () => this.start(),\n stop: () => this.stop(),\n render: () => this.render(),\n setTargetFPS: (fps) => this.setTargetFPS(fps),\n setTimeScale: (scale) => this.setTimeScale(scale),\n setFixedTimeStep: (step) => this.setFixedTimeStep(step),\n setDebug: (options) => this.setDebug(options),\n getMetrics: () => this.getMetrics(),\n handleResize: (width, height) => this.handleResize(width, height),\n subscribe: (event, callback) => this.subscribe(event, callback),\n // Pointer API - receives normalized events from main thread\n handlePointerEvent: (normalizedEvent) => this.handlePointerEvent(normalizedEvent),\n subscribeToPointer: (callback) => this.#pointerSurface.$subscribe(callback),\n bindPointer: (path) => this.#pointerSurface.$bind(path),\n // Test helper - only for testing\n _testEmitPointerEvent: (normalizedEvent) => this._testEmitPointerEvent(normalizedEvent)\n };\n }\n\n use(factories) {\n for (const factory of factories) {\n const type = definitionType(factory);\n switch (type) {\n case DEFINITIONS_TYPES.BRUSH:\n this.#addBrush(GLOBAL_LAYER_NAME, factory);\n break;\n case DEFINITIONS_TYPES.LAYER:\n this.#addLayer(factory);\n break;\n case DEFINITIONS_TYPES.SUBSCRIPTION:\n this.#addSubscription(factory);\n break;\n\n case DEFINITIONS_TYPES.SUBSCRIPTIONS:\n this.#addSubscriptions(factory);\n break;\n\n default:\n throw new Error(`Invalid factory type: ${type}`);\n }\n }\n return this;\n }\n\n // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n #addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n\n const layer = {...config, name, context: this.#contexts.get(config.context || '2d') };\n \n // Set up layer computed if it has data paths\n if (config.data) {\n layer.dataReactor = this.#createReactor(config.data, () => this.#pointerSurface);\n }\n\n // Set up when reactor if layer has condition\n if (config.when) {\n layer.whenReactor = this.#createReactor(config.when, () => (layer?.dataReactor?.computed() || undefined));\n }\n\n // Set up brush reactors and structure\n if (config.children && config.children.length > 0) {\n for (const child of config.children) {\n if (definitionType(child) === 'BRUSH') {\n this.#addBrush(name, child);\n }\n if (definitionType(child) === 'LAYER') {\n this.#addLayer(child);\n }\n }\n }\n\n this.#layers.set(name, layer);\n\n // Call layer mount hook\n if (layer.lifecycle?.onMount) {\n try {\n layer.lifecycle.onMount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onMount:`, error);\n }\n }\n\n return layer;\n }\n\n #addBrush(layerName, brushFactory) {\n const name = brushFactory._name;\n const brushConfig = brushFactory(this.useContext, this.#hitRegistry);\n const brush = {\n name,\n ...brushConfig\n };\n\n if (brushConfig.data) {\n brush.dataReactor = this.#createReactor(brushConfig.data, () => this.#pointerSurface);\n }\n\n if (brushConfig.when) {\n brush.whenReactor = this.#createReactor(brushConfig.when, () => (brush?.dataReactor?.computed() || undefined));\n }\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || this.#layers.get(layerName)?.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n if (!this.#brushes.has(layerName)) {\n this.#brushes.set(layerName, []);\n }\n\n this.#brushes.get(layerName).push(brush);\n\n return brush;\n }\n\n #addSubscription(subscriptionFactory) {\n const name = subscriptionFactory._name;\n const subscriptionConfig = subscriptionFactory(this.useContext);\n this.subscribe(name, subscriptionConfig);\n }\n\n #addSubscriptions(subscriptionsFactory) {\n const prefix = subscriptionsFactory._name;\n const subscriptions = subscriptionsFactory(this.useContext);\n for (const [event, handler] of Object.entries(subscriptions)) {\n const finalEvent = prefix ? `${prefix}:${event}` : event;\n this.subscribe(finalEvent, handler);\n }\n }\n\n #removeLayer(name) {\n const layer = this.#layers.get(name);\n if (!layer) return;\n\n // Call layer unmount hook\n if (layer.lifecycle?.onUnmount) {\n try {\n layer.lifecycle.onUnmount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onUnmount:`, error);\n }\n }\n\n const brushes = this.#brushes.get(name) || [];\n this.#brushes.delete(name);\n\n // Call brush unmount hooks and clean up reactors\n\n for (const brush of brushes) {\n if (brush.lifecycle?.onUnmount) {\n try {\n brush.lifecycle.onUnmount(\n this.#contexts.get(brush.context || layer.context)\n );\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onUnmount:`, error);\n }\n }\n // Clean up brush when reactor\n if (brush.whenReactor) {\n destroyComputed(brush.whenReactor);\n }\n // Clean up brush computed and subscription\n if (brush.dataReactor) {\n brush.dataReactor?.unsubscribe();\n if (brush.dataReactor?.computed) {\n destroyComputed(brush.dataReactor.computed);\n }\n }\n }\n\n // Clean up layer when reactor\n if (layer.whenReactor) {\n layer.whenReactor?.unsubscribe();\n if (layer.whenReactor?.computed) {\n destroyComputed(layer.whenReactor.computed);\n }\n }\n\n this.#layers.delete(name);\n }\n\n #scheduleRender() {\n if (this.#renderScheduled || this.#isRendering) return;\n \n this.#renderScheduled = true;\n \n this.#frameId = requestAnimationFrame(() => {\n this.#renderScheduled = false;\n this.#frameId = null;\n this.#render();\n });\n }\n\n async #render() {\n if (!this.#canvas) return;\n this.#isRendering = true;\n \n try {\n // Clear hit registry at start of render\n this.#hitRegistry.clear();\n \n const renderStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Clear all contexts\n this.#contexts.forEach(ctx => {\n ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n });\n\n // Render layers in order\n for (const layer of this.#layers.values()) {\n const layerStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Check layer condition\n if (layer.whenReactor && !layer.whenReactor.computed()) continue;\n\n const ctx = layer.context;\n\n if (!ctx) continue;\n\n // Layer beforeRender hook\n if (layer.lifecycle?.beforeRender) {\n try {\n layer.lifecycle.beforeRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" beforeRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n // Apply layer settings\n ctx.save();\n if (layer.settings) {\n Object.entries(layer.settings).forEach(([key, value]) => {\n if (typeof ctx[key] === 'function') {\n ctx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n ctx[key] = value;\n }\n });\n }\n\n const brushes = this.#brushes.get(layer.name) || [];\n\n // Render brushes\n for (const brush of brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor.computed()) continue;\n\n\n const brushCtx = brush.context ? \n this.#contexts.get(brush.context) : \n ctx;\n\n if (!brushCtx) continue;\n\n // Brush beforeRender hook\n if (brush.lifecycle?.beforeRender) {\n try {\n brush.lifecycle.beforeRender(brushCtx, this.#timing);\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" beforeRender:`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n continue;\n }\n }\n\n brushCtx.save();\n \n if (brush.settings) {\n Object.entries(brush.settings).forEach(([key, value]) => {\n if (typeof brushCtx[key] === 'function') {\n brushCtx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n brushCtx[key] = value;\n }\n });\n }\n \n try {\n const requiredAssets = {};\n if (brush.assets) {\n for (const key of brush.assets) {\n requiredAssets[key] = this.#assets.get(key);\n }\n }\n brush.render(brushCtx, (brush.dataReactor ? brush.dataReactor.computed() : undefined), requiredAssets, this.#timing);\n\n // Brush afterRender hook\n if (brush.lifecycle?.afterRender) {\n brush.lifecycle.afterRender(brushCtx, this.#timing);\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const brushTime = performance.now() - brushStart;\n this.#metrics.brushTimes.set(brush.name, brushTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderBrushBounds(brushCtx, brush);\n }\n }\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\":`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n } finally {\n brushCtx.restore();\n }\n }\n\n ctx.restore();\n\n // Layer afterRender hook\n if (layer.lifecycle?.afterRender) {\n try {\n layer.lifecycle.afterRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" afterRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const layerTime = performance.now() - layerStart;\n this.#metrics.layerTimes.set(layer.name, layerTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderLayerBounds(ctx, layer);\n }\n }\n }\n\n // Render debug overlay if enabled\n if (this.#runtimeConfig.debug?.enabled) {\n this.#renderDebugOverlay();\n }\n \n } finally {\n this.#isRendering = false;\n }\n }\n\n #renderBrushBounds(ctx, brush) {\n ctx.save();\n ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';\n ctx.lineWidth = 1;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderLayerBounds(ctx, layer) {\n ctx.save();\n ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';\n ctx.lineWidth = 2;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderDebugOverlay() {\n const ctx = this.#contexts.get(ContextTypes['2D']);\n if (!ctx) return;\n\n ctx.save();\n ctx.resetTransform();\n ctx.font = '12px monospace';\n ctx.fillStyle = 'white';\n ctx.strokeStyle = 'black';\n ctx.lineWidth = 3;\n\n let y = 20;\n const lineHeight = 15;\n\n if (this.#runtimeConfig.debug?.showFPS) {\n const text = `FPS: ${Math.round(this.#metrics.fps)} (${this.#timing.deltaTime.toFixed(2)}ms)`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n if (this.#runtimeConfig.debug?.showLayerTiming) {\n ctx.fillText('Layer Times:', 10, y);\n y += lineHeight;\n\n for (const [name, time] of this.#metrics.layerTimes) {\n const text = ` ${name}: ${time.toFixed(2)}ms`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n ctx.fillText(this.state.get(['_transitions', 'pointer', 'currentState']), 10, y);\n }\n\n ctx.restore();\n }\n\n handleResize(width, height) {\n // Call onResize hooks for all layers\n for (const layer of this.#layers.values()) {\n if (layer.lifecycle?.onResize) {\n try {\n layer.lifecycle.onResize(width, height, layer.context);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" onResize:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n }\n }\n\n #createReactor(fn, context = () => undefined) {\n if (!fn) return null;\n \n const computed = createComputed(fn, {\n immediate: true,\n context\n });\n \n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n \n return {computed, unsubscribe};\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.#removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n const event = pointer.event;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer);\n \n // Emit click if it wasn't a drag\n if (event && !event.isDragging) {\n this.#emit('pointer:click', pointer);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer);\n break;\n \n case 'dragstart':\n this.#emit('pointer:drag:start', pointer);\n break;\n \n case 'drag':\n this.#emit('pointer:drag:move', pointer);\n break;\n \n case 'dragend':\n this.#emit('pointer:drag:end', pointer);\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer);\n break;\n\n case 'drop':\n this.#emit('pointer:drop', pointer);\n break;\n\n case 'dragenter':\n this.#emit('pointer:dragenter', pointer);\n break;\n\n case 'dragover':\n this.#emit('pointer:dragover', pointer);\n break;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = event?.isOverCanvas || false;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n }\n\n #handlePointerInteraction(normalizedEvent) {\n const { type, x, y } = normalizedEvent;\n const pointer = this.#pointerSurface;\n\n switch (type) {\n case 'down': {\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDown?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDown.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'up': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerUp?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerUp.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'move': {\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle pointer move on hovered area (only when NOT dragging)\n if (hitArea?.onPointerMove?.handler && !normalizedEvent.isDragging) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n // Handle hover changes\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'dragstart': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragStart?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragStart.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'drag': {\n // Perform hit test to detect drop targets while dragging\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle hover changes (for drop target detection)\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n\n // Call drag move handler on the active area (dragged element)\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragMove?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dragend': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragEnd?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragEnd.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dblclick':\n // Use active area from the last down event instead of a new hit test\n // This prevents issues when the hit registry is cleared during re-render\n const activeArea = pointer.activeArea;\n\n if (activeArea?.onPointerDblClick?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerDblClick.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n }\n\n #getContextForArea(area) {\n if (!area) return null;\n return area.context \n ? this.#contexts.get(area.context) \n : this.#contexts.get(ContextTypes['2D']);\n }\n\n subscribe(event, callback) {\n if (!this.#subscribers.has(event)) {\n this.#subscribers.set(event, new Set());\n }\n this.#subscribers.get(event).add(callback);\n \n return () => {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.#subscribers.delete(event);\n }\n }\n };\n }\n\n #hitTest(x, y) {\n // Sort by priority (highest first) and test\n const sorted = this.#hitRegistry.areas.sort((a, b) => \n (b.priority || 0) - (a.priority || 0)\n );\n \n for (const area of sorted) {\n if (this.#isPointInBounds(x, y, area.bounds)) {\n return area;\n }\n }\n return null;\n }\n\n #isPointInBounds(x, y, bounds) {\n return x >= bounds.x && \n x <= bounds.x + bounds.width &&\n y >= bounds.y && \n y <= bounds.y + bounds.height;\n }\n\n #emit(event, data) {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n for (const callback of callbacks) {\n callback(data);\n }\n }\n }\n\n // Test helper - only for testing, simulates normalized pointer events\n _testEmitPointerEvent(normalizedEvent) {\n this.#pointerSurface.handleEvent(normalizedEvent);\n this.#handlePointerInteraction(normalizedEvent);\n }\n}"],
5
+ "mappings": "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",
6
6
  "names": ["ContextTypes", "HitRegistry", "#areas", "id", "area", "ServiceProvider", "CanvasEvents", "#canvas", "#offscreenCanvas", "#cachedRect", "#resizeObserver", "#subscribers", "#resizeSubscribers", "#pendingMove", "#rafId", "#hasTransferredControl", "#dropSubscribers", "#state", "canvas", "listener", "#addDropSubscriber", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#emitResize", "#callDropSubscribers", "args", "entries", "entry", "width", "height", "#handleScroll", "#handleDown", "#handleDragEnter", "#handleDragOver", "#handleDragLeave", "#handleDrop", "#handleMove", "#handleUp", "#handleCancel", "event", "normalized", "#normalizeEvent", "#emit", "rawEvent", "type", "position", "#getPosition", "dx", "dy", "e", "dragend", "now", "timeDiff", "distance", "dblclickEvent", "#extractDragData", "rect", "files", "#extractFiles", "dataTransfer", "item", "file", "resizeData", "isOverCanvas", "x", "y", "isWithinBounds", "deltaX", "deltaY", "deltaZ", "deltaMode", "dragDistance", "defineSurface", "usePointerSurface", "setup", "event", "hoveredArea", "activeArea", "handleEvent", "_", "normalizedEvent", "setHoveredArea", "area", "setActiveArea", "reset", "ServiceProvider", "createComputed", "destroyComputed", "addEffect", "createDefinition", "definitionType", "DEFINITIONS_TYPES", "GLOBAL_LAYER_NAME", "defineBrush", "defineLayer", "defineSubscription", "defineSubscriptions", "Painter", "#layers", "#brushes", "#canvas", "#contexts", "#assets", "#isRunning", "#frameId", "#isRendering", "#renderScheduled", "#runtimeConfig", "#timing", "#metrics", "#hitRegistry", "HitRegistry", "#pointerSurface", "usePointerSurface", "#canvasEvents", "#pointerUnsubscribe", "#resizeObserver", "#subscribers", "#wasOverCanvas", "#addLayer", "ContextTypes", "layerDef", "layers", "layer", "factories", "fn", "canvas", "offscreenCanvas", "assets", "name", "#removeLayer", "fps", "scale", "step", "options", "width", "height", "event", "callback", "normalizedEvent", "path", "factory", "type", "#addBrush", "#addSubscription", "#addSubscriptions", "domCanvas", "ctx", "CanvasEvents", "entries", "entry", "result", "#scheduleRender", "config", "#createReactor", "child", "error", "layerName", "brushFactory", "brushConfig", "brush", "subscriptionFactory", "subscriptionConfig", "subscriptionsFactory", "prefix", "subscriptions", "handler", "finalEvent", "brushes", "#render", "renderStart", "layerStart", "key", "value", "brushStart", "brushCtx", "requiredAssets", "brushTime", "#renderBrushBounds", "layerTime", "#renderLayerBounds", "#renderDebugOverlay", "y", "lineHeight", "text", "time", "context", "computed", "unsubscribe", "#handlePointerInteraction", "#emitPointerEvents", "pointer", "#emit", "wasOverCanvas", "isOverCanvas", "x", "hitArea", "#hitTest", "#getContextForArea", "activeArea", "prevHovered", "area", "callbacks", "sorted", "a", "b", "#isPointInBounds", "bounds", "data"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jucie.io/engine-painter",
3
- "version": "1.0.58",
3
+ "version": "1.0.60",
4
4
  "description": "Canvas painting service for @jucie.io/engine with reactive rendering support",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",