@jucie.io/engine-painter 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1,2 +1,2 @@
1
- var ft=Object.freeze(Object.create(null));function Ie(s,e,t="value"){if(Array.isArray(e)){for(let n of e)if(ke(s,n))return!0;let i=e.map(B).join(" | ");throw new TypeError(`${t} must be one of: ${i}. Got ${B(s)}`)}if(!ke(s,e))throw new TypeError(`${t} must be ${B(e)}. Got ${B(s)}`);return!0}function ke(s,e){return e===String?typeof s=="string":e===Number?typeof s=="number"&&!isNaN(s):e===Boolean?typeof s=="boolean":e===Symbol?typeof s=="symbol":e===BigInt?typeof s=="bigint":e===Function?typeof s=="function":e===Array?Array.isArray(s):e===Object?s!==null&&typeof s=="object"&&!Array.isArray(s):s instanceof e}function B(s){return s===String?"String":s===Number?"Number":s===Boolean?"Boolean":s===Array?"Array":s===Object?"Object":s===Function?"Function":s===Date?"Date":s===RegExp?"RegExp":s===Promise?"Promise":s===Map?"Map":s===Set?"Set":s===WeakMap?"WeakMap":s===WeakSet?"WeakSet":s===Symbol?"Symbol":s===BigInt?"BigInt":s===Error?"Error":typeof s=="string"?"string":typeof s=="number"?"number":typeof s=="boolean"?"boolean":typeof s=="symbol"?"symbol":typeof s=="bigint"?"bigint":typeof s=="function"?"function":Array.isArray(s)?"Array":s===null?"null":s===void 0?"undefined":typeof s=="object"?s.constructor?.name||"Object":"unknown"}function $(s,e="value"){return t=>Ie(t,s,e)}var ee=new Map,te=new WeakMap,I=s=>{if(te.has(s))return te.get(s)},b=(s,e=[])=>{let t=e.length>0?$(e,"return value"):null;if(ee.has(s))return console.warn(`Definition type "${s}" already exists`),ee.get(s);let i=(n,r,...o)=>{$(String,"name")(n),$(Function,"factory")(r);let a=(...c)=>{try{let h=[...c,...o],g=r(...h);if(t&&g===void 0)throw new Error(`Factory ${s} must return a value for ${n}`);return t&&t(g),g}catch(h){throw console.error(`Error creating definition "${n}"`,h),h}};return Object.defineProperty(a,"_name",{value:n,enumerable:!1,configurable:!1}),te.set(a,s),a};return ee.set(s,i),i};var et=new Set(["__proto__","prototype","constructor"]),tt=new Set(["use","install","uninstall","relay","state","debug"]),De=64,st=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/;function it(s,e="key"){if(et.has(s))throw new Error(`Illegal key "${s}" in ${e}`)}function se(s){if(it(s,"namespace"),typeof s!="string")throw new Error(`Namespace must be a string, got ${typeof s}`);if(!st.test(s))throw new Error(`Invalid namespace "${s}". Must be a valid JS identifier`);if(s.length>De)throw new Error(`Namespace "${s}" too long (max ${De} chars)`);if(tt.has(s))throw new Error(`Namespace "${s}" is reserved`);return s}var ie=b("MIDDLEWARE",[Function,Array]),ne=b("ACTIONS",[Object]),re=b("UNINSTALL"),oe=b("INITIALIZE"),ae=b("GETTERS",[Object]);var U=class s{static create(e){return new s(e)}#e;#r;#t={MIDDLEWARE:null,GETTERS:null,ACTIONS:null,INITIALIZE:null,UNINSTALL:null};constructor(e){this.#e=e}#i(e,t,i){if(this.#t[e])throw new Error(`${e} already defined for ${this.#e}`);this.#t[e]=i(this.#e,t)}defineMiddleware=e=>this.#i("MIDDLEWARE",e,ie);defineGetters=e=>this.#i("GETTERS",e,ae);defineActions=e=>this.#i("ACTIONS",e,ne);defineInitialize=e=>this.#i("INITIALIZE",e,oe);defineUninstall=e=>this.#i("UNINSTALL",e,re);_toArray(){return[this.#t.MIDDLEWARE,this.#t.GETTERS,this.#t.ACTIONS,this.#t.INITIALIZE,this.#t.UNINSTALL].filter(Boolean)}};var S=class s{static#e=new Set;static manifest={name:"base",dependencies:[],version:"1.0.0",description:"Base extension template"};static config=null;static unique=!1;static configure(e={}){return{install:(t,i)=>this.install(t,i),manifest:this.manifest,config:{...this.config||this.manifest.defaults||{},...e},unique:!0,configured:!0}}static install(e,t){try{let{namespace:i}=this.manifest;se(i);let n=new this;s.#e.add(n),Object.defineProperty(n,"config",{value:Object.freeze({...t}),writable:!1,configurable:!1,enumerable:!1}),Object.defineProperty(n,"context",{get:()=>e(),configurable:!1,enumerable:!1}),Object.defineProperty(n,"useContext",{value:(...o)=>e(...o),writable:!1,configurable:!1,enumerable:!1});let r=U.create(i);if(n.setup){let o={defineActions:c=>r.defineActions(()=>c(e,t)),defineMiddleware:c=>r.defineMiddleware(()=>c(e,t)),defineGetters:c=>r.defineGetters(()=>c(e,t)),defineInitialize:c=>r.defineInitialize(()=>c(e,t)),defineUninstall:c=>r.defineUninstall(()=>c(e,t))},a=n.setup(o);return a?.then?a.then(()=>r._toArray()):r._toArray()}return n.middleware&&r.defineMiddleware(()=>n.middleware(e,t)),n.getters&&r.defineGetters(()=>n.getters(e,t)),n.actions&&r.defineActions(()=>n.actions(e,t)),n.initialize&&r.defineInitialize(()=>n.initialize(e,t)),n.uninstall&&r.defineUninstall(()=>n.uninstall(e,t)),r._toArray()}catch(i){throw i}}};var cs=Symbol("jucie.engine");var L={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};function Pe(s){return typeof window<"u"&&window.requestIdleCallback?window.requestIdleCallback(s,{timeout:100}):typeof window<"u"?window.requestAnimationFrame?window.requestAnimationFrame(()=>{setTimeout(s,0)}):setTimeout(s,0):(typeof s=="function"&&s(),null)}var W=class{constructor(){this.roots=new Map,this.pending=new Set,this.onCompleteCallbacks=new Set,this.onNextIdle=new Set,this.idleScheduled=!1}markAsDirty(e){if(!e.isDirty&&(e.isDirty=!0,e.isAsync||e.immediate||e.effects&&e.effects.size>0?this.scheduleRecomputation(e):(this.onNextIdle.add(e),this.idleScheduled||(this.idleScheduled=!0,Pe(()=>{for(let t of this.onNextIdle)this.pending.add(t);this.flush(null),this.onNextIdle.clear(),this.idleScheduled=!1}))),e.dependants&&e.dependants.size>0)){let t=[],i=new Set;e.dependants.forEach(n=>{let r=n.deref();r?(this.markAsDirty(r),i.add(r._id)):t.push(n)}),t.forEach(n=>e.dependants.delete(n)),e.dependantIds=i}}scheduleRecomputation(e){if(!e.debounce)return this.recompute(e);let t=Date.now(),i=e._lastComputeTime?t-e._lastComputeTime:1/0;return!e._hasPendingDebounce||i>=e.debounce?(clearTimeout(e._debounceTimer),e._hasPendingDebounce=!0,e._lastComputeTime=t,e._debounceTimer=setTimeout(()=>{e._hasPendingDebounce=!1,e._debounceTimer=null},e.debounce),this.recompute(e)):e.cachedValue}removeReactive(e){this.pending.delete(e),this.onNextIdle.delete(e)}recompute(e){return this.pending.add(e),this.flush(e)}flush(e){let t=Array.from(this.pending);this.pending.clear();let i=this.sortByDependencies(t);for(let n of i)this.onNextIdle.delete(n),n.compute();for(let n of this.onCompleteCallbacks)try{n()}catch(r){console.error("Error in batch completion callback:",r)}if(e)return i.includes(e)||e.compute(),e.cachedValue}sortByDependencies(e){let t=[],i=new Set,n=new Set,r=o=>{if(n.has(o)||i.has(o))return;n.add(o);let a=o.dependants;a&&a.size>0&&a.forEach(c=>{let h=c.deref();h&&e.includes(h)&&r(h)}),n.delete(o),i.add(o),t.unshift(o)};for(let o of e)i.has(o)||r(o);return t}};var l=class s{static computationManager=new W;static awaitingRecomputation=new Set;static reactives=new WeakMap;static currentlyComputing=null;static computationStack=[];static currentDepth=0;static effectsCache=new Set;static processingEffects=!1;static _nextId=1;static config={maxDepth:2e3};static ctx={};static nextId(){return s._nextId++}static addContext(e,t){if(!e||typeof e!="string")throw new Error("Invalid context key");if(typeof t>"u")throw new Error("Invalid context value");if(e in s.ctx)throw new Error("Context key already exists");s.ctx[e]=t}static useContext(e){if(!e||e.length===0)return s.ctx;if(e.length===1)return s.ctx[e[0]];let t=new Array(e.length);for(let i=0;i<e.length;i++)t[i]=s.ctx[e[i]];return t}static hasContext(e){if(!e||e.length===0)return Object.keys(s.ctx).length>0;if(e.length===1)return e[0]in s.ctx;for(let t of e)if(!(t in s.ctx))return!1;return!0}static clearContext(){s.ctx={}}static begin(e){s.awaitingRecomputation.has(e)&&s.awaitingRecomputation.delete(e);let t=s.computationStack.indexOf(e);if(t!==-1){if(e.isAsync){s.computationStack.splice(t,1),s.computationStack.push(e),s.currentlyComputing=e;return}let i=s.computationStack.slice(t).concat(e),n=new Error(`Circular dependency detected: ${i.map(r=>r).join(" -> ")}`);throw n.name="CircularDependencyError",n.displayed=!1,n}if(s.currentDepth>=s.config.maxDepth)throw new Error(`Maximum reactive depth of ${s.config.maxDepth} exceeded`);s.computationStack.push(e),s.currentlyComputing=e,s.currentDepth++}static end(e){if(e.isAsync){s.computationStack.splice(s.computationStack.indexOf(e),1),s.currentlyComputing=s.computationStack[s.computationStack.length-1]||null,s.currentDepth--;return}s.computationStack.pop(),s.currentlyComputing=s.computationStack[s.computationStack.length-1]||null,s.currentDepth--}static addEffect(e,t){let i=s.reactives.get(e);return i.isDirty&&s.computationManager.scheduleRecomputation(i),i.effects||(i.effects=new Set),i.effects.add(t),()=>s.removeEffect(e,t)}static removeEffect(e,t){let i=s.reactives.get(e);i.effects&&i.effects.delete(t)}static recompute(e){return s.awaitingRecomputation.has(e)||s.awaitingRecomputation.add(e),s.computationManager.scheduleRecomputation(e)}static callEffects(e){s.effectsCache.add(e),s.processingEffects||(s.processingEffects=!0,setTimeout(()=>{s.processEffectsCache(),s.processingEffects=!1},0))}static processEffectsCache(){let e=new Set(s.effectsCache);s.effectsCache.clear();for(let t of e)try{(t.effects||new Set).forEach(n=>{n&&n(t.cachedValue)})}catch(i){console.error(`Error in reactive ${t._id} effect:`,i)}s.effectsCache.size>0&&setTimeout(()=>{s.processEffectsCache()},0)}static markAsDirty(e){if(!e.isDirty){e.isDirty=!0,(e.immediate||e.effects&&e.effects.size>0)&&s.computationManager.scheduleRecomputation(e);let t=[],i=new Set;e.dependants.forEach(n=>{let r=n.deref();r?(s.markAsDirty(r),i.add(r._id)):t.push(n)}),t.forEach(n=>e.dependants.delete(n)),e.dependantIds=i}}static destroy(e){let t=s.reactives.get(e);s.computationManager.removeReactive(t),s.reactives.delete(e)}};var Me=s=>l.reactives.has(s),F=(s,e)=>{if(!Me(s))throw new Error("Invalid effect getter");if(!e||typeof e!="function")throw new Error("Invalid effect function");return l.addEffect(s,e)};var $e=s=>typeof s=="function"&&(s.constructor.name==="AsyncFunction"||s.constructor.name==="AsyncGeneratorFunction");var Y=class s{static create(e,t={}){let i=new s(e,t);return l.reactives.set(i.getter,i),i.getter}constructor(e,t={}){this.fn=e,this.isAsync=$e(e),this.pendingResolve=void 0,this.roots=new Set,this.dependants=new Set,this.dependantIds=new Set,this.effects=new Set(Array.isArray(t.effects)?t.effects:[]),this.cachedValue=t.initialValue||void 0,this.isDirty=!0,this.debounce=t.debounce||0,this.onAccess=t.onAccess||void 0,this.detatched=t.detatched||!1,this.immediate=t.immediate||!1,this.context=t.context||void 0,this.useContext=()=>this.context?this.context:l.hasContext()?l.useContext():void 0,this.resolvers=[],this.rejectors=[],this._id=l.nextId(),this._lastComputeTime=void 0,this._hasPendingDebounce=!1,this._debounceTimer=void 0,this._computationId=0,this.getter=this.#e.bind(this),this.immediate&&this.compute()}compute(){l.begin(this);try{if(!this.isAsync)return this.cachedValue=this.fn(this.useContext(),this.cachedValue),this.isDirty=!1,this.cachedValue;this._computationId=(this._computationId||0)+1;let e=this._computationId;return this.pendingResolve=this.fn(this.useContext(),this.cachedValue),this.pendingResolve.then(t=>(this._computationId===e&&(this.resolvers.forEach(i=>i(t)),this.resolvers=[],this.cachedValue=t,this.isDirty=!1),t)).catch(t=>{this._computationId===e&&(this.rejectors.forEach(i=>i(t)),this.rejectors=[])}).finally(()=>{this.pendingResolve=null,this._computationId===e&&(l.end(this),l.callEffects(this))}),this.cachedValue=new Promise((t,i)=>{this.resolvers.push(t),this.rejectors.push(i)}),this.cachedValue}finally{this.isAsync||(l.end(this),l.callEffects(this))}}#e(){try{return!this.detatched&&l.currentlyComputing&&l.currentlyComputing!==this&&!this.dependantIds.has(l.currentlyComputing._id)&&(this.dependantIds.add(l.currentlyComputing._id),this.dependants.add(new WeakRef(l.currentlyComputing))),this.isDirty?l.recompute(this):this.isAsync?Promise.resolve(this.cachedValue):this.cachedValue}catch(e){throw e}finally{this.onAccess&&this.onAccess(this.cachedValue)}}},D=(s,e={})=>Y.create(s,e),R=s=>{Le(s)&&l.destroy(s)},Le=s=>{let e=l.reactives.get(s);return e?e instanceof Y:!1};var ce=class s{static create(e,t={}){let i=new s(e,t);return l.reactives.set(i.getter,i),i.getter}constructor(e,t={}){this._id=l.nextId(),this.isAsync=!1,this.cachedValue=void 0,this.dependants=new Set,this.dependantIds=new Set,this.roots=new Set,this.effects=new Set(Array.isArray(t.effects)?t.effects:[]),this.isDirty=!0,this.debounce=t.debounce||0,this.onAccess=t.onAccess||null,this.detatched=t.detatched||!1,this.immediate=t.immediate||!1,this._pendingChange=e,this._lastComputeTime=null,this._hasPendingDebounce=!1,this._debounceTimer=null,this.getter=(...i)=>this.#e(...i)}compute(){l.begin(this);try{return this.cachedValue=this._pendingChange,this._pendingChange=void 0,this.isDirty=!1,this.cachedValue}finally{l.end(this),l.callEffects(this)}}#e(...e){try{if(!this.detatched&&l.currentlyComputing&&l.currentlyComputing!==this&&!this.dependantIds.has(l.currentlyComputing._id)&&(this.dependantIds.add(l.currentlyComputing._id),this.dependants.add(new WeakRef(l.currentlyComputing))),e.length>0){let t=e[0];this._pendingChange=typeof t=="function"?t(this.cachedValue):t,l.markAsDirty(this);return}return this.isDirty?l.recompute(this):this.cachedValue}catch(t){throw t}finally{this.onAccess&&this.onAccess(this.cachedValue)}}},le=(s,e={})=>ce.create(s,e);var j=[null,null,(s,e)=>s?.[e[0]]?.[e[1]],(s,e)=>s?.[e[0]]?.[e[1]]?.[e[2]],(s,e)=>s?.[e[0]]?.[e[1]]?.[e[2]]?.[e[3]],(s,e)=>s?.[e[0]]?.[e[1]]?.[e[2]]?.[e[3]]?.[e[4]],(s,e)=>s?.[e[0]]?.[e[1]]?.[e[2]]?.[e[3]]?.[e[4]]?.[e[5]],(s,e)=>s?.[e[0]]?.[e[1]]?.[e[2]]?.[e[3]]?.[e[4]]?.[e[5]]?.[e[6]],(s,e)=>s?.[e[0]]?.[e[1]]?.[e[2]]?.[e[3]]?.[e[4]]?.[e[5]]?.[e[6]]?.[e[7]]];function ot(s){let t="obj"+Array.from({length:s},(n,r)=>`?.[path[${r}]]`).join(""),i=new Function("obj","path",`return ${t}`);return j[s]=i,i}function Fe(s,e){let t=e.length;return t===0?s:t===1?s[e[0]]:t<j.length&&j[t]||j[t]?j[t](s,e):ot(t)(s,e)}var G=Symbol(),X=class s{static surfaces=new WeakMap;static plugins=new Map;static registerPlugin(e,t){if(s.plugins.has(e))throw new Error(`Plugin "${e}" already registered`);s.plugins.set(e,t())}static resetPlugins(){s.plugins.clear()}static create(e,t={}){let i=new s(t),n=i.setup(e);return s.surfaces.set(n,i),n}static createPlugin(e,t,i={}){let n=s.create(t,i);return s.registerPlugin(e,n),n}constructor(e={}){this.options=e,this.setupFn=null,this.subscribers=new Set,this.subscribersQueued=!1,this.destroyCallback=null,this.values=new Set,this.computeds=new Set,this.actions=new Set,this.extensions=new Set,this.snapshotCache=G,this.surface=this.#p(),this.useSurface=()=>this.surface}setup(e){if(!e)return null;this.setupFn=e,this.reset();let t=new Set;try{let i;if(typeof e=="function")i=this.#e(e,t);else if(typeof e=="object"&&e!==null)i=this.#t(e,t);else throw new Error("setupFn must be a function or object configuration");return this.#o(i),t.forEach(n=>F(n,()=>this.#a())),this.#a(),this.useSurface}catch(i){throw console.error("Error in setup function",i),i}}reset(){this.subscribers.clear(),this.subscribersQueued=!1,this.values.clear(),this.computeds.clear(),this.actions.clear(),this.extensions.clear(),this.snapshotCache=G,this.surface=this.#p()}createValue(e=void 0,t){let i=le(e),n=Object.create(null);return Object.defineProperty(n,"value",{get:()=>i(),set:r=>i(r),enumerable:!0}),this.values.add(n),t?.(i),n}createComputed(e,t){let i=D(e,{context:this.surface}),n=Object.create(null);return Object.defineProperty(n,"value",{get:()=>i(),enumerable:!0}),this.computeds.add(n),t?.(i),n}createAction(e){let t=e.bind(this.surface,this.surface);return this.actions.add(t),t}extend(e){if(!e)throw new Error("No source surface provided");if(!Ve(e))throw new Error("Cannot extend non-surface");let t=e();return this.extensions.add(t),t}#e(e,t){return e({value:(i=void 0)=>this.createValue(i,n=>t.add(n)),computed:(i=()=>{})=>this.createComputed(i,n=>t.add(n)),action:(i=()=>{})=>this.createAction(i),extend:i=>this.extend(i),destroy:()=>this.#s(),...Object.fromEntries(s.plugins.entries())})||{}}#r(e,t,i){if(typeof e!="object"||e===null)return typeof e=="function"?e():e;if(!("default"in e))return t&&"dummy"in e&&console.warn(`State "${i}" has dummy value but no default value`),typeof e=="function"?e():e;let n=t&&"dummy"in e?e.dummy:e.default;return typeof n=="function"?n():n}#t(e,t){let i={},n=this.options.mode==="development"||this.options.mode==="dev";if(e.extend&&Array.isArray(e.extend))for(let r of e.extend)this.extend(r);if(e.state&&typeof e.state=="object")for(let[r,o]of Object.entries(e.state)){let a=this.#r(o,n,r);i[r]=this.createValue(a,c=>t.add(c))}if(e.computed&&typeof e.computed=="object")for(let[r,o]of Object.entries(e.computed))typeof o=="function"&&(i[r]=this.createComputed(o,a=>t.add(a)));if(e.actions&&typeof e.actions=="object")for(let[r,o]of Object.entries(e.actions))typeof o=="function"&&(i[r]=this.createAction(o));return e.onInit&&typeof e.onInit=="function"&&Promise.resolve().then(()=>{try{e.onInit(this.surface)}catch(r){console.error("Error in onInit callback",r)}}),e.onDestroy&&typeof e.onDestroy=="function"&&(this.destroyCallback=e.onDestroy),i}#i(){return[()=>this.#f(),e=>this.#h(e)]}#f(){if(this.snapshotCache!==G)return this.snapshotCache;let e=Object.create(Object.getPrototypeOf(this.surface));return Object.defineProperties(e,Object.getOwnPropertyDescriptors(this.surface)),this.snapshotCache=Object.freeze(e),this.snapshotCache}#h(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}#u(e){for(let t of this.subscribers)t(e)}#a(){this.subscribers.size===0||this.subscribersQueued||(this.subscribersQueued=!0,Promise.resolve().then(()=>{this.subscribersQueued=!1,this.snapshotCache=G,this.#u(this.#f())}))}#p(e=Object.create(null)){return Object.defineProperty(e,"$get",{value:t=>this.#c(t),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$set",{value:(t,i)=>this.#m(t,i),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$dispatch",{value:t=>this.#g(t),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$inject",{value:t=>Object.assign({},this.surface,t),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$snapshot",{value:()=>this.#f(),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$subscribe",{value:t=>this.#h(t),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$adapter",{value:()=>this.#i(),writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(e,"$destroy",{value:()=>this.#s(),writable:!1,enumerable:!1,configurable:!1}),e}#s(){if(this.destroyCallback&&typeof this.destroyCallback=="function")try{this.destroyCallback(this.surface)}catch(t){console.error("Error in onDestroy callback",t)}let e=this.surfaceComputed;this.surfaceComputed=null,s.surfaces.delete(e),R(e)}#c(e=[]){return Fe(this.surface,e)}#m(e,t){let i=this.values?.get?.(e);return i.value=t,this.surface}#g(e,...t){let i=this.actions.has(e)?this.actions.get(e):this.surface[e];return typeof i=="function"?i(...t):this.surfaceComputed()}#o(e={}){let t=Object.keys(this.surface);for(;t.length>0;){let n=t.shift();n in this.surface&&delete this.surface[n]}for(let[n,r]of s.plugins)Object.defineProperty(this.surface,n,{value:r});for(let n of this.extensions){let r=Object.getOwnPropertyDescriptors(n),o=Object.fromEntries(Object.entries(r).filter(([a])=>!a.startsWith("$")));Object.defineProperties(this.surface,o)}let i=Object.entries(e);for(let[n,r]of i){if(this.values.has(r)){Object.defineProperty(this.surface,n,{get:()=>r.value,set:o=>r.value=o});continue}if(this.computeds.has(r)){Object.defineProperty(this.surface,n,{get:()=>r.value});continue}if(this.actions.has(r)){Object.defineProperty(this.surface,n,{value:r});continue}this.surface[n]=r}return this.surface}},he=(...s)=>X.create(...s);var Ve=s=>X.surfaces.has(s);var V=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 N=class extends S{#e=null;#r=null;#t=null;#i=null;#f=new Set;#h=new Set;#u=null;#a=null;#p=!1;static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),onResize:e=>this.onResize(e),transferControlToOffscreen:()=>this.transferControlToOffscreen()}}setCanvas(e){this.#e&&this.#m(),this.#e=e,this.#s(),this.#c()}subscribe(e){return this.#f.add(e),()=>this.#f.delete(e)}onResize(e){return this.#h.add(e),()=>this.#h.delete(e)}transferControlToOffscreen(){if(!this.#e)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#p)throw new Error("Control has already been transferred to offscreen");return this.#r=this.#e.transferControlToOffscreen(),this.#p=!0,this.#r.width=this.#e.width,this.#r.height=this.#e.height,this.#v({width:this.#e.width,height:this.#e.height}),this.#r}#s(){this.#e&&(this.#t=this.#e.getBoundingClientRect())}#c(){this.#e&&(this.#s(),this.#i=new ResizeObserver(e=>{for(let t of e){if(t.target!==this.#e)continue;let{width:i,height:n}=t.contentRect;this.#v({width:i,height:n})}this.#s()}),this.#i.observe(this.#e),document.addEventListener("wheel",this.#g,{passive:!1}),document.addEventListener("pointermove",this.#o),document.addEventListener("pointerdown",this.#y),document.addEventListener("pointerup",this.#d),document.addEventListener("pointercancel",this.#d),document.addEventListener("dblclick",this.#b))}#m(){this.#i&&(this.#i.disconnect(),this.#i=null),document.removeEventListener("wheel",this.#g),document.removeEventListener("pointermove",this.#o),document.removeEventListener("pointerdown",this.#y),document.removeEventListener("pointerup",this.#d),document.removeEventListener("pointercancel",this.#d),document.removeEventListener("dblclick",this.#b)}#g=e=>{if(e.target===this.#e)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#w(e,"zoom");this.#l(t)}else{let t=this.#w(e,"scroll");this.#l(t)}};#o=e=>{let t=this.#w(e,"move");this.#u=t,!this.#a&&(this.#a=requestAnimationFrame(()=>{this.#u&&(this.#l(this.#u),this.#u=null),this.#a=null}))};#y=e=>{if(e.target===this.#e){let t=this.#w(e,"down");this.#l(t)}};#d=e=>{let t=this.#w(e,"up");this.#l(t)};#b=e=>{let t=this.#w(e,"dblclick");this.#l(t)};#l(e){for(let t of this.#f)t(e)}#v(e){for(let t of this.#h)t(e)}#w(e,t){let i=e.target===this.#e,n,r;i?(n=e.offsetX,r=e.offsetY):this.#t?(n=e.clientX-this.#t.left,r=e.clientY-this.#t.top):(n=e.clientX,r=e.clientY);let o=i||this.#t&&n>=0&&n<=this.#t.width&&r>=0&&r<=this.#t.height,a={x:n,y:r,type:t,isOverCanvas:i,isWithinBounds:o,clientX:e.clientX,clientY:e.clientY,button:e.button??null,buttons:e.buttons??0,timestamp:Date.now()};return(t==="scroll"||t==="zoom")&&(a.deltaX=e.deltaX,a.deltaY=e.deltaY,a.deltaZ=e.deltaZ,a.deltaMode=e.deltaMode),a.shiftKey=e.shiftKey||!1,a.ctrlKey=e.ctrlKey||!1,a.altKey=e.altKey||!1,a.metaKey=e.metaKey||!1,a}destroy(){this.#a&&(cancelAnimationFrame(this.#a),this.#a=null),this.#m(),this.#e=null,this.#r=null,this.#t=null,this.#f.clear(),this.#h.clear(),this.#p=!1}};var ue=he(s=>{let e=s.value(0),t=s.value(0),i=s.value(0),n=s.value(0),r=s.value(0),o=s.value(0),a=s.value(!1),c=s.value(!1),h=s.value(!1),g=s.value(null),y=s.value(0),P=s.value(null),q=s.value(null),Ne=s.value(null),de=s.value(null),pe=s.value(null),H=s.value(null),K=s.value(null),w=s.value(!1),A=s.value(0),me=s.value(0),T=s.value(0),O=s.value(0),ye=s.value(0),be=s.value(0),ge=s.value(0),_=s.value(null),z=s.value(null),E=s.value({dragThreshold:5,doubleClickThreshold:300,holdThreshold:500,velocitySmoothing:.3,maxVelocity:1e4}),we=s.computed(()=>({x:e.value,y:t.value})),ve=s.computed(()=>({x:r.value,y:o.value})),xe=s.computed(()=>({x:i.value,y:n.value})),Ae=s.computed(()=>{let f=typeof e.value=="number"?e.value:0,u=typeof i.value=="number"?i.value:0,d=typeof t.value=="number"?t.value:0,p=typeof n.value=="number"?n.value:0;return{x:f-u,y:d-p}}),Ee=s.computed(()=>({x:T.value,y:O.value})),Ce=s.computed(()=>{let f=T.value,u=O.value;return Math.sqrt(f*f+u*u)}),Z=s.computed(()=>{let f=H.value,u=K.value;if(f===null||u===null||typeof f!="number"||typeof u!="number")return 0;let d=typeof e.value=="number"?e.value:0,p=typeof t.value=="number"?t.value:0,C=d-f,m=p-u;return Math.sqrt(C*C+m*m)}),Se=s.computed(()=>{let f=H.value,u=K.value;if(f===null||u===null||typeof f!="number"||typeof u!="number")return{x:0,y:0};let d=typeof e.value=="number"?e.value:0,p=typeof t.value=="number"?t.value:0;return{x:d-f,y:p-u}}),J=s.computed(()=>!h.value||!q.value?0:Date.now()-q.value),Te=s.computed(()=>J.value>E.value.holdThreshold&&!w.value),_e=s.computed(()=>{let f=pe.value;return f?Date.now()-f:0}),ze=s.computed(()=>({position:we.value,clientPosition:ve.value,previousPosition:xe.value,delta:Ae.value,velocity:Ee.value,speed:Ce.value,isPressed:h.value,button:g.value,buttons:y.value,isDragging:w.value,dragDistance:Z.value,dragDelta:Se.value,isHolding:Te.value,holdDuration:J.value,isOverCanvas:a.value,isWithinBounds:c.value,hoveredArea:_.value,activeArea:z.value,clickCount:A.value,lastEventType:P.value})),k=(f,u,d,p)=>{i.value=e.value,n.value=t.value,e.value=f,t.value=u,r.value=d,o.value=p,de.value=Date.now()},Be=()=>{let f=Date.now(),u=de.value;if(u){let d=(f-u)/1e3;if(d>0&&d<.1){let p=(e.value-i.value)/d,C=(t.value-n.value)/d,m=E.value.maxVelocity,v=Math.max(-m,Math.min(m,p)),Q=Math.max(-m,Math.min(m,C)),x=E.value.velocitySmoothing;T.value=T.value*(1-x)+v*x,O.value=O.value*(1-x)+Q*x}}},Ue=s.action((f,u)=>{let{x:d,y:p,type:C,clientX:m,clientY:v,button:Q,buttons:x,isOverCanvas:qe,isWithinBounds:He}=u,M=Date.now();switch(pe.value=M,P.value=C,a.value=qe,c.value=He,C){case"down":k(d,p,m,v),h.value=!0,q.value=M,g.value=Q,y.value=x,H.value=d,K.value=p,w.value=!1,M-me.value<E.value.doubleClickThreshold?A.value=A.value+1:A.value=1;break;case"up":k(d,p,m,v),h.value=!1,Ne.value=M,me.value=M,w.value=!1,T.value=0,O.value=0,y.value=x;break;case"move":k(d,p,m,v),Be(),y.value=x,h.value&&!w.value&&Z.value>E.value.dragThreshold&&(w.value=!0);break;case"dblclick":k(d,p,m,v),A.value=2;break;case"scroll":k(d,p,m,v),u.deltaX!==void 0&&(ye.value=u.deltaX),u.deltaY!==void 0&&(be.value=u.deltaY);break;case"zoom":k(d,p,m,v),u.deltaY!==void 0&&(ge.value=u.deltaY);break}}),We=s.action((f,u)=>{_.value=u}),Ye=s.action((f,u)=>{z.value=u}),Ge=s.action(()=>{h.value=!1,w.value=!1,z.value=null,_.value=null,T.value=0,O.value=0,A.value=0,ye.value=0,be.value=0,ge.value=0}),Xe=s.action((f,u)=>{E.value={...E.value,...u}});return{state:ze,position:we,clientPosition:ve,previousPosition:xe,delta:Ae,velocity:Ee,speed:Ce,isPressed:h,button:g,buttons:y,isDragging:w,dragDistance:Z,dragDelta:Se,isHolding:Te,holdDuration:J,isOverCanvas:a,isWithinBounds:c,hoveredArea:_,activeArea:z,clickCount:A,lastEventType:P,timeSinceLastEvent:_e,handleEvent:Ue,setHoveredArea:We,setActiveArea:Ye,reset:Ge,updateConfig:Xe}});var at=b("BRUSH",[Object]),ct=b("LAYER",[Object]),fe=class extends S{#e=new Map;#r=null;#t=new Map;#i=new Map;#f=new Map;#h=!1;#u=null;#a=!1;#p=!1;#s={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#c={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#m={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#g=new V;#o=ue();#y=null;#d=null;#b=null;#l=new Map;#v=!1;#w=!1;#A=!1;static manifest={name:"Painter",namespace:"painter",version:"1.0.0",defaults:{targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}}};getters(){return{pointer:()=>this.#o.state}}actions(){return this.config&&Object.assign(this.#s,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.#o.$subscribe(e),bindPointer:e=>this.#o.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){let t=e,i=e.transferControlToOffscreen();i.width=t.width,i.height=t.height,this.#r=i,Object.values(L).forEach(n=>{try{let r=i.getContext(n);r&&this.#t.set(n,r)}catch{console.warn(`Context type ${n} not supported`)}}),this.#y||(this.#y=new N),this.#y.setCanvas(t),this.#b&&this.#b.disconnect(),this.#b=new ResizeObserver(n=>{let r=n[0];r&&r.target===t&&(i.width=t.width,i.height=t.height,this.handleResize(t.width,t.height))}),this.#b.observe(t),this.#d&&this.#d(),this.#d=this.#y.subscribe(n=>{this.handlePointerEvent(n)})}setOffscreenCanvas(e){this.#r=e,Object.values(L).forEach(t=>{try{let i=e.getContext(t);i&&this.#t.set(t,i)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#r);t&&(this.#r=t)}setAssets(e){this.#f=e}start(){this.#h||(this.#h=!0,this.#E())}stop(){this.#h&&(this.#h=!1,this.#u&&(cancelAnimationFrame(this.#u),this.#u=null))}addLayer(e){if(I(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,i=e(this.useContext,this.#g);if(i.data){let o=this.#C(`layer_${t}`,i.data);o&&this.#i.set(`layer_${t}`,o)}let n=i.children.map(o=>{if(I(o)==="BRUSH"){let a=o._name,c=o(this.useContext,this.#g),h=c.data?this.#C(`brush_${a}`,c.data):()=>{},g=c.when?D(c.when,{immediate:!0,context:()=>this.#o.state}):null,y={name:a,...c,dataReactor:h,whenReactor:g};if(y.lifecycle?.onMount)try{y.lifecycle.onMount(this.#t.get(y.context||i.context))}catch(P){console.error(`Error in brush "${y.name}" onMount:`,P)}return y}return this.addLayer(o)}),r={...i,name:t,brushes:n,context:this.#t.get(i.context)};if(this.#e.set(t,r),r.lifecycle?.onMount)try{r.lifecycle.onMount(r.context)}catch(o){console.error(`Error in layer "${t}" onMount:`,o)}return r}removeLayer(e){let t=this.#e.get(e);if(!t)return;if(t.lifecycle?.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(n){console.error(`Error in layer "${e}" onUnmount:`,n)}t.brushes.forEach(n=>{if(n.lifecycle?.onUnmount)try{n.lifecycle.onUnmount(this.#t.get(n.context||t.context))}catch(o){console.error(`Error in brush "${n.name}" onUnmount:`,o)}let r=this.#i.get(`painter_brush_${n.name}`);r&&(r.unsubscribe(),r.computed&&R(r.computed),this.#i.delete(`painter_brush_${n.name}`))});let i=this.#i.get(`painter_layer_${e}`);i&&(i.unsubscribe(),i.computed&&R(i.computed),this.#i.delete(`painter_layer_${e}`)),this.#e.delete(e)}#E(){this.#p||this.#a||(this.#p=!0,this.#u=requestAnimationFrame(()=>{this.#p=!1,this.#u=null,this.#O()}))}async#O(){if(this.#r){this.#a=!0;try{this.#g.clear();let e=this.#s.debug?.enabled?performance.now():0;this.#t.forEach(t=>{t.clearRect(0,0,this.#r.width,this.#r.height)});for(let t of this.#e.values()){let i=this.#s.debug?.enabled?performance.now():0;if(t.whenReactor){let r=this.#i.get(`painter_layer_${t.name}`)?.computed;if(!t.when(r()))continue}let n=t.context;if(n){if(t.lifecycle?.beforeRender)try{t.lifecycle.beforeRender(n,this.#c)}catch(r){console.error(`Error in layer "${t.name}" beforeRender:`,r),t.lifecycle?.onError&&t.lifecycle.onError(r)}n.save(),t.settings&&Object.entries(t.settings).forEach(([r,o])=>{typeof n[r]=="function"?n[r](...Array.isArray(o)?o:[o]):n[r]=o});for(let r of t.brushes){let o=this.#s.debug?.enabled?performance.now():0;if(r.whenReactor&&!r.whenReactor())continue;let a=r.context?this.#t.get(r.context):n;if(a){if(r.lifecycle?.beforeRender)try{r.lifecycle.beforeRender(a,this.#c)}catch(c){console.error(`Error in brush "${r.name}" beforeRender:`,c),r.lifecycle?.onError&&r.lifecycle.onError(c);continue}a.save(),r.settings&&Object.entries(r.settings).forEach(([c,h])=>{typeof a[c]=="function"?a[c](...Array.isArray(h)?h:[h]):a[c]=h});try{let c={};if(r.assets)for(let h of r.assets)c[h]=this.#f.get(h);if(r.render(a,r.dataReactor(),c,this.#c),r.lifecycle?.afterRender&&r.lifecycle.afterRender(a,this.#c),this.#s.debug?.enabled){let h=performance.now()-o;this.#m.brushTimes.set(r.name,h),this.#s.debug?.showBounds&&this.#k(a,r)}}catch(c){console.error(`Error in brush "${r.name}":`,c),r.lifecycle?.onError&&r.lifecycle.onError(c)}finally{a.restore()}}}if(n.restore(),t.lifecycle?.afterRender)try{t.lifecycle.afterRender(n,this.#c)}catch(r){console.error(`Error in layer "${t.name}" afterRender:`,r),t.lifecycle?.onError&&t.lifecycle.onError(r)}if(this.#s.debug?.enabled){let r=performance.now()-i;this.#m.layerTimes.set(t.name,r),this.#s.debug?.showBounds&&this.#I(n,t)}}}this.#s.debug?.enabled&&this.#D()}finally{this.#a=!1}}}#k(e,t){e.save(),e.strokeStyle="rgba(0, 255, 0, 0.5)",e.lineWidth=1,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#I(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()}#D(){let e=this.#t.get(L["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(this.#s.debug?.showFPS){let n=`FPS: ${Math.round(this.#m.fps)} (${this.#c.deltaTime.toFixed(2)}ms)`;e.strokeText(n,10,t),e.fillText(n,10,t),t+=i}if(this.#s.debug?.showLayerTiming){e.fillText("Layer Times:",10,t),t+=i;for(let[n,r]of this.#m.layerTimes){let o=` ${n}: ${r.toFixed(2)}ms`;e.strokeText(o,10,t),e.fillText(o,10,t),t+=i}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){for(let i of this.#e.values())if(i.lifecycle?.onResize)try{i.lifecycle.onResize(e,t,i.context)}catch(n){console.error(`Error in layer "${i.name}" onResize:`,n),i.lifecycle?.onError&&i.lifecycle.onError(n)}}#C(e,t){let i=D(t,{immediate:!0,context:()=>this.#o.state}),n=F(i,()=>this.#E());return this.#i.set(`painter_${e}`,{computed:i,unsubscribe:n}),i}destroy(){this.stop(),this.#d&&(this.#d(),this.#d=null),this.#y&&(this.#y.destroy(),this.#y=null),this.#b&&(this.#b.disconnect(),this.#b=null),this.#o&&this.#o.$destroy();for(let e of this.#e.keys())this.removeLayer(e)}setTargetFPS(e){this.#s.targetFPS=e,this.#s.fixedTimeStep=1e3/e}setTimeScale(e){this.#s.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#s.fixedTimeStep=e}setDebug(e={}){this.#s.debug||(this.#s.debug={}),Object.assign(this.#s.debug,e)}getMetrics(){return{...this.#m,deltaTime:this.#c.deltaTime,elapsedTime:this.#c.elapsedTime,frameCount:this.#c.frameCount}}handlePointerEvent(e){this.#o.handleEvent(e),this.#S(e),this.#R(e)}#R(e){let{type:t}=e,i=this.#o;switch(t){case"down":this.#n("pointer:down",i.state);break;case"up":this.#n("pointer:up",i.state),i.isDragging||this.#n("pointer:click",i.state);break;case"move":if(this.#n("pointer:move",i.state),i.isDragging&&i.isPressed){let c=this.#v;this.#v=!0,c?this.#n("pointer:drag:move",i.state):this.#n("pointer:drag:start",i.state)}break;case"scroll":this.#n("pointer:scroll",i.state);break;case"zoom":this.#n("pointer:zoom",i.state);break;case"dblclick":this.#n("pointer:dblclick",i.state);break}t==="up"&&this.#v&&(this.#n("pointer:drag:end",i.state),this.#v=!1);let n=this.#w,r=i.isOverCanvas;r&&!n?this.#n("pointer:enter",i.state):!r&&n&&this.#n("pointer:leave",i.state),this.#w=r;let o=this.#A,a=i.isHolding;a&&!o?this.#n("pointer:hold:start",i.state):!a&&o&&this.#n("pointer:hold:end",i.state),this.#A=a}#S(e){let{type:t,x:i,y:n}=e,r=this.#o;switch(t){case"down":{let o=this.#T(i,n);if(r.setActiveArea(o),o?.onPointerDown?.handler){let a=this.#x(o);o.onPointerDown.handler({...r.state,ctx:a,emit:this.#n.bind(this)})}break}case"up":{let o=r.activeArea;if(o?.onPointerUp?.handler){let a=this.#x(o);o.onPointerUp.handler({...r.state,ctx:a,emit:this.#n.bind(this)})}break}case"move":{let o=this.#T(i,n),a=r.hoveredArea,c=r.activeArea;if(c?.onPointerMove?.handler&&r.isDragging){let h=this.#x(c);c.onPointerMove.handler({...r.state,ctx:h,emit:this.#n.bind(this)})}if(o?.id!==a?.id){if(a?.onPointerLeave?.handler){let h=this.#x(a);a.onPointerLeave.handler({...r.state,ctx:h,emit:this.#n.bind(this)})}if(o?.onPointerEnter?.handler){let h=this.#x(o);o.onPointerEnter.handler({...r.state,ctx:h,emit:this.#n.bind(this)})}r.setHoveredArea(o)}break}case"scroll":case"zoom":break;case"dblclick":break}}#x(e){return e?e.context?this.#t.get(e.context):this.#t.get(L["2D"]):null}subscribe(e,t){return this.#l.has(e)||this.#l.set(e,new Set),this.#l.get(e).add(t),()=>{let i=this.#l.get(e);i&&(i.delete(t),i.size===0&&this.#l.delete(e))}}#T(e,t){let i=this.#g.areas.sort((n,r)=>(r.priority||0)-(n.priority||0));for(let n of i)if(this.#j(e,t,n.bounds))return n;return null}#j(e,t,i){return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height}#n(e,t){let i=this.#l.get(e);if(i)for(let n of i)n(t)}_testEmitPointerEvent(e){this.#o.handleEvent(e),this.#S(e)}};export{N as CanvasEvents,V as HitRegistry,fe as Painter,at as defineBrush,ct as defineLayer,ue as usePointerSurface};
1
+ var U=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var Ee=(r,e)=>{for(var t in e)U(r,t,{get:e[t],enumerable:!0})},Ce=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of xe(e))!Te.call(r,n)&&n!==t&&U(r,n,{get:()=>e[n],enumerable:!(s=we(e,n))||s.enumerable});return r};var Se=r=>Ce(U({},"__esModule",{value:!0}),r);var Re={};Ee(Re,{CanvasEvents:()=>P,HitRegistry:()=>R,Painter:()=>z,defineBrush:()=>oe,defineLayer:()=>le,usePointerSurface:()=>Y});module.exports=Se(Re);var ae=require("@jucie.io/engine");var M={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var p=require("@jucie.io/reactive"),k=require("@jucie.io/engine");var R=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 ne=require("@jucie.io/engine"),P=class extends ne.ServiceProvider{#e=null;#r=null;#s=null;#a=null;#b=new Set;#v=new Set;#h=null;#u=null;#g=!1;static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),onResize:e=>this.onResize(e),transferControlToOffscreen:()=>this.transferControlToOffscreen()}}setCanvas(e){this.#e&&this.#y(),this.#e=e,this.#t(),this.#l()}subscribe(e){return this.#b.add(e),()=>this.#b.delete(e)}onResize(e){return this.#v.add(e),()=>this.#v.delete(e)}transferControlToOffscreen(){if(!this.#e)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#g)throw new Error("Control has already been transferred to offscreen");return this.#r=this.#e.transferControlToOffscreen(),this.#g=!0,this.#r.width=this.#e.width,this.#r.height=this.#e.height,this.#w({width:this.#e.width,height:this.#e.height}),this.#r}#t(){this.#e&&(this.#s=this.#e.getBoundingClientRect())}#l(){this.#e&&(this.#t(),this.#a=new ResizeObserver(e=>{for(let t of e){if(t.target!==this.#e)continue;let{width:s,height:n}=t.contentRect;this.#w({width:s,height:n})}this.#t()}),this.#a.observe(this.#e),document.addEventListener("wheel",this.#p,{passive:!1}),document.addEventListener("pointermove",this.#n),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#c),document.addEventListener("pointercancel",this.#c),document.addEventListener("dblclick",this.#f))}#y(){this.#a&&(this.#a.disconnect(),this.#a=null),document.removeEventListener("wheel",this.#p),document.removeEventListener("pointermove",this.#n),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#c),document.removeEventListener("pointercancel",this.#c),document.removeEventListener("dblclick",this.#f)}#p=e=>{if(e.target===this.#e)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#m(e,"zoom");this.#o(t)}else{let t=this.#m(e,"scroll");this.#o(t)}};#n=e=>{let t=this.#m(e,"move");this.#h=t,!this.#u&&(this.#u=requestAnimationFrame(()=>{this.#h&&(this.#o(this.#h),this.#h=null),this.#u=null}))};#d=e=>{if(e.target===this.#e){let t=this.#m(e,"down");this.#o(t)}};#c=e=>{let t=this.#m(e,"up");this.#o(t)};#f=e=>{let t=this.#m(e,"dblclick");this.#o(t)};#o(e){for(let t of this.#b)t(e)}#w(e){for(let t of this.#v)t(e)}#m(e,t){let s=e.target===this.#e,n,i;s?(n=e.offsetX,i=e.offsetY):this.#s?(n=e.clientX-this.#s.left,i=e.clientY-this.#s.top):(n=e.clientX,i=e.clientY);let a=s||this.#s&&n>=0&&n<=this.#s.width&&i>=0&&i<=this.#s.height,o={x:n,y:i,type:t,isOverCanvas:s,isWithinBounds:a,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.#u&&(cancelAnimationFrame(this.#u),this.#u=null),this.#y(),this.#e=null,this.#r=null,this.#s=null,this.#b.clear(),this.#v.clear(),this.#g=!1}};var re=require("@jucie.io/reactive"),Y=(0,re.defineSurface)(r=>{let e=r.value(0),t=r.value(0),s=r.value(0),n=r.value(0),i=r.value(0),a=r.value(0),o=r.value(!1),c=r.value(!1),h=r.value(!1),L=r.value(null),m=r.value(0),D=r.value(null),B=r.value(null),ce=r.value(null),W=r.value(null),K=r.value(null),F=r.value(null),X=r.value(null),y=r.value(!1),w=r.value(0),j=r.value(0),E=r.value(0),C=r.value(0),I=r.value(0),q=r.value(0),Z=r.value(0),O=r.value(null),$=r.value(null),x=r.value({dragThreshold:5,doubleClickThreshold:300,holdThreshold:500,velocitySmoothing:.3,maxVelocity:1e4}),G=r.computed(()=>({x:e.value,y:t.value})),N=r.computed(()=>({x:i.value,y:a.value})),J=r.computed(()=>({x:s.value,y:n.value})),Q=r.computed(()=>{let u=typeof e.value=="number"?e.value:0,l=typeof s.value=="number"?s.value:0,d=typeof t.value=="number"?t.value:0,f=typeof n.value=="number"?n.value:0;return{x:u-l,y:d-f}}),ee=r.computed(()=>({x:E.value,y:C.value})),te=r.computed(()=>{let u=E.value,l=C.value;return Math.sqrt(u*u+l*l)}),_=r.computed(()=>{let u=F.value,l=X.value;if(u===null||l===null||typeof u!="number"||typeof l!="number")return 0;let d=typeof e.value=="number"?e.value:0,f=typeof t.value=="number"?t.value:0,T=d-u,v=f-l;return Math.sqrt(T*T+v*v)}),se=r.computed(()=>{let u=F.value,l=X.value;if(u===null||l===null||typeof u!="number"||typeof l!="number")return{x:0,y:0};let d=typeof e.value=="number"?e.value:0,f=typeof t.value=="number"?t.value:0;return{x:d-u,y:f-l}}),V=r.computed(()=>!h.value||!B.value?0:Date.now()-B.value),ie=r.computed(()=>V.value>x.value.holdThreshold&&!y.value),he=r.computed(()=>{let u=K.value;return u?Date.now()-u:0}),ue=r.computed(()=>({position:G.value,clientPosition:N.value,previousPosition:J.value,delta:Q.value,velocity:ee.value,speed:te.value,isPressed:h.value,button:L.value,buttons:m.value,isDragging:y.value,dragDistance:_.value,dragDelta:se.value,isHolding:ie.value,holdDuration:V.value,isOverCanvas:o.value,isWithinBounds:c.value,hoveredArea:O.value,activeArea:$.value,clickCount:w.value,lastEventType:D.value})),S=(u,l,d,f)=>{s.value=e.value,n.value=t.value,e.value=u,t.value=l,i.value=d,a.value=f,W.value=Date.now()},de=()=>{let u=Date.now(),l=W.value;if(l){let d=(u-l)/1e3;if(d>0&&d<.1){let f=(e.value-s.value)/d,T=(t.value-n.value)/d,v=x.value.maxVelocity,b=Math.max(-v,Math.min(v,f)),H=Math.max(-v,Math.min(v,T)),g=x.value.velocitySmoothing;E.value=E.value*(1-g)+b*g,C.value=C.value*(1-g)+H*g}}},fe=r.action((u,l)=>{let{x:d,y:f,type:T,clientX:v,clientY:b,button:H,buttons:g,isOverCanvas:ge,isWithinBounds:pe}=l,A=Date.now();switch(K.value=A,D.value=T,o.value=ge,c.value=pe,T){case"down":S(d,f,v,b),h.value=!0,B.value=A,L.value=H,m.value=g,F.value=d,X.value=f,y.value=!1,A-j.value<x.value.doubleClickThreshold?w.value=w.value+1:w.value=1;break;case"up":S(d,f,v,b),h.value=!1,ce.value=A,j.value=A,y.value=!1,E.value=0,C.value=0,m.value=g;break;case"move":S(d,f,v,b),de(),m.value=g,h.value&&!y.value&&_.value>x.value.dragThreshold&&(y.value=!0);break;case"dblclick":S(d,f,v,b),w.value=2;break;case"scroll":S(d,f,v,b),l.deltaX!==void 0&&(I.value=l.deltaX),l.deltaY!==void 0&&(q.value=l.deltaY);break;case"zoom":S(d,f,v,b),l.deltaY!==void 0&&(Z.value=l.deltaY);break}}),ve=r.action((u,l)=>{O.value=l}),me=r.action((u,l)=>{$.value=l}),ye=r.action(()=>{h.value=!1,y.value=!1,$.value=null,O.value=null,E.value=0,C.value=0,w.value=0,I.value=0,q.value=0,Z.value=0}),be=r.action((u,l)=>{x.value={...x.value,...l}});return{state:ue,position:G,clientPosition:N,previousPosition:J,delta:Q,velocity:ee,speed:te,isPressed:h,button:L,buttons:m,isDragging:y,dragDistance:_,dragDelta:se,isHolding:ie,holdDuration:V,isOverCanvas:o,isWithinBounds:c,hoveredArea:O,activeArea:$,clickCount:w,lastEventType:D,timeSinceLastEvent:he,handleEvent:fe,setHoveredArea:ve,setActiveArea:me,reset:ye,updateConfig:be}});var oe=(0,k.createDefinition)("BRUSH",[Object]),le=(0,k.createDefinition)("LAYER",[Object]),z=class extends ae.ServiceProvider{#e=new Map;#r=null;#s=new Map;#a=new Map;#b=new Map;#v=!1;#h=null;#u=!1;#g=!1;#t={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#l={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#y={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#p=new R;#n=Y();#d=null;#c=null;#f=null;#o=new Map;#w=!1;#m=!1;#T=!1;static manifest={name:"Painter",namespace:"painter",version:"1.0.0",defaults:{targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}}};getters(){return{pointer:()=>this.#n.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.#n.$subscribe(e),bindPointer:e=>this.#n.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){let t=e,s=e.transferControlToOffscreen();s.width=t.width,s.height=t.height,this.#r=s,Object.values(M).forEach(n=>{try{let i=s.getContext(n);i&&this.#s.set(n,i)}catch{console.warn(`Context type ${n} not supported`)}}),this.#d||(this.#d=new P),this.#d.setCanvas(t),this.#f&&this.#f.disconnect(),this.#f=new ResizeObserver(n=>{let i=n[0];i&&i.target===t&&(s.width=t.width,s.height=t.height,this.handleResize(t.width,t.height))}),this.#f.observe(t),this.#c&&this.#c(),this.#c=this.#d.subscribe(n=>{this.handlePointerEvent(n)})}setOffscreenCanvas(e){this.#r=e,Object.values(M).forEach(t=>{try{let s=e.getContext(t);s&&this.#s.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#r);t&&(this.#r=t)}setAssets(e){this.#b=e}start(){this.#v||(this.#v=!0,this.#E())}stop(){this.#v&&(this.#v=!1,this.#h&&(cancelAnimationFrame(this.#h),this.#h=null))}addLayer(e){if((0,k.definitionType)(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#p);if(s.data){let a=this.#C(`layer_${t}`,s.data);a&&this.#a.set(`layer_${t}`,a)}let n=s.children.map(a=>{if((0,k.definitionType)(a)==="BRUSH"){let o=a._name,c=a(this.useContext,this.#p),h=c.data?this.#C(`brush_${o}`,c.data):()=>{},L=c.when?(0,p.createComputed)(c.when,{immediate:!0,context:()=>this.#n.state}):null,m={name:o,...c,dataReactor:h,whenReactor:L};if(m.lifecycle?.onMount)try{m.lifecycle.onMount(this.#s.get(m.context||s.context))}catch(D){console.error(`Error in brush "${m.name}" onMount:`,D)}return m}return this.addLayer(a)}),i={...s,name:t,brushes:n,context:this.#s.get(s.context)};if(this.#e.set(t,i),i.lifecycle?.onMount)try{i.lifecycle.onMount(i.context)}catch(a){console.error(`Error in layer "${t}" onMount:`,a)}return i}removeLayer(e){let t=this.#e.get(e);if(!t)return;if(t.lifecycle?.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(n){console.error(`Error in layer "${e}" onUnmount:`,n)}t.brushes.forEach(n=>{if(n.lifecycle?.onUnmount)try{n.lifecycle.onUnmount(this.#s.get(n.context||t.context))}catch(a){console.error(`Error in brush "${n.name}" onUnmount:`,a)}let i=this.#a.get(`painter_brush_${n.name}`);i&&(i.unsubscribe(),i.computed&&(0,p.destroyComputed)(i.computed),this.#a.delete(`painter_brush_${n.name}`))});let s=this.#a.get(`painter_layer_${e}`);s&&(s.unsubscribe(),s.computed&&(0,p.destroyComputed)(s.computed),this.#a.delete(`painter_layer_${e}`)),this.#e.delete(e)}#E(){this.#g||this.#u||(this.#g=!0,this.#h=requestAnimationFrame(()=>{this.#g=!1,this.#h=null,this.#P()}))}async#P(){if(this.#r){this.#u=!0;try{this.#p.clear();let e=this.#t.debug?.enabled?performance.now():0;this.#s.forEach(t=>{t.clearRect(0,0,this.#r.width,this.#r.height)});for(let t of this.#e.values()){let s=this.#t.debug?.enabled?performance.now():0;if(t.whenReactor){let i=this.#a.get(`painter_layer_${t.name}`)?.computed;if(!t.when(i()))continue}let n=t.context;if(n){if(t.lifecycle?.beforeRender)try{t.lifecycle.beforeRender(n,this.#l)}catch(i){console.error(`Error in layer "${t.name}" beforeRender:`,i),t.lifecycle?.onError&&t.lifecycle.onError(i)}n.save(),t.settings&&Object.entries(t.settings).forEach(([i,a])=>{typeof n[i]=="function"?n[i](...Array.isArray(a)?a:[a]):n[i]=a});for(let i of t.brushes){let a=this.#t.debug?.enabled?performance.now():0;if(i.whenReactor&&!i.whenReactor())continue;let o=i.context?this.#s.get(i.context):n;if(o){if(i.lifecycle?.beforeRender)try{i.lifecycle.beforeRender(o,this.#l)}catch(c){console.error(`Error in brush "${i.name}" beforeRender:`,c),i.lifecycle?.onError&&i.lifecycle.onError(c);continue}o.save(),i.settings&&Object.entries(i.settings).forEach(([c,h])=>{typeof o[c]=="function"?o[c](...Array.isArray(h)?h:[h]):o[c]=h});try{let c={};if(i.assets)for(let h of i.assets)c[h]=this.#b.get(h);if(i.render(o,i.dataReactor(),c,this.#l),i.lifecycle?.afterRender&&i.lifecycle.afterRender(o,this.#l),this.#t.debug?.enabled){let h=performance.now()-a;this.#y.brushTimes.set(i.name,h),this.#t.debug?.showBounds&&this.#k(o,i)}}catch(c){console.error(`Error in brush "${i.name}":`,c),i.lifecycle?.onError&&i.lifecycle.onError(c)}finally{o.restore()}}}if(n.restore(),t.lifecycle?.afterRender)try{t.lifecycle.afterRender(n,this.#l)}catch(i){console.error(`Error in layer "${t.name}" afterRender:`,i),t.lifecycle?.onError&&t.lifecycle.onError(i)}if(this.#t.debug?.enabled){let i=performance.now()-s;this.#y.layerTimes.set(t.name,i),this.#t.debug?.showBounds&&this.#L(n,t)}}}this.#t.debug?.enabled&&this.#D()}finally{this.#u=!1}}}#k(e,t){e.save(),e.strokeStyle="rgba(0, 255, 0, 0.5)",e.lineWidth=1,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#L(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()}#D(){let e=this.#s.get(M["2D"]);if(!e)return;e.save(),e.resetTransform(),e.font="12px monospace",e.fillStyle="white",e.strokeStyle="black",e.lineWidth=3;let t=20,s=15;if(this.#t.debug?.showFPS){let n=`FPS: ${Math.round(this.#y.fps)} (${this.#l.deltaTime.toFixed(2)}ms)`;e.strokeText(n,10,t),e.fillText(n,10,t),t+=s}if(this.#t.debug?.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[n,i]of this.#y.layerTimes){let a=` ${n}: ${i.toFixed(2)}ms`;e.strokeText(a,10,t),e.fillText(a,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){for(let s of this.#e.values())if(s.lifecycle?.onResize)try{s.lifecycle.onResize(e,t,s.context)}catch(n){console.error(`Error in layer "${s.name}" onResize:`,n),s.lifecycle?.onError&&s.lifecycle.onError(n)}}#C(e,t){let s=(0,p.createComputed)(t,{immediate:!0,context:()=>this.#n.state}),n=(0,p.addEffect)(s,()=>this.#E());return this.#a.set(`painter_${e}`,{computed:s,unsubscribe:n}),s}destroy(){this.stop(),this.#c&&(this.#c(),this.#c=null),this.#d&&(this.#d.destroy(),this.#d=null),this.#f&&(this.#f.disconnect(),this.#f=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.#y,deltaTime:this.#l.deltaTime,elapsedTime:this.#l.elapsedTime,frameCount:this.#l.frameCount}}handlePointerEvent(e){this.#n.handleEvent(e),this.#S(e),this.#A(e)}#A(e){let{type:t}=e,s=this.#n;switch(t){case"down":this.#i("pointer:down",s.state);break;case"up":this.#i("pointer:up",s.state),s.isDragging||this.#i("pointer:click",s.state);break;case"move":if(this.#i("pointer:move",s.state),s.isDragging&&s.isPressed){let c=this.#w;this.#w=!0,c?this.#i("pointer:drag:move",s.state):this.#i("pointer:drag:start",s.state)}break;case"scroll":this.#i("pointer:scroll",s.state);break;case"zoom":this.#i("pointer:zoom",s.state);break;case"dblclick":this.#i("pointer:dblclick",s.state);break}t==="up"&&this.#w&&(this.#i("pointer:drag:end",s.state),this.#w=!1);let n=this.#m,i=s.isOverCanvas;i&&!n?this.#i("pointer:enter",s.state):!i&&n&&this.#i("pointer:leave",s.state),this.#m=i;let a=this.#T,o=s.isHolding;o&&!a?this.#i("pointer:hold:start",s.state):!o&&a&&this.#i("pointer:hold:end",s.state),this.#T=o}#S(e){let{type:t,x:s,y:n}=e,i=this.#n;switch(t){case"down":{let a=this.#R(s,n);if(i.setActiveArea(a),a?.onPointerDown?.handler){let o=this.#x(a);a.onPointerDown.handler({...i.state,ctx:o,emit:this.#i.bind(this)})}break}case"up":{let a=i.activeArea;if(a?.onPointerUp?.handler){let o=this.#x(a);a.onPointerUp.handler({...i.state,ctx:o,emit:this.#i.bind(this)})}break}case"move":{let a=this.#R(s,n),o=i.hoveredArea,c=i.activeArea;if(c?.onPointerMove?.handler&&i.isDragging){let h=this.#x(c);c.onPointerMove.handler({...i.state,ctx:h,emit:this.#i.bind(this)})}if(a?.id!==o?.id){if(o?.onPointerLeave?.handler){let h=this.#x(o);o.onPointerLeave.handler({...i.state,ctx:h,emit:this.#i.bind(this)})}if(a?.onPointerEnter?.handler){let h=this.#x(a);a.onPointerEnter.handler({...i.state,ctx:h,emit:this.#i.bind(this)})}i.setHoveredArea(a)}break}case"scroll":case"zoom":break;case"dblclick":break}}#x(e){return e?e.context?this.#s.get(e.context):this.#s.get(M["2D"]):null}subscribe(e,t){return this.#o.has(e)||this.#o.set(e,new Set),this.#o.get(e).add(t),()=>{let s=this.#o.get(e);s&&(s.delete(t),s.size===0&&this.#o.delete(e))}}#R(e,t){let s=this.#p.areas.sort((n,i)=>(i.priority||0)-(n.priority||0));for(let n of s)if(this.#M(e,t,n.bounds))return n;return null}#M(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#i(e,t){let s=this.#o.get(e);if(s)for(let n of s)n(t)}_testEmitPointerEvent(e){this.#n.handleEvent(e),this.#S(e)}};0&&(module.exports={CanvasEvents,HitRegistry,Painter,defineBrush,defineLayer,usePointerSurface});
2
2
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/lib/relay/src/Relay.js", "../../../src/utils/typeChecker.js", "../../../src/definitions/createDefinition.js", "../../../src/utils/asserts.js", "../../../src/definitions/defaults.js", "../../../src/definitions/DefinitionBuilder.js", "../../../src/ServiceProvider.js", "../../../src/global.js", "../src/ContextTypes.js", "../../../../reactive/src/utils/nextIdleTick.js", "../../../../reactive/src/ComputationManager.js", "../../../../reactive/src/Reactive.js", "../../../../reactive/src/utils/isAsync.js", "../../../../reactive/src/Computed.js", "../../../../reactive/src/Signal.js", "../../../../reactive/src/lib/traverse.js", "../../../../reactive/src/Surface.js", "../src/HitRegistry.js", "../src/CanvasEvents.js", "../src/usePointerSurface.js", "../src/Painter.js"],
4
- "sourcesContent": ["// Simple, readable relay with wildcard matching and no indexing\n\nconst GLOBAL_NS_OBJ = Object.freeze(Object.create(null));\n\nfunction queueMicrotask(fn) {\n if (globalThis.queueMicrotask && typeof globalThis.queueMicrotask === 'function') {\n globalThis.queueMicrotask(fn);\n return;\n }\n setTimeout(fn, 0);\n}\n\nclass Channel {\n #nsObj; #relay;\n constructor(nsObj, relay) { this.#nsObj = nsObj; this.#relay = relay; }\n\n // Any source -> me\n on(event, handler) {\n return this.#relay.subscribe(event, GLOBAL_NS_OBJ, this.#nsObj, handler);\n }\n\n once(event, handler) {\n return this.#relay.once(event, GLOBAL_NS_OBJ, this.#nsObj, handler);\n }\n\n // Me -> everyone (sender never hears itself)\n broadcast(event, ...payload) {\n this.#relay.publish(event, this.#nsObj, GLOBAL_NS_OBJ, payload);\n }\n\n // Specific source -> me\n from(fromNs) {\n return {\n subscribe: (event, handler) => this.#relay.subscribe(event, fromNs, this.#nsObj, handler),\n once: (event, handler) => this.#relay.once(event, fromNs, this.#nsObj, handler),\n };\n }\n\n // Me -> specific target\n to(toNs) {\n return {\n publish: (event, ...payload) => this.#relay.publish(event, this.#nsObj, toNs, payload),\n publishAsync: (event, ...payload) => this.#relay.publishAsync(event, this.#nsObj, toNs, payload),\n };\n }\n}\n\nexport class Relay {\n #channels = new WeakMap(); // nsObj -> Channel\n #events = new Map(); // eventName -> Set<Listener>\n #onError = null;\n\n static create(config = {}) {\n return new Relay(config);\n }\n\n constructor({ onError = null } = {}) {\n this.#onError = onError;\n this.createChannel(GLOBAL_NS_OBJ);\n }\n\n // Public convenience\n channel(nsObj) { return this.createChannel(nsObj); }\n createChannel(nsObj) {\n if (this.#channels.has(nsObj)) return this.#channels.get(nsObj);\n const ch = new Channel(nsObj, this);\n this.#channels.set(nsObj, ch);\n return ch;\n }\n\n // Internal helpers\n #listeners(event) {\n let set = this.#events.get(event);\n if (!set) { set = new Set(); this.#events.set(event, set); }\n return set;\n }\n\n // Wildcard matcher:\n // - If published `from` is GLOBAL, it matches every listener.from\n // - If listener.from is GLOBAL, it matches every published from\n // Same for `to`. This makes broadcast (to = GLOBAL) hit specific targets too.\n static #matchSide(published, constraint) {\n return published === GLOBAL_NS_OBJ || constraint === GLOBAL_NS_OBJ || published === constraint;\n }\n\n static #matches(publishedFrom, publishedTo, listenerFrom, listenerTo) {\n return Relay.#matchSide(publishedFrom, listenerFrom)\n && Relay.#matchSide(publishedTo, listenerTo);\n }\n\n subscribe(event, from, to, handler) {\n const listener = { from, to, handler };\n this.#listeners(event).add(listener);\n return () => {\n const set = this.#events.get(event);\n if (set) set.delete(listener);\n };\n }\n\n once(event, from, to, handler) {\n let off = null;\n const wrapped = (payload) => {\n try { handler(payload); } finally { off && off(); }\n };\n off = this.subscribe(event, from, to, wrapped);\n return off;\n }\n\n offAllFor(nsObj) {\n for (const set of this.#events.values()) {\n for (const l of Array.from(set)) {\n if (l.from === nsObj || l.to === nsObj) set.delete(l);\n }\n }\n }\n\n listenerCount(event) {\n const set = this.#events.get(event);\n return set ? set.size : 0;\n }\n\n #deliver(event, from, to, payload) {\n const set = this.#events.get(event);\n if (!set || set.size === 0) return;\n\n for (const l of set) {\n // Always skip self-delivery\n if (l.to === from) continue;\n\n if (Relay.#matches(from, to, l.from, l.to)) {\n try { l.handler(...payload); }\n catch (err) { if (this.#onError) this.#onError(err, { event, from, to, listener: l }); }\n }\n }\n }\n\n publish(event, from, to, payload) {\n this.#deliver(event, from, to, payload);\n }\n\n publishAsync(event, from, to, payload) {\n queueMicrotask(() => this.#deliver(event, from, to, payload));\n }\n\n broadcast(event, from, payload) {\n this.publish(event, from, GLOBAL_NS_OBJ, payload);\n }\n}\n", "/**\n * Type Checker Utility\n * \n * Supports syntax like:\n * - createDefinition('action', [Array, Function]) // Array or Function\n * - createDefinition('name', String) // Must be String\n * - createDefinition('items', Array) // Must be Array\n * - createDefinition('callback', Function) // Must be Function\n * - createDefinition('value', [String, Number]) // String or Number\n */\n\n/**\n * Type definitions mapping constructor names to actual constructors\n */\nconst TYPE_MAP = {\n String,\n Number,\n Boolean,\n Array,\n Object,\n Function,\n Date,\n RegExp,\n Promise,\n Map,\n Set,\n WeakMap,\n WeakSet,\n Symbol,\n BigInt,\n Error,\n TypeError,\n RangeError,\n ReferenceError,\n SyntaxError,\n EvalError,\n URIError\n};\n\n/**\n * Checks if a value matches the expected type(s)\n * @param {*} value - The value to check\n * @param {Function|Array<Function>} expectedType - Single type or array of possible types\n * @param {string} name - Name of the parameter for error messages\n * @returns {boolean} - True if value matches expected type(s)\n */\nexport function checkType(value, expectedType, name = 'value') {\n // Handle array of possible types\n if (Array.isArray(expectedType)) {\n for (const type of expectedType) {\n if (matchesType(value, type)) {\n return true;\n }\n }\n \n const typeNames = expectedType.map(getTypeName).join(' | ');\n throw new TypeError(`${name} must be one of: ${typeNames}. Got ${getTypeName(value)}`);\n }\n \n // Handle single type\n if (!matchesType(value, expectedType)) {\n throw new TypeError(`${name} must be ${getTypeName(expectedType)}. Got ${getTypeName(value)}`);\n }\n \n return true;\n}\n\n/**\n * Checks if a value matches a specific type\n * @param {*} value - The value to check\n * @param {Function} type - The expected constructor/type\n * @returns {boolean} - True if value matches the type\n */\nfunction matchesType(value, type) {\n // Handle primitive constructors\n if (type === String) {\n return typeof value === 'string';\n }\n if (type === Number) {\n return typeof value === 'number' && !isNaN(value);\n }\n if (type === Boolean) {\n return typeof value === 'boolean';\n }\n if (type === Symbol) {\n return typeof value === 'symbol';\n }\n if (type === BigInt) {\n return typeof value === 'bigint';\n }\n if (type === Function) {\n return typeof value === 'function';\n }\n \n // Handle object constructors (including Array, Object, Date, etc.)\n if (type === Array) {\n return Array.isArray(value);\n }\n if (type === Object) {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n }\n \n // Handle other constructors (Date, RegExp, Map, Set, etc.)\n return value instanceof type;\n}\n\n/**\n * Gets a human-readable name for a type\n * @param {*} value - The value or constructor to get name for\n * @returns {string} - Human-readable type name\n */\nfunction getTypeName(value) {\n if (value === String) return 'String';\n if (value === Number) return 'Number';\n if (value === Boolean) return 'Boolean';\n if (value === Array) return 'Array';\n if (value === Object) return 'Object';\n if (value === Function) return 'Function';\n if (value === Date) return 'Date';\n if (value === RegExp) return 'RegExp';\n if (value === Promise) return 'Promise';\n if (value === Map) return 'Map';\n if (value === Set) return 'Set';\n if (value === WeakMap) return 'WeakMap';\n if (value === WeakSet) return 'WeakSet';\n if (value === Symbol) return 'Symbol';\n if (value === BigInt) return 'BigInt';\n if (value === Error) return 'Error';\n \n if (typeof value === 'string') return 'string';\n if (typeof value === 'number') return 'number';\n if (typeof value === 'boolean') return 'boolean';\n if (typeof value === 'symbol') return 'symbol';\n if (typeof value === 'bigint') return 'bigint';\n if (typeof value === 'function') return 'function';\n if (Array.isArray(value)) return 'Array';\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'object') {\n return value.constructor?.name || 'Object';\n }\n \n return 'unknown';\n}\n\n/**\n * Creates a type checker function for a specific parameter\n * @param {Function|Array<Function>} expectedType - Expected type(s)\n * @param {string} name - Parameter name\n * @returns {Function} - Type checker function\n */\nexport function createTypeChecker(expectedType, name = 'value') {\n return (value) => checkType(value, expectedType, name);\n}\n\n/**\n * Validates an object against a schema\n * @param {Object} obj - Object to validate\n * @param {Object} schema - Schema definition { prop: Type, prop2: [Type1, Type2] }\n * @param {string} objName - Name of the object for error messages\n */\nexport function validateObject(obj, schema, objName = 'object') {\n if (!obj || typeof obj !== 'object') {\n throw new TypeError(`${objName} must be an object`);\n }\n \n for (const [prop, expectedType] of Object.entries(schema)) {\n if (prop in obj) {\n checkType(obj[prop], expectedType, `${objName}.${prop}`);\n }\n }\n}\n\n/**\n * Creates a validator function for an object schema\n * @param {Object} schema - Schema definition\n * @param {string} objName - Name of the object\n * @returns {Function} - Validator function\n */\nexport function createObjectValidator(schema, objName = 'object') {\n return (obj) => validateObject(obj, schema, objName);\n}\n\n// Export the type map for advanced usage\nexport { TYPE_MAP };\n", "const DefinitionTypes = new Map();\nconst Definitions = new WeakMap();\nimport { createTypeChecker } from '../utils/typeChecker.js';\n\n/**\n * Creates a definition type with return type validation\n * @param {string} type - The definition type name\n * @param {Function|Array<Function>} returnTypes - Expected return type(s)\n * @returns {Function} - Definition creator function\n */\n\n\nexport const definitionType = (definition) => {\n if (Definitions.has(definition)) {\n return Definitions.get(definition);\n }\n return undefined;\n}\n\nexport const createDefinition = (type, returnTypes = []) => { \n // Create type checker for return values if returnTypes specified\n const returnTypeChecker = returnTypes.length > 0 ? createTypeChecker(returnTypes, 'return value') : null;\n \n if (DefinitionTypes.has(type)) {\n console.warn(`Definition type \"${type}\" already exists`);\n return DefinitionTypes.get(type);\n }\n\n const definitionType = (name, factory, ...defaultArgs) => {\n // Validate inputs using type checker\n createTypeChecker(String, 'name')(name);\n createTypeChecker(Function, 'factory')(factory);\n\n const definition = (...args) => {\n try {\n const combinedArgs = [...args, ...defaultArgs];\n const res = factory(...combinedArgs);\n \n if (returnTypeChecker && res === undefined) {\n throw new Error(`Factory ${type} must return a value for ${name}`);\n }\n\n // Use type checker to validate return value\n if (returnTypeChecker) {\n returnTypeChecker(res);\n }\n\n return res\n } catch (error) {\n console.error(`Error creating definition \"${name}\"`, error);\n throw error;\n }\n }\n\n Object.defineProperty(definition, '_name', {\n value: name,\n enumerable: false,\n configurable: false\n });\n\n Definitions.set(definition, type);\n\n return definition;\n }\n\n DefinitionTypes.set(type, definitionType);\n\n return definitionType;\n}; ", "// utils/asserts.js\n\nconst BAD_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\nconst RESERVED_NAMESPACES = new Set(['use', 'install', 'uninstall', 'relay', 'state', 'debug']);\n\nconst MAX_NAME_LENGTH = 64;\nconst VALID_NAME = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;\n\n/**\n * Throw if key is unsafe (__proto__, constructor, etc.)\n */\nexport function assertSafeKey(key, where = 'key') {\n if (BAD_KEYS.has(key)) {\n throw new Error(`Illegal key \"${key}\" in ${where}`);\n }\n}\n\n/**\n * Validate a namespace string: format, length, reserved words, proto poisoning.\n */\nexport function assertNamespace(ns) {\n assertSafeKey(ns, 'namespace');\n if (typeof ns !== 'string') {\n throw new Error(`Namespace must be a string, got ${typeof ns}`);\n }\n if (!VALID_NAME.test(ns)) {\n throw new Error(`Invalid namespace \"${ns}\". Must be a valid JS identifier`);\n }\n if (ns.length > MAX_NAME_LENGTH) {\n throw new Error(`Namespace \"${ns}\" too long (max ${MAX_NAME_LENGTH} chars)`);\n }\n if (RESERVED_NAMESPACES.has(ns)) {\n throw new Error(`Namespace \"${ns}\" is reserved`);\n }\n return ns;\n}\n\n/**\n * Validate an action or getter name within a namespace.\n */\nexport function assertMemberName(name, namespace, kind = 'member') {\n assertSafeKey(name, `${kind}:${namespace}`);\n if (typeof name !== 'string') {\n throw new Error(`${kind} name in ${namespace} must be a string`);\n }\n if (!VALID_NAME.test(name)) {\n throw new Error(`Invalid ${kind} name \"${name}\" in ${namespace}`);\n }\n if (name.length > MAX_NAME_LENGTH) {\n throw new Error(\n `${kind} name \"${name}\" in ${namespace} too long (max ${MAX_NAME_LENGTH})`\n );\n }\n return name;\n}\n", "import { createDefinition, definitionType } from './createDefinition.js';\nexport const defineMiddleware = createDefinition('MIDDLEWARE', [Function, Array]);\nexport const defineActions = createDefinition('ACTIONS', [Object]);\nexport const defineUninstall = createDefinition('UNINSTALL');\nexport const defineInitialize = createDefinition('INITIALIZE');\nexport const defineGetters = createDefinition('GETTERS', [Object]);\nexport { createDefinition, definitionType };", "// DefinitionBuilder.js\nimport { defineActions, defineGetters, defineMiddleware, defineInitialize, defineUninstall } from './defaults.js';\n\nexport class DefinitionBuilder {\n static create(namespace) {\n return new DefinitionBuilder(namespace);\n }\n\n #ns; #args;\n #slots = { MIDDLEWARE:null, GETTERS:null, ACTIONS:null, INITIALIZE:null, UNINSTALL:null };\n constructor(namespace) { this.#ns = namespace }\n\n #set(type, factory, creator) {\n if (this.#slots[type]) throw new Error(`${type} already defined for ${this.#ns}`);\n this.#slots[type] = creator(this.#ns, factory);\n }\n\n defineMiddleware = (factory) => this.#set('MIDDLEWARE', factory, defineMiddleware);\n defineGetters = (factory) => this.#set('GETTERS', factory, defineGetters);\n defineActions = (factory) => this.#set('ACTIONS', factory, defineActions);\n defineInitialize = (factory) => this.#set('INITIALIZE', factory, defineInitialize);\n defineUninstall = (factory) => this.#set('UNINSTALL', factory, defineUninstall);\n\n _toArray() {\n return [\n this.#slots.MIDDLEWARE,\n this.#slots.GETTERS,\n this.#slots.ACTIONS,\n this.#slots.INITIALIZE,\n this.#slots.UNINSTALL\n ].filter(Boolean);\n }\n}\n\n", "import { assertNamespace } from './utils/asserts.js';\nimport { DefinitionBuilder } from './definitions/DefinitionBuilder.js';\n\n\nexport class ServiceProvider {\n static #services = new Set();\n\n static manifest = {\n name: 'base',\n dependencies: [],\n version: '1.0.0',\n description: 'Base extension template',\n };\n\n static config = null;\n\n static unique = false;\n\n static configure(options = {}) {\n return {\n install: (useContext, config) => this.install(useContext, config),\n manifest: this.manifest,\n config: { ...(this.config || this.manifest.defaults || {}), ...options },\n unique: true,\n configured: true\n };\n }\n\n static install(useContext, config) { \n try {\n const {namespace} = this.manifest;\n assertNamespace(namespace);\n\n // instantiate\n const instance = new this();\n ServiceProvider.#services.add(instance);\n\n // bind context/config\n // bind config (frozen to avoid accidental mutation)\n Object.defineProperty(instance, 'config', {\n value: Object.freeze({ ...config }),\n writable: false,\n configurable: false,\n enumerable: false,\n });\n\n // expose both a live context getter AND the keyed accessor\n Object.defineProperty(instance, 'context', {\n get: () => useContext(), // always fresh, via your proxy\n configurable: false,\n enumerable: false,\n });\n \n Object.defineProperty(instance, 'useContext', {\n value: (...keys) => useContext(...keys),\n writable: false,\n configurable: false,\n enumerable: false,\n });\n\n const builder = DefinitionBuilder.create(namespace);\n\n if (instance.setup) {\n // Create properly bound context for setup pattern\n const setupContext = {\n defineActions: (factory) => builder.defineActions(() => factory(useContext, config)),\n defineMiddleware: (factory) => builder.defineMiddleware(() => factory(useContext, config)),\n defineGetters: (factory) => builder.defineGetters(() => factory(useContext, config)),\n defineInitialize: (factory) => builder.defineInitialize(() => factory(useContext, config)),\n defineUninstall: (factory) => builder.defineUninstall(() => factory(useContext, config))\n };\n const maybe = instance.setup(setupContext);\n return maybe?.then ? maybe.then(() => builder._toArray()) : builder._toArray();\n }\n\n if (instance.middleware) builder.defineMiddleware(() => instance.middleware(useContext, config));\n if (instance.getters) builder.defineGetters (() => instance.getters(useContext, config));\n if (instance.actions) builder.defineActions (() => instance.actions(useContext, config));\n if (instance.initialize) builder.defineInitialize(() => instance.initialize(useContext, config));\n if (instance.uninstall) builder.defineUninstall (() => instance.uninstall(useContext, config));\n\n return builder._toArray();\n } catch (error) {\n throw error;\n }\n }\n}", "const ENGINE_CONTEXT = Symbol('jucie.engine');\n\n/**\n * Registers the engine globally, but only if no engine has already been set.\n * @param {object} engine \n */\n\nexport function provideEngine(engine) {\n if (!globalThis[ENGINE_CONTEXT]) {\n globalThis[ENGINE_CONTEXT] = engine;\n }\n}\n\nexport function hasEngine() {\n return globalThis[ENGINE_CONTEXT] !== undefined;\n}\n\n/**\n * Forcefully override the engine in the global context.\n * Useful for testing or resetting.\n */\nexport function forceEngine(engine) {\n globalThis[ENGINE_CONTEXT] = engine;\n}\n\n/**\n * Retrieves the globally registered engine.\n */\nexport function getEngine() {\n return globalThis[ENGINE_CONTEXT] || null;\n}\n\n/**\n * Retrieves the globally registered engine.\n */\nexport function useEngine() {\n return getEngine();\n}", "export const ContextTypes = {\n '2D': '2d',\n 'WEBGL': 'webgl',\n 'WEBGL2': 'webgl2',\n 'BITMAPRENDERER': 'bitmaprenderer'\n};", "export function nextIdleTick(callback) {\n if (typeof window !== 'undefined' && window.requestIdleCallback) {\n return window.requestIdleCallback(callback, { timeout: 100 });\n }\n\n // Fallback for browsers without requestIdleCallback (Safari/WebKit)\n if (typeof window !== 'undefined') {\n // Use requestAnimationFrame + setTimeout for better idle approximation\n if (window.requestAnimationFrame) {\n return window.requestAnimationFrame(() => {\n setTimeout(callback, 0);\n });\n }\n // Final fallback to setTimeout\n return setTimeout(callback, 0);\n }\n\n // Server-side or no window object - execute immediately\n if (typeof callback === 'function') {\n callback();\n }\n return null;\n}\n", "import { nextIdleTick } from './utils/nextIdleTick.js';\n\nexport class ComputationManager {\n constructor() {\n this.roots = new Map();\n this.pending = new Set();\n this.onCompleteCallbacks = new Set();\n this.onNextIdle = new Set();\n this.idleScheduled = false;\n }\n\n markAsDirty(reactive) {\n if (!reactive.isDirty) {\n reactive.isDirty = true;\n \n if (reactive.isAsync || reactive.immediate || (reactive.effects && reactive.effects.size > 0)) {\n this.scheduleRecomputation(reactive);\n } else {\n this.onNextIdle.add(reactive);\n\n if (!this.idleScheduled) {\n this.idleScheduled = true;\n nextIdleTick(() => {\n for (const reactive of this.onNextIdle) {\n this.pending.add(reactive);\n }\n this.flush(null);\n this.onNextIdle.clear();\n this.idleScheduled = false; // \u2190 Reset flag\n });\n }\n }\n if (reactive.dependants && reactive.dependants.size > 0) {\n // Process WeakRefs and rebuild ID set with only alive IDs\n const deadRefs = [];\n const ids = new Set();\n reactive.dependants.forEach(weakRef => {\n const dependant = weakRef.deref();\n if (dependant) {\n this.markAsDirty(dependant);\n ids.add(dependant._id);\n } else {\n deadRefs.push(weakRef);\n }\n });\n // Clean up dead WeakRefs and sync IDs\n deadRefs.forEach(ref => reactive.dependants.delete(ref));\n reactive.dependantIds = ids;\n }\n }\n }\n\n scheduleRecomputation(reactive) {\n if (!reactive.debounce) {\n return this.recompute(reactive);\n }\n\n // Check if we can recompute (either first time or cooldown expired)\n const now = Date.now();\n const timeElapsed = reactive._lastComputeTime ? now - reactive._lastComputeTime : Infinity;\n const canRecompute = !reactive._hasPendingDebounce || timeElapsed >= reactive.debounce;\n\n if (canRecompute) {\n // Clear any existing timer and set up new cooldown period\n clearTimeout(reactive._debounceTimer);\n reactive._hasPendingDebounce = true;\n reactive._lastComputeTime = now;\n \n reactive._debounceTimer = setTimeout(() => {\n reactive._hasPendingDebounce = false;\n reactive._debounceTimer = null;\n }, reactive.debounce);\n \n return this.recompute(reactive);\n }\n\n // Still in cooldown period, return cached value\n return reactive.cachedValue;\n }\n\n removeReactive(reactive) {\n this.pending.delete(reactive);\n this.onNextIdle.delete(reactive);\n }\n\n recompute(reactive) {\n this.pending.add(reactive);\n return this.flush(reactive);\n }\n\n flush(reactive) {\n const reactives = Array.from(this.pending);\n this.pending.clear();\n\n // Sort by dependencies\n const sortedReactives = this.sortByDependencies(reactives);\n \n // Process in reverse order (dependencies first)\n for (const reactive of sortedReactives) {\n this.onNextIdle.delete(reactive);\n reactive.compute()\n }\n\n // Notify completion callbacks\n for (const callback of this.onCompleteCallbacks) {\n try {\n callback();\n } catch (error) {\n console.error('Error in batch completion callback:', error);\n }\n }\n\n // If we have a target ID, ensure it's computed and return its value\n if (reactive) {\n // Make sure the target computed is evaluated if it wasn't in the batch\n if (!sortedReactives.includes(reactive)) {\n reactive.compute();\n }\n return reactive.cachedValue;\n }\n \n return undefined;\n }\n\n sortByDependencies(reactives) {\n const sorted = [];\n const visited = new Set();\n const visiting = new Set();\n\n const visit = (reactive) => {\n if (visiting.has(reactive)) return;\n if (visited.has(reactive)) return;\n\n visiting.add(reactive);\n\n // Get dependant computed values (handle WeakRefs)\n const dependants = reactive.dependants;\n if (dependants && dependants.size > 0) {\n dependants.forEach(weakRef => {\n const dependant = weakRef.deref();\n if (dependant && reactives.includes(dependant)) {\n visit(dependant); // Visit dependants first\n }\n });\n }\n\n visiting.delete(reactive);\n visited.add(reactive);\n sorted.unshift(reactive); // Add to start of array instead of end\n };\n\n // Process all nodes\n for (const reactive of reactives) {\n if (!visited.has(reactive)) {\n visit(reactive);\n }\n }\n\n return sorted;\n }\n}", "import { ComputationManager } from './ComputationManager.js';\n\nexport class Reactive {\n static computationManager = new ComputationManager();\n static awaitingRecomputation = new Set();\n static reactives = new WeakMap();\n static currentlyComputing = null;\n static computationStack = [];\n static currentDepth = 0;\n static effectsCache = new Set();\n static processingEffects = false;\n static _nextId = 1; // Counter for unique reactive IDs\n static config = {\n maxDepth: 2000,\n }\n static ctx = {};\n \n static nextId() {\n return Reactive._nextId++;\n }\n\n static addContext(key, value) {\n if (!key || typeof key !== 'string') {\n throw new Error('Invalid context key');\n }\n \n if (typeof value === 'undefined') {\n throw new Error('Invalid context value');\n }\n \n if (key in Reactive.ctx) {\n throw new Error('Context key already exists');\n }\n \n Reactive.ctx[key] = value;\n }\n\n static useContext(keys) { \n if (!keys || keys.length === 0) return Reactive.ctx;\n if (keys.length === 1) return Reactive.ctx[keys[0]];\n\n const out = new Array(keys.length);\n for (let i = 0; i < keys.length; i++) {\n out[i] = Reactive.ctx[keys[i]];\n }\n return out;\n }\n\n static hasContext(keys) {\n if (!keys || keys.length === 0) return Object.keys(Reactive.ctx).length > 0;\n if (keys.length === 1) return keys[0] in Reactive.ctx;\n for (const key of keys) {\n if (!(key in Reactive.ctx)) return false;\n }\n return true;\n }\n\n static clearContext() {\n Reactive.ctx = {};\n }\n\n static begin(reactive) {\n if (Reactive.awaitingRecomputation.has(reactive)) {\n Reactive.awaitingRecomputation.delete(reactive);\n }\n\n const reactorIndex = Reactive.computationStack.indexOf(reactive);\n\n if (reactorIndex !== -1) {\n if (reactive.isAsync) {\n Reactive.computationStack.splice(reactorIndex, 1);\n Reactive.computationStack.push(reactive);\n Reactive.currentlyComputing = reactive;\n return;\n } \n const cycle = Reactive.computationStack.slice(reactorIndex).concat(reactive);\n const error = new Error(`Circular dependency detected: ${cycle.map(r => r).join(' -> ')}`);\n error.name = 'CircularDependencyError';\n error.displayed = false;\n throw error;\n }\n \n if (Reactive.currentDepth >= Reactive.config.maxDepth) {\n throw new Error(`Maximum reactive depth of ${Reactive.config.maxDepth} exceeded`);\n }\n \n Reactive.computationStack.push(reactive);\n Reactive.currentlyComputing = reactive;\n Reactive.currentDepth++;\n }\n \n static end(reactive) {\n if (reactive.isAsync) {\n Reactive.computationStack.splice(Reactive.computationStack.indexOf(reactive), 1);\n Reactive.currentlyComputing = Reactive.computationStack[Reactive.computationStack.length - 1] || null;\n Reactive.currentDepth--;\n return;\n }\n Reactive.computationStack.pop();\n Reactive.currentlyComputing = Reactive.computationStack[Reactive.computationStack.length - 1] || null;\n Reactive.currentDepth--;\n }\n\n static addEffect(getter, effect) {\n const reactive = Reactive.reactives.get(getter);\n \n // Compute if needed and notify with current value\n if (reactive.isDirty) {\n Reactive.computationManager.scheduleRecomputation(reactive);\n }\n \n if (!reactive.effects) {\n reactive.effects = new Set();\n }\n \n // Store the WeakRef instead of the raw effect\n reactive.effects.add(effect);\n \n // Return unsubscribe function\n return () => Reactive.removeEffect(getter, effect);\n }\n\n static removeEffect(getter, effect) {\n const reactive = Reactive.reactives.get(getter);\n if (reactive.effects) {\n reactive.effects.delete(effect);\n }\n }\n\n static recompute(reactive) {\n if (!Reactive.awaitingRecomputation.has(reactive)) {\n Reactive.awaitingRecomputation.add(reactive);\n }\n\n \n return Reactive.computationManager.scheduleRecomputation(reactive);\n }\n\n static callEffects(reactive) { \n Reactive.effectsCache.add(reactive);\n \n // Use a single setTimeout for batching\n if (!Reactive.processingEffects) {\n Reactive.processingEffects = true;\n setTimeout(() => {\n Reactive.processEffectsCache();\n Reactive.processingEffects = false;\n }, 0);\n }\n }\n\n static processEffectsCache() {\n const reactives = new Set(Reactive.effectsCache);\n Reactive.effectsCache.clear();\n \n for (const reactive of reactives) {\n try {\n // Process effects using WeakRefs\n const effects = reactive.effects || new Set();\n effects.forEach(effect => {\n if (effect) {\n effect(reactive.cachedValue);\n }\n });\n } catch (error) {\n console.error(`Error in reactive ${reactive._id} effect:`, error);\n }\n }\n \n // If new effects were added during processing, schedule another batch\n if (Reactive.effectsCache.size > 0) {\n setTimeout(() => {\n Reactive.processEffectsCache();\n }, 0);\n }\n }\n\n static markAsDirty(reactive) {\n if (!reactive.isDirty) {\n reactive.isDirty = true;\n \n if (reactive.immediate || (reactive.effects && reactive.effects.size > 0)) {\n Reactive.computationManager.scheduleRecomputation(reactive);\n }\n \n // Process WeakRefs and clean up dead ones\n const deadRefs = [];\n const ids = new Set();\n reactive.dependants.forEach(weakRef => {\n const dependant = weakRef.deref();\n if (dependant) {\n Reactive.markAsDirty(dependant);\n ids.add(dependant._id);\n } else {\n deadRefs.push(weakRef);\n }\n });\n // Clean up dead WeakRefs and sync IDs\n deadRefs.forEach(ref => reactive.dependants.delete(ref));\n reactive.dependantIds = ids;\n }\n }\n\n static destroy(getter) {\n const reactive = Reactive.reactives.get(getter);\n Reactive.computationManager.removeReactive(reactive);\n Reactive.reactives.delete(getter);\n }\n}\n\nexport const markAsDirty = (reactive) => {\n if (isReactive(reactive)) {\n const reactiveInstance = Reactive.reactives.get(reactive);\n if (reactiveInstance) {\n return Reactive.markAsDirty(reactiveInstance);\n }\n }\n}\n\nexport const isReactive = (getter) => {\n return Reactive.reactives.has(getter);\n}\n\nexport const addEffect = (getter, effect) => {\n if (!isReactive(getter)) {\n throw new Error('Invalid effect getter');\n \n }\n\n if (!effect || typeof effect !== 'function') {\n throw new Error('Invalid effect function');\n }\n\n return Reactive.addEffect(getter, effect);\n}\n\nexport const removeEffect = (getter, effect) => {\n if (isReactive(getter)) {\n return Reactive.removeEffect(getter, effect);\n }\n}\n\nexport const destroyReactive = (getter) => {\n if (isReactive(getter)) {\n return Reactive.destroy(getter);\n }\n}\n\nexport const addContext = (key, value) => Reactive.addContext(key, value)\n\nexport const useContext = (...keys) => {\n if (keys.length === 0) return Reactive.ctx;\n if (keys.length === 1) return Reactive.ctx[keys[0]];\n return keys.map(key => Reactive.ctx[key]);\n}\n\nexport const hasContext = (...keys) => Reactive.hasContext(keys)\n\nexport const createAdapter = (getter, path = []) => {\n if (!isReactive(getter)) {\n throw new Error('Invalid adapter getter');\n }\n\n let snapshotCache = undefined;\n let unsubscribeAll = null;\n const subscribers = new Set();\n\n const getSnapshot = () => {\n if (snapshotCache !== undefined) {\n return snapshotCache;\n }\n\n const value = path && path.length > 0 ? traverse(getter(), path) : getter();\n\n if (Array.isArray(value)) {\n snapshotCache = value.slice();\n } else if (typeof value === 'object' && value !== null) {\n const clone = Object.create(Object.getPrototypeOf(value));\n Object.defineProperties(clone, Object.getOwnPropertyDescriptors(value));\n snapshotCache = Object.freeze(clone);\n } else {\n snapshotCache = value;\n }\n \n return snapshotCache;\n };\n\n const subscribe = (listener) => {\n if (!unsubscribeAll) {\n unsubscribeAll = addEffect(getter, () => {\n snapshotCache = undefined;\n for (const subscriber of subscribers) {\n subscriber(getSnapshot);\n }\n });\n }\n \n subscribers.add(listener);\n return () => {\n subscribers.delete(listener);\n if (subscribers.size === 0) {\n unsubscribeAll();\n unsubscribeAll = null;\n }\n };\n };\n\n return [getSnapshot, subscribe];\n}", "export const isAsyncFunction = fn =>\n typeof fn === 'function' &&\n (fn.constructor.name === 'AsyncFunction' ||\n fn.constructor.name === 'AsyncGeneratorFunction');\n", "import { Reactive } from './Reactive.js';\nimport { isAsyncFunction } from './utils/isAsync.js';\n\nexport class Computed {\n static create(fn, config = {}) {\n const computed = new Computed(fn, config);\n Reactive.reactives.set(computed.getter, computed);\n return computed.getter;\n }\n\n constructor(fn, config = {}) {\n this.fn = fn;\n this.isAsync = isAsyncFunction(fn);\n this.pendingResolve = undefined;\n this.roots = new Set();\n this.dependants = new Set();\n this.dependantIds = new Set();\n this.effects = new Set(Array.isArray(config.effects) ? config.effects : []);\n this.cachedValue = config.initialValue || undefined;\n this.isDirty = true;\n this.debounce = config.debounce || 0;\n this.onAccess = config.onAccess || undefined;\n this.detatched = config.detatched || false;\n this.immediate = config.immediate || false;\n this.context = config.context || undefined;\n this.useContext = () => this.context ? this.context : Reactive.hasContext() ? Reactive.useContext() : undefined;\n this.resolvers = [];\n this.rejectors = [];\n this._id = Reactive.nextId();\n this._lastComputeTime = undefined;\n this._hasPendingDebounce = false;\n this._debounceTimer = undefined;\n this._computationId = 0; // Track computation version\n this.getter = this.#getter.bind(this);\n \n\n if (this.immediate) {\n this.compute();\n }\n }\n\n compute() {\n Reactive.begin(this);\n try { \n if (!this.isAsync) {\n this.cachedValue = this.fn(this.useContext(), this.cachedValue);\n this.isDirty = false;\n return this.cachedValue;\n }\n\n // Track this specific computation\n this._computationId = (this._computationId || 0) + 1;\n const computationId = this._computationId;\n\n this.pendingResolve = this.fn(this.useContext(), this.cachedValue);\n this.pendingResolve.then(value => {\n // Only update if this is still the latest computation\n if (this._computationId === computationId) {\n this.resolvers.forEach(resolve => resolve(value));\n this.resolvers = [];\n this.cachedValue = value;\n this.isDirty = false;\n }\n return value;\n }).catch(error => {\n if (this._computationId === computationId) {\n this.rejectors.forEach(reject => reject(error));\n this.rejectors = [];\n }\n }).finally(() => {\n this.pendingResolve = null; // Always clear pending promise\n // Only call end/effects if this is still the latest computation\n if (this._computationId === computationId) {\n Reactive.end(this);\n Reactive.callEffects(this);\n }\n });\n\n this.cachedValue = new Promise((resolve, reject) => {\n this.resolvers.push(resolve);\n this.rejectors.push(reject);\n });\n \n return this.cachedValue;\n } finally {\n if (!this.isAsync) {\n Reactive.end(this);\n Reactive.callEffects(this);\n }\n }\n }\n\n #getter() {\n try {\n if (!this.detatched && Reactive.currentlyComputing && Reactive.currentlyComputing !== this && !this.dependantIds.has(Reactive.currentlyComputing._id)) {\n this.dependantIds.add(Reactive.currentlyComputing._id);\n this.dependants.add(new WeakRef(Reactive.currentlyComputing));\n }\n \n if (!this.isDirty) {\n if (this.isAsync) {\n return Promise.resolve(this.cachedValue);\n }\n\n return this.cachedValue;\n }\n\n // If dirty, always start new computation (even if previous pending)\n return Reactive.recompute(this);\n } catch (error) {\n throw error;\n } finally {\n if (this.onAccess) {\n this.onAccess(this.cachedValue);\n }\n }\n }\n}\n\nexport const createComputed = (fn, config = {}) => Computed.create(fn, config);\n\nexport const destroyComputed = (target) => {\n if (isComputed(target)) {\n Reactive.destroy(target);\n }\n}\n\nexport const isComputed = (getter) => {\n const computed = Reactive.reactives.get(getter);\n if (!computed) {\n return false;\n }\n\n return computed instanceof Computed;\n}\n\nexport const isDirtyComputed = (getter) => {\n const computed = Reactive.reactives.get(getter);\n if (!computed) {\n return false;\n }\n\n return computed.isDirty;\n}\n", "import { Reactive } from './Reactive.js';\n\nexport class Signal {\n static create(initialValue, config = {}) {\n const signal = new Signal(initialValue, config);\n Reactive.reactives.set(signal.getter, signal);\n return signal.getter;\n }\n\n constructor(initialValue, config = {}) {\n this._id = Reactive.nextId();\n this.isAsync = false;\n this.cachedValue = undefined;\n this.dependants = new Set();\n this.dependantIds = new Set();\n this.roots = new Set();\n this.effects = new Set(Array.isArray(config.effects) ? config.effects : []);\n this.isDirty = true;\n this.debounce = config.debounce || 0;\n this.onAccess = config.onAccess || null;\n this.detatched = config.detatched || false;\n this.immediate = config.immediate || false;\n this._pendingChange = initialValue;\n this._lastComputeTime = null;\n this._hasPendingDebounce = false;\n this._debounceTimer = null;\n this.getter = (...args) => this.#getter(...args);\n }\n\n compute() {\n Reactive.begin(this);\n try {\n this.cachedValue = this._pendingChange;\n this._pendingChange = undefined;\n this.isDirty = false;\n return this.cachedValue;\n } finally {\n Reactive.end(this);\n Reactive.callEffects(this);\n }\n }\n\n #getter(...args) {\n try {\n if (!this.detatched && Reactive.currentlyComputing && Reactive.currentlyComputing !== this && !this.dependantIds.has(Reactive.currentlyComputing._id)) {\n this.dependantIds.add(Reactive.currentlyComputing._id);\n this.dependants.add(new WeakRef(Reactive.currentlyComputing));\n }\n\n if (args.length > 0) {\n const signal = args[0];\n this._pendingChange = typeof signal === 'function' ? signal(this.cachedValue) : signal;\n Reactive.markAsDirty(this);\n return;\n }\n\n if (this.isDirty) {\n return Reactive.recompute(this);\n }\n\n return this.cachedValue;\n \n } catch (error) {\n throw error;\n } finally {\n if (this.onAccess) {\n this.onAccess(this.cachedValue);\n }\n }\n }\n}\n\nexport const createSignal = (initialValue, config = {}) => Signal.create(initialValue, config);\n\nexport const destroySignal = (getter) => {\n if (isSignal(getter)) {\n Reactive.destroy(getter);\n }\n}\n\nexport const isSignal = (getter) => {\n const signal = Reactive.reactives.get(getter);\n if (!signal) {\n return false;\n }\n\n return signal instanceof Signal;\n}\n\nexport const isDirtySignal = (getter) => {\n const signal = Reactive.reactives.get(getter);\n if (!signal) {\n return false;\n }\n\n return signal.isDirty;\n}", "const traversalFunctions = [\n null, // index 0 (unused)\n null, // index 1 (single property access doesn't need optimization)\n (obj, path) => obj?.[path[0]]?.[path[1]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]]?.[path[5]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]]?.[path[5]]?.[path[6]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]]?.[path[5]]?.[path[6]]?.[path[7]]\n]\n\nfunction createTraversalFunction(length) {\n const accessors = Array.from({ length }, (_, i) => `?.[path[${i}]]`);\n const expr = \"obj\" + accessors.join(\"\");\n const fn = new Function(\"obj\", \"path\", `return ${expr}`);\n traversalFunctions[length] = fn;\n return fn;\n}\n\nexport function traverse(state, path) {\n const len = path.length;\n if (len === 0) return state;\n if (len === 1) return state[path[0]];\n \n // Use existing function if available\n if (len < traversalFunctions.length && traversalFunctions[len]) {\n return traversalFunctions[len](state, path);\n }\n \n // Create and cache new function if needed\n if (!traversalFunctions[len]) {\n return createTraversalFunction(len)(state, path);\n }\n \n return traversalFunctions[len](state, path);\n}\n", "// Surface.js\nimport { createComputed, destroyComputed } from './Computed.js';\nimport { addEffect } from './Reactive.js';\nimport { createSignal } from './Signal.js';\nimport { traverse } from './lib/traverse.js';\n\nconst EMPTY_CACHE = Symbol();\n\nexport class Surface {\n static surfaces = new WeakMap();\n static plugins = new Map();\n\n static registerPlugin(name, plugin) {\n if (Surface.plugins.has(name)) {\n throw new Error(`Plugin \"${name}\" already registered`);\n }\n Surface.plugins.set(name, plugin());\n }\n\n static resetPlugins() {\n Surface.plugins.clear();\n }\n\n static create(setupFn, options = {}) {\n const instance = new Surface(options);\n const useSurface = instance.setup(setupFn);\n Surface.surfaces.set(useSurface, instance);\n return useSurface;\n }\n\n static createPlugin(name, fn, options = {}) {\n const plugin = Surface.create(fn, options);\n Surface.registerPlugin(name, plugin);\n return plugin;\n }\n\n constructor(options = {}) {\n this.options = options;\n this.setupFn = null;\n this.subscribers = new Set();\n this.subscribersQueued = false;\n this.destroyCallback = null;\n\n // Values, computeds, actions, and extensions that are pending to be bound to the surface\n this.values = new Set();\n this.computeds = new Set();\n this.actions = new Set();\n this.extensions = new Set();\n\n this.snapshotCache = EMPTY_CACHE;\n this.surface = this.#createSurface();\n this.useSurface = () => this.surface;\n }\n\n setup(setupFn) {\n if (!setupFn) {\n return null;\n }\n\n this.setupFn = setupFn;\n this.reset();\n\n const pendingReactives = new Set();\n\n try {\n let result;\n \n if (typeof setupFn === 'function') {\n result = this.#setupFromFunction(setupFn, pendingReactives);\n } else if (typeof setupFn === 'object' && setupFn !== null) {\n result = this.#setupFromObject(setupFn, pendingReactives);\n } else {\n throw new Error('setupFn must be a function or object configuration');\n }\n \n this.#bindSurface(result);\n pendingReactives.forEach(reactive => addEffect(reactive, () => this.#queueSubscribers()));\n this.#queueSubscribers(); \n return this.useSurface;\n } catch (error) {\n console.error('Error in setup function', error);\n throw error;\n }\n }\n\n reset() {\n this.subscribers.clear();\n this.subscribersQueued = false;\n this.values.clear();\n this.computeds.clear();\n this.actions.clear();\n this.extensions.clear();\n this.snapshotCache = EMPTY_CACHE;\n this.surface = this.#createSurface();\n }\n\n createValue(initial = undefined, cb) {\n const signal = createSignal(initial);\n const value = Object.create(null);\n Object.defineProperty(value, 'value', {\n get: () => signal(),\n set: (newValue) => signal(newValue),\n enumerable: true,\n });\n this.values.add(value);\n cb?.(signal);\n return value;\n }\n\n createComputed(fn, cb) {\n const computed = createComputed(fn, { context: this.surface });\n const computedValue = Object.create(null);\n Object.defineProperty(computedValue, 'value', {\n get: () => computed(),\n enumerable: true,\n });\n this.computeds.add(computedValue);\n cb?.(computed);\n return computedValue;\n }\n\n createAction(fn) {\n const action = fn.bind(this.surface, this.surface)\n this.actions.add(action);\n return action;\n }\n\n extend(useSurface) {\n \n if (!useSurface) throw new Error('No source surface provided');\n \n if (!isSurface(useSurface)) {\n throw new Error('Cannot extend non-surface');\n }\n const surface = useSurface();\n this.extensions.add(surface);\n return surface;\n }\n\n #setupFromFunction(setupFn, pendingReactives) {\n return setupFn({\n value: (initial = undefined) => this.createValue(initial, (signal) => pendingReactives.add(signal)),\n computed: (fn = () => {}) => this.createComputed(fn, (reactor) => pendingReactives.add(reactor)),\n action: (fn = () => {}) => this.createAction(fn),\n extend: (useSurface) => this.extend(useSurface),\n destroy: () => this.#destroy(),\n ...Object.fromEntries(Surface.plugins.entries())\n }) || {};\n }\n\n #processStateValue(stateConfig, isDev, key) {\n // Support shorthand: state: { count: 0 } instead of { count: { default: 0 } }\n if (typeof stateConfig !== 'object' || stateConfig === null) {\n return typeof stateConfig === 'function' ? stateConfig() : stateConfig;\n }\n \n // If it's an object but doesn't have 'default', treat as shorthand\n if (!('default' in stateConfig)) {\n // Validate state config in dev mode\n if (isDev && 'dummy' in stateConfig) {\n console.warn(`State \"${key}\" has dummy value but no default value`);\n }\n return typeof stateConfig === 'function' ? stateConfig() : stateConfig;\n }\n \n // Full config with default/dummy\n let value = isDev && 'dummy' in stateConfig ? stateConfig.dummy : stateConfig.default;\n return typeof value === 'function' ? value() : value;\n }\n\n #setupFromObject(config, pendingReactives) {\n const result = {};\n const isDev = this.options.mode === 'development' || this.options.mode === 'dev';\n\n // 1. Process extend array first (so extended properties are available)\n if (config.extend && Array.isArray(config.extend)) {\n for (const useSurface of config.extend) {\n this.extend(useSurface);\n }\n }\n\n // 2. Process plugins (if specified) - handled in #bindSurface via Surface.plugins\n // Note: Plugins are automatically added to all surfaces, so we don't need to add them to result\n // If you want selective plugin inclusion, you'd need to modify #bindSurface\n\n // 3. Process state definitions\n if (config.state && typeof config.state === 'object') {\n for (const [key, stateConfig] of Object.entries(config.state)) {\n const initialValue = this.#processStateValue(stateConfig, isDev, key);\n result[key] = this.createValue(initialValue, (signal) => pendingReactives.add(signal));\n }\n }\n\n // 4. Process computed properties\n if (config.computed && typeof config.computed === 'object') {\n for (const [key, fn] of Object.entries(config.computed)) {\n if (typeof fn === 'function') {\n result[key] = this.createComputed(fn, (reactor) => pendingReactives.add(reactor));\n }\n }\n }\n\n // 5. Process actions\n if (config.actions && typeof config.actions === 'object') {\n for (const [key, fn] of Object.entries(config.actions)) {\n if (typeof fn === 'function') {\n result[key] = this.createAction(fn);\n }\n }\n }\n\n // 6. Handle lifecycle hooks\n if (config.onInit && typeof config.onInit === 'function') {\n // Execute after setup is complete\n Promise.resolve().then(() => {\n try {\n config.onInit(this.surface);\n } catch (error) {\n console.error('Error in onInit callback', error);\n }\n });\n }\n\n if (config.onDestroy && typeof config.onDestroy === 'function') {\n // Store for later execution\n this.destroyCallback = config.onDestroy;\n }\n\n return result;\n }\n\n #createAdapter () { \n return [() => this.#getSnapshot(), (subscriber) => this.#subscribe(subscriber)];\n }\n\n #getSnapshot() {\n if (this.snapshotCache !== EMPTY_CACHE) {\n return this.snapshotCache;\n }\n\n const clone = Object.create(Object.getPrototypeOf(this.surface));\n Object.defineProperties(clone, Object.getOwnPropertyDescriptors(this.surface));\n this.snapshotCache = Object.freeze(clone);\n \n return this.snapshotCache;\n };\n\n #subscribe(listener) {\n this.subscribers.add(listener);\n return () => this.subscribers.delete(listener);\n }\n\n #callSubscribers(snapshot) {\n for (const subscriber of this.subscribers) {\n subscriber(snapshot);\n }\n }\n\n #queueSubscribers() {\n if (this.subscribers.size === 0 || this.subscribersQueued) return;\n this.subscribersQueued = true;\n Promise.resolve().then(() => {\n this.subscribersQueued = false;\n this.snapshotCache = EMPTY_CACHE;\n this.#callSubscribers(this.#getSnapshot());\n });\n }\n\n #createSurface(surface = Object.create(null)) {\n Object.defineProperty(surface, '$get', {\n value: (path) => this.#get(path),\n writable: false,\n enumerable: false,\n configurable: false\n });\n \n Object.defineProperty(surface, '$set', {\n value: (path, newValue) => this.#set(path, newValue),\n writable: false,\n enumerable: false,\n configurable: false\n });\n \n Object.defineProperty(surface, '$dispatch', {\n value: (name) => this.#dispatch(name),\n writable: false,\n enumerable: false,\n configurable: false\n });\n \n Object.defineProperty(surface, '$inject', {\n value: (overrides) => Object.assign({}, this.surface, overrides),\n writable: false,\n enumerable: false,\n configurable: false\n });\n\n Object.defineProperty(surface, '$snapshot', {\n value: () => this.#getSnapshot(),\n writable: false,\n enumerable: false,\n configurable: false\n });\n\n Object.defineProperty(surface, '$subscribe', {\n value: (listener) => this.#subscribe(listener),\n writable: false,\n enumerable: false,\n configurable: false\n });\n \n Object.defineProperty(surface, '$adapter', {\n value: () => this.#createAdapter(),\n writable: false,\n enumerable: false,\n configurable: false\n });\n\n Object.defineProperty(surface, '$destroy', {\n value: () => this.#destroy(),\n writable: false,\n enumerable: false,\n configurable: false\n });\n return surface;\n }\n\n #destroy() {\n // Call onDestroy callback if defined\n if (this.destroyCallback && typeof this.destroyCallback === 'function') {\n try {\n this.destroyCallback(this.surface);\n } catch (error) {\n console.error('Error in onDestroy callback', error);\n }\n }\n \n const surfaceComputed = this.surfaceComputed;\n this.surfaceComputed = null;\n Surface.surfaces.delete(surfaceComputed);\n destroyComputed(surfaceComputed);\n }\n\n #get(path = []) {\n return traverse(this.surface, path);\n }\n\n #set(name, newValue) {\n const value = this.values?.get?.(name);\n value.value = newValue;\n return this.surface;\n }\n\n #dispatch(name, ...args) {\n const action = this.actions.has(name)\n ? this.actions.get(name)\n : this.surface[name];\n\n if (typeof action === 'function') {\n return action(...args);\n }\n return this.surfaceComputed();\n }\n\n #bindSurface(result = {}) {\n const oldKeys = Object.keys(this.surface);\n\n while (oldKeys.length > 0) {\n const key = oldKeys.shift();\n if (key in this.surface) {\n delete this.surface[key];\n }\n }\n\n for (const [key, plugin] of Surface.plugins) {\n Object.defineProperty(this.surface, key, {\n value: plugin\n });\n }\n\n for (const extension of this.extensions) {\n const descriptors = Object.getOwnPropertyDescriptors(extension);\n // Filter out the special $ methods if you don't want to inherit those\n const filteredDescriptors = Object.fromEntries(\n Object.entries(descriptors).filter(([key]) => !key.startsWith('$'))\n );\n Object.defineProperties(this.surface, filteredDescriptors);\n }\n\n const entries = Object.entries(result);\n \n for (const [key, value] of entries) {\n if (this.values.has(value)) {\n Object.defineProperty(this.surface, key, {\n get: () => value.value,\n set: (newValue) => value.value = newValue\n });\n\n continue;\n }\n\n if (this.computeds.has(value)) {\n Object.defineProperty(this.surface, key, {\n get: () => value.value\n });\n continue;\n }\n \n if (this.actions.has(value)) {\n Object.defineProperty(this.surface, key, { value });\n continue;\n }\n\n this.surface[key] = value;\n }\n\n return this.surface;\n }\n}\n\nexport const defineSurface = (...args) => Surface.create(...args);\nexport const refreshSurface = (surfaceComputed) => {\n if (isSurface(surfaceComputed)) {\n const surfaceInstance = Surface.surfaces.get(surfaceComputed);\n if (surfaceInstance) {\n surfaceInstance.setup();\n }\n }\n}\nexport const definePlugin = (...args) => Surface.createPlugin(...args);\nexport const isSurface = (surfaceComputed) => Surface.surfaces.has(surfaceComputed);\n\nexport const destroySurface = (surfaceComputed) => {\n if (isSurface(surfaceComputed)) {\n Surface.surfaces.delete(surfaceComputed);\n }\n}\n", "export class HitRegistry {\n #areas = new Map();\n\n register(id, area) {\n if (!id) {\n throw new Error('Hit area must have an id');\n }\n this.#areas.set(id, { id, ...area });\n return () => this.unregister(id);\n }\n\n unregister(id) {\n this.#areas.delete(id);\n }\n\n get(id) {\n return this.#areas.get(id);\n }\n\n has(id) {\n return this.#areas.has(id);\n }\n\n get areas() {\n return Array.from(this.#areas.values());\n }\n\n clear() {\n this.#areas.clear();\n }\n}", "import { ServiceProvider } from '@jucie.io/engine';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #offscreenCanvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #resizeSubscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n #hasTransferredControl = false;\n\n static manifest = {\n name: 'CanvasEvents',\n namespace: 'canvasEvents',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n onResize: (listener) => this.onResize(listener),\n transferControlToOffscreen: () => this.transferControlToOffscreen()\n };\n }\n\n setCanvas(canvas) {\n if (this.#canvas) {\n this.#removeListeners();\n }\n \n this.#canvas = canvas;\n this.#updateCachedRect();\n this.#initializeListeners();\n }\n\n subscribe(subscriber) {\n this.#subscribers.add(subscriber);\n return () => this.#subscribers.delete(subscriber);\n }\n\n onResize(subscriber) {\n this.#resizeSubscribers.add(subscriber);\n return () => this.#resizeSubscribers.delete(subscriber);\n }\n\n transferControlToOffscreen() {\n if (!this.#canvas) {\n throw new Error('Canvas must be set before transferring control to offscreen');\n }\n\n if (this.#hasTransferredControl) {\n throw new Error('Control has already been transferred to offscreen');\n }\n\n // Transfer control\n this.#offscreenCanvas = this.#canvas.transferControlToOffscreen();\n this.#hasTransferredControl = true;\n\n // Set initial dimensions on offscreen canvas\n this.#offscreenCanvas.width = this.#canvas.width;\n this.#offscreenCanvas.height = this.#canvas.height;\n\n // Emit initial resize event with actual canvas dimensions\n this.#emitResize({\n width: this.#canvas.width,\n height: this.#canvas.height\n });\n\n return this.#offscreenCanvas;\n }\n\n #updateCachedRect() {\n if (this.#canvas) {\n this.#cachedRect = this.#canvas.getBoundingClientRect();\n }\n }\n\n #initializeListeners() {\n if (!this.#canvas) return;\n\n this.#updateCachedRect();\n\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target !== this.#canvas) {\n continue;\n }\n const { width, height } = entry.contentRect;\n this.#emitResize({\n width: width,\n height: height\n });\n }\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n 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 #emitResize(resizeData) {\n for (const subscriber of this.#resizeSubscribers) {\n subscriber(resizeData);\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.#offscreenCanvas = null;\n this.#cachedRect = null;\n this.#subscribers.clear();\n this.#resizeSubscribers.clear();\n this.#hasTransferredControl = false;\n }\n}\n", "import { defineSurface } from '@jucie.io/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 = (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 = () => {\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(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(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(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(newX, newY, newClientX, newClientY);\n clickCount.value = 2;\n break;\n \n case 'scroll':\n updatePosition(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(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", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\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 #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasDragging = false;\n #wasOverCanvas = false;\n #wasHolding = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface.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 // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n \n // Set up layer computed 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 computed if data exists\n const dataReactor = brushConfig.data \n ? this.#createDataReactor(`brush_${name}`, brushConfig.data)\n : () => undefined;\n \n const whenReactor = brushConfig.when \n ? createComputed(brushConfig.when, {\n immediate: true,\n context: () => this.#pointerSurface.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 computed and subscription\n const reactorData = this.#reactors.get(`painter_brush_${brush.name}`);\n if (reactorData) {\n reactorData.unsubscribe();\n if (reactorData.computed) {\n destroyComputed(reactorData.computed);\n }\n this.#reactors.delete(`painter_brush_${brush.name}`);\n }\n });\n\n // Clean up layer computed and subscription\n const layerReactorData = this.#reactors.get(`painter_layer_${name}`);\n if (layerReactorData) {\n layerReactorData.unsubscribe();\n if (layerReactorData.computed) {\n destroyComputed(layerReactorData.computed);\n }\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}`)?.computed;\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 computed = createComputed(data, {\n immediate: true,\n context: () => this.#pointerSurface.state\n });\n\n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n\n this.#reactors.set(`painter_${id}`, {\n computed,\n unsubscribe\n });\n\n return computed;\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer.state);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer.state);\n \n // Emit click if it wasn't a drag\n if (!pointer.isDragging) {\n this.#emit('pointer:click', pointer.state);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer.state);\n \n // Check for drag start/move\n if (pointer.isDragging && pointer.isPressed) {\n const wasDragging = this.#wasDragging;\n this.#wasDragging = true;\n \n if (!wasDragging) {\n this.#emit('pointer:drag:start', pointer.state);\n } else {\n this.#emit('pointer:drag:move', pointer.state);\n }\n }\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer.state);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer.state);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer.state);\n break;\n }\n \n // Check for drag end\n if (type === 'up' && this.#wasDragging) {\n this.#emit('pointer:drag:end', pointer.state);\n this.#wasDragging = false;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = pointer.isOverCanvas;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer.state);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer.state);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n \n // Check for hold start/end\n const wasHolding = this.#wasHolding;\n const isHolding = pointer.isHolding;\n \n if (isHolding && !wasHolding) {\n this.#emit('pointer:hold:start', pointer.state);\n } else if (!isHolding && wasHolding) {\n this.#emit('pointer:hold:end', pointer.state);\n }\n \n this.#wasHolding = isHolding;\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 // These are already emitted in #emitPointerEvents\n break;\n\n case 'dblclick':\n // This is already emitted in #emitPointerEvents\n break;\n }\n }\n\n #getContextForArea(area) {\n if (!area) return null;\n return area.context \n ? this.#contexts.get(area.context) \n : this.#contexts.get(ContextTypes['2D']);\n }\n\n subscribe(event, callback) {\n if (!this.#subscribers.has(event)) {\n this.#subscribers.set(event, new Set());\n }\n this.#subscribers.get(event).add(callback);\n \n return () => {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.#subscribers.delete(event);\n }\n }\n };\n }\n\n #hitTest(x, y) {\n // Sort by priority (highest first) and test\n const sorted = this.#hitRegistry.areas.sort((a, b) => \n (b.priority || 0) - (a.priority || 0)\n );\n \n for (const area of sorted) {\n if (this.#isPointInBounds(x, y, area.bounds)) {\n return area;\n }\n }\n return null;\n }\n\n #isPointInBounds(x, y, bounds) {\n return x >= bounds.x && \n x <= bounds.x + bounds.width &&\n y >= bounds.y && \n y <= bounds.y + bounds.height;\n }\n\n #emit(event, data) {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n for (const callback of callbacks) {\n callback(data);\n }\n }\n }\n\n // Test helper - only for testing, simulates normalized pointer events\n _testEmitPointerEvent(normalizedEvent) {\n this.#pointerSurface.handleEvent(normalizedEvent);\n this.#handlePointerInteraction(normalizedEvent);\n }\n}"],
5
- "mappings": "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",
6
- "names": ["GLOBAL_NS_OBJ", "checkType", "value", "expectedType", "name", "type", "matchesType", "typeNames", "getTypeName", "createTypeChecker", "DefinitionTypes", "Definitions", "definitionType", "definition", "createDefinition", "type", "returnTypes", "returnTypeChecker", "createTypeChecker", "name", "factory", "defaultArgs", "args", "combinedArgs", "res", "error", "BAD_KEYS", "RESERVED_NAMESPACES", "MAX_NAME_LENGTH", "VALID_NAME", "assertSafeKey", "key", "where", "assertNamespace", "ns", "defineMiddleware", "createDefinition", "defineActions", "defineUninstall", "defineInitialize", "defineGetters", "DefinitionBuilder", "_DefinitionBuilder", "namespace", "#ns", "#args", "#slots", "#set", "type", "factory", "creator", "defineMiddleware", "defineGetters", "defineActions", "defineInitialize", "defineUninstall", "ServiceProvider", "_ServiceProvider", "#services", "options", "useContext", "config", "namespace", "assertNamespace", "instance", "keys", "builder", "DefinitionBuilder", "setupContext", "factory", "maybe", "error", "ENGINE_CONTEXT", "ContextTypes", "nextIdleTick", "callback", "ComputationManager", "reactive", "nextIdleTick", "deadRefs", "ids", "weakRef", "dependant", "ref", "now", "timeElapsed", "reactives", "sortedReactives", "callback", "error", "sorted", "visited", "visiting", "visit", "dependants", "Reactive", "_Reactive", "ComputationManager", "key", "value", "keys", "out", "reactive", "reactorIndex", "cycle", "error", "getter", "effect", "reactives", "deadRefs", "ids", "weakRef", "dependant", "ref", "isReactive", "getter", "Reactive", "addEffect", "effect", "isAsyncFunction", "fn", "Computed", "_Computed", "fn", "config", "computed", "Reactive", "isAsyncFunction", "#getter", "computationId", "value", "resolve", "error", "reject", "createComputed", "destroyComputed", "target", "isComputed", "getter", "Signal", "_Signal", "initialValue", "config", "signal", "Reactive", "args", "#getter", "error", "createSignal", "traversalFunctions", "obj", "path", "createTraversalFunction", "length", "expr", "_", "i", "fn", "traverse", "state", "len", "EMPTY_CACHE", "Surface", "_Surface", "name", "plugin", "setupFn", "options", "instance", "useSurface", "fn", "#createSurface", "pendingReactives", "result", "#setupFromFunction", "#setupFromObject", "#bindSurface", "reactive", "addEffect", "#queueSubscribers", "error", "initial", "cb", "signal", "createSignal", "value", "newValue", "computed", "createComputed", "computedValue", "action", "isSurface", "surface", "reactor", "#destroy", "#processStateValue", "stateConfig", "isDev", "key", "config", "initialValue", "#createAdapter", "#getSnapshot", "subscriber", "#subscribe", "clone", "listener", "#callSubscribers", "snapshot", "path", "#get", "#set", "#dispatch", "overrides", "surfaceComputed", "destroyComputed", "traverse", "args", "oldKeys", "extension", "descriptors", "filteredDescriptors", "entries", "defineSurface", "isSurface", "surfaceComputed", "Surface", "HitRegistry", "#areas", "id", "area", "CanvasEvents", "ServiceProvider", "#canvas", "#offscreenCanvas", "#cachedRect", "#resizeObserver", "#subscribers", "#resizeSubscribers", "#pendingMove", "#rafId", "#hasTransferredControl", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#emitResize", "entries", "entry", "width", "height", "#handleScroll", "#handleMove", "#handleDown", "#handleUp", "#handleDblClick", "event", "normalized", "#normalizeEvent", "#emit", "resizeData", "type", "isOverCanvas", "x", "y", "isWithinBounds", "usePointerSurface", "defineSurface", "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", "newX", "newY", "newClientX", "newClientY", "updateVelocity", "now", "lastMove", "dt", "newVx", "newVy", "maxVel", "clampedVx", "clampedVy", "smoothing", "handleEvent", "ctx", "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", "#resizeObserver", "#subscribers", "#wasDragging", "#wasOverCanvas", "#wasHolding", "layerDef", "layers", "layer", "fn", "canvas", "offscreenCanvas", "assets", "name", "fps", "scale", "step", "options", "width", "height", "event", "callback", "normalizedEvent", "path", "domCanvas", "ContextTypes", "type", "ctx", "CanvasEvents", "entries", "entry", "result", "#scheduleRender", "definitionType", "config", "dataReactor", "#createDataReactor", "brushes", "child", "brushConfig", "whenReactor", "createComputed", "brush", "error", "reactorData", "destroyComputed", "layerReactorData", "#render", "renderStart", "layerStart", "layerReactor", "key", "value", "brushStart", "brushCtx", "requiredAssets", "brushTime", "#renderBrushBounds", "layerTime", "#renderLayerBounds", "#renderDebugOverlay", "y", "lineHeight", "text", "time", "id", "data", "computed", "unsubscribe", "addEffect", "#handlePointerInteraction", "#emitPointerEvents", "pointer", "#emit", "wasDragging", "wasOverCanvas", "isOverCanvas", "wasHolding", "isHolding", "x", "hitArea", "#hitTest", "#getContextForArea", "activeArea", "prevHovered", "area", "callbacks", "sorted", "a", "b", "#isPointInBounds", "bounds"]
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.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\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 #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasDragging = false;\n #wasOverCanvas = false;\n #wasHolding = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface.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 // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n \n // Set up layer computed 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 computed if data exists\n const dataReactor = brushConfig.data \n ? this.#createDataReactor(`brush_${name}`, brushConfig.data)\n : () => undefined;\n \n const whenReactor = brushConfig.when \n ? createComputed(brushConfig.when, {\n immediate: true,\n context: () => this.#pointerSurface.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 computed and subscription\n const reactorData = this.#reactors.get(`painter_brush_${brush.name}`);\n if (reactorData) {\n reactorData.unsubscribe();\n if (reactorData.computed) {\n destroyComputed(reactorData.computed);\n }\n this.#reactors.delete(`painter_brush_${brush.name}`);\n }\n });\n\n // Clean up layer computed and subscription\n const layerReactorData = this.#reactors.get(`painter_layer_${name}`);\n if (layerReactorData) {\n layerReactorData.unsubscribe();\n if (layerReactorData.computed) {\n destroyComputed(layerReactorData.computed);\n }\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}`)?.computed;\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 computed = createComputed(data, {\n immediate: true,\n context: () => this.#pointerSurface.state\n });\n\n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n\n this.#reactors.set(`painter_${id}`, {\n computed,\n unsubscribe\n });\n\n return computed;\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer.state);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer.state);\n \n // Emit click if it wasn't a drag\n if (!pointer.isDragging) {\n this.#emit('pointer:click', pointer.state);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer.state);\n \n // Check for drag start/move\n if (pointer.isDragging && pointer.isPressed) {\n const wasDragging = this.#wasDragging;\n this.#wasDragging = true;\n \n if (!wasDragging) {\n this.#emit('pointer:drag:start', pointer.state);\n } else {\n this.#emit('pointer:drag:move', pointer.state);\n }\n }\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer.state);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer.state);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer.state);\n break;\n }\n \n // Check for drag end\n if (type === 'up' && this.#wasDragging) {\n this.#emit('pointer:drag:end', pointer.state);\n this.#wasDragging = false;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = pointer.isOverCanvas;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer.state);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer.state);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n \n // Check for hold start/end\n const wasHolding = this.#wasHolding;\n const isHolding = pointer.isHolding;\n \n if (isHolding && !wasHolding) {\n this.#emit('pointer:hold:start', pointer.state);\n } else if (!isHolding && wasHolding) {\n this.#emit('pointer:hold:end', pointer.state);\n }\n \n this.#wasHolding = isHolding;\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 // These are already emitted in #emitPointerEvents\n break;\n\n case 'dblclick':\n // This is already emitted in #emitPointerEvents\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.io/engine';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #offscreenCanvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #resizeSubscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n #hasTransferredControl = false;\n\n static manifest = {\n name: 'CanvasEvents',\n namespace: 'canvasEvents',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n onResize: (listener) => this.onResize(listener),\n transferControlToOffscreen: () => this.transferControlToOffscreen()\n };\n }\n\n setCanvas(canvas) {\n if (this.#canvas) {\n this.#removeListeners();\n }\n \n this.#canvas = canvas;\n this.#updateCachedRect();\n this.#initializeListeners();\n }\n\n subscribe(subscriber) {\n this.#subscribers.add(subscriber);\n return () => this.#subscribers.delete(subscriber);\n }\n\n onResize(subscriber) {\n this.#resizeSubscribers.add(subscriber);\n return () => this.#resizeSubscribers.delete(subscriber);\n }\n\n transferControlToOffscreen() {\n if (!this.#canvas) {\n throw new Error('Canvas must be set before transferring control to offscreen');\n }\n\n if (this.#hasTransferredControl) {\n throw new Error('Control has already been transferred to offscreen');\n }\n\n // Transfer control\n this.#offscreenCanvas = this.#canvas.transferControlToOffscreen();\n this.#hasTransferredControl = true;\n\n // Set initial dimensions on offscreen canvas\n this.#offscreenCanvas.width = this.#canvas.width;\n this.#offscreenCanvas.height = this.#canvas.height;\n\n // Emit initial resize event with actual canvas dimensions\n this.#emitResize({\n width: this.#canvas.width,\n height: this.#canvas.height\n });\n\n return this.#offscreenCanvas;\n }\n\n #updateCachedRect() {\n if (this.#canvas) {\n this.#cachedRect = this.#canvas.getBoundingClientRect();\n }\n }\n\n #initializeListeners() {\n if (!this.#canvas) return;\n\n this.#updateCachedRect();\n\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target !== this.#canvas) {\n continue;\n }\n const { width, height } = entry.contentRect;\n this.#emitResize({\n width: width,\n height: height\n });\n }\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n 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 #emitResize(resizeData) {\n for (const subscriber of this.#resizeSubscribers) {\n subscriber(resizeData);\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.#offscreenCanvas = null;\n this.#cachedRect = null;\n this.#subscribers.clear();\n this.#resizeSubscribers.clear();\n this.#hasTransferredControl = false;\n }\n}\n", "import { defineSurface } from '@jucie.io/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 = (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 = () => {\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(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(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(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(newX, newY, newClientX, newClientY);\n clickCount.value = 2;\n break;\n \n case 'scroll':\n updatePosition(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(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,kBAAAE,EAAA,gBAAAC,EAAA,YAAAC,EAAA,gBAAAC,GAAA,gBAAAC,GAAA,sBAAAC,IAAA,eAAAC,GAAAR,ICAA,IAAAS,GAAgC,4BCAzB,IAAMC,EAAe,CAC1B,KAAM,KACN,MAAS,QACT,OAAU,SACV,eAAkB,gBACpB,EDHA,IAAAC,EAA2D,8BAC3DC,EAAiD,4BEH1C,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,4BAEnBC,EAAN,cAA2B,kBAAgB,CAChDC,GAAU,KACVC,GAAmB,KACnBC,GAAc,KACdC,GAAkB,KAClBC,GAAe,IAAI,IACnBC,GAAqB,IAAI,IACzBC,GAAe,KACfC,GAAS,KACTC,GAAyB,GAEzB,OAAO,SAAW,CAChB,KAAM,eACN,UAAW,eACX,QAAS,OACX,EAEA,SAAU,CACR,MAAO,CACL,UAAYC,GAAW,KAAK,UAAUA,CAAM,EAC5C,UAAYC,GAAa,KAAK,UAAUA,CAAQ,EAChD,SAAWA,GAAa,KAAK,SAASA,CAAQ,EAC9C,2BAA4B,IAAM,KAAK,2BAA2B,CACpE,CACF,CAEA,UAAUD,EAAQ,CACZ,KAAKT,IACP,KAAKW,GAAiB,EAGxB,KAAKX,GAAUS,EACf,KAAKG,GAAkB,EACvB,KAAKC,GAAqB,CAC5B,CAEA,UAAUC,EAAY,CACpB,YAAKV,GAAa,IAAIU,CAAU,EACzB,IAAM,KAAKV,GAAa,OAAOU,CAAU,CAClD,CAEA,SAASA,EAAY,CACnB,YAAKT,GAAmB,IAAIS,CAAU,EAC/B,IAAM,KAAKT,GAAmB,OAAOS,CAAU,CACxD,CAEA,4BAA6B,CAC3B,GAAI,CAAC,KAAKd,GACR,MAAM,IAAI,MAAM,6DAA6D,EAG/E,GAAI,KAAKQ,GACP,MAAM,IAAI,MAAM,mDAAmD,EAIrE,YAAKP,GAAmB,KAAKD,GAAQ,2BAA2B,EAChE,KAAKQ,GAAyB,GAG9B,KAAKP,GAAiB,MAAQ,KAAKD,GAAQ,MAC3C,KAAKC,GAAiB,OAAS,KAAKD,GAAQ,OAG5C,KAAKe,GAAY,CACf,MAAO,KAAKf,GAAQ,MACpB,OAAQ,KAAKA,GAAQ,MACvB,CAAC,EAEM,KAAKC,EACd,CAEAW,IAAoB,CACd,KAAKZ,KACP,KAAKE,GAAc,KAAKF,GAAQ,sBAAsB,EAE1D,CAEAa,IAAuB,CAChB,KAAKb,KAEV,KAAKY,GAAkB,EAEvB,KAAKT,GAAkB,IAAI,eAAgBa,GAAY,CACrD,QAAWC,KAASD,EAAS,CAC3B,GAAIC,EAAM,SAAW,KAAKjB,GACxB,SAEF,GAAM,CAAE,MAAAkB,EAAO,OAAAC,CAAO,EAAIF,EAAM,YAChC,KAAKF,GAAY,CACf,MAAOG,EACP,OAAQC,CACV,CAAC,CACH,CACA,KAAKP,GAAkB,CACzB,CAAC,EACD,KAAKT,GAAgB,QAAQ,KAAKH,EAAO,EAEzC,SAAS,iBAAiB,QAAS,KAAKoB,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,CAEAb,IAAmB,CACb,KAAKR,KACP,KAAKA,GAAgB,WAAW,EAChC,KAAKA,GAAkB,MAGzB,SAAS,oBAAoB,QAAS,KAAKiB,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,KAAKzB,GAO1B,GAHAyB,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,KAAKnB,GAAeoB,EAChB,MAAKnB,KAET,KAAKA,GAAS,sBAAsB,IAAM,CACpC,KAAKD,KACP,KAAKsB,GAAM,KAAKtB,EAAY,EAC5B,KAAKA,GAAe,MAEtB,KAAKC,GAAS,IAChB,CAAC,EACH,EAEAe,GAAeG,GAAU,CAEvB,GAAIA,EAAM,SAAW,KAAKzB,GAAS,CACjC,IAAM0B,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,QAAWX,KAAc,KAAKV,GAC5BU,EAAWW,CAAK,CAEpB,CAEAV,GAAYc,EAAY,CACtB,QAAWf,KAAc,KAAKT,GAC5BS,EAAWe,CAAU,CAEzB,CAEAF,GAAgBF,EAAOK,EAAM,CAC3B,IAAMC,EAAeN,EAAM,SAAW,KAAKzB,GAEvCgC,EAAGC,EACHF,GACFC,EAAIP,EAAM,QACVQ,EAAIR,EAAM,SACD,KAAKvB,IACd8B,EAAIP,EAAM,QAAU,KAAKvB,GAAY,KACrC+B,EAAIR,EAAM,QAAU,KAAKvB,GAAY,MAErC8B,EAAIP,EAAM,QACVQ,EAAIR,EAAM,SAGZ,IAAMS,EAAiBH,GACrB,KAAK7B,IACL8B,GAAK,GACLA,GAAK,KAAK9B,GAAY,OACtB+B,GAAK,GACLA,GAAK,KAAK/B,GAAY,OAGlBwB,EAAa,CACjB,EAAAM,EACA,EAAAC,EACA,KAAAH,EACA,aAAAC,EACA,eAAAG,EACA,QAAST,EAAM,QACf,QAASA,EAAM,QACf,OAAQA,EAAM,QAAU,KACxB,QAASA,EAAM,SAAW,EAC1B,UAAW,KAAK,IAAI,CACtB,EAGA,OAAIK,IAAS,UAAYA,IAAS,UAChCJ,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,KAAKnB,KACP,qBAAqB,KAAKA,EAAM,EAChC,KAAKA,GAAS,MAEhB,KAAKI,GAAiB,EACtB,KAAKX,GAAU,KACf,KAAKC,GAAmB,KACxB,KAAKC,GAAc,KACnB,KAAKE,GAAa,MAAM,EACxB,KAAKC,GAAmB,MAAM,EAC9B,KAAKG,GAAyB,EAChC,CACF,EC5PA,IAAA2B,GAA8B,8BAEjBC,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,GAASd,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,EAAQjC,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,EAAM,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,EAAiB,CAACC,EAAMC,EAAMC,EAAYC,IAAe,CAC7DtD,EAAM,MAAQF,EAAE,MAChBG,EAAM,MAAQF,EAAE,MAChBD,EAAE,MAAQqD,EACVpD,EAAE,MAAQqD,EACVlD,EAAQ,MAAQmD,EAChBlD,EAAQ,MAAQmD,EAChB1C,EAAa,MAAQ,KAAK,IAAI,CAChC,EAEM2C,GAAiB,IAAM,CAC3B,IAAMC,EAAM,KAAK,IAAI,EACfC,EAAW7C,EAAa,MAE9B,GAAI6C,EAAU,CACZ,IAAMC,GAAMF,EAAMC,GAAY,IAC9B,GAAIC,EAAK,GAAKA,EAAK,GAAK,CACtB,IAAMC,GAAS7D,EAAE,MAAQE,EAAM,OAAS0D,EAClCE,GAAS7D,EAAE,MAAQE,EAAM,OAASyD,EAGlCG,EAASnC,EAAO,MAAM,YACtBoC,EAAY,KAAK,IAAI,CAACD,EAAQ,KAAK,IAAIA,EAAQF,CAAK,CAAC,EACrDI,EAAY,KAAK,IAAI,CAACF,EAAQ,KAAK,IAAIA,EAAQD,CAAK,CAAC,EAGrDI,EAAYtC,EAAO,MAAM,kBAC/BP,EAAU,MAAQA,EAAU,OAAS,EAAI6C,GAAaF,EAAYE,EAClE5C,EAAU,MAAQA,EAAU,OAAS,EAAI4C,GAAaD,EAAYC,CACpE,CACF,CACF,EAGMC,GAAcpE,EAAM,OAAO,CAACqE,EAAKC,IAAoB,CACzD,GAAM,CAAE,EAAGhB,EAAM,EAAGC,EAAM,KAAAgB,EAAM,QAASf,EAAY,QAASC,EAAY,OAAQe,EAAa,QAASC,EAAc,aAAcC,GAAmB,eAAgBC,EAAoB,EAAIL,EACzLX,EAAM,KAAK,IAAI,EAOrB,OALA3C,EAAc,MAAQ2C,EACtB/C,EAAc,MAAQ2D,EACtBhE,EAAa,MAAQmE,GACrBlE,EAAe,MAAQmE,GAEfJ,EAAM,CACZ,IAAK,OACHlB,EAAeC,EAAMC,EAAMC,EAAYC,CAAU,EACjDhD,EAAU,MAAQ,GAClBI,EAAS,MAAQ8C,EACjBjD,EAAO,MAAQ8D,EACf7D,EAAQ,MAAQ8D,EAChBxD,EAAW,MAAQqC,EACnBpC,EAAW,MAAQqC,EACnBpC,EAAW,MAAQ,GAGQwC,EAAMtC,EAAc,MACtBQ,EAAO,MAAM,qBACpCT,EAAW,MAAQA,EAAW,MAAQ,EAEtCA,EAAW,MAAQ,EAErB,MAEF,IAAK,KACHiC,EAAeC,EAAMC,EAAMC,EAAYC,CAAU,EACjDhD,EAAU,MAAQ,GAClBK,GAAO,MAAQ6C,EACftC,EAAc,MAAQsC,EACtBxC,EAAW,MAAQ,GACnBG,EAAU,MAAQ,EAClBC,EAAU,MAAQ,EAClBZ,EAAQ,MAAQ8D,EAChB,MAEF,IAAK,OACHpB,EAAeC,EAAMC,EAAMC,EAAYC,CAAU,EACjDC,GAAe,EACf/C,EAAQ,MAAQ8D,EAGZhE,EAAU,OAAS,CAACU,EAAW,OAChBuB,EAAa,MACfb,EAAO,MAAM,gBAC1BV,EAAW,MAAQ,IAGvB,MAEF,IAAK,WACHkC,EAAeC,EAAMC,EAAMC,EAAYC,CAAU,EACjDrC,EAAW,MAAQ,EACnB,MAEF,IAAK,SACHiC,EAAeC,EAAMC,EAAMC,EAAYC,CAAU,EAE7Ca,EAAgB,SAAW,SAC7B9C,EAAiB,MAAQ8C,EAAgB,QAEvCA,EAAgB,SAAW,SAC7B7C,EAAiB,MAAQ6C,EAAgB,QAE3C,MAEF,IAAK,OACHjB,EAAeC,EAAMC,EAAMC,EAAYC,CAAU,EAC7Ca,EAAgB,SAAW,SAC7B5C,EAAc,MAAQ4C,EAAgB,QAExC,KACJ,CACF,CAAC,EAEKM,GAAiB5E,EAAM,OAAO,CAACqE,EAAKQ,IAAS,CACjDlD,EAAY,MAAQkD,CACtB,CAAC,EAEKC,GAAgB9E,EAAM,OAAO,CAACqE,EAAKQ,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,CAACqE,EAAKY,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,EACA,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,YAAAkB,GACA,eAAAQ,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,GAAkBC,EAAkB,EACpCC,GAAgB,KAChBC,GAAsB,KACtBC,GAAkB,KAClBC,GAAe,IAAI,IAGnBC,GAAe,GACfC,GAAiB,GACjBC,GAAc,GAEd,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,KAAKR,GAAgB,KACtC,CACF,CAEA,SAAU,CAER,OAAI,KAAK,QACP,OAAO,OAAO,KAAKL,GAAgB,KAAK,MAAM,EAGzC,CACL,SAAWc,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,mBAAqBC,GAAoB,KAAK,mBAAmBA,CAAe,EAChF,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,mBAAqBC,GAAoB,KAAK,mBAAmBA,CAAe,EAChF,mBAAqBD,GAAa,KAAKxB,GAAgB,WAAWwB,CAAQ,EAC1E,YAAcE,GAAS,KAAK1B,GAAgB,MAAM0B,CAAI,EAEtD,sBAAwBD,GAAoB,KAAK,sBAAsBA,CAAe,CACxF,CACF,CAGA,UAAUZ,EAAQ,CAEhB,IAAMc,EAAYd,EAGZC,EAAkBD,EAAO,2BAA2B,EAG1DC,EAAgB,MAAQa,EAAU,MAClCb,EAAgB,OAASa,EAAU,OAEnC,KAAKxC,GAAU2B,EAGf,OAAO,OAAOc,CAAY,EAAE,QAAQC,GAAQ,CAC1C,GAAI,CACF,IAAMC,EAAMhB,EAAgB,WAAWe,CAAI,EACvCC,GAAK,KAAK1C,GAAU,IAAIyC,EAAMC,CAAG,CACvC,MAAY,CACV,QAAQ,KAAK,gBAAgBD,CAAI,gBAAgB,CACnD,CACF,CAAC,EAGI,KAAK3B,KACR,KAAKA,GAAgB,IAAI6B,GAG3B,KAAK7B,GAAc,UAAUyB,CAAS,EAGlC,KAAKvB,IACP,KAAKA,GAAgB,WAAW,EAGlC,KAAKA,GAAkB,IAAI,eAAgB4B,GAAY,CACrD,IAAMC,EAAQD,EAAQ,CAAC,EACnBC,GAASA,EAAM,SAAWN,IAE5Bb,EAAgB,MAAQa,EAAU,MAClCb,EAAgB,OAASa,EAAU,OAGnC,KAAK,aAAaA,EAAU,MAAOA,EAAU,MAAM,EAEvD,CAAC,EAED,KAAKvB,GAAgB,QAAQuB,CAAS,EAGlC,KAAKxB,IACP,KAAKA,GAAoB,EAG3B,KAAKA,GAAsB,KAAKD,GAAc,UAAWuB,GAAoB,CAC3E,KAAK,mBAAmBA,CAAe,CACzC,CAAC,CACH,CAGA,mBAAmBX,EAAiB,CAClC,KAAK3B,GAAU2B,EAGf,OAAO,OAAOc,CAAY,EAAE,QAAQC,GAAQ,CAC1C,GAAI,CACF,IAAMC,EAAMhB,EAAgB,WAAWe,CAAI,EACvCC,GAAK,KAAK1C,GAAU,IAAIyC,EAAMC,CAAG,CACvC,MAAY,CACV,QAAQ,KAAK,gBAAgBD,CAAI,gBAAgB,CACnD,CACF,CAAC,CAIH,CAEA,aAAajB,EAAI,CACf,IAAMsB,EAAStB,EAAG,KAAKzB,EAAO,EAC1B+C,IACF,KAAK/C,GAAU+C,EAEnB,CAEA,UAAUnB,EAAQ,CAChB,KAAKzB,GAAUyB,CACjB,CAEA,OAAQ,CACD,KAAKxB,KACR,KAAKA,GAAa,GAClB,KAAK4C,GAAgB,EAEzB,CAEA,MAAO,CACD,KAAK5C,KACP,KAAKA,GAAa,GACd,KAAKC,KACP,qBAAqB,KAAKA,EAAQ,EAClC,KAAKA,GAAW,MAGtB,CAEA,SAASiB,EAAU,CACjB,MAAI,kBAAeA,CAAQ,IAAM,QAC/B,MAAM,IAAI,MAAM,0BAA0B,EAG5C,IAAMO,EAAOP,EAAS,MAChB2B,EAAS3B,EAAS,KAAK,WAAY,KAAKX,EAAY,EAG1D,GAAIsC,EAAO,KAAM,CACf,IAAMC,EAAc,KAAKC,GAAmB,SAAStB,CAAI,GAAIoB,EAAO,IAAI,EACpEC,GACF,KAAKhD,GAAU,IAAI,SAAS2B,CAAI,GAAIqB,CAAW,CAEnD,CAGA,IAAME,EAAUH,EAAO,SAAS,IAAII,GAAS,CAC3C,MAAI,kBAAeA,CAAK,IAAM,QAAS,CACrC,IAAMxB,EAAOwB,EAAM,MACbC,EAAcD,EAAM,KAAK,WAAY,KAAK1C,EAAY,EAGtDuC,EAAcI,EAAY,KAC5B,KAAKH,GAAmB,SAAStB,CAAI,GAAIyB,EAAY,IAAI,EACzD,IAAG,GAEDC,EAAcD,EAAY,QAC5B,kBAAeA,EAAY,KAAM,CAC/B,UAAW,GACX,QAAS,IAAM,KAAKzC,GAAgB,KACtC,CAAC,EACD,KAEE2C,EAAQ,CACZ,KAAA3B,EACA,GAAGyB,EACH,YAAAJ,EACA,YAAAK,CACF,EAGA,GAAIC,EAAM,WAAW,QACnB,GAAI,CACFA,EAAM,UAAU,QAAQ,KAAKvD,GAAU,IAAIuD,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,EAEK7B,EAAQ,CACZ,GAAGyB,EACH,KAAApB,EACA,QAAAuB,EACA,QAAS,KAAKnD,GAAU,IAAIgD,EAAO,OAAO,CAC5C,EAKA,GAHA,KAAKlD,GAAQ,IAAI8B,EAAML,CAAK,EAGxBA,EAAM,WAAW,QACnB,GAAI,CACFA,EAAM,UAAU,QAAQA,EAAM,OAAO,CACvC,OAASiC,EAAO,CACd,QAAQ,MAAM,mBAAmB5B,CAAI,aAAc4B,CAAK,CAC1D,CAGF,OAAOjC,CACT,CAEA,YAAYK,EAAM,CAChB,IAAML,EAAQ,KAAKzB,GAAQ,IAAI8B,CAAI,EACnC,GAAI,CAACL,EAAO,OAGZ,GAAIA,EAAM,WAAW,UACnB,GAAI,CACFA,EAAM,UAAU,UAAUA,EAAM,OAAO,CACzC,OAASiC,EAAO,CACd,QAAQ,MAAM,mBAAmB5B,CAAI,eAAgB4B,CAAK,CAC5D,CAIFjC,EAAM,QAAQ,QAAQgC,GAAS,CAC7B,GAAIA,EAAM,WAAW,UACnB,GAAI,CACFA,EAAM,UAAU,UACd,KAAKvD,GAAU,IAAIuD,EAAM,SAAWhC,EAAM,OAAO,CACnD,CACF,OAASiC,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,eAAgBC,CAAK,CAClE,CAGF,IAAMC,EAAc,KAAKxD,GAAU,IAAI,iBAAiBsD,EAAM,IAAI,EAAE,EAChEE,IACFA,EAAY,YAAY,EACpBA,EAAY,aACd,mBAAgBA,EAAY,QAAQ,EAEtC,KAAKxD,GAAU,OAAO,iBAAiBsD,EAAM,IAAI,EAAE,EAEvD,CAAC,EAGD,IAAMG,EAAmB,KAAKzD,GAAU,IAAI,iBAAiB2B,CAAI,EAAE,EAC/D8B,IACFA,EAAiB,YAAY,EACzBA,EAAiB,aACnB,mBAAgBA,EAAiB,QAAQ,EAE3C,KAAKzD,GAAU,OAAO,iBAAiB2B,CAAI,EAAE,GAG/C,KAAK9B,GAAQ,OAAO8B,CAAI,CAC1B,CAEAmB,IAAkB,CACZ,KAAKzC,IAAoB,KAAKD,KAElC,KAAKC,GAAmB,GAExB,KAAKF,GAAW,sBAAsB,IAAM,CAC1C,KAAKE,GAAmB,GACxB,KAAKF,GAAW,KAChB,KAAKuD,GAAQ,CACf,CAAC,EACH,CAEA,KAAMA,IAAU,CACd,GAAK,KAAK5D,GACV,MAAKM,GAAe,GAEpB,GAAI,CAEF,KAAKK,GAAa,MAAM,EAExB,IAAMkD,EAAc,KAAKrD,GAAe,OAAO,QAAU,YAAY,IAAI,EAAI,EAG7E,KAAKP,GAAU,QAAQ0C,GAAO,CAC5BA,EAAI,UAAU,EAAG,EAAG,KAAK3C,GAAQ,MAAO,KAAKA,GAAQ,MAAM,CAC7D,CAAC,EAGD,QAAWwB,KAAS,KAAKzB,GAAQ,OAAO,EAAG,CACzC,IAAM+D,EAAa,KAAKtD,GAAe,OAAO,QAAU,YAAY,IAAI,EAAI,EAG5E,GAAIgB,EAAM,YAAa,CACrB,IAAMuC,EAAe,KAAK7D,GAAU,IAAI,iBAAiBsB,EAAM,IAAI,EAAE,GAAG,SACxE,GAAI,CAACA,EAAM,KAAKuC,EAAa,CAAC,EAAG,QACnC,CAEA,IAAMpB,EAAMnB,EAAM,QAElB,GAAKmB,EAGL,IAAInB,EAAM,WAAW,aACnB,GAAI,CACFA,EAAM,UAAU,aAAamB,EAAK,KAAKlC,EAAO,CAChD,OAASgD,EAAO,CACd,QAAQ,MAAM,mBAAmBjC,EAAM,IAAI,kBAAmBiC,CAAK,EAC/DjC,EAAM,WAAW,SAASA,EAAM,UAAU,QAAQiC,CAAK,CAC7D,CAIFd,EAAI,KAAK,EACLnB,EAAM,UACR,OAAO,QAAQA,EAAM,QAAQ,EAAE,QAAQ,CAAC,CAACwC,EAAKC,CAAK,IAAM,CACnD,OAAOtB,EAAIqB,CAAG,GAAM,WACtBrB,EAAIqB,CAAG,EAAE,GAAI,MAAM,QAAQC,CAAK,EAAIA,EAAQ,CAACA,CAAK,CAAE,EAEpDtB,EAAIqB,CAAG,EAAIC,CAEf,CAAC,EAIH,QAAWT,KAAShC,EAAM,QAAS,CACjC,IAAM0C,EAAa,KAAK1D,GAAe,OAAO,QAAU,YAAY,IAAI,EAAI,EAE5E,GAAIgD,EAAM,aAAe,CAACA,EAAM,YAAY,EAAG,SAG/C,IAAMW,EAAWX,EAAM,QACrB,KAAKvD,GAAU,IAAIuD,EAAM,OAAO,EAChCb,EAEF,GAAKwB,EAGL,IAAIX,EAAM,WAAW,aACnB,GAAI,CACFA,EAAM,UAAU,aAAaW,EAAU,KAAK1D,EAAO,CACrD,OAASgD,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,kBAAmBC,CAAK,EAC/DD,EAAM,WAAW,SAASA,EAAM,UAAU,QAAQC,CAAK,EAC3D,QACF,CAGFU,EAAS,KAAK,EAEVX,EAAM,UACR,OAAO,QAAQA,EAAM,QAAQ,EAAE,QAAQ,CAAC,CAACQ,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,GAAIZ,EAAM,OACR,QAAWQ,KAAOR,EAAM,OACtBY,EAAeJ,CAAG,EAAI,KAAK7D,GAAQ,IAAI6D,CAAG,EAU9C,GAPAR,EAAM,OAAOW,EAAUX,EAAM,YAAY,EAAGY,EAAgB,KAAK3D,EAAO,EAGpE+C,EAAM,WAAW,aACnBA,EAAM,UAAU,YAAYW,EAAU,KAAK1D,EAAO,EAGhD,KAAKD,GAAe,OAAO,QAAS,CACtC,IAAM6D,EAAY,YAAY,IAAI,EAAIH,EACtC,KAAKxD,GAAS,WAAW,IAAI8C,EAAM,KAAMa,CAAS,EAE9C,KAAK7D,GAAe,OAAO,YAC7B,KAAK8D,GAAmBH,EAAUX,CAAK,CAE3C,CACF,OAASC,EAAO,CACd,QAAQ,MAAM,mBAAmBD,EAAM,IAAI,KAAMC,CAAK,EAClDD,EAAM,WAAW,SAASA,EAAM,UAAU,QAAQC,CAAK,CAC7D,QAAE,CACAU,EAAS,QAAQ,CACnB,EACF,CAKA,GAHAxB,EAAI,QAAQ,EAGRnB,EAAM,WAAW,YACnB,GAAI,CACFA,EAAM,UAAU,YAAYmB,EAAK,KAAKlC,EAAO,CAC/C,OAASgD,EAAO,CACd,QAAQ,MAAM,mBAAmBjC,EAAM,IAAI,iBAAkBiC,CAAK,EAC9DjC,EAAM,WAAW,SAASA,EAAM,UAAU,QAAQiC,CAAK,CAC7D,CAGF,GAAI,KAAKjD,GAAe,OAAO,QAAS,CACtC,IAAM+D,EAAY,YAAY,IAAI,EAAIT,EACtC,KAAKpD,GAAS,WAAW,IAAIc,EAAM,KAAM+C,CAAS,EAE9C,KAAK/D,GAAe,OAAO,YAC7B,KAAKgE,GAAmB7B,EAAKnB,CAAK,CAEtC,EACF,CAGI,KAAKhB,GAAe,OAAO,SAC7B,KAAKiE,GAAoB,CAG7B,QAAE,CACA,KAAKnE,GAAe,EACtB,EACF,CAEAgE,GAAmB3B,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,CAEA6B,GAAmB7B,EAAKnB,EAAO,CAC7BmB,EAAI,KAAK,EACTA,EAAI,YAAc,uBAClBA,EAAI,UAAY,EAChBA,EAAI,WAAW,EAAG,EAAGA,EAAI,OAAO,MAAOA,EAAI,OAAO,MAAM,EACxDA,EAAI,QAAQ,CACd,CAEA8B,IAAsB,CACpB,IAAM9B,EAAM,KAAK1C,GAAU,IAAIwC,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+B,EAAI,GACFC,EAAa,GAEnB,GAAI,KAAKnE,GAAe,OAAO,QAAS,CACtC,IAAMoE,EAAO,QAAQ,KAAK,MAAM,KAAKlE,GAAS,GAAG,CAAC,KAAK,KAAKD,GAAQ,UAAU,QAAQ,CAAC,CAAC,MACxFkC,EAAI,WAAWiC,EAAM,GAAIF,CAAC,EAC1B/B,EAAI,SAASiC,EAAM,GAAIF,CAAC,EACxBA,GAAKC,CACP,CAEA,GAAI,KAAKnE,GAAe,OAAO,gBAAiB,CAC9CmC,EAAI,SAAS,eAAgB,GAAI+B,CAAC,EAClCA,GAAKC,EAEL,OAAW,CAAC9C,EAAMgD,CAAI,IAAK,KAAKnE,GAAS,WAAY,CACnD,IAAMkE,EAAO,KAAK/C,CAAI,KAAKgD,EAAK,QAAQ,CAAC,CAAC,KAC1ClC,EAAI,WAAWiC,EAAM,GAAIF,CAAC,EAC1B/B,EAAI,SAASiC,EAAM,GAAIF,CAAC,EACxBA,GAAKC,CACP,CAEAhC,EAAI,SAAS,KAAK,MAAM,IAAI,CAAC,eAAgB,UAAW,cAAc,CAAC,EAAG,GAAI+B,CAAC,CACjF,CAEA/B,EAAI,QAAQ,CACd,CAEA,aAAaT,EAAOC,EAAQ,CAE1B,QAAWX,KAAS,KAAKzB,GAAQ,OAAO,EACtC,GAAIyB,EAAM,WAAW,SACnB,GAAI,CACFA,EAAM,UAAU,SAASU,EAAOC,EAAQX,EAAM,OAAO,CACvD,OAASiC,EAAO,CACd,QAAQ,MAAM,mBAAmBjC,EAAM,IAAI,cAAeiC,CAAK,EAC3DjC,EAAM,WAAW,SAASA,EAAM,UAAU,QAAQiC,CAAK,CAC7D,CAGN,CAEAN,GAAmB2B,EAAIC,EAAM,CAC3B,IAAMC,KAAW,kBAAeD,EAAM,CACpC,UAAW,GACX,QAAS,IAAM,KAAKlE,GAAgB,KACtC,CAAC,EAEKoE,KAAc,aAAUD,EAAU,IAAM,KAAKhC,GAAgB,CAAC,EAEpE,YAAK9C,GAAU,IAAI,WAAW4E,CAAE,GAAI,CAClC,SAAAE,EACA,YAAAC,CACF,CAAC,EAEMD,CACT,CAEA,SAAU,CACR,KAAK,KAAK,EAGN,KAAKhE,KACP,KAAKA,GAAoB,EACzB,KAAKA,GAAsB,MAEzB,KAAKD,KACP,KAAKA,GAAc,QAAQ,EAC3B,KAAKA,GAAgB,MAEnB,KAAKE,KACP,KAAKA,GAAgB,WAAW,EAChC,KAAKA,GAAkB,MAErB,KAAKJ,IACP,KAAKA,GAAgB,SAAS,EAIhC,QAAWgB,KAAQ,KAAK9B,GAAQ,KAAK,EACnC,KAAK,YAAY8B,CAAI,CAEzB,CAEA,aAAaC,EAAK,CAChB,KAAKtB,GAAe,UAAYsB,EAChC,KAAKtB,GAAe,cAAgB,IAAOsB,CAC7C,CAEA,aAAaC,EAAO,CAClB,KAAKvB,GAAe,UAAY,KAAK,IAAI,EAAGuB,CAAK,CACnD,CAEA,iBAAiBC,EAAM,CACrB,KAAKxB,GAAe,cAAgBwB,CACtC,CAEA,SAASC,EAAU,CAAC,EAAG,CAChB,KAAKzB,GAAe,QACvB,KAAKA,GAAe,MAAQ,CAAC,GAE/B,OAAO,OAAO,KAAKA,GAAe,MAAOyB,CAAO,CAClD,CAEA,YAAa,CACX,MAAO,CACL,GAAG,KAAKvB,GACR,UAAW,KAAKD,GAAQ,UACxB,YAAa,KAAKA,GAAQ,YAC1B,WAAY,KAAKA,GAAQ,UAC3B,CACF,CAGA,mBAAmB6B,EAAiB,CAElC,KAAKzB,GAAgB,YAAYyB,CAAe,EAGhD,KAAK4C,GAA0B5C,CAAe,EAG9C,KAAK6C,GAAmB7C,CAAe,CACzC,CAEA6C,GAAmB7C,EAAiB,CAClC,GAAM,CAAE,KAAAI,CAAK,EAAIJ,EACX8C,EAAU,KAAKvE,GAGrB,OAAQ6B,EAAM,CACZ,IAAK,OACH,KAAK2C,GAAM,eAAgBD,EAAQ,KAAK,EACxC,MAEF,IAAK,KACH,KAAKC,GAAM,aAAcD,EAAQ,KAAK,EAGjCA,EAAQ,YACX,KAAKC,GAAM,gBAAiBD,EAAQ,KAAK,EAE3C,MAEF,IAAK,OAIH,GAHA,KAAKC,GAAM,eAAgBD,EAAQ,KAAK,EAGpCA,EAAQ,YAAcA,EAAQ,UAAW,CAC3C,IAAME,EAAc,KAAKnE,GACzB,KAAKA,GAAe,GAEfmE,EAGH,KAAKD,GAAM,oBAAqBD,EAAQ,KAAK,EAF7C,KAAKC,GAAM,qBAAsBD,EAAQ,KAAK,CAIlD,CACA,MAEF,IAAK,SACH,KAAKC,GAAM,iBAAkBD,EAAQ,KAAK,EAC1C,MAEF,IAAK,OACH,KAAKC,GAAM,eAAgBD,EAAQ,KAAK,EACxC,MAEF,IAAK,WACH,KAAKC,GAAM,mBAAoBD,EAAQ,KAAK,EAC5C,KACJ,CAGI1C,IAAS,MAAQ,KAAKvB,KACxB,KAAKkE,GAAM,mBAAoBD,EAAQ,KAAK,EAC5C,KAAKjE,GAAe,IAItB,IAAMoE,EAAgB,KAAKnE,GACrBoE,EAAeJ,EAAQ,aAEzBI,GAAgB,CAACD,EACnB,KAAKF,GAAM,gBAAiBD,EAAQ,KAAK,EAChC,CAACI,GAAgBD,GAC1B,KAAKF,GAAM,gBAAiBD,EAAQ,KAAK,EAG3C,KAAKhE,GAAiBoE,EAGtB,IAAMC,EAAa,KAAKpE,GAClBqE,EAAYN,EAAQ,UAEtBM,GAAa,CAACD,EAChB,KAAKJ,GAAM,qBAAsBD,EAAQ,KAAK,EACrC,CAACM,GAAaD,GACvB,KAAKJ,GAAM,mBAAoBD,EAAQ,KAAK,EAG9C,KAAK/D,GAAcqE,CACrB,CAEAR,GAA0B5C,EAAiB,CACzC,GAAM,CAAE,KAAAI,EAAM,EAAAiD,EAAG,EAAAjB,CAAE,EAAIpC,EACjB8C,EAAU,KAAKvE,GAErB,OAAQ6B,EAAM,CACZ,IAAK,OAAQ,CACX,IAAMkD,EAAU,KAAKC,GAASF,EAAGjB,CAAC,EAGlC,GAFAU,EAAQ,cAAcQ,CAAO,EAEzBA,GAAS,eAAe,QAAS,CACnC,IAAMjD,EAAM,KAAKmD,GAAmBF,CAAO,EAC3CA,EAAQ,cAAc,QAAQ,CAC5B,GAAGR,EAAQ,MACX,IAAAzC,EACA,KAAM,KAAK0C,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CACA,KACF,CAEA,IAAK,KAAM,CACT,IAAMU,EAAaX,EAAQ,WAC3B,GAAIW,GAAY,aAAa,QAAS,CACpC,IAAMpD,EAAM,KAAKmD,GAAmBC,CAAU,EAC9CA,EAAW,YAAY,QAAQ,CAC7B,GAAGX,EAAQ,MACX,IAAAzC,EACA,KAAM,KAAK0C,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CACA,KACF,CAEA,IAAK,OAAQ,CACX,IAAMO,EAAU,KAAKC,GAASF,EAAGjB,CAAC,EAC5BsB,EAAcZ,EAAQ,YAGtBW,EAAaX,EAAQ,WAC3B,GAAIW,GAAY,eAAe,SAAWX,EAAQ,WAAY,CAC5D,IAAMzC,EAAM,KAAKmD,GAAmBC,CAAU,EAC9CA,EAAW,cAAc,QAAQ,CAC/B,GAAGX,EAAQ,MACX,IAAAzC,EACA,KAAM,KAAK0C,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CAGA,GAAIO,GAAS,KAAOI,GAAa,GAAI,CACnC,GAAIA,GAAa,gBAAgB,QAAS,CACxC,IAAMrD,EAAM,KAAKmD,GAAmBE,CAAW,EAC/CA,EAAY,eAAe,QAAQ,CACjC,GAAGZ,EAAQ,MACX,IAAAzC,EACA,KAAM,KAAK0C,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CAEA,GAAIO,GAAS,gBAAgB,QAAS,CACpC,IAAMjD,EAAM,KAAKmD,GAAmBF,CAAO,EAC3CA,EAAQ,eAAe,QAAQ,CAC7B,GAAGR,EAAQ,MACX,IAAAzC,EACA,KAAM,KAAK0C,GAAM,KAAK,IAAI,CAC5B,CAAC,CACH,CAEAD,EAAQ,eAAeQ,CAAO,CAChC,CACA,KACF,CAEA,IAAK,SACL,IAAK,OAEH,MAEF,IAAK,WAEH,KACJ,CACF,CAEAE,GAAmBG,EAAM,CACvB,OAAKA,EACEA,EAAK,QACR,KAAKhG,GAAU,IAAIgG,EAAK,OAAO,EAC/B,KAAKhG,GAAU,IAAIwC,EAAa,IAAI,CAAC,EAHvB,IAIpB,CAEA,UAAUL,EAAOC,EAAU,CACzB,OAAK,KAAKnB,GAAa,IAAIkB,CAAK,GAC9B,KAAKlB,GAAa,IAAIkB,EAAO,IAAI,GAAK,EAExC,KAAKlB,GAAa,IAAIkB,CAAK,EAAE,IAAIC,CAAQ,EAElC,IAAM,CACX,IAAM6D,EAAY,KAAKhF,GAAa,IAAIkB,CAAK,EACzC8D,IACFA,EAAU,OAAO7D,CAAQ,EACrB6D,EAAU,OAAS,GACrB,KAAKhF,GAAa,OAAOkB,CAAK,EAGpC,CACF,CAEAyD,GAASF,EAAGjB,EAAG,CAEb,IAAMyB,EAAS,KAAKxF,GAAa,MAAM,KAAK,CAACyF,EAAGC,KAC7CA,EAAE,UAAY,IAAMD,EAAE,UAAY,EACrC,EAEA,QAAWH,KAAQE,EACjB,GAAI,KAAKG,GAAiBX,EAAGjB,EAAGuB,EAAK,MAAM,EACzC,OAAOA,EAGX,OAAO,IACT,CAEAK,GAAiBX,EAAGjB,EAAG6B,EAAQ,CAC7B,OAAOZ,GAAKY,EAAO,GACZZ,GAAKY,EAAO,EAAIA,EAAO,OACvB7B,GAAK6B,EAAO,GACZ7B,GAAK6B,EAAO,EAAIA,EAAO,MAChC,CAEAlB,GAAMjD,EAAO2C,EAAM,CACjB,IAAMmB,EAAY,KAAKhF,GAAa,IAAIkB,CAAK,EAC7C,GAAI8D,EACF,QAAW7D,KAAY6D,EACrB7D,EAAS0C,CAAI,CAGnB,CAGA,sBAAsBzC,EAAiB,CACrC,KAAKzB,GAAgB,YAAYyB,CAAe,EAChD,KAAK4C,GAA0B5C,CAAe,CAChD,CACF",
6
+ "names": ["main_exports", "__export", "CanvasEvents", "HitRegistry", "Painter", "defineBrush", "defineLayer", "usePointerSurface", "__toCommonJS", "import_engine", "ContextTypes", "import_reactive", "import_engine", "HitRegistry", "#areas", "id", "area", "import_engine", "CanvasEvents", "#canvas", "#offscreenCanvas", "#cachedRect", "#resizeObserver", "#subscribers", "#resizeSubscribers", "#pendingMove", "#rafId", "#hasTransferredControl", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#emitResize", "entries", "entry", "width", "height", "#handleScroll", "#handleMove", "#handleDown", "#handleUp", "#handleDblClick", "event", "normalized", "#normalizeEvent", "#emit", "resizeData", "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", "newX", "newY", "newClientX", "newClientY", "updateVelocity", "now", "lastMove", "dt", "newVx", "newVy", "maxVel", "clampedVx", "clampedVy", "smoothing", "handleEvent", "ctx", "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", "#resizeObserver", "#subscribers", "#wasDragging", "#wasOverCanvas", "#wasHolding", "layerDef", "layers", "layer", "fn", "canvas", "offscreenCanvas", "assets", "name", "fps", "scale", "step", "options", "width", "height", "event", "callback", "normalizedEvent", "path", "domCanvas", "ContextTypes", "type", "ctx", "CanvasEvents", "entries", "entry", "result", "#scheduleRender", "config", "dataReactor", "#createDataReactor", "brushes", "child", "brushConfig", "whenReactor", "brush", "error", "reactorData", "layerReactorData", "#render", "renderStart", "layerStart", "layerReactor", "key", "value", "brushStart", "brushCtx", "requiredAssets", "brushTime", "#renderBrushBounds", "layerTime", "#renderLayerBounds", "#renderDebugOverlay", "y", "lineHeight", "text", "time", "id", "data", "computed", "unsubscribe", "#handlePointerInteraction", "#emitPointerEvents", "pointer", "#emit", "wasDragging", "wasOverCanvas", "isOverCanvas", "wasHolding", "isHolding", "x", "hitArea", "#hitTest", "#getContextForArea", "activeArea", "prevHovered", "area", "callbacks", "sorted", "a", "b", "#isPointInBounds", "bounds"]
7
7
  }
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@jucie.io/engine-painter",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "Canvas painting service for @jucie.io/engine with reactive rendering support",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",
7
7
  "exports": {
8
- ".": "./dist/index.js"
8
+ ".": "./dist/main.js"
9
9
  },
10
10
  "files": [
11
11
  "dist/",
12
12
  "README.md"
13
13
  ],
14
14
  "scripts": {
15
+ "build": "node build.js",
15
16
  "test": "vitest"
16
17
  },
17
18
  "keywords": [