@omnipad/core 0.4.5 → 0.6.0
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/chunk-42WBUPM3.cjs +1 -0
- package/dist/chunk-45F3BQT7.cjs +1 -0
- package/dist/chunk-52YF3VHH.cjs +1 -0
- package/dist/chunk-6XY2ZHZ3.mjs +1 -0
- package/dist/chunk-AK3RL7NL.mjs +1 -0
- package/dist/chunk-EYKCVOUA.mjs +1 -0
- package/dist/chunk-HCOFKHVV.cjs +1 -0
- package/dist/chunk-HQNUZXP5.mjs +1 -0
- package/dist/chunk-J5SVBM6K.mjs +1 -0
- package/dist/chunk-NB4FTDOP.cjs +1 -0
- package/dist/chunk-OVV5DKL6.cjs +1 -0
- package/dist/chunk-YAS6LFBF.mjs +1 -0
- package/dist/dom/index.cjs +1 -0
- package/dist/dom/index.d.cts +375 -0
- package/dist/dom/index.d.ts +375 -0
- package/dist/dom/index.mjs +1 -0
- package/dist/guest/index.cjs +1 -0
- package/dist/guest/index.d.cts +21 -0
- package/dist/guest/index.d.ts +21 -0
- package/dist/guest/index.mjs +1 -0
- package/dist/{index-CT1fDlB9.d.cts → index-Dd0aHJaA.d.cts} +752 -181
- package/dist/{index-CT1fDlB9.d.ts → index-Dd0aHJaA.d.ts} +752 -181
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +270 -157
- package/dist/index.d.ts +270 -157
- package/dist/index.mjs +1 -1
- package/dist/sticky-CCj0ECTY.d.cts +285 -0
- package/dist/sticky-d_z_GU83.d.ts +285 -0
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +140 -173
- package/dist/utils/index.d.ts +140 -173
- package/dist/utils/index.mjs +1 -1
- package/package.json +17 -1
- package/dist/chunk-4J2ZANLB.cjs +0 -1
- package/dist/chunk-W7OR5ESR.mjs +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {c,b,f,d as d$1,a,h,l,A as A$1,m,w,C,v}from'./chunk-W7OR5ESR.mjs';export{d as ACTION_TYPES,c as CMP_TYPES,f as CONTEXT,b as KEYS,h as Registry,e as VALID_UNITS,g as setGlobalSignalHandler}from'./chunk-W7OR5ESR.mjs';var x=Symbol.for("omnipad.gamepad_manager.instance"),it={A:0,B:1,X:2,Y:3,LB:4,RB:5,LT:6,RT:7,Select:8,Start:9,L3:10,R3:11,Up:12,Down:13,Left:14,Right:15},M=class c{constructor(){a(this,"isRunning",false);a(this,"config",null);a(this,"lastButtonStates",[]);a(this,"loop",()=>{if(!this.isRunning)return;let i=navigator.getGamepads();this.config?.forEach((t,e)=>{let s=i[e];s&&s.connected&&t&&(this.lastButtonStates[e]||(this.lastButtonStates[e]=[]),this.processButtons(s,t,e),this.processDPad(s,t),this.processAxes(s,t));}),requestAnimationFrame(this.loop);});}static getInstance(){let i=globalThis;return i[x]||(i[x]=new c),i[x]}setConfig(i){this.config=i;}getConfig(){return this.config}start(){this.isRunning||(this.isRunning=true,window.addEventListener("gamepadconnected",i=>{import.meta.env?.DEV&&console.log("[Omnipad-Core] Gamepad Connected:",i.gamepad.id);}),window.addEventListener("gamepaddisconnected",()=>{import.meta.env?.DEV&&console.log("[Omnipad-Core] Gamepad disconnected.");}),this.loop());}stop(){this.isRunning=false;}processButtons(i,t,e){t.buttons&&Object.entries(t.buttons).forEach(([s,o])=>{let n=it[s];if(n===void 0||!i.buttons[n])return;let l=i.buttons[n].pressed,u=this.lastButtonStates[e][n]||false;l&&!u?this.triggerVirtualEntity(o,"down"):!l&&u&&this.triggerVirtualEntity(o,"up"),this.lastButtonStates[e][n]=l;});}processDPad(i,t){let e=t?.dpad;if(!e)return;let s=i.buttons[12]?.pressed?-1:0,o=i.buttons[13]?.pressed?1:0,n=i.buttons[14]?.pressed?-1:0,l=i.buttons[15]?.pressed?1:0,u=n+l,v=s+o;this.triggerVirtualEntity(e,"vector",{x:u,y:v});}processAxes(i,t){let e=t?.deadzone??.1;if(t?.leftStick){let s=Math.abs(i.axes[0])>e?i.axes[0]:0,o=Math.abs(i.axes[1])>e?i.axes[1]:0;this.triggerVirtualEntity(t.leftStick,"vector",{x:s,y:o});}if(t?.rightStick){let s=Math.abs(i.axes[2])>e?i.axes[2]:0,o=Math.abs(i.axes[3])>e?i.axes[3]:0;this.triggerVirtualEntity(t.rightStick,"vector",{x:s,y:o});}}triggerVirtualEntity(i,t,e){let s=h.getInstance().getEntity(i);!s||s.activePointerId!=null||(t==="down"&&typeof s.triggerDown=="function"&&s.triggerDown(),t==="up"&&typeof s.triggerUp=="function"&&s.triggerUp(),t==="vector"&&typeof s.triggerVector=="function"&&e&&s.triggerVector(e.x,e.y));}};var R=typeof globalThis<"u"&&globalThis.requestAnimationFrame?globalThis.requestAnimationFrame.bind(globalThis):c=>setTimeout(c,16),st=typeof globalThis<"u"&&globalThis.cancelAnimationFrame?globalThis.cancelAnimationFrame.bind(globalThis):c=>clearTimeout(c);function T(c){let i=false,t;return function(e){t=e,i||(i=true,R(()=>{c(t),i=false;}));}}function z(c){let i=null,t=()=>{c(),i=R(t);};return {start:()=>{i===null&&t();},stop:()=>{i!==null&&(st(i),i=null);}}}var Z=(c=2)=>new Promise(i=>{let t=0,e=()=>{++t>=c?i():R(e);};R(e);});var O=Symbol.for("omnipad.element_observer.instance"),k=class c{constructor(){a(this,"_ro");a(this,"_roRegistry",new Map);a(this,"_elToRoCb",new WeakMap);a(this,"_io");a(this,"_ioRegistry",new Map);a(this,"_elToIoCb",new WeakMap);let i=T(t=>{for(let e of t)this._elToRoCb.get(e.target)?.();});this._ro=new ResizeObserver(t=>{i(t);}),this._io=new IntersectionObserver(t=>{for(let e of t)this._elToIoCb.get(e.target)?.(e.isIntersecting);},{threshold:0});}static getInstance(){let i=globalThis;return i[O]||(i[O]=new c),i[O]}observeResize(i,t,e){this.unobserveResize(i),this._roRegistry.set(i,t),this._elToRoCb.set(t,e),this._ro.observe(t);}unobserveResize(i){let t=this._roRegistry.get(i);t&&(this._ro.unobserve(t),this._elToRoCb.delete(t),this._roRegistry.delete(i));}observeIntersect(i,t,e){this.unobserveIntersect(i),this._ioRegistry.set(i,t),this._elToIoCb.set(t,e),this._io.observe(t);}unobserveIntersect(i){let t=this._ioRegistry.get(i);t&&(this._io.unobserve(t),this._elToIoCb.delete(t),this._ioRegistry.delete(i));}disconnect(i){this.unobserveResize(i),this.unobserveIntersect(i);}};var _=Symbol.for("omnipad.window_manager.instance"),Y=class c{constructor(){a(this,"_isListening",false);a(this,"throttledReset");a(this,"handleGlobalReset",()=>{import.meta.env?.DEV&&console.debug("[OmniPad-Core] Safety reset triggered by environment change."),h.getInstance().resetAll(),h.getInstance().markAllRectDirty();});a(this,"handleResizeReset",()=>{this.throttledReset(null);});a(this,"handleBlurReset",()=>{this.handleGlobalReset();});a(this,"handleScrollReset",()=>{this.throttledReset(null);});a(this,"handleVisibilityChangeReset",()=>{document.visibilityState==="hidden"&&this.handleGlobalReset();});this.throttledReset=T(()=>{this.handleGlobalReset();});}static getInstance(){let i=globalThis;return i[_]||(i[_]=new c),i[_]}init(){this._isListening||(window.addEventListener("resize",this.handleResizeReset),window.addEventListener("blur",this.handleBlurReset),window.addEventListener("scroll",this.handleScrollReset,{capture:true,passive:true}),document.addEventListener("visibilitychange",this.handleVisibilityChangeReset),this._isListening=true,import.meta.env?.DEV&&console.log("[OmniPad-Core] Global WindowManager monitoring started."));}async toggleFullscreen(i){let t=i||document.documentElement;try{document.fullscreenElement?(this.handleGlobalReset(),await document.exitFullscreen()):(this.handleGlobalReset(),await t.requestFullscreen());}catch(e){console.error("[OmniPad-Core] Fullscreen toggle failed:",e);}}isFullscreen(){return !!document.fullscreenElement}destroy(){window.removeEventListener("resize",this.handleResizeReset),window.removeEventListener("blur",this.handleBlurReset),window.removeEventListener("scroll",this.handleScrollReset,{capture:true}),window.removeEventListener("visibilitychange",this.handleVisibilityChangeReset),this._isListening=false;}};var A=class{constructor(){a(this,"listeners",new Set);}subscribe(i){return this.listeners.add(i),()=>this.listeners.delete(i)}emit(i){this.listeners.forEach(t=>{try{t(i);}catch(e){console.error("[OmniPad-Core] Emitter callback error:",e);}});}clear(){this.listeners.clear();}};var d=class{constructor(i,t,e,s){a(this,"uid");a(this,"type");a(this,"config");a(this,"state");a(this,"rectProvider",null);a(this,"_onMarkDirtyCb",null);a(this,"stateEmitter",new A);a(this,"configEmitter",new A);this.uid=i,this.type=t,this.config=e,this.state=s;}getConfig(){return this.config}subscribeConfig(i){return i(this.config),this.configEmitter.subscribe(i)}updateConfig(i){this.config={...this.config,...i},this.configEmitter.emit(this.config);}getState(){return this.state}setState(i){this.state={...this.state,...i},this.stateEmitter.emit(this.state);}subscribeState(i){return i(this.state),this.stateEmitter.subscribe(i)}destroy(){this.reset(),this.stateEmitter.clear(),this.configEmitter.clear(),h.getInstance().unregister(this.uid);}get rect(){return this.rectProvider?this.rectProvider():null}bindRectProvider(i,t){this.rectProvider=i,t&&(this._onMarkDirtyCb=t);}markRectDirty(){this._onMarkDirtyCb?.();}};var p=class{constructor(i,t){a(this,"isPressed",false);a(this,"mapping");a(this,"targetId");this.update(i,t);}update(i,t){this.isPressed&&this.reset(),this.targetId=i,this.mapping=this.hydrate(t);}hydrate(i){if(!i)return;let t={...i};if(t.type==="mouse")return t.button=t.button??0,t;let{key:e,code:s,keyCode:o}=t;if(e||s||o){t.type="keyboard";let n=Object.values(b).find(l=>l.code===s||l.key===e||l.keyCode===o);n&&(t.key=e??n.key,t.code=s??n.code,t.keyCode=o??n.keyCode);}return t}press(){if(!this.mapping||this.isPressed)return;this.isPressed=true;let i=this.mapping.type==="keyboard"?d$1.KEYDOWN:d$1.MOUSEDOWN;this.emitSignal(i);}release(i=true){if(!this.mapping||!this.isPressed)return;this.isPressed=false;let t=this.mapping.type==="keyboard"?d$1.KEYUP:d$1.MOUSEUP;this.emitSignal(t),this.mapping.type==="mouse"&&i&&this.emitSignal(d$1.CLICK);}move(i){this.mapping?.type==="mouse"&&this.emitSignal(d$1.MOUSEMOVE,i);}reset(){this.isPressed&&this.release(false);}async tap(i=true){this.isPressed||(this.press(),await Z(2),this.isPressed&&this.release(i));}emitSignal(i,t={}){!this.targetId||!this.mapping||h.getInstance().broadcastSignal({targetStageId:this.targetId,type:i,payload:{key:this.mapping.key,code:this.mapping.code,keyCode:this.mapping.keyCode,button:this.mapping.button,point:this.mapping.fixedPoint,...t}});}};var V={isActive:false,isPressed:false,pointerId:null,value:0},B=class extends d{constructor(t,e,s){super(t,s||c.BUTTON,e,V);a(this,"emitter");this.emitter=new p(e.targetStageId,e.mapping);}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.setState({isActive:true,isPressed:true,pointerId:t.pointerId}),this.emitter.press();}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||this.handleRelease(true);}onPointerCancel(){this.handleRelease(false);}onPointerMove(){}reset(){this.setState(V),this.emitter.reset();}updateConfig(t){super.updateConfig(t),this.emitter.update(this.config.targetStageId,this.config.mapping);}handleRelease(t){this.setState(V),this.emitter.release(t);}triggerDown(){this.state.isPressed||(this.setState({isActive:true,isPressed:true}),this.emitter.press());}triggerUp(){this.state.isPressed&&(this.setState({isActive:false,isPressed:false}),this.emitter.release(true));}};var q={isActive:false,pointerId:null,vector:{x:0,y:0}},j=.002,J=.3,G=class extends d{constructor(t,e,s){super(t,s||c.D_PAD,e,q);a(this,"emitters");let o=e.targetStageId;this.emitters={up:new p(o,e.mapping?.up),down:new p(o,e.mapping?.down),left:new p(o,e.mapping?.left),right:new p(o,e.mapping?.right)};}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.setState({isActive:true,pointerId:t.pointerId,vector:{x:0,y:0}}),this.processInput(t,true);}onPointerMove(t){!this.state.isActive||t.pointerId!==this.state.pointerId||this.processInput(t);}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||this.reset();}onPointerCancel(){this.reset();}processInput(t,e=false){if(!this.state.isActive)return;let s=this.rect;if(!s)return;let o=s.left+s.width/2,n=s.top+s.height/2,l$1=s.width/2,u=s.height/2,v=(t.clientX-o)/l$1,P=(t.clientY-n)/u;if(e&&(v!=l(v,-1,1)||P!=l(P,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let C={x:l(v,-1,1),y:l(P,-1,1)};A$1(C,this.state.vector,j)||(this.setState({vector:C}),this.handleDigitalKeys(C));}handleDigitalKeys(t){let e=this.config.threshold??.3;t.y<-e?(this.emitters.up.press(),this.emitters.down.release()):t.y>e?(this.emitters.down.press(),this.emitters.up.release()):(this.emitters.up.release(),this.emitters.down.release()),t.x<-e?(this.emitters.left.press(),this.emitters.right.release()):t.x>e?(this.emitters.right.press(),this.emitters.left.release()):(this.emitters.left.release(),this.emitters.right.release());}reset(){this.emitters.up.reset(),this.emitters.down.reset(),this.emitters.left.reset(),this.emitters.right.reset(),this.setState(q);}updateConfig(t){super.updateConfig(t),this.emitters.up.update(this.config.targetStageId,this.config.mapping?.up),this.emitters.down.update(this.config.targetStageId,this.config.mapping?.down),this.emitters.left.update(this.config.targetStageId,this.config.mapping?.left),this.emitters.right.update(this.config.targetStageId,this.config.mapping?.right);}triggerVector(t,e){let s=this.config.threshold??.3;if(Math.abs(t)<s&&Math.abs(e)<s){this.state.isActive&&this.reset();return}this.state.isActive||this.setState({isActive:true});let o=m(this.state.vector.x,t,J),n=m(this.state.vector.y,e,J),l={x:o,y:n};A$1(l,this.state.vector,j)||(this.setState({vector:l}),this.handleDigitalKeys(l));}};var rt={isDynamicActive:false,dynamicPointerId:null,dynamicPosition:{x:0,y:0}},H=class extends d{constructor(t,e,s){super(t,s||c.INPUT_ZONE,e,rt);a(this,"delegates",{dynamicWidgetPointerDown:()=>{},dynamicWidgetPointerMove:()=>{},dynamicWidgetPointerUp:()=>{},dynamicWidgetPointerCancel:()=>{}});}bindDelegate(t,e){Object.prototype.hasOwnProperty.call(this.delegates,t)?this.delegates[t]=e:import.meta.env?.DEV&&console.warn(`[Omnipad-Core] TargetZone attempted to bind unknown delegate: ${t}`);}get activePointerId(){return this.state.dynamicPointerId}onPointerDown(t){if(this.state.isDynamicActive)return;let e=this.calculateRelativePosition(t.clientX,t.clientY);this.setState({isDynamicActive:true,dynamicPointerId:t.pointerId,dynamicPosition:e}),this.delegates.dynamicWidgetPointerDown?.(t);}onPointerMove(t){this.state.isDynamicActive&&this.delegates.dynamicWidgetPointerMove?.(t);}onPointerUp(t){this.delegates.dynamicWidgetPointerUp?.(t),this.reset();}onPointerCancel(t){this.delegates.dynamicWidgetPointerCancel?.(t),this.reset();}calculateRelativePosition(t,e){let s=this.rect;return s?{x:w(t-s.left,s.width),y:w(e-s.top,s.height)}:{x:0,y:0}}get isInterceptorRequired(){return !!(this.config.dynamicWidgetId||this.config.preventFocusLoss)}reset(){this.setState({isDynamicActive:false,dynamicPointerId:null});}};var I=class{constructor(i={}){a(this,"options");a(this,"startTime",0);a(this,"startPos",{x:0,y:0});a(this,"lastTapTime",0);a(this,"hasMoved",false);a(this,"isDoubleTapHolding",false);this.options={tapTime:250,tapDistance:10,doubleTapGap:300,...i};}onPointerDown(i,t){let e=Date.now();this.startTime=e,this.startPos={x:i,y:t},this.hasMoved=false,e-this.lastTapTime<this.options.doubleTapGap?(this.isDoubleTapHolding=true,this.options.onDoubleTapHoldStart?.()):this.isDoubleTapHolding=false;}onPointerMove(i,t){this.hasMoved||Math.hypot(i-this.startPos.x,t-this.startPos.y)>this.options.tapDistance&&(this.hasMoved=true);}onPointerUp(){let i=Date.now(),t=i-this.startTime;this.isDoubleTapHolding?(this.isDoubleTapHolding=false,this.options.onDoubleTapHoldEnd?.(),this.lastTapTime=0):t<=this.options.tapTime&&!this.hasMoved&&(this.options.onTap?.(),i-this.lastTapTime<this.options.doubleTapGap?(this.options.onDoubleTap?.(),this.lastTapTime=0):this.lastTapTime=i);}reset(){this.isDoubleTapHolding&&this.options.onDoubleTapHoldEnd?.(),this.isDoubleTapHolding=false,this.hasMoved=false,this.startTime=0,this.lastTapTime=0;}};var $={isActive:false,isPressed:false,pointerId:null,value:0,vector:{x:0,y:0}},U=.002,Q=.3,L=class extends d{constructor(t,e,s){super(t,s||c.JOYSTICK,e,$);a(this,"emitters");a(this,"stickEmitter");a(this,"cursorEmitter");a(this,"gesture");a(this,"ticker");let o=e.targetStageId,n=e.mapping||{};this.emitters={up:new p(o,n.up),down:new p(o,n.down),left:new p(o,n.left),right:new p(o,n.right)},this.stickEmitter=new p(o,n.stick),this.cursorEmitter=new p(o,{type:"mouse"}),this.gesture=new I({onTap:async()=>{this.setState({isPressed:true}),await this.stickEmitter.tap(),this.setState({isPressed:false});},onDoubleTapHoldStart:()=>{this.setState({isPressed:true}),this.stickEmitter.press();},onDoubleTapHoldEnd:()=>{this.setState({isPressed:false}),this.stickEmitter.release(false);}}),this.ticker=z(()=>{this.handleCursorTick();});}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.setState({isActive:true,pointerId:t.pointerId,vector:{x:0,y:0}}),this.gesture.onPointerDown(t.clientX,t.clientY),this.processInput(t,true);}onPointerMove(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerMove(t.clientX,t.clientY),this.config.cursorMode&&this.ticker.start(),this.processInput(t));}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerUp(),this.handleRelease());}onPointerCancel(){this.handleRelease();}handleRelease(){this.setState({isActive:false,pointerId:null,vector:{x:0,y:0}}),this.ticker.stop(),Object.values(this.emitters).forEach(t=>t?.reset());}processInput(t,e=false){if(!this.state.isActive)return;let s=this.rect;if(!s)return;let o=s.left+s.width/2,n=s.top+s.height/2,l$1=s.width/2,u=s.height/2,v=(t.clientX-o)/l$1,P=(t.clientY-n)/u;if(e&&(v!=l(v,-1,1)||P!=l(P,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let D=C({x:v,y:P},1,this.config.threshold||.15);A$1(D,this.state.vector,U)||(this.setState({vector:D}),this.handleDigitalKeys(D));}handleCursorTick(){let{vector:t,isActive:e}=this.state;if(!e||!this.config.cursorMode||A$1(t,{x:0,y:0},U)){this.ticker.stop();return}let s=this.config.cursorSensitivity??1,o={x:t.x*Math.abs(t.x)*s,y:t.y*Math.abs(t.y)*s};(Math.abs(o.x)>0||Math.abs(o.y)>0)&&this.cursorEmitter.move({delta:o});}handleDigitalKeys(t){let e=this.config.threshold??.3;t.y<-e?(this.emitters.up.press(),this.emitters.down.release()):t.y>e?(this.emitters.down.press(),this.emitters.up.release()):(this.emitters.up.release(),this.emitters.down.release()),t.x<-e?(this.emitters.left.press(),this.emitters.right.release()):t.x>e?(this.emitters.right.press(),this.emitters.left.release()):(this.emitters.left.release(),this.emitters.right.release());}reset(){this.setState($),this.gesture.reset(),this.handleRelease(),this.stickEmitter.reset(),this.cursorEmitter.reset();}updateConfig(t){super.updateConfig(t);let e=this.config.targetStageId,s=this.config.mapping||{};this.emitters.up.update(e,s.up),this.emitters.down.update(e,s.down),this.emitters.left.update(e,s.left),this.emitters.right.update(e,s.right),this.stickEmitter.update(e,s.stick),this.cursorEmitter.update(e);}triggerDown(){this.state.isPressed||(this.setState({isActive:true,isPressed:true}),this.stickEmitter.press());}triggerUp(){this.state.isPressed&&(this.setState({isActive:false,isPressed:false}),this.stickEmitter.release(true));}triggerVector(t,e){let s=this.config.threshold??.15;if(Math.hypot(t,e)<s){this.state.isActive&&this.handleRelease();return}this.state.isActive||this.setState({isActive:true});let n=m(this.state.vector.x,t,Q),l=m(this.state.vector.y,e,Q),u={x:n,y:l};A$1(u,this.state.vector,U)||(this.setState({vector:u}),this.handleDigitalKeys(u)),this.config.cursorMode&&this.ticker.start();}};var ot={isHighlighted:false},F=class extends d{constructor(i,t,e){super(i,e||c.ROOT_LAYER,t,ot);}reset(){}};var nt={position:{x:50,y:50},isVisible:false,isPointerDown:false,isFocusReturning:false},y=1,N=class extends d{constructor(t,e,s){super(t,s||c.TARGET_ZONE,e,nt);a(this,"hideTimer",null);a(this,"focusFeedbackTimer",null);a(this,"throttledMoveExecution");a(this,"delegates",{dispatchKeyboardEvent:()=>{},dispatchPointerEventAtPos:()=>{},reclaimFocusAtPos:()=>{}});this.throttledMoveExecution=T(o=>{this.executeMouseAction(d$1.POINTERMOVE,o);});}bindDelegate(t,e){Object.prototype.hasOwnProperty.call(this.delegates,t)?this.delegates[t]=e:import.meta.env?.DEV&&console.warn(`[Omnipad-Core] TargetZone attempted to bind unknown delegate: ${t}`);}get activePointerId(){return null}onPointerDown(t){this.processPhysicalEvent(t,d$1.MOUSEDOWN);}onPointerMove(t){this.processPhysicalEvent(t,d$1.MOUSEMOVE);}onPointerUp(t){this.processPhysicalEvent(t,d$1.MOUSEUP),this.processPhysicalEvent(t,d$1.CLICK);}onPointerCancel(t){this.processPhysicalEvent(t,d$1.MOUSEUP);}processPhysicalEvent(t,e){let s=this.rect;if(!s)return;let o={x:w(t.clientX-s.left,s.width),y:w(t.clientY-s.top,s.height)};this.handleSignal({targetStageId:this.uid,type:e,payload:{point:o,button:t.button}});}handleSignal(t){let{type:e,payload:s}=t;switch(this.ensureFocus(),e){case d$1.KEYDOWN:case d$1.KEYUP:this.delegates.dispatchKeyboardEvent?.(e,s);break;case d$1.MOUSEMOVE:s.point?this.updateCursorPosition(s.point):s.delta&&this.updateCursorPositionByDelta(s.delta),this.config.cursorEnabled&&this.showCursor(),this.throttledMoveExecution(s);break;case d$1.MOUSEDOWN:case d$1.MOUSEUP:case d$1.CLICK:s.point&&this.updateCursorPosition(s.point),this.config.cursorEnabled&&this.showCursor(),this.executeMouseAction(e.startsWith(d$1.MOUSE)?e.replace(d$1.MOUSE,d$1.POINTER):e,s);break}}executeMouseAction(t,e){let s=this.rect;if(!s)return;t===d$1.POINTERDOWN&&this.setState({isPointerDown:true}),t===d$1.POINTERUP&&this.setState({isPointerDown:false});let o=e.point||this.state.position,n=l(s.left+v(o.x,s.width),s.left+y,s.left+s.width-y),l$1=l(s.top+v(o.y,s.height),s.top+y,s.top+s.height-y);this.delegates.dispatchPointerEventAtPos?.(t,n,l$1,{button:e.button??0,buttons:this.state.isPointerDown?1:0,pressure:this.state.isPointerDown?.5:0});}ensureFocus(){let t=this.rect;if(!t)return;let e=l(t.left+v(this.state.position.x,t.width),t.left+y,t.left+t.width-y),s=l(t.top+v(this.state.position.y,t.height),t.top+y,t.top+t.height-y);this.delegates.reclaimFocusAtPos?.(e,s,()=>this.triggerFocusFeedback());}triggerFocusFeedback(){this.setState({isFocusReturning:true}),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.focusFeedbackTimer=setTimeout(()=>this.setState({isFocusReturning:false}),500);}updateCursorPosition(t){A$1(t,this.state.position)||this.setState({position:{...t}});}updateCursorPositionByDelta(t){if(A$1(t,{x:0,y:0}))return;let e=this.rect;if(!e)return;let s=w(t.x,e.width),o=w(t.y,e.height);this.updateCursorPosition({x:l(this.state.position.x+s,0,100),y:l(this.state.position.y+o,0,100)});}showCursor(){this.setState({isVisible:true}),this.hideTimer&&clearTimeout(this.hideTimer),this.config.cursorAutoDelay&&this.config.cursorAutoDelay>0&&(this.hideTimer=setTimeout(()=>this.setState({isVisible:false}),this.config.cursorAutoDelay));}reset(){this.state.isPointerDown&&this.executeMouseAction(d$1.POINTERUP,{}),this.hideTimer&&clearTimeout(this.hideTimer),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.setState({isVisible:false,isPointerDown:false,isFocusReturning:false});}};var tt={isActive:false,isPressed:false,pointerId:null,value:0},W=class extends d{constructor(t,e,s){super(t,s||c.TRACKPAD,e,tt);a(this,"lastPointerPos",{x:0,y:0});a(this,"gesture");a(this,"emitter");let o=e.mapping||{type:"mouse"};this.emitter=new p(e.targetStageId,o),this.gesture=new I({onTap:()=>{this.setState({isPressed:true}),this.emitter.tap();},onDoubleTapHoldStart:()=>{this.setState({isPressed:true}),this.emitter.press();},onDoubleTapHoldEnd:()=>{this.setState({isPressed:false}),this.emitter.release(false);}});}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.lastPointerPos={x:t.clientX,y:t.clientY},this.gesture.onPointerDown(t.clientX,t.clientY),this.setState({isActive:true,pointerId:t.pointerId});}onPointerMove(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerMove(t.clientX,t.clientY),this.processInput(t));}processInput(t){if(!this.state.isActive)return;let e=t.clientX-this.lastPointerPos.x,s=t.clientY-this.lastPointerPos.y,o=this.rect;if(!o)return;let n=e/o.width*100*(this.config.sensitivity??1),l=s/o.height*100*(this.config.sensitivity??1),u={x:n,y:l};A$1(u,{x:0,y:0})||this.emitter.move({delta:u}),this.lastPointerPos={x:t.clientX,y:t.clientY};}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerUp(),this.handleRelease());}onPointerCancel(){this.handleRelease();}reset(){this.gesture.reset(),this.emitter.reset(),this.handleRelease();}updateConfig(t){super.updateConfig(t),this.emitter.update(this.config.targetStageId,this.config.mapping);}handleRelease(){this.setState(tt);}};var Ue={ActionTypes:d$1,Context:f,Keys:b,Types:c};export{d as BaseEntity,B as ButtonCore,G as DPadCore,k as ElementObserver,M as GamepadManager,H as InputZoneCore,L as JoystickCore,Ue as OmniPad,F as RootLayerCore,N as TargetZoneCore,W as TrackpadCore,Y as WindowManager};
|
|
1
|
+
import {a as a$1,c as c$1}from'./chunk-AK3RL7NL.mjs';import {b as b$1,f as f$1,e as e$1,g as g$2}from'./chunk-YAS6LFBF.mjs';export{b as Registry,d as StickyController,c as StickyProvider,a as setGlobalSignalHandler}from'./chunk-YAS6LFBF.mjs';import {b,a,e,c,f,m as m$1,l,M,N as N$1,q,F as F$1,r,B as B$1,H as H$1,A,h,g as g$1}from'./chunk-EYKCVOUA.mjs';export{c as ACTION_TYPES,b as CMP_TYPES,e as CONTEXT,a as KEYS,d as VALID_UNITS}from'./chunk-EYKCVOUA.mjs';import {a as a$2}from'./chunk-HQNUZXP5.mjs';export{b as OMNIPAD_IPC_SIGNATURE}from'./chunk-HQNUZXP5.mjs';function Tt(n,s){if(!(!n||!s)&&"bindDelegate"in n&&typeof n.bindDelegate=="function"){let t=Object.entries(s);for(let i=0;i<t.length;i++){let[e,o]=t[i];typeof o=="function"&&n.bindDelegate(e,o);}}}function Et(n,s,t,i,e){if(!n.uid)return ()=>{};let o=n.uid;if("bindRectProvider"in n){let c=n,d=f(()=>i(s));c.bindRectProvider(d.get,()=>{d.markDirty(),e&&e.markDirty();}),t.observeResize(o,s,()=>{c.markRectDirty();});}if("reset"in n){let c=n;t.observeIntersect(o,s,d=>{d||c.reset();});}return ()=>{t.disconnect(o);}}function It(n=[],s){return n?.filter(t=>t.uid!==s)||[]}function St(n,s){return a$1(n,s)}function Ct(n,s,t,i,e,o){let c=c$1(i,e,o);return c.id=s,c.baseType=n,c.parentId=t,c.layout=c$1(i.layout,e.layout,o.layout),c}function At(n,s=[],t){let i=s?.find(o=>o.uid===t),e=n.length>0;return n.length>1&&console.error(`[OmniPad-Validation] InputZone ${t} has multiple dynamic widgets in slot. Only the first one will be activated.`),e&&i&&console.warn(`[OmniPad-Validation] InputZone ${t} has both Slot and Config dynamic widgets. Config ignored.`),{nodeToRender:e?n[0]:i||null,isFromSlot:e}}function Dt(n,s){if(!n||Object.keys(n??{}).length===0)return;if(!(n.config?.baseType===s||n.type===s)){import.meta.env?.DEV&&console.warn(`[OmniPad-Validation] Type mismatch! Expected "${s}", received "${n.type}". Config ignored.`);return}return n}function Rt(n){if(!n||typeof n!="object")throw new Error("[OmniPad-Validation] Profile must be a valid JSON object.");if(n=m$1(n),!Array.isArray(n.items))throw new Error('[OmniPad-Validation] "items" must be an array.');let s={name:n.meta?.name||"Untitled Profile",version:n.meta?.version||"1.0.0",author:n.meta?.author||"Unknown"},t=n.items.map((e,o)=>{if(!e.id||!e.type)throw new Error(`[OmniPad-Validation] Item at index ${o} is missing "id" or "type".`);return {id:String(e.id),type:String(e.type),parentId:e.parentId?String(e.parentId):void 0,config:{...e.config,layout:M(e.config.layout),cssClass:l(e.config.cssClass)}}}),i=n.gamepadMappings;return {meta:s,items:t,gamepadMappings:i}}function Nt(n){let{items:s,gamepadMappings:t}=n,i=new Map,e=(r,p="node")=>h(r)?r:(i.has(r)||i.set(r,g$1(p)),i.get(r));s.forEach(r=>e(r.id,r.type));let o=[];t&&t.forEach(r=>{let p={};if(r.buttons){p.buttons={};for(let[u,b]of Object.entries(r.buttons))p.buttons[u]=e(b);}r.dpad&&(p.dpad=e(r.dpad)),r.leftStick&&(p.leftStick=e(r.leftStick)),r.rightStick&&(p.rightStick=e(r.rightStick)),o.push(p);});let c=new Map,d=[];s.forEach(r=>{r.parentId?(c.has(r.parentId)||c.set(r.parentId,[]),c.get(r.parentId).push(r)):d.push(r);});let h$1=(r,p)=>{if(p.has(r.id))throw new Error(`[OmniPad-Core] Circular dependency detected at node: ${r.id}`);p.add(r.id);let u={...r.config};u?.targetStageId&&(u.targetStageId=e(u.targetStageId)),u?.dynamicWidgetId&&(u.dynamicWidgetId=e(u.dynamicWidgetId));let V=(c.get(r.id)||[]).map(K=>h$1(K,new Set(p)));return {uid:e(r.id),type:r.type,config:u,children:V}},f={};return d.forEach(r=>{f[r.id]=h$1(r,new Set);}),{roots:f,runtimeGamepadMappings:o}}function Yt(n,s,t){let i=b$1.getInstance(),e=[];if(!s||s.length===0)e=i.getAllEntities();else {let r=new Set;s.forEach(p=>{i.getEntitiesByRoot(p).forEach(b=>r.add(b));}),e=Array.from(r);}let o=new Map,c=0,d=r=>h(r)?r:(o.has(r)||o.set(r,`node_${++c}`),o.get(r)),h$1=e.map(r=>{let p=r.getConfig(),u=r.uid,b={...p};b.targetStageId&&(b.targetStageId=d(b.targetStageId)),b.dynamicWidgetId&&(b.dynamicWidgetId=d(b.dynamicWidgetId));let{id:V,parentId:K,...W}=b;return {id:d(u),type:r.type,parentId:p.parentId?d(p.parentId):void 0,config:{...W,layout:N$1(W.layout)}}}),f=[];return t&&t.forEach(r=>{let p={};if(r.buttons){p.buttons={};for(let[u,b]of Object.entries(r.buttons))o.has(b)&&(p.buttons[u]=o.get(b));}r.dpad&&o.has(r.dpad)&&(p.dpad=o.get(r.dpad)),r.leftStick&&o.has(r.leftStick)&&(p.leftStick=o.get(r.leftStick)),r.rightStick&&o.has(r.rightStick)&&(p.rightStick=o.get(r.rightStick)),Object.keys(p).length>0?f.push(p):f.push({});}),{meta:n,items:h$1,gamepadMappings:Object.keys(f).length>0?f:void 0}}var x=class{constructor(){a$2(this,"listeners",new Set);}subscribe(s){return this.listeners.add(s),()=>this.listeners.delete(s)}emit(s){this.listeners.forEach(t=>{try{t(s);}catch(i){console.error("[OmniPad-Core] Emitter callback error:",i);}});}clear(){this.listeners.clear();}};var g=class{constructor(s,t,i,e){a$2(this,"uid");a$2(this,"type");a$2(this,"config");a$2(this,"state");a$2(this,"rectProvider",null);a$2(this,"_onMarkDirtyCb",null);a$2(this,"stateEmitter",new x);a$2(this,"configEmitter",new x);this.uid=s,this.type=t,this.config=i,this.state=e;}getConfig(){return this.config}subscribeConfig(s){return s(this.config),this.configEmitter.subscribe(s)}updateConfig(s){this.config={...this.config,...s},this.configEmitter.emit(this.config);}getState(){return this.state}setState(s){this.state={...this.state,...s},this.stateEmitter.emit(this.state);}subscribeState(s){return s(this.state),this.stateEmitter.subscribe(s)}destroy(){this.reset(),this.stateEmitter.clear(),this.configEmitter.clear(),b$1.getInstance().unregister(this.uid);}get rect(){return this.rectProvider?this.rectProvider():null}bindRectProvider(s,t){this.rectProvider=s,t&&(this._onMarkDirtyCb=t);}markRectDirty(){this._onMarkDirtyCb?.();}};var it=32,dt=255,m=class{constructor(s,t){a$2(this,"isPressed",false);a$2(this,"mapping");a$2(this,"targetId");this.update(s,t);}update(s,t){this.isPressed&&this.reset(),this.targetId=s,this.mapping=typeof t=="string"?a[t]??void 0:this.hydrate(t);}hydrate(s){if(!s||typeof s!="object")return;let{type:t,key:i,code:e,keyCode:o,button:c,fixedPoint:d}=s;if(t==="mouse")return {type:"mouse",button:typeof c=="number"&&c>=0&&c<=2?c:0,fixedPoint:d&&typeof d.x=="number"?{x:Number(d.x),y:Number(d.y)}:void 0};let h=typeof i=="string"?i.substring(0,it):void 0,f=typeof e=="string"?e.substring(0,it):void 0,r=typeof o=="number"&&Number.isFinite(o)?Math.floor(Math.min(o,dt)):void 0;if(h||f||r){let p=Object.values(a).find(u=>u.type!=="keyboard"?false:u.code===f||u.key===h||u.keyCode===r);return p?{type:"keyboard",key:h??p.key,code:f??p.code,keyCode:r??p.keyCode}:{type:"keyboard",key:h||"unknown",code:f||"Unknown",keyCode:r||0}}}press(){if(!this.mapping||this.isPressed)return;this.isPressed=true;let s=this.mapping.type==="keyboard"?c.KEYDOWN:c.MOUSEDOWN;this.emitSignal(s);}release(s=true){if(!this.mapping||!this.isPressed)return;this.isPressed=false;let t=this.mapping.type==="keyboard"?c.KEYUP:c.MOUSEUP;this.emitSignal(t),this.mapping.type==="mouse"&&s&&this.emitSignal(c.CLICK);}move(s){this.mapping?.type==="mouse"&&this.emitSignal(c.MOUSEMOVE,s);}reset(){this.isPressed&&this.release(false);}async tap(s=true){this.isPressed||(this.press(),await g$2(2),this.isPressed&&this.release(s));}emitSignal(s,t={}){this.mapping&&b$1.getInstance().broadcastSignal({targetStageId:this.targetId||"",type:s,payload:{key:this.mapping.key,code:this.mapping.code,keyCode:this.mapping.keyCode,button:this.mapping.button,point:this.mapping.fixedPoint,...t}});}};var k={isActive:false,isPressed:false,pointerId:null,value:0},O=class extends g{constructor(t,i,e){super(t,e||b.BUTTON,i,k);a$2(this,"emitter");this.emitter=new m(i.targetStageId,i.mapping);}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.setState({isActive:true,isPressed:true,pointerId:t.pointerId}),this.emitter.press();}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||this.handleRelease(true);}onPointerCancel(){this.handleRelease(false);}onPointerMove(){}reset(){this.setState(k),this.emitter.reset();}updateConfig(t){super.updateConfig(t),this.emitter.update(this.config.targetStageId,this.config.mapping);}handleRelease(t){this.setState(k),this.emitter.release(t);}triggerDown(){this.state.isPressed||(this.setState({isActive:true,isPressed:true}),this.emitter.press());}triggerUp(){this.state.isPressed&&(this.setState({isActive:false,isPressed:false}),this.emitter.release(true));}};var st={isActive:false,pointerId:null,vector:{x:0,y:0}},rt=.15,ot=.002,nt=.3,R=class extends g{constructor(t,i,e){super(t,e||b.D_PAD,i,st);a$2(this,"emitters");let o=i.targetStageId;this.emitters={up:new m(o,i.mapping?.up),down:new m(o,i.mapping?.down),left:new m(o,i.mapping?.left),right:new m(o,i.mapping?.right)};}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.setState({isActive:true,pointerId:t.pointerId,vector:{x:0,y:0}}),this.processInput(t,true);}onPointerMove(t){!this.state.isActive||t.pointerId!==this.state.pointerId||this.processInput(t);}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||this.reset();}onPointerCancel(){this.reset();}processInput(t,i=false){if(!this.state.isActive)return;let e=this.rect;if(!e)return;let o=e.left+e.width/2,c=e.top+e.height/2,d=e.width/2,h=e.height/2,f=(t.clientX-o)/d,r=(t.clientY-c)/h;if(i&&(f!=q(f,-1,1)||r!=q(r,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let p={x:q(f,-1,1),y:q(r,-1,1)};F$1(p,this.state.vector,ot)||(this.setState({vector:p}),this.handleDigitalKeys(p));}handleDigitalKeys(t){let i=this.config.threshold??rt;t.y<-i?(this.emitters.up.press(),this.emitters.down.release()):t.y>i?(this.emitters.down.press(),this.emitters.up.release()):(this.emitters.up.release(),this.emitters.down.release()),t.x<-i?(this.emitters.left.press(),this.emitters.right.release()):t.x>i?(this.emitters.right.press(),this.emitters.left.release()):(this.emitters.left.release(),this.emitters.right.release());}reset(){this.emitters.up.reset(),this.emitters.down.reset(),this.emitters.left.reset(),this.emitters.right.reset(),this.setState(st);}updateConfig(t){super.updateConfig(t),this.emitters.up.update(this.config.targetStageId,this.config.mapping?.up),this.emitters.down.update(this.config.targetStageId,this.config.mapping?.down),this.emitters.left.update(this.config.targetStageId,this.config.mapping?.left),this.emitters.right.update(this.config.targetStageId,this.config.mapping?.right);}triggerVector(t,i){let e=this.config.threshold??rt;if(Math.abs(t)<e&&Math.abs(i)<e){this.state.isActive&&this.reset();return}this.state.isActive||this.setState({isActive:true});let o=r(this.state.vector.x,t,nt),c=r(this.state.vector.y,i,nt),d={x:o,y:c};F$1(d,this.state.vector,ot)||(this.setState({vector:d}),this.handleDigitalKeys(d));}};var lt={isDynamicActive:false,dynamicPointerId:null,dynamicPosition:{x:0,y:0}},N=class extends g{constructor(t,i,e){super(t,e||b.INPUT_ZONE,i,lt);a$2(this,"delegates",{dynamicWidgetPointerDown:()=>{},dynamicWidgetPointerMove:()=>{},dynamicWidgetPointerUp:()=>{},dynamicWidgetPointerCancel:()=>{}});}bindDelegate(t,i){Object.prototype.hasOwnProperty.call(this.delegates,t)?this.delegates[t]=i:import.meta.env?.DEV&&console.warn(`[OmniPad-Core] TargetZone attempted to bind unknown delegate: ${t}`);}get activePointerId(){return this.state.dynamicPointerId}onPointerDown(t){if(this.state.isDynamicActive)return;let i=this.calculateRelativePosition(t.clientX,t.clientY);this.setState({isDynamicActive:true,dynamicPointerId:t.pointerId,dynamicPosition:i}),this.delegates.dynamicWidgetPointerDown?.(t);}onPointerMove(t){this.state.isDynamicActive&&this.delegates.dynamicWidgetPointerMove?.(t);}onPointerUp(t){this.delegates.dynamicWidgetPointerUp?.(t),this.reset();}onPointerCancel(t){this.delegates.dynamicWidgetPointerCancel?.(t),this.reset();}calculateRelativePosition(t,i){let e=this.rect;return e?{x:B$1(t-e.left,e.width),y:B$1(i-e.top,e.height)}:{x:0,y:0}}get isInterceptorRequired(){return !!(this.config.dynamicWidgetId||this.config.preventFocusLoss)}reset(){this.setState({isDynamicActive:false,dynamicPointerId:null});}};var C=class{constructor(s={}){a$2(this,"options");a$2(this,"startTime",0);a$2(this,"startPos",{x:0,y:0});a$2(this,"lastTapTime",0);a$2(this,"hasMoved",false);a$2(this,"isDoubleTapHolding",false);this.options={tapTime:250,tapDistance:10,doubleTapGap:300,...s};}onPointerDown(s,t){let i=Date.now();this.startTime=i,this.startPos={x:s,y:t},this.hasMoved=false,i-this.lastTapTime<this.options.doubleTapGap?(this.isDoubleTapHolding=true,this.options.onDoubleTapHoldStart?.()):this.isDoubleTapHolding=false;}onPointerMove(s,t){this.hasMoved||Math.hypot(s-this.startPos.x,t-this.startPos.y)>this.options.tapDistance&&(this.hasMoved=true);}onPointerUp(){let s=Date.now(),t=s-this.startTime;this.isDoubleTapHolding?(this.isDoubleTapHolding=false,this.options.onDoubleTapHoldEnd?.(),this.lastTapTime=0):t<=this.options.tapTime&&!this.hasMoved&&(this.options.onTap?.(),s-this.lastTapTime<this.options.doubleTapGap?(this.options.onDoubleTap?.(),this.lastTapTime=0):this.lastTapTime=s);}reset(){this.isDoubleTapHolding&&this.options.onDoubleTapHoldEnd?.(),this.isDoubleTapHolding=false,this.hasMoved=false,this.startTime=0,this.lastTapTime=0;}};var at={isActive:false,isPressed:false,pointerId:null,value:0,vector:{x:0,y:0}},Y=.15,U=.002,ct=.3,H=class extends g{constructor(t,i,e){super(t,e||b.JOYSTICK,i,at);a$2(this,"emitters");a$2(this,"stickEmitter");a$2(this,"cursorEmitter");a$2(this,"gesture");a$2(this,"ticker");let o=i.targetStageId,c=i.mapping||{};this.emitters={up:new m(o,c.up),down:new m(o,c.down),left:new m(o,c.left),right:new m(o,c.right)},this.stickEmitter=new m(o,c.stick),this.cursorEmitter=new m(o,"Mouse"),this.gesture=new C({onTap:async()=>{this.setState({isPressed:true}),await this.stickEmitter.tap(),this.setState({isPressed:false});},onDoubleTapHoldStart:()=>{this.setState({isPressed:true}),this.stickEmitter.press();},onDoubleTapHoldEnd:()=>{this.setState({isPressed:false}),this.stickEmitter.release(false);}}),this.ticker=f$1(()=>{this.handleCursorTick();});}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.setState({isActive:true,pointerId:t.pointerId,vector:{x:0,y:0}}),this.gesture.onPointerDown(t.clientX,t.clientY),this.processInput(t,true);}onPointerMove(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerMove(t.clientX,t.clientY),this.config.cursorMode&&this.ticker.start(),this.processInput(t));}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerUp(),this.handleRelease());}onPointerCancel(){this.handleRelease();}handleRelease(){this.setState({isActive:false,pointerId:null,vector:{x:0,y:0}}),this.ticker.stop(),Object.values(this.emitters).forEach(t=>t?.reset());}processInput(t,i=false){if(!this.state.isActive)return;let e=this.rect;if(!e)return;let o=e.left+e.width/2,c=e.top+e.height/2,d=e.width/2,h=e.height/2,f=(t.clientX-o)/d,r=(t.clientY-c)/h;if(i&&(f!=q(f,-1,1)||r!=q(r,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let u=H$1({x:f,y:r},1,this.config.threshold??Y);F$1(u,this.state.vector,U)||(this.setState({vector:u}),this.handleDigitalKeys(u));}handleCursorTick(){let{vector:t,isActive:i}=this.state;if(!i||!this.config.cursorMode||F$1(t,{x:0,y:0},U)){this.ticker.stop();return}let e=this.config.cursorSensitivity??1,o={x:t.x*Math.abs(t.x)*e,y:t.y*Math.abs(t.y)*e};(Math.abs(o.x)>0||Math.abs(o.y)>0)&&this.cursorEmitter.move({delta:o});}handleDigitalKeys(t){let i=this.config.threshold??Y;t.y<-i?(this.emitters.up.press(),this.emitters.down.release()):t.y>i?(this.emitters.down.press(),this.emitters.up.release()):(this.emitters.up.release(),this.emitters.down.release()),t.x<-i?(this.emitters.left.press(),this.emitters.right.release()):t.x>i?(this.emitters.right.press(),this.emitters.left.release()):(this.emitters.left.release(),this.emitters.right.release());}reset(){this.setState(at),this.gesture.reset(),this.handleRelease(),this.stickEmitter.reset(),this.cursorEmitter.reset();}updateConfig(t){super.updateConfig(t);let i=this.config.targetStageId,e=this.config.mapping||{};this.emitters.up.update(i,e.up),this.emitters.down.update(i,e.down),this.emitters.left.update(i,e.left),this.emitters.right.update(i,e.right),this.stickEmitter.update(i,e.stick),this.cursorEmitter.update(i);}triggerDown(){this.state.isPressed||(this.setState({isActive:true,isPressed:true}),this.stickEmitter.press());}triggerUp(){this.state.isPressed&&(this.setState({isActive:false,isPressed:false}),this.stickEmitter.release(true));}triggerVector(t,i){let e=this.config.threshold??Y;if(Math.hypot(t,i)<e){this.state.isActive&&this.handleRelease();return}this.state.isActive||this.setState({isActive:true});let c=r(this.state.vector.x,t,ct),d=r(this.state.vector.y,i,ct),h={x:c,y:d};F$1(h,this.state.vector,U)||(this.setState({vector:h}),this.handleDigitalKeys(h)),this.config.cursorMode&&this.ticker.start();}};var ut={isHighlighted:false},F=class extends g{constructor(s,t,i){super(s,i||b.ROOT_LAYER,t,ut);}reset(){}};var ht={position:{x:50,y:50},isVisible:false,isPointerDown:false,isFocusReturning:false},E=1,_=class extends g{constructor(t,i,e){super(t,e||b.TARGET_ZONE,i,ht);a$2(this,"hideTimer",null);a$2(this,"focusFeedbackTimer",null);a$2(this,"throttledMoveExecution");a$2(this,"delegates",{dispatchKeyboardEvent:()=>{},dispatchPointerEventAtPos:()=>{},reclaimFocusAtPos:()=>{}});this.throttledMoveExecution=e$1(o=>{this.executeMouseAction(c.POINTERMOVE,o);});}bindDelegate(t,i){Object.prototype.hasOwnProperty.call(this.delegates,t)?this.delegates[t]=i:import.meta.env?.DEV&&console.warn(`[OmniPad-Core] TargetZone attempted to bind unknown delegate: ${t}`);}get activePointerId(){return null}onPointerDown(t){this.processPhysicalEvent(t,c.MOUSEDOWN);}onPointerMove(t){this.processPhysicalEvent(t,c.MOUSEMOVE);}onPointerUp(t){this.processPhysicalEvent(t,c.MOUSEUP),this.processPhysicalEvent(t,c.CLICK);}onPointerCancel(t){this.processPhysicalEvent(t,c.MOUSEUP);}processPhysicalEvent(t,i){let e=this.rect;if(!e)return;let o={x:B$1(t.clientX-e.left,e.width),y:B$1(t.clientY-e.top,e.height)};this.handleSignal({targetStageId:this.uid,type:i,payload:{point:o,button:t.button}});}handleSignal(t){let{type:i,payload:e}=t;switch(this.ensureFocus(),i){case c.KEYDOWN:case c.KEYUP:this.delegates.dispatchKeyboardEvent?.(i,e);break;case c.MOUSEMOVE:e.point?this.updateCursorPosition(e.point):e.delta&&this.updateCursorPositionByDelta(e.delta),this.config.cursorEnabled&&this.showCursor(),this.throttledMoveExecution(e);break;case c.MOUSEDOWN:case c.MOUSEUP:case c.CLICK:e.point&&this.updateCursorPosition(e.point),this.config.cursorEnabled&&this.showCursor(),this.executeMouseAction(i.startsWith(c.MOUSE)?i.replace(c.MOUSE,c.POINTER):i,e);break}}executeMouseAction(t,i){let e=this.rect;if(!e)return;t===c.POINTERDOWN&&this.setState({isPointerDown:true}),t===c.POINTERUP&&this.setState({isPointerDown:false});let o=i.point||this.state.position,c$1=q(e.left+A(o.x,e.width),e.left+E,e.left+e.width-E),d=q(e.top+A(o.y,e.height),e.top+E,e.top+e.height-E);this.delegates.dispatchPointerEventAtPos?.(t,c$1,d,{button:i.button??0,buttons:this.state.isPointerDown?1:0,pressure:this.state.isPointerDown?.5:0});}ensureFocus(){let t=this.rect;if(!t)return;let i=q(t.left+A(this.state.position.x,t.width),t.left+E,t.left+t.width-E),e=q(t.top+A(this.state.position.y,t.height),t.top+E,t.top+t.height-E);this.delegates.reclaimFocusAtPos?.(i,e,()=>this.triggerFocusFeedback());}triggerFocusFeedback(){this.setState({isFocusReturning:true}),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.focusFeedbackTimer=setTimeout(()=>this.setState({isFocusReturning:false}),500);}updateCursorPosition(t){F$1(t,this.state.position)||this.setState({position:{...t}});}updateCursorPositionByDelta(t){if(F$1(t,{x:0,y:0}))return;let i=this.rect;if(!i)return;let e=B$1(t.x,i.width),o=B$1(t.y,i.height);this.updateCursorPosition({x:q(this.state.position.x+e,0,100),y:q(this.state.position.y+o,0,100)});}showCursor(){this.setState({isVisible:true}),this.hideTimer&&clearTimeout(this.hideTimer),this.config.cursorAutoDelay&&this.config.cursorAutoDelay>0&&(this.hideTimer=setTimeout(()=>this.setState({isVisible:false}),this.config.cursorAutoDelay));}reset(){this.state.isPointerDown&&this.executeMouseAction(c.POINTERUP,{}),this.hideTimer&&clearTimeout(this.hideTimer),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.setState({isVisible:false,isPointerDown:false,isFocusReturning:false});}};var pt={isActive:false,isPressed:false,pointerId:null,value:0},B=class extends g{constructor(t,i,e){super(t,e||b.TRACKPAD,i,pt);a$2(this,"lastPointerPos",{x:0,y:0});a$2(this,"gesture");a$2(this,"emitter");let o=i.mapping||"Mouse";this.emitter=new m(i.targetStageId,o),this.gesture=new C({onTap:()=>{this.setState({isPressed:true}),this.emitter.tap();},onDoubleTapHoldStart:()=>{this.setState({isPressed:true}),this.emitter.press();},onDoubleTapHoldEnd:()=>{this.setState({isPressed:false}),this.emitter.release(false);}});}get activePointerId(){return this.state.pointerId}onPointerDown(t){this.lastPointerPos={x:t.clientX,y:t.clientY},this.gesture.onPointerDown(t.clientX,t.clientY),this.setState({isActive:true,pointerId:t.pointerId});}onPointerMove(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerMove(t.clientX,t.clientY),this.processInput(t));}processInput(t){if(!this.state.isActive)return;let i=t.clientX-this.lastPointerPos.x,e=t.clientY-this.lastPointerPos.y,o=this.rect;if(!o)return;let c=i/o.width*100*(this.config.sensitivity??1),d=e/o.height*100*(this.config.sensitivity??1),h={x:c,y:d};F$1(h,{x:0,y:0})||this.emitter.move({delta:h}),this.lastPointerPos={x:t.clientX,y:t.clientY};}onPointerUp(t){!this.state.isActive||t.pointerId!==this.state.pointerId||(this.gesture.onPointerUp(),this.handleRelease());}onPointerCancel(){this.handleRelease();}reset(){this.gesture.reset(),this.emitter.reset(),this.handleRelease();}updateConfig(t){super.updateConfig(t),this.emitter.update(this.config.targetStageId,this.config.mapping);}handleRelease(){this.setState(pt);}};var di={ActionTypes:c,Context:e,Keys:a,Types:b};export{g as BaseEntity,O as ButtonCore,R as DPadCore,N as InputZoneCore,H as JoystickCore,di as OmniPad,F as RootLayerCore,_ as TargetZoneCore,B as TrackpadCore,Tt as bindEntityDelegates,Yt as exportProfile,It as filterNotDynamicChildren,St as getOverrideProps,Ct as mergeWidgetConfig,Rt as parseProfileJson,Nt as parseProfileTrees,At as resolveDynamicWidget,Et as setupSpatialLogic,Dt as validateWidgetNode};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { E as EntityType, a as AbstractRect, c as AbstractPointerEvent, A as AnyFunction, I as InputActionSignal } from './index-Dd0aHJaA.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface for the global ElementObserver singleton.
|
|
5
|
+
*/
|
|
6
|
+
interface IElementObserver<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Starts observing size changes for a specific element.
|
|
9
|
+
*
|
|
10
|
+
* @param uid - The unique entity ID associated with the observation.
|
|
11
|
+
* @param el - The target element to observe.
|
|
12
|
+
* @param cb - Callback triggered when the element's size changes.
|
|
13
|
+
*/
|
|
14
|
+
observeResize(uid: string, el: T, cb: () => void): void;
|
|
15
|
+
/**
|
|
16
|
+
* Stops observing size changes for the entity identified by the UID.
|
|
17
|
+
*
|
|
18
|
+
* @param uid - The unique entity ID to unregister.
|
|
19
|
+
*/
|
|
20
|
+
unobserveResize(uid: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Starts observing visibility (intersection) changes for a specific element.
|
|
23
|
+
*
|
|
24
|
+
* @param uid - The unique entity ID associated with the observation.
|
|
25
|
+
* @param el - The target element to observe.
|
|
26
|
+
* @param cb - Callback triggered when visibility enters or exits the viewport.
|
|
27
|
+
*/
|
|
28
|
+
observeIntersect(uid: string, el: T, cb: (isIntersecting: boolean) => void): void;
|
|
29
|
+
/**
|
|
30
|
+
* Stops observing intersection changes for the entity identified by the UID.
|
|
31
|
+
*
|
|
32
|
+
* @param uid - The unique entity ID to unregister.
|
|
33
|
+
*/
|
|
34
|
+
unobserveIntersect(uid: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Disconnects all observers (RO and IO) associated with a specific UID.
|
|
37
|
+
* Usually called during component destruction for thorough cleanup.
|
|
38
|
+
*
|
|
39
|
+
* @param uid - The unique entity ID to fully disconnect.
|
|
40
|
+
*/
|
|
41
|
+
disconnect(uid: string): void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Trait: Provides identity with a unique ID and specific entity type.
|
|
46
|
+
*/
|
|
47
|
+
interface IIdentifiable {
|
|
48
|
+
readonly uid: string;
|
|
49
|
+
readonly type: EntityType;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Trait: Provides lifecycle management hooks.
|
|
53
|
+
*/
|
|
54
|
+
interface ILifecycle {
|
|
55
|
+
/**
|
|
56
|
+
* Performs cleanup, unregisters the entity, and releases resources.
|
|
57
|
+
*/
|
|
58
|
+
destroy(): void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The core contract for any object that can be managed by the Registry.
|
|
62
|
+
* Only objects implementing this interface are eligible for registration.
|
|
63
|
+
*/
|
|
64
|
+
interface ICoreEntity extends IIdentifiable, ILifecycle {
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Trait: Enables spatial awareness for DOM/UI-related components.
|
|
68
|
+
*/
|
|
69
|
+
interface ISpatial {
|
|
70
|
+
readonly rect: AbstractRect | null;
|
|
71
|
+
/**
|
|
72
|
+
* Dynamically obtain dimensions and position to ensure the most precise real-time screen coordinates are obtained during each interaction.
|
|
73
|
+
*/
|
|
74
|
+
bindRectProvider(provider: () => AbstractRect, onMarkDirty?: () => void): void;
|
|
75
|
+
/**
|
|
76
|
+
* Trigger a cache invalidation.
|
|
77
|
+
*/
|
|
78
|
+
markRectDirty(): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Trait: Provides configuration management.
|
|
82
|
+
*/
|
|
83
|
+
interface IConfigurable<TConfig> {
|
|
84
|
+
/**
|
|
85
|
+
* Retrieves a snapshot of the current configuration.
|
|
86
|
+
*/
|
|
87
|
+
getConfig(): TConfig;
|
|
88
|
+
/**
|
|
89
|
+
* Subscribes to config changes.
|
|
90
|
+
* @param cb - Callback function triggered on config updates.
|
|
91
|
+
* @returns An unsubscribe function.
|
|
92
|
+
*/
|
|
93
|
+
subscribeConfig(cb: (config: TConfig) => void): () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Updates the internal config and notifies all subscribers.
|
|
96
|
+
* @param config - Partial configuration object to merge.
|
|
97
|
+
*/
|
|
98
|
+
updateConfig(config: Partial<TConfig>): void;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Trait: Provides state management.
|
|
102
|
+
*/
|
|
103
|
+
interface IStateful<TState> {
|
|
104
|
+
/**
|
|
105
|
+
* Retrieves the current state snapshot.
|
|
106
|
+
*/
|
|
107
|
+
getState(): TState;
|
|
108
|
+
/**
|
|
109
|
+
* Subscribes to state changes.
|
|
110
|
+
* @param cb - Callback function triggered on state updates.
|
|
111
|
+
* @returns An unsubscribe function.
|
|
112
|
+
*/
|
|
113
|
+
subscribeState(cb: (state: TState) => void): () => void;
|
|
114
|
+
/**
|
|
115
|
+
* Updates the internal state and notifies all subscribers.
|
|
116
|
+
* @param state - Partial object containing updated state values.
|
|
117
|
+
*/
|
|
118
|
+
setState(state: Partial<TState>): void;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Trait: Allows resetting the entity to its idle/safe state.
|
|
122
|
+
*/
|
|
123
|
+
interface IResettable {
|
|
124
|
+
/**
|
|
125
|
+
* Forcefully clears active states and cuts off outgoing signals.
|
|
126
|
+
*/
|
|
127
|
+
reset(): void;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Trait: Handles raw pointer input (Touch/Mouse).
|
|
131
|
+
*/
|
|
132
|
+
interface IPointerHandler {
|
|
133
|
+
readonly activePointerId: number | null;
|
|
134
|
+
onPointerDown(e: AbstractPointerEvent): void;
|
|
135
|
+
onPointerMove(e: AbstractPointerEvent): void;
|
|
136
|
+
onPointerUp(e: AbstractPointerEvent): void;
|
|
137
|
+
onPointerCancel(e: AbstractPointerEvent): void;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Trait: Receives and processes input signals (e.g., TargetZone).
|
|
141
|
+
*/
|
|
142
|
+
interface ISignalReceiver {
|
|
143
|
+
/**
|
|
144
|
+
* Handles incoming signals from widgets.
|
|
145
|
+
* @param signal - The signal data containing action type and payload.
|
|
146
|
+
*/
|
|
147
|
+
handleSignal(signal: InputActionSignal): void;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Capability for an entity to receive and store external functional dependencies.
|
|
151
|
+
*
|
|
152
|
+
* This enables Runtime Dependency Injection (DI), allowing core logic to invoke
|
|
153
|
+
* host-specific methods (such as DOM event dispatchers or custom triggers)
|
|
154
|
+
* without being tightly coupled to the environment.
|
|
155
|
+
*/
|
|
156
|
+
interface IDependencyBindable {
|
|
157
|
+
/**
|
|
158
|
+
* Binds a functional delegate by a specific identifier key.
|
|
159
|
+
*
|
|
160
|
+
* @param key - The unique lookup identifier for the dependency (e.g., 'domDispatcher').
|
|
161
|
+
* @param delegate - The function implementation provided by the adapter layer.
|
|
162
|
+
*/
|
|
163
|
+
bindDelegate(key: string, delegate: AnyFunction): void;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Contract for widgets that support programmatic control.
|
|
167
|
+
*
|
|
168
|
+
* This interface allows external systems—such as a Physical Gamepad Manager or
|
|
169
|
+
* automation scripts—to directly drive the state and behavior of a widget,
|
|
170
|
+
* bypassing native DOM pointer events.
|
|
171
|
+
*/
|
|
172
|
+
interface IProgrammatic {
|
|
173
|
+
/**
|
|
174
|
+
* Manually triggers the 'down' (pressed) state of the widget.
|
|
175
|
+
* Primarily used for Button-type components to simulate a physical press.
|
|
176
|
+
*/
|
|
177
|
+
triggerDown?(): void;
|
|
178
|
+
/**
|
|
179
|
+
* Manually triggers the 'up' (released) state of the widget.
|
|
180
|
+
* Primarily used for Button-type components to simulate a physical release.
|
|
181
|
+
*/
|
|
182
|
+
triggerUp?(): void;
|
|
183
|
+
/**
|
|
184
|
+
* Manually updates the directional input vector of the widget.
|
|
185
|
+
* Primarily used for Joystick or D-Pad components.
|
|
186
|
+
*
|
|
187
|
+
* @param x - The horizontal component, normalized between -1.0 and 1.0.
|
|
188
|
+
* @param y - The vertical component, normalized between -1.0 and 1.0.
|
|
189
|
+
*/
|
|
190
|
+
triggerVector?(x: number, y: number): void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Headless Sticky Provider.
|
|
195
|
+
* Manages reference coordinate tracking without direct DOM dependency.
|
|
196
|
+
*
|
|
197
|
+
* It relies on an externally injected 'finder' function to resolve
|
|
198
|
+
* the reference object and a 'rectProvider' to get its dimensions.
|
|
199
|
+
*/
|
|
200
|
+
declare class StickyProvider<T> {
|
|
201
|
+
private finder;
|
|
202
|
+
private rectProvider;
|
|
203
|
+
private presenceChecker;
|
|
204
|
+
private _selector;
|
|
205
|
+
private _cachedTarget;
|
|
206
|
+
private _rectCache;
|
|
207
|
+
/**
|
|
208
|
+
* @param selector - The selector (e.g. selector) of the reference.
|
|
209
|
+
* @param finder - A function that resolves the selector to a physical object.
|
|
210
|
+
* @param rectProvider - A function that returns the bounds of the resolved object.
|
|
211
|
+
* @param presenceChecker - A function to check if the target is still valid/attached.
|
|
212
|
+
*/
|
|
213
|
+
constructor(selector: string, finder: (id: string) => T, rectProvider: (target: T) => AbstractRect | null, presenceChecker: (target: T) => boolean);
|
|
214
|
+
/**
|
|
215
|
+
* Resolves and returns the target object.
|
|
216
|
+
*/
|
|
217
|
+
getTarget(): T | null;
|
|
218
|
+
/**
|
|
219
|
+
* Returns the current Rect of the sticky target.
|
|
220
|
+
* Uses internal cache to prevent layout thrashing.
|
|
221
|
+
*/
|
|
222
|
+
getRect(): AbstractRect | null;
|
|
223
|
+
/**
|
|
224
|
+
* Invalidates the current Rect cache.
|
|
225
|
+
* Should be called during window resize, scroll, or manual re-alignments.
|
|
226
|
+
*/
|
|
227
|
+
markDirty(): void;
|
|
228
|
+
/**
|
|
229
|
+
* Updates the selector and clears the current element cache.
|
|
230
|
+
*
|
|
231
|
+
* @param newSelector - The new CSS selector.
|
|
232
|
+
* @returns Whether the selector is updated.
|
|
233
|
+
*/
|
|
234
|
+
updateSelector(newSelector: string): boolean;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Orchestrates the "sticky" layout logic for an entity.
|
|
238
|
+
*
|
|
239
|
+
* It manages the lifecycle of a StickyProvider and synchronizes spatial
|
|
240
|
+
* updates (Resize/Intersection) between a physical DOM target and the
|
|
241
|
+
* logical Core entity.
|
|
242
|
+
*
|
|
243
|
+
* @template T - The type of the physical element (usually HTMLElement or Element).
|
|
244
|
+
*/
|
|
245
|
+
declare class StickyController<T> {
|
|
246
|
+
private observer;
|
|
247
|
+
private instance;
|
|
248
|
+
private onUpdate;
|
|
249
|
+
/**
|
|
250
|
+
* Creates an instance of StickyController.
|
|
251
|
+
*
|
|
252
|
+
* @param observer - The unified observer singleton (RO/IO) to track the target.
|
|
253
|
+
* @param instance - The core entity instance which must support spatial awareness and resetting.
|
|
254
|
+
* @param onUpdate - Callback triggered when the layout needs to be re-synchronized (e.g., forcing a UI refresh).
|
|
255
|
+
*/
|
|
256
|
+
constructor(observer: IElementObserver<T>, instance: ICoreEntity & ISpatial & IResettable, onUpdate: () => void);
|
|
257
|
+
/**
|
|
258
|
+
* Generates a unique identifier for this controller's target element's internal observer registrations.
|
|
259
|
+
*/
|
|
260
|
+
get uid(): string;
|
|
261
|
+
/**
|
|
262
|
+
* Resolves the strategy for changing or initializing the sticky target.
|
|
263
|
+
*
|
|
264
|
+
* This method handles:
|
|
265
|
+
* 1. Teardown of old observers if the selector is removed.
|
|
266
|
+
* 2. Lazy initialization or hot-swapping of the StickyProvider.
|
|
267
|
+
* 3. Re-binding spatial and visibility observers to the new target.
|
|
268
|
+
*
|
|
269
|
+
* @param newSelector - The CSS selector of the target element to stick to.
|
|
270
|
+
* @param currentProvider - The current active StickyProvider instance, if any.
|
|
271
|
+
* @param factory - A factory function to create a new environment-specific StickyProvider (e.g., WebStickyProvider).
|
|
272
|
+
* @returns An object containing the resolved provider and a flag indicating if an update occurred.
|
|
273
|
+
*/
|
|
274
|
+
handleSelectorChange(newSelector: string | undefined, currentProvider: StickyProvider<T> | null, factory: (s: string) => StickyProvider<T>): {
|
|
275
|
+
provider: StickyProvider<T> | null;
|
|
276
|
+
updated: boolean;
|
|
277
|
+
};
|
|
278
|
+
/**
|
|
279
|
+
* Disconnects all observers and releases resources.
|
|
280
|
+
* Should be called when the host component is unmounted.
|
|
281
|
+
*/
|
|
282
|
+
onCleanUp(): void;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export { type ICoreEntity as I, StickyProvider as S, type IElementObserver as a, type ISpatial as b, type IResettable as c, type IConfigurable as d, type IStateful as e, type IPointerHandler as f, type IProgrammatic as g, type IDependencyBindable as h, type ISignalReceiver as i, type IIdentifiable as j, type ILifecycle as k, StickyController as l };
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { E as EntityType, a as AbstractRect, c as AbstractPointerEvent, A as AnyFunction, I as InputActionSignal } from './index-Dd0aHJaA.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface for the global ElementObserver singleton.
|
|
5
|
+
*/
|
|
6
|
+
interface IElementObserver<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Starts observing size changes for a specific element.
|
|
9
|
+
*
|
|
10
|
+
* @param uid - The unique entity ID associated with the observation.
|
|
11
|
+
* @param el - The target element to observe.
|
|
12
|
+
* @param cb - Callback triggered when the element's size changes.
|
|
13
|
+
*/
|
|
14
|
+
observeResize(uid: string, el: T, cb: () => void): void;
|
|
15
|
+
/**
|
|
16
|
+
* Stops observing size changes for the entity identified by the UID.
|
|
17
|
+
*
|
|
18
|
+
* @param uid - The unique entity ID to unregister.
|
|
19
|
+
*/
|
|
20
|
+
unobserveResize(uid: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Starts observing visibility (intersection) changes for a specific element.
|
|
23
|
+
*
|
|
24
|
+
* @param uid - The unique entity ID associated with the observation.
|
|
25
|
+
* @param el - The target element to observe.
|
|
26
|
+
* @param cb - Callback triggered when visibility enters or exits the viewport.
|
|
27
|
+
*/
|
|
28
|
+
observeIntersect(uid: string, el: T, cb: (isIntersecting: boolean) => void): void;
|
|
29
|
+
/**
|
|
30
|
+
* Stops observing intersection changes for the entity identified by the UID.
|
|
31
|
+
*
|
|
32
|
+
* @param uid - The unique entity ID to unregister.
|
|
33
|
+
*/
|
|
34
|
+
unobserveIntersect(uid: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Disconnects all observers (RO and IO) associated with a specific UID.
|
|
37
|
+
* Usually called during component destruction for thorough cleanup.
|
|
38
|
+
*
|
|
39
|
+
* @param uid - The unique entity ID to fully disconnect.
|
|
40
|
+
*/
|
|
41
|
+
disconnect(uid: string): void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Trait: Provides identity with a unique ID and specific entity type.
|
|
46
|
+
*/
|
|
47
|
+
interface IIdentifiable {
|
|
48
|
+
readonly uid: string;
|
|
49
|
+
readonly type: EntityType;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Trait: Provides lifecycle management hooks.
|
|
53
|
+
*/
|
|
54
|
+
interface ILifecycle {
|
|
55
|
+
/**
|
|
56
|
+
* Performs cleanup, unregisters the entity, and releases resources.
|
|
57
|
+
*/
|
|
58
|
+
destroy(): void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The core contract for any object that can be managed by the Registry.
|
|
62
|
+
* Only objects implementing this interface are eligible for registration.
|
|
63
|
+
*/
|
|
64
|
+
interface ICoreEntity extends IIdentifiable, ILifecycle {
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Trait: Enables spatial awareness for DOM/UI-related components.
|
|
68
|
+
*/
|
|
69
|
+
interface ISpatial {
|
|
70
|
+
readonly rect: AbstractRect | null;
|
|
71
|
+
/**
|
|
72
|
+
* Dynamically obtain dimensions and position to ensure the most precise real-time screen coordinates are obtained during each interaction.
|
|
73
|
+
*/
|
|
74
|
+
bindRectProvider(provider: () => AbstractRect, onMarkDirty?: () => void): void;
|
|
75
|
+
/**
|
|
76
|
+
* Trigger a cache invalidation.
|
|
77
|
+
*/
|
|
78
|
+
markRectDirty(): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Trait: Provides configuration management.
|
|
82
|
+
*/
|
|
83
|
+
interface IConfigurable<TConfig> {
|
|
84
|
+
/**
|
|
85
|
+
* Retrieves a snapshot of the current configuration.
|
|
86
|
+
*/
|
|
87
|
+
getConfig(): TConfig;
|
|
88
|
+
/**
|
|
89
|
+
* Subscribes to config changes.
|
|
90
|
+
* @param cb - Callback function triggered on config updates.
|
|
91
|
+
* @returns An unsubscribe function.
|
|
92
|
+
*/
|
|
93
|
+
subscribeConfig(cb: (config: TConfig) => void): () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Updates the internal config and notifies all subscribers.
|
|
96
|
+
* @param config - Partial configuration object to merge.
|
|
97
|
+
*/
|
|
98
|
+
updateConfig(config: Partial<TConfig>): void;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Trait: Provides state management.
|
|
102
|
+
*/
|
|
103
|
+
interface IStateful<TState> {
|
|
104
|
+
/**
|
|
105
|
+
* Retrieves the current state snapshot.
|
|
106
|
+
*/
|
|
107
|
+
getState(): TState;
|
|
108
|
+
/**
|
|
109
|
+
* Subscribes to state changes.
|
|
110
|
+
* @param cb - Callback function triggered on state updates.
|
|
111
|
+
* @returns An unsubscribe function.
|
|
112
|
+
*/
|
|
113
|
+
subscribeState(cb: (state: TState) => void): () => void;
|
|
114
|
+
/**
|
|
115
|
+
* Updates the internal state and notifies all subscribers.
|
|
116
|
+
* @param state - Partial object containing updated state values.
|
|
117
|
+
*/
|
|
118
|
+
setState(state: Partial<TState>): void;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Trait: Allows resetting the entity to its idle/safe state.
|
|
122
|
+
*/
|
|
123
|
+
interface IResettable {
|
|
124
|
+
/**
|
|
125
|
+
* Forcefully clears active states and cuts off outgoing signals.
|
|
126
|
+
*/
|
|
127
|
+
reset(): void;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Trait: Handles raw pointer input (Touch/Mouse).
|
|
131
|
+
*/
|
|
132
|
+
interface IPointerHandler {
|
|
133
|
+
readonly activePointerId: number | null;
|
|
134
|
+
onPointerDown(e: AbstractPointerEvent): void;
|
|
135
|
+
onPointerMove(e: AbstractPointerEvent): void;
|
|
136
|
+
onPointerUp(e: AbstractPointerEvent): void;
|
|
137
|
+
onPointerCancel(e: AbstractPointerEvent): void;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Trait: Receives and processes input signals (e.g., TargetZone).
|
|
141
|
+
*/
|
|
142
|
+
interface ISignalReceiver {
|
|
143
|
+
/**
|
|
144
|
+
* Handles incoming signals from widgets.
|
|
145
|
+
* @param signal - The signal data containing action type and payload.
|
|
146
|
+
*/
|
|
147
|
+
handleSignal(signal: InputActionSignal): void;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Capability for an entity to receive and store external functional dependencies.
|
|
151
|
+
*
|
|
152
|
+
* This enables Runtime Dependency Injection (DI), allowing core logic to invoke
|
|
153
|
+
* host-specific methods (such as DOM event dispatchers or custom triggers)
|
|
154
|
+
* without being tightly coupled to the environment.
|
|
155
|
+
*/
|
|
156
|
+
interface IDependencyBindable {
|
|
157
|
+
/**
|
|
158
|
+
* Binds a functional delegate by a specific identifier key.
|
|
159
|
+
*
|
|
160
|
+
* @param key - The unique lookup identifier for the dependency (e.g., 'domDispatcher').
|
|
161
|
+
* @param delegate - The function implementation provided by the adapter layer.
|
|
162
|
+
*/
|
|
163
|
+
bindDelegate(key: string, delegate: AnyFunction): void;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Contract for widgets that support programmatic control.
|
|
167
|
+
*
|
|
168
|
+
* This interface allows external systems—such as a Physical Gamepad Manager or
|
|
169
|
+
* automation scripts—to directly drive the state and behavior of a widget,
|
|
170
|
+
* bypassing native DOM pointer events.
|
|
171
|
+
*/
|
|
172
|
+
interface IProgrammatic {
|
|
173
|
+
/**
|
|
174
|
+
* Manually triggers the 'down' (pressed) state of the widget.
|
|
175
|
+
* Primarily used for Button-type components to simulate a physical press.
|
|
176
|
+
*/
|
|
177
|
+
triggerDown?(): void;
|
|
178
|
+
/**
|
|
179
|
+
* Manually triggers the 'up' (released) state of the widget.
|
|
180
|
+
* Primarily used for Button-type components to simulate a physical release.
|
|
181
|
+
*/
|
|
182
|
+
triggerUp?(): void;
|
|
183
|
+
/**
|
|
184
|
+
* Manually updates the directional input vector of the widget.
|
|
185
|
+
* Primarily used for Joystick or D-Pad components.
|
|
186
|
+
*
|
|
187
|
+
* @param x - The horizontal component, normalized between -1.0 and 1.0.
|
|
188
|
+
* @param y - The vertical component, normalized between -1.0 and 1.0.
|
|
189
|
+
*/
|
|
190
|
+
triggerVector?(x: number, y: number): void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Headless Sticky Provider.
|
|
195
|
+
* Manages reference coordinate tracking without direct DOM dependency.
|
|
196
|
+
*
|
|
197
|
+
* It relies on an externally injected 'finder' function to resolve
|
|
198
|
+
* the reference object and a 'rectProvider' to get its dimensions.
|
|
199
|
+
*/
|
|
200
|
+
declare class StickyProvider<T> {
|
|
201
|
+
private finder;
|
|
202
|
+
private rectProvider;
|
|
203
|
+
private presenceChecker;
|
|
204
|
+
private _selector;
|
|
205
|
+
private _cachedTarget;
|
|
206
|
+
private _rectCache;
|
|
207
|
+
/**
|
|
208
|
+
* @param selector - The selector (e.g. selector) of the reference.
|
|
209
|
+
* @param finder - A function that resolves the selector to a physical object.
|
|
210
|
+
* @param rectProvider - A function that returns the bounds of the resolved object.
|
|
211
|
+
* @param presenceChecker - A function to check if the target is still valid/attached.
|
|
212
|
+
*/
|
|
213
|
+
constructor(selector: string, finder: (id: string) => T, rectProvider: (target: T) => AbstractRect | null, presenceChecker: (target: T) => boolean);
|
|
214
|
+
/**
|
|
215
|
+
* Resolves and returns the target object.
|
|
216
|
+
*/
|
|
217
|
+
getTarget(): T | null;
|
|
218
|
+
/**
|
|
219
|
+
* Returns the current Rect of the sticky target.
|
|
220
|
+
* Uses internal cache to prevent layout thrashing.
|
|
221
|
+
*/
|
|
222
|
+
getRect(): AbstractRect | null;
|
|
223
|
+
/**
|
|
224
|
+
* Invalidates the current Rect cache.
|
|
225
|
+
* Should be called during window resize, scroll, or manual re-alignments.
|
|
226
|
+
*/
|
|
227
|
+
markDirty(): void;
|
|
228
|
+
/**
|
|
229
|
+
* Updates the selector and clears the current element cache.
|
|
230
|
+
*
|
|
231
|
+
* @param newSelector - The new CSS selector.
|
|
232
|
+
* @returns Whether the selector is updated.
|
|
233
|
+
*/
|
|
234
|
+
updateSelector(newSelector: string): boolean;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Orchestrates the "sticky" layout logic for an entity.
|
|
238
|
+
*
|
|
239
|
+
* It manages the lifecycle of a StickyProvider and synchronizes spatial
|
|
240
|
+
* updates (Resize/Intersection) between a physical DOM target and the
|
|
241
|
+
* logical Core entity.
|
|
242
|
+
*
|
|
243
|
+
* @template T - The type of the physical element (usually HTMLElement or Element).
|
|
244
|
+
*/
|
|
245
|
+
declare class StickyController<T> {
|
|
246
|
+
private observer;
|
|
247
|
+
private instance;
|
|
248
|
+
private onUpdate;
|
|
249
|
+
/**
|
|
250
|
+
* Creates an instance of StickyController.
|
|
251
|
+
*
|
|
252
|
+
* @param observer - The unified observer singleton (RO/IO) to track the target.
|
|
253
|
+
* @param instance - The core entity instance which must support spatial awareness and resetting.
|
|
254
|
+
* @param onUpdate - Callback triggered when the layout needs to be re-synchronized (e.g., forcing a UI refresh).
|
|
255
|
+
*/
|
|
256
|
+
constructor(observer: IElementObserver<T>, instance: ICoreEntity & ISpatial & IResettable, onUpdate: () => void);
|
|
257
|
+
/**
|
|
258
|
+
* Generates a unique identifier for this controller's target element's internal observer registrations.
|
|
259
|
+
*/
|
|
260
|
+
get uid(): string;
|
|
261
|
+
/**
|
|
262
|
+
* Resolves the strategy for changing or initializing the sticky target.
|
|
263
|
+
*
|
|
264
|
+
* This method handles:
|
|
265
|
+
* 1. Teardown of old observers if the selector is removed.
|
|
266
|
+
* 2. Lazy initialization or hot-swapping of the StickyProvider.
|
|
267
|
+
* 3. Re-binding spatial and visibility observers to the new target.
|
|
268
|
+
*
|
|
269
|
+
* @param newSelector - The CSS selector of the target element to stick to.
|
|
270
|
+
* @param currentProvider - The current active StickyProvider instance, if any.
|
|
271
|
+
* @param factory - A factory function to create a new environment-specific StickyProvider (e.g., WebStickyProvider).
|
|
272
|
+
* @returns An object containing the resolved provider and a flag indicating if an update occurred.
|
|
273
|
+
*/
|
|
274
|
+
handleSelectorChange(newSelector: string | undefined, currentProvider: StickyProvider<T> | null, factory: (s: string) => StickyProvider<T>): {
|
|
275
|
+
provider: StickyProvider<T> | null;
|
|
276
|
+
updated: boolean;
|
|
277
|
+
};
|
|
278
|
+
/**
|
|
279
|
+
* Disconnects all observers and releases resources.
|
|
280
|
+
* Should be called when the host component is unmounted.
|
|
281
|
+
*/
|
|
282
|
+
onCleanUp(): void;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export { type ICoreEntity as I, StickyProvider as S, type IElementObserver as a, type ISpatial as b, type IResettable as c, type IConfigurable as d, type IStateful as e, type IPointerHandler as f, type IProgrammatic as g, type IDependencyBindable as h, type ISignalReceiver as i, type IIdentifiable as j, type ILifecycle as k, StickyController as l };
|