@omnipad/core 0.4.4 → 0.5.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/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { I as ICoreEntity, V as Vec2, G as GamepadMappingConfig, a as ISpatial, b as IResettable, c as IConfigurable, d as IStateful, E as EntityType, A as AbstractRect, B as ButtonConfig, e as IPointerHandler, f as IProgrammatic, g as AbstractPointerEvent, D as DPadConfig, h as InputZoneConfig, i as IDependencyBindable, j as AnyFunction, J as JoystickConfig, k as BaseConfig, T as TargetZoneConfig, l as ISignalReceiver, m as InputActionSignal, n as TrackpadConfig } from './index-CTJog5sj.js';
2
- export { o as ACTION_TYPES, p as ActionMapping, q as AnchorPoint, r as AnyConfig, s as AnyEntityType, t as BuiltInActionType, C as CMP_TYPES, u as CONTEXT, v as ConfigTreeNode, w as CssUnit, F as FlatConfigItem, x as FlexibleLength, y as GamepadProfile, z as IIdentifiable, H as ILifecycle, K as InputActionType, L as KEYS, M as KeyMapping, N as LayoutBox, P as ParsedLength, S as StageId, O as StandardButton, Q as VALID_UNITS, W as WidgetId, R as WidgetType, Z as ZoneId, U as ZoneType } from './index-CTJog5sj.js';
1
+ import { I as InputActionSignal, V as Vec2, E as EntityType, A as AbstractRect, B as ButtonConfig, a as AbstractPointerEvent, D as DPadConfig, b as InputZoneConfig, c as AnyFunction, J as JoystickConfig, d as BaseConfig, T as TargetZoneConfig, e as TrackpadConfig } from './index-DVegtw8s.js';
2
+ export { f as ACTION_TYPES, g as ActionMapping, h as AnchorPoint, i as AnyConfig, j as AnyEntityType, k as BuiltInActionType, C as CMP_TYPES, l as CONTEXT, m as ConfigTreeNode, n as CssUnit, F as FlatConfigItem, o as FlexibleLength, G as GamepadMappingConfig, p as InputActionType, K as KEYS, q as KeyMapping, L as LayoutBox, O as OmniPadProfile, P as ParsedLength, S as StageId, r as StandardButton, s as VALID_UNITS, W as WidgetId, t as WidgetType, Z as ZoneId, u as ZoneType } from './index-DVegtw8s.js';
3
+ import { I as ICoreEntity, a as ISpatial, b as IResettable, c as IConfigurable, d as IStateful, e as IPointerHandler, f as IProgrammatic, g as IDependencyBindable, h as ISignalReceiver } from './traits-dAndzyWS.js';
4
+ export { i as IIdentifiable, j as ILifecycle } from './traits-dAndzyWS.js';
3
5
 
4
6
  /**
5
7
  * Interface for the global Registry singleton.
@@ -55,11 +57,26 @@ interface IRegistry {
55
57
  * Essential for cutting off active input signals (e.g., stuck keys) during profile reloads.
56
58
  */
57
59
  resetAll(): void;
60
+ /**
61
+ * Triggers the markRectDirty() method on all compatible entities.
62
+ * Essential for calibrating logical position during window resizes or scrolls.
63
+ */
64
+ markAllRectDirty(): void;
58
65
  /**
59
66
  * Clears all registered entities.
60
67
  * Used for system resets or full application unmounts.
61
68
  */
62
69
  clear(): void;
70
+ /**
71
+ * Dispatches an input action signal to a specific target entity or a global handler.
72
+ *
73
+ * @param signal - The action signal object containing the target ID and payload data.
74
+ * @example
75
+ * ```typescript
76
+ * dispatcher.broadcastSignal({ targetStageId: 'player_1', type: 'KEYDOWN' });
77
+ * ```
78
+ */
79
+ broadcastSignal(signal: InputActionSignal): void;
63
80
  }
64
81
 
65
82
  /**
@@ -156,68 +173,17 @@ interface JoystickState extends InteractionState, AxisLogicState, ButtonLogicSta
156
173
  }
157
174
 
158
175
  /**
159
- * GamepadManager
160
- *
161
- * A singleton service that polls the browser Gamepad API via requestAnimationFrame.
162
- * It translates physical hardware inputs into programmatic signals sent to
163
- * virtual entities registered in the system.
176
+ * Configures the global fallback handler for action signals.
164
177
  *
165
- * Handles:
166
- * 1. Button edge detection (Down/Up).
167
- * 2. D-Pad to vector conversion.
168
- * 3. Analog stick deadzone processing.
178
+ * @param handler - A callback function that processes signals when no specific
179
+ * entity target is found.
180
+ * @example
181
+ * ```typescript
182
+ * // In a browser environment:
183
+ * setGlobalSignalHandler((signal) => window.postMessage(signal, '*'));
184
+ * ```
169
185
  */
170
- declare class GamepadManager {
171
- private isRunning;
172
- private config;
173
- private lastButtonStates;
174
- private constructor();
175
- /**
176
- * Retrieves the global singleton instance of the GamepadManager.
177
- */
178
- static getInstance(): GamepadManager;
179
- /**
180
- * Updates the current gamepad mapping configuration.
181
- *
182
- * @param config - The mapping of physical inputs to virtual component IDs (UID).
183
- */
184
- setConfig(config: GamepadMappingConfig[]): void;
185
- /** Return the current gamepad mapping configuration. */
186
- getConfig(): Readonly<GamepadMappingConfig[] | null>;
187
- /**
188
- * Starts the polling loop and listens for gamepad connection events.
189
- */
190
- start(): void;
191
- /**
192
- * Stops the polling loop.
193
- */
194
- stop(): void;
195
- /**
196
- * The core polling loop executing at the browser's refresh rate.
197
- */
198
- private loop;
199
- /**
200
- * Process binary button inputs with edge detection.
201
- */
202
- private processButtons;
203
- /**
204
- * Translates physical D-Pad buttons into a normalized vector.
205
- */
206
- private processDPad;
207
- /**
208
- * Process analog stick movements with deadzone logic.
209
- */
210
- private processAxes;
211
- /**
212
- * Locates a virtual entity and triggers its programmatic interface.
213
- *
214
- * @param uid - The Entity ID (UID) of the target.
215
- * @param action - The type of trigger ('down', 'up', or 'vector').
216
- * @param payload - Optional data for vector movements.
217
- */
218
- private triggerVirtualEntity;
219
- }
220
-
186
+ declare function setGlobalSignalHandler(handler: (signal: InputActionSignal) => void): void;
221
187
  /**
222
188
  * Global Registry Singleton.
223
189
  *
@@ -245,52 +211,8 @@ declare class Registry implements IRegistry {
245
211
  destroyByRoot(rootUid: string): void;
246
212
  clear(): void;
247
213
  resetAll(): void;
248
- debugGetSnapshot(): Map<string, ICoreEntity>;
249
- }
250
-
251
- /**
252
- * Global Input Manager Singleton.
253
- *
254
- * Responsible for monitoring global browser events (resize, blur, visibility)
255
- * and coordinating system-wide resets to prevent stuck inputs.
256
- */
257
- declare class WindowManager {
258
- /** Internal flag to prevent multiple event registrations */
259
- private _isListening;
260
- /** A throttled version of the reset logic */
261
- private throttledReset;
262
- private constructor();
263
- /**
264
- * Retrieves the global instance of the WindowManager.
265
- * Ensures uniqueness across multiple bundles or modules.
266
- */
267
- static getInstance(): WindowManager;
268
- /**
269
- * Manually triggers a system-wide input reset via Registry.
270
- */
271
- private handleGlobalReset;
272
- private handleResizeReset;
273
- private handleBlurReset;
274
- private handleScrollReset;
275
- private handleVisibilityChangeReset;
276
- /**
277
- * Initializes global safety listeners.
278
- * Should be called once at the root component lifecycle (e.g., VirtualLayer).
279
- */
280
- init(): void;
281
- /**
282
- * Toggle full-screen state of the page.
283
- * @param element Target HTMLElement
284
- */
285
- toggleFullscreen(element?: HTMLElement): Promise<void>;
286
- /**
287
- * Full-screen status query provided to the UI layer.
288
- */
289
- isFullscreen(): boolean;
290
- /**
291
- * Detaches all global listeners.
292
- */
293
- destroy(): void;
214
+ markAllRectDirty(): void;
215
+ broadcastSignal(signal: InputActionSignal): void;
294
216
  }
295
217
 
296
218
  /**
@@ -1112,4 +1034,4 @@ declare const OmniPad: {
1112
1034
  };
1113
1035
  };
1114
1036
 
1115
- export { AbstractPointerEvent, AbstractRect, AnyFunction, type AxisLogicState, BaseConfig, BaseEntity, ButtonConfig, ButtonCore, type ButtonLogicState, type ButtonState, type CursorState, DPadConfig, DPadCore, type DPadState, EntityType, GamepadManager, GamepadMappingConfig, IConfigurable, ICoreEntity, IDependencyBindable, IPointerHandler, IProgrammatic, type IRegistry, IResettable, ISignalReceiver, ISpatial, IStateful, InputActionSignal, InputZoneConfig, InputZoneCore, type InputZoneState, type InteractionState, JoystickConfig, JoystickCore, type JoystickState, type KeyboardButtonState, type LayerState, type MouseButtonState, OmniPad, Registry, RootLayerCore, TargetZoneConfig, TargetZoneCore, TrackpadConfig, TrackpadCore, type TrackpadState, Vec2, WindowManager };
1037
+ export { AbstractPointerEvent, AbstractRect, AnyFunction, type AxisLogicState, BaseConfig, BaseEntity, ButtonConfig, ButtonCore, type ButtonLogicState, type ButtonState, type CursorState, DPadConfig, DPadCore, type DPadState, EntityType, IConfigurable, ICoreEntity, IDependencyBindable, IPointerHandler, IProgrammatic, type IRegistry, IResettable, ISignalReceiver, ISpatial, IStateful, InputActionSignal, InputZoneConfig, InputZoneCore, type InputZoneState, type InteractionState, JoystickConfig, JoystickCore, type JoystickState, type KeyboardButtonState, type LayerState, type MouseButtonState, OmniPad, Registry, RootLayerCore, TargetZoneConfig, TargetZoneCore, TrackpadConfig, TrackpadCore, type TrackpadState, Vec2, setGlobalSignalHandler };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import {c,b,f,d as d$1,a,g,k as k$1,z as z$1,l,v,B as B$1,u}from'./chunk-ETLJK7NP.mjs';export{d as ACTION_TYPES,c as CMP_TYPES,f as CONTEXT,b as KEYS,g as Registry,e as VALID_UNITS}from'./chunk-ETLJK7NP.mjs';var R=Symbol.for("omnipad.gamepad_manager.instance"),Q={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 s=navigator.getGamepads();this.config?.forEach((t,e)=>{let i=s[e];i&&i.connected&&t&&(this.lastButtonStates[e]||(this.lastButtonStates[e]=[]),this.processButtons(i,t,e),this.processDPad(i,t),this.processAxes(i,t));}),requestAnimationFrame(this.loop);});}static getInstance(){let s=globalThis;return s[R]||(s[R]=new c),s[R]}setConfig(s){this.config=s;}getConfig(){return this.config}start(){this.isRunning||(this.isRunning=true,window.addEventListener("gamepadconnected",s=>{import.meta.env?.DEV&&console.log("[Omnipad-Core] Gamepad Connected:",s.gamepad.id);}),window.addEventListener("gamepaddisconnected",()=>{import.meta.env?.DEV&&console.log("[Omnipad-Core] Gamepad disconnected.");}),this.loop());}stop(){this.isRunning=false;}processButtons(s,t,e){t.buttons&&Object.entries(t.buttons).forEach(([i,o])=>{let n=Q[i];if(n===void 0||!s.buttons[n])return;let l=s.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(s,t){let e=t?.dpad;if(!e)return;let i=s.buttons[12]?.pressed?-1:0,o=s.buttons[13]?.pressed?1:0,n=s.buttons[14]?.pressed?-1:0,l=s.buttons[15]?.pressed?1:0,u=n+l,v=i+o;this.triggerVirtualEntity(e,"vector",{x:u,y:v});}processAxes(s,t){let e=t?.deadzone??.1;if(t?.leftStick){let i=Math.abs(s.axes[0])>e?s.axes[0]:0,o=Math.abs(s.axes[1])>e?s.axes[1]:0;this.triggerVirtualEntity(t.leftStick,"vector",{x:i,y:o});}if(t?.rightStick){let i=Math.abs(s.axes[2])>e?s.axes[2]:0,o=Math.abs(s.axes[3])>e?s.axes[3]:0;this.triggerVirtualEntity(t.rightStick,"vector",{x:i,y:o});}}triggerVirtualEntity(s,t,e){let i=g.getInstance().getEntity(s);!i||i.activePointerId!=null||(t==="down"&&i.triggerDown&&i.triggerDown(),t==="up"&&i.triggerUp&&i.triggerUp(),t==="vector"&&i.triggerVector&&e&&i.triggerVector(e.x,e.y));}};var w=typeof globalThis<"u"&&globalThis.requestAnimationFrame?globalThis.requestAnimationFrame.bind(globalThis):c=>setTimeout(c,16),tt=typeof globalThis<"u"&&globalThis.cancelAnimationFrame?globalThis.cancelAnimationFrame.bind(globalThis):c=>clearTimeout(c);function D(c){let s=false,t;return function(e){t=e,s||(s=true,w(()=>{c(t),s=false;}));}}function K(c){let s=null,t=()=>{c(),s=w(t);};return {start:()=>{s===null&&t();},stop:()=>{s!==null&&(tt(s),s=null);}}}var X=(c=2)=>new Promise(s=>{let t=0,e=()=>{++t>=c?s():w(e);};w(e);});var k=Symbol.for("omnipad.window_manager.instance"),O=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."),g.getInstance().resetAll();});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=D(()=>{this.handleGlobalReset();});}static getInstance(){let s=globalThis;return s[k]||(s[k]=new c),s[k]}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(s){let t=s||document.documentElement;try{document.fullscreenElement?(g.getInstance().resetAll(),await document.exitFullscreen()):(g.getInstance().resetAll(),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 S=class{constructor(){a(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(e){console.error("[OmniPad-Core] Emitter callback error:",e);}});}clear(){this.listeners.clear();}};var d=class{constructor(s,t,e,i){a(this,"uid");a(this,"type");a(this,"config");a(this,"state");a(this,"rectProvider",null);a(this,"_onMarkDirtyCb",null);a(this,"stateEmitter",new S);a(this,"configEmitter",new S);this.uid=s,this.type=t,this.config=e,this.state=i;}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(),g.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 p=class{constructor(s,t){a(this,"isPressed",false);a(this,"mapping");a(this,"targetId");this.update(s,t);}update(s,t){this.isPressed&&this.reset(),this.targetId=s,this.mapping=this.hydrate(t);}hydrate(s){if(!s)return;let t={...s};if(t.type==="mouse")return t.button=t.button??0,t;let{key:e,code:i,keyCode:o}=t;if(e||i||o){t.type="keyboard";let n=Object.values(b).find(l=>l.code===i||l.key===e||l.keyCode===o);n&&(t.key=e??n.key,t.code=i??n.code,t.keyCode=o??n.keyCode);}return t}press(){if(!this.mapping||this.isPressed)return;this.isPressed=true;let s=this.mapping.type==="keyboard"?d$1.KEYDOWN:d$1.MOUSEDOWN;this.emitSignal(s);}release(s=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"&&s&&this.emitSignal(d$1.CLICK);}move(s){this.mapping?.type==="mouse"&&this.emitSignal(d$1.MOUSEMOVE,s);}reset(){this.isPressed&&this.release(false);}async tap(s=true){this.isPressed||(this.press(),await X(2),this.isPressed&&this.release(s));}emitSignal(s,t={}){if(!this.targetId||!this.mapping)return;let e=g.getInstance().getEntity(this.targetId);e&&e.handleSignal({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 Y={isActive:false,isPressed:false,pointerId:null,value:0},V=class extends d{constructor(t,e,i){super(t,i||c.BUTTON,e,Y);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(Y),this.emitter.reset();}updateConfig(t){super.updateConfig(t),this.emitter.update(this.config.targetStageId,this.config.mapping);}handleRelease(t){this.setState(Y),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 Z={isActive:false,pointerId:null,vector:{x:0,y:0}},z=.002,q=.3,_=class extends d{constructor(t,e,i){super(t,i||c.D_PAD,e,Z);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 i=this.rect;if(!i)return;let o=i.left+i.width/2,n=i.top+i.height/2,l=i.width/2,u=i.height/2,v=(t.clientX-o)/l,P=(t.clientY-n)/u;if(e&&(v!=k$1(v,-1,1)||P!=k$1(P,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let A={x:k$1(v,-1,1),y:k$1(P,-1,1)};z$1(A,this.state.vector,z)||(this.setState({vector:A}),this.handleDigitalKeys(A));}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(Z);}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 i=this.config.threshold??.3;if(Math.abs(t)<i&&Math.abs(e)<i){this.state.isActive&&this.reset();return}this.state.isActive||this.setState({isActive:true});let o=l(this.state.vector.x,t,q),n=l(this.state.vector.y,e,q),l$1={x:o,y:n};z$1(l$1,this.state.vector,z)||(this.setState({vector:l$1}),this.handleDigitalKeys(l$1));}};var et={isDynamicActive:false,dynamicPointerId:null,dynamicPosition:{x:0,y:0}},B=class extends d{constructor(t,e,i){super(t,i||c.INPUT_ZONE,e,et);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 i=this.rect;return i?{x:v(t-i.left,i.width),y:v(e-i.top,i.height)}:{x:0,y:0}}get isInterceptorRequired(){return !!(this.config.dynamicWidgetId||this.config.preventFocusLoss)}reset(){this.setState({isDynamicActive:false,dynamicPointerId:null});}};var T=class{constructor(s={}){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,...s};}onPointerDown(s,t){let e=Date.now();this.startTime=e,this.startPos={x:s,y:t},this.hasMoved=false,e-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 J={isActive:false,isPressed:false,pointerId:null,value:0,vector:{x:0,y:0}},U=.002,j=.3,H=class extends d{constructor(t,e,i){super(t,i||c.JOYSTICK,e,J);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 T({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=K(()=>{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 i=this.rect;if(!i)return;let o=i.left+i.width/2,n=i.top+i.height/2,l=i.width/2,u=i.height/2,v=(t.clientX-o)/l,P=(t.clientY-n)/u;if(e&&(v!=k$1(v,-1,1)||P!=k$1(P,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let x=B$1({x:v,y:P},1,this.config.threshold||.15);z$1(x,this.state.vector,U)||(this.setState({vector:x}),this.handleDigitalKeys(x));}handleCursorTick(){let{vector:t,isActive:e}=this.state;if(!e||!this.config.cursorMode||z$1(t,{x:0,y:0},U)){this.ticker.stop();return}let i=this.config.cursorSensitivity??1,o={x:t.x*Math.abs(t.x)*i,y:t.y*Math.abs(t.y)*i};(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(J),this.gesture.reset(),this.handleRelease(),this.stickEmitter.reset(),this.cursorEmitter.reset();}updateConfig(t){super.updateConfig(t);let e=this.config.targetStageId,i=this.config.mapping||{};this.emitters.up.update(e,i.up),this.emitters.down.update(e,i.down),this.emitters.left.update(e,i.left),this.emitters.right.update(e,i.right),this.stickEmitter.update(e,i.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 i=this.config.threshold??.15;if(Math.hypot(t,e)<i){this.state.isActive&&this.handleRelease();return}this.state.isActive||this.setState({isActive:true});let n=l(this.state.vector.x,t,j),l$1=l(this.state.vector.y,e,j),u={x:n,y:l$1};z$1(u,this.state.vector,U)||(this.setState({vector:u}),this.handleDigitalKeys(u)),this.config.cursorMode&&this.ticker.start();}};var it={isHighlighted:false},F=class extends d{constructor(s,t,e){super(s,e||c.ROOT_LAYER,t,it);}reset(){}};var st={position:{x:50,y:50},isVisible:false,isPointerDown:false,isFocusReturning:false},y=1,G=class extends d{constructor(t,e,i){super(t,i||c.TARGET_ZONE,e,st);a(this,"hideTimer",null);a(this,"focusFeedbackTimer",null);a(this,"throttledMoveExecution");a(this,"delegates",{dispatchKeyboardEvent:()=>{},dispatchPointerEventAtPos:()=>{},reclaimFocusAtPos:()=>{}});this.throttledMoveExecution=D(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 i=this.rect;if(!i)return;let o={x:v(t.clientX-i.left,i.width),y:v(t.clientY-i.top,i.height)};this.handleSignal({targetStageId:this.uid,type:e,payload:{point:o,button:t.button}});}handleSignal(t){let{type:e,payload:i}=t;switch(this.ensureFocus(),e){case d$1.KEYDOWN:case d$1.KEYUP:this.delegates.dispatchKeyboardEvent?.(e,i);break;case d$1.MOUSEMOVE:i.point?this.updateCursorPosition(i.point):i.delta&&this.updateCursorPositionByDelta(i.delta),this.config.cursorEnabled&&this.showCursor(),this.throttledMoveExecution(i);break;case d$1.MOUSEDOWN:case d$1.MOUSEUP:case d$1.CLICK:i.point&&this.updateCursorPosition(i.point),this.config.cursorEnabled&&this.showCursor(),this.executeMouseAction(e.startsWith(d$1.MOUSE)?e.replace(d$1.MOUSE,d$1.POINTER):e,i);break}}executeMouseAction(t,e){let i=this.rect;if(!i)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=k$1(i.left+u(o.x,i.width),i.left+y,i.left+i.width-y),l=k$1(i.top+u(o.y,i.height),i.top+y,i.top+i.height-y);this.delegates.dispatchPointerEventAtPos?.(t,n,l,{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=k$1(t.left+u(this.state.position.x,t.width),t.left+y,t.left+t.width-y),i=k$1(t.top+u(this.state.position.y,t.height),t.top+y,t.top+t.height-y);this.delegates.reclaimFocusAtPos?.(e,i,()=>this.triggerFocusFeedback());}triggerFocusFeedback(){this.setState({isFocusReturning:true}),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.focusFeedbackTimer=setTimeout(()=>this.setState({isFocusReturning:false}),500);}updateCursorPosition(t){z$1(t,this.state.position)||this.setState({position:{...t}});}updateCursorPositionByDelta(t){if(z$1(t,{x:0,y:0}))return;let e=this.rect;if(!e)return;let i=v(t.x,e.width),o=v(t.y,e.height);this.updateCursorPosition({x:k$1(this.state.position.x+i,0,100),y:k$1(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 $={isActive:false,isPressed:false,pointerId:null,value:0},L=class extends d{constructor(t,e,i){super(t,i||c.TRACKPAD,e,$);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 T({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,i=t.clientY-this.lastPointerPos.y,o=this.rect;if(!o)return;let n=e/o.width*100*(this.config.sensitivity??1),l=i/o.height*100*(this.config.sensitivity??1),u={x:n,y:l};z$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($);}};var Ye={ActionTypes:d$1,Context:f,Keys:b,Types:c};export{d as BaseEntity,V as ButtonCore,_ as DPadCore,M as GamepadManager,B as InputZoneCore,H as JoystickCore,Ye as OmniPad,F as RootLayerCore,G as TargetZoneCore,L as TrackpadCore,O as WindowManager};
1
+ import {d as d$1,s,e,o,u,n}from'./chunk-V7AHGFPB.mjs';import {b as b$1,a as a$1,c as c$2}from'./chunk-ZM2LX5IW.mjs';import {c as c$1,b,f,d,a,h}from'./chunk-PACTGVBB.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-PACTGVBB.mjs';var S=class{constructor(){a(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(e){console.error("[OmniPad-Core] Emitter callback error:",e);}});}clear(){this.listeners.clear();}};var l=class{constructor(s,t,e,i){a(this,"uid");a(this,"type");a(this,"config");a(this,"state");a(this,"rectProvider",null);a(this,"_onMarkDirtyCb",null);a(this,"stateEmitter",new S);a(this,"configEmitter",new S);this.uid=s,this.type=t,this.config=e,this.state=i;}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(),h.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 c=class{constructor(s,t){a(this,"isPressed",false);a(this,"mapping");a(this,"targetId");this.update(s,t);}update(s,t){this.isPressed&&this.reset(),this.targetId=s,this.mapping=this.hydrate(t);}hydrate(s){if(!s)return;let t={...s};if(t.type==="mouse")return t.button=t.button??0,t;let{key:e,code:i,keyCode:o}=t;if(e||i||o){t.type="keyboard";let a=Object.values(b).find(p=>p.code===i||p.key===e||p.keyCode===o);a&&(t.key=e??a.key,t.code=i??a.code,t.keyCode=o??a.keyCode);}return t}press(){if(!this.mapping||this.isPressed)return;this.isPressed=true;let s=this.mapping.type==="keyboard"?d.KEYDOWN:d.MOUSEDOWN;this.emitSignal(s);}release(s=true){if(!this.mapping||!this.isPressed)return;this.isPressed=false;let t=this.mapping.type==="keyboard"?d.KEYUP:d.MOUSEUP;this.emitSignal(t),this.mapping.type==="mouse"&&s&&this.emitSignal(d.CLICK);}move(s){this.mapping?.type==="mouse"&&this.emitSignal(d.MOUSEMOVE,s);}reset(){this.isPressed&&this.release(false);}async tap(s=true){this.isPressed||(this.press(),await c$2(2),this.isPressed&&this.release(s));}emitSignal(s,t={}){this.mapping&&h.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 x={isActive:false,isPressed:false,pointerId:null,value:0},w=class extends l{constructor(t,e,i){super(t,i||c$1.BUTTON,e,x);a(this,"emitter");this.emitter=new c(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(x),this.emitter.reset();}updateConfig(t){super.updateConfig(t),this.emitter.update(this.config.targetStageId,this.config.mapping);}handleRelease(t){this.setState(x),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 K={isActive:false,pointerId:null,vector:{x:0,y:0}},X=.002,L=.3,M=class extends l{constructor(t,e,i){super(t,i||c$1.D_PAD,e,K);a(this,"emitters");let o=e.targetStageId;this.emitters={up:new c(o,e.mapping?.up),down:new c(o,e.mapping?.down),left:new c(o,e.mapping?.left),right:new c(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 i=this.rect;if(!i)return;let o=i.left+i.width/2,a=i.top+i.height/2,p=i.width/2,f=i.height/2,P=(t.clientX-o)/p,b=(t.clientY-a)/f;if(e&&(P!=d$1(P,-1,1)||b!=d$1(b,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let A={x:d$1(P,-1,1),y:d$1(b,-1,1)};s(A,this.state.vector,X)||(this.setState({vector:A}),this.handleDigitalKeys(A));}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(K);}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$1){let i=this.config.threshold??.3;if(Math.abs(t)<i&&Math.abs(e$1)<i){this.state.isActive&&this.reset();return}this.state.isActive||this.setState({isActive:true});let o=e(this.state.vector.x,t,L),a=e(this.state.vector.y,e$1,L),p={x:o,y:a};s(p,this.state.vector,X)||(this.setState({vector:p}),this.handleDigitalKeys(p));}};var q={isDynamicActive:false,dynamicPointerId:null,dynamicPosition:{x:0,y:0}},k=class extends l{constructor(t,e,i){super(t,i||c$1.INPUT_ZONE,e,q);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 i=this.rect;return i?{x:o(t-i.left,i.width),y:o(e-i.top,i.height)}:{x:0,y:0}}get isInterceptorRequired(){return !!(this.config.dynamicWidgetId||this.config.preventFocusLoss)}reset(){this.setState({isDynamicActive:false,dynamicPointerId:null});}};var T=class{constructor(s={}){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,...s};}onPointerDown(s,t){let e=Date.now();this.startTime=e,this.startPos={x:s,y:t},this.hasMoved=false,e-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 W={isActive:false,isPressed:false,pointerId:null,value:0,vector:{x:0,y:0}},O=.002,G=.3,R=class extends l{constructor(t,e,i){super(t,i||c$1.JOYSTICK,e,W);a(this,"emitters");a(this,"stickEmitter");a(this,"cursorEmitter");a(this,"gesture");a(this,"ticker");let o=e.targetStageId,a$1=e.mapping||{};this.emitters={up:new c(o,a$1.up),down:new c(o,a$1.down),left:new c(o,a$1.left),right:new c(o,a$1.right)},this.stickEmitter=new c(o,a$1.stick),this.cursorEmitter=new c(o,{type:"mouse"}),this.gesture=new T({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=b$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,e=false){if(!this.state.isActive)return;let i=this.rect;if(!i)return;let o=i.left+i.width/2,a=i.top+i.height/2,p=i.width/2,f=i.height/2,P=(t.clientX-o)/p,b=(t.clientY-a)/f;if(e&&(P!=d$1(P,-1,1)||b!=d$1(b,-1,1))){this.setState({vector:{x:0,y:0}}),this.markRectDirty();return}let D=u({x:P,y:b},1,this.config.threshold||.15);s(D,this.state.vector,O)||(this.setState({vector:D}),this.handleDigitalKeys(D));}handleCursorTick(){let{vector:t,isActive:e}=this.state;if(!e||!this.config.cursorMode||s(t,{x:0,y:0},O)){this.ticker.stop();return}let i=this.config.cursorSensitivity??1,o={x:t.x*Math.abs(t.x)*i,y:t.y*Math.abs(t.y)*i};(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(W),this.gesture.reset(),this.handleRelease(),this.stickEmitter.reset(),this.cursorEmitter.reset();}updateConfig(t){super.updateConfig(t);let e=this.config.targetStageId,i=this.config.mapping||{};this.emitters.up.update(e,i.up),this.emitters.down.update(e,i.down),this.emitters.left.update(e,i.left),this.emitters.right.update(e,i.right),this.stickEmitter.update(e,i.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$1){let i=this.config.threshold??.15;if(Math.hypot(t,e$1)<i){this.state.isActive&&this.handleRelease();return}this.state.isActive||this.setState({isActive:true});let a=e(this.state.vector.x,t,G),p=e(this.state.vector.y,e$1,G),f={x:a,y:p};s(f,this.state.vector,O)||(this.setState({vector:f}),this.handleDigitalKeys(f)),this.config.cursorMode&&this.ticker.start();}};var z={isHighlighted:false},Y=class extends l{constructor(s,t,e){super(s,e||c$1.ROOT_LAYER,t,z);}reset(){}};var j={position:{x:50,y:50},isVisible:false,isPointerDown:false,isFocusReturning:false},v=1,H=class extends l{constructor(t,e,i){super(t,i||c$1.TARGET_ZONE,e,j);a(this,"hideTimer",null);a(this,"focusFeedbackTimer",null);a(this,"throttledMoveExecution");a(this,"delegates",{dispatchKeyboardEvent:()=>{},dispatchPointerEventAtPos:()=>{},reclaimFocusAtPos:()=>{}});this.throttledMoveExecution=a$1(o=>{this.executeMouseAction(d.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.MOUSEDOWN);}onPointerMove(t){this.processPhysicalEvent(t,d.MOUSEMOVE);}onPointerUp(t){this.processPhysicalEvent(t,d.MOUSEUP),this.processPhysicalEvent(t,d.CLICK);}onPointerCancel(t){this.processPhysicalEvent(t,d.MOUSEUP);}processPhysicalEvent(t,e){let i=this.rect;if(!i)return;let o$1={x:o(t.clientX-i.left,i.width),y:o(t.clientY-i.top,i.height)};this.handleSignal({targetStageId:this.uid,type:e,payload:{point:o$1,button:t.button}});}handleSignal(t){let{type:e,payload:i}=t;switch(this.ensureFocus(),e){case d.KEYDOWN:case d.KEYUP:this.delegates.dispatchKeyboardEvent?.(e,i);break;case d.MOUSEMOVE:i.point?this.updateCursorPosition(i.point):i.delta&&this.updateCursorPositionByDelta(i.delta),this.config.cursorEnabled&&this.showCursor(),this.throttledMoveExecution(i);break;case d.MOUSEDOWN:case d.MOUSEUP:case d.CLICK:i.point&&this.updateCursorPosition(i.point),this.config.cursorEnabled&&this.showCursor(),this.executeMouseAction(e.startsWith(d.MOUSE)?e.replace(d.MOUSE,d.POINTER):e,i);break}}executeMouseAction(t,e){let i=this.rect;if(!i)return;t===d.POINTERDOWN&&this.setState({isPointerDown:true}),t===d.POINTERUP&&this.setState({isPointerDown:false});let o=e.point||this.state.position,a=d$1(i.left+n(o.x,i.width),i.left+v,i.left+i.width-v),p=d$1(i.top+n(o.y,i.height),i.top+v,i.top+i.height-v);this.delegates.dispatchPointerEventAtPos?.(t,a,p,{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=d$1(t.left+n(this.state.position.x,t.width),t.left+v,t.left+t.width-v),i=d$1(t.top+n(this.state.position.y,t.height),t.top+v,t.top+t.height-v);this.delegates.reclaimFocusAtPos?.(e,i,()=>this.triggerFocusFeedback());}triggerFocusFeedback(){this.setState({isFocusReturning:true}),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.focusFeedbackTimer=setTimeout(()=>this.setState({isFocusReturning:false}),500);}updateCursorPosition(t){s(t,this.state.position)||this.setState({position:{...t}});}updateCursorPositionByDelta(t){if(s(t,{x:0,y:0}))return;let e=this.rect;if(!e)return;let i=o(t.x,e.width),o$1=o(t.y,e.height);this.updateCursorPosition({x:d$1(this.state.position.x+i,0,100),y:d$1(this.state.position.y+o$1,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.POINTERUP,{}),this.hideTimer&&clearTimeout(this.hideTimer),this.focusFeedbackTimer&&clearTimeout(this.focusFeedbackTimer),this.setState({isVisible:false,isPointerDown:false,isFocusReturning:false});}};var Z={isActive:false,isPressed:false,pointerId:null,value:0},U=class extends l{constructor(t,e,i){super(t,i||c$1.TRACKPAD,e,Z);a(this,"lastPointerPos",{x:0,y:0});a(this,"gesture");a(this,"emitter");let o=e.mapping||{type:"mouse"};this.emitter=new c(e.targetStageId,o),this.gesture=new T({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,i=t.clientY-this.lastPointerPos.y,o=this.rect;if(!o)return;let a=e/o.width*100*(this.config.sensitivity??1),p=i/o.height*100*(this.config.sensitivity??1),f={x:a,y:p};s(f,{x:0,y:0})||this.emitter.move({delta:f}),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(Z);}};var ye={ActionTypes:d,Context:f,Keys:b,Types:c$1};export{l as BaseEntity,w as ButtonCore,M as DPadCore,k as InputZoneCore,R as JoystickCore,ye as OmniPad,Y as RootLayerCore,H as TargetZoneCore,U as TrackpadCore};
@@ -0,0 +1,59 @@
1
+ import { A as AbstractRect, L as LayoutBox } from './index-DVegtw8s.cjs';
2
+
3
+ /**
4
+ * Headless Sticky Provider.
5
+ * Manages reference coordinate tracking without direct DOM dependency.
6
+ *
7
+ * It relies on an externally injected 'finder' function to resolve
8
+ * the reference object and a 'rectProvider' to get its dimensions.
9
+ */
10
+ declare class StickyProvider {
11
+ private finder;
12
+ private rectProvider;
13
+ private presenceChecker;
14
+ private _selector;
15
+ private _cachedTarget;
16
+ private _rectCache;
17
+ /**
18
+ * @param selector - The selector (e.g. selector) of the reference.
19
+ * @param finder - A function that resolves the selector to a physical object.
20
+ * @param rectProvider - A function that returns the bounds of the resolved object.
21
+ * @param presenceChecker - A function to check if the target is still valid/attached.
22
+ */
23
+ constructor(selector: string, finder: (id: string) => any, rectProvider: (target: any) => AbstractRect | null, presenceChecker: (target: any) => boolean);
24
+ /**
25
+ * Resolves and returns the target object.
26
+ */
27
+ getTarget(): any | null;
28
+ /**
29
+ * Returns the current Rect of the sticky target.
30
+ * Uses internal cache to prevent layout thrashing.
31
+ */
32
+ getRect(): AbstractRect | null;
33
+ /**
34
+ * Invalidates the current Rect cache.
35
+ * Should be called during window resize, scroll, or manual re-alignments.
36
+ */
37
+ markDirty(): void;
38
+ /**
39
+ * Updates the selector and clears the current element cache.
40
+ *
41
+ * @param newSelector - The new CSS selector.
42
+ * @returns Whether the selector is updated.
43
+ */
44
+ updateSelector(newSelector: string): boolean;
45
+ }
46
+ /**
47
+ * Resolves a relative "Sticky" layout into absolute viewport coordinates.
48
+ *
49
+ * This function calculates the exact pixel positions required for `fixed` CSS positioning
50
+ * by mapping a relative `LayoutBox` (which may use percentages or offsets) onto the
51
+ * physical coordinate system of a target reference element (e.g., a game canvas).
52
+ *
53
+ * @param layout - The relative layout configuration containing sticky instructions.
54
+ * @param targetRect - The current physical bounding box of the reference element.
55
+ * @returns A new LayoutBox with all dimensions resolved to absolute pixel strings.
56
+ */
57
+ declare function resolveStickyLayout(layout: LayoutBox, targetRect: AbstractRect): LayoutBox;
58
+
59
+ export { StickyProvider as S, resolveStickyLayout as r };
@@ -0,0 +1,59 @@
1
+ import { A as AbstractRect, L as LayoutBox } from './index-DVegtw8s.js';
2
+
3
+ /**
4
+ * Headless Sticky Provider.
5
+ * Manages reference coordinate tracking without direct DOM dependency.
6
+ *
7
+ * It relies on an externally injected 'finder' function to resolve
8
+ * the reference object and a 'rectProvider' to get its dimensions.
9
+ */
10
+ declare class StickyProvider {
11
+ private finder;
12
+ private rectProvider;
13
+ private presenceChecker;
14
+ private _selector;
15
+ private _cachedTarget;
16
+ private _rectCache;
17
+ /**
18
+ * @param selector - The selector (e.g. selector) of the reference.
19
+ * @param finder - A function that resolves the selector to a physical object.
20
+ * @param rectProvider - A function that returns the bounds of the resolved object.
21
+ * @param presenceChecker - A function to check if the target is still valid/attached.
22
+ */
23
+ constructor(selector: string, finder: (id: string) => any, rectProvider: (target: any) => AbstractRect | null, presenceChecker: (target: any) => boolean);
24
+ /**
25
+ * Resolves and returns the target object.
26
+ */
27
+ getTarget(): any | null;
28
+ /**
29
+ * Returns the current Rect of the sticky target.
30
+ * Uses internal cache to prevent layout thrashing.
31
+ */
32
+ getRect(): AbstractRect | null;
33
+ /**
34
+ * Invalidates the current Rect cache.
35
+ * Should be called during window resize, scroll, or manual re-alignments.
36
+ */
37
+ markDirty(): void;
38
+ /**
39
+ * Updates the selector and clears the current element cache.
40
+ *
41
+ * @param newSelector - The new CSS selector.
42
+ * @returns Whether the selector is updated.
43
+ */
44
+ updateSelector(newSelector: string): boolean;
45
+ }
46
+ /**
47
+ * Resolves a relative "Sticky" layout into absolute viewport coordinates.
48
+ *
49
+ * This function calculates the exact pixel positions required for `fixed` CSS positioning
50
+ * by mapping a relative `LayoutBox` (which may use percentages or offsets) onto the
51
+ * physical coordinate system of a target reference element (e.g., a game canvas).
52
+ *
53
+ * @param layout - The relative layout configuration containing sticky instructions.
54
+ * @param targetRect - The current physical bounding box of the reference element.
55
+ * @returns A new LayoutBox with all dimensions resolved to absolute pixel strings.
56
+ */
57
+ declare function resolveStickyLayout(layout: LayoutBox, targetRect: AbstractRect): LayoutBox;
58
+
59
+ export { StickyProvider as S, resolveStickyLayout as r };
@@ -0,0 +1,152 @@
1
+ import { E as EntityType, A as AbstractRect, a as AbstractPointerEvent, c as AnyFunction, I as InputActionSignal } from './index-DVegtw8s.cjs';
2
+
3
+ /**
4
+ * Trait: Provides identity with a unique ID and specific entity type.
5
+ */
6
+ interface IIdentifiable {
7
+ readonly uid: string;
8
+ readonly type: EntityType;
9
+ }
10
+ /**
11
+ * Trait: Provides lifecycle management hooks.
12
+ */
13
+ interface ILifecycle {
14
+ /**
15
+ * Performs cleanup, unregisters the entity, and releases resources.
16
+ */
17
+ destroy(): void;
18
+ }
19
+ /**
20
+ * The core contract for any object that can be managed by the Registry.
21
+ * Only objects implementing this interface are eligible for registration.
22
+ */
23
+ interface ICoreEntity extends IIdentifiable, ILifecycle {
24
+ }
25
+ /**
26
+ * Trait: Enables spatial awareness for DOM/UI-related components.
27
+ */
28
+ interface ISpatial {
29
+ readonly rect: AbstractRect | null;
30
+ /**
31
+ * Dynamically obtain dimensions and position to ensure the most precise real-time screen coordinates are obtained during each interaction.
32
+ */
33
+ bindRectProvider(provider: () => AbstractRect, onMarkDirty?: () => void): void;
34
+ /**
35
+ * Trigger a cache invalidation.
36
+ */
37
+ markRectDirty(): void;
38
+ }
39
+ /**
40
+ * Trait: Provides configuration management.
41
+ */
42
+ interface IConfigurable<TConfig> {
43
+ /**
44
+ * Retrieves a snapshot of the current configuration.
45
+ */
46
+ getConfig(): TConfig;
47
+ /**
48
+ * Subscribes to config changes.
49
+ * @param cb - Callback function triggered on config updates.
50
+ * @returns An unsubscribe function.
51
+ */
52
+ subscribeConfig(cb: (config: TConfig) => void): () => void;
53
+ /**
54
+ * Updates the internal config and notifies all subscribers.
55
+ * @param config - Partial configuration object to merge.
56
+ */
57
+ updateConfig(config: Partial<TConfig>): void;
58
+ }
59
+ /**
60
+ * Trait: Provides state management.
61
+ */
62
+ interface IStateful<TState> {
63
+ /**
64
+ * Retrieves the current state snapshot.
65
+ */
66
+ getState(): TState;
67
+ /**
68
+ * Subscribes to state changes.
69
+ * @param cb - Callback function triggered on state updates.
70
+ * @returns An unsubscribe function.
71
+ */
72
+ subscribeState(cb: (state: TState) => void): () => void;
73
+ /**
74
+ * Updates the internal state and notifies all subscribers.
75
+ * @param state - Partial object containing updated state values.
76
+ */
77
+ setState(state: Partial<TState>): void;
78
+ }
79
+ /**
80
+ * Trait: Allows resetting the entity to its idle/safe state.
81
+ */
82
+ interface IResettable {
83
+ /**
84
+ * Forcefully clears active states and cuts off outgoing signals.
85
+ */
86
+ reset(): void;
87
+ }
88
+ /**
89
+ * Trait: Handles raw pointer input (Touch/Mouse).
90
+ */
91
+ interface IPointerHandler {
92
+ readonly activePointerId: number | null;
93
+ onPointerDown(e: AbstractPointerEvent): void;
94
+ onPointerMove(e: AbstractPointerEvent): void;
95
+ onPointerUp(e: AbstractPointerEvent): void;
96
+ onPointerCancel(e: AbstractPointerEvent): void;
97
+ }
98
+ /**
99
+ * Trait: Receives and processes input signals (e.g., TargetZone).
100
+ */
101
+ interface ISignalReceiver {
102
+ /**
103
+ * Handles incoming signals from widgets.
104
+ * @param signal - The signal data containing action type and payload.
105
+ */
106
+ handleSignal(signal: InputActionSignal): void;
107
+ }
108
+ /**
109
+ * Capability for an entity to receive and store external functional dependencies.
110
+ *
111
+ * This enables Runtime Dependency Injection (DI), allowing core logic to invoke
112
+ * host-specific methods (such as DOM event dispatchers or custom triggers)
113
+ * without being tightly coupled to the environment.
114
+ */
115
+ interface IDependencyBindable {
116
+ /**
117
+ * Binds a functional delegate by a specific identifier key.
118
+ *
119
+ * @param key - The unique lookup identifier for the dependency (e.g., 'domDispatcher').
120
+ * @param delegate - The function implementation provided by the adapter layer.
121
+ */
122
+ bindDelegate(key: string, delegate: AnyFunction): void;
123
+ }
124
+ /**
125
+ * Contract for widgets that support programmatic control.
126
+ *
127
+ * This interface allows external systems—such as a Physical Gamepad Manager or
128
+ * automation scripts—to directly drive the state and behavior of a widget,
129
+ * bypassing native DOM pointer events.
130
+ */
131
+ interface IProgrammatic {
132
+ /**
133
+ * Manually triggers the 'down' (pressed) state of the widget.
134
+ * Primarily used for Button-type components to simulate a physical press.
135
+ */
136
+ triggerDown?(): void;
137
+ /**
138
+ * Manually triggers the 'up' (released) state of the widget.
139
+ * Primarily used for Button-type components to simulate a physical release.
140
+ */
141
+ triggerUp?(): void;
142
+ /**
143
+ * Manually updates the directional input vector of the widget.
144
+ * Primarily used for Joystick or D-Pad components.
145
+ *
146
+ * @param x - The horizontal component, normalized between -1.0 and 1.0.
147
+ * @param y - The vertical component, normalized between -1.0 and 1.0.
148
+ */
149
+ triggerVector?(x: number, y: number): void;
150
+ }
151
+
152
+ export type { ICoreEntity as I, ISpatial as a, IResettable as b, IConfigurable as c, IStateful as d, IPointerHandler as e, IProgrammatic as f, IDependencyBindable as g, ISignalReceiver as h, IIdentifiable as i, ILifecycle as j };