@jucie-engine/painter 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var G=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var Ee=(s,e)=>{for(var t in e)G(s,t,{get:e[t],enumerable:!0})},Se=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of we(e))!Te.call(s,r)&&r!==t&&G(s,r,{get:()=>e[r],enumerable:!(i=xe(e,r))||i.enumerable});return s};var Ce=s=>Se(G({},"__esModule",{value:!0}),s);var Re={};Ee(Re,{CanvasPointer:()=>B,HitRegistry:()=>Y,Painter:()=>j,defineBrush:()=>le,defineLayer:()=>ce,usePointerSurface:()=>I});module.exports=Ce(Re);var oe=require("@jucie-engine/core");var K={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var V=require("@jucie-state/reactive"),F=require("@jucie-engine/core");var Y=class{#e=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#e.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#e.delete(e)}get(e){return this.#e.get(e)}has(e){return this.#e.has(e)}get areas(){return Array.from(this.#e.values())}clear(){this.#e.clear()}};var re=require("@jucie-engine/core"),B=class extends re.ServiceProvider{#e=null;#s=null;#i=null;#a=new Set;#f=null;#l=null;static manifest={name:"CanvasPointer",namespace:"canvasPointer",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),getOffscreenCanvas:()=>this.getOffscreenCanvas()}}getOffscreenCanvas(){return this.#e?this.#e.transferControlToOffscreen():null}setCanvas(e){this.#e&&this.#m(),this.#e=e,this.#u(),this.#b()}subscribe(e){return this.#a.add(e),()=>this.#a.delete(e)}#u(){this.#e&&(this.#s=this.#e.getBoundingClientRect())}#b(){this.#e&&(this.#u(),this.#i=new ResizeObserver(()=>{this.#u()}),this.#i.observe(this.#e),document.addEventListener("wheel",this.#t,{passive:!1}),document.addEventListener("pointermove",this.#o),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#h),document.addEventListener("pointercancel",this.#h),document.addEventListener("dblclick",this.#c))}#m(){this.#i&&(this.#i.disconnect(),this.#i=null),document.removeEventListener("wheel",this.#t),document.removeEventListener("pointermove",this.#o),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#h),document.removeEventListener("pointercancel",this.#h),document.removeEventListener("dblclick",this.#c)}#t=e=>{if(e.target===this.#e)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#r(e,"zoom");this.#n(t)}else{let t=this.#r(e,"scroll");this.#n(t)}};#o=e=>{let t=this.#r(e,"move");this.#f=t,!this.#l&&(this.#l=requestAnimationFrame(()=>{this.#f&&(this.#n(this.#f),this.#f=null),this.#l=null}))};#d=e=>{if(e.target===this.#e){let t=this.#r(e,"down");this.#n(t)}};#h=e=>{let t=this.#r(e,"up");this.#n(t)};#c=e=>{let t=this.#r(e,"dblclick");this.#n(t)};#n(e){for(let t of this.#a)t(e)}#r(e,t){let i=e.target===this.#e,r,n;i?(r=e.offsetX,n=e.offsetY):this.#s?(r=e.clientX-this.#s.left,n=e.clientY-this.#s.top):(r=e.clientX,n=e.clientY);let d=i||this.#s&&r>=0&&r<=this.#s.width&&n>=0&&n<=this.#s.height,o={x:r,y:n,type:t,isOverCanvas:i,isWithinBounds:d,clientX:e.clientX,clientY:e.clientY,button:e.button??null,buttons:e.buttons??0,timestamp:Date.now()};return(t==="scroll"||t==="zoom")&&(o.deltaX=e.deltaX,o.deltaY=e.deltaY,o.deltaZ=e.deltaZ,o.deltaMode=e.deltaMode),o.shiftKey=e.shiftKey||!1,o.ctrlKey=e.ctrlKey||!1,o.altKey=e.altKey||!1,o.metaKey=e.metaKey||!1,o}destroy(){this.#l&&(cancelAnimationFrame(this.#l),this.#l=null),this.#m(),this.#e=null,this.#s=null,this.#a.clear()}};var ae=require("@jucie-state/reactive"),I=(0,ae.defineSurface)(s=>{let e=s.value(0),t=s.value(0),i=s.value(0),r=s.value(0),n=s.value(0),d=s.value(0),o=s.value(!1),y=s.value(!1),g=s.value(!1),p=s.value(null),l=s.value(0),f=s.value(null),m=s.value(null),C=s.value(null),X=s.value(null),_=s.value(null),$=s.value(null),z=s.value(null),u=s.value(!1),P=s.value(0),T=s.value(0),a=s.value(0),E=s.value(0),S=s.value(0),x=s.value(0),R=s.value(0),U=s.value(null),W=s.value(null),D=s.value({dragThreshold:5,doubleClickThreshold:300,holdThreshold:500,velocitySmoothing:.3,maxVelocity:1e4}),N=s.computed(()=>({x:e.value,y:t.value})),J=s.computed(()=>({x:n.value,y:d.value})),Q=s.computed(()=>({x:i.value,y:r.value})),ee=s.computed(()=>{let h=typeof e.value=="number"?e.value:0,c=typeof i.value=="number"?i.value:0,v=typeof t.value=="number"?t.value:0,b=typeof r.value=="number"?r.value:0;return{x:h-c,y:v-b}}),te=s.computed(()=>({x:a.value,y:E.value})),se=s.computed(()=>{let h=a.value,c=E.value;return Math.sqrt(h*h+c*c)}),H=s.computed(()=>{let h=$.value,c=z.value;if(h===null||c===null||typeof h!="number"||typeof c!="number")return 0;let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0,L=v-h,w=b-c;return Math.sqrt(L*L+w*w)}),ie=s.computed(()=>{let h=$.value,c=z.value;if(h===null||c===null||typeof h!="number"||typeof c!="number")return{x:0,y:0};let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0;return{x:v-h,y:b-c}}),q=s.computed(()=>!g.value||!m.value?0:Date.now()-m.value),ne=s.computed(()=>q.value>D.value.holdThreshold&&!u.value),ue=s.computed(()=>{let h=_.value;return h?Date.now()-h:0}),he=s.computed(()=>({position:N.value,clientPosition:J.value,previousPosition:Q.value,delta:ee.value,velocity:te.value,speed:se.value,isPressed:g.value,button:p.value,buttons:l.value,isDragging:u.value,dragDistance:H.value,dragDelta:ie.value,isHolding:ne.value,holdDuration:q.value,isOverCanvas:o.value,isWithinBounds:y.value,hoveredArea:U.value,activeArea:W.value,clickCount:P.value,lastEventType:f.value})),A=s.action((h,c,v,b,L)=>{i.value=e.value,r.value=t.value,e.value=c,t.value=v,n.value=b,d.value=L,X.value=Date.now()}),de=s.action(()=>{let h=Date.now(),c=X.value;if(c){let v=(h-c)/1e3;if(v>0&&v<.1){let b=(e.value-i.value)/v,L=(t.value-r.value)/v,w=D.value.maxVelocity,k=Math.max(-w,Math.min(w,b)),Z=Math.max(-w,Math.min(w,L)),M=D.value.velocitySmoothing;a.value=a.value*(1-M)+k*M,E.value=E.value*(1-M)+Z*M}}}),fe=s.action((h,c)=>{let{x:v,y:b,type:L,clientX:w,clientY:k,button:Z,buttons:M,isOverCanvas:ge,isWithinBounds:pe}=c,O=Date.now();switch(_.value=O,f.value=L,o.value=ge,y.value=pe,L){case"down":A(h,v,b,w,k),g.value=!0,m.value=O,p.value=Z,l.value=M,$.value=v,z.value=b,u.value=!1,O-T.value<D.value.doubleClickThreshold?P.value=P.value+1:P.value=1;break;case"up":A(h,v,b,w,k),g.value=!1,C.value=O,T.value=O,u.value=!1,a.value=0,E.value=0,l.value=M;break;case"move":A(h,v,b,w,k),de(),l.value=M,g.value&&!u.value&&H.value>D.value.dragThreshold&&(u.value=!0);break;case"dblclick":A(h,v,b,w,k),P.value=2;break;case"scroll":A(h,v,b,w,k),c.deltaX!==void 0&&(S.value=c.deltaX),c.deltaY!==void 0&&(x.value=c.deltaY);break;case"zoom":A(h,v,b,w,k),c.deltaY!==void 0&&(R.value=c.deltaY);break}}),ve=s.action((h,c)=>{U.value=c}),me=s.action((h,c)=>{W.value=c}),ye=s.action(()=>{g.value=!1,u.value=!1,W.value=null,U.value=null,a.value=0,E.value=0,P.value=0,S.value=0,x.value=0,R.value=0}),be=s.action((h,c)=>{D.value={...D.value,...c}});return{state:he,position:N,clientPosition:J,previousPosition:Q,delta:ee,velocity:te,speed:se,isPressed:g,button:p,buttons:l,isDragging:u,dragDistance:H,dragDelta:ie,isHolding:ne,holdDuration:q,isOverCanvas:o,isWithinBounds:y,hoveredArea:U,activeArea:W,clickCount:P,lastEventType:f,timeSinceLastEvent:ue,handleEvent:fe,setHoveredArea:ve,setActiveArea:me,reset:ye,updateConfig:be}});var le=(0,F.createDefinition)("BRUSH",[Object]),ce=(0,F.createDefinition)("LAYER",[Object]),j=class extends oe.ServiceProvider{#e=new Map;#s=null;#i=new Map;#a=new Map;#f=new Map;#l=!1;#u=null;#b=!1;#m=!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};#d={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#h=new Y;#c=null;#n=I();#r=null;#y=new Map;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.state}}actions(){return this.config&&Object.assign(this.#t,this.config),{addLayer:e=>this.addLayer(e),addLayers:(...e)=>{for(let t of e)this.addLayer(t)},updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.removeLayer(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),subscribeToPointer:e=>this.#n.$subscribe(e),bindPointer:e=>this.#n.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){this.#s=e,Object.values(K).forEach(t=>{try{let i=e.getContext(t);i&&this.#i.set(t,i)}catch{console.warn(`Context type ${t} not supported`)}}),this.#c||(this.#c=new B),this.#c.setCanvas(e),this.#r&&this.#r(),this.#r=this.#c.subscribe(t=>{this.#n.handleEvent(t),this.#w(t)})}updateCanvas(e){let t=e(this.#s);t&&(this.#s=t)}setAssets(e){this.#f=e}start(){this.#l||(this.#l=!0,this.#p())}stop(){this.#l&&(this.#l=!1,this.#u&&(cancelAnimationFrame(this.#u),this.#u=null))}addLayer(e){var d;if((0,F.definitionType)(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,i=e(this.useContext,this.#h);if(i.data){let o=this.#x(`layer_${t}`,i.data);o&&this.#a.set(`layer_${t}`,o)}let r=i.children.map(o=>{var y;if((0,F.definitionType)(o)==="BRUSH"){let g=o._name,p=o(this.useContext,this.#h),l=p.data?this.#x(`brush_${g}`,p.data):()=>{},f=p.when?(0,V.createReactor)(p.when,{immediate:!0,context:this.useContext("state")}):null,m={name:g,...p,dataReactor:l,whenReactor:f};if((y=m.lifecycle)!=null&&y.onMount)try{m.lifecycle.onMount(this.#i.get(m.context||i.context))}catch(C){console.error(`Error in brush "${m.name}" onMount:`,C)}return m}return this.addLayer(o)}),n={...i,name:t,brushes:r,context:this.#i.get(i.context)};if(this.#e.set(t,n),(d=n.lifecycle)!=null&&d.onMount)try{n.lifecycle.onMount(n.context)}catch(o){console.error(`Error in layer "${t}" onMount:`,o)}return n}removeLayer(e){var r;let t=this.#e.get(e);if(!t)return;if((r=t.lifecycle)!=null&&r.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(n){console.error(`Error in layer "${e}" onUnmount:`,n)}t.brushes.forEach(n=>{var o;if((o=n.lifecycle)!=null&&o.onUnmount)try{n.lifecycle.onUnmount(this.#i.get(n.context||t.context))}catch(y){console.error(`Error in brush "${n.name}" onUnmount:`,y)}let d=this.#a.get(`painter_brush_${n.name}`);d&&(d.unsubscribe(),d.reactor.destroy(),this.#a.delete(`painter_brush_${n.name}`))});let i=this.#a.get(`painter_layer_${e}`);i&&(i.unsubscribe(),i.reactor.destroy(),this.#a.delete(`painter_layer_${e}`)),this.#e.delete(e)}#p(){this.#m||this.#b||(this.#m=!0,this.#u=requestAnimationFrame(()=>{this.#m=!1,this.#u=null,this.#E()}))}async#E(){var e,t,i,r,n,d,o,y,g,p,l,f,m,C,X,_,$;if(this.#s){this.#b=!0;try{this.#h.clear();let z=(e=this.#t.debug)!=null&&e.enabled?performance.now():0;this.#i.forEach(u=>{u.clearRect(0,0,this.#s.width,this.#s.height)});for(let u of this.#e.values()){let P=(t=this.#t.debug)!=null&&t.enabled?performance.now():0;if(u.whenReactor){let a=(i=this.#a.get(`painter_layer_${u.name}`))==null?void 0:i.reactor;if(!u.when(a()))continue}let T=u.context;if(T){if((r=u.lifecycle)!=null&&r.beforeRender)try{u.lifecycle.beforeRender(T,this.#o)}catch(a){console.error(`Error in layer "${u.name}" beforeRender:`,a),(n=u.lifecycle)!=null&&n.onError&&u.lifecycle.onError(a)}T.save(),u.settings&&Object.entries(u.settings).forEach(([a,E])=>{typeof T[a]=="function"?T[a](...Array.isArray(E)?E:[E]):T[a]=E});for(let a of u.brushes){let E=(d=this.#t.debug)!=null&&d.enabled?performance.now():0;if(a.whenReactor&&!a.whenReactor())continue;let S=a.context?this.#i.get(a.context):T;if(S){if((o=a.lifecycle)!=null&&o.beforeRender)try{a.lifecycle.beforeRender(S,this.#o)}catch(x){console.error(`Error in brush "${a.name}" beforeRender:`,x),(y=a.lifecycle)!=null&&y.onError&&a.lifecycle.onError(x);continue}S.save(),a.settings&&Object.entries(a.settings).forEach(([x,R])=>{typeof S[x]=="function"?S[x](...Array.isArray(R)?R:[R]):S[x]=R});try{let x={};if(a.assets)for(let R of a.assets)x[R]=this.#f.get(R);if(a.render(S,a.dataReactor(),x,this.#o),(g=a.lifecycle)!=null&&g.afterRender&&a.lifecycle.afterRender(S,this.#o),(p=this.#t.debug)!=null&&p.enabled){let R=performance.now()-E;this.#d.brushTimes.set(a.name,R),(l=this.#t.debug)!=null&&l.showBounds&&this.#S(S,a)}}catch(x){console.error(`Error in brush "${a.name}":`,x),(f=a.lifecycle)!=null&&f.onError&&a.lifecycle.onError(x)}finally{S.restore()}}}if(T.restore(),(m=u.lifecycle)!=null&&m.afterRender)try{u.lifecycle.afterRender(T,this.#o)}catch(a){console.error(`Error in layer "${u.name}" afterRender:`,a),(C=u.lifecycle)!=null&&C.onError&&u.lifecycle.onError(a)}if((X=this.#t.debug)!=null&&X.enabled){let a=performance.now()-P;this.#d.layerTimes.set(u.name,a),(_=this.#t.debug)!=null&&_.showBounds&&this.#C(T,u)}}}($=this.#t.debug)!=null&&$.enabled&&this.#R()}finally{this.#b=!1}}}#S(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()}#C(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()}#R(){var r,n;let e=this.#i.get(K["2D"]);if(!e)return;e.save(),e.resetTransform(),e.font="12px monospace",e.fillStyle="white",e.strokeStyle="black",e.lineWidth=3;let t=20,i=15;if((r=this.#t.debug)!=null&&r.showFPS){let d=`FPS: ${Math.round(this.#d.fps)} (${this.#o.deltaTime.toFixed(2)}ms)`;e.strokeText(d,10,t),e.fillText(d,10,t),t+=i}if((n=this.#t.debug)!=null&&n.showLayerTiming){e.fillText("Layer Times:",10,t),t+=i;for(let[d,o]of this.#d.layerTimes){let y=` ${d}: ${o.toFixed(2)}ms`;e.strokeText(y,10,t),e.fillText(y,10,t),t+=i}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){var i,r;for(let n of this.#e.values())if((i=n.lifecycle)!=null&&i.onResize)try{n.lifecycle.onResize(e,t,n.context)}catch(d){console.error(`Error in layer "${n.name}" onResize:`,d),(r=n.lifecycle)!=null&&r.onError&&n.lifecycle.onError(d)}}#x(e,t){let i=this.useContext("state"),r=(0,V.createReactor)(t,{immediate:!0,context:i}),n=(0,V.addEffect)(r,()=>this.#p());return this.#a.set(`painter_${e}`,{reactor:r,unsubscribe:n}),r}destroy(){this.stop(),this.#r&&(this.#r(),this.#r=null),this.#c&&(this.#c.destroy(),this.#c=null),this.#n&&this.#n.$destroy();for(let e of this.#e.keys())this.removeLayer(e)}setTargetFPS(e){this.#t.targetFPS=e,this.#t.fixedTimeStep=1e3/e}setTimeScale(e){this.#t.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#t.fixedTimeStep=e}setDebug(e={}){this.#t.debug||(this.#t.debug={}),Object.assign(this.#t.debug,e)}getMetrics(){return{...this.#d,deltaTime:this.#o.deltaTime,elapsedTime:this.#o.elapsedTime,frameCount:this.#o.frameCount}}#w(e){var d,o,y,g,p;let{type:t,x:i,y:r}=e,n=this.#n;switch(t){case"down":{let l=this.#T(i,r);if(n.setActiveArea(l),(d=l==null?void 0:l.onPointerDown)!=null&&d.handler){let f=this.#g(l);l.onPointerDown.handler({...n.state,ctx:f,emit:this.#v.bind(this)})}break}case"up":{let l=n.activeArea;if((o=l==null?void 0:l.onPointerUp)!=null&&o.handler){let f=this.#g(l);l.onPointerUp.handler({...n.state,ctx:f,emit:this.#v.bind(this)})}break}case"move":{let l=this.#T(i,r),f=n.hoveredArea,m=n.activeArea;if((y=m==null?void 0:m.onPointerMove)!=null&&y.handler&&n.isDragging){let C=this.#g(m);m.onPointerMove.handler({...n.state,ctx:C,emit:this.#v.bind(this)})}if((l==null?void 0:l.id)!==(f==null?void 0:f.id)){if((g=f==null?void 0:f.onPointerLeave)!=null&&g.handler){let C=this.#g(f);f.onPointerLeave.handler({...n.state,ctx:C,emit:this.#v.bind(this)})}if((p=l==null?void 0:l.onPointerEnter)!=null&&p.handler){let C=this.#g(l);l.onPointerEnter.handler({...n.state,ctx:C,emit:this.#v.bind(this)})}n.setHoveredArea(l)}break}case"scroll":case"zoom":this.#v(`pointer:${t}`,n.state);break;case"dblclick":this.#v("pointer:dblclick",n.state);break}}#g(e){return e?e.context?this.#i.get(e.context):this.#i.get(K["2D"]):null}subscribe(e,t){return this.#y.has(e)||this.#y.set(e,new Set),this.#y.get(e).add(t),()=>{let i=this.#y.get(e);i&&(i.delete(t),i.size===0&&this.#y.delete(e))}}#T(e,t){let i=this.#h.areas.sort((r,n)=>(n.priority||0)-(r.priority||0));for(let r of i)if(this.#P(e,t,r.bounds))return r;return null}#P(e,t,i){return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height}#v(e,t){let i=this.#y.get(e);if(i)for(let r of i)r(t)}_testEmitPointerEvent(e){this.#n.handleEvent(e),this.#w(e)}};0&&(module.exports={CanvasPointer,HitRegistry,Painter,defineBrush,defineLayer,usePointerSurface});
|
|
1
|
+
var G=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Ee=Object.prototype.hasOwnProperty;var Te=(i,e)=>{for(var t in e)G(i,t,{get:e[t],enumerable:!0})},Se=(i,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of we(e))!Ee.call(i,r)&&r!==t&&G(i,r,{get:()=>e[r],enumerable:!(s=xe(e,r))||s.enumerable});return i};var Ce=i=>Se(G({},"__esModule",{value:!0}),i);var Re={};Te(Re,{CanvasEvents:()=>B,HitRegistry:()=>Y,Painter:()=>I,defineBrush:()=>le,defineLayer:()=>ce,usePointerSurface:()=>j});module.exports=Ce(Re);var oe=require("@jucie-engine/core");var V={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var z=require("@jucie-state/reactive"),F=require("@jucie-engine/core");var Y=class{#e=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#e.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#e.delete(e)}get(e){return this.#e.get(e)}has(e){return this.#e.has(e)}get areas(){return Array.from(this.#e.values())}clear(){this.#e.clear()}};var re=require("@jucie-engine/core"),B=class extends re.ServiceProvider{#e=null;#s=null;#i=null;#a=new Set;#f=null;#l=null;static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e)}}setCanvas(e){this.#e&&this.#m(),this.#e=e,this.#h(),this.#b()}subscribe(e){return this.#a.add(e),()=>this.#a.delete(e)}#h(){this.#e&&(this.#s=this.#e.getBoundingClientRect())}#b(){this.#e&&(this.#h(),this.#i=new ResizeObserver(()=>{this.#h()}),this.#i.observe(this.#e),document.addEventListener("wheel",this.#t,{passive:!1}),document.addEventListener("pointermove",this.#o),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#u),document.addEventListener("pointercancel",this.#u),document.addEventListener("dblclick",this.#c))}#m(){this.#i&&(this.#i.disconnect(),this.#i=null),document.removeEventListener("wheel",this.#t),document.removeEventListener("pointermove",this.#o),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#u),document.removeEventListener("pointercancel",this.#u),document.removeEventListener("dblclick",this.#c)}#t=e=>{if(e.target===this.#e)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#r(e,"zoom");this.#n(t)}else{let t=this.#r(e,"scroll");this.#n(t)}};#o=e=>{let t=this.#r(e,"move");this.#f=t,!this.#l&&(this.#l=requestAnimationFrame(()=>{this.#f&&(this.#n(this.#f),this.#f=null),this.#l=null}))};#d=e=>{if(e.target===this.#e){let t=this.#r(e,"down");this.#n(t)}};#u=e=>{let t=this.#r(e,"up");this.#n(t)};#c=e=>{let t=this.#r(e,"dblclick");this.#n(t)};#n(e){for(let t of this.#a)t(e)}#r(e,t){let s=e.target===this.#e,r,n;s?(r=e.offsetX,n=e.offsetY):this.#s?(r=e.clientX-this.#s.left,n=e.clientY-this.#s.top):(r=e.clientX,n=e.clientY);let d=s||this.#s&&r>=0&&r<=this.#s.width&&n>=0&&n<=this.#s.height,o={x:r,y:n,type:t,isOverCanvas:s,isWithinBounds:d,clientX:e.clientX,clientY:e.clientY,button:e.button??null,buttons:e.buttons??0,timestamp:Date.now()};return(t==="scroll"||t==="zoom")&&(o.deltaX=e.deltaX,o.deltaY=e.deltaY,o.deltaZ=e.deltaZ,o.deltaMode=e.deltaMode),o.shiftKey=e.shiftKey||!1,o.ctrlKey=e.ctrlKey||!1,o.altKey=e.altKey||!1,o.metaKey=e.metaKey||!1,o}destroy(){this.#l&&(cancelAnimationFrame(this.#l),this.#l=null),this.#m(),this.#e=null,this.#s=null,this.#a.clear()}};var ae=require("@jucie-state/reactive"),j=(0,ae.defineSurface)(i=>{let e=i.value(0),t=i.value(0),s=i.value(0),r=i.value(0),n=i.value(0),d=i.value(0),o=i.value(!1),y=i.value(!1),g=i.value(!1),p=i.value(null),l=i.value(0),f=i.value(null),m=i.value(null),C=i.value(null),O=i.value(null),X=i.value(null),$=i.value(null),U=i.value(null),h=i.value(!1),P=i.value(0),E=i.value(0),a=i.value(0),T=i.value(0),S=i.value(0),x=i.value(0),R=i.value(0),W=i.value(null),K=i.value(null),D=i.value({dragThreshold:5,doubleClickThreshold:300,holdThreshold:500,velocitySmoothing:.3,maxVelocity:1e4}),N=i.computed(()=>({x:e.value,y:t.value})),J=i.computed(()=>({x:n.value,y:d.value})),Q=i.computed(()=>({x:s.value,y:r.value})),ee=i.computed(()=>{let u=typeof e.value=="number"?e.value:0,c=typeof s.value=="number"?s.value:0,v=typeof t.value=="number"?t.value:0,b=typeof r.value=="number"?r.value:0;return{x:u-c,y:v-b}}),te=i.computed(()=>({x:a.value,y:T.value})),se=i.computed(()=>{let u=a.value,c=T.value;return Math.sqrt(u*u+c*c)}),H=i.computed(()=>{let u=$.value,c=U.value;if(u===null||c===null||typeof u!="number"||typeof c!="number")return 0;let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0,L=v-u,w=b-c;return Math.sqrt(L*L+w*w)}),ie=i.computed(()=>{let u=$.value,c=U.value;if(u===null||c===null||typeof u!="number"||typeof c!="number")return{x:0,y:0};let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0;return{x:v-u,y:b-c}}),q=i.computed(()=>!g.value||!m.value?0:Date.now()-m.value),ne=i.computed(()=>q.value>D.value.holdThreshold&&!h.value),he=i.computed(()=>{let u=X.value;return u?Date.now()-u:0}),ue=i.computed(()=>({position:N.value,clientPosition:J.value,previousPosition:Q.value,delta:ee.value,velocity:te.value,speed:se.value,isPressed:g.value,button:p.value,buttons:l.value,isDragging:h.value,dragDistance:H.value,dragDelta:ie.value,isHolding:ne.value,holdDuration:q.value,isOverCanvas:o.value,isWithinBounds:y.value,hoveredArea:W.value,activeArea:K.value,clickCount:P.value,lastEventType:f.value})),A=i.action((u,c,v,b,L)=>{s.value=e.value,r.value=t.value,e.value=c,t.value=v,n.value=b,d.value=L,O.value=Date.now()}),de=i.action(()=>{let u=Date.now(),c=O.value;if(c){let v=(u-c)/1e3;if(v>0&&v<.1){let b=(e.value-s.value)/v,L=(t.value-r.value)/v,w=D.value.maxVelocity,k=Math.max(-w,Math.min(w,b)),Z=Math.max(-w,Math.min(w,L)),M=D.value.velocitySmoothing;a.value=a.value*(1-M)+k*M,T.value=T.value*(1-M)+Z*M}}}),fe=i.action((u,c)=>{let{x:v,y:b,type:L,clientX:w,clientY:k,button:Z,buttons:M,isOverCanvas:ge,isWithinBounds:pe}=c,_=Date.now();switch(X.value=_,f.value=L,o.value=ge,y.value=pe,L){case"down":A(u,v,b,w,k),g.value=!0,m.value=_,p.value=Z,l.value=M,$.value=v,U.value=b,h.value=!1,_-E.value<D.value.doubleClickThreshold?P.value=P.value+1:P.value=1;break;case"up":A(u,v,b,w,k),g.value=!1,C.value=_,E.value=_,h.value=!1,a.value=0,T.value=0,l.value=M;break;case"move":A(u,v,b,w,k),de(),l.value=M,g.value&&!h.value&&H.value>D.value.dragThreshold&&(h.value=!0);break;case"dblclick":A(u,v,b,w,k),P.value=2;break;case"scroll":A(u,v,b,w,k),c.deltaX!==void 0&&(S.value=c.deltaX),c.deltaY!==void 0&&(x.value=c.deltaY);break;case"zoom":A(u,v,b,w,k),c.deltaY!==void 0&&(R.value=c.deltaY);break}}),ve=i.action((u,c)=>{W.value=c}),me=i.action((u,c)=>{K.value=c}),ye=i.action(()=>{g.value=!1,h.value=!1,K.value=null,W.value=null,a.value=0,T.value=0,P.value=0,S.value=0,x.value=0,R.value=0}),be=i.action((u,c)=>{D.value={...D.value,...c}});return{state:ue,position:N,clientPosition:J,previousPosition:Q,delta:ee,velocity:te,speed:se,isPressed:g,button:p,buttons:l,isDragging:h,dragDistance:H,dragDelta:ie,isHolding:ne,holdDuration:q,isOverCanvas:o,isWithinBounds:y,hoveredArea:W,activeArea:K,clickCount:P,lastEventType:f,timeSinceLastEvent:he,handleEvent:fe,setHoveredArea:ve,setActiveArea:me,reset:ye,updateConfig:be}});var le=(0,F.createDefinition)("BRUSH",[Object]),ce=(0,F.createDefinition)("LAYER",[Object]),I=class extends oe.ServiceProvider{#e=new Map;#s=null;#i=new Map;#a=new Map;#f=new Map;#l=!1;#h=null;#b=!1;#m=!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};#d={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#u=new Y;#c=j();#n=null;#r=null;#y=new Map;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.#c.state}}actions(){return this.config&&Object.assign(this.#t,this.config),{addLayer:e=>this.addLayer(e),addLayers:(...e)=>{for(let t of e)this.addLayer(t)},updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setOffscreenCanvas:e=>this.setOffscreenCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.removeLayer(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.#c.$subscribe(e),bindPointer:e=>this.#c.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){let t=e.transferControlToOffscreen();this.#s=t,Object.values(V).forEach(s=>{try{let r=t.getContext(s);r&&this.#i.set(s,r)}catch{console.warn(`Context type ${s} not supported`)}}),this.#n||(this.#n=new B),this.#n.setCanvas(e),this.#r&&this.#r(),this.#r=this.#n.subscribe(s=>{this.handlePointerEvent(s)})}setOffscreenCanvas(e){this.#s=e,Object.values(V).forEach(t=>{try{let s=e.getContext(t);s&&this.#i.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#s);t&&(this.#s=t)}setAssets(e){this.#f=e}start(){this.#l||(this.#l=!0,this.#p())}stop(){this.#l&&(this.#l=!1,this.#h&&(cancelAnimationFrame(this.#h),this.#h=null))}addLayer(e){var d;if((0,F.definitionType)(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#u);if(s.data){let o=this.#x(`layer_${t}`,s.data);o&&this.#a.set(`layer_${t}`,o)}let r=s.children.map(o=>{var y;if((0,F.definitionType)(o)==="BRUSH"){let g=o._name,p=o(this.useContext,this.#u),l=p.data?this.#x(`brush_${g}`,p.data):()=>{},f=p.when?(0,z.createReactor)(p.when,{immediate:!0,context:this.useContext("state")}):null,m={name:g,...p,dataReactor:l,whenReactor:f};if((y=m.lifecycle)!=null&&y.onMount)try{m.lifecycle.onMount(this.#i.get(m.context||s.context))}catch(C){console.error(`Error in brush "${m.name}" onMount:`,C)}return m}return this.addLayer(o)}),n={...s,name:t,brushes:r,context:this.#i.get(s.context)};if(this.#e.set(t,n),(d=n.lifecycle)!=null&&d.onMount)try{n.lifecycle.onMount(n.context)}catch(o){console.error(`Error in layer "${t}" onMount:`,o)}return n}removeLayer(e){var r;let t=this.#e.get(e);if(!t)return;if((r=t.lifecycle)!=null&&r.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(n){console.error(`Error in layer "${e}" onUnmount:`,n)}t.brushes.forEach(n=>{var o;if((o=n.lifecycle)!=null&&o.onUnmount)try{n.lifecycle.onUnmount(this.#i.get(n.context||t.context))}catch(y){console.error(`Error in brush "${n.name}" onUnmount:`,y)}let d=this.#a.get(`painter_brush_${n.name}`);d&&(d.unsubscribe(),d.reactor.destroy(),this.#a.delete(`painter_brush_${n.name}`))});let s=this.#a.get(`painter_layer_${e}`);s&&(s.unsubscribe(),s.reactor.destroy(),this.#a.delete(`painter_layer_${e}`)),this.#e.delete(e)}#p(){this.#m||this.#b||(this.#m=!0,this.#h=requestAnimationFrame(()=>{this.#m=!1,this.#h=null,this.#T()}))}async#T(){var e,t,s,r,n,d,o,y,g,p,l,f,m,C,O,X,$;if(this.#s){this.#b=!0;try{this.#u.clear();let U=(e=this.#t.debug)!=null&&e.enabled?performance.now():0;this.#i.forEach(h=>{h.clearRect(0,0,this.#s.width,this.#s.height)});for(let h of this.#e.values()){let P=(t=this.#t.debug)!=null&&t.enabled?performance.now():0;if(h.whenReactor){let a=(s=this.#a.get(`painter_layer_${h.name}`))==null?void 0:s.reactor;if(!h.when(a()))continue}let E=h.context;if(E){if((r=h.lifecycle)!=null&&r.beforeRender)try{h.lifecycle.beforeRender(E,this.#o)}catch(a){console.error(`Error in layer "${h.name}" beforeRender:`,a),(n=h.lifecycle)!=null&&n.onError&&h.lifecycle.onError(a)}E.save(),h.settings&&Object.entries(h.settings).forEach(([a,T])=>{typeof E[a]=="function"?E[a](...Array.isArray(T)?T:[T]):E[a]=T});for(let a of h.brushes){let T=(d=this.#t.debug)!=null&&d.enabled?performance.now():0;if(a.whenReactor&&!a.whenReactor())continue;let S=a.context?this.#i.get(a.context):E;if(S){if((o=a.lifecycle)!=null&&o.beforeRender)try{a.lifecycle.beforeRender(S,this.#o)}catch(x){console.error(`Error in brush "${a.name}" beforeRender:`,x),(y=a.lifecycle)!=null&&y.onError&&a.lifecycle.onError(x);continue}S.save(),a.settings&&Object.entries(a.settings).forEach(([x,R])=>{typeof S[x]=="function"?S[x](...Array.isArray(R)?R:[R]):S[x]=R});try{let x={};if(a.assets)for(let R of a.assets)x[R]=this.#f.get(R);if(a.render(S,a.dataReactor(),x,this.#o),(g=a.lifecycle)!=null&&g.afterRender&&a.lifecycle.afterRender(S,this.#o),(p=this.#t.debug)!=null&&p.enabled){let R=performance.now()-T;this.#d.brushTimes.set(a.name,R),(l=this.#t.debug)!=null&&l.showBounds&&this.#S(S,a)}}catch(x){console.error(`Error in brush "${a.name}":`,x),(f=a.lifecycle)!=null&&f.onError&&a.lifecycle.onError(x)}finally{S.restore()}}}if(E.restore(),(m=h.lifecycle)!=null&&m.afterRender)try{h.lifecycle.afterRender(E,this.#o)}catch(a){console.error(`Error in layer "${h.name}" afterRender:`,a),(C=h.lifecycle)!=null&&C.onError&&h.lifecycle.onError(a)}if((O=this.#t.debug)!=null&&O.enabled){let a=performance.now()-P;this.#d.layerTimes.set(h.name,a),(X=this.#t.debug)!=null&&X.showBounds&&this.#C(E,h)}}}($=this.#t.debug)!=null&&$.enabled&&this.#R()}finally{this.#b=!1}}}#S(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()}#C(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()}#R(){var r,n;let e=this.#i.get(V["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((r=this.#t.debug)!=null&&r.showFPS){let d=`FPS: ${Math.round(this.#d.fps)} (${this.#o.deltaTime.toFixed(2)}ms)`;e.strokeText(d,10,t),e.fillText(d,10,t),t+=s}if((n=this.#t.debug)!=null&&n.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[d,o]of this.#d.layerTimes){let y=` ${d}: ${o.toFixed(2)}ms`;e.strokeText(y,10,t),e.fillText(y,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){var s,r;for(let n of this.#e.values())if((s=n.lifecycle)!=null&&s.onResize)try{n.lifecycle.onResize(e,t,n.context)}catch(d){console.error(`Error in layer "${n.name}" onResize:`,d),(r=n.lifecycle)!=null&&r.onError&&n.lifecycle.onError(d)}}#x(e,t){let s=this.useContext("state"),r=(0,z.createReactor)(t,{immediate:!0,context:s}),n=(0,z.addEffect)(r,()=>this.#p());return this.#a.set(`painter_${e}`,{reactor:r,unsubscribe:n}),r}destroy(){this.stop(),this.#r&&(this.#r(),this.#r=null),this.#n&&(this.#n.destroy(),this.#n=null),this.#c&&this.#c.$destroy();for(let e of this.#e.keys())this.removeLayer(e)}setTargetFPS(e){this.#t.targetFPS=e,this.#t.fixedTimeStep=1e3/e}setTimeScale(e){this.#t.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#t.fixedTimeStep=e}setDebug(e={}){this.#t.debug||(this.#t.debug={}),Object.assign(this.#t.debug,e)}getMetrics(){return{...this.#d,deltaTime:this.#o.deltaTime,elapsedTime:this.#o.elapsedTime,frameCount:this.#o.frameCount}}handlePointerEvent(e){this.#c.handleEvent(e),this.#w(e)}#w(e){var d,o,y,g,p;let{type:t,x:s,y:r}=e,n=this.#c;switch(t){case"down":{let l=this.#E(s,r);if(n.setActiveArea(l),(d=l==null?void 0:l.onPointerDown)!=null&&d.handler){let f=this.#g(l);l.onPointerDown.handler({...n.state,ctx:f,emit:this.#v.bind(this)})}break}case"up":{let l=n.activeArea;if((o=l==null?void 0:l.onPointerUp)!=null&&o.handler){let f=this.#g(l);l.onPointerUp.handler({...n.state,ctx:f,emit:this.#v.bind(this)})}break}case"move":{let l=this.#E(s,r),f=n.hoveredArea,m=n.activeArea;if((y=m==null?void 0:m.onPointerMove)!=null&&y.handler&&n.isDragging){let C=this.#g(m);m.onPointerMove.handler({...n.state,ctx:C,emit:this.#v.bind(this)})}if((l==null?void 0:l.id)!==(f==null?void 0:f.id)){if((g=f==null?void 0:f.onPointerLeave)!=null&&g.handler){let C=this.#g(f);f.onPointerLeave.handler({...n.state,ctx:C,emit:this.#v.bind(this)})}if((p=l==null?void 0:l.onPointerEnter)!=null&&p.handler){let C=this.#g(l);l.onPointerEnter.handler({...n.state,ctx:C,emit:this.#v.bind(this)})}n.setHoveredArea(l)}break}case"scroll":case"zoom":this.#v(`pointer:${t}`,n.state);break;case"dblclick":this.#v("pointer:dblclick",n.state);break}}#g(e){return e?e.context?this.#i.get(e.context):this.#i.get(V["2D"]):null}subscribe(e,t){return this.#y.has(e)||this.#y.set(e,new Set),this.#y.get(e).add(t),()=>{let s=this.#y.get(e);s&&(s.delete(t),s.size===0&&this.#y.delete(e))}}#E(e,t){let s=this.#u.areas.sort((r,n)=>(n.priority||0)-(r.priority||0));for(let r of s)if(this.#P(e,t,r.bounds))return r;return null}#P(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#v(e,t){let s=this.#y.get(e);if(s)for(let r of s)r(t)}_testEmitPointerEvent(e){this.#c.handleEvent(e),this.#w(e)}};0&&(module.exports={CanvasEvents,HitRegistry,Painter,defineBrush,defineLayer,usePointerSurface});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/main.js", "../src/Painter.js", "../src/ContextTypes.js", "../src/HitRegistry.js", "../src/
|
|
4
|
-
"sourcesContent": ["export { Painter, defineLayer, defineBrush } from './Painter';\nexport { HitRegistry } from './HitRegistry';\nexport { CanvasPointer } from './CanvasPointer';\nexport { usePointerSurface } from './usePointerSurface';", "import { ServiceProvider } from '@jucie-engine/core';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createReactor, addEffect } from '@jucie-state/reactive';\nimport { createDefinition, definitionType } from '@jucie-engine/core';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasPointer } from './CanvasPointer.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nexport const defineBrush = createDefinition('BRUSH', [Object]);\nexport const defineLayer = createDefinition('LAYER', [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #canvas = null;\n #contexts = new Map();\n #reactors = 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 #canvasPointer = null;\n #pointerSurface = usePointerSurface();\n #pointerUnsubscribe = null;\n #subscribers = new Map(); // Map<event, Set<callback>>\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.state,\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 updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\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\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 setCanvas(canvas) {\n this.#canvas = canvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = canvas.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 // Set up canvas pointer if not already\n if (!this.#canvasPointer) {\n this.#canvasPointer = new CanvasPointer();\n }\n\n this.#canvasPointer.setCanvas(canvas);\n\n // Connect canvas pointer to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasPointer.subscribe((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 }\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 // Set up layer reactor if it has data paths\n if (config.data) {\n const dataReactor = this.#createDataReactor(`layer_${name}`, config.data);\n if (dataReactor) {\n this.#reactors.set(`layer_${name}`, dataReactor);\n }\n }\n\n // Set up brush reactors and structure\n const brushes = config.children.map(child => {\n if (definitionType(child) === 'BRUSH') {\n const name = child._name;\n const brushConfig = child(this.useContext, this.#hitRegistry);\n \n // Only create data reactor if data exists\n const dataReactor = brushConfig.data \n ? this.#createDataReactor(`brush_${name}`, brushConfig.data)\n : () => undefined;\n \n const whenReactor = brushConfig.when \n ? createReactor(brushConfig.when, {\n immediate: true,\n context: this.useContext('state')\n })\n : null;\n\n const brush = {\n name,\n ...brushConfig,\n dataReactor,\n whenReactor\n };\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || config.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n return brush;\n }\n // Handle nested layers recursively\n return this.addLayer(child);\n });\n\n const layer = {\n ...config,\n name,\n brushes,\n context: this.#contexts.get(config.context)\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 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 // Call brush unmount hooks and clean up reactors\n layer.brushes.forEach(brush => {\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 reactor and subscription\n const reactorData = this.#reactors.get(`painter_brush_${brush.name}`);\n if (reactorData) {\n reactorData.unsubscribe();\n reactorData.reactor.destroy();\n this.#reactors.delete(`painter_brush_${brush.name}`);\n }\n });\n\n // Clean up layer reactor and subscription\n const layerReactorData = this.#reactors.get(`painter_layer_${name}`);\n if (layerReactorData) {\n layerReactorData.unsubscribe();\n layerReactorData.reactor.destroy();\n this.#reactors.delete(`painter_layer_${name}`);\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) {\n const layerReactor = this.#reactors.get(`painter_layer_${layer.name}`)?.reactor;\n if (!layer.when(layerReactor())) continue;\n }\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 // Render brushes\n for (const brush of layer.brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor()) 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(), 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 #createDataReactor(id, data) {\n const state = this.useContext('state');\n\n const reactor = createReactor(data, {\n immediate: true,\n context: state\n });\n\n const unsubscribe = addEffect(reactor, () => this.#scheduleRender());\n\n this.#reactors.set(`painter_${id}`, {\n reactor,\n unsubscribe\n });\n\n return reactor;\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.#canvasPointer) {\n this.#canvasPointer.destroy();\n this.#canvasPointer = 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 #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 ...pointer.state,\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 ...pointer.state,\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 drag on active area\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerMove?.handler && pointer.isDragging) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerMove.handler({\n ...pointer.state,\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 ...pointer.state,\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 ...pointer.state,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'scroll':\n case 'zoom':\n // Emit custom events for scroll/zoom\n this.#emit(`pointer:${type}`, pointer.state);\n break;\n\n case 'dblclick':\n // Emit double-click event\n this.#emit('pointer:dblclick', pointer.state);\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}", "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-engine/core';\n\nexport class CanvasPointer extends ServiceProvider {\n #canvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n\n static manifest = {\n name: 'CanvasPointer',\n namespace: 'canvasPointer',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n getOffscreenCanvas: () => this.getOffscreenCanvas(),\n };\n }\n\n getOffscreenCanvas() {\n if (!this.#canvas) return null;\n return this.#canvas.transferControlToOffscreen();\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 #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(() => {\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n document.addEventListener('wheel', this.#handleScroll, { passive: false });\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerdown', this.#handleDown);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleUp);\n document.addEventListener('dblclick', this.#handleDblClick);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n document.removeEventListener('wheel', this.#handleScroll);\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerdown', this.#handleDown);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleUp);\n document.removeEventListener('dblclick', this.#handleDblClick);\n }\n\n #handleScroll = (event) => {\n if (event.target !== this.#canvas) {\n return;\n }\n\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 const normalized = this.#normalizeEvent(event, 'move');\n \n // Store latest move and throttle with RAF\n this.#pendingMove = normalized;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n this.#emit(this.#pendingMove);\n this.#pendingMove = null;\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n // Only capture if starting on canvas\n if (event.target === this.#canvas) {\n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n }\n\n #handleUp = (event) => {\n // Use the actual up event position, not pending move\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\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 #normalizeEvent(event, type) {\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 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 const normalized = {\n x,\n y,\n type,\n isOverCanvas,\n isWithinBounds,\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button ?? null,\n buttons: event.buttons ?? 0,\n timestamp: Date.now()\n };\n\n // Add wheel-specific data for scroll/zoom\n if (type === 'scroll' || type === 'zoom') {\n normalized.deltaX = event.deltaX;\n normalized.deltaY = event.deltaY;\n normalized.deltaZ = event.deltaZ;\n normalized.deltaMode = event.deltaMode;\n }\n\n // Add modifier keys\n normalized.shiftKey = event.shiftKey || false;\n normalized.ctrlKey = event.ctrlKey || false;\n normalized.altKey = event.altKey || false;\n normalized.metaKey = event.metaKey || false;\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.#cachedRect = null;\n this.#subscribers.clear();\n }\n}\n", "import { defineSurface } from '@jucie-state/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // ============= Core State =============\n \n // Position (canvas coordinates)\n const x = setup.value(0);\n const y = setup.value(0);\n const prevX = setup.value(0);\n const prevY = setup.value(0);\n \n // Client position (screen coordinates)\n const clientX = setup.value(0);\n const clientY = setup.value(0);\n \n // Canvas boundary state\n const isOverCanvas = setup.value(false);\n const isWithinBounds = setup.value(false);\n \n // Button state\n const isPressed = setup.value(false);\n const button = setup.value(null); // 0=left, 1=middle, 2=right\n const buttons = setup.value(0); // Bitmask of pressed buttons\n \n // Event type tracking\n const lastEventType = setup.value(null);\n \n // Timing\n const downTime = setup.value(null);\n const upTime = setup.value(null);\n const lastMoveTime = setup.value(null);\n const lastEventTime = setup.value(null);\n \n // Drag state\n const dragStartX = setup.value(null);\n const dragStartY = setup.value(null);\n const isDragging = setup.value(false);\n \n // Click detection\n const clickCount = setup.value(0);\n const lastClickTime = setup.value(0);\n \n // Velocity tracking\n const velocityX = setup.value(0);\n const velocityY = setup.value(0);\n \n // Scroll/Zoom state\n const lastScrollDeltaX = setup.value(0);\n const lastScrollDeltaY = setup.value(0);\n const lastZoomDelta = setup.value(0);\n \n // Hit areas (from HitRegistry)\n const hoveredArea = setup.value(null);\n const activeArea = setup.value(null);\n \n // ============= Configuration =============\n const config = setup.value({\n dragThreshold: 5,\n doubleClickThreshold: 300,\n holdThreshold: 500,\n velocitySmoothing: 0.3,\n maxVelocity: 10000 // Clamp unrealistic velocities\n });\n \n // ============= Computed Values =============\n \n const position = setup.computed(() => ({\n x: x.value,\n y: y.value\n }));\n \n const clientPosition = setup.computed(() => ({\n x: clientX.value,\n y: clientY.value\n }));\n \n const previousPosition = setup.computed(() => ({\n x: prevX.value,\n y: prevY.value\n }));\n \n const delta = setup.computed(() => {\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const prevXVal = typeof prevX.value === 'number' ? prevX.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const prevYVal = typeof prevY.value === 'number' ? prevY.value : 0;\n return {\n x: xVal - prevXVal,\n y: yVal - prevYVal\n };\n });\n \n const velocity = setup.computed(() => ({\n x: velocityX.value,\n y: velocityY.value\n }));\n \n const speed = setup.computed(() => {\n const vx = velocityX.value;\n const vy = velocityY.value;\n return Math.sqrt(vx * vx + vy * vy);\n });\n \n const dragDistance = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') return 0;\n \n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const dx = xVal - startX;\n const dy = yVal - startY;\n return Math.sqrt(dx * dx + dy * dy);\n });\n \n const dragDelta = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') {\n return { x: 0, y: 0 };\n }\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n return {\n x: xVal - startX,\n y: yVal - startY\n };\n });\n \n const holdDuration = setup.computed(() => {\n if (!isPressed.value || !downTime.value) return 0;\n return Date.now() - downTime.value;\n });\n \n const isHolding = setup.computed(() => {\n return holdDuration.value > config.value.holdThreshold && !isDragging.value;\n });\n \n const timeSinceLastEvent = setup.computed(() => {\n const lastTime = lastEventTime.value;\n return lastTime ? Date.now() - lastTime : 0;\n });\n \n // Full state snapshot\n const state = setup.computed(() => ({\n position: position.value,\n clientPosition: clientPosition.value,\n previousPosition: previousPosition.value,\n delta: delta.value,\n velocity: velocity.value,\n speed: speed.value,\n isPressed: isPressed.value,\n button: button.value,\n buttons: buttons.value,\n isDragging: isDragging.value,\n dragDistance: dragDistance.value,\n dragDelta: dragDelta.value,\n isHolding: isHolding.value,\n holdDuration: holdDuration.value,\n isOverCanvas: isOverCanvas.value,\n isWithinBounds: isWithinBounds.value,\n hoveredArea: hoveredArea.value,\n activeArea: activeArea.value,\n clickCount: clickCount.value,\n lastEventType: lastEventType.value\n }));\n \n // ============= Actions =============\n \n const updatePosition = setup.action((ctx, newX, newY, newClientX, newClientY) => {\n prevX.value = x.value;\n prevY.value = y.value;\n x.value = newX;\n y.value = newY;\n clientX.value = newClientX;\n clientY.value = newClientY;\n lastMoveTime.value = Date.now();\n });\n \n const updateVelocity = setup.action(() => {\n const now = Date.now();\n const lastMove = lastMoveTime.value;\n \n if (lastMove) {\n const dt = (now - lastMove) / 1000;\n if (dt > 0 && dt < 0.1) {\n const newVx = (x.value - prevX.value) / dt;\n const newVy = (y.value - prevY.value) / dt;\n \n // Clamp unrealistic velocities\n const maxVel = config.value.maxVelocity;\n const clampedVx = Math.max(-maxVel, Math.min(maxVel, newVx));\n const clampedVy = Math.max(-maxVel, Math.min(maxVel, newVy));\n \n // Apply smoothing\n const smoothing = config.value.velocitySmoothing;\n velocityX.value = velocityX.value * (1 - smoothing) + clampedVx * smoothing;\n velocityY.value = velocityY.value * (1 - smoothing) + clampedVy * smoothing;\n }\n }\n });\n \n // Main event handler - consumes normalized events from CanvasPointer\n const handleEvent = setup.action((ctx, normalizedEvent) => {\n const { x: newX, y: newY, type, clientX: newClientX, clientY: newClientY, button: eventButton, buttons: eventButtons, isOverCanvas: eventIsOverCanvas, isWithinBounds: eventIsWithinBounds } = normalizedEvent;\n const now = Date.now();\n \n lastEventTime.value = now;\n lastEventType.value = type;\n isOverCanvas.value = eventIsOverCanvas;\n isWithinBounds.value = eventIsWithinBounds;\n \n switch (type) {\n case 'down':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = true;\n downTime.value = now;\n button.value = eventButton;\n buttons.value = eventButtons;\n dragStartX.value = newX;\n dragStartY.value = newY;\n isDragging.value = false;\n \n // Double-click detection\n const timeSinceLastClick = now - lastClickTime.value;\n if (timeSinceLastClick < config.value.doubleClickThreshold) {\n clickCount.value = clickCount.value + 1;\n } else {\n clickCount.value = 1;\n }\n break;\n \n case 'up':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = false;\n upTime.value = now;\n lastClickTime.value = now;\n isDragging.value = false;\n velocityX.value = 0;\n velocityY.value = 0;\n buttons.value = eventButtons;\n break;\n \n case 'move':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n updateVelocity();\n buttons.value = eventButtons;\n \n // Check for drag start\n if (isPressed.value && !isDragging.value) {\n const distance = dragDistance.value;\n if (distance > config.value.dragThreshold) {\n isDragging.value = true;\n }\n }\n break;\n \n case 'dblclick':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n clickCount.value = 2;\n break;\n \n case 'scroll':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n // Extract wheel delta from event if available\n if (normalizedEvent.deltaX !== undefined) {\n lastScrollDeltaX.value = normalizedEvent.deltaX;\n }\n if (normalizedEvent.deltaY !== undefined) {\n lastScrollDeltaY.value = normalizedEvent.deltaY;\n }\n break;\n \n case 'zoom':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n if (normalizedEvent.deltaY !== undefined) {\n lastZoomDelta.value = normalizedEvent.deltaY;\n }\n break;\n }\n });\n \n const setHoveredArea = setup.action((ctx, area) => {\n hoveredArea.value = area;\n });\n \n const setActiveArea = setup.action((ctx, area) => {\n activeArea.value = area;\n });\n \n const reset = setup.action(() => {\n isPressed.value = false;\n isDragging.value = false;\n activeArea.value = null;\n hoveredArea.value = null;\n velocityX.value = 0;\n velocityY.value = 0;\n clickCount.value = 0;\n lastScrollDeltaX.value = 0;\n lastScrollDeltaY.value = 0;\n lastZoomDelta.value = 0;\n });\n \n const updateConfig = setup.action((ctx, updates) => {\n config.value = { ...config.value, ...updates };\n });\n \n // ============= Return Public API =============\n return {\n // State (read-only through computed)\n state,\n position,\n clientPosition,\n previousPosition,\n delta,\n velocity,\n speed,\n isPressed,\n button,\n buttons,\n isDragging,\n dragDistance,\n dragDelta,\n isHolding,\n holdDuration,\n isOverCanvas,\n isWithinBounds,\n hoveredArea,\n activeArea,\n clickCount,\n lastEventType,\n timeSinceLastEvent,\n \n // Actions\n handleEvent, // Main entry point for normalized events\n setHoveredArea,\n setActiveArea,\n reset,\n updateConfig\n };\n});\n"],
|
|
5
|
-
"mappings": "saAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,mBAAAE,EAAA,gBAAAC,EAAA,YAAAC,EAAA,gBAAAC,GAAA,gBAAAC,GAAA,sBAAAC,IAAA,eAAAC,GAAAR,ICAA,IAAAS,GAAgC,8BCAzB,IAAMC,EAAe,CAC1B,KAAM,KACN,MAAS,QACT,OAAU,SACV,eAAkB,gBACpB,EDHA,IAAAC,EAAyC,iCACzCC,EAAiD,8BEH1C,IAAMC,EAAN,KAAkB,CACvBC,GAAS,IAAI,IAEb,SAASC,EAAIC,EAAM,CACjB,GAAI,CAACD,EACH,MAAM,IAAI,MAAM,0BAA0B,EAE5C,YAAKD,GAAO,IAAIC,EAAI,CAAE,GAAAA,EAAI,GAAGC,CAAK,CAAC,EAC5B,IAAM,KAAK,WAAWD,CAAE,CACjC,CAEA,WAAWA,EAAI,CACb,KAAKD,GAAO,OAAOC,CAAE,CACvB,CAEA,IAAIA,EAAI,CACN,OAAO,KAAKD,GAAO,IAAIC,CAAE,CAC3B,CAEA,IAAIA,EAAI,CACN,OAAO,KAAKD,GAAO,IAAIC,CAAE,CAC3B,CAEA,IAAI,OAAQ,CACV,OAAO,MAAM,KAAK,KAAKD,GAAO,OAAO,CAAC,CACxC,CAEA,OAAQ,CACN,KAAKA,GAAO,MAAM,CACpB,CACF,EC9BA,IAAAG,GAAgC,8BAEnBC,EAAN,cAA4B,kBAAgB,CACjDC,GAAU,KACVC,GAAc,KACdC,GAAkB,KAClBC,GAAe,IAAI,IACnBC,GAAe,KACfC,GAAS,KAET,OAAO,SAAW,CAChB,KAAM,gBACN,UAAW,gBACX,QAAS,OACX,EAEA,SAAU,CACR,MAAO,CACL,UAAYC,GAAW,KAAK,UAAUA,CAAM,EAC5C,UAAYC,GAAa,KAAK,UAAUA,CAAQ,EAChD,mBAAoB,IAAM,KAAK,mBAAmB,CACpD,CACF,CAEA,oBAAqB,CACnB,OAAK,KAAKP,GACH,KAAKA,GAAQ,2BAA2B,EADrB,IAE5B,CAEA,UAAUM,EAAQ,CACZ,KAAKN,IACP,KAAKQ,GAAiB,EAGxB,KAAKR,GAAUM,EACf,KAAKG,GAAkB,EACvB,KAAKC,GAAqB,CAC5B,CAEA,UAAUC,EAAY,CACpB,YAAKR,GAAa,IAAIQ,CAAU,EACzB,IAAM,KAAKR,GAAa,OAAOQ,CAAU,CAClD,CAEAF,IAAoB,CACd,KAAKT,KACP,KAAKC,GAAc,KAAKD,GAAQ,sBAAsB,EAE1D,CAEAU,IAAuB,CAChB,KAAKV,KAEV,KAAKS,GAAkB,EAEvB,KAAKP,GAAkB,IAAI,eAAe,IAAM,CAC9C,KAAKO,GAAkB,CACzB,CAAC,EACD,KAAKP,GAAgB,QAAQ,KAAKF,EAAO,EAEzC,SAAS,iBAAiB,QAAS,KAAKY,GAAe,CAAE,QAAS,EAAM,CAAC,EACzE,SAAS,iBAAiB,cAAe,KAAKC,EAAW,EACzD,SAAS,iBAAiB,cAAe,KAAKC,EAAW,EACzD,SAAS,iBAAiB,YAAa,KAAKC,EAAS,EACrD,SAAS,iBAAiB,gBAAiB,KAAKA,EAAS,EACzD,SAAS,iBAAiB,WAAY,KAAKC,EAAe,EAC5D,CAEAR,IAAmB,CACb,KAAKN,KACP,KAAKA,GAAgB,WAAW,EAChC,KAAKA,GAAkB,MAGzB,SAAS,oBAAoB,QAAS,KAAKU,EAAa,EACxD,SAAS,oBAAoB,cAAe,KAAKC,EAAW,EAC5D,SAAS,oBAAoB,cAAe,KAAKC,EAAW,EAC5D,SAAS,oBAAoB,YAAa,KAAKC,EAAS,EACxD,SAAS,oBAAoB,gBAAiB,KAAKA,EAAS,EAC5D,SAAS,oBAAoB,WAAY,KAAKC,EAAe,CAC/D,CAEAJ,GAAiBK,GAAU,CACzB,GAAIA,EAAM,SAAW,KAAKjB,GAO1B,GAHAiB,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EAElBA,EAAM,QAAS,CACjB,IAAMC,EAAa,KAAKC,GAAgBF,EAAO,MAAM,EACrD,KAAKG,GAAMF,CAAU,CACvB,KAAO,CACL,IAAMA,EAAa,KAAKC,GAAgBF,EAAO,QAAQ,EACvD,KAAKG,GAAMF,CAAU,CACvB,CACF,EAEAL,GAAeI,GAAU,CACvB,IAAMC,EAAa,KAAKC,GAAgBF,EAAO,MAAM,EAGrD,KAAKb,GAAec,EAChB,MAAKb,KAET,KAAKA,GAAS,sBAAsB,IAAM,CACpC,KAAKD,KACP,KAAKgB,GAAM,KAAKhB,EAAY,EAC5B,KAAKA,GAAe,MAEtB,KAAKC,GAAS,IAChB,CAAC,EACH,EAEAS,GAAeG,GAAU,CAEvB,GAAIA,EAAM,SAAW,KAAKjB,GAAS,CACjC,IAAMkB,EAAa,KAAKC,GAAgBF,EAAO,MAAM,EACrD,KAAKG,GAAMF,CAAU,CACvB,CACF,EAEAH,GAAaE,GAAU,CAErB,IAAMC,EAAa,KAAKC,GAAgBF,EAAO,IAAI,EACnD,KAAKG,GAAMF,CAAU,CACvB,EAEAF,GAAmBC,GAAU,CAC3B,IAAMC,EAAa,KAAKC,GAAgBF,EAAO,UAAU,EACzD,KAAKG,GAAMF,CAAU,CACvB,EAEAE,GAAMH,EAAO,CACX,QAAWN,KAAc,KAAKR,GAC5BQ,EAAWM,CAAK,CAEpB,CAEAE,GAAgBF,EAAOI,EAAM,CAC3B,IAAMC,EAAeL,EAAM,SAAW,KAAKjB,GAEvCuB,EAAGC,EACHF,GACFC,EAAIN,EAAM,QACVO,EAAIP,EAAM,SACD,KAAKhB,IACdsB,EAAIN,EAAM,QAAU,KAAKhB,GAAY,KACrCuB,EAAIP,EAAM,QAAU,KAAKhB,GAAY,MAErCsB,EAAIN,EAAM,QACVO,EAAIP,EAAM,SAGZ,IAAMQ,EAAiBH,GACrB,KAAKrB,IACLsB,GAAK,GACLA,GAAK,KAAKtB,GAAY,OACtBuB,GAAK,GACLA,GAAK,KAAKvB,GAAY,OAGlBiB,EAAa,CACjB,EAAAK,EACA,EAAAC,EACA,KAAAH,EACA,aAAAC,EACA,eAAAG,EACA,QAASR,EAAM,QACf,QAASA,EAAM,QACf,OAAQA,EAAM,QAAU,KACxB,QAASA,EAAM,SAAW,EAC1B,UAAW,KAAK,IAAI,CACtB,EAGA,OAAII,IAAS,UAAYA,IAAS,UAChCH,EAAW,OAASD,EAAM,OAC1BC,EAAW,OAASD,EAAM,OAC1BC,EAAW,OAASD,EAAM,OAC1BC,EAAW,UAAYD,EAAM,WAI/BC,EAAW,SAAWD,EAAM,UAAY,GACxCC,EAAW,QAAUD,EAAM,SAAW,GACtCC,EAAW,OAASD,EAAM,QAAU,GACpCC,EAAW,QAAUD,EAAM,SAAW,GAE/BC,CACT,CAEA,SAAU,CACJ,KAAKb,KACP,qBAAqB,KAAKA,EAAM,EAChC,KAAKA,GAAS,MAEhB,KAAKG,GAAiB,EACtB,KAAKR,GAAU,KACf,KAAKC,GAAc,KACnB,KAAKE,GAAa,MAAM,CAC1B,CACF,EC3MA,IAAAuB,GAA8B,iCAEjBC,KAAoB,kBAAeC,GAAU,CAIxD,IAAMC,EAAID,EAAM,MAAM,CAAC,EACjBE,EAAIF,EAAM,MAAM,CAAC,EACjBG,EAAQH,EAAM,MAAM,CAAC,EACrBI,EAAQJ,EAAM,MAAM,CAAC,EAGrBK,EAAUL,EAAM,MAAM,CAAC,EACvBM,EAAUN,EAAM,MAAM,CAAC,EAGvBO,EAAeP,EAAM,MAAM,EAAK,EAChCQ,EAAiBR,EAAM,MAAM,EAAK,EAGlCS,EAAYT,EAAM,MAAM,EAAK,EAC7BU,EAASV,EAAM,MAAM,IAAI,EACzBW,EAAUX,EAAM,MAAM,CAAC,EAGvBY,EAAgBZ,EAAM,MAAM,IAAI,EAGhCa,EAAWb,EAAM,MAAM,IAAI,EAC3Bc,EAASd,EAAM,MAAM,IAAI,EACzBe,EAAef,EAAM,MAAM,IAAI,EAC/BgB,EAAgBhB,EAAM,MAAM,IAAI,EAGhCiB,EAAajB,EAAM,MAAM,IAAI,EAC7BkB,EAAalB,EAAM,MAAM,IAAI,EAC7BmB,EAAanB,EAAM,MAAM,EAAK,EAG9BoB,EAAapB,EAAM,MAAM,CAAC,EAC1BqB,EAAgBrB,EAAM,MAAM,CAAC,EAG7BsB,EAAYtB,EAAM,MAAM,CAAC,EACzBuB,EAAYvB,EAAM,MAAM,CAAC,EAGzBwB,EAAmBxB,EAAM,MAAM,CAAC,EAChCyB,EAAmBzB,EAAM,MAAM,CAAC,EAChC0B,EAAgB1B,EAAM,MAAM,CAAC,EAG7B2B,EAAc3B,EAAM,MAAM,IAAI,EAC9B4B,EAAa5B,EAAM,MAAM,IAAI,EAG7B6B,EAAS7B,EAAM,MAAM,CACzB,cAAe,EACf,qBAAsB,IACtB,cAAe,IACf,kBAAmB,GACnB,YAAa,GACf,CAAC,EAIK8B,EAAW9B,EAAM,SAAS,KAAO,CACrC,EAAGC,EAAE,MACL,EAAGC,EAAE,KACP,EAAE,EAEI6B,EAAiB/B,EAAM,SAAS,KAAO,CAC3C,EAAGK,EAAQ,MACX,EAAGC,EAAQ,KACb,EAAE,EAEI0B,EAAmBhC,EAAM,SAAS,KAAO,CAC7C,EAAGG,EAAM,MACT,EAAGC,EAAM,KACX,EAAE,EAEI6B,GAAQjC,EAAM,SAAS,IAAM,CACjC,IAAMkC,EAAO,OAAOjC,EAAE,OAAU,SAAWA,EAAE,MAAQ,EAC/CkC,EAAW,OAAOhC,EAAM,OAAU,SAAWA,EAAM,MAAQ,EAC3DiC,EAAO,OAAOlC,EAAE,OAAU,SAAWA,EAAE,MAAQ,EAC/CmC,EAAW,OAAOjC,EAAM,OAAU,SAAWA,EAAM,MAAQ,EACjE,MAAO,CACL,EAAG8B,EAAOC,EACV,EAAGC,EAAOC,CACZ,CACF,CAAC,EAEKC,GAAWtC,EAAM,SAAS,KAAO,CACrC,EAAGsB,EAAU,MACb,EAAGC,EAAU,KACf,EAAE,EAEIgB,GAAQvC,EAAM,SAAS,IAAM,CACjC,IAAMwC,EAAKlB,EAAU,MACfmB,EAAKlB,EAAU,MACrB,OAAO,KAAK,KAAKiB,EAAKA,EAAKC,EAAKA,CAAE,CACpC,CAAC,EAEKC,EAAe1C,EAAM,SAAS,IAAM,CACxC,IAAM2C,EAAS1B,EAAW,MACpB2B,EAAS1B,EAAW,MAC1B,GAAIyB,IAAW,MAAQC,IAAW,MAAQ,OAAOD,GAAW,UAAY,OAAOC,GAAW,SAAU,MAAO,GAE3G,IAAMV,EAAO,OAAOjC,EAAE,OAAU,SAAWA,EAAE,MAAQ,EAC/CmC,EAAO,OAAOlC,EAAE,OAAU,SAAWA,EAAE,MAAQ,EAC/C2C,EAAKX,EAAOS,EACZG,EAAKV,EAAOQ,EAClB,OAAO,KAAK,KAAKC,EAAKA,EAAKC,EAAKA,CAAE,CACpC,CAAC,EAEKC,GAAY/C,EAAM,SAAS,IAAM,CACrC,IAAM2C,EAAS1B,EAAW,MACpB2B,EAAS1B,EAAW,MAC1B,GAAIyB,IAAW,MAAQC,IAAW,MAAQ,OAAOD,GAAW,UAAY,OAAOC,GAAW,SACxF,MAAO,CAAE,EAAG,EAAG,EAAG,CAAE,EAEtB,IAAMV,EAAO,OAAOjC,EAAE,OAAU,SAAWA,EAAE,MAAQ,EAC/CmC,EAAO,OAAOlC,EAAE,OAAU,SAAWA,EAAE,MAAQ,EACrD,MAAO,CACL,EAAGgC,EAAOS,EACV,EAAGP,EAAOQ,CACZ,CACF,CAAC,EAEKI,EAAehD,EAAM,SAAS,IAC9B,CAACS,EAAU,OAAS,CAACI,EAAS,MAAc,EACzC,KAAK,IAAI,EAAIA,EAAS,KAC9B,EAEKoC,GAAYjD,EAAM,SAAS,IACxBgD,EAAa,MAAQnB,EAAO,MAAM,eAAiB,CAACV,EAAW,KACvE,EAEK+B,GAAqBlD,EAAM,SAAS,IAAM,CAC9C,IAAMmD,EAAWnC,EAAc,MAC/B,OAAOmC,EAAW,KAAK,IAAI,EAAIA,EAAW,CAC5C,CAAC,EAGKC,GAAQpD,EAAM,SAAS,KAAO,CAClC,SAAU8B,EAAS,MACnB,eAAgBC,EAAe,MAC/B,iBAAkBC,EAAiB,MACnC,MAAOC,GAAM,MACb,SAAUK,GAAS,MACnB,MAAOC,GAAM,MACb,UAAW9B,EAAU,MACrB,OAAQC,EAAO,MACf,QAASC,EAAQ,MACjB,WAAYQ,EAAW,MACvB,aAAcuB,EAAa,MAC3B,UAAWK,GAAU,MACrB,UAAWE,GAAU,MACrB,aAAcD,EAAa,MAC3B,aAAczC,EAAa,MAC3B,eAAgBC,EAAe,MAC/B,YAAamB,EAAY,MACzB,WAAYC,EAAW,MACvB,WAAYR,EAAW,MACvB,cAAeR,EAAc,KAC/B,EAAE,EAIIyC,EAAiBrD,EAAM,OAAO,CAACsD,EAAKC,EAAMC,EAAMC,EAAYC,IAAe,CAC/EvD,EAAM,MAAQF,EAAE,MAChBG,EAAM,MAAQF,EAAE,MAChBD,EAAE,MAAQsD,EACVrD,EAAE,MAAQsD,EACVnD,EAAQ,MAAQoD,EAChBnD,EAAQ,MAAQoD,EAChB3C,EAAa,MAAQ,KAAK,IAAI,CAChC,CAAC,EAEK4C,GAAiB3D,EAAM,OAAO,IAAM,CACxC,IAAM4D,EAAM,KAAK,IAAI,EACfC,EAAW9C,EAAa,MAE9B,GAAI8C,EAAU,CACZ,IAAMC,GAAMF,EAAMC,GAAY,IAC9B,GAAIC,EAAK,GAAKA,EAAK,GAAK,CACtB,IAAMC,GAAS9D,EAAE,MAAQE,EAAM,OAAS2D,EAClCE,GAAS9D,EAAE,MAAQE,EAAM,OAAS0D,EAGlCG,EAASpC,EAAO,MAAM,YACtBqC,EAAY,KAAK,IAAI,CAACD,EAAQ,KAAK,IAAIA,EAAQF,CAAK,CAAC,EACrDI,EAAY,KAAK,IAAI,CAACF,EAAQ,KAAK,IAAIA,EAAQD,CAAK,CAAC,EAGrDI,EAAYvC,EAAO,MAAM,kBAC/BP,EAAU,MAAQA,EAAU,OAAS,EAAI8C,GAAaF,EAAYE,EAClE7C,EAAU,MAAQA,EAAU,OAAS,EAAI6C,GAAaD,EAAYC,CACpE,CACF,CACF,CAAC,EAGKC,GAAcrE,EAAM,OAAO,CAACsD,EAAKgB,IAAoB,CACzD,GAAM,CAAE,EAAGf,EAAM,EAAGC,EAAM,KAAAe,EAAM,QAASd,EAAY,QAASC,EAAY,OAAQc,EAAa,QAASC,EAAc,aAAcC,GAAmB,eAAgBC,EAAoB,EAAIL,EACzLV,EAAM,KAAK,IAAI,EAOrB,OALA5C,EAAc,MAAQ4C,EACtBhD,EAAc,MAAQ2D,EACtBhE,EAAa,MAAQmE,GACrBlE,EAAe,MAAQmE,GAEfJ,EAAM,CACZ,IAAK,OACHlB,EAAeC,EAAKC,EAAMC,EAAMC,EAAYC,CAAU,EACtDjD,EAAU,MAAQ,GAClBI,EAAS,MAAQ+C,EACjBlD,EAAO,MAAQ8D,EACf7D,EAAQ,MAAQ8D,EAChBxD,EAAW,MAAQsC,EACnBrC,EAAW,MAAQsC,EACnBrC,EAAW,MAAQ,GAGQyC,EAAMvC,EAAc,MACtBQ,EAAO,MAAM,qBACpCT,EAAW,MAAQA,EAAW,MAAQ,EAEtCA,EAAW,MAAQ,EAErB,MAEF,IAAK,KACHiC,EAAeC,EAAKC,EAAMC,EAAMC,EAAYC,CAAU,EACtDjD,EAAU,MAAQ,GAClBK,EAAO,MAAQ8C,EACfvC,EAAc,MAAQuC,EACtBzC,EAAW,MAAQ,GACnBG,EAAU,MAAQ,EAClBC,EAAU,MAAQ,EAClBZ,EAAQ,MAAQ8D,EAChB,MAEF,IAAK,OACHpB,EAAeC,EAAKC,EAAMC,EAAMC,EAAYC,CAAU,EACtDC,GAAe,EACfhD,EAAQ,MAAQ8D,EAGZhE,EAAU,OAAS,CAACU,EAAW,OAChBuB,EAAa,MACfb,EAAO,MAAM,gBAC1BV,EAAW,MAAQ,IAGvB,MAEF,IAAK,WACHkC,EAAeC,EAAKC,EAAMC,EAAMC,EAAYC,CAAU,EACtDtC,EAAW,MAAQ,EACnB,MAEF,IAAK,SACHiC,EAAeC,EAAKC,EAAMC,EAAMC,EAAYC,CAAU,EAElDY,EAAgB,SAAW,SAC7B9C,EAAiB,MAAQ8C,EAAgB,QAEvCA,EAAgB,SAAW,SAC7B7C,EAAiB,MAAQ6C,EAAgB,QAE3C,MAEF,IAAK,OACHjB,EAAeC,EAAKC,EAAMC,EAAMC,EAAYC,CAAU,EAClDY,EAAgB,SAAW,SAC7B5C,EAAc,MAAQ4C,EAAgB,QAExC,KACJ,CACF,CAAC,EAEKM,GAAiB5E,EAAM,OAAO,CAACsD,EAAKuB,IAAS,CACjDlD,EAAY,MAAQkD,CACtB,CAAC,EAEKC,GAAgB9E,EAAM,OAAO,CAACsD,EAAKuB,IAAS,CAChDjD,EAAW,MAAQiD,CACrB,CAAC,EAEKE,GAAQ/E,EAAM,OAAO,IAAM,CAC/BS,EAAU,MAAQ,GAClBU,EAAW,MAAQ,GACnBS,EAAW,MAAQ,KACnBD,EAAY,MAAQ,KACpBL,EAAU,MAAQ,EAClBC,EAAU,MAAQ,EAClBH,EAAW,MAAQ,EACnBI,EAAiB,MAAQ,EACzBC,EAAiB,MAAQ,EACzBC,EAAc,MAAQ,CACxB,CAAC,EAEKsD,GAAehF,EAAM,OAAO,CAACsD,EAAK2B,IAAY,CAClDpD,EAAO,MAAQ,CAAE,GAAGA,EAAO,MAAO,GAAGoD,CAAQ,CAC/C,CAAC,EAGD,MAAO,CAEL,MAAA7B,GACA,SAAAtB,EACA,eAAAC,EACA,iBAAAC,EACA,MAAAC,GACA,SAAAK,GACA,MAAAC,GACA,UAAA9B,EACA,OAAAC,EACA,QAAAC,EACA,WAAAQ,EACA,aAAAuB,EACA,UAAAK,GACA,UAAAE,GACA,aAAAD,EACA,aAAAzC,EACA,eAAAC,EACA,YAAAmB,EACA,WAAAC,EACA,WAAAR,EACA,cAAAR,EACA,mBAAAsC,GAGA,YAAAmB,GACA,eAAAO,GACA,cAAAE,GACA,MAAAC,GACA,aAAAC,EACF,CACF,CAAC,EJ5UM,IAAME,MAAc,oBAAiB,QAAS,CAAC,MAAM,CAAC,EAChDC,MAAc,oBAAiB,QAAS,CAAC,MAAM,CAAC,EAEhDC,EAAN,cAAsB,kBAAgB,CAC3CC,GAAU,IAAI,IACdC,GAAU,KACVC,GAAY,IAAI,IAChBC,GAAY,IAAI,IAChBC,GAAU,IAAI,IACdC,GAAa,GACbC,GAAW,KACXC,GAAe,GACfC,GAAmB,GAGnBC,GAAiB,CACf,UAAW,GACX,cAAe,IAAO,GACtB,UAAW,EACX,MAAO,CACL,QAAS,GACT,QAAS,GACT,WAAY,GACZ,gBAAiB,EACnB,CACF,EAGAC,GAAU,CACR,cAAe,EACf,UAAW,EACX,YAAa,EACb,WAAY,CACd,EAGAC,GAAW,CACT,IAAK,EACL,UAAW,EACX,WAAY,IAAI,IAChB,WAAY,IAAI,IAChB,cAAe,CACjB,EAGAC,GAAe,IAAIC,EACnBC,GAAiB,KACjBC,GAAkBC,EAAkB,EACpCC,GAAsB,KACtBC,GAAe,IAAI,IAEnB,OAAO,SAAW,CAChB,KAAM,UACN,UAAW,UACX,QAAS,QACT,SAAU,CAER,UAAW,GACX,cAAe,IAAO,GACtB,UAAW,EAEX,MAAO,CACL,QAAS,GACT,QAAS,GACT,WAAY,GACZ,gBAAiB,EACnB,CACF,CACF,EAEA,SAAW,CACT,MAAO,CACL,QAAS,IAAM,KAAKH,GAAgB,KACtC,CACF,CAEA,SAAU,CAER,OAAI,KAAK,QACP,OAAO,OAAO,KAAKN,GAAgB,KAAK,MAAM,EAGzC,CACL,SAAWU,GAAa,KAAK,SAASA,CAAQ,EAC9C,UAAW,IAAIC,IAAW,CACxB,QAAWC,KAASD,EAClB,KAAK,SAASC,CAAK,CAEvB,EACA,aAAeC,GAAO,KAAK,aAAaA,CAAE,EAC1C,UAAYC,GAAW,KAAK,UAAUA,CAAM,EAC5C,UAAYC,GAAW,KAAK,UAAUA,CAAM,EAC5C,YAAcC,GAAS,KAAK,YAAYA,CAAI,EAC5C,MAAO,IAAM,KAAK,MAAM,EACxB,KAAM,IAAM,KAAK,KAAK,EACtB,OAAQ,IAAM,KAAK,OAAO,EAC1B,aAAeC,GAAQ,KAAK,aAAaA,CAAG,EAC5C,aAAeC,GAAU,KAAK,aAAaA,CAAK,EAChD,iBAAmBC,GAAS,KAAK,iBAAiBA,CAAI,EACtD,SAAWC,GAAY,KAAK,SAASA,CAAO,EAC5C,WAAY,IAAM,KAAK,WAAW,EAClC,aAAc,CAACC,EAAOC,IAAW,KAAK,aAAaD,EAAOC,CAAM,EAChE,UAAW,CAACC,EAAOC,IAAa,KAAK,UAAUD,EAAOC,CAAQ,EAE9D,mBAAqBA,GAAa,KAAKlB,GAAgB,WAAWkB,CAAQ,EAC1E,YAAcC,GAAS,KAAKnB,GAAgB,MAAMmB,CAAI,EAEtD,sBAAwBC,GAAoB,KAAK,sBAAsBA,CAAe,CACxF,CACF,CAEA,UAAUZ,EAAQ,CAChB,KAAKtB,GAAUsB,EAGf,OAAO,OAAOa,CAAY,EAAE,QAAQC,GAAQ,CAC1C,GAAI,CACF,IAAMC,EAAMf,EAAO,WAAWc,CAAI,EAC9BC,GAAK,KAAKpC,GAAU,IAAImC,EAAMC,CAAG,CACvC,MAAY,CACV,QAAQ,KAAK,gBAAgBD,CAAI,gBAAgB,CACnD,CACF,CAAC,EAGI,KAAKvB,KACR,KAAKA,GAAiB,IAAIyB,GAG5B,KAAKzB,GAAe,UAAUS,CAAM,EAGhC,KAAKN,IACP,KAAKA,GAAoB,EAG3B,KAAKA,GAAsB,KAAKH,GAAe,UAAWqB,GAAoB,CAE5E,KAAKpB,GAAgB,YAAYoB,CAAe,EAGhD,KAAKK,GAA0BL,CAAe,CAChD,CAAC,CACH,CAEA,aAAab,EAAI,CACf,IAAMmB,EAASnB,EAAG,KAAKrB,EAAO,EAC1BwC,IACF,KAAKxC,GAAUwC,EAEnB,CAEA,UAAUjB,EAAQ,CAChB,KAAKpB,GAAUoB,CACjB,CAEA,OAAQ,CACD,KAAKnB,KACR,KAAKA,GAAa,GAClB,KAAKqC,GAAgB,EAEzB,CAEA,MAAO,CACD,KAAKrC,KACP,KAAKA,GAAa,GACd,KAAKC,KACP,qBAAqB,KAAKA,EAAQ,EAClC,KAAKA,GAAW,MAGtB,CAEA,SAASa,EAAU,CArLrB,IAAAwB,EAsLI,MAAI,kBAAexB,CAAQ,IAAM,QAC/B,MAAM,IAAI,MAAM,0BAA0B,EAG5C,IAAMM,EAAON,EAAS,MAChByB,EAASzB,EAAS,KAAK,WAAY,KAAKP,EAAY,EAG1D,GAAIgC,EAAO,KAAM,CACf,IAAMC,EAAc,KAAKC,GAAmB,SAASrB,CAAI,GAAImB,EAAO,IAAI,EACpEC,GACF,KAAK1C,GAAU,IAAI,SAASsB,CAAI,GAAIoB,CAAW,CAEnD,CAGA,IAAME,EAAUH,EAAO,SAAS,IAAII,GAAS,CAtMjD,IAAAL,EAuMM,MAAI,kBAAeK,CAAK,IAAM,QAAS,CACrC,IAAMvB,EAAOuB,EAAM,MACbC,EAAcD,EAAM,KAAK,WAAY,KAAKpC,EAAY,EAGtDiC,EAAcI,EAAY,KAC5B,KAAKH,GAAmB,SAASrB,CAAI,GAAIwB,EAAY,IAAI,EACzD,IAAG,GAEDC,EAAcD,EAAY,QAC5B,iBAAcA,EAAY,KAAM,CAC9B,UAAW,GACX,QAAS,KAAK,WAAW,OAAO,CAClC,CAAC,EACD,KAEEE,EAAQ,CACZ,KAAA1B,EACA,GAAGwB,EACH,YAAAJ,EACA,YAAAK,CACF,EAGA,IAAIP,EAAAQ,EAAM,YAAN,MAAAR,EAAiB,QACnB,GAAI,CACFQ,EAAM,UAAU,QAAQ,KAAKjD,GAAU,IAAIiD,EAAM,SAAWP,EAAO,OAAO,CAAC,CAC7E,OAASQ,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,aAAcC,CAAK,CAChE,CAGF,OAAOD,CACT,CAEA,OAAO,KAAK,SAASH,CAAK,CAC5B,CAAC,EAEK3B,EAAQ,CACZ,GAAGuB,EACH,KAAAnB,EACA,QAAAsB,EACA,QAAS,KAAK7C,GAAU,IAAI0C,EAAO,OAAO,CAC5C,EAKA,GAHA,KAAK5C,GAAQ,IAAIyB,EAAMJ,CAAK,GAGxBsB,EAAAtB,EAAM,YAAN,MAAAsB,EAAiB,QACnB,GAAI,CACFtB,EAAM,UAAU,QAAQA,EAAM,OAAO,CACvC,OAAS+B,EAAO,CACd,QAAQ,MAAM,mBAAmB3B,CAAI,aAAc2B,CAAK,CAC1D,CAGF,OAAO/B,CACT,CAEA,YAAYI,EAAM,CAlQpB,IAAAkB,EAmQI,IAAMtB,EAAQ,KAAKrB,GAAQ,IAAIyB,CAAI,EACnC,GAAI,CAACJ,EAAO,OAGZ,IAAIsB,EAAAtB,EAAM,YAAN,MAAAsB,EAAiB,UACnB,GAAI,CACFtB,EAAM,UAAU,UAAUA,EAAM,OAAO,CACzC,OAAS+B,EAAO,CACd,QAAQ,MAAM,mBAAmB3B,CAAI,eAAgB2B,CAAK,CAC5D,CAIF/B,EAAM,QAAQ,QAAQ8B,GAAS,CAhRnC,IAAAR,EAiRM,IAAIA,EAAAQ,EAAM,YAAN,MAAAR,EAAiB,UACnB,GAAI,CACFQ,EAAM,UAAU,UACd,KAAKjD,GAAU,IAAIiD,EAAM,SAAW9B,EAAM,OAAO,CACnD,CACF,OAAS+B,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,eAAgBC,CAAK,CAClE,CAGF,IAAMC,EAAc,KAAKlD,GAAU,IAAI,iBAAiBgD,EAAM,IAAI,EAAE,EAChEE,IACFA,EAAY,YAAY,EACxBA,EAAY,QAAQ,QAAQ,EAC5B,KAAKlD,GAAU,OAAO,iBAAiBgD,EAAM,IAAI,EAAE,EAEvD,CAAC,EAGD,IAAMG,EAAmB,KAAKnD,GAAU,IAAI,iBAAiBsB,CAAI,EAAE,EAC/D6B,IACFA,EAAiB,YAAY,EAC7BA,EAAiB,QAAQ,QAAQ,EACjC,KAAKnD,GAAU,OAAO,iBAAiBsB,CAAI,EAAE,GAG/C,KAAKzB,GAAQ,OAAOyB,CAAI,CAC1B,CAEAiB,IAAkB,CACZ,KAAKlC,IAAoB,KAAKD,KAElC,KAAKC,GAAmB,GAExB,KAAKF,GAAW,sBAAsB,IAAM,CAC1C,KAAKE,GAAmB,GACxB,KAAKF,GAAW,KAChB,KAAKiD,GAAQ,CACf,CAAC,EACH,CAEA,KAAMA,IAAU,CA1TlB,IAAAZ,EAAAa,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EA2TI,GAAK,KAAKtE,GACV,MAAKM,GAAe,GAEpB,GAAI,CAEF,KAAKK,GAAa,MAAM,EAExB,IAAM4D,GAAc7B,EAAA,KAAKlC,GAAe,QAApB,MAAAkC,EAA2B,QAAU,YAAY,IAAI,EAAI,EAG7E,KAAKzC,GAAU,QAAQoC,GAAO,CAC5BA,EAAI,UAAU,EAAG,EAAG,KAAKrC,GAAQ,MAAO,KAAKA,GAAQ,MAAM,CAC7D,CAAC,EAGD,QAAWoB,KAAS,KAAKrB,GAAQ,OAAO,EAAG,CACzC,IAAMyE,GAAajB,EAAA,KAAK/C,GAAe,QAApB,MAAA+C,EAA2B,QAAU,YAAY,IAAI,EAAI,EAG5E,GAAInC,EAAM,YAAa,CACrB,IAAMqD,GAAejB,EAAA,KAAKtD,GAAU,IAAI,iBAAiBkB,EAAM,IAAI,EAAE,IAAhD,YAAAoC,EAAmD,QACxE,GAAI,CAACpC,EAAM,KAAKqD,EAAa,CAAC,EAAG,QACnC,CAEA,IAAMpC,EAAMjB,EAAM,QAElB,GAAKiB,EAGL,KAAIoB,EAAArC,EAAM,YAAN,MAAAqC,EAAiB,aACnB,GAAI,CACFrC,EAAM,UAAU,aAAaiB,EAAK,KAAK5B,EAAO,CAChD,OAAS0C,EAAO,CACd,QAAQ,MAAM,mBAAmB/B,EAAM,IAAI,kBAAmB+B,CAAK,GAC/DO,EAAAtC,EAAM,YAAN,MAAAsC,EAAiB,SAAStC,EAAM,UAAU,QAAQ+B,CAAK,CAC7D,CAIFd,EAAI,KAAK,EACLjB,EAAM,UACR,OAAO,QAAQA,EAAM,QAAQ,EAAE,QAAQ,CAAC,CAACsD,EAAKC,CAAK,IAAM,CACnD,OAAOtC,EAAIqC,CAAG,GAAM,WACtBrC,EAAIqC,CAAG,EAAE,GAAI,MAAM,QAAQC,CAAK,EAAIA,EAAQ,CAACA,CAAK,CAAE,EAEpDtC,EAAIqC,CAAG,EAAIC,CAEf,CAAC,EAIH,QAAWzB,KAAS9B,EAAM,QAAS,CACjC,IAAMwD,GAAajB,EAAA,KAAKnD,GAAe,QAApB,MAAAmD,EAA2B,QAAU,YAAY,IAAI,EAAI,EAE5E,GAAIT,EAAM,aAAe,CAACA,EAAM,YAAY,EAAG,SAG/C,IAAM2B,EAAW3B,EAAM,QACrB,KAAKjD,GAAU,IAAIiD,EAAM,OAAO,EAChCb,EAEF,GAAKwC,EAGL,KAAIjB,EAAAV,EAAM,YAAN,MAAAU,EAAiB,aACnB,GAAI,CACFV,EAAM,UAAU,aAAa2B,EAAU,KAAKpE,EAAO,CACrD,OAAS0C,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,kBAAmBC,CAAK,GAC/DU,EAAAX,EAAM,YAAN,MAAAW,EAAiB,SAASX,EAAM,UAAU,QAAQC,CAAK,EAC3D,QACF,CAGF0B,EAAS,KAAK,EAEV3B,EAAM,UACR,OAAO,QAAQA,EAAM,QAAQ,EAAE,QAAQ,CAAC,CAACwB,EAAKC,CAAK,IAAM,CACnD,OAAOE,EAASH,CAAG,GAAM,WAC3BG,EAASH,CAAG,EAAE,GAAI,MAAM,QAAQC,CAAK,EAAIA,EAAQ,CAACA,CAAK,CAAE,EAEzDE,EAASH,CAAG,EAAIC,CAElB,CAAC,EAGL,GAAI,CACF,IAAMG,EAAiB,CAAC,EACxB,GAAI5B,EAAM,OACR,QAAWwB,KAAOxB,EAAM,OACtB4B,EAAeJ,CAAG,EAAI,KAAKvE,GAAQ,IAAIuE,CAAG,EAU9C,GAPAxB,EAAM,OAAO2B,EAAU3B,EAAM,YAAY,EAAG4B,EAAgB,KAAKrE,EAAO,GAGpEqD,EAAAZ,EAAM,YAAN,MAAAY,EAAiB,aACnBZ,EAAM,UAAU,YAAY2B,EAAU,KAAKpE,EAAO,GAGhDsD,EAAA,KAAKvD,GAAe,QAApB,MAAAuD,EAA2B,QAAS,CACtC,IAAMgB,EAAY,YAAY,IAAI,EAAIH,EACtC,KAAKlE,GAAS,WAAW,IAAIwC,EAAM,KAAM6B,CAAS,GAE9Cf,EAAA,KAAKxD,GAAe,QAApB,MAAAwD,EAA2B,YAC7B,KAAKgB,GAAmBH,EAAU3B,CAAK,CAE3C,CACF,OAASC,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,KAAMC,CAAK,GAClDc,EAAAf,EAAM,YAAN,MAAAe,EAAiB,SAASf,EAAM,UAAU,QAAQC,CAAK,CAC7D,QAAE,CACA0B,EAAS,QAAQ,CACnB,EACF,CAKA,GAHAxC,EAAI,QAAQ,GAGR6B,EAAA9C,EAAM,YAAN,MAAA8C,EAAiB,YACnB,GAAI,CACF9C,EAAM,UAAU,YAAYiB,EAAK,KAAK5B,EAAO,CAC/C,OAAS0C,EAAO,CACd,QAAQ,MAAM,mBAAmB/B,EAAM,IAAI,iBAAkB+B,CAAK,GAC9DgB,EAAA/C,EAAM,YAAN,MAAA+C,EAAiB,SAAS/C,EAAM,UAAU,QAAQ+B,CAAK,CAC7D,CAGF,IAAIiB,EAAA,KAAK5D,GAAe,QAApB,MAAA4D,EAA2B,QAAS,CACtC,IAAMa,EAAY,YAAY,IAAI,EAAIT,EACtC,KAAK9D,GAAS,WAAW,IAAIU,EAAM,KAAM6D,CAAS,GAE9CZ,EAAA,KAAK7D,GAAe,QAApB,MAAA6D,EAA2B,YAC7B,KAAKa,GAAmB7C,EAAKjB,CAAK,CAEtC,EACF,EAGIkD,EAAA,KAAK9D,GAAe,QAApB,MAAA8D,EAA2B,SAC7B,KAAKa,GAAoB,CAG7B,QAAE,CACA,KAAK7E,GAAe,EACtB,EACF,CAEA0E,GAAmB3C,EAAKa,EAAO,CAC7Bb,EAAI,KAAK,EACTA,EAAI,YAAc,uBAClBA,EAAI,UAAY,EAChBA,EAAI,WAAW,EAAG,EAAGA,EAAI,OAAO,MAAOA,EAAI,OAAO,MAAM,EACxDA,EAAI,QAAQ,CACd,CAEA6C,GAAmB7C,EAAKjB,EAAO,CAC7BiB,EAAI,KAAK,EACTA,EAAI,YAAc,uBAClBA,EAAI,UAAY,EAChBA,EAAI,WAAW,EAAG,EAAGA,EAAI,OAAO,MAAOA,EAAI,OAAO,MAAM,EACxDA,EAAI,QAAQ,CACd,CAEA8C,IAAsB,CA/dxB,IAAAzC,EAAAa,EAgeI,IAAMlB,EAAM,KAAKpC,GAAU,IAAIkC,EAAa,IAAI,CAAC,EACjD,GAAI,CAACE,EAAK,OAEVA,EAAI,KAAK,EACTA,EAAI,eAAe,EACnBA,EAAI,KAAO,iBACXA,EAAI,UAAY,QAChBA,EAAI,YAAc,QAClBA,EAAI,UAAY,EAEhB,IAAI+C,EAAI,GACFC,EAAa,GAEnB,IAAI3C,EAAA,KAAKlC,GAAe,QAApB,MAAAkC,EAA2B,QAAS,CACtC,IAAM4C,EAAO,QAAQ,KAAK,MAAM,KAAK5E,GAAS,GAAG,CAAC,KAAK,KAAKD,GAAQ,UAAU,QAAQ,CAAC,CAAC,MACxF4B,EAAI,WAAWiD,EAAM,GAAIF,CAAC,EAC1B/C,EAAI,SAASiD,EAAM,GAAIF,CAAC,EACxBA,GAAKC,CACP,CAEA,IAAI9B,EAAA,KAAK/C,GAAe,QAApB,MAAA+C,EAA2B,gBAAiB,CAC9ClB,EAAI,SAAS,eAAgB,GAAI+C,CAAC,EAClCA,GAAKC,EAEL,OAAW,CAAC7D,EAAM+D,CAAI,IAAK,KAAK7E,GAAS,WAAY,CACnD,IAAM4E,EAAO,KAAK9D,CAAI,KAAK+D,EAAK,QAAQ,CAAC,CAAC,KAC1ClD,EAAI,WAAWiD,EAAM,GAAIF,CAAC,EAC1B/C,EAAI,SAASiD,EAAM,GAAIF,CAAC,EACxBA,GAAKC,CACP,CAEAhD,EAAI,SAAS,KAAK,MAAM,IAAI,CAAC,eAAgB,UAAW,cAAc,CAAC,EAAG,GAAI+C,CAAC,CACjF,CAEA/C,EAAI,QAAQ,CACd,CAEA,aAAaR,EAAOC,EAAQ,CArgB9B,IAAAY,EAAAa,EAugBI,QAAWnC,KAAS,KAAKrB,GAAQ,OAAO,EACtC,IAAI2C,EAAAtB,EAAM,YAAN,MAAAsB,EAAiB,SACnB,GAAI,CACFtB,EAAM,UAAU,SAASS,EAAOC,EAAQV,EAAM,OAAO,CACvD,OAAS+B,EAAO,CACd,QAAQ,MAAM,mBAAmB/B,EAAM,IAAI,cAAe+B,CAAK,GAC3DI,EAAAnC,EAAM,YAAN,MAAAmC,EAAiB,SAASnC,EAAM,UAAU,QAAQ+B,CAAK,CAC7D,CAGN,CAEAN,GAAmB2C,EAAIC,EAAM,CAC3B,IAAMC,EAAQ,KAAK,WAAW,OAAO,EAE/BC,KAAU,iBAAcF,EAAM,CAClC,UAAW,GACX,QAASC,CACX,CAAC,EAEKE,KAAc,aAAUD,EAAS,IAAM,KAAKlD,GAAgB,CAAC,EAEnE,YAAKvC,GAAU,IAAI,WAAWsF,CAAE,GAAI,CAClC,QAAAG,EACA,YAAAC,CACF,CAAC,EAEMD,CACT,CAEA,SAAU,CACR,KAAK,KAAK,EAGN,KAAK3E,KACP,KAAKA,GAAoB,EACzB,KAAKA,GAAsB,MAEzB,KAAKH,KACP,KAAKA,GAAe,QAAQ,EAC5B,KAAKA,GAAiB,MAEpB,KAAKC,IACP,KAAKA,GAAgB,SAAS,EAIhC,QAAWU,KAAQ,KAAKzB,GAAQ,KAAK,EACnC,KAAK,YAAYyB,CAAI,CAEzB,CAEA,aAAaC,EAAK,CAChB,KAAKjB,GAAe,UAAYiB,EAChC,KAAKjB,GAAe,cAAgB,IAAOiB,CAC7C,CAEA,aAAaC,EAAO,CAClB,KAAKlB,GAAe,UAAY,KAAK,IAAI,EAAGkB,CAAK,CACnD,CAEA,iBAAiBC,EAAM,CACrB,KAAKnB,GAAe,cAAgBmB,CACtC,CAEA,SAASC,EAAU,CAAC,EAAG,CAChB,KAAKpB,GAAe,QACvB,KAAKA,GAAe,MAAQ,CAAC,GAE/B,OAAO,OAAO,KAAKA,GAAe,MAAOoB,CAAO,CAClD,CAEA,YAAa,CACX,MAAO,CACL,GAAG,KAAKlB,GACR,UAAW,KAAKD,GAAQ,UACxB,YAAa,KAAKA,GAAQ,YAC1B,WAAY,KAAKA,GAAQ,UAC3B,CACF,CAEA8B,GAA0BL,EAAiB,CAxlB7C,IAAAQ,EAAAa,EAAAC,EAAAC,EAAAC,EAylBI,GAAM,CAAE,KAAAtB,EAAM,EAAAyD,EAAG,EAAAT,CAAE,EAAIlD,EACjB4D,EAAU,KAAKhF,GAErB,OAAQsB,EAAM,CACZ,IAAK,OAAQ,CACX,IAAM2D,EAAU,KAAKC,GAASH,EAAGT,CAAC,EAGlC,GAFAU,EAAQ,cAAcC,CAAO,GAEzBrD,EAAAqD,GAAA,YAAAA,EAAS,gBAAT,MAAArD,EAAwB,QAAS,CACnC,IAAML,EAAM,KAAK4D,GAAmBF,CAAO,EAC3CA,EAAQ,cAAc,QAAQ,CAC5B,GAAGD,EAAQ,MACX,IAAAzD,EACA,KAAM,KAAK6D,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CACA,KACF,CAEA,IAAK,KAAM,CACT,IAAMC,EAAaL,EAAQ,WAC3B,IAAIvC,EAAA4C,GAAA,YAAAA,EAAY,cAAZ,MAAA5C,EAAyB,QAAS,CACpC,IAAMlB,EAAM,KAAK4D,GAAmBE,CAAU,EAC9CA,EAAW,YAAY,QAAQ,CAC7B,GAAGL,EAAQ,MACX,IAAAzD,EACA,KAAM,KAAK6D,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CACA,KACF,CAEA,IAAK,OAAQ,CACX,IAAMH,EAAU,KAAKC,GAASH,EAAGT,CAAC,EAC5BgB,EAAcN,EAAQ,YAGtBK,EAAaL,EAAQ,WAC3B,IAAItC,EAAA2C,GAAA,YAAAA,EAAY,gBAAZ,MAAA3C,EAA2B,SAAWsC,EAAQ,WAAY,CAC5D,IAAMzD,EAAM,KAAK4D,GAAmBE,CAAU,EAC9CA,EAAW,cAAc,QAAQ,CAC/B,GAAGL,EAAQ,MACX,IAAAzD,EACA,KAAM,KAAK6D,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CAGA,IAAIH,GAAA,YAAAA,EAAS,OAAOK,GAAA,YAAAA,EAAa,IAAI,CACnC,IAAI3C,EAAA2C,GAAA,YAAAA,EAAa,iBAAb,MAAA3C,EAA6B,QAAS,CACxC,IAAMpB,EAAM,KAAK4D,GAAmBG,CAAW,EAC/CA,EAAY,eAAe,QAAQ,CACjC,GAAGN,EAAQ,MACX,IAAAzD,EACA,KAAM,KAAK6D,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CAEA,IAAIxC,EAAAqC,GAAA,YAAAA,EAAS,iBAAT,MAAArC,EAAyB,QAAS,CACpC,IAAMrB,EAAM,KAAK4D,GAAmBF,CAAO,EAC3CA,EAAQ,eAAe,QAAQ,CAC7B,GAAGD,EAAQ,MACX,IAAAzD,EACA,KAAM,KAAK6D,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CAEAJ,EAAQ,eAAeC,CAAO,CAChC,CACA,KACF,CAEA,IAAK,SACL,IAAK,OAEH,KAAKG,GAAM,WAAW9D,CAAI,GAAI0D,EAAQ,KAAK,EAC3C,MAEF,IAAK,WAEH,KAAKI,GAAM,mBAAoBJ,EAAQ,KAAK,EAC5C,KACJ,CACF,CAEAG,GAAmBI,EAAM,CACvB,OAAKA,EACEA,EAAK,QACR,KAAKpG,GAAU,IAAIoG,EAAK,OAAO,EAC/B,KAAKpG,GAAU,IAAIkC,EAAa,IAAI,CAAC,EAHvB,IAIpB,CAEA,UAAUJ,EAAOC,EAAU,CACzB,OAAK,KAAKf,GAAa,IAAIc,CAAK,GAC9B,KAAKd,GAAa,IAAIc,EAAO,IAAI,GAAK,EAExC,KAAKd,GAAa,IAAIc,CAAK,EAAE,IAAIC,CAAQ,EAElC,IAAM,CACX,IAAMsE,EAAY,KAAKrF,GAAa,IAAIc,CAAK,EACzCuE,IACFA,EAAU,OAAOtE,CAAQ,EACrBsE,EAAU,OAAS,GACrB,KAAKrF,GAAa,OAAOc,CAAK,EAGpC,CACF,CAEAiE,GAASH,EAAGT,EAAG,CAEb,IAAMmB,EAAS,KAAK5F,GAAa,MAAM,KAAK,CAAC6F,EAAGC,KAC7CA,EAAE,UAAY,IAAMD,EAAE,UAAY,EACrC,EAEA,QAAWH,KAAQE,EACjB,GAAI,KAAKG,GAAiBb,EAAGT,EAAGiB,EAAK,MAAM,EACzC,OAAOA,EAGX,OAAO,IACT,CAEAK,GAAiBb,EAAGT,EAAGuB,EAAQ,CAC7B,OAAOd,GAAKc,EAAO,GACZd,GAAKc,EAAO,EAAIA,EAAO,OACvBvB,GAAKuB,EAAO,GACZvB,GAAKuB,EAAO,EAAIA,EAAO,MAChC,CAEAT,GAAMnE,EAAO0D,EAAM,CACjB,IAAMa,EAAY,KAAKrF,GAAa,IAAIc,CAAK,EAC7C,GAAIuE,EACF,QAAWtE,KAAYsE,EACrBtE,EAASyD,CAAI,CAGnB,CAGA,sBAAsBvD,EAAiB,CACrC,KAAKpB,GAAgB,YAAYoB,CAAe,EAChD,KAAKK,GAA0BL,CAAe,CAChD,CACF",
|
|
6
|
-
"names": ["main_exports", "__export", "
|
|
3
|
+
"sources": ["../src/main.js", "../src/Painter.js", "../src/ContextTypes.js", "../src/HitRegistry.js", "../src/CanvasEvents.js", "../src/usePointerSurface.js"],
|
|
4
|
+
"sourcesContent": ["export { Painter, defineLayer, defineBrush } from './Painter';\nexport { HitRegistry } from './HitRegistry';\nexport { CanvasEvents } from './CanvasEvents';\nexport { usePointerSurface } from './usePointerSurface';", "import { ServiceProvider } from '@jucie-engine/core';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createReactor, addEffect } from '@jucie-state/reactive';\nimport { createDefinition, definitionType } from '@jucie-engine/core';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nexport const defineBrush = createDefinition('BRUSH', [Object]);\nexport const defineLayer = createDefinition('LAYER', [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #reactors = 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 #subscribers = new Map(); // Map<event, Set<callback>>\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.state,\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 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 // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\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(canvas);\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 // Set up layer reactor if it has data paths\n if (config.data) {\n const dataReactor = this.#createDataReactor(`layer_${name}`, config.data);\n if (dataReactor) {\n this.#reactors.set(`layer_${name}`, dataReactor);\n }\n }\n\n // Set up brush reactors and structure\n const brushes = config.children.map(child => {\n if (definitionType(child) === 'BRUSH') {\n const name = child._name;\n const brushConfig = child(this.useContext, this.#hitRegistry);\n \n // Only create data reactor if data exists\n const dataReactor = brushConfig.data \n ? this.#createDataReactor(`brush_${name}`, brushConfig.data)\n : () => undefined;\n \n const whenReactor = brushConfig.when \n ? createReactor(brushConfig.when, {\n immediate: true,\n context: this.useContext('state')\n })\n : null;\n\n const brush = {\n name,\n ...brushConfig,\n dataReactor,\n whenReactor\n };\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || config.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n return brush;\n }\n // Handle nested layers recursively\n return this.addLayer(child);\n });\n\n const layer = {\n ...config,\n name,\n brushes,\n context: this.#contexts.get(config.context)\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 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 // Call brush unmount hooks and clean up reactors\n layer.brushes.forEach(brush => {\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 reactor and subscription\n const reactorData = this.#reactors.get(`painter_brush_${brush.name}`);\n if (reactorData) {\n reactorData.unsubscribe();\n reactorData.reactor.destroy();\n this.#reactors.delete(`painter_brush_${brush.name}`);\n }\n });\n\n // Clean up layer reactor and subscription\n const layerReactorData = this.#reactors.get(`painter_layer_${name}`);\n if (layerReactorData) {\n layerReactorData.unsubscribe();\n layerReactorData.reactor.destroy();\n this.#reactors.delete(`painter_layer_${name}`);\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) {\n const layerReactor = this.#reactors.get(`painter_layer_${layer.name}`)?.reactor;\n if (!layer.when(layerReactor())) continue;\n }\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 // Render brushes\n for (const brush of layer.brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor()) 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(), 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 #createDataReactor(id, data) {\n const state = this.useContext('state');\n\n const reactor = createReactor(data, {\n immediate: true,\n context: state\n });\n\n const unsubscribe = addEffect(reactor, () => this.#scheduleRender());\n\n this.#reactors.set(`painter_${id}`, {\n reactor,\n unsubscribe\n });\n\n return reactor;\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.#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\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 ...pointer.state,\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 ...pointer.state,\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 drag on active area\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerMove?.handler && pointer.isDragging) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerMove.handler({\n ...pointer.state,\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 ...pointer.state,\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 ...pointer.state,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'scroll':\n case 'zoom':\n // Emit custom events for scroll/zoom\n this.#emit(`pointer:${type}`, pointer.state);\n break;\n\n case 'dblclick':\n // Emit double-click event\n this.#emit('pointer:dblclick', pointer.state);\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}", "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-engine/core';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #pendingMove = null;\n #rafId = null;\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 };\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 #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(() => {\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n document.addEventListener('wheel', this.#handleScroll, { passive: false });\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerdown', this.#handleDown);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleUp);\n document.addEventListener('dblclick', this.#handleDblClick);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n document.removeEventListener('wheel', this.#handleScroll);\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerdown', this.#handleDown);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleUp);\n document.removeEventListener('dblclick', this.#handleDblClick);\n }\n\n #handleScroll = (event) => {\n if (event.target !== this.#canvas) {\n return;\n }\n\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 const normalized = this.#normalizeEvent(event, 'move');\n \n // Store latest move and throttle with RAF\n this.#pendingMove = normalized;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n this.#emit(this.#pendingMove);\n this.#pendingMove = null;\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n // Only capture if starting on canvas\n if (event.target === this.#canvas) {\n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n }\n\n #handleUp = (event) => {\n // Use the actual up event position, not pending move\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\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 #normalizeEvent(event, type) {\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 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 const normalized = {\n x,\n y,\n type,\n isOverCanvas,\n isWithinBounds,\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button ?? null,\n buttons: event.buttons ?? 0,\n timestamp: Date.now()\n };\n\n // Add wheel-specific data for scroll/zoom\n if (type === 'scroll' || type === 'zoom') {\n normalized.deltaX = event.deltaX;\n normalized.deltaY = event.deltaY;\n normalized.deltaZ = event.deltaZ;\n normalized.deltaMode = event.deltaMode;\n }\n\n // Add modifier keys\n normalized.shiftKey = event.shiftKey || false;\n normalized.ctrlKey = event.ctrlKey || false;\n normalized.altKey = event.altKey || false;\n normalized.metaKey = event.metaKey || false;\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.#cachedRect = null;\n this.#subscribers.clear();\n }\n}\n", "import { defineSurface } from '@jucie-state/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // ============= Core State =============\n \n // Position (canvas coordinates)\n const x = setup.value(0);\n const y = setup.value(0);\n const prevX = setup.value(0);\n const prevY = setup.value(0);\n \n // Client position (screen coordinates)\n const clientX = setup.value(0);\n const clientY = setup.value(0);\n \n // Canvas boundary state\n const isOverCanvas = setup.value(false);\n const isWithinBounds = setup.value(false);\n \n // Button state\n const isPressed = setup.value(false);\n const button = setup.value(null); // 0=left, 1=middle, 2=right\n const buttons = setup.value(0); // Bitmask of pressed buttons\n \n // Event type tracking\n const lastEventType = setup.value(null);\n \n // Timing\n const downTime = setup.value(null);\n const upTime = setup.value(null);\n const lastMoveTime = setup.value(null);\n const lastEventTime = setup.value(null);\n \n // Drag state\n const dragStartX = setup.value(null);\n const dragStartY = setup.value(null);\n const isDragging = setup.value(false);\n \n // Click detection\n const clickCount = setup.value(0);\n const lastClickTime = setup.value(0);\n \n // Velocity tracking\n const velocityX = setup.value(0);\n const velocityY = setup.value(0);\n \n // Scroll/Zoom state\n const lastScrollDeltaX = setup.value(0);\n const lastScrollDeltaY = setup.value(0);\n const lastZoomDelta = setup.value(0);\n \n // Hit areas (from HitRegistry)\n const hoveredArea = setup.value(null);\n const activeArea = setup.value(null);\n \n // ============= Configuration =============\n const config = setup.value({\n dragThreshold: 5,\n doubleClickThreshold: 300,\n holdThreshold: 500,\n velocitySmoothing: 0.3,\n maxVelocity: 10000 // Clamp unrealistic velocities\n });\n \n // ============= Computed Values =============\n \n const position = setup.computed(() => ({\n x: x.value,\n y: y.value\n }));\n \n const clientPosition = setup.computed(() => ({\n x: clientX.value,\n y: clientY.value\n }));\n \n const previousPosition = setup.computed(() => ({\n x: prevX.value,\n y: prevY.value\n }));\n \n const delta = setup.computed(() => {\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const prevXVal = typeof prevX.value === 'number' ? prevX.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const prevYVal = typeof prevY.value === 'number' ? prevY.value : 0;\n return {\n x: xVal - prevXVal,\n y: yVal - prevYVal\n };\n });\n \n const velocity = setup.computed(() => ({\n x: velocityX.value,\n y: velocityY.value\n }));\n \n const speed = setup.computed(() => {\n const vx = velocityX.value;\n const vy = velocityY.value;\n return Math.sqrt(vx * vx + vy * vy);\n });\n \n const dragDistance = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') return 0;\n \n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const dx = xVal - startX;\n const dy = yVal - startY;\n return Math.sqrt(dx * dx + dy * dy);\n });\n \n const dragDelta = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') {\n return { x: 0, y: 0 };\n }\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n return {\n x: xVal - startX,\n y: yVal - startY\n };\n });\n \n const holdDuration = setup.computed(() => {\n if (!isPressed.value || !downTime.value) return 0;\n return Date.now() - downTime.value;\n });\n \n const isHolding = setup.computed(() => {\n return holdDuration.value > config.value.holdThreshold && !isDragging.value;\n });\n \n const timeSinceLastEvent = setup.computed(() => {\n const lastTime = lastEventTime.value;\n return lastTime ? Date.now() - lastTime : 0;\n });\n \n // Full state snapshot\n const state = setup.computed(() => ({\n position: position.value,\n clientPosition: clientPosition.value,\n previousPosition: previousPosition.value,\n delta: delta.value,\n velocity: velocity.value,\n speed: speed.value,\n isPressed: isPressed.value,\n button: button.value,\n buttons: buttons.value,\n isDragging: isDragging.value,\n dragDistance: dragDistance.value,\n dragDelta: dragDelta.value,\n isHolding: isHolding.value,\n holdDuration: holdDuration.value,\n isOverCanvas: isOverCanvas.value,\n isWithinBounds: isWithinBounds.value,\n hoveredArea: hoveredArea.value,\n activeArea: activeArea.value,\n clickCount: clickCount.value,\n lastEventType: lastEventType.value\n }));\n \n // ============= Actions =============\n \n const updatePosition = setup.action((ctx, newX, newY, newClientX, newClientY) => {\n prevX.value = x.value;\n prevY.value = y.value;\n x.value = newX;\n y.value = newY;\n clientX.value = newClientX;\n clientY.value = newClientY;\n lastMoveTime.value = Date.now();\n });\n \n const updateVelocity = setup.action(() => {\n const now = Date.now();\n const lastMove = lastMoveTime.value;\n \n if (lastMove) {\n const dt = (now - lastMove) / 1000;\n if (dt > 0 && dt < 0.1) {\n const newVx = (x.value - prevX.value) / dt;\n const newVy = (y.value - prevY.value) / dt;\n \n // Clamp unrealistic velocities\n const maxVel = config.value.maxVelocity;\n const clampedVx = Math.max(-maxVel, Math.min(maxVel, newVx));\n const clampedVy = Math.max(-maxVel, Math.min(maxVel, newVy));\n \n // Apply smoothing\n const smoothing = config.value.velocitySmoothing;\n velocityX.value = velocityX.value * (1 - smoothing) + clampedVx * smoothing;\n velocityY.value = velocityY.value * (1 - smoothing) + clampedVy * smoothing;\n }\n }\n });\n \n // Main event handler - consumes normalized events from CanvasEvents\n const handleEvent = setup.action((ctx, normalizedEvent) => {\n const { x: newX, y: newY, type, clientX: newClientX, clientY: newClientY, button: eventButton, buttons: eventButtons, isOverCanvas: eventIsOverCanvas, isWithinBounds: eventIsWithinBounds } = normalizedEvent;\n const now = Date.now();\n \n lastEventTime.value = now;\n lastEventType.value = type;\n isOverCanvas.value = eventIsOverCanvas;\n isWithinBounds.value = eventIsWithinBounds;\n \n switch (type) {\n case 'down':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = true;\n downTime.value = now;\n button.value = eventButton;\n buttons.value = eventButtons;\n dragStartX.value = newX;\n dragStartY.value = newY;\n isDragging.value = false;\n \n // Double-click detection\n const timeSinceLastClick = now - lastClickTime.value;\n if (timeSinceLastClick < config.value.doubleClickThreshold) {\n clickCount.value = clickCount.value + 1;\n } else {\n clickCount.value = 1;\n }\n break;\n \n case 'up':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = false;\n upTime.value = now;\n lastClickTime.value = now;\n isDragging.value = false;\n velocityX.value = 0;\n velocityY.value = 0;\n buttons.value = eventButtons;\n break;\n \n case 'move':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n updateVelocity();\n buttons.value = eventButtons;\n \n // Check for drag start\n if (isPressed.value && !isDragging.value) {\n const distance = dragDistance.value;\n if (distance > config.value.dragThreshold) {\n isDragging.value = true;\n }\n }\n break;\n \n case 'dblclick':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n clickCount.value = 2;\n break;\n \n case 'scroll':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n // Extract wheel delta from event if available\n if (normalizedEvent.deltaX !== undefined) {\n lastScrollDeltaX.value = normalizedEvent.deltaX;\n }\n if (normalizedEvent.deltaY !== undefined) {\n lastScrollDeltaY.value = normalizedEvent.deltaY;\n }\n break;\n \n case 'zoom':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n if (normalizedEvent.deltaY !== undefined) {\n lastZoomDelta.value = normalizedEvent.deltaY;\n }\n break;\n }\n });\n \n const setHoveredArea = setup.action((ctx, area) => {\n hoveredArea.value = area;\n });\n \n const setActiveArea = setup.action((ctx, area) => {\n activeArea.value = area;\n });\n \n const reset = setup.action(() => {\n isPressed.value = false;\n isDragging.value = false;\n activeArea.value = null;\n hoveredArea.value = null;\n velocityX.value = 0;\n velocityY.value = 0;\n clickCount.value = 0;\n lastScrollDeltaX.value = 0;\n lastScrollDeltaY.value = 0;\n lastZoomDelta.value = 0;\n });\n \n const updateConfig = setup.action((ctx, updates) => {\n config.value = { ...config.value, ...updates };\n });\n \n // ============= Return Public API =============\n return {\n // State (read-only through computed)\n state,\n position,\n clientPosition,\n previousPosition,\n delta,\n velocity,\n speed,\n isPressed,\n button,\n buttons,\n isDragging,\n dragDistance,\n dragDelta,\n isHolding,\n holdDuration,\n isOverCanvas,\n isWithinBounds,\n hoveredArea,\n activeArea,\n clickCount,\n lastEventType,\n timeSinceLastEvent,\n \n // Actions\n handleEvent, // Main entry point for normalized events\n setHoveredArea,\n setActiveArea,\n reset,\n updateConfig\n };\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["main_exports", "__export", "CanvasEvents", "HitRegistry", "Painter", "defineBrush", "defineLayer", "usePointerSurface", "__toCommonJS", "import_core", "ContextTypes", "import_reactive", "import_core", "HitRegistry", "#areas", "id", "area", "import_core", "CanvasEvents", "#canvas", "#cachedRect", "#resizeObserver", "#subscribers", "#pendingMove", "#rafId", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#handleScroll", "#handleMove", "#handleDown", "#handleUp", "#handleDblClick", "event", "normalized", "#normalizeEvent", "#emit", "type", "isOverCanvas", "x", "y", "isWithinBounds", "import_reactive", "usePointerSurface", "setup", "x", "y", "prevX", "prevY", "clientX", "clientY", "isOverCanvas", "isWithinBounds", "isPressed", "button", "buttons", "lastEventType", "downTime", "upTime", "lastMoveTime", "lastEventTime", "dragStartX", "dragStartY", "isDragging", "clickCount", "lastClickTime", "velocityX", "velocityY", "lastScrollDeltaX", "lastScrollDeltaY", "lastZoomDelta", "hoveredArea", "activeArea", "config", "position", "clientPosition", "previousPosition", "delta", "xVal", "prevXVal", "yVal", "prevYVal", "velocity", "speed", "vx", "vy", "dragDistance", "startX", "startY", "dx", "dy", "dragDelta", "holdDuration", "isHolding", "timeSinceLastEvent", "lastTime", "state", "updatePosition", "ctx", "newX", "newY", "newClientX", "newClientY", "updateVelocity", "now", "lastMove", "dt", "newVx", "newVy", "maxVel", "clampedVx", "clampedVy", "smoothing", "handleEvent", "normalizedEvent", "type", "eventButton", "eventButtons", "eventIsOverCanvas", "eventIsWithinBounds", "setHoveredArea", "area", "setActiveArea", "reset", "updateConfig", "updates", "defineBrush", "defineLayer", "Painter", "#layers", "#canvas", "#contexts", "#reactors", "#assets", "#isRunning", "#frameId", "#isRendering", "#renderScheduled", "#runtimeConfig", "#timing", "#metrics", "#hitRegistry", "HitRegistry", "#pointerSurface", "usePointerSurface", "#canvasEvents", "#pointerUnsubscribe", "#subscribers", "layerDef", "layers", "layer", "fn", "canvas", "offscreenCanvas", "assets", "name", "fps", "scale", "step", "options", "width", "height", "event", "callback", "normalizedEvent", "path", "ContextTypes", "type", "ctx", "CanvasEvents", "result", "#scheduleRender", "_a", "config", "dataReactor", "#createDataReactor", "brushes", "child", "brushConfig", "whenReactor", "brush", "error", "reactorData", "layerReactorData", "#render", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "_k", "_l", "_m", "_n", "_o", "_p", "_q", "renderStart", "layerStart", "layerReactor", "key", "value", "brushStart", "brushCtx", "requiredAssets", "brushTime", "#renderBrushBounds", "layerTime", "#renderLayerBounds", "#renderDebugOverlay", "y", "lineHeight", "text", "time", "id", "data", "state", "reactor", "unsubscribe", "#handlePointerInteraction", "x", "pointer", "hitArea", "#hitTest", "#getContextForArea", "#emit", "activeArea", "prevHovered", "area", "callbacks", "sorted", "a", "b", "#isPointInBounds", "bounds"]
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ServiceProvider as be}from"@jucie-engine/core";var U={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};import{createReactor as se,addEffect as ge}from"@jucie-state/reactive";import{createDefinition as ne,definitionType as ie}from"@jucie-engine/core";var X=class{#e=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#e.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#e.delete(e)}get(e){return this.#e.get(e)}has(e){return this.#e.has(e)}get areas(){return Array.from(this.#e.values())}clear(){this.#e.clear()}};import{ServiceProvider as me}from"@jucie-engine/core";var _=class extends me{#e=null;#s=null;#i=null;#a=new Set;#f=null;#l=null;static manifest={name:"CanvasPointer",namespace:"canvasPointer",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),getOffscreenCanvas:()=>this.getOffscreenCanvas()}}getOffscreenCanvas(){return this.#e?this.#e.transferControlToOffscreen():null}setCanvas(e){this.#e&&this.#m(),this.#e=e,this.#u(),this.#b()}subscribe(e){return this.#a.add(e),()=>this.#a.delete(e)}#u(){this.#e&&(this.#s=this.#e.getBoundingClientRect())}#b(){this.#e&&(this.#u(),this.#i=new ResizeObserver(()=>{this.#u()}),this.#i.observe(this.#e),document.addEventListener("wheel",this.#t,{passive:!1}),document.addEventListener("pointermove",this.#o),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#h),document.addEventListener("pointercancel",this.#h),document.addEventListener("dblclick",this.#c))}#m(){this.#i&&(this.#i.disconnect(),this.#i=null),document.removeEventListener("wheel",this.#t),document.removeEventListener("pointermove",this.#o),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#h),document.removeEventListener("pointercancel",this.#h),document.removeEventListener("dblclick",this.#c)}#t=e=>{if(e.target===this.#e)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#r(e,"zoom");this.#n(t)}else{let t=this.#r(e,"scroll");this.#n(t)}};#o=e=>{let t=this.#r(e,"move");this.#f=t,!this.#l&&(this.#l=requestAnimationFrame(()=>{this.#f&&(this.#n(this.#f),this.#f=null),this.#l=null}))};#d=e=>{if(e.target===this.#e){let t=this.#r(e,"down");this.#n(t)}};#h=e=>{let t=this.#r(e,"up");this.#n(t)};#c=e=>{let t=this.#r(e,"dblclick");this.#n(t)};#n(e){for(let t of this.#a)t(e)}#r(e,t){let s=e.target===this.#e,a,i;s?(a=e.offsetX,i=e.offsetY):this.#s?(a=e.clientX-this.#s.left,i=e.clientY-this.#s.top):(a=e.clientX,i=e.clientY);let d=s||this.#s&&a>=0&&a<=this.#s.width&&i>=0&&i<=this.#s.height,o={x:a,y:i,type:t,isOverCanvas:s,isWithinBounds:d,clientX:e.clientX,clientY:e.clientY,button:e.button??null,buttons:e.buttons??0,timestamp:Date.now()};return(t==="scroll"||t==="zoom")&&(o.deltaX=e.deltaX,o.deltaY=e.deltaY,o.deltaZ=e.deltaZ,o.deltaMode=e.deltaMode),o.shiftKey=e.shiftKey||!1,o.ctrlKey=e.ctrlKey||!1,o.altKey=e.altKey||!1,o.metaKey=e.metaKey||!1,o}destroy(){this.#l&&(cancelAnimationFrame(this.#l),this.#l=null),this.#m(),this.#e=null,this.#s=null,this.#a.clear()}};import{defineSurface as ye}from"@jucie-state/reactive";var j=ye(n=>{let e=n.value(0),t=n.value(0),s=n.value(0),a=n.value(0),i=n.value(0),d=n.value(0),o=n.value(!1),y=n.value(!1),g=n.value(!1),p=n.value(null),l=n.value(0),f=n.value(null),m=n.value(null),C=n.value(null),Y=n.value(null),B=n.value(null),$=n.value(null),O=n.value(null),u=n.value(!1),P=n.value(0),T=n.value(0),r=n.value(0),E=n.value(0),S=n.value(0),x=n.value(0),R=n.value(0),V=n.value(null),z=n.value(null),D=n.value({dragThreshold:5,doubleClickThreshold:300,holdThreshold:500,velocitySmoothing:.3,maxVelocity:1e4}),q=n.computed(()=>({x:e.value,y:t.value})),Z=n.computed(()=>({x:i.value,y:d.value})),G=n.computed(()=>({x:s.value,y:a.value})),N=n.computed(()=>{let h=typeof e.value=="number"?e.value:0,c=typeof s.value=="number"?s.value:0,v=typeof t.value=="number"?t.value:0,b=typeof a.value=="number"?a.value:0;return{x:h-c,y:v-b}}),J=n.computed(()=>({x:r.value,y:E.value})),Q=n.computed(()=>{let h=r.value,c=E.value;return Math.sqrt(h*h+c*c)}),W=n.computed(()=>{let h=$.value,c=O.value;if(h===null||c===null||typeof h!="number"||typeof c!="number")return 0;let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0,L=v-h,w=b-c;return Math.sqrt(L*L+w*w)}),ee=n.computed(()=>{let h=$.value,c=O.value;if(h===null||c===null||typeof h!="number"||typeof c!="number")return{x:0,y:0};let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0;return{x:v-h,y:b-c}}),K=n.computed(()=>!g.value||!m.value?0:Date.now()-m.value),te=n.computed(()=>K.value>D.value.holdThreshold&&!u.value),re=n.computed(()=>{let h=B.value;return h?Date.now()-h:0}),ae=n.computed(()=>({position:q.value,clientPosition:Z.value,previousPosition:G.value,delta:N.value,velocity:J.value,speed:Q.value,isPressed:g.value,button:p.value,buttons:l.value,isDragging:u.value,dragDistance:W.value,dragDelta:ee.value,isHolding:te.value,holdDuration:K.value,isOverCanvas:o.value,isWithinBounds:y.value,hoveredArea:V.value,activeArea:z.value,clickCount:P.value,lastEventType:f.value})),A=n.action((h,c,v,b,L)=>{s.value=e.value,a.value=t.value,e.value=c,t.value=v,i.value=b,d.value=L,Y.value=Date.now()}),oe=n.action(()=>{let h=Date.now(),c=Y.value;if(c){let v=(h-c)/1e3;if(v>0&&v<.1){let b=(e.value-s.value)/v,L=(t.value-a.value)/v,w=D.value.maxVelocity,k=Math.max(-w,Math.min(w,b)),I=Math.max(-w,Math.min(w,L)),M=D.value.velocitySmoothing;r.value=r.value*(1-M)+k*M,E.value=E.value*(1-M)+I*M}}}),le=n.action((h,c)=>{let{x:v,y:b,type:L,clientX:w,clientY:k,button:I,buttons:M,isOverCanvas:fe,isWithinBounds:ve}=c,F=Date.now();switch(B.value=F,f.value=L,o.value=fe,y.value=ve,L){case"down":A(h,v,b,w,k),g.value=!0,m.value=F,p.value=I,l.value=M,$.value=v,O.value=b,u.value=!1,F-T.value<D.value.doubleClickThreshold?P.value=P.value+1:P.value=1;break;case"up":A(h,v,b,w,k),g.value=!1,C.value=F,T.value=F,u.value=!1,r.value=0,E.value=0,l.value=M;break;case"move":A(h,v,b,w,k),oe(),l.value=M,g.value&&!u.value&&W.value>D.value.dragThreshold&&(u.value=!0);break;case"dblclick":A(h,v,b,w,k),P.value=2;break;case"scroll":A(h,v,b,w,k),c.deltaX!==void 0&&(S.value=c.deltaX),c.deltaY!==void 0&&(x.value=c.deltaY);break;case"zoom":A(h,v,b,w,k),c.deltaY!==void 0&&(R.value=c.deltaY);break}}),ce=n.action((h,c)=>{V.value=c}),ue=n.action((h,c)=>{z.value=c}),he=n.action(()=>{g.value=!1,u.value=!1,z.value=null,V.value=null,r.value=0,E.value=0,P.value=0,S.value=0,x.value=0,R.value=0}),de=n.action((h,c)=>{D.value={...D.value,...c}});return{state:ae,position:q,clientPosition:Z,previousPosition:G,delta:N,velocity:J,speed:Q,isPressed:g,button:p,buttons:l,isDragging:u,dragDistance:W,dragDelta:ee,isHolding:te,holdDuration:K,isOverCanvas:o,isWithinBounds:y,hoveredArea:V,activeArea:z,clickCount:P,lastEventType:f,timeSinceLastEvent:re,handleEvent:le,setHoveredArea:ce,setActiveArea:ue,reset:he,updateConfig:de}});var pe=ne("BRUSH",[Object]),xe=ne("LAYER",[Object]),H=class extends be{#e=new Map;#s=null;#i=new Map;#a=new Map;#f=new Map;#l=!1;#u=null;#b=!1;#m=!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};#d={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#h=new X;#c=null;#n=j();#r=null;#y=new Map;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.state}}actions(){return this.config&&Object.assign(this.#t,this.config),{addLayer:e=>this.addLayer(e),addLayers:(...e)=>{for(let t of e)this.addLayer(t)},updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.removeLayer(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),subscribeToPointer:e=>this.#n.$subscribe(e),bindPointer:e=>this.#n.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){this.#s=e,Object.values(U).forEach(t=>{try{let s=e.getContext(t);s&&this.#i.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}}),this.#c||(this.#c=new _),this.#c.setCanvas(e),this.#r&&this.#r(),this.#r=this.#c.subscribe(t=>{this.#n.handleEvent(t),this.#w(t)})}updateCanvas(e){let t=e(this.#s);t&&(this.#s=t)}setAssets(e){this.#f=e}start(){this.#l||(this.#l=!0,this.#p())}stop(){this.#l&&(this.#l=!1,this.#u&&(cancelAnimationFrame(this.#u),this.#u=null))}addLayer(e){var d;if(ie(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#h);if(s.data){let o=this.#x(`layer_${t}`,s.data);o&&this.#a.set(`layer_${t}`,o)}let a=s.children.map(o=>{var y;if(ie(o)==="BRUSH"){let g=o._name,p=o(this.useContext,this.#h),l=p.data?this.#x(`brush_${g}`,p.data):()=>{},f=p.when?se(p.when,{immediate:!0,context:this.useContext("state")}):null,m={name:g,...p,dataReactor:l,whenReactor:f};if((y=m.lifecycle)!=null&&y.onMount)try{m.lifecycle.onMount(this.#i.get(m.context||s.context))}catch(C){console.error(`Error in brush "${m.name}" onMount:`,C)}return m}return this.addLayer(o)}),i={...s,name:t,brushes:a,context:this.#i.get(s.context)};if(this.#e.set(t,i),(d=i.lifecycle)!=null&&d.onMount)try{i.lifecycle.onMount(i.context)}catch(o){console.error(`Error in layer "${t}" onMount:`,o)}return i}removeLayer(e){var a;let t=this.#e.get(e);if(!t)return;if((a=t.lifecycle)!=null&&a.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(i){console.error(`Error in layer "${e}" onUnmount:`,i)}t.brushes.forEach(i=>{var o;if((o=i.lifecycle)!=null&&o.onUnmount)try{i.lifecycle.onUnmount(this.#i.get(i.context||t.context))}catch(y){console.error(`Error in brush "${i.name}" onUnmount:`,y)}let d=this.#a.get(`painter_brush_${i.name}`);d&&(d.unsubscribe(),d.reactor.destroy(),this.#a.delete(`painter_brush_${i.name}`))});let s=this.#a.get(`painter_layer_${e}`);s&&(s.unsubscribe(),s.reactor.destroy(),this.#a.delete(`painter_layer_${e}`)),this.#e.delete(e)}#p(){this.#m||this.#b||(this.#m=!0,this.#u=requestAnimationFrame(()=>{this.#m=!1,this.#u=null,this.#E()}))}async#E(){var e,t,s,a,i,d,o,y,g,p,l,f,m,C,Y,B,$;if(this.#s){this.#b=!0;try{this.#h.clear();let O=(e=this.#t.debug)!=null&&e.enabled?performance.now():0;this.#i.forEach(u=>{u.clearRect(0,0,this.#s.width,this.#s.height)});for(let u of this.#e.values()){let P=(t=this.#t.debug)!=null&&t.enabled?performance.now():0;if(u.whenReactor){let r=(s=this.#a.get(`painter_layer_${u.name}`))==null?void 0:s.reactor;if(!u.when(r()))continue}let T=u.context;if(T){if((a=u.lifecycle)!=null&&a.beforeRender)try{u.lifecycle.beforeRender(T,this.#o)}catch(r){console.error(`Error in layer "${u.name}" beforeRender:`,r),(i=u.lifecycle)!=null&&i.onError&&u.lifecycle.onError(r)}T.save(),u.settings&&Object.entries(u.settings).forEach(([r,E])=>{typeof T[r]=="function"?T[r](...Array.isArray(E)?E:[E]):T[r]=E});for(let r of u.brushes){let E=(d=this.#t.debug)!=null&&d.enabled?performance.now():0;if(r.whenReactor&&!r.whenReactor())continue;let S=r.context?this.#i.get(r.context):T;if(S){if((o=r.lifecycle)!=null&&o.beforeRender)try{r.lifecycle.beforeRender(S,this.#o)}catch(x){console.error(`Error in brush "${r.name}" beforeRender:`,x),(y=r.lifecycle)!=null&&y.onError&&r.lifecycle.onError(x);continue}S.save(),r.settings&&Object.entries(r.settings).forEach(([x,R])=>{typeof S[x]=="function"?S[x](...Array.isArray(R)?R:[R]):S[x]=R});try{let x={};if(r.assets)for(let R of r.assets)x[R]=this.#f.get(R);if(r.render(S,r.dataReactor(),x,this.#o),(g=r.lifecycle)!=null&&g.afterRender&&r.lifecycle.afterRender(S,this.#o),(p=this.#t.debug)!=null&&p.enabled){let R=performance.now()-E;this.#d.brushTimes.set(r.name,R),(l=this.#t.debug)!=null&&l.showBounds&&this.#S(S,r)}}catch(x){console.error(`Error in brush "${r.name}":`,x),(f=r.lifecycle)!=null&&f.onError&&r.lifecycle.onError(x)}finally{S.restore()}}}if(T.restore(),(m=u.lifecycle)!=null&&m.afterRender)try{u.lifecycle.afterRender(T,this.#o)}catch(r){console.error(`Error in layer "${u.name}" afterRender:`,r),(C=u.lifecycle)!=null&&C.onError&&u.lifecycle.onError(r)}if((Y=this.#t.debug)!=null&&Y.enabled){let r=performance.now()-P;this.#d.layerTimes.set(u.name,r),(B=this.#t.debug)!=null&&B.showBounds&&this.#C(T,u)}}}($=this.#t.debug)!=null&&$.enabled&&this.#R()}finally{this.#b=!1}}}#S(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()}#C(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()}#R(){var a,i;let e=this.#i.get(U["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((a=this.#t.debug)!=null&&a.showFPS){let d=`FPS: ${Math.round(this.#d.fps)} (${this.#o.deltaTime.toFixed(2)}ms)`;e.strokeText(d,10,t),e.fillText(d,10,t),t+=s}if((i=this.#t.debug)!=null&&i.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[d,o]of this.#d.layerTimes){let y=` ${d}: ${o.toFixed(2)}ms`;e.strokeText(y,10,t),e.fillText(y,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){var s,a;for(let i of this.#e.values())if((s=i.lifecycle)!=null&&s.onResize)try{i.lifecycle.onResize(e,t,i.context)}catch(d){console.error(`Error in layer "${i.name}" onResize:`,d),(a=i.lifecycle)!=null&&a.onError&&i.lifecycle.onError(d)}}#x(e,t){let s=this.useContext("state"),a=se(t,{immediate:!0,context:s}),i=ge(a,()=>this.#p());return this.#a.set(`painter_${e}`,{reactor:a,unsubscribe:i}),a}destroy(){this.stop(),this.#r&&(this.#r(),this.#r=null),this.#c&&(this.#c.destroy(),this.#c=null),this.#n&&this.#n.$destroy();for(let e of this.#e.keys())this.removeLayer(e)}setTargetFPS(e){this.#t.targetFPS=e,this.#t.fixedTimeStep=1e3/e}setTimeScale(e){this.#t.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#t.fixedTimeStep=e}setDebug(e={}){this.#t.debug||(this.#t.debug={}),Object.assign(this.#t.debug,e)}getMetrics(){return{...this.#d,deltaTime:this.#o.deltaTime,elapsedTime:this.#o.elapsedTime,frameCount:this.#o.frameCount}}#w(e){var d,o,y,g,p;let{type:t,x:s,y:a}=e,i=this.#n;switch(t){case"down":{let l=this.#T(s,a);if(i.setActiveArea(l),(d=l==null?void 0:l.onPointerDown)!=null&&d.handler){let f=this.#g(l);l.onPointerDown.handler({...i.state,ctx:f,emit:this.#v.bind(this)})}break}case"up":{let l=i.activeArea;if((o=l==null?void 0:l.onPointerUp)!=null&&o.handler){let f=this.#g(l);l.onPointerUp.handler({...i.state,ctx:f,emit:this.#v.bind(this)})}break}case"move":{let l=this.#T(s,a),f=i.hoveredArea,m=i.activeArea;if((y=m==null?void 0:m.onPointerMove)!=null&&y.handler&&i.isDragging){let C=this.#g(m);m.onPointerMove.handler({...i.state,ctx:C,emit:this.#v.bind(this)})}if((l==null?void 0:l.id)!==(f==null?void 0:f.id)){if((g=f==null?void 0:f.onPointerLeave)!=null&&g.handler){let C=this.#g(f);f.onPointerLeave.handler({...i.state,ctx:C,emit:this.#v.bind(this)})}if((p=l==null?void 0:l.onPointerEnter)!=null&&p.handler){let C=this.#g(l);l.onPointerEnter.handler({...i.state,ctx:C,emit:this.#v.bind(this)})}i.setHoveredArea(l)}break}case"scroll":case"zoom":this.#v(`pointer:${t}`,i.state);break;case"dblclick":this.#v("pointer:dblclick",i.state);break}}#g(e){return e?e.context?this.#i.get(e.context):this.#i.get(U["2D"]):null}subscribe(e,t){return this.#y.has(e)||this.#y.set(e,new Set),this.#y.get(e).add(t),()=>{let s=this.#y.get(e);s&&(s.delete(t),s.size===0&&this.#y.delete(e))}}#T(e,t){let s=this.#h.areas.sort((a,i)=>(i.priority||0)-(a.priority||0));for(let a of s)if(this.#P(e,t,a.bounds))return a;return null}#P(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#v(e,t){let s=this.#y.get(e);if(s)for(let a of s)a(t)}_testEmitPointerEvent(e){this.#n.handleEvent(e),this.#w(e)}};export{_ as CanvasPointer,X as HitRegistry,H as Painter,pe as defineBrush,xe as defineLayer,j as usePointerSurface};
|
|
1
|
+
import{ServiceProvider as be}from"@jucie-engine/core";var O={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};import{createReactor as se,addEffect as ge}from"@jucie-state/reactive";import{createDefinition as ne,definitionType as ie}from"@jucie-engine/core";var X=class{#e=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#e.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#e.delete(e)}get(e){return this.#e.get(e)}has(e){return this.#e.has(e)}get areas(){return Array.from(this.#e.values())}clear(){this.#e.clear()}};import{ServiceProvider as me}from"@jucie-engine/core";var _=class extends me{#e=null;#s=null;#i=null;#a=new Set;#f=null;#l=null;static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e)}}setCanvas(e){this.#e&&this.#m(),this.#e=e,this.#h(),this.#b()}subscribe(e){return this.#a.add(e),()=>this.#a.delete(e)}#h(){this.#e&&(this.#s=this.#e.getBoundingClientRect())}#b(){this.#e&&(this.#h(),this.#i=new ResizeObserver(()=>{this.#h()}),this.#i.observe(this.#e),document.addEventListener("wheel",this.#t,{passive:!1}),document.addEventListener("pointermove",this.#o),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#u),document.addEventListener("pointercancel",this.#u),document.addEventListener("dblclick",this.#c))}#m(){this.#i&&(this.#i.disconnect(),this.#i=null),document.removeEventListener("wheel",this.#t),document.removeEventListener("pointermove",this.#o),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#u),document.removeEventListener("pointercancel",this.#u),document.removeEventListener("dblclick",this.#c)}#t=e=>{if(e.target===this.#e)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#r(e,"zoom");this.#n(t)}else{let t=this.#r(e,"scroll");this.#n(t)}};#o=e=>{let t=this.#r(e,"move");this.#f=t,!this.#l&&(this.#l=requestAnimationFrame(()=>{this.#f&&(this.#n(this.#f),this.#f=null),this.#l=null}))};#d=e=>{if(e.target===this.#e){let t=this.#r(e,"down");this.#n(t)}};#u=e=>{let t=this.#r(e,"up");this.#n(t)};#c=e=>{let t=this.#r(e,"dblclick");this.#n(t)};#n(e){for(let t of this.#a)t(e)}#r(e,t){let s=e.target===this.#e,r,i;s?(r=e.offsetX,i=e.offsetY):this.#s?(r=e.clientX-this.#s.left,i=e.clientY-this.#s.top):(r=e.clientX,i=e.clientY);let d=s||this.#s&&r>=0&&r<=this.#s.width&&i>=0&&i<=this.#s.height,o={x:r,y:i,type:t,isOverCanvas:s,isWithinBounds:d,clientX:e.clientX,clientY:e.clientY,button:e.button??null,buttons:e.buttons??0,timestamp:Date.now()};return(t==="scroll"||t==="zoom")&&(o.deltaX=e.deltaX,o.deltaY=e.deltaY,o.deltaZ=e.deltaZ,o.deltaMode=e.deltaMode),o.shiftKey=e.shiftKey||!1,o.ctrlKey=e.ctrlKey||!1,o.altKey=e.altKey||!1,o.metaKey=e.metaKey||!1,o}destroy(){this.#l&&(cancelAnimationFrame(this.#l),this.#l=null),this.#m(),this.#e=null,this.#s=null,this.#a.clear()}};import{defineSurface as ye}from"@jucie-state/reactive";var I=ye(n=>{let e=n.value(0),t=n.value(0),s=n.value(0),r=n.value(0),i=n.value(0),d=n.value(0),o=n.value(!1),y=n.value(!1),g=n.value(!1),p=n.value(null),l=n.value(0),f=n.value(null),m=n.value(null),C=n.value(null),Y=n.value(null),B=n.value(null),$=n.value(null),V=n.value(null),h=n.value(!1),P=n.value(0),E=n.value(0),a=n.value(0),T=n.value(0),S=n.value(0),x=n.value(0),R=n.value(0),z=n.value(null),U=n.value(null),D=n.value({dragThreshold:5,doubleClickThreshold:300,holdThreshold:500,velocitySmoothing:.3,maxVelocity:1e4}),q=n.computed(()=>({x:e.value,y:t.value})),Z=n.computed(()=>({x:i.value,y:d.value})),G=n.computed(()=>({x:s.value,y:r.value})),N=n.computed(()=>{let u=typeof e.value=="number"?e.value:0,c=typeof s.value=="number"?s.value:0,v=typeof t.value=="number"?t.value:0,b=typeof r.value=="number"?r.value:0;return{x:u-c,y:v-b}}),J=n.computed(()=>({x:a.value,y:T.value})),Q=n.computed(()=>{let u=a.value,c=T.value;return Math.sqrt(u*u+c*c)}),W=n.computed(()=>{let u=$.value,c=V.value;if(u===null||c===null||typeof u!="number"||typeof c!="number")return 0;let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0,L=v-u,w=b-c;return Math.sqrt(L*L+w*w)}),ee=n.computed(()=>{let u=$.value,c=V.value;if(u===null||c===null||typeof u!="number"||typeof c!="number")return{x:0,y:0};let v=typeof e.value=="number"?e.value:0,b=typeof t.value=="number"?t.value:0;return{x:v-u,y:b-c}}),K=n.computed(()=>!g.value||!m.value?0:Date.now()-m.value),te=n.computed(()=>K.value>D.value.holdThreshold&&!h.value),re=n.computed(()=>{let u=B.value;return u?Date.now()-u:0}),ae=n.computed(()=>({position:q.value,clientPosition:Z.value,previousPosition:G.value,delta:N.value,velocity:J.value,speed:Q.value,isPressed:g.value,button:p.value,buttons:l.value,isDragging:h.value,dragDistance:W.value,dragDelta:ee.value,isHolding:te.value,holdDuration:K.value,isOverCanvas:o.value,isWithinBounds:y.value,hoveredArea:z.value,activeArea:U.value,clickCount:P.value,lastEventType:f.value})),A=n.action((u,c,v,b,L)=>{s.value=e.value,r.value=t.value,e.value=c,t.value=v,i.value=b,d.value=L,Y.value=Date.now()}),oe=n.action(()=>{let u=Date.now(),c=Y.value;if(c){let v=(u-c)/1e3;if(v>0&&v<.1){let b=(e.value-s.value)/v,L=(t.value-r.value)/v,w=D.value.maxVelocity,k=Math.max(-w,Math.min(w,b)),j=Math.max(-w,Math.min(w,L)),M=D.value.velocitySmoothing;a.value=a.value*(1-M)+k*M,T.value=T.value*(1-M)+j*M}}}),le=n.action((u,c)=>{let{x:v,y:b,type:L,clientX:w,clientY:k,button:j,buttons:M,isOverCanvas:fe,isWithinBounds:ve}=c,F=Date.now();switch(B.value=F,f.value=L,o.value=fe,y.value=ve,L){case"down":A(u,v,b,w,k),g.value=!0,m.value=F,p.value=j,l.value=M,$.value=v,V.value=b,h.value=!1,F-E.value<D.value.doubleClickThreshold?P.value=P.value+1:P.value=1;break;case"up":A(u,v,b,w,k),g.value=!1,C.value=F,E.value=F,h.value=!1,a.value=0,T.value=0,l.value=M;break;case"move":A(u,v,b,w,k),oe(),l.value=M,g.value&&!h.value&&W.value>D.value.dragThreshold&&(h.value=!0);break;case"dblclick":A(u,v,b,w,k),P.value=2;break;case"scroll":A(u,v,b,w,k),c.deltaX!==void 0&&(S.value=c.deltaX),c.deltaY!==void 0&&(x.value=c.deltaY);break;case"zoom":A(u,v,b,w,k),c.deltaY!==void 0&&(R.value=c.deltaY);break}}),ce=n.action((u,c)=>{z.value=c}),he=n.action((u,c)=>{U.value=c}),ue=n.action(()=>{g.value=!1,h.value=!1,U.value=null,z.value=null,a.value=0,T.value=0,P.value=0,S.value=0,x.value=0,R.value=0}),de=n.action((u,c)=>{D.value={...D.value,...c}});return{state:ae,position:q,clientPosition:Z,previousPosition:G,delta:N,velocity:J,speed:Q,isPressed:g,button:p,buttons:l,isDragging:h,dragDistance:W,dragDelta:ee,isHolding:te,holdDuration:K,isOverCanvas:o,isWithinBounds:y,hoveredArea:z,activeArea:U,clickCount:P,lastEventType:f,timeSinceLastEvent:re,handleEvent:le,setHoveredArea:ce,setActiveArea:he,reset:ue,updateConfig:de}});var pe=ne("BRUSH",[Object]),xe=ne("LAYER",[Object]),H=class extends be{#e=new Map;#s=null;#i=new Map;#a=new Map;#f=new Map;#l=!1;#h=null;#b=!1;#m=!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};#d={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#u=new X;#c=I();#n=null;#r=null;#y=new Map;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.#c.state}}actions(){return this.config&&Object.assign(this.#t,this.config),{addLayer:e=>this.addLayer(e),addLayers:(...e)=>{for(let t of e)this.addLayer(t)},updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setOffscreenCanvas:e=>this.setOffscreenCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.removeLayer(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.#c.$subscribe(e),bindPointer:e=>this.#c.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){let t=e.transferControlToOffscreen();this.#s=t,Object.values(O).forEach(s=>{try{let r=t.getContext(s);r&&this.#i.set(s,r)}catch{console.warn(`Context type ${s} not supported`)}}),this.#n||(this.#n=new _),this.#n.setCanvas(e),this.#r&&this.#r(),this.#r=this.#n.subscribe(s=>{this.handlePointerEvent(s)})}setOffscreenCanvas(e){this.#s=e,Object.values(O).forEach(t=>{try{let s=e.getContext(t);s&&this.#i.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#s);t&&(this.#s=t)}setAssets(e){this.#f=e}start(){this.#l||(this.#l=!0,this.#p())}stop(){this.#l&&(this.#l=!1,this.#h&&(cancelAnimationFrame(this.#h),this.#h=null))}addLayer(e){var d;if(ie(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#u);if(s.data){let o=this.#x(`layer_${t}`,s.data);o&&this.#a.set(`layer_${t}`,o)}let r=s.children.map(o=>{var y;if(ie(o)==="BRUSH"){let g=o._name,p=o(this.useContext,this.#u),l=p.data?this.#x(`brush_${g}`,p.data):()=>{},f=p.when?se(p.when,{immediate:!0,context:this.useContext("state")}):null,m={name:g,...p,dataReactor:l,whenReactor:f};if((y=m.lifecycle)!=null&&y.onMount)try{m.lifecycle.onMount(this.#i.get(m.context||s.context))}catch(C){console.error(`Error in brush "${m.name}" onMount:`,C)}return m}return this.addLayer(o)}),i={...s,name:t,brushes:r,context:this.#i.get(s.context)};if(this.#e.set(t,i),(d=i.lifecycle)!=null&&d.onMount)try{i.lifecycle.onMount(i.context)}catch(o){console.error(`Error in layer "${t}" onMount:`,o)}return i}removeLayer(e){var r;let t=this.#e.get(e);if(!t)return;if((r=t.lifecycle)!=null&&r.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(i){console.error(`Error in layer "${e}" onUnmount:`,i)}t.brushes.forEach(i=>{var o;if((o=i.lifecycle)!=null&&o.onUnmount)try{i.lifecycle.onUnmount(this.#i.get(i.context||t.context))}catch(y){console.error(`Error in brush "${i.name}" onUnmount:`,y)}let d=this.#a.get(`painter_brush_${i.name}`);d&&(d.unsubscribe(),d.reactor.destroy(),this.#a.delete(`painter_brush_${i.name}`))});let s=this.#a.get(`painter_layer_${e}`);s&&(s.unsubscribe(),s.reactor.destroy(),this.#a.delete(`painter_layer_${e}`)),this.#e.delete(e)}#p(){this.#m||this.#b||(this.#m=!0,this.#h=requestAnimationFrame(()=>{this.#m=!1,this.#h=null,this.#T()}))}async#T(){var e,t,s,r,i,d,o,y,g,p,l,f,m,C,Y,B,$;if(this.#s){this.#b=!0;try{this.#u.clear();let V=(e=this.#t.debug)!=null&&e.enabled?performance.now():0;this.#i.forEach(h=>{h.clearRect(0,0,this.#s.width,this.#s.height)});for(let h of this.#e.values()){let P=(t=this.#t.debug)!=null&&t.enabled?performance.now():0;if(h.whenReactor){let a=(s=this.#a.get(`painter_layer_${h.name}`))==null?void 0:s.reactor;if(!h.when(a()))continue}let E=h.context;if(E){if((r=h.lifecycle)!=null&&r.beforeRender)try{h.lifecycle.beforeRender(E,this.#o)}catch(a){console.error(`Error in layer "${h.name}" beforeRender:`,a),(i=h.lifecycle)!=null&&i.onError&&h.lifecycle.onError(a)}E.save(),h.settings&&Object.entries(h.settings).forEach(([a,T])=>{typeof E[a]=="function"?E[a](...Array.isArray(T)?T:[T]):E[a]=T});for(let a of h.brushes){let T=(d=this.#t.debug)!=null&&d.enabled?performance.now():0;if(a.whenReactor&&!a.whenReactor())continue;let S=a.context?this.#i.get(a.context):E;if(S){if((o=a.lifecycle)!=null&&o.beforeRender)try{a.lifecycle.beforeRender(S,this.#o)}catch(x){console.error(`Error in brush "${a.name}" beforeRender:`,x),(y=a.lifecycle)!=null&&y.onError&&a.lifecycle.onError(x);continue}S.save(),a.settings&&Object.entries(a.settings).forEach(([x,R])=>{typeof S[x]=="function"?S[x](...Array.isArray(R)?R:[R]):S[x]=R});try{let x={};if(a.assets)for(let R of a.assets)x[R]=this.#f.get(R);if(a.render(S,a.dataReactor(),x,this.#o),(g=a.lifecycle)!=null&&g.afterRender&&a.lifecycle.afterRender(S,this.#o),(p=this.#t.debug)!=null&&p.enabled){let R=performance.now()-T;this.#d.brushTimes.set(a.name,R),(l=this.#t.debug)!=null&&l.showBounds&&this.#S(S,a)}}catch(x){console.error(`Error in brush "${a.name}":`,x),(f=a.lifecycle)!=null&&f.onError&&a.lifecycle.onError(x)}finally{S.restore()}}}if(E.restore(),(m=h.lifecycle)!=null&&m.afterRender)try{h.lifecycle.afterRender(E,this.#o)}catch(a){console.error(`Error in layer "${h.name}" afterRender:`,a),(C=h.lifecycle)!=null&&C.onError&&h.lifecycle.onError(a)}if((Y=this.#t.debug)!=null&&Y.enabled){let a=performance.now()-P;this.#d.layerTimes.set(h.name,a),(B=this.#t.debug)!=null&&B.showBounds&&this.#C(E,h)}}}($=this.#t.debug)!=null&&$.enabled&&this.#R()}finally{this.#b=!1}}}#S(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()}#C(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()}#R(){var r,i;let e=this.#i.get(O["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((r=this.#t.debug)!=null&&r.showFPS){let d=`FPS: ${Math.round(this.#d.fps)} (${this.#o.deltaTime.toFixed(2)}ms)`;e.strokeText(d,10,t),e.fillText(d,10,t),t+=s}if((i=this.#t.debug)!=null&&i.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[d,o]of this.#d.layerTimes){let y=` ${d}: ${o.toFixed(2)}ms`;e.strokeText(y,10,t),e.fillText(y,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){var s,r;for(let i of this.#e.values())if((s=i.lifecycle)!=null&&s.onResize)try{i.lifecycle.onResize(e,t,i.context)}catch(d){console.error(`Error in layer "${i.name}" onResize:`,d),(r=i.lifecycle)!=null&&r.onError&&i.lifecycle.onError(d)}}#x(e,t){let s=this.useContext("state"),r=se(t,{immediate:!0,context:s}),i=ge(r,()=>this.#p());return this.#a.set(`painter_${e}`,{reactor:r,unsubscribe:i}),r}destroy(){this.stop(),this.#r&&(this.#r(),this.#r=null),this.#n&&(this.#n.destroy(),this.#n=null),this.#c&&this.#c.$destroy();for(let e of this.#e.keys())this.removeLayer(e)}setTargetFPS(e){this.#t.targetFPS=e,this.#t.fixedTimeStep=1e3/e}setTimeScale(e){this.#t.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#t.fixedTimeStep=e}setDebug(e={}){this.#t.debug||(this.#t.debug={}),Object.assign(this.#t.debug,e)}getMetrics(){return{...this.#d,deltaTime:this.#o.deltaTime,elapsedTime:this.#o.elapsedTime,frameCount:this.#o.frameCount}}handlePointerEvent(e){this.#c.handleEvent(e),this.#w(e)}#w(e){var d,o,y,g,p;let{type:t,x:s,y:r}=e,i=this.#c;switch(t){case"down":{let l=this.#E(s,r);if(i.setActiveArea(l),(d=l==null?void 0:l.onPointerDown)!=null&&d.handler){let f=this.#g(l);l.onPointerDown.handler({...i.state,ctx:f,emit:this.#v.bind(this)})}break}case"up":{let l=i.activeArea;if((o=l==null?void 0:l.onPointerUp)!=null&&o.handler){let f=this.#g(l);l.onPointerUp.handler({...i.state,ctx:f,emit:this.#v.bind(this)})}break}case"move":{let l=this.#E(s,r),f=i.hoveredArea,m=i.activeArea;if((y=m==null?void 0:m.onPointerMove)!=null&&y.handler&&i.isDragging){let C=this.#g(m);m.onPointerMove.handler({...i.state,ctx:C,emit:this.#v.bind(this)})}if((l==null?void 0:l.id)!==(f==null?void 0:f.id)){if((g=f==null?void 0:f.onPointerLeave)!=null&&g.handler){let C=this.#g(f);f.onPointerLeave.handler({...i.state,ctx:C,emit:this.#v.bind(this)})}if((p=l==null?void 0:l.onPointerEnter)!=null&&p.handler){let C=this.#g(l);l.onPointerEnter.handler({...i.state,ctx:C,emit:this.#v.bind(this)})}i.setHoveredArea(l)}break}case"scroll":case"zoom":this.#v(`pointer:${t}`,i.state);break;case"dblclick":this.#v("pointer:dblclick",i.state);break}}#g(e){return e?e.context?this.#i.get(e.context):this.#i.get(O["2D"]):null}subscribe(e,t){return this.#y.has(e)||this.#y.set(e,new Set),this.#y.get(e).add(t),()=>{let s=this.#y.get(e);s&&(s.delete(t),s.size===0&&this.#y.delete(e))}}#E(e,t){let s=this.#u.areas.sort((r,i)=>(i.priority||0)-(r.priority||0));for(let r of s)if(this.#P(e,t,r.bounds))return r;return null}#P(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#v(e,t){let s=this.#y.get(e);if(s)for(let r of s)r(t)}_testEmitPointerEvent(e){this.#c.handleEvent(e),this.#w(e)}};export{_ as CanvasEvents,X as HitRegistry,H as Painter,pe as defineBrush,xe as defineLayer,I as usePointerSurface};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/Painter.js", "../src/ContextTypes.js", "../src/HitRegistry.js", "../src/
|
|
4
|
-
"sourcesContent": ["import { ServiceProvider } from '@jucie-engine/core';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createReactor, addEffect } from '@jucie-state/reactive';\nimport { createDefinition, definitionType } from '@jucie-engine/core';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasPointer } from './CanvasPointer.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nexport const defineBrush = createDefinition('BRUSH', [Object]);\nexport const defineLayer = createDefinition('LAYER', [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #canvas = null;\n #contexts = new Map();\n #reactors = 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 #canvasPointer = null;\n #pointerSurface = usePointerSurface();\n #pointerUnsubscribe = null;\n #subscribers = new Map(); // Map<event, Set<callback>>\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.state,\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 updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\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\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 setCanvas(canvas) {\n this.#canvas = canvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = canvas.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 // Set up canvas pointer if not already\n if (!this.#canvasPointer) {\n this.#canvasPointer = new CanvasPointer();\n }\n\n this.#canvasPointer.setCanvas(canvas);\n\n // Connect canvas pointer to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasPointer.subscribe((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 }\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 // Set up layer reactor if it has data paths\n if (config.data) {\n const dataReactor = this.#createDataReactor(`layer_${name}`, config.data);\n if (dataReactor) {\n this.#reactors.set(`layer_${name}`, dataReactor);\n }\n }\n\n // Set up brush reactors and structure\n const brushes = config.children.map(child => {\n if (definitionType(child) === 'BRUSH') {\n const name = child._name;\n const brushConfig = child(this.useContext, this.#hitRegistry);\n \n // Only create data reactor if data exists\n const dataReactor = brushConfig.data \n ? this.#createDataReactor(`brush_${name}`, brushConfig.data)\n : () => undefined;\n \n const whenReactor = brushConfig.when \n ? createReactor(brushConfig.when, {\n immediate: true,\n context: this.useContext('state')\n })\n : null;\n\n const brush = {\n name,\n ...brushConfig,\n dataReactor,\n whenReactor\n };\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || config.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n return brush;\n }\n // Handle nested layers recursively\n return this.addLayer(child);\n });\n\n const layer = {\n ...config,\n name,\n brushes,\n context: this.#contexts.get(config.context)\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 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 // Call brush unmount hooks and clean up reactors\n layer.brushes.forEach(brush => {\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 reactor and subscription\n const reactorData = this.#reactors.get(`painter_brush_${brush.name}`);\n if (reactorData) {\n reactorData.unsubscribe();\n reactorData.reactor.destroy();\n this.#reactors.delete(`painter_brush_${brush.name}`);\n }\n });\n\n // Clean up layer reactor and subscription\n const layerReactorData = this.#reactors.get(`painter_layer_${name}`);\n if (layerReactorData) {\n layerReactorData.unsubscribe();\n layerReactorData.reactor.destroy();\n this.#reactors.delete(`painter_layer_${name}`);\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) {\n const layerReactor = this.#reactors.get(`painter_layer_${layer.name}`)?.reactor;\n if (!layer.when(layerReactor())) continue;\n }\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 // Render brushes\n for (const brush of layer.brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor()) 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(), 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 #createDataReactor(id, data) {\n const state = this.useContext('state');\n\n const reactor = createReactor(data, {\n immediate: true,\n context: state\n });\n\n const unsubscribe = addEffect(reactor, () => this.#scheduleRender());\n\n this.#reactors.set(`painter_${id}`, {\n reactor,\n unsubscribe\n });\n\n return reactor;\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.#canvasPointer) {\n this.#canvasPointer.destroy();\n this.#canvasPointer = 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 #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 ...pointer.state,\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 ...pointer.state,\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 drag on active area\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerMove?.handler && pointer.isDragging) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerMove.handler({\n ...pointer.state,\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 ...pointer.state,\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 ...pointer.state,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'scroll':\n case 'zoom':\n // Emit custom events for scroll/zoom\n this.#emit(`pointer:${type}`, pointer.state);\n break;\n\n case 'dblclick':\n // Emit double-click event\n this.#emit('pointer:dblclick', pointer.state);\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}", "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-engine/core';\n\nexport class CanvasPointer extends ServiceProvider {\n #canvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n\n static manifest = {\n name: 'CanvasPointer',\n namespace: 'canvasPointer',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n getOffscreenCanvas: () => this.getOffscreenCanvas(),\n };\n }\n\n getOffscreenCanvas() {\n if (!this.#canvas) return null;\n return this.#canvas.transferControlToOffscreen();\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 #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(() => {\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n document.addEventListener('wheel', this.#handleScroll, { passive: false });\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerdown', this.#handleDown);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleUp);\n document.addEventListener('dblclick', this.#handleDblClick);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n document.removeEventListener('wheel', this.#handleScroll);\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerdown', this.#handleDown);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleUp);\n document.removeEventListener('dblclick', this.#handleDblClick);\n }\n\n #handleScroll = (event) => {\n if (event.target !== this.#canvas) {\n return;\n }\n\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 const normalized = this.#normalizeEvent(event, 'move');\n \n // Store latest move and throttle with RAF\n this.#pendingMove = normalized;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n this.#emit(this.#pendingMove);\n this.#pendingMove = null;\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n // Only capture if starting on canvas\n if (event.target === this.#canvas) {\n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n }\n\n #handleUp = (event) => {\n // Use the actual up event position, not pending move\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\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 #normalizeEvent(event, type) {\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 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 const normalized = {\n x,\n y,\n type,\n isOverCanvas,\n isWithinBounds,\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button ?? null,\n buttons: event.buttons ?? 0,\n timestamp: Date.now()\n };\n\n // Add wheel-specific data for scroll/zoom\n if (type === 'scroll' || type === 'zoom') {\n normalized.deltaX = event.deltaX;\n normalized.deltaY = event.deltaY;\n normalized.deltaZ = event.deltaZ;\n normalized.deltaMode = event.deltaMode;\n }\n\n // Add modifier keys\n normalized.shiftKey = event.shiftKey || false;\n normalized.ctrlKey = event.ctrlKey || false;\n normalized.altKey = event.altKey || false;\n normalized.metaKey = event.metaKey || false;\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.#cachedRect = null;\n this.#subscribers.clear();\n }\n}\n", "import { defineSurface } from '@jucie-state/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // ============= Core State =============\n \n // Position (canvas coordinates)\n const x = setup.value(0);\n const y = setup.value(0);\n const prevX = setup.value(0);\n const prevY = setup.value(0);\n \n // Client position (screen coordinates)\n const clientX = setup.value(0);\n const clientY = setup.value(0);\n \n // Canvas boundary state\n const isOverCanvas = setup.value(false);\n const isWithinBounds = setup.value(false);\n \n // Button state\n const isPressed = setup.value(false);\n const button = setup.value(null); // 0=left, 1=middle, 2=right\n const buttons = setup.value(0); // Bitmask of pressed buttons\n \n // Event type tracking\n const lastEventType = setup.value(null);\n \n // Timing\n const downTime = setup.value(null);\n const upTime = setup.value(null);\n const lastMoveTime = setup.value(null);\n const lastEventTime = setup.value(null);\n \n // Drag state\n const dragStartX = setup.value(null);\n const dragStartY = setup.value(null);\n const isDragging = setup.value(false);\n \n // Click detection\n const clickCount = setup.value(0);\n const lastClickTime = setup.value(0);\n \n // Velocity tracking\n const velocityX = setup.value(0);\n const velocityY = setup.value(0);\n \n // Scroll/Zoom state\n const lastScrollDeltaX = setup.value(0);\n const lastScrollDeltaY = setup.value(0);\n const lastZoomDelta = setup.value(0);\n \n // Hit areas (from HitRegistry)\n const hoveredArea = setup.value(null);\n const activeArea = setup.value(null);\n \n // ============= Configuration =============\n const config = setup.value({\n dragThreshold: 5,\n doubleClickThreshold: 300,\n holdThreshold: 500,\n velocitySmoothing: 0.3,\n maxVelocity: 10000 // Clamp unrealistic velocities\n });\n \n // ============= Computed Values =============\n \n const position = setup.computed(() => ({\n x: x.value,\n y: y.value\n }));\n \n const clientPosition = setup.computed(() => ({\n x: clientX.value,\n y: clientY.value\n }));\n \n const previousPosition = setup.computed(() => ({\n x: prevX.value,\n y: prevY.value\n }));\n \n const delta = setup.computed(() => {\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const prevXVal = typeof prevX.value === 'number' ? prevX.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const prevYVal = typeof prevY.value === 'number' ? prevY.value : 0;\n return {\n x: xVal - prevXVal,\n y: yVal - prevYVal\n };\n });\n \n const velocity = setup.computed(() => ({\n x: velocityX.value,\n y: velocityY.value\n }));\n \n const speed = setup.computed(() => {\n const vx = velocityX.value;\n const vy = velocityY.value;\n return Math.sqrt(vx * vx + vy * vy);\n });\n \n const dragDistance = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') return 0;\n \n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const dx = xVal - startX;\n const dy = yVal - startY;\n return Math.sqrt(dx * dx + dy * dy);\n });\n \n const dragDelta = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') {\n return { x: 0, y: 0 };\n }\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n return {\n x: xVal - startX,\n y: yVal - startY\n };\n });\n \n const holdDuration = setup.computed(() => {\n if (!isPressed.value || !downTime.value) return 0;\n return Date.now() - downTime.value;\n });\n \n const isHolding = setup.computed(() => {\n return holdDuration.value > config.value.holdThreshold && !isDragging.value;\n });\n \n const timeSinceLastEvent = setup.computed(() => {\n const lastTime = lastEventTime.value;\n return lastTime ? Date.now() - lastTime : 0;\n });\n \n // Full state snapshot\n const state = setup.computed(() => ({\n position: position.value,\n clientPosition: clientPosition.value,\n previousPosition: previousPosition.value,\n delta: delta.value,\n velocity: velocity.value,\n speed: speed.value,\n isPressed: isPressed.value,\n button: button.value,\n buttons: buttons.value,\n isDragging: isDragging.value,\n dragDistance: dragDistance.value,\n dragDelta: dragDelta.value,\n isHolding: isHolding.value,\n holdDuration: holdDuration.value,\n isOverCanvas: isOverCanvas.value,\n isWithinBounds: isWithinBounds.value,\n hoveredArea: hoveredArea.value,\n activeArea: activeArea.value,\n clickCount: clickCount.value,\n lastEventType: lastEventType.value\n }));\n \n // ============= Actions =============\n \n const updatePosition = setup.action((ctx, newX, newY, newClientX, newClientY) => {\n prevX.value = x.value;\n prevY.value = y.value;\n x.value = newX;\n y.value = newY;\n clientX.value = newClientX;\n clientY.value = newClientY;\n lastMoveTime.value = Date.now();\n });\n \n const updateVelocity = setup.action(() => {\n const now = Date.now();\n const lastMove = lastMoveTime.value;\n \n if (lastMove) {\n const dt = (now - lastMove) / 1000;\n if (dt > 0 && dt < 0.1) {\n const newVx = (x.value - prevX.value) / dt;\n const newVy = (y.value - prevY.value) / dt;\n \n // Clamp unrealistic velocities\n const maxVel = config.value.maxVelocity;\n const clampedVx = Math.max(-maxVel, Math.min(maxVel, newVx));\n const clampedVy = Math.max(-maxVel, Math.min(maxVel, newVy));\n \n // Apply smoothing\n const smoothing = config.value.velocitySmoothing;\n velocityX.value = velocityX.value * (1 - smoothing) + clampedVx * smoothing;\n velocityY.value = velocityY.value * (1 - smoothing) + clampedVy * smoothing;\n }\n }\n });\n \n // Main event handler - consumes normalized events from CanvasPointer\n const handleEvent = setup.action((ctx, normalizedEvent) => {\n const { x: newX, y: newY, type, clientX: newClientX, clientY: newClientY, button: eventButton, buttons: eventButtons, isOverCanvas: eventIsOverCanvas, isWithinBounds: eventIsWithinBounds } = normalizedEvent;\n const now = Date.now();\n \n lastEventTime.value = now;\n lastEventType.value = type;\n isOverCanvas.value = eventIsOverCanvas;\n isWithinBounds.value = eventIsWithinBounds;\n \n switch (type) {\n case 'down':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = true;\n downTime.value = now;\n button.value = eventButton;\n buttons.value = eventButtons;\n dragStartX.value = newX;\n dragStartY.value = newY;\n isDragging.value = false;\n \n // Double-click detection\n const timeSinceLastClick = now - lastClickTime.value;\n if (timeSinceLastClick < config.value.doubleClickThreshold) {\n clickCount.value = clickCount.value + 1;\n } else {\n clickCount.value = 1;\n }\n break;\n \n case 'up':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = false;\n upTime.value = now;\n lastClickTime.value = now;\n isDragging.value = false;\n velocityX.value = 0;\n velocityY.value = 0;\n buttons.value = eventButtons;\n break;\n \n case 'move':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n updateVelocity();\n buttons.value = eventButtons;\n \n // Check for drag start\n if (isPressed.value && !isDragging.value) {\n const distance = dragDistance.value;\n if (distance > config.value.dragThreshold) {\n isDragging.value = true;\n }\n }\n break;\n \n case 'dblclick':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n clickCount.value = 2;\n break;\n \n case 'scroll':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n // Extract wheel delta from event if available\n if (normalizedEvent.deltaX !== undefined) {\n lastScrollDeltaX.value = normalizedEvent.deltaX;\n }\n if (normalizedEvent.deltaY !== undefined) {\n lastScrollDeltaY.value = normalizedEvent.deltaY;\n }\n break;\n \n case 'zoom':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n if (normalizedEvent.deltaY !== undefined) {\n lastZoomDelta.value = normalizedEvent.deltaY;\n }\n break;\n }\n });\n \n const setHoveredArea = setup.action((ctx, area) => {\n hoveredArea.value = area;\n });\n \n const setActiveArea = setup.action((ctx, area) => {\n activeArea.value = area;\n });\n \n const reset = setup.action(() => {\n isPressed.value = false;\n isDragging.value = false;\n activeArea.value = null;\n hoveredArea.value = null;\n velocityX.value = 0;\n velocityY.value = 0;\n clickCount.value = 0;\n lastScrollDeltaX.value = 0;\n lastScrollDeltaY.value = 0;\n lastZoomDelta.value = 0;\n });\n \n const updateConfig = setup.action((ctx, updates) => {\n config.value = { ...config.value, ...updates };\n });\n \n // ============= Return Public API =============\n return {\n // State (read-only through computed)\n state,\n position,\n clientPosition,\n previousPosition,\n delta,\n velocity,\n speed,\n isPressed,\n button,\n buttons,\n isDragging,\n dragDistance,\n dragDelta,\n isHolding,\n holdDuration,\n isOverCanvas,\n isWithinBounds,\n hoveredArea,\n activeArea,\n clickCount,\n lastEventType,\n timeSinceLastEvent,\n \n // Actions\n handleEvent, // Main entry point for normalized events\n setHoveredArea,\n setActiveArea,\n reset,\n updateConfig\n };\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["ServiceProvider", "ContextTypes", "createReactor", "addEffect", "createDefinition", "definitionType", "HitRegistry", "#areas", "id", "area", "ServiceProvider", "
|
|
3
|
+
"sources": ["../src/Painter.js", "../src/ContextTypes.js", "../src/HitRegistry.js", "../src/CanvasEvents.js", "../src/usePointerSurface.js"],
|
|
4
|
+
"sourcesContent": ["import { ServiceProvider } from '@jucie-engine/core';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createReactor, addEffect } from '@jucie-state/reactive';\nimport { createDefinition, definitionType } from '@jucie-engine/core';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nexport const defineBrush = createDefinition('BRUSH', [Object]);\nexport const defineLayer = createDefinition('LAYER', [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #reactors = 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 #subscribers = new Map(); // Map<event, Set<callback>>\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.state,\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 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 // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\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(canvas);\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 // Set up layer reactor if it has data paths\n if (config.data) {\n const dataReactor = this.#createDataReactor(`layer_${name}`, config.data);\n if (dataReactor) {\n this.#reactors.set(`layer_${name}`, dataReactor);\n }\n }\n\n // Set up brush reactors and structure\n const brushes = config.children.map(child => {\n if (definitionType(child) === 'BRUSH') {\n const name = child._name;\n const brushConfig = child(this.useContext, this.#hitRegistry);\n \n // Only create data reactor if data exists\n const dataReactor = brushConfig.data \n ? this.#createDataReactor(`brush_${name}`, brushConfig.data)\n : () => undefined;\n \n const whenReactor = brushConfig.when \n ? createReactor(brushConfig.when, {\n immediate: true,\n context: this.useContext('state')\n })\n : null;\n\n const brush = {\n name,\n ...brushConfig,\n dataReactor,\n whenReactor\n };\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || config.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n return brush;\n }\n // Handle nested layers recursively\n return this.addLayer(child);\n });\n\n const layer = {\n ...config,\n name,\n brushes,\n context: this.#contexts.get(config.context)\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 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 // Call brush unmount hooks and clean up reactors\n layer.brushes.forEach(brush => {\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 reactor and subscription\n const reactorData = this.#reactors.get(`painter_brush_${brush.name}`);\n if (reactorData) {\n reactorData.unsubscribe();\n reactorData.reactor.destroy();\n this.#reactors.delete(`painter_brush_${brush.name}`);\n }\n });\n\n // Clean up layer reactor and subscription\n const layerReactorData = this.#reactors.get(`painter_layer_${name}`);\n if (layerReactorData) {\n layerReactorData.unsubscribe();\n layerReactorData.reactor.destroy();\n this.#reactors.delete(`painter_layer_${name}`);\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) {\n const layerReactor = this.#reactors.get(`painter_layer_${layer.name}`)?.reactor;\n if (!layer.when(layerReactor())) continue;\n }\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 // Render brushes\n for (const brush of layer.brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor()) 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(), 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 #createDataReactor(id, data) {\n const state = this.useContext('state');\n\n const reactor = createReactor(data, {\n immediate: true,\n context: state\n });\n\n const unsubscribe = addEffect(reactor, () => this.#scheduleRender());\n\n this.#reactors.set(`painter_${id}`, {\n reactor,\n unsubscribe\n });\n\n return reactor;\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.#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\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 ...pointer.state,\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 ...pointer.state,\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 drag on active area\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerMove?.handler && pointer.isDragging) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerMove.handler({\n ...pointer.state,\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 ...pointer.state,\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 ...pointer.state,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'scroll':\n case 'zoom':\n // Emit custom events for scroll/zoom\n this.#emit(`pointer:${type}`, pointer.state);\n break;\n\n case 'dblclick':\n // Emit double-click event\n this.#emit('pointer:dblclick', pointer.state);\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}", "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-engine/core';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #pendingMove = null;\n #rafId = null;\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 };\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 #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(() => {\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n document.addEventListener('wheel', this.#handleScroll, { passive: false });\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerdown', this.#handleDown);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleUp);\n document.addEventListener('dblclick', this.#handleDblClick);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n document.removeEventListener('wheel', this.#handleScroll);\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerdown', this.#handleDown);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleUp);\n document.removeEventListener('dblclick', this.#handleDblClick);\n }\n\n #handleScroll = (event) => {\n if (event.target !== this.#canvas) {\n return;\n }\n\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 const normalized = this.#normalizeEvent(event, 'move');\n \n // Store latest move and throttle with RAF\n this.#pendingMove = normalized;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n this.#emit(this.#pendingMove);\n this.#pendingMove = null;\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n // Only capture if starting on canvas\n if (event.target === this.#canvas) {\n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n }\n\n #handleUp = (event) => {\n // Use the actual up event position, not pending move\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\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 #normalizeEvent(event, type) {\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 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 const normalized = {\n x,\n y,\n type,\n isOverCanvas,\n isWithinBounds,\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button ?? null,\n buttons: event.buttons ?? 0,\n timestamp: Date.now()\n };\n\n // Add wheel-specific data for scroll/zoom\n if (type === 'scroll' || type === 'zoom') {\n normalized.deltaX = event.deltaX;\n normalized.deltaY = event.deltaY;\n normalized.deltaZ = event.deltaZ;\n normalized.deltaMode = event.deltaMode;\n }\n\n // Add modifier keys\n normalized.shiftKey = event.shiftKey || false;\n normalized.ctrlKey = event.ctrlKey || false;\n normalized.altKey = event.altKey || false;\n normalized.metaKey = event.metaKey || false;\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.#cachedRect = null;\n this.#subscribers.clear();\n }\n}\n", "import { defineSurface } from '@jucie-state/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // ============= Core State =============\n \n // Position (canvas coordinates)\n const x = setup.value(0);\n const y = setup.value(0);\n const prevX = setup.value(0);\n const prevY = setup.value(0);\n \n // Client position (screen coordinates)\n const clientX = setup.value(0);\n const clientY = setup.value(0);\n \n // Canvas boundary state\n const isOverCanvas = setup.value(false);\n const isWithinBounds = setup.value(false);\n \n // Button state\n const isPressed = setup.value(false);\n const button = setup.value(null); // 0=left, 1=middle, 2=right\n const buttons = setup.value(0); // Bitmask of pressed buttons\n \n // Event type tracking\n const lastEventType = setup.value(null);\n \n // Timing\n const downTime = setup.value(null);\n const upTime = setup.value(null);\n const lastMoveTime = setup.value(null);\n const lastEventTime = setup.value(null);\n \n // Drag state\n const dragStartX = setup.value(null);\n const dragStartY = setup.value(null);\n const isDragging = setup.value(false);\n \n // Click detection\n const clickCount = setup.value(0);\n const lastClickTime = setup.value(0);\n \n // Velocity tracking\n const velocityX = setup.value(0);\n const velocityY = setup.value(0);\n \n // Scroll/Zoom state\n const lastScrollDeltaX = setup.value(0);\n const lastScrollDeltaY = setup.value(0);\n const lastZoomDelta = setup.value(0);\n \n // Hit areas (from HitRegistry)\n const hoveredArea = setup.value(null);\n const activeArea = setup.value(null);\n \n // ============= Configuration =============\n const config = setup.value({\n dragThreshold: 5,\n doubleClickThreshold: 300,\n holdThreshold: 500,\n velocitySmoothing: 0.3,\n maxVelocity: 10000 // Clamp unrealistic velocities\n });\n \n // ============= Computed Values =============\n \n const position = setup.computed(() => ({\n x: x.value,\n y: y.value\n }));\n \n const clientPosition = setup.computed(() => ({\n x: clientX.value,\n y: clientY.value\n }));\n \n const previousPosition = setup.computed(() => ({\n x: prevX.value,\n y: prevY.value\n }));\n \n const delta = setup.computed(() => {\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const prevXVal = typeof prevX.value === 'number' ? prevX.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const prevYVal = typeof prevY.value === 'number' ? prevY.value : 0;\n return {\n x: xVal - prevXVal,\n y: yVal - prevYVal\n };\n });\n \n const velocity = setup.computed(() => ({\n x: velocityX.value,\n y: velocityY.value\n }));\n \n const speed = setup.computed(() => {\n const vx = velocityX.value;\n const vy = velocityY.value;\n return Math.sqrt(vx * vx + vy * vy);\n });\n \n const dragDistance = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') return 0;\n \n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n const dx = xVal - startX;\n const dy = yVal - startY;\n return Math.sqrt(dx * dx + dy * dy);\n });\n \n const dragDelta = setup.computed(() => {\n const startX = dragStartX.value;\n const startY = dragStartY.value;\n if (startX === null || startY === null || typeof startX !== 'number' || typeof startY !== 'number') {\n return { x: 0, y: 0 };\n }\n const xVal = typeof x.value === 'number' ? x.value : 0;\n const yVal = typeof y.value === 'number' ? y.value : 0;\n return {\n x: xVal - startX,\n y: yVal - startY\n };\n });\n \n const holdDuration = setup.computed(() => {\n if (!isPressed.value || !downTime.value) return 0;\n return Date.now() - downTime.value;\n });\n \n const isHolding = setup.computed(() => {\n return holdDuration.value > config.value.holdThreshold && !isDragging.value;\n });\n \n const timeSinceLastEvent = setup.computed(() => {\n const lastTime = lastEventTime.value;\n return lastTime ? Date.now() - lastTime : 0;\n });\n \n // Full state snapshot\n const state = setup.computed(() => ({\n position: position.value,\n clientPosition: clientPosition.value,\n previousPosition: previousPosition.value,\n delta: delta.value,\n velocity: velocity.value,\n speed: speed.value,\n isPressed: isPressed.value,\n button: button.value,\n buttons: buttons.value,\n isDragging: isDragging.value,\n dragDistance: dragDistance.value,\n dragDelta: dragDelta.value,\n isHolding: isHolding.value,\n holdDuration: holdDuration.value,\n isOverCanvas: isOverCanvas.value,\n isWithinBounds: isWithinBounds.value,\n hoveredArea: hoveredArea.value,\n activeArea: activeArea.value,\n clickCount: clickCount.value,\n lastEventType: lastEventType.value\n }));\n \n // ============= Actions =============\n \n const updatePosition = setup.action((ctx, newX, newY, newClientX, newClientY) => {\n prevX.value = x.value;\n prevY.value = y.value;\n x.value = newX;\n y.value = newY;\n clientX.value = newClientX;\n clientY.value = newClientY;\n lastMoveTime.value = Date.now();\n });\n \n const updateVelocity = setup.action(() => {\n const now = Date.now();\n const lastMove = lastMoveTime.value;\n \n if (lastMove) {\n const dt = (now - lastMove) / 1000;\n if (dt > 0 && dt < 0.1) {\n const newVx = (x.value - prevX.value) / dt;\n const newVy = (y.value - prevY.value) / dt;\n \n // Clamp unrealistic velocities\n const maxVel = config.value.maxVelocity;\n const clampedVx = Math.max(-maxVel, Math.min(maxVel, newVx));\n const clampedVy = Math.max(-maxVel, Math.min(maxVel, newVy));\n \n // Apply smoothing\n const smoothing = config.value.velocitySmoothing;\n velocityX.value = velocityX.value * (1 - smoothing) + clampedVx * smoothing;\n velocityY.value = velocityY.value * (1 - smoothing) + clampedVy * smoothing;\n }\n }\n });\n \n // Main event handler - consumes normalized events from CanvasEvents\n const handleEvent = setup.action((ctx, normalizedEvent) => {\n const { x: newX, y: newY, type, clientX: newClientX, clientY: newClientY, button: eventButton, buttons: eventButtons, isOverCanvas: eventIsOverCanvas, isWithinBounds: eventIsWithinBounds } = normalizedEvent;\n const now = Date.now();\n \n lastEventTime.value = now;\n lastEventType.value = type;\n isOverCanvas.value = eventIsOverCanvas;\n isWithinBounds.value = eventIsWithinBounds;\n \n switch (type) {\n case 'down':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = true;\n downTime.value = now;\n button.value = eventButton;\n buttons.value = eventButtons;\n dragStartX.value = newX;\n dragStartY.value = newY;\n isDragging.value = false;\n \n // Double-click detection\n const timeSinceLastClick = now - lastClickTime.value;\n if (timeSinceLastClick < config.value.doubleClickThreshold) {\n clickCount.value = clickCount.value + 1;\n } else {\n clickCount.value = 1;\n }\n break;\n \n case 'up':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n isPressed.value = false;\n upTime.value = now;\n lastClickTime.value = now;\n isDragging.value = false;\n velocityX.value = 0;\n velocityY.value = 0;\n buttons.value = eventButtons;\n break;\n \n case 'move':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n updateVelocity();\n buttons.value = eventButtons;\n \n // Check for drag start\n if (isPressed.value && !isDragging.value) {\n const distance = dragDistance.value;\n if (distance > config.value.dragThreshold) {\n isDragging.value = true;\n }\n }\n break;\n \n case 'dblclick':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n clickCount.value = 2;\n break;\n \n case 'scroll':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n // Extract wheel delta from event if available\n if (normalizedEvent.deltaX !== undefined) {\n lastScrollDeltaX.value = normalizedEvent.deltaX;\n }\n if (normalizedEvent.deltaY !== undefined) {\n lastScrollDeltaY.value = normalizedEvent.deltaY;\n }\n break;\n \n case 'zoom':\n updatePosition(ctx, newX, newY, newClientX, newClientY);\n if (normalizedEvent.deltaY !== undefined) {\n lastZoomDelta.value = normalizedEvent.deltaY;\n }\n break;\n }\n });\n \n const setHoveredArea = setup.action((ctx, area) => {\n hoveredArea.value = area;\n });\n \n const setActiveArea = setup.action((ctx, area) => {\n activeArea.value = area;\n });\n \n const reset = setup.action(() => {\n isPressed.value = false;\n isDragging.value = false;\n activeArea.value = null;\n hoveredArea.value = null;\n velocityX.value = 0;\n velocityY.value = 0;\n clickCount.value = 0;\n lastScrollDeltaX.value = 0;\n lastScrollDeltaY.value = 0;\n lastZoomDelta.value = 0;\n });\n \n const updateConfig = setup.action((ctx, updates) => {\n config.value = { ...config.value, ...updates };\n });\n \n // ============= Return Public API =============\n return {\n // State (read-only through computed)\n state,\n position,\n clientPosition,\n previousPosition,\n delta,\n velocity,\n speed,\n isPressed,\n button,\n buttons,\n isDragging,\n dragDistance,\n dragDelta,\n isHolding,\n holdDuration,\n isOverCanvas,\n isWithinBounds,\n hoveredArea,\n activeArea,\n clickCount,\n lastEventType,\n timeSinceLastEvent,\n \n // Actions\n handleEvent, // Main entry point for normalized events\n setHoveredArea,\n setActiveArea,\n reset,\n updateConfig\n };\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["ServiceProvider", "ContextTypes", "createReactor", "addEffect", "createDefinition", "definitionType", "HitRegistry", "#areas", "id", "area", "ServiceProvider", "CanvasEvents", "#canvas", "#cachedRect", "#resizeObserver", "#subscribers", "#pendingMove", "#rafId", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#handleScroll", "#handleMove", "#handleDown", "#handleUp", "#handleDblClick", "event", "normalized", "#normalizeEvent", "#emit", "type", "isOverCanvas", "x", "y", "isWithinBounds", "defineSurface", "usePointerSurface", "setup", "x", "y", "prevX", "prevY", "clientX", "clientY", "isOverCanvas", "isWithinBounds", "isPressed", "button", "buttons", "lastEventType", "downTime", "upTime", "lastMoveTime", "lastEventTime", "dragStartX", "dragStartY", "isDragging", "clickCount", "lastClickTime", "velocityX", "velocityY", "lastScrollDeltaX", "lastScrollDeltaY", "lastZoomDelta", "hoveredArea", "activeArea", "config", "position", "clientPosition", "previousPosition", "delta", "xVal", "prevXVal", "yVal", "prevYVal", "velocity", "speed", "vx", "vy", "dragDistance", "startX", "startY", "dx", "dy", "dragDelta", "holdDuration", "isHolding", "timeSinceLastEvent", "lastTime", "state", "updatePosition", "ctx", "newX", "newY", "newClientX", "newClientY", "updateVelocity", "now", "lastMove", "dt", "newVx", "newVy", "maxVel", "clampedVx", "clampedVy", "smoothing", "handleEvent", "normalizedEvent", "type", "eventButton", "eventButtons", "eventIsOverCanvas", "eventIsWithinBounds", "setHoveredArea", "area", "setActiveArea", "reset", "updateConfig", "updates", "defineBrush", "createDefinition", "defineLayer", "Painter", "ServiceProvider", "#layers", "#canvas", "#contexts", "#reactors", "#assets", "#isRunning", "#frameId", "#isRendering", "#renderScheduled", "#runtimeConfig", "#timing", "#metrics", "#hitRegistry", "HitRegistry", "#pointerSurface", "usePointerSurface", "#canvasEvents", "#pointerUnsubscribe", "#subscribers", "layerDef", "layers", "layer", "fn", "canvas", "offscreenCanvas", "assets", "name", "fps", "scale", "step", "options", "width", "height", "event", "callback", "normalizedEvent", "path", "ContextTypes", "type", "ctx", "CanvasEvents", "result", "#scheduleRender", "_a", "definitionType", "config", "dataReactor", "#createDataReactor", "brushes", "child", "brushConfig", "whenReactor", "createReactor", "brush", "error", "reactorData", "layerReactorData", "#render", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "_k", "_l", "_m", "_n", "_o", "_p", "_q", "renderStart", "layerStart", "layerReactor", "key", "value", "brushStart", "brushCtx", "requiredAssets", "brushTime", "#renderBrushBounds", "layerTime", "#renderLayerBounds", "#renderDebugOverlay", "y", "lineHeight", "text", "time", "id", "data", "state", "reactor", "unsubscribe", "addEffect", "#handlePointerInteraction", "x", "pointer", "hitArea", "#hitTest", "#getContextForArea", "#emit", "activeArea", "prevHovered", "area", "callbacks", "sorted", "a", "b", "#isPointInBounds", "bounds"]
|
|
7
7
|
}
|