@jucie.io/engine-painter 1.0.59 → 1.0.61

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;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};
1
+ var f={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var g=class{#e=new Map;register(t,e){if(!t)throw new Error("Hit area must have an id");return this.#e.set(t,{id:t,...e}),()=>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 D}from"@jucie.io/engine";var m=class extends D{#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 e of this.#i)e(...t)}#a(){this.#e&&(this.#r=this.#e.getBoundingClientRect())}#m(){this.#e&&(this.#a(),this.#n=new ResizeObserver(t=>{for(let e of t){if(e.target!==this.#e)continue;let{width:s,height:i}=e.contentRect;this.#L({width:s,height:i})}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 e=this.#h(t,"zoom");this.#o(e)}else{let e=this.#h(t,"scroll");this.#o(e)}};#b=t=>{this.#d=t,!this.#f&&(this.#f=requestAnimationFrame(()=>{if(this.#d){let e=this.#d;this.#d=null;let s="move",i=this.#v(e);if(this.#t.isPressed&&!this.#t.isDragging){let r=i.x-this.#t.dragStartX,a=i.y-this.#t.dragStartY;Math.sqrt(r*r+a*a)>this.#t.dragThreshold&&(this.#t.isDragging=!0,s="dragstart")}else this.#t.isDragging&&(s="drag");let n=this.#h(e,s);this.#o(n)}this.#f=null}))};#E=t=>{let e=this.#v(t);this.#t.isPressed=!0,this.#t.button=t.button??null,this.#t.dragStartX=e.x,this.#t.dragStartY=e.y,this.#t.isDragging=!1;try{this.#e.setPointerCapture(t.pointerId)}catch(i){console.warn("Failed to capture pointer:",i)}let s=this.#h(t,"down");this.#o(s)};#y=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let s=this.#h(t,"dragend");this.#o(s)}if(!this.#t.isDragging){let s=this.#v(t),i=Date.now();if(this.#t.lastClickTime!==null){let n=i-this.#t.lastClickTime,r=s.x-this.#t.lastClickX,a=s.y-this.#t.lastClickY,o=Math.sqrt(r*r+a*a);if(n<this.#t.doubleClickThreshold&&o<this.#t.doubleClickDistanceThreshold){let h=this.#h(t,"dblclick");this.#o(h),this.#t.lastClickTime=null,this.#t.lastClickX=null,this.#t.lastClickY=null}else this.#t.lastClickTime=i,this.#t.lastClickX=s.x,this.#t.lastClickY=s.y}else this.#t.lastClickTime=i,this.#t.lastClickX=s.x,this.#t.lastClickY=s.y}let e=this.#h(t,"up");this.#o(e),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 s=this.#h(t,"dragend");this.#o(s)}let e=this.#h(t,"cancel");this.#o(e),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 e=this.#h(t,"dragenter");this.#o(e)};#k=t=>{t.preventDefault(),t.dataTransfer.dropEffect=this.#t.externalDragData?.hasFiles?"copy":"move";let e=this.#h(t,"dragover");this.#o(e)};#D=t=>{t.preventDefault();let e=this.#e.getBoundingClientRect();if(t.clientX<e.left||t.clientX>=e.right||t.clientY<e.top||t.clientY>=e.bottom){this.#t.isExternalDragOver=!1,this.#t.externalDragData=null;let i=this.#h(t,"dragleave");this.#o(i)}};#T=t=>{t.preventDefault(),this.#t.isExternalDragOver=!1,this.#t.externalDragData=this.#A(t.dataTransfer);let e=this.#h(t,"drop"),s=this.#O(t.dataTransfer);this.#C(s,e),this.#o(e),this.#t.externalDragData=null};#O(t){let e=[];if(t?.items){console.log("\u{1F4E6} Processing",t.items.length,"items");for(let s of t.items)if(s.kind==="file"){let i=s.getAsFile();i&&e.push(i)}}if(e.length===0&&t?.files){console.log("\u{1F4E6} Fallback to DataTransfer.files:",t.files.length,"files");for(let s=0;s<t.files.length;s++){let i=t.files[s];i&&e.push(i)}}return e}#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 e of this.#S)e(t)}#L(t){for(let e of this.#g)e(t)}#v(t){let e=t.target===this.#e,s,i;return e?(s=t.offsetX,i=t.offsetY):this.#r?(s=t.clientX-this.#r.left,i=t.clientY-this.#r.top):(s=t.clientX,i=t.clientY),{x:s,y:i,isOverCanvas:e}}#h(t,e){let{x:s,y:i,isOverCanvas:n}=this.#v(t),r=n||this.#r&&s>=0&&s<=this.#r.width&&i>=0&&i<=this.#r.height,a=0,o=0,h=0,l=0;e==="scroll"?(a=t.deltaX,o=t.deltaY,h=t.deltaZ,l=t.deltaMode):e==="zoom"?(a=0,o=t.deltaY,h=0):(e==="move"||e==="drag"||e==="dragstart")&&this.#t.prevX!==null&&this.#t.prevY!==null&&(a=s-this.#t.prevX,o=i-this.#t.prevY);let w=0;if(this.#t.isDragging&&this.#t.dragStartX!==null&&this.#t.dragStartY!==null){let u=s-this.#t.dragStartX,C=i-this.#t.dragStartY;w=Math.sqrt(u*u+C*C)}let x={x:s,y:i,clientX:t.clientX,clientY:t.clientY,prevX:this.#t.prevX,prevY:this.#t.prevY,type:e,timestamp:Date.now(),isOverCanvas:n,isWithinBounds:r,deltaX:a,deltaY:o,deltaZ:h,deltaMode:l,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:w,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 e==="drop"&&t.dataTransfer&&(x.dataTransfer={items:Array.from(t.dataTransfer.items).map(u=>({kind:u.kind,type:u.type})),types:Array.from(t.dataTransfer.types)}),this.#t.prevX=s,this.#t.prevY=i,x}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 T}from"@jucie.io/reactive";var v=T(c=>{let t=c.signal(null),e=c.signal(null),s=c.signal(null),i=c.action((o,h)=>{t(h)}),n=c.action((o,h)=>{e(h)}),r=c.action((o,h)=>{s(h)}),a=c.action(()=>{t(null),e(null),s(null)});return{event:t,hoveredArea:e,activeArea:s,handleEvent:i,setHoveredArea:n,setActiveArea:r,reset:a}});import{ServiceProvider as P}from"@jucie.io/engine";import{createComputed as k,destroyComputed as y,addEffect as A}from"@jucie.io/reactive";import{createDefinition as p,definitionType as b}from"@jucie.io/engine";var d={BRUSH:"BRUSH",LAYER:"LAYER",SUBSCRIPTION:"SUBSCRIPTION",SUBSCRIPTIONS:"SUBSCRIPTIONS"},E="GLOBAL_LAYER",L=p(d.BRUSH,[Object]),R=p(d.LAYER,[Object]),O=p(d.SUBSCRIPTION,[Function]),Y=p(d.SUBSCRIPTIONS,[Object]),S=class extends P{#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 g;#a=v();#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(R(E,()=>({context:f["2D"]})))}actions(){return this.config&&Object.assign(this.#i,this.config),{addLayer:t=>this.#y(t),addLayers:(...t)=>{for(let e of t)this.#y(e)},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,e)=>this.handleResize(t,e),subscribe:(t,e)=>this.subscribe(t,e),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 e of t){let s=b(e);switch(s){case d.BRUSH:this.#R(E,e);break;case d.LAYER:this.#y(e);break;case d.SUBSCRIPTION:this.#P(e);break;case d.SUBSCRIPTIONS:this.#k(e);break;default:throw new Error(`Invalid factory type: ${s}`)}}return this}setCanvas(t){let e=t,s=t.transferControlToOffscreen();s.width=e.width,s.height=e.height,this.#r=s,Object.values(f).forEach(i=>{try{let n=s.getContext(i);n&&this.#n.set(i,n)}catch{console.warn(`Context type ${i} not supported`)}}),this.#m||(this.#m=new m),this.#m.setCanvas(e),this.#u&&this.#u.disconnect(),this.#u=new ResizeObserver(i=>{let n=i[0];n&&n.target===e&&(s.width=e.width,s.height=e.height,this.handleResize(e.width,e.height))}),this.#u.observe(e),this.#p&&this.#p(),this.#p=this.#m.subscribe(i=>{this.handlePointerEvent(i)})}setOffscreenCanvas(t){this.#r=t,Object.values(f).forEach(e=>{try{let s=t.getContext(e);s&&this.#n.set(e,s)}catch{console.warn(`Context type ${e} not supported`)}})}updateCanvas(t){let e=t(this.#r);e&&(this.#r=e)}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(b(t)!=="LAYER")throw new Error("Invalid layer definition");let e=t._name,s=t(this.useContext,this.#C),i={...s,name:e,context:this.#n.get(s.context||"2d")};if(s.data&&(i.dataReactor=this.#v(s.data,()=>this.#a)),s.when&&(i.whenReactor=this.#v(s.when,()=>i?.dataReactor?.computed()||void 0)),s.children&&s.children.length>0)for(let n of s.children)b(n)==="BRUSH"&&this.#R(e,n),b(n)==="LAYER"&&this.#y(n);if(this.#e.set(e,i),i.lifecycle?.onMount)try{i.lifecycle.onMount(i.context)}catch(n){console.error(`Error in layer "${e}" onMount:`,n)}return i}#R(t,e){let s=e._name,i=e(this.useContext,this.#C),n={name:s,...i};if(i.data&&(n.dataReactor=this.#v(i.data,()=>this.#a)),i.when&&(n.whenReactor=this.#v(i.when,()=>n?.dataReactor?.computed()||void 0)),n.lifecycle?.onMount)try{n.lifecycle.onMount(this.#n.get(n.context||this.#e.get(t)?.context))}catch(r){console.error(`Error in brush "${n.name}" onMount:`,r)}return this.#l.has(t)||this.#l.set(t,[]),this.#l.get(t).push(n),n}#P(t){let e=t._name,s=t(this.useContext);this.subscribe(e,s)}#k(t){let e=t._name,s=t(this.useContext);for(let[i,n]of Object.entries(s)){let r=e?`${e}:${i}`:i;this.subscribe(r,n)}}#D(t){let e=this.#e.get(t);if(!e)return;if(e.lifecycle?.onUnmount)try{e.lifecycle.onUnmount(e.context)}catch(i){console.error(`Error in layer "${t}" onUnmount:`,i)}let s=this.#l.get(t)||[];this.#l.delete(t);for(let i of s){if(i.lifecycle?.onUnmount)try{i.lifecycle.onUnmount(this.#n.get(i.context||e.context))}catch(n){console.error(`Error in brush "${i.name}" onUnmount:`,n)}i.whenReactor&&y(i.whenReactor),i.dataReactor&&(i.dataReactor?.unsubscribe(),i.dataReactor?.computed&&y(i.dataReactor.computed))}e.whenReactor&&(e.whenReactor?.unsubscribe(),e.whenReactor?.computed&&y(e.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(e=>{e.clearRect(0,0,this.#r.width,this.#r.height)});for(let e of this.#e.values()){let s=this.#i.debug?.enabled?performance.now():0;if(e.whenReactor&&!e.whenReactor.computed())continue;let i=e.context;if(!i)continue;if(e.lifecycle?.beforeRender)try{e.lifecycle.beforeRender(i,this.#t)}catch(r){console.error(`Error in layer "${e.name}" beforeRender:`,r),e.lifecycle?.onError&&e.lifecycle.onError(r)}i.save(),e.settings&&Object.entries(e.settings).forEach(([r,a])=>{typeof i[r]=="function"?i[r](...Array.isArray(a)?a:[a]):i[r]=a});let n=this.#l.get(e.name)||[];for(let r of n){let a=this.#i.debug?.enabled?performance.now():0;if(r.whenReactor&&!r.whenReactor.computed())continue;let o=r.context?this.#n.get(r.context):i;if(o){if(r.lifecycle?.beforeRender)try{r.lifecycle.beforeRender(o,this.#t)}catch(h){console.error(`Error in brush "${r.name}" beforeRender:`,h),r.lifecycle?.onError&&r.lifecycle.onError(h);continue}o.save(),r.settings&&Object.entries(r.settings).forEach(([h,l])=>{typeof o[h]=="function"?o[h](...Array.isArray(l)?l:[l]):o[h]=l});try{let h={};if(r.assets)for(let l of r.assets)h[l]=this.#S.get(l);if(r.render(o,r.dataReactor?r.dataReactor.computed():void 0,h,this.#t),r.lifecycle?.afterRender&&r.lifecycle.afterRender(o,this.#t),this.#i.debug?.enabled){let l=performance.now()-a;this.#x.brushTimes.set(r.name,l),this.#i.debug?.showBounds&&this.#A(o,r)}}catch(h){console.error(`Error in brush "${r.name}":`,h),r.lifecycle?.onError&&r.lifecycle.onError(h)}finally{o.restore()}}}if(i.restore(),e.lifecycle?.afterRender)try{e.lifecycle.afterRender(i,this.#t)}catch(r){console.error(`Error in layer "${e.name}" afterRender:`,r),e.lifecycle?.onError&&e.lifecycle.onError(r)}if(this.#i.debug?.enabled){let r=performance.now()-s;this.#x.layerTimes.set(e.name,r),this.#i.debug?.showBounds&&this.#o(i,e)}}this.#i.debug?.enabled&&this.#L()}finally{this.#f=!1}}}#A(t,e){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,e){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(f["2D"]);if(!t)return;t.save(),t.resetTransform(),t.font="12px monospace",t.fillStyle="white",t.strokeStyle="black",t.lineWidth=3;let e=20,s=15;if(this.#i.debug?.showFPS){let i=`FPS: ${Math.round(this.#x.fps)} (${this.#t.deltaTime.toFixed(2)}ms)`;t.strokeText(i,10,e),t.fillText(i,10,e),e+=s}if(this.#i.debug?.showLayerTiming){t.fillText("Layer Times:",10,e),e+=s;for(let[i,n]of this.#x.layerTimes){let r=` ${i}: ${n.toFixed(2)}ms`;t.strokeText(r,10,e),t.fillText(r,10,e),e+=s}t.fillText(this.state.get(["_transitions","pointer","currentState"]),10,e)}t.restore()}handleResize(t,e){for(let s of this.#e.values())if(s.lifecycle?.onResize)try{s.lifecycle.onResize(t,e,s.context)}catch(i){console.error(`Error in layer "${s.name}" onResize:`,i),s.lifecycle?.onError&&s.lifecycle.onError(i)}}#v(t,e=()=>{}){if(!t)return null;let s=k(t,{immediate:!0,context:e}),i=A(s,()=>this.#T());return{computed:s,unsubscribe:i}}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:e}=t,s=this.#a,i=s.event;switch(e){case"down":this.#s("pointer:down",s);break;case"up":this.#s("pointer:up",s),i&&!i.isDragging&&this.#s("pointer:click",s);break;case"move":this.#s("pointer:move",s);break;case"dragstart":this.#s("pointer:drag:start",s);break;case"drag":this.#s("pointer:drag:move",s);break;case"dragend":this.#s("pointer:drag:end",s);break;case"scroll":this.#s("pointer:scroll",s);break;case"zoom":this.#s("pointer:zoom",s);break;case"dblclick":this.#s("pointer:dblclick",s);break;case"drop":this.#s("pointer:drop",s);break;case"dragenter":this.#s("pointer:dragenter",s);break;case"dragover":this.#s("pointer:dragover",s);break}let n=this.#E,r=i?.isOverCanvas||!1;r&&!n?this.#s("pointer:enter",s):!r&&n&&this.#s("pointer:leave",s),this.#E=r}#B(t){let{type:e,x:s,y:i}=t,n=this.#a;switch(e){case"down":{let a=this.#Y(s,i);if(n.setActiveArea(a),a?.onPointerDown?.handler){let o=this.#c(a);a.onPointerDown.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}case"up":{let a=n.activeArea;if(a?.onPointerUp?.handler){let o=this.#c(a);a.onPointerUp.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}case"move":{let a=this.#Y(s,i),o=n.hoveredArea;if(a?.onPointerMove?.handler&&!t.isDragging){let h=this.#c(a);a.onPointerMove.handler({event:t,ctx:h,emit:this.#s.bind(this)})}if(a?.id!==o?.id){if(o?.onPointerLeave?.handler){let h=this.#c(o);o.onPointerLeave.handler({event:t,ctx:h,emit:this.#s.bind(this)})}if(a?.onPointerEnter?.handler){let h=this.#c(a);a.onPointerEnter.handler({event:t,ctx:h,emit:this.#s.bind(this)})}n.setHoveredArea(a)}break}case"dragstart":{let a=n.activeArea;if(a?.onDragStart?.handler){let o=this.#c(a);a.onDragStart.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}case"drag":{let a=this.#Y(s,i),o=n.hoveredArea;if(a?.id!==o?.id){if(o?.onPointerLeave?.handler){let l=this.#c(o);o.onPointerLeave.handler({event:t,ctx:l,emit:this.#s.bind(this)})}if(a?.onPointerEnter?.handler){let l=this.#c(a);a.onPointerEnter.handler({event:t,ctx:l,emit:this.#s.bind(this)})}n.setHoveredArea(a)}let h=n.activeArea;if(h?.onDragMove?.handler){let l=this.#c(h);h.onDragMove.handler({event:t,ctx:l,emit:this.#s.bind(this)})}break}case"dragend":{let a=n.activeArea;if(a?.onDragEnd?.handler){let o=this.#c(a);a.onDragEnd.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}case"dblclick":let r=n.activeArea;if(r?.onPointerDblClick?.handler){let a=this.#c(r);r.onPointerDblClick.handler({event:t,ctx:a,emit:this.#s.bind(this)})}break}}#c(t){return t?t.context?this.#n.get(t.context):this.#n.get(f["2D"]):null}subscribe(t,e){return this.#b.has(t)||this.#b.set(t,new Set),this.#b.get(t).add(e),()=>{let s=this.#b.get(t);s&&(s.delete(e),s.size===0&&this.#b.delete(t))}}#Y(t,e){let s=this.#C.areas.sort((i,n)=>(n.priority||0)-(i.priority||0));for(let i of s)if(this.#M(t,e,i.bounds))return i;return null}#M(t,e,s){return t>=s.x&&t<=s.x+s.width&&e>=s.y&&e<=s.y+s.height}#s(t,e){let s=this.#b.get(t);if(s)for(let i of s)i(e)}_testEmitPointerEvent(t){this.#a.handleEvent(t),this.#B(t)}};export{m as CanvasEvents,g as HitRegistry,S as Painter,L as defineBrush,R as defineLayer,O as defineSubscription,Y as defineSubscriptions,v 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 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
- "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"]
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 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
+ "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", "i", "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.59",
3
+ "version": "1.0.61",
4
4
  "description": "Canvas painting service for @jucie.io/engine with reactive rendering support",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",