@jucie.io/engine-painter 1.0.49 → 1.0.50

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 f={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var u=class{#t=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#t.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#t.delete(e)}get(e){return this.#t.get(e)}has(e){return this.#t.has(e)}get areas(){return Array.from(this.#t.values())}clear(){this.#t.clear()}};import{ServiceProvider as C}from"@jucie.io/engine";var g=class extends C{#t=null;#h=null;#i=null;#r=null;#v=new Set;#m=new Set;#d=null;#f=null;#y=!1;#e={isPressed:!1,button:null,dragStartX:null,dragStartY:null,isDragging:!1,dragThreshold:5,prevX:null,prevY:null};static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),onResize:e=>this.onResize(e),transferControlToOffscreen:()=>this.transferControlToOffscreen()}}setCanvas(e){this.#t&&this.#w(),this.#t=e,this.#a(),this.#S()}subscribe(e){return this.#v.add(e),()=>this.#v.delete(e)}onResize(e){return this.#m.add(e),()=>this.#m.delete(e)}transferControlToOffscreen(){if(!this.#t)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#y)throw new Error("Control has already been transferred to offscreen");return this.#h=this.#t.transferControlToOffscreen(),this.#y=!0,this.#h.width=this.#i.width,this.#h.height=this.#i.height,this.#x({width:this.#t.width,height:this.#t.height}),this.#h}#a(){this.#t&&(this.#i=this.#t.getBoundingClientRect())}#S(){this.#t&&(this.#a(),this.#r=new ResizeObserver(e=>{for(let t of e){if(t.target!==this.#t)continue;let{width:s,height:i}=t.contentRect;this.#x({width:s,height:i})}this.#a()}),this.#r.observe(this.#t),this.#t.addEventListener("wheel",this.#o,{passive:!1}),this.#t.addEventListener("pointerdown",this.#b),this.#t.addEventListener("dblclick",this.#R),document.addEventListener("pointermove",this.#u),document.addEventListener("pointerup",this.#g),document.addEventListener("pointercancel",this.#p))}#w(){this.#r&&(this.#r.disconnect(),this.#r=null),this.#t&&(this.#t.removeEventListener("wheel",this.#o),this.#t.removeEventListener("pointerdown",this.#b),this.#t.removeEventListener("dblclick",this.#R)),document.removeEventListener("pointermove",this.#u),document.removeEventListener("pointerup",this.#g),document.removeEventListener("pointercancel",this.#p)}#o=e=>{if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#c(e,"zoom");this.#n(t)}else{let t=this.#c(e,"scroll");this.#n(t)}};#u=e=>{this.#d=e,!this.#f&&(this.#f=requestAnimationFrame(()=>{if(this.#d){let t=this.#d;this.#d=null;let s="move",i=this.#E(t);if(this.#e.isPressed&&!this.#e.isDragging){let r=i.x-this.#e.dragStartX,o=i.y-this.#e.dragStartY;Math.sqrt(r*r+o*o)>this.#e.dragThreshold&&(this.#e.isDragging=!0,s="dragstart")}else this.#e.isDragging&&(s="drag");let n=this.#c(t,s);this.#n(n)}this.#f=null}))};#b=e=>{let t=this.#E(e);this.#e.isPressed=!0,this.#e.button=e.button??null,this.#e.dragStartX=t.x,this.#e.dragStartY=t.y,this.#e.isDragging=!1;try{this.#t.setPointerCapture(e.pointerId)}catch(i){console.warn("Failed to capture pointer:",i)}let s=this.#c(e,"down");this.#n(s)};#g=e=>{if(this.#t&&this.#e.isPressed)try{this.#t.releasePointerCapture(e.pointerId)}catch{}if(this.#e.isDragging){let s=this.#c(e,"dragend");this.#n(s)}let t=this.#c(e,"up");this.#n(t),this.#e.isPressed=!1,this.#e.isDragging=!1,this.#e.dragStartX=null,this.#e.dragStartY=null};#p=e=>{if(this.#t&&this.#e.isPressed)try{this.#t.releasePointerCapture(e.pointerId)}catch{}if(this.#e.isDragging){let s=this.#c(e,"dragend");this.#n(s)}let t=this.#c(e,"cancel");this.#n(t),this.#e.isPressed=!1,this.#e.isDragging=!1,this.#e.dragStartX=null,this.#e.dragStartY=null};#R=e=>{let t=this.#c(e,"dblclick");this.#n(t)};#n(e){for(let t of this.#v)t(e)}#x(e){for(let t of this.#m)t(e)}#E(e){let t=e.target===this.#t,s,i;return t?(s=e.offsetX,i=e.offsetY):this.#i?(s=e.clientX-this.#i.left,i=e.clientY-this.#i.top):(s=e.clientX,i=e.clientY),{x:s,y:i,isOverCanvas:t}}#c(e,t){let{x:s,y:i,isOverCanvas:n}=this.#E(e),r=n||this.#i&&s>=0&&s<=this.#i.width&&i>=0&&i<=this.#i.height,o=0,a=0,h=0,c=0;t==="scroll"?(o=e.deltaX,a=e.deltaY,h=e.deltaZ,c=e.deltaMode):t==="zoom"?(o=0,a=e.deltaY,h=0):(t==="move"||t==="drag"||t==="dragstart")&&this.#e.prevX!==null&&this.#e.prevY!==null&&(o=s-this.#e.prevX,a=i-this.#e.prevY);let S=0;if(this.#e.isDragging&&this.#e.dragStartX!==null&&this.#e.dragStartY!==null){let w=s-this.#e.dragStartX,R=i-this.#e.dragStartY;S=Math.sqrt(w*w+R*R)}let P={x:s,y:i,clientX:e.clientX,clientY:e.clientY,prevX:this.#e.prevX,prevY:this.#e.prevY,type:t,timestamp:Date.now(),isOverCanvas:n,isWithinBounds:r,deltaX:o,deltaY:a,deltaZ:h,deltaMode:c,button:e.button??this.#e.button,buttons:e.buttons??0,isPressed:this.#e.isPressed,isDragging:this.#e.isDragging,dragStartX:this.#e.dragStartX,dragStartY:this.#e.dragStartY,dragDistance:S,shiftKey:e.shiftKey||!1,ctrlKey:e.ctrlKey||!1,altKey:e.altKey||!1,metaKey:e.metaKey||!1};return this.#e.prevX=s,this.#e.prevY=i,P}destroy(){this.#f&&(cancelAnimationFrame(this.#f),this.#f=null),this.#w(),this.#t=null,this.#h=null,this.#i=null,this.#v.clear(),this.#m.clear(),this.#y=!1,this.#e.isPressed=!1,this.#e.button=null,this.#e.dragStartX=null,this.#e.dragStartY=null,this.#e.isDragging=!1,this.#e.prevX=null,this.#e.prevY=null}};import{defineSurface as T}from"@jucie.io/reactive";var p=T(l=>{let e=l.signal(null),t=l.signal(null),s=l.signal(null),i=l.action((a,h)=>{e(h)}),n=l.action((a,h)=>{t(h)}),r=l.action((a,h)=>{s(h)}),o=l.action(()=>{e(null),t(null),s(null)});return{event:e,hoveredArea:t,activeArea:s,handleEvent:i,setHoveredArea:n,setActiveArea:r,reset:o}});import{ServiceProvider as A}from"@jucie.io/engine";import{createComputed as L,destroyComputed as v,addEffect as O}from"@jucie.io/reactive";import{createDefinition as m,definitionType as b}from"@jucie.io/engine";var d={BRUSH:"BRUSH",LAYER:"LAYER",SUBSCRIPTION:"SUBSCRIPTION",SUBSCRIPTIONS:"SUBSCRIPTIONS"},x="GLOBAL_LAYER",k=m(d.BRUSH,[Object]),E=m(d.LAYER,[Object]),D=m(d.SUBSCRIPTION,[Function]),Y=m(d.SUBSCRIPTIONS,[Object]),y=class extends A{#t=new Map;#h=new Map;#i=null;#r=new Map;#v=new Map;#m=!1;#d=null;#f=!1;#y=!1;#e={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#a={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#S={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#w=new u;#o=p();#u=null;#b=null;#g=null;#p=new Map;#R=!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.#o}}initialize(){this.#n(E(x,()=>({context:f["2D"]})))}actions(){return this.config&&Object.assign(this.#e,this.config),{addLayer:e=>this.#n(e),addLayers:(...e)=>{for(let t of e)this.#n(t)},use:(...e)=>this.use(e),updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setOffscreenCanvas:e=>this.setOffscreenCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.#T(e),start:()=>this.start(),stop:()=>this.stop(),render:()=>this.render(),setTargetFPS:e=>this.setTargetFPS(e),setTimeScale:e=>this.setTimeScale(e),setFixedTimeStep:e=>this.setFixedTimeStep(e),setDebug:e=>this.setDebug(e),getMetrics:()=>this.getMetrics(),handleResize:(e,t)=>this.handleResize(e,t),subscribe:(e,t)=>this.subscribe(e,t),handlePointerEvent:e=>this.handlePointerEvent(e),subscribeToPointer:e=>this.#o.$subscribe(e),bindPointer:e=>this.#o.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}use(e){for(let t of e){let s=b(t);switch(s){case d.BRUSH:this.#x(x,t);break;case d.LAYER:this.#n(t);break;case d.SUBSCRIPTION:this.#E(t);break;case d.SUBSCRIPTIONS:this.#c(t);break;default:throw new Error(`Invalid factory type: ${s}`)}}return this}setCanvas(e){let t=e,s=e.transferControlToOffscreen();s.width=t.width,s.height=t.height,this.#i=s,Object.values(f).forEach(i=>{try{let n=s.getContext(i);n&&this.#r.set(i,n)}catch{console.warn(`Context type ${i} not supported`)}}),this.#u||(this.#u=new g),this.#u.setCanvas(t),this.#g&&this.#g.disconnect(),this.#g=new ResizeObserver(i=>{let n=i[0];n&&n.target===t&&(s.width=t.width,s.height=t.height,this.handleResize(t.width,t.height))}),this.#g.observe(t),this.#b&&this.#b(),this.#b=this.#u.subscribe(i=>{this.handlePointerEvent(i)})}setOffscreenCanvas(e){this.#i=e,Object.values(f).forEach(t=>{try{let s=e.getContext(t);s&&this.#r.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#i);t&&(this.#i=t)}setAssets(e){this.#v=e}start(){this.#m||(this.#m=!0,this.#A())}stop(){this.#m&&(this.#m=!1,this.#d&&(cancelAnimationFrame(this.#d),this.#d=null))}#n(e){if(b(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#w),i={...s,name:t,context:this.#r.get(s.context||"2d")};if(s.data&&(i.dataReactor=this.#P(s.data,()=>this.#o)),s.when&&(i.whenReactor=this.#P(s.when,()=>i?.dataReactor?.computed()||void 0)),s.children&&s.children.length>0)for(let n of s.children)b(n)==="BRUSH"&&this.#x(t,n),b(n)==="LAYER"&&this.#n(n);if(this.#t.set(t,i),i.lifecycle?.onMount)try{i.lifecycle.onMount(i.context)}catch(n){console.error(`Error in layer "${t}" onMount:`,n)}return i}#x(e,t){let s=t._name,i=t(this.useContext,this.#w),n={name:s,...i};if(i.data&&(n.dataReactor=this.#P(i.data,()=>this.#o)),i.when&&(n.whenReactor=this.#P(i.when,()=>n?.dataReactor?.computed()||void 0)),n.lifecycle?.onMount)try{n.lifecycle.onMount(this.#r.get(n.context||this.#t.get(e)?.context))}catch(r){console.error(`Error in brush "${n.name}" onMount:`,r)}return this.#h.has(e)||this.#h.set(e,[]),this.#h.get(e).push(n),n}#E(e){let t=e._name,s=e(this.useContext);this.subscribe(t,s)}#c(e){let t=e._name,s=e(this.useContext);for(let[i,n]of Object.entries(s)){let r=t?`${t}:${i}`:i;this.subscribe(r,n)}}#T(e){let t=this.#t.get(e);if(!t)return;if(t.lifecycle?.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(i){console.error(`Error in layer "${e}" onUnmount:`,i)}let s=this.#h.get(e)||[];this.#h.delete(e);for(let i of s){if(i.lifecycle?.onUnmount)try{i.lifecycle.onUnmount(this.#r.get(i.context||t.context))}catch(n){console.error(`Error in brush "${i.name}" onUnmount:`,n)}i.whenReactor&&v(i.whenReactor),i.dataReactor&&(i.dataReactor?.unsubscribe(),i.dataReactor?.computed&&v(i.dataReactor.computed))}t.whenReactor&&(t.whenReactor?.unsubscribe(),t.whenReactor?.computed&&v(t.whenReactor.computed)),this.#t.delete(e)}#A(){this.#y||this.#f||(this.#y=!0,this.#d=requestAnimationFrame(()=>{this.#y=!1,this.#d=null,this.#O()}))}async#O(){if(this.#i){this.#f=!0;try{this.#w.clear();let e=this.#e.debug?.enabled?performance.now():0;this.#r.forEach(t=>{t.clearRect(0,0,this.#i.width,this.#i.height)});for(let t of this.#t.values()){let s=this.#e.debug?.enabled?performance.now():0;if(t.whenReactor&&!t.whenReactor.computed())continue;let i=t.context;if(!i)continue;if(t.lifecycle?.beforeRender)try{t.lifecycle.beforeRender(i,this.#a)}catch(r){console.error(`Error in layer "${t.name}" beforeRender:`,r),t.lifecycle?.onError&&t.lifecycle.onError(r)}i.save(),t.settings&&Object.entries(t.settings).forEach(([r,o])=>{typeof i[r]=="function"?i[r](...Array.isArray(o)?o:[o]):i[r]=o});let n=this.#h.get(t.name)||[];for(let r of n){let o=this.#e.debug?.enabled?performance.now():0;if(r.whenReactor&&!r.whenReactor.computed())continue;let a=r.context?this.#r.get(r.context):i;if(a){if(r.lifecycle?.beforeRender)try{r.lifecycle.beforeRender(a,this.#a)}catch(h){console.error(`Error in brush "${r.name}" beforeRender:`,h),r.lifecycle?.onError&&r.lifecycle.onError(h);continue}a.save(),r.settings&&Object.entries(r.settings).forEach(([h,c])=>{typeof a[h]=="function"?a[h](...Array.isArray(c)?c:[c]):a[h]=c});try{let h={};if(r.assets)for(let c of r.assets)h[c]=this.#v.get(c);if(r.render(a,r.dataReactor?r.dataReactor.computed():void 0,h,this.#a),r.lifecycle?.afterRender&&r.lifecycle.afterRender(a,this.#a),this.#e.debug?.enabled){let c=performance.now()-o;this.#S.brushTimes.set(r.name,c),this.#e.debug?.showBounds&&this.#k(a,r)}}catch(h){console.error(`Error in brush "${r.name}":`,h),r.lifecycle?.onError&&r.lifecycle.onError(h)}finally{a.restore()}}}if(i.restore(),t.lifecycle?.afterRender)try{t.lifecycle.afterRender(i,this.#a)}catch(r){console.error(`Error in layer "${t.name}" afterRender:`,r),t.lifecycle?.onError&&t.lifecycle.onError(r)}if(this.#e.debug?.enabled){let r=performance.now()-s;this.#S.layerTimes.set(t.name,r),this.#e.debug?.showBounds&&this.#D(i,t)}}this.#e.debug?.enabled&&this.#Y()}finally{this.#f=!1}}}#k(e,t){e.save(),e.strokeStyle="rgba(0, 255, 0, 0.5)",e.lineWidth=1,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#D(e,t){e.save(),e.strokeStyle="rgba(255, 0, 0, 0.5)",e.lineWidth=2,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#Y(){let e=this.#r.get(f["2D"]);if(!e)return;e.save(),e.resetTransform(),e.font="12px monospace",e.fillStyle="white",e.strokeStyle="black",e.lineWidth=3;let t=20,s=15;if(this.#e.debug?.showFPS){let i=`FPS: ${Math.round(this.#S.fps)} (${this.#a.deltaTime.toFixed(2)}ms)`;e.strokeText(i,10,t),e.fillText(i,10,t),t+=s}if(this.#e.debug?.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[i,n]of this.#S.layerTimes){let r=` ${i}: ${n.toFixed(2)}ms`;e.strokeText(r,10,t),e.fillText(r,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){for(let s of this.#t.values())if(s.lifecycle?.onResize)try{s.lifecycle.onResize(e,t,s.context)}catch(i){console.error(`Error in layer "${s.name}" onResize:`,i),s.lifecycle?.onError&&s.lifecycle.onError(i)}}#P(e,t=()=>{}){if(!e)return null;let s=L(e,{immediate:!0,context:t}),i=O(s,()=>this.#A());return{computed:s,unsubscribe:i}}destroy(){this.stop(),this.#b&&(this.#b(),this.#b=null),this.#u&&(this.#u.destroy(),this.#u=null),this.#g&&(this.#g.disconnect(),this.#g=null),this.#o&&this.#o.$destroy();for(let e of this.#t.keys())this.#T(e)}setTargetFPS(e){this.#e.targetFPS=e,this.#e.fixedTimeStep=1e3/e}setTimeScale(e){this.#e.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#e.fixedTimeStep=e}setDebug(e={}){this.#e.debug||(this.#e.debug={}),Object.assign(this.#e.debug,e)}getMetrics(){return{...this.#S,deltaTime:this.#a.deltaTime,elapsedTime:this.#a.elapsedTime,frameCount:this.#a.frameCount}}handlePointerEvent(e){this.#o.handleEvent(e),this.#L(e),this.#B(e)}#B(e){let{type:t}=e,s=this.#o,i=s.event;switch(t){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}let n=this.#R,r=i?.isOverCanvas||!1;r&&!n?this.#s("pointer:enter",s):!r&&n&&this.#s("pointer:leave",s),this.#R=r}#L(e){let{type:t,x:s,y:i}=e,n=this.#o;switch(t){case"down":{let o=this.#C(s,i);if(n.setActiveArea(o),o?.onPointerDown?.handler){let a=this.#l(o);o.onPointerDown.handler({event:e,ctx:a,emit:this.#s.bind(this)})}break}case"up":{let o=n.activeArea;if(o?.onPointerUp?.handler){let a=this.#l(o);o.onPointerUp.handler({event:e,ctx:a,emit:this.#s.bind(this)})}break}case"move":{let o=this.#C(s,i),a=n.hoveredArea;if(o?.onPointerMove?.handler&&!e.isDragging){let h=this.#l(o);o.onPointerMove.handler({event:e,ctx:h,emit:this.#s.bind(this)})}if(o?.id!==a?.id){if(a?.onPointerLeave?.handler){let h=this.#l(a);a.onPointerLeave.handler({event:e,ctx:h,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let h=this.#l(o);o.onPointerEnter.handler({event:e,ctx:h,emit:this.#s.bind(this)})}n.setHoveredArea(o)}break}case"dragstart":{let o=n.activeArea;if(o?.onDragStart?.handler){let a=this.#l(o);o.onDragStart.handler({event:e,ctx:a,emit:this.#s.bind(this)})}break}case"drag":{let o=this.#C(s,i),a=n.hoveredArea;if(o?.id!==a?.id){if(a?.onPointerLeave?.handler){let c=this.#l(a);a.onPointerLeave.handler({event:e,ctx:c,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let c=this.#l(o);o.onPointerEnter.handler({event:e,ctx:c,emit:this.#s.bind(this)})}n.setHoveredArea(o)}let h=n.activeArea;if(h?.onDragMove?.handler){let c=this.#l(h);h.onDragMove.handler({event:e,ctx:c,emit:this.#s.bind(this)})}break}case"dragend":{let o=n.activeArea;if(o?.onDragEnd?.handler){let a=this.#l(o);o.onDragEnd.handler({event:e,ctx:a,emit:this.#s.bind(this)})}break}case"dblclick":let r=this.#C(s,i);if(n.setActiveArea(r),r?.onPointerDblClick?.handler){let o=this.#l(r);r.onPointerDblClick.handler({event:e,ctx:o,emit:this.#s.bind(this)})}break}}#l(e){return e?e.context?this.#r.get(e.context):this.#r.get(f["2D"]):null}subscribe(e,t){return this.#p.has(e)||this.#p.set(e,new Set),this.#p.get(e).add(t),()=>{let s=this.#p.get(e);s&&(s.delete(t),s.size===0&&this.#p.delete(e))}}#C(e,t){let s=this.#w.areas.sort((i,n)=>(n.priority||0)-(i.priority||0));for(let i of s)if(this.#M(e,t,i.bounds))return i;return null}#M(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#s(e,t){let s=this.#p.get(e);if(s)for(let i of s)i(t)}_testEmitPointerEvent(e){this.#o.handleEvent(e),this.#L(e)}};export{g as CanvasEvents,u as HitRegistry,y as Painter,k as defineBrush,E as defineLayer,D as defineSubscription,Y as defineSubscriptions,p as usePointerSurface};
1
+ var f={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var u=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 E}from"@jucie.io/engine";var g=class extends E{#e=null;#a=null;#i=null;#r=null;#y=new Set;#m=new Set;#d=null;#f=null;#S=!1;#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};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()}}setCanvas(t){this.#e&&this.#C(),this.#e=t,this.#o(),this.#w()}subscribe(t){return this.#y.add(t),()=>this.#y.delete(t)}onResize(t){return this.#m.add(t),()=>this.#m.delete(t)}transferControlToOffscreen(){if(!this.#e)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#S)throw new Error("Control has already been transferred to offscreen");return this.#a=this.#e.transferControlToOffscreen(),this.#S=!0,this.#a.width=this.#i.width,this.#a.height=this.#i.height,this.#v({width:this.#e.width,height:this.#e.height}),this.#a}#o(){this.#e&&(this.#i=this.#e.getBoundingClientRect())}#w(){this.#e&&(this.#o(),this.#r=new ResizeObserver(t=>{for(let e of t){if(e.target!==this.#e)continue;let{width:s,height:i}=e.contentRect;this.#v({width:s,height:i})}this.#o()}),this.#r.observe(this.#e),this.#e.addEventListener("wheel",this.#n,{passive:!1}),this.#e.addEventListener("pointerdown",this.#b),document.addEventListener("pointermove",this.#u),document.addEventListener("pointerup",this.#g),document.addEventListener("pointercancel",this.#p))}#C(){this.#r&&(this.#r.disconnect(),this.#r=null),this.#e&&(this.#e.removeEventListener("wheel",this.#n),this.#e.removeEventListener("pointerdown",this.#b)),document.removeEventListener("pointermove",this.#u),document.removeEventListener("pointerup",this.#g),document.removeEventListener("pointercancel",this.#p)}#n=t=>{if(t.preventDefault(),t.stopPropagation(),t.ctrlKey){let e=this.#c(t,"zoom");this.#h(e)}else{let e=this.#c(t,"scroll");this.#h(e)}};#u=t=>{this.#d=t,!this.#f&&(this.#f=requestAnimationFrame(()=>{if(this.#d){let e=this.#d;this.#d=null;let s="move",i=this.#R(e);if(this.#t.isPressed&&!this.#t.isDragging){let r=i.x-this.#t.dragStartX,o=i.y-this.#t.dragStartY;Math.sqrt(r*r+o*o)>this.#t.dragThreshold&&(this.#t.isDragging=!0,s="dragstart")}else this.#t.isDragging&&(s="drag");let n=this.#c(e,s);this.#h(n)}this.#f=null}))};#b=t=>{let e=this.#R(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.#c(t,"down");this.#h(s)};#g=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let s=this.#c(t,"dragend");this.#h(s)}if(!this.#t.isDragging){let s=this.#R(t),i=Date.now();if(this.#t.lastClickTime!==null){let n=i-this.#t.lastClickTime,r=s.x-this.#t.lastClickX,o=s.y-this.#t.lastClickY,a=Math.sqrt(r*r+o*o);if(n<this.#t.doubleClickThreshold&&a<this.#t.doubleClickDistanceThreshold){let h=this.#c(t,"dblclick");this.#h(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.#c(t,"up");this.#h(e),this.#t.isPressed=!1,this.#t.isDragging=!1,this.#t.dragStartX=null,this.#t.dragStartY=null};#p=t=>{if(this.#e&&this.#t.isPressed)try{this.#e.releasePointerCapture(t.pointerId)}catch{}if(this.#t.isDragging){let s=this.#c(t,"dragend");this.#h(s)}let e=this.#c(t,"cancel");this.#h(e),this.#t.isPressed=!1,this.#t.isDragging=!1,this.#t.dragStartX=null,this.#t.dragStartY=null};#h(t){for(let e of this.#y)e(t)}#v(t){for(let e of this.#m)e(t)}#R(t){let e=t.target===this.#e,s,i;return e?(s=t.offsetX,i=t.offsetY):this.#i?(s=t.clientX-this.#i.left,i=t.clientY-this.#i.top):(s=t.clientX,i=t.clientY),{x:s,y:i,isOverCanvas:e}}#c(t,e){let{x:s,y:i,isOverCanvas:n}=this.#R(t),r=n||this.#i&&s>=0&&s<=this.#i.width&&i>=0&&i<=this.#i.height,o=0,a=0,h=0,c=0;e==="scroll"?(o=t.deltaX,a=t.deltaY,h=t.deltaZ,c=t.deltaMode):e==="zoom"?(o=0,a=t.deltaY,h=0):(e==="move"||e==="drag"||e==="dragstart")&&this.#t.prevX!==null&&this.#t.prevY!==null&&(o=s-this.#t.prevX,a=i-this.#t.prevY);let S=0;if(this.#t.isDragging&&this.#t.dragStartX!==null&&this.#t.dragStartY!==null){let w=s-this.#t.dragStartX,C=i-this.#t.dragStartY;S=Math.sqrt(w*w+C*C)}let T={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:o,deltaY:a,deltaZ:h,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:S,shiftKey:t.shiftKey||!1,ctrlKey:t.ctrlKey||!1,altKey:t.altKey||!1,metaKey:t.metaKey||!1};return this.#t.prevX=s,this.#t.prevY=i,T}destroy(){this.#f&&(cancelAnimationFrame(this.#f),this.#f=null),this.#C(),this.#e=null,this.#a=null,this.#i=null,this.#y.clear(),this.#m.clear(),this.#S=!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}};import{defineSurface as P}from"@jucie.io/reactive";var p=P(l=>{let t=l.signal(null),e=l.signal(null),s=l.signal(null),i=l.action((a,h)=>{t(h)}),n=l.action((a,h)=>{e(h)}),r=l.action((a,h)=>{s(h)}),o=l.action(()=>{t(null),e(null),s(null)});return{event:t,hoveredArea:e,activeArea:s,handleEvent:i,setHoveredArea:n,setActiveArea:r,reset:o}});import{ServiceProvider as k}from"@jucie.io/engine";import{createComputed as A,destroyComputed as v,addEffect as D}from"@jucie.io/reactive";import{createDefinition as m,definitionType as b}from"@jucie.io/engine";var d={BRUSH:"BRUSH",LAYER:"LAYER",SUBSCRIPTION:"SUBSCRIPTION",SUBSCRIPTIONS:"SUBSCRIPTIONS"},R="GLOBAL_LAYER",L=m(d.BRUSH,[Object]),x=m(d.LAYER,[Object]),O=m(d.SUBSCRIPTION,[Function]),Y=m(d.SUBSCRIPTIONS,[Object]),y=class extends k{#e=new Map;#a=new Map;#i=null;#r=new Map;#y=new Map;#m=!1;#d=null;#f=!1;#S=!1;#t={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#o={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#w={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#C=new u;#n=p();#u=null;#b=null;#g=null;#p=new Map;#h=!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.#n}}initialize(){this.#v(x(R,()=>({context:f["2D"]})))}actions(){return this.config&&Object.assign(this.#t,this.config),{addLayer:t=>this.#v(t),addLayers:(...t)=>{for(let e of t)this.#v(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.#E(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.#n.$subscribe(t),bindPointer:t=>this.#n.$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(R,e);break;case d.LAYER:this.#v(e);break;case d.SUBSCRIPTION:this.#c(e);break;case d.SUBSCRIPTIONS:this.#A(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.#i=s,Object.values(f).forEach(i=>{try{let n=s.getContext(i);n&&this.#r.set(i,n)}catch{console.warn(`Context type ${i} not supported`)}}),this.#u||(this.#u=new g),this.#u.setCanvas(e),this.#g&&this.#g.disconnect(),this.#g=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.#g.observe(e),this.#b&&this.#b(),this.#b=this.#u.subscribe(i=>{this.handlePointerEvent(i)})}setOffscreenCanvas(t){this.#i=t,Object.values(f).forEach(e=>{try{let s=t.getContext(e);s&&this.#r.set(e,s)}catch{console.warn(`Context type ${e} not supported`)}})}updateCanvas(t){let e=t(this.#i);e&&(this.#i=e)}setAssets(t){this.#y=t}start(){this.#m||(this.#m=!0,this.#P())}stop(){this.#m&&(this.#m=!1,this.#d&&(cancelAnimationFrame(this.#d),this.#d=null))}#v(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.#r.get(s.context||"2d")};if(s.data&&(i.dataReactor=this.#x(s.data,()=>this.#n)),s.when&&(i.whenReactor=this.#x(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.#v(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.#x(i.data,()=>this.#n)),i.when&&(n.whenReactor=this.#x(i.when,()=>n?.dataReactor?.computed()||void 0)),n.lifecycle?.onMount)try{n.lifecycle.onMount(this.#r.get(n.context||this.#e.get(t)?.context))}catch(r){console.error(`Error in brush "${n.name}" onMount:`,r)}return this.#a.has(t)||this.#a.set(t,[]),this.#a.get(t).push(n),n}#c(t){let e=t._name,s=t(this.useContext);this.subscribe(e,s)}#A(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)}}#E(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.#a.get(t)||[];this.#a.delete(t);for(let i of s){if(i.lifecycle?.onUnmount)try{i.lifecycle.onUnmount(this.#r.get(i.context||e.context))}catch(n){console.error(`Error in brush "${i.name}" onUnmount:`,n)}i.whenReactor&&v(i.whenReactor),i.dataReactor&&(i.dataReactor?.unsubscribe(),i.dataReactor?.computed&&v(i.dataReactor.computed))}e.whenReactor&&(e.whenReactor?.unsubscribe(),e.whenReactor?.computed&&v(e.whenReactor.computed)),this.#e.delete(t)}#P(){this.#S||this.#f||(this.#S=!0,this.#d=requestAnimationFrame(()=>{this.#S=!1,this.#d=null,this.#D()}))}async#D(){if(this.#i){this.#f=!0;try{this.#C.clear();let t=this.#t.debug?.enabled?performance.now():0;this.#r.forEach(e=>{e.clearRect(0,0,this.#i.width,this.#i.height)});for(let e of this.#e.values()){let s=this.#t.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.#o)}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,o])=>{typeof i[r]=="function"?i[r](...Array.isArray(o)?o:[o]):i[r]=o});let n=this.#a.get(e.name)||[];for(let r of n){let o=this.#t.debug?.enabled?performance.now():0;if(r.whenReactor&&!r.whenReactor.computed())continue;let a=r.context?this.#r.get(r.context):i;if(a){if(r.lifecycle?.beforeRender)try{r.lifecycle.beforeRender(a,this.#o)}catch(h){console.error(`Error in brush "${r.name}" beforeRender:`,h),r.lifecycle?.onError&&r.lifecycle.onError(h);continue}a.save(),r.settings&&Object.entries(r.settings).forEach(([h,c])=>{typeof a[h]=="function"?a[h](...Array.isArray(c)?c:[c]):a[h]=c});try{let h={};if(r.assets)for(let c of r.assets)h[c]=this.#y.get(c);if(r.render(a,r.dataReactor?r.dataReactor.computed():void 0,h,this.#o),r.lifecycle?.afterRender&&r.lifecycle.afterRender(a,this.#o),this.#t.debug?.enabled){let c=performance.now()-o;this.#w.brushTimes.set(r.name,c),this.#t.debug?.showBounds&&this.#L(a,r)}}catch(h){console.error(`Error in brush "${r.name}":`,h),r.lifecycle?.onError&&r.lifecycle.onError(h)}finally{a.restore()}}}if(i.restore(),e.lifecycle?.afterRender)try{e.lifecycle.afterRender(i,this.#o)}catch(r){console.error(`Error in layer "${e.name}" afterRender:`,r),e.lifecycle?.onError&&e.lifecycle.onError(r)}if(this.#t.debug?.enabled){let r=performance.now()-s;this.#w.layerTimes.set(e.name,r),this.#t.debug?.showBounds&&this.#O(i,e)}}this.#t.debug?.enabled&&this.#Y()}finally{this.#f=!1}}}#L(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()}#Y(){let t=this.#r.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.#t.debug?.showFPS){let i=`FPS: ${Math.round(this.#w.fps)} (${this.#o.deltaTime.toFixed(2)}ms)`;t.strokeText(i,10,e),t.fillText(i,10,e),e+=s}if(this.#t.debug?.showLayerTiming){t.fillText("Layer Times:",10,e),e+=s;for(let[i,n]of this.#w.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)}}#x(t,e=()=>{}){if(!t)return null;let s=A(t,{immediate:!0,context:e}),i=D(s,()=>this.#P());return{computed:s,unsubscribe:i}}destroy(){this.stop(),this.#b&&(this.#b(),this.#b=null),this.#u&&(this.#u.destroy(),this.#u=null),this.#g&&(this.#g.disconnect(),this.#g=null),this.#n&&this.#n.$destroy();for(let t of this.#e.keys())this.#E(t)}setTargetFPS(t){this.#t.targetFPS=t,this.#t.fixedTimeStep=1e3/t}setTimeScale(t){this.#t.timeScale=Math.max(0,t)}setFixedTimeStep(t){this.#t.fixedTimeStep=t}setDebug(t={}){this.#t.debug||(this.#t.debug={}),Object.assign(this.#t.debug,t)}getMetrics(){return{...this.#w,deltaTime:this.#o.deltaTime,elapsedTime:this.#o.elapsedTime,frameCount:this.#o.frameCount}}handlePointerEvent(t){this.#n.handleEvent(t),this.#k(t),this.#M(t)}#M(t){let{type:e}=t,s=this.#n,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}let n=this.#h,r=i?.isOverCanvas||!1;r&&!n?this.#s("pointer:enter",s):!r&&n&&this.#s("pointer:leave",s),this.#h=r}#k(t){let{type:e,x:s,y:i}=t,n=this.#n;switch(e){case"down":{let o=this.#T(s,i);if(n.setActiveArea(o),o?.onPointerDown?.handler){let a=this.#l(o);o.onPointerDown.handler({event:t,ctx:a,emit:this.#s.bind(this)})}break}case"up":{let o=n.activeArea;if(o?.onPointerUp?.handler){let a=this.#l(o);o.onPointerUp.handler({event:t,ctx:a,emit:this.#s.bind(this)})}break}case"move":{let o=this.#T(s,i),a=n.hoveredArea;if(o?.onPointerMove?.handler&&!t.isDragging){let h=this.#l(o);o.onPointerMove.handler({event:t,ctx:h,emit:this.#s.bind(this)})}if(o?.id!==a?.id){if(a?.onPointerLeave?.handler){let h=this.#l(a);a.onPointerLeave.handler({event:t,ctx:h,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let h=this.#l(o);o.onPointerEnter.handler({event:t,ctx:h,emit:this.#s.bind(this)})}n.setHoveredArea(o)}break}case"dragstart":{let o=n.activeArea;if(o?.onDragStart?.handler){let a=this.#l(o);o.onDragStart.handler({event:t,ctx:a,emit:this.#s.bind(this)})}break}case"drag":{let o=this.#T(s,i),a=n.hoveredArea;if(o?.id!==a?.id){if(a?.onPointerLeave?.handler){let c=this.#l(a);a.onPointerLeave.handler({event:t,ctx:c,emit:this.#s.bind(this)})}if(o?.onPointerEnter?.handler){let c=this.#l(o);o.onPointerEnter.handler({event:t,ctx:c,emit:this.#s.bind(this)})}n.setHoveredArea(o)}let h=n.activeArea;if(h?.onDragMove?.handler){let c=this.#l(h);h.onDragMove.handler({event:t,ctx:c,emit:this.#s.bind(this)})}break}case"dragend":{let o=n.activeArea;if(o?.onDragEnd?.handler){let a=this.#l(o);o.onDragEnd.handler({event:t,ctx:a,emit:this.#s.bind(this)})}break}case"dblclick":let r=this.#T(s,i);if(n.setActiveArea(r),r?.onPointerDblClick?.handler){let o=this.#l(r);r.onPointerDblClick.handler({event:t,ctx:o,emit:this.#s.bind(this)})}break}}#l(t){return t?t.context?this.#r.get(t.context):this.#r.get(f["2D"]):null}subscribe(t,e){return this.#p.has(t)||this.#p.set(t,new Set),this.#p.get(t).add(e),()=>{let s=this.#p.get(t);s&&(s.delete(e),s.size===0&&this.#p.delete(t))}}#T(t,e){let s=this.#C.areas.sort((i,n)=>(n.priority||0)-(i.priority||0));for(let i of s)if(this.#B(t,e,i.bounds))return i;return null}#B(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.#p.get(t);if(s)for(let i of s)i(e)}_testEmitPointerEvent(t){this.#n.handleEvent(t),this.#k(t)}};export{g as CanvasEvents,u as HitRegistry,y as Painter,L as defineBrush,x as defineLayer,O as defineSubscription,Y as defineSubscriptions,p 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\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 };\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 };\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 #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 this.#canvas.addEventListener('dblclick', this.#handleDblClick);\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('dblclick', this.#handleDblClick);\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 // 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 #handleDblClick = (event) => {\n const normalized = this.#normalizeEvent(event, 'dblclick');\n this.#emit(normalized);\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 \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 }\n}\n", "import { defineSurface } from '@jucie.io/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // Current normalized event from CanvasEvents\n const event = setup.signal(null);\n \n // Hit registry integration (still managed here)\n const hoveredArea = setup.signal(null);\n const activeArea = setup.signal(null);\n \n // Main handler - just stores the event\n const handleEvent = setup.action((_, normalizedEvent) => {\n event(normalizedEvent);\n });\n \n const setHoveredArea = setup.action((_, area) => {\n hoveredArea(area);\n });\n \n const setActiveArea = setup.action((_, area) => {\n activeArea(area);\n });\n \n const reset = setup.action(() => {\n event(null);\n hoveredArea(null);\n activeArea(null);\n });\n \n return {\n // Signals\n event,\n hoveredArea,\n activeArea,\n\n // Actions\n handleEvent,\n setHoveredArea,\n setActiveArea,\n reset\n };\n});\n", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nconst DEFINITIONS_TYPES = {\n BRUSH: 'BRUSH',\n LAYER: 'LAYER',\n SUBSCRIPTION: 'SUBSCRIPTION',\n SUBSCRIPTIONS: 'SUBSCRIPTIONS'\n};\n\nconst GLOBAL_LAYER_NAME = 'GLOBAL_LAYER';\n\nexport const defineBrush = createDefinition(DEFINITIONS_TYPES.BRUSH, [Object]);\nexport const defineLayer = createDefinition(DEFINITIONS_TYPES.LAYER, [Object]);\nexport const defineSubscription = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTION, [Function]);\nexport const defineSubscriptions = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTIONS, [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #brushes = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #assets = new Map();\n #isRunning = false;\n #frameId = null;\n #isRendering = false;\n #renderScheduled = false;\n\n // Mutable runtime config (separate from frozen config)\n #runtimeConfig = {\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n };\n\n // Timing state\n #timing = {\n lastFrameTime: 0,\n deltaTime: 0,\n elapsedTime: 0,\n frameCount: 0\n };\n\n // Debug metrics\n #metrics = {\n fps: 0,\n frameTime: 0,\n layerTimes: new Map(),\n brushTimes: new Map(),\n skippedFrames: 0\n };\n\n // Hit detection state\n #hitRegistry = new HitRegistry();\n #pointerSurface = usePointerSurface();\n #canvasEvents = null; // Only created in main thread mode\n #pointerUnsubscribe = null;\n #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasOverCanvas = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface,\n };\n }\n \n initialize () {\n this.#addLayer(defineLayer(GLOBAL_LAYER_NAME, () => ({\n context: ContextTypes['2D']\n })));\n }\n\n actions() {\n // Initialize runtime config from frozen config\n if (this.config) {\n Object.assign(this.#runtimeConfig, this.config);\n }\n \n return {\n addLayer: (layerDef) => this.#addLayer(layerDef),\n addLayers: (...layers) => {\n for (const layer of layers) {\n this.#addLayer(layer);\n }\n },\n use: (...factories) => this.use(factories),\n updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\n setOffscreenCanvas: (offscreenCanvas) => this.setOffscreenCanvas(offscreenCanvas),\n setAssets: (assets) => this.setAssets(assets),\n removeLayer: (name) => this.#removeLayer(name),\n start: () => this.start(),\n stop: () => this.stop(),\n render: () => this.render(),\n setTargetFPS: (fps) => this.setTargetFPS(fps),\n setTimeScale: (scale) => this.setTimeScale(scale),\n setFixedTimeStep: (step) => this.setFixedTimeStep(step),\n setDebug: (options) => this.setDebug(options),\n getMetrics: () => this.getMetrics(),\n handleResize: (width, height) => this.handleResize(width, height),\n subscribe: (event, callback) => this.subscribe(event, callback),\n // Pointer API - receives normalized events from main thread\n handlePointerEvent: (normalizedEvent) => this.handlePointerEvent(normalizedEvent),\n subscribeToPointer: (callback) => this.#pointerSurface.$subscribe(callback),\n bindPointer: (path) => this.#pointerSurface.$bind(path),\n // Test helper - only for testing\n _testEmitPointerEvent: (normalizedEvent) => this._testEmitPointerEvent(normalizedEvent)\n };\n }\n\n use(factories) {\n for (const factory of factories) {\n const type = definitionType(factory);\n switch (type) {\n case DEFINITIONS_TYPES.BRUSH:\n this.#addBrush(GLOBAL_LAYER_NAME, factory);\n break;\n case DEFINITIONS_TYPES.LAYER:\n this.#addLayer(factory);\n break;\n case DEFINITIONS_TYPES.SUBSCRIPTION:\n this.#addSubscription(factory);\n break;\n\n case DEFINITIONS_TYPES.SUBSCRIPTIONS:\n this.#addSubscriptions(factory);\n break;\n\n default:\n throw new Error(`Invalid factory type: ${type}`);\n }\n }\n return this;\n }\n\n // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n #addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n\n const layer = {...config, name, context: this.#contexts.get(config.context || '2d') };\n \n // Set up layer computed if it has data paths\n if (config.data) {\n layer.dataReactor = this.#createReactor(config.data, () => this.#pointerSurface);\n }\n\n // Set up when reactor if layer has condition\n if (config.when) {\n layer.whenReactor = this.#createReactor(config.when, () => (layer?.dataReactor?.computed() || undefined));\n }\n\n // Set up brush reactors and structure\n if (config.children && config.children.length > 0) {\n for (const child of config.children) {\n if (definitionType(child) === 'BRUSH') {\n this.#addBrush(name, child);\n }\n if (definitionType(child) === 'LAYER') {\n this.#addLayer(child);\n }\n }\n }\n\n this.#layers.set(name, layer);\n\n // Call layer mount hook\n if (layer.lifecycle?.onMount) {\n try {\n layer.lifecycle.onMount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onMount:`, error);\n }\n }\n\n return layer;\n }\n\n #addBrush(layerName, brushFactory) {\n const name = brushFactory._name;\n const brushConfig = brushFactory(this.useContext, this.#hitRegistry);\n const brush = {\n name,\n ...brushConfig\n };\n\n if (brushConfig.data) {\n brush.dataReactor = this.#createReactor(brushConfig.data, () => this.#pointerSurface);\n }\n\n if (brushConfig.when) {\n brush.whenReactor = this.#createReactor(brushConfig.when, () => (brush?.dataReactor?.computed() || undefined));\n }\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || this.#layers.get(layerName)?.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n if (!this.#brushes.has(layerName)) {\n this.#brushes.set(layerName, []);\n }\n\n this.#brushes.get(layerName).push(brush);\n\n return brush;\n }\n\n #addSubscription(subscriptionFactory) {\n const name = subscriptionFactory._name;\n const subscriptionConfig = subscriptionFactory(this.useContext);\n this.subscribe(name, subscriptionConfig);\n }\n\n #addSubscriptions(subscriptionsFactory) {\n const prefix = subscriptionsFactory._name;\n const subscriptions = subscriptionsFactory(this.useContext);\n for (const [event, handler] of Object.entries(subscriptions)) {\n const finalEvent = prefix ? `${prefix}:${event}` : event;\n this.subscribe(finalEvent, handler);\n }\n }\n\n #removeLayer(name) {\n const layer = this.#layers.get(name);\n if (!layer) return;\n\n // Call layer unmount hook\n if (layer.lifecycle?.onUnmount) {\n try {\n layer.lifecycle.onUnmount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onUnmount:`, error);\n }\n }\n\n const brushes = this.#brushes.get(name) || [];\n this.#brushes.delete(name);\n\n // Call brush unmount hooks and clean up reactors\n\n for (const brush of brushes) {\n if (brush.lifecycle?.onUnmount) {\n try {\n brush.lifecycle.onUnmount(\n this.#contexts.get(brush.context || layer.context)\n );\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onUnmount:`, error);\n }\n }\n // Clean up brush when reactor\n if (brush.whenReactor) {\n destroyComputed(brush.whenReactor);\n }\n // Clean up brush computed and subscription\n if (brush.dataReactor) {\n brush.dataReactor?.unsubscribe();\n if (brush.dataReactor?.computed) {\n destroyComputed(brush.dataReactor.computed);\n }\n }\n }\n\n // Clean up layer when reactor\n if (layer.whenReactor) {\n layer.whenReactor?.unsubscribe();\n if (layer.whenReactor?.computed) {\n destroyComputed(layer.whenReactor.computed);\n }\n }\n\n this.#layers.delete(name);\n }\n\n #scheduleRender() {\n if (this.#renderScheduled || this.#isRendering) return;\n \n this.#renderScheduled = true;\n \n this.#frameId = requestAnimationFrame(() => {\n this.#renderScheduled = false;\n this.#frameId = null;\n this.#render();\n });\n }\n\n async #render() {\n if (!this.#canvas) return;\n this.#isRendering = true;\n \n try {\n // Clear hit registry at start of render\n this.#hitRegistry.clear();\n \n const renderStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Clear all contexts\n this.#contexts.forEach(ctx => {\n ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n });\n\n // Render layers in order\n for (const layer of this.#layers.values()) {\n const layerStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Check layer condition\n if (layer.whenReactor && !layer.whenReactor.computed()) continue;\n\n const ctx = layer.context;\n\n if (!ctx) continue;\n\n // Layer beforeRender hook\n if (layer.lifecycle?.beforeRender) {\n try {\n layer.lifecycle.beforeRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" beforeRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n // Apply layer settings\n ctx.save();\n if (layer.settings) {\n Object.entries(layer.settings).forEach(([key, value]) => {\n if (typeof ctx[key] === 'function') {\n ctx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n ctx[key] = value;\n }\n });\n }\n\n const brushes = this.#brushes.get(layer.name) || [];\n\n // Render brushes\n for (const brush of brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor.computed()) continue;\n\n\n const brushCtx = brush.context ? \n this.#contexts.get(brush.context) : \n ctx;\n\n if (!brushCtx) continue;\n\n // Brush beforeRender hook\n if (brush.lifecycle?.beforeRender) {\n try {\n brush.lifecycle.beforeRender(brushCtx, this.#timing);\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" beforeRender:`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n continue;\n }\n }\n\n brushCtx.save();\n \n if (brush.settings) {\n Object.entries(brush.settings).forEach(([key, value]) => {\n if (typeof brushCtx[key] === 'function') {\n brushCtx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n brushCtx[key] = value;\n }\n });\n }\n \n try {\n const requiredAssets = {};\n if (brush.assets) {\n for (const key of brush.assets) {\n requiredAssets[key] = this.#assets.get(key);\n }\n }\n brush.render(brushCtx, (brush.dataReactor ? brush.dataReactor.computed() : undefined), requiredAssets, this.#timing);\n\n // Brush afterRender hook\n if (brush.lifecycle?.afterRender) {\n brush.lifecycle.afterRender(brushCtx, this.#timing);\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const brushTime = performance.now() - brushStart;\n this.#metrics.brushTimes.set(brush.name, brushTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderBrushBounds(brushCtx, brush);\n }\n }\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\":`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n } finally {\n brushCtx.restore();\n }\n }\n\n ctx.restore();\n\n // Layer afterRender hook\n if (layer.lifecycle?.afterRender) {\n try {\n layer.lifecycle.afterRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" afterRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const layerTime = performance.now() - layerStart;\n this.#metrics.layerTimes.set(layer.name, layerTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderLayerBounds(ctx, layer);\n }\n }\n }\n\n // Render debug overlay if enabled\n if (this.#runtimeConfig.debug?.enabled) {\n this.#renderDebugOverlay();\n }\n \n } finally {\n this.#isRendering = false;\n }\n }\n\n #renderBrushBounds(ctx, brush) {\n ctx.save();\n ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';\n ctx.lineWidth = 1;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderLayerBounds(ctx, layer) {\n ctx.save();\n ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';\n ctx.lineWidth = 2;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderDebugOverlay() {\n const ctx = this.#contexts.get(ContextTypes['2D']);\n if (!ctx) return;\n\n ctx.save();\n ctx.resetTransform();\n ctx.font = '12px monospace';\n ctx.fillStyle = 'white';\n ctx.strokeStyle = 'black';\n ctx.lineWidth = 3;\n\n let y = 20;\n const lineHeight = 15;\n\n if (this.#runtimeConfig.debug?.showFPS) {\n const text = `FPS: ${Math.round(this.#metrics.fps)} (${this.#timing.deltaTime.toFixed(2)}ms)`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n if (this.#runtimeConfig.debug?.showLayerTiming) {\n ctx.fillText('Layer Times:', 10, y);\n y += lineHeight;\n\n for (const [name, time] of this.#metrics.layerTimes) {\n const text = ` ${name}: ${time.toFixed(2)}ms`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n ctx.fillText(this.state.get(['_transitions', 'pointer', 'currentState']), 10, y);\n }\n\n ctx.restore();\n }\n\n handleResize(width, height) {\n // Call onResize hooks for all layers\n for (const layer of this.#layers.values()) {\n if (layer.lifecycle?.onResize) {\n try {\n layer.lifecycle.onResize(width, height, layer.context);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" onResize:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n }\n }\n\n #createReactor(fn, context = () => undefined) {\n if (!fn) return null;\n \n const computed = createComputed(fn, {\n immediate: true,\n context\n });\n \n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n \n return {computed, unsubscribe};\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.#removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n const event = pointer.event;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer);\n \n // Emit click if it wasn't a drag\n if (event && !event.isDragging) {\n this.#emit('pointer:click', pointer);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer);\n break;\n \n case 'dragstart':\n this.#emit('pointer:drag:start', pointer);\n break;\n \n case 'drag':\n this.#emit('pointer:drag:move', pointer);\n break;\n \n case 'dragend':\n this.#emit('pointer:drag:end', pointer);\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer);\n break;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = event?.isOverCanvas || false;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n }\n\n #handlePointerInteraction(normalizedEvent) {\n const { type, x, y } = normalizedEvent;\n const pointer = this.#pointerSurface;\n\n switch (type) {\n case 'down': {\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDown?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDown.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'up': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerUp?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerUp.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'move': {\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle pointer move on hovered area (only when NOT dragging)\n if (hitArea?.onPointerMove?.handler && !normalizedEvent.isDragging) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n // Handle hover changes\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'dragstart': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragStart?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragStart.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'drag': {\n // Perform hit test to detect drop targets while dragging\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle hover changes (for drop target detection)\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n\n // Call drag move handler on the active area (dragged element)\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragMove?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dragend': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragEnd?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragEnd.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dblclick':\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDblClick?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.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", "#state", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#emitResize", "entries", "entry", "width", "height", "#handleScroll", "#handleDown", "#handleDblClick", "#handleMove", "#handleUp", "#handleCancel", "event", "normalized", "#normalizeEvent", "#emit", "rawEvent", "type", "position", "#getPosition", "dx", "dy", "e", "dragend", "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\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 };\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 };\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 #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 // 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 }\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\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 \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 }\n}\n", "import { defineSurface } from '@jucie.io/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // Current normalized event from CanvasEvents\n const event = setup.signal(null);\n \n // Hit registry integration (still managed here)\n const hoveredArea = setup.signal(null);\n const activeArea = setup.signal(null);\n \n // Main handler - just stores the event\n const handleEvent = setup.action((_, normalizedEvent) => {\n event(normalizedEvent);\n });\n \n const setHoveredArea = setup.action((_, area) => {\n hoveredArea(area);\n });\n \n const setActiveArea = setup.action((_, area) => {\n activeArea(area);\n });\n \n const reset = setup.action(() => {\n event(null);\n hoveredArea(null);\n activeArea(null);\n });\n \n return {\n // Signals\n event,\n hoveredArea,\n activeArea,\n\n // Actions\n handleEvent,\n setHoveredArea,\n setActiveArea,\n reset\n };\n});\n", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nconst DEFINITIONS_TYPES = {\n BRUSH: 'BRUSH',\n LAYER: 'LAYER',\n SUBSCRIPTION: 'SUBSCRIPTION',\n SUBSCRIPTIONS: 'SUBSCRIPTIONS'\n};\n\nconst GLOBAL_LAYER_NAME = 'GLOBAL_LAYER';\n\nexport const defineBrush = createDefinition(DEFINITIONS_TYPES.BRUSH, [Object]);\nexport const defineLayer = createDefinition(DEFINITIONS_TYPES.LAYER, [Object]);\nexport const defineSubscription = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTION, [Function]);\nexport const defineSubscriptions = createDefinition(DEFINITIONS_TYPES.SUBSCRIPTIONS, [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #brushes = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #assets = new Map();\n #isRunning = false;\n #frameId = null;\n #isRendering = false;\n #renderScheduled = false;\n\n // Mutable runtime config (separate from frozen config)\n #runtimeConfig = {\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n };\n\n // Timing state\n #timing = {\n lastFrameTime: 0,\n deltaTime: 0,\n elapsedTime: 0,\n frameCount: 0\n };\n\n // Debug metrics\n #metrics = {\n fps: 0,\n frameTime: 0,\n layerTimes: new Map(),\n brushTimes: new Map(),\n skippedFrames: 0\n };\n\n // Hit detection state\n #hitRegistry = new HitRegistry();\n #pointerSurface = usePointerSurface();\n #canvasEvents = null; // Only created in main thread mode\n #pointerUnsubscribe = null;\n #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasOverCanvas = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface,\n };\n }\n \n initialize () {\n this.#addLayer(defineLayer(GLOBAL_LAYER_NAME, () => ({\n context: ContextTypes['2D']\n })));\n }\n\n actions() {\n // Initialize runtime config from frozen config\n if (this.config) {\n Object.assign(this.#runtimeConfig, this.config);\n }\n \n return {\n addLayer: (layerDef) => this.#addLayer(layerDef),\n addLayers: (...layers) => {\n for (const layer of layers) {\n this.#addLayer(layer);\n }\n },\n use: (...factories) => this.use(factories),\n updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\n setOffscreenCanvas: (offscreenCanvas) => this.setOffscreenCanvas(offscreenCanvas),\n setAssets: (assets) => this.setAssets(assets),\n removeLayer: (name) => this.#removeLayer(name),\n start: () => this.start(),\n stop: () => this.stop(),\n render: () => this.render(),\n setTargetFPS: (fps) => this.setTargetFPS(fps),\n setTimeScale: (scale) => this.setTimeScale(scale),\n setFixedTimeStep: (step) => this.setFixedTimeStep(step),\n setDebug: (options) => this.setDebug(options),\n getMetrics: () => this.getMetrics(),\n handleResize: (width, height) => this.handleResize(width, height),\n subscribe: (event, callback) => this.subscribe(event, callback),\n // Pointer API - receives normalized events from main thread\n handlePointerEvent: (normalizedEvent) => this.handlePointerEvent(normalizedEvent),\n subscribeToPointer: (callback) => this.#pointerSurface.$subscribe(callback),\n bindPointer: (path) => this.#pointerSurface.$bind(path),\n // Test helper - only for testing\n _testEmitPointerEvent: (normalizedEvent) => this._testEmitPointerEvent(normalizedEvent)\n };\n }\n\n use(factories) {\n for (const factory of factories) {\n const type = definitionType(factory);\n switch (type) {\n case DEFINITIONS_TYPES.BRUSH:\n this.#addBrush(GLOBAL_LAYER_NAME, factory);\n break;\n case DEFINITIONS_TYPES.LAYER:\n this.#addLayer(factory);\n break;\n case DEFINITIONS_TYPES.SUBSCRIPTION:\n this.#addSubscription(factory);\n break;\n\n case DEFINITIONS_TYPES.SUBSCRIPTIONS:\n this.#addSubscriptions(factory);\n break;\n\n default:\n throw new Error(`Invalid factory type: ${type}`);\n }\n }\n return this;\n }\n\n // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n #addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n\n const layer = {...config, name, context: this.#contexts.get(config.context || '2d') };\n \n // Set up layer computed if it has data paths\n if (config.data) {\n layer.dataReactor = this.#createReactor(config.data, () => this.#pointerSurface);\n }\n\n // Set up when reactor if layer has condition\n if (config.when) {\n layer.whenReactor = this.#createReactor(config.when, () => (layer?.dataReactor?.computed() || undefined));\n }\n\n // Set up brush reactors and structure\n if (config.children && config.children.length > 0) {\n for (const child of config.children) {\n if (definitionType(child) === 'BRUSH') {\n this.#addBrush(name, child);\n }\n if (definitionType(child) === 'LAYER') {\n this.#addLayer(child);\n }\n }\n }\n\n this.#layers.set(name, layer);\n\n // Call layer mount hook\n if (layer.lifecycle?.onMount) {\n try {\n layer.lifecycle.onMount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onMount:`, error);\n }\n }\n\n return layer;\n }\n\n #addBrush(layerName, brushFactory) {\n const name = brushFactory._name;\n const brushConfig = brushFactory(this.useContext, this.#hitRegistry);\n const brush = {\n name,\n ...brushConfig\n };\n\n if (brushConfig.data) {\n brush.dataReactor = this.#createReactor(brushConfig.data, () => this.#pointerSurface);\n }\n\n if (brushConfig.when) {\n brush.whenReactor = this.#createReactor(brushConfig.when, () => (brush?.dataReactor?.computed() || undefined));\n }\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || this.#layers.get(layerName)?.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n if (!this.#brushes.has(layerName)) {\n this.#brushes.set(layerName, []);\n }\n\n this.#brushes.get(layerName).push(brush);\n\n return brush;\n }\n\n #addSubscription(subscriptionFactory) {\n const name = subscriptionFactory._name;\n const subscriptionConfig = subscriptionFactory(this.useContext);\n this.subscribe(name, subscriptionConfig);\n }\n\n #addSubscriptions(subscriptionsFactory) {\n const prefix = subscriptionsFactory._name;\n const subscriptions = subscriptionsFactory(this.useContext);\n for (const [event, handler] of Object.entries(subscriptions)) {\n const finalEvent = prefix ? `${prefix}:${event}` : event;\n this.subscribe(finalEvent, handler);\n }\n }\n\n #removeLayer(name) {\n const layer = this.#layers.get(name);\n if (!layer) return;\n\n // Call layer unmount hook\n if (layer.lifecycle?.onUnmount) {\n try {\n layer.lifecycle.onUnmount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onUnmount:`, error);\n }\n }\n\n const brushes = this.#brushes.get(name) || [];\n this.#brushes.delete(name);\n\n // Call brush unmount hooks and clean up reactors\n\n for (const brush of brushes) {\n if (brush.lifecycle?.onUnmount) {\n try {\n brush.lifecycle.onUnmount(\n this.#contexts.get(brush.context || layer.context)\n );\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onUnmount:`, error);\n }\n }\n // Clean up brush when reactor\n if (brush.whenReactor) {\n destroyComputed(brush.whenReactor);\n }\n // Clean up brush computed and subscription\n if (brush.dataReactor) {\n brush.dataReactor?.unsubscribe();\n if (brush.dataReactor?.computed) {\n destroyComputed(brush.dataReactor.computed);\n }\n }\n }\n\n // Clean up layer when reactor\n if (layer.whenReactor) {\n layer.whenReactor?.unsubscribe();\n if (layer.whenReactor?.computed) {\n destroyComputed(layer.whenReactor.computed);\n }\n }\n\n this.#layers.delete(name);\n }\n\n #scheduleRender() {\n if (this.#renderScheduled || this.#isRendering) return;\n \n this.#renderScheduled = true;\n \n this.#frameId = requestAnimationFrame(() => {\n this.#renderScheduled = false;\n this.#frameId = null;\n this.#render();\n });\n }\n\n async #render() {\n if (!this.#canvas) return;\n this.#isRendering = true;\n \n try {\n // Clear hit registry at start of render\n this.#hitRegistry.clear();\n \n const renderStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Clear all contexts\n this.#contexts.forEach(ctx => {\n ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n });\n\n // Render layers in order\n for (const layer of this.#layers.values()) {\n const layerStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Check layer condition\n if (layer.whenReactor && !layer.whenReactor.computed()) continue;\n\n const ctx = layer.context;\n\n if (!ctx) continue;\n\n // Layer beforeRender hook\n if (layer.lifecycle?.beforeRender) {\n try {\n layer.lifecycle.beforeRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" beforeRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n // Apply layer settings\n ctx.save();\n if (layer.settings) {\n Object.entries(layer.settings).forEach(([key, value]) => {\n if (typeof ctx[key] === 'function') {\n ctx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n ctx[key] = value;\n }\n });\n }\n\n const brushes = this.#brushes.get(layer.name) || [];\n\n // Render brushes\n for (const brush of brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor.computed()) continue;\n\n\n const brushCtx = brush.context ? \n this.#contexts.get(brush.context) : \n ctx;\n\n if (!brushCtx) continue;\n\n // Brush beforeRender hook\n if (brush.lifecycle?.beforeRender) {\n try {\n brush.lifecycle.beforeRender(brushCtx, this.#timing);\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" beforeRender:`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n continue;\n }\n }\n\n brushCtx.save();\n \n if (brush.settings) {\n Object.entries(brush.settings).forEach(([key, value]) => {\n if (typeof brushCtx[key] === 'function') {\n brushCtx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n brushCtx[key] = value;\n }\n });\n }\n \n try {\n const requiredAssets = {};\n if (brush.assets) {\n for (const key of brush.assets) {\n requiredAssets[key] = this.#assets.get(key);\n }\n }\n brush.render(brushCtx, (brush.dataReactor ? brush.dataReactor.computed() : undefined), requiredAssets, this.#timing);\n\n // Brush afterRender hook\n if (brush.lifecycle?.afterRender) {\n brush.lifecycle.afterRender(brushCtx, this.#timing);\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const brushTime = performance.now() - brushStart;\n this.#metrics.brushTimes.set(brush.name, brushTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderBrushBounds(brushCtx, brush);\n }\n }\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\":`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n } finally {\n brushCtx.restore();\n }\n }\n\n ctx.restore();\n\n // Layer afterRender hook\n if (layer.lifecycle?.afterRender) {\n try {\n layer.lifecycle.afterRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" afterRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const layerTime = performance.now() - layerStart;\n this.#metrics.layerTimes.set(layer.name, layerTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderLayerBounds(ctx, layer);\n }\n }\n }\n\n // Render debug overlay if enabled\n if (this.#runtimeConfig.debug?.enabled) {\n this.#renderDebugOverlay();\n }\n \n } finally {\n this.#isRendering = false;\n }\n }\n\n #renderBrushBounds(ctx, brush) {\n ctx.save();\n ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';\n ctx.lineWidth = 1;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderLayerBounds(ctx, layer) {\n ctx.save();\n ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';\n ctx.lineWidth = 2;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderDebugOverlay() {\n const ctx = this.#contexts.get(ContextTypes['2D']);\n if (!ctx) return;\n\n ctx.save();\n ctx.resetTransform();\n ctx.font = '12px monospace';\n ctx.fillStyle = 'white';\n ctx.strokeStyle = 'black';\n ctx.lineWidth = 3;\n\n let y = 20;\n const lineHeight = 15;\n\n if (this.#runtimeConfig.debug?.showFPS) {\n const text = `FPS: ${Math.round(this.#metrics.fps)} (${this.#timing.deltaTime.toFixed(2)}ms)`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n if (this.#runtimeConfig.debug?.showLayerTiming) {\n ctx.fillText('Layer Times:', 10, y);\n y += lineHeight;\n\n for (const [name, time] of this.#metrics.layerTimes) {\n const text = ` ${name}: ${time.toFixed(2)}ms`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n ctx.fillText(this.state.get(['_transitions', 'pointer', 'currentState']), 10, y);\n }\n\n ctx.restore();\n }\n\n handleResize(width, height) {\n // Call onResize hooks for all layers\n for (const layer of this.#layers.values()) {\n if (layer.lifecycle?.onResize) {\n try {\n layer.lifecycle.onResize(width, height, layer.context);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" onResize:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n }\n }\n\n #createReactor(fn, context = () => undefined) {\n if (!fn) return null;\n \n const computed = createComputed(fn, {\n immediate: true,\n context\n });\n \n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n \n return {computed, unsubscribe};\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.#removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n const event = pointer.event;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer);\n \n // Emit click if it wasn't a drag\n if (event && !event.isDragging) {\n this.#emit('pointer:click', pointer);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer);\n break;\n \n case 'dragstart':\n this.#emit('pointer:drag:start', pointer);\n break;\n \n case 'drag':\n this.#emit('pointer:drag:move', pointer);\n break;\n \n case 'dragend':\n this.#emit('pointer:drag:end', pointer);\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer);\n break;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = event?.isOverCanvas || false;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n }\n\n #handlePointerInteraction(normalizedEvent) {\n const { type, x, y } = normalizedEvent;\n const pointer = this.#pointerSurface;\n\n switch (type) {\n case 'down': {\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDown?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDown.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'up': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerUp?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerUp.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'move': {\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle pointer move on hovered area (only when NOT dragging)\n if (hitArea?.onPointerMove?.handler && !normalizedEvent.isDragging) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n // Handle hover changes\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'dragstart': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragStart?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragStart.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'drag': {\n // Perform hit test to detect drop targets while dragging\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle hover changes (for drop target detection)\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n\n // Call drag move handler on the active area (dragged element)\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragMove?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragMove.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dragend': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onDragEnd?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onDragEnd.handler({\n event: normalizedEvent,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'dblclick':\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDblClick?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.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", "#state", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#emitResize", "entries", "entry", "width", "height", "#handleScroll", "#handleDown", "#handleMove", "#handleUp", "#handleCancel", "event", "normalized", "#normalizeEvent", "#emit", "rawEvent", "type", "position", "#getPosition", "dx", "dy", "e", "dragend", "now", "timeDiff", "distance", "dblclickEvent", "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.49",
3
+ "version": "1.0.50",
4
4
  "description": "Canvas painting service for @jucie.io/engine with reactive rendering support",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",