@utsp/input 0.10.0-nightly.20251211194839.e68c16e → 0.10.0-nightly.20251213135145.115c488

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var D=Object.defineProperty;var ae=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var ue=Object.prototype.hasOwnProperty;var le=(d,s,e)=>s in d?D(d,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[s]=e;var m=(d,s)=>D(d,"name",{value:s,configurable:!0});var de=(d,s)=>{for(var e in s)D(d,e,{get:s[e],enumerable:!0})},ce=(d,s,e,t)=>{if(s&&typeof s=="object"||typeof s=="function")for(let o of re(s))!ue.call(d,o)&&o!==e&&D(d,o,{get:()=>s[o],enumerable:!(t=ae(s,o))||t.enumerable});return d};var he=d=>ce(D({},"__esModule",{value:!0}),d);var l=(d,s,e)=>(le(d,typeof s!="symbol"?s+"":s,e),e);var pe={};de(pe,{BaseInputs:()=>f,GamepadInput:()=>y.GamepadInput,GamepadInputs:()=>x,InputCollector:()=>K,InputDeviceType:()=>y.InputDeviceType,InputEventType:()=>W,KeyboardInput:()=>y.KeyboardInput,KeyboardInputs:()=>C,MobileInputs:()=>w,MouseInput:()=>y.MouseInput,MouseInputs:()=>I,TouchInput:()=>y.TouchInput,UnifiedInputRouter:()=>L,Vector2:()=>R.Vector2,Vector3:()=>R.Vector3,isInputs:()=>Q,useGamepadInputs:()=>te,useKeyboardInputs:()=>Z,useMobileInputs:()=>ee,useMouseInputs:()=>_});module.exports=he(pe);var R=require("@utsp/types"),y=require("@utsp/types");var W=(p=>(p.KeyDown="keydown",p.KeyUp="keyup",p.MouseDown="mousedown",p.MouseUp="mouseup",p.MouseMove="mousemove",p.MouseWheel="mousewheel",p.TouchStart="touchstart",p.TouchEnd="touchend",p.TouchMove="touchmove",p.GamepadConnected="gamepadconnected",p.GamepadDisconnected="gamepaddisconnected",p.GamepadButton="gamepadbutton",p.GamepadAxis="gamepadaxis",p))(W||{}),V=class V{constructor(s=window,e={}){l(this,"isActive",!1);l(this,"targetElement");l(this,"config");l(this,"callbacks",{});this.targetElement=s,this.config={enabled:!0,preventDefault:!1,stopPropagation:!1,debug:!1,...e}}isListening(){return this.isActive}destroy(){this.stop(),this.clearCallbacks()}setCallbacks(s){typeof s=="object"&&s!==null&&Object.assign(this.callbacks,s)}clearCallbacks(){this.callbacks={}}getTargetElement(){return this.targetElement}enable(){this.config.enabled=!0,this.isActive||this.start()}disable(){this.config.enabled=!1,this.isActive&&this.stop()}isEnabled(){return this.config.enabled??!0}emit(s,...e){this.callbacks[s]&&this.callbacks[s].forEach(t=>{try{t(...e)}catch(o){this.config.debug&&console.error(`Error in ${s} callback:`,o)}})}log(...s){this.config.debug&&console.warn("[InputSystem]",...s)}};m(V,"BaseInputs");var f=V;function Q(d){return typeof d=="object"&&d!==null&&"start"in d&&"stop"in d&&"reset"in d&&"isListening"in d&&"destroy"in d}m(Q,"isInputs");var U=class U extends f{constructor(e=window,t={}){super(e,t);l(this,"keys",{});l(this,"keyboardCallbacks",{});l(this,"textInputsThisFrame",[]);l(this,"boundHandlers");this.boundHandlers={keyDown:this.handleKeyDown.bind(this),keyUp:this.handleKeyUp.bind(this)}}start(){this.isActive||(this.targetElement.addEventListener("keydown",this.boundHandlers.keyDown),this.targetElement.addEventListener("keyup",this.boundHandlers.keyUp),this.isActive=!0)}stop(){this.isActive&&(this.targetElement.removeEventListener("keydown",this.boundHandlers.keyDown),this.targetElement.removeEventListener("keyup",this.boundHandlers.keyUp),this.isActive=!1)}reset(){this.keys={}}resetDelta(){}poll(){for(let e in this.keys)this.keys[e].justPressed=!1,this.keys[e].justReleased=!1;this.textInputsThisFrame=[]}getTextInputs(){return this.textInputsThisFrame}isKeyPressed(e){return this.keys[e]?.pressed||!1}isKeyJustPressed(e){return this.keys[e]?.justPressed||!1}isKeyJustReleased(e){return this.keys[e]?.justReleased||!1}getKeysPressed(){return Object.keys(this.keys).filter(e=>this.keys[e].pressed)}getKeysJustPressed(){return Object.keys(this.keys).filter(e=>this.keys[e].justPressed)}getKeysJustReleased(){return Object.keys(this.keys).filter(e=>this.keys[e].justReleased)}isAnyKeyPressed(){return Object.values(this.keys).some(e=>e.pressed)}setKeyboardCallbacks(e){this.keyboardCallbacks={...this.keyboardCallbacks,...e}}clearKeyboardCallbacks(){this.keyboardCallbacks={}}setCallbacks(e){this.isKeyboardCallbacks(e)&&this.setKeyboardCallbacks(e)}isKeyboardCallbacks(e){return typeof e=="object"&&e!==null&&("onKeyDown"in e||"onKeyUp"in e)}handleKeyDown(e){try{let t=e.code,o=/^F([1-9]|1[0-2])$/.test(t),n=(e.ctrlKey||e.metaKey)&&(t==="KeyT"||t==="KeyW"||t==="KeyR"||t==="KeyN"||t==="Tab");this.config.preventDefault&&!o&&!n&&e.preventDefault(),this.config.stopPropagation&&!o&&!n&&e.stopPropagation(),this.keys[t]||(this.keys[t]={pressed:!1,justPressed:!1,justReleased:!1}),this.keys[t].pressed||(this.keys[t].justPressed=!0,this.keyboardCallbacks.onKeyDown?.(t,e)),this.keys[t].pressed=!0,this.keys[t].justReleased=!1;let i=e.key;i.length===1&&!e.ctrlKey&&!e.metaKey&&this.textInputsThisFrame.push(i)}catch(t){console.error("Error in keyboard keydown handler:",t)}}handleKeyUp(e){try{let t=e.code,o=/^F([1-9]|1[0-2])$/.test(t),n=(e.ctrlKey||e.metaKey)&&(t==="KeyT"||t==="KeyW"||t==="KeyR"||t==="KeyN"||t==="Tab");this.config.preventDefault&&!o&&!n&&e.preventDefault(),this.config.stopPropagation&&!o&&!n&&e.stopPropagation(),this.keys[t]||(this.keys[t]={pressed:!1,justPressed:!1,justReleased:!1}),this.keys[t].pressed&&(this.keys[t].justReleased=!0,this.keyboardCallbacks.onKeyUp?.(t,e)),this.keys[t].pressed=!1,this.keys[t].justPressed=!1}catch(t){console.error("Error in keyboard keyup handler:",t)}}};m(U,"KeyboardInputs");var C=U;function Z(d,s){let e=new C(d);return s&&e.setCallbacks(s),e.start(),e}m(Z,"useKeyboardInputs");var T=require("@utsp/types");var z=class z extends f{constructor(e=window,t={}){super(e,t);l(this,"mouseButtons",{left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}});l(this,"mousePosition",T.Vector2.zero());l(this,"mouseDelta",T.Vector2.zero());l(this,"wheelDelta",0);l(this,"mouseCallbacks",{});l(this,"boundHandlers");this.boundHandlers={mouseDown:this.handleMouseDown.bind(this),mouseUp:this.handleMouseUp.bind(this),mouseMove:this.handleMouseMove.bind(this),wheel:this.handleWheel.bind(this),mouseEnter:this.handleMouseEnter.bind(this),mouseLeave:this.handleMouseLeave.bind(this),contextMenu:this.handleContextMenu.bind(this)}}start(){this.isActive||(this.targetElement.addEventListener("mousedown",this.boundHandlers.mouseDown),this.targetElement.addEventListener("mouseup",this.boundHandlers.mouseUp),this.targetElement.addEventListener("mousemove",this.boundHandlers.mouseMove),this.targetElement.addEventListener("wheel",this.boundHandlers.wheel),this.targetElement.addEventListener("mouseenter",this.boundHandlers.mouseEnter),this.targetElement.addEventListener("mouseleave",this.boundHandlers.mouseLeave),this.targetElement.addEventListener("contextmenu",this.boundHandlers.contextMenu),this.isActive=!0)}stop(){this.isActive&&(this.targetElement.removeEventListener("mousedown",this.boundHandlers.mouseDown),this.targetElement.removeEventListener("mouseup",this.boundHandlers.mouseUp),this.targetElement.removeEventListener("mousemove",this.boundHandlers.mouseMove),this.targetElement.removeEventListener("wheel",this.boundHandlers.wheel),this.targetElement.removeEventListener("mouseenter",this.boundHandlers.mouseEnter),this.targetElement.removeEventListener("mouseleave",this.boundHandlers.mouseLeave),this.targetElement.removeEventListener("contextmenu",this.boundHandlers.contextMenu),this.isActive=!1)}reset(){this.mouseButtons={left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}},this.mousePosition=T.Vector2.zero(),this.mouseDelta=T.Vector2.zero(),this.wheelDelta=0}poll(){this.mouseButtons.left.justPressed=!1,this.mouseButtons.left.justReleased=!1,this.mouseButtons.middle.justPressed=!1,this.mouseButtons.middle.justReleased=!1,this.mouseButtons.right.justPressed=!1,this.mouseButtons.right.justReleased=!1,this.resetDelta()}resetDelta(){this.mouseDelta=T.Vector2.zero(),this.wheelDelta=0}isLeftMousePressed(){return this.mouseButtons.left.pressed}isLeftMouseJustPressed(){return this.mouseButtons.left.justPressed}isLeftMouseJustReleased(){return this.mouseButtons.left.justReleased}isRightMousePressed(){return this.mouseButtons.right.pressed}isRightMouseJustPressed(){return this.mouseButtons.right.justPressed}isRightMouseJustReleased(){return this.mouseButtons.right.justReleased}isMiddleMousePressed(){return this.mouseButtons.middle.pressed}isMiddleMouseJustPressed(){return this.mouseButtons.middle.justPressed}isMiddleMouseJustReleased(){return this.mouseButtons.middle.justReleased}getMousePosition(){return this.mousePosition.clone()}getMouseDelta(){return this.mouseDelta.clone()}getWheelDelta(){return this.wheelDelta}setMouseCallbacks(e){this.mouseCallbacks={...this.mouseCallbacks,...e}}clearMouseCallbacks(){this.mouseCallbacks={}}setCallbacks(e){this.isMouseCallbacks(e)&&this.setMouseCallbacks(e)}isMouseCallbacks(e){return typeof e=="object"&&e!==null&&("onMouseDown"in e||"onMouseUp"in e||"onMouseMove"in e||"onMouseWheel"in e||"onMouseEnter"in e||"onMouseLeave"in e)}handleMouseDown(e){try{switch(this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),e.button){case 0:this.mouseButtons.left.pressed||(this.mouseButtons.left.justPressed=!0),this.mouseButtons.left.pressed=!0,this.mouseButtons.left.justReleased=!1,this.mouseCallbacks.onMouseDown?.("left",this.mousePosition,e);break;case 1:this.mouseButtons.middle.pressed||(this.mouseButtons.middle.justPressed=!0),this.mouseButtons.middle.pressed=!0,this.mouseButtons.middle.justReleased=!1,this.mouseCallbacks.onMouseDown?.("middle",this.mousePosition,e);break;case 2:this.mouseButtons.right.pressed||(this.mouseButtons.right.justPressed=!0),this.mouseButtons.right.pressed=!0,this.mouseButtons.right.justReleased=!1,this.mouseCallbacks.onMouseDown?.("right",this.mousePosition,e);break}}catch(t){console.error("Error in mouse down handler:",t)}}handleMouseUp(e){try{switch(this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),e.button){case 0:this.mouseButtons.left.pressed&&(this.mouseButtons.left.justReleased=!0),this.mouseButtons.left.pressed=!1,this.mouseButtons.left.justPressed=!1,this.mouseCallbacks.onMouseUp?.("left",this.mousePosition,e);break;case 1:this.mouseButtons.middle.pressed&&(this.mouseButtons.middle.justReleased=!0),this.mouseButtons.middle.pressed=!1,this.mouseButtons.middle.justPressed=!1,this.mouseCallbacks.onMouseUp?.("middle",this.mousePosition,e);break;case 2:this.mouseButtons.right.pressed&&(this.mouseButtons.right.justReleased=!0),this.mouseButtons.right.pressed=!1,this.mouseButtons.right.justPressed=!1,this.mouseCallbacks.onMouseUp?.("right",this.mousePosition,e);break}}catch(t){console.error("Error in mouse up handler:",t)}}handleMouseMove(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation();let t=new T.Vector2(e.clientX,e.clientY);this.mouseDelta=t.subtract(this.mousePosition),this.mousePosition=t,this.mouseCallbacks.onMouseMove?.(this.mousePosition,this.mouseDelta,e)}catch(t){console.error("Error in mouse move handler:",t)}}handleWheel(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),this.wheelDelta=e.deltaY,this.mouseCallbacks.onMouseWheel?.(this.wheelDelta,e)}catch(t){console.error("Error in mouse wheel handler:",t)}}handleMouseEnter(e){try{this.mouseCallbacks.onMouseEnter?.(e)}catch(t){console.error("Error in mouse enter handler:",t)}}handleMouseLeave(e){try{this.mouseCallbacks.onMouseLeave?.(e)}catch(t){console.error("Error in mouse leave handler:",t)}}handleContextMenu(e){try{e.preventDefault(),this.config.stopPropagation&&e.stopPropagation()}catch(t){console.error("Error in context menu handler:",t)}}};m(z,"MouseInputs");var I=z;function _(d,s){let e=new I(d);return s&&e.setCallbacks(s),e.start(),e}m(_,"useMouseInputs");var Y=require("@utsp/types");var X=class X extends f{constructor(e=window,t={}){super(e,t);l(this,"touches",new Map);l(this,"nativeToInternal",new Map);l(this,"mobileCallbacks",{});l(this,"mobileConfig");l(this,"maxTouches",10);l(this,"lastLogTime",0);l(this,"boundHandlers");this.mobileConfig={targetElement:e,preventDefault:t.preventDefault??!0,passive:t.passive??!1,maxTouches:t.maxTouches??10,enabled:t.enabled??!0,debug:t.debug??!1,stopPropagation:t.stopPropagation??!1},this.maxTouches=this.mobileConfig.maxTouches,this.mobileConfig.preventDefault&&this.mobileConfig.passive&&(console.warn("[MobileInputs] passive=true prevents preventDefault() from working! Setting passive=false."),this.mobileConfig.passive=!1),this.boundHandlers={touchStart:this.handleTouchStart.bind(this),touchEnd:this.handleTouchEnd.bind(this),touchMove:this.handleTouchMove.bind(this),touchCancel:this.handleTouchCancel.bind(this),orientationChange:this.handleOrientationChange.bind(this)}}start(){if(this.isActive)return;let e={passive:!this.mobileConfig.preventDefault&&this.mobileConfig.passive};this.targetElement.addEventListener("touchstart",this.boundHandlers.touchStart,e),this.targetElement.addEventListener("touchend",this.boundHandlers.touchEnd,e),this.targetElement.addEventListener("touchmove",this.boundHandlers.touchMove,e),this.targetElement.addEventListener("touchcancel",this.boundHandlers.touchCancel,e),window.addEventListener("orientationchange",this.boundHandlers.orientationChange),this.isActive=!0}stop(){this.isActive&&(this.targetElement.removeEventListener("touchstart",this.boundHandlers.touchStart),this.targetElement.removeEventListener("touchend",this.boundHandlers.touchEnd),this.targetElement.removeEventListener("touchmove",this.boundHandlers.touchMove),this.targetElement.removeEventListener("touchcancel",this.boundHandlers.touchCancel),window.removeEventListener("orientationchange",this.boundHandlers.orientationChange),this.isActive=!1)}reset(){this.touches.clear(),this.nativeToInternal.clear()}resetDelta(){}poll(){for(let e of this.touches.values())e.justTouched=!1,e.justReleased=!1}isTouchActive(e){return e<0||e>=this.maxTouches?!1:this.touches.has(e)}getTouchPosition(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.position.clone():null}getTouchStartPosition(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.startPosition.clone():null}getTouchDelta(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.position.subtract(t.startPosition):null}getTouchCount(){return this.touches.size}isTouchJustStarted(e){if(e<0||e>=this.maxTouches)return!1;let t=this.touches.get(e);return t?t.justTouched:!1}isTouchJustReleased(e){if(e<0||e>=this.maxTouches)return!1;let t=this.touches.get(e);return t?t.justReleased:!1}isAnyTouchJustStarted(){for(let e of this.touches.values())if(e.justTouched)return!0;return!1}getAllTouches(){return Array.from(this.touches.values())}setMobileCallbacks(e){this.mobileCallbacks={...this.mobileCallbacks,...e}}clearMobileCallbacks(){this.mobileCallbacks={}}setCallbacks(e){this.isMobileCallbacks(e)&&this.setMobileCallbacks(e)}isMobileCallbacks(e){return typeof e=="object"&&e!==null&&("onTouchStart"in e||"onTouchEnd"in e||"onTouchMove"in e||"onTouchCancel"in e||"onOrientationChange"in e)}handleTouchStart(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=Array.from(e.changedTouches),o=[];for(let n of t){if(this.touches.size>=this.maxTouches)break;let i=-1;for(let h=0;h<this.maxTouches;h++)if(!this.touches.has(h)){i=h;break}if(i===-1)continue;let a=new Y.Vector2(n.clientX,n.clientY),c={id:i,nativeId:n.identifier,position:a.clone(),startPosition:a.clone(),active:!0,justTouched:!0,justReleased:!1};this.touches.set(i,c),this.nativeToInternal.set(n.identifier,i),o.push(c),console.warn(`\u{1F446} Touch START - ID: ${i}`)}this.mobileCallbacks.onTouchStart?.(o,e)}catch(t){console.error("Error in touch start handler:",t)}}handleTouchEnd(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=Array.from(e.changedTouches),o=[];for(let n of t){let i=this.nativeToInternal.get(n.identifier);if(i!==void 0){let a=this.touches.get(i);a&&(a.justReleased=!0,a.justTouched=!1,o.push({...a}))}}for(let n of t){let i=this.nativeToInternal.get(n.identifier);i!==void 0&&(this.touches.delete(i),this.nativeToInternal.delete(n.identifier),console.warn(`\u{1F447} Touch END - ID: ${i}`))}this.mobileCallbacks.onTouchEnd?.(o,e)}catch(t){console.error("Error in touch end handler:",t)}}handleTouchMove(e){try{let t=Array.from(e.changedTouches);this.mobileConfig.debug&&(!this.lastLogTime||Date.now()-this.lastLogTime>200)&&(console.warn(`\u{1F504} TouchMove event - ${t.length} touches changed`),this.lastLogTime=Date.now());for(let o of t){let n=this.nativeToInternal.get(o.identifier);if(n!==void 0){let i=this.touches.get(n);if(i){let a=i.position.clone();i.position=new Y.Vector2(o.clientX,o.clientY),this.mobileConfig.debug&&(!this.lastLogTime||Date.now()-this.lastLogTime>200)&&console.warn(`\u{1F504} Updated touch ${i.id} (native ${o.identifier}) - ${a.x.toFixed(1)},${a.y.toFixed(1)} \u2192 ${o.clientX.toFixed(1)},${o.clientY.toFixed(1)}`)}}else this.mobileConfig.debug&&console.warn(`\u26A0\uFE0F Touch move for unknown native ID ${o.identifier}`)}this.mobileCallbacks.onTouchMove?.(this.getAllTouches(),e)}catch(t){console.error("Error in touch move handler:",t)}}handleTouchCancel(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=[],o=Array.from(e.changedTouches);for(let n of o){let i=this.nativeToInternal.get(n.identifier);if(i!==void 0){let a=this.touches.get(i);a&&(a.justReleased=!0,a.justTouched=!1,t.push({...a}))}}for(let n of o){let i=this.nativeToInternal.get(n.identifier);i!==void 0&&(this.touches.delete(i),this.nativeToInternal.delete(n.identifier),this.mobileConfig.debug&&console.warn(`\u274C Touch CANCEL - ID: ${i}, nativeId: ${n.identifier}`))}this.mobileCallbacks.onTouchCancel?.(t,e)}catch(t){console.error("Error in touch cancel handler:",t)}}handleOrientationChange(e){try{let t=(window.screen.orientation&&window.screen.orientation.angle)??window.orientation??0;this.mobileCallbacks.onOrientationChange?.(t)}catch(t){console.error("Error in orientation change handler:",t)}}};m(X,"MobileInputs");var w=X;function ee(d,s,e){console.warn("[MobileInputs] useMobileInputs() is deprecated and causes memory leaks. Use useMemo + useEffect instead.");let t=new w(d,e);return s&&t.setCallbacks(s),t.start(),t}m(ee,"useMobileInputs");var N=class N extends f{constructor(e={}){super(window,e);l(this,"gamepads",new Map);l(this,"previousGamepads",new Map);l(this,"gamepadCallbacks",{});l(this,"gamepadConfig");l(this,"pollingIntervalId",null);l(this,"rafId",null);l(this,"boundHandlers");this.gamepadConfig={targetElement:window,maxGamepads:e.maxGamepads??4,axisDeadzone:e.axisDeadzone??.1,pollingInterval:e.pollingInterval??16,autoPolling:e.autoPolling??!0,enabled:e.enabled??!0,debug:e.debug??!1,preventDefault:e.preventDefault??!1,stopPropagation:e.stopPropagation??!1},this.boundHandlers={connected:this.handleGamepadConnected.bind(this),disconnected:this.handleGamepadDisconnected.bind(this)}}start(){this.isActive||(window.addEventListener("gamepadconnected",this.boundHandlers.connected),window.addEventListener("gamepaddisconnected",this.boundHandlers.disconnected),this.gamepadConfig.autoPolling&&this.startPolling(),this.isActive=!0,this.log("GamepadInputs started"))}stop(){this.isActive&&(window.removeEventListener("gamepadconnected",this.boundHandlers.connected),window.removeEventListener("gamepaddisconnected",this.boundHandlers.disconnected),this.stopPolling(),this.isActive=!1,this.log("GamepadInputs stopped"))}reset(){this.gamepads.clear(),this.previousGamepads.clear()}resetDelta(){this.previousGamepads.clear(),this.gamepads.forEach((e,t)=>{this.previousGamepads.set(t,this.cloneGamepadState(e))})}startPolling(){if(this.pollingIntervalId!==null||this.rafId!==null)return;let e=m(()=>{this.poll(),this.rafId=requestAnimationFrame(e)},"poll");this.rafId=requestAnimationFrame(e),this.log("Polling started")}stopPolling(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.pollingIntervalId!==null&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null),this.log("Polling stopped")}poll(){let e=navigator.getGamepads?navigator.getGamepads():[];for(let t=0;t<e.length&&t<this.gamepadConfig.maxGamepads;t++){let o=e[t];o&&this.updateGamepadState(o)}}getConnectedGamepadCount(){return this.gamepads.size}isGamepadConnected(e){return this.gamepads.has(e)&&this.gamepads.get(e).connected}getGamepadState(e){return this.gamepads.get(e)||null}getAllGamepads(){return Array.from(this.gamepads.values()).filter(e=>e.connected)}isButtonPressed(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?!1:o.buttons[t].pressed}isButtonJustPressed(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?!1:o.buttons[t].justPressed}isButtonJustReleased(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?!1:o.buttons[t].justReleased}getButtonValue(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?0:o.buttons[t].value}getAxis(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid axisIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);if(!o||!o.connected||t>=o.axes.length)return 0;let n=o.axes[t];return this.applyDeadzone(n)}getAxisRaw(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid axisIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.axes.length?0:o.axes[t]}getLeftStick(e){return{x:this.getAxis(e,0),y:this.getAxis(e,1)}}getRightStick(e){return{x:this.getAxis(e,2),y:this.getAxis(e,3)}}setGamepadCallbacks(e){this.gamepadCallbacks={...this.gamepadCallbacks,...e}}clearGamepadCallbacks(){this.gamepadCallbacks={}}setCallbacks(e){this.isGamepadCallbacks(e)&&this.setGamepadCallbacks(e)}isGamepadCallbacks(e){return typeof e=="object"&&e!==null&&("onGamepadConnected"in e||"onGamepadDisconnected"in e||"onButtonDown"in e||"onButtonUp"in e||"onAxisMove"in e)}updateGamepadState(e){let t=this.gamepads.get(e.index),o=Array.from(e.buttons).map((a,c)=>{let h=t?.buttons[c],M=a.pressed,g=h?.pressed??!1;return{pressed:M,justPressed:M&&!g,justReleased:!M&&g,value:a.value,touched:a.touched??!1}}),n=Array.from(e.axes),i={id:e.id,index:e.index,connected:e.connected,buttons:o,axes:n,timestamp:e.timestamp,mapping:e.mapping};this.gamepads.set(e.index,i),this.triggerCallbacks(i,t)}triggerCallbacks(e,t){try{e.buttons.forEach((o,n)=>{o.justPressed&&this.gamepadCallbacks.onButtonDown?.(e.index,n,o.value),o.justReleased&&this.gamepadCallbacks.onButtonUp?.(e.index,n)}),e.axes.forEach((o,n)=>{let i=t?.axes[n]??0,a=this.applyDeadzone(o),c=this.applyDeadzone(i);Math.abs(a-c)>.01&&this.gamepadCallbacks.onAxisMove?.(e.index,n,a)})}catch(o){this.log("Error in gamepad callbacks:",o)}}handleGamepadConnected(e){try{this.log(`Gamepad connected: ${e.gamepad.id} at index ${e.gamepad.index}`);let t={id:e.gamepad.id,index:e.gamepad.index,connected:!0,buttons:Array.from(e.gamepad.buttons).map(o=>({pressed:o.pressed,justPressed:!1,justReleased:!1,value:o.value,touched:o.touched??!1})),axes:Array.from(e.gamepad.axes),timestamp:e.gamepad.timestamp,mapping:e.gamepad.mapping};this.gamepads.set(e.gamepad.index,t),this.gamepadCallbacks.onGamepadConnected?.(t)}catch(t){this.log("Error handling gamepad connected:",t)}}handleGamepadDisconnected(e){try{this.log(`Gamepad disconnected at index ${e.gamepad.index}`),this.gamepads.delete(e.gamepad.index),this.previousGamepads.delete(e.gamepad.index),this.gamepadCallbacks.onGamepadDisconnected?.(e.gamepad.index)}catch(t){this.log("Error handling gamepad disconnected:",t)}}applyDeadzone(e){let t=this.gamepadConfig.axisDeadzone;return Math.abs(e)<t?0:(e>0?1:-1)*((Math.abs(e)-t)/(1-t))}cloneGamepadState(e){return{...e,buttons:e.buttons.map(t=>({...t})),axes:[...e.axes]}}};m(N,"GamepadInputs");var x=N;function te(d,s){let e=new x(s);return d&&e.setGamepadCallbacks(d),e.start(),e}m(te,"useGamepadInputs");var r=require("@utsp/types");var F=class F{constructor(s={}){l(this,"keyboard",null);l(this,"mouse",null);l(this,"gamepad",null);l(this,"mobile",null);l(this,"config");this.config={enableKeyboardMouse:s.enableKeyboardMouse??!0,enableGamepad:s.enableGamepad??!0,enableMobile:s.enableMobile??!1,targetElement:s.targetElement??window,mobileTargetElement:s.mobileTargetElement??s.targetElement??window,debug:s.debug??!1,keyboardConfig:{preventDefault:!1,stopPropagation:!1,...s.keyboardConfig},mouseConfig:{preventDefault:!1,stopPropagation:!1,...s.mouseConfig},mobileConfig:{preventDefault:!0,passive:!1,maxTouches:10,...s.mobileConfig}},this.initialize()}initialize(){this.config.enableKeyboardMouse&&(this.keyboard=new C(this.config.targetElement,{preventDefault:this.config.keyboardConfig?.preventDefault??!1,stopPropagation:this.config.keyboardConfig?.stopPropagation??!1,debug:this.config.debug}),this.keyboard.start(),this.mouse=new I(this.config.targetElement,{preventDefault:this.config.mouseConfig?.preventDefault??!1,stopPropagation:this.config.mouseConfig?.stopPropagation??!1,debug:this.config.debug}),this.mouse.start(),this.log("Keyboard/Mouse initialized")),this.config.enableGamepad&&(this.gamepad=new x({debug:this.config.debug}),this.gamepad.start(),this.log("Gamepad initialized")),this.config.enableMobile&&(this.config.mobileTargetElement?(this.mobile=new w(this.config.mobileTargetElement,this.config.mobileConfig),this.mobile.start(),this.log("Mobile/Touch initialized")):this.warn("Mobile input enabled but no canvas provided - mobile input will be disabled until setMobileTarget() is called"))}getButton(s,e){if(!(0,r.isButton)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case r.InputDeviceType.Keyboard:return this.getKeyboardButton(e);case r.InputDeviceType.Mouse:return this.getMouseButton(e);case r.InputDeviceType.Gamepad:return this.getGamepadButton(e);case r.InputDeviceType.Touch:return this.getTouchButton(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getButtonJustPressed(s,e){if(!(0,r.isButton)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case r.InputDeviceType.Keyboard:return this.getKeyboardButtonJustPressed(e);case r.InputDeviceType.Mouse:return this.getMouseButtonJustPressed(e);case r.InputDeviceType.Gamepad:return this.getGamepadButtonJustPressed(e);case r.InputDeviceType.Touch:return this.getTouchButtonJustPressed(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getButtonJustReleased(s,e){if(!(0,r.isButton)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case r.InputDeviceType.Keyboard:return this.getKeyboardButtonJustReleased(e);case r.InputDeviceType.Mouse:return this.getMouseButtonJustReleased(e);case r.InputDeviceType.Gamepad:return this.getGamepadButtonJustReleased(e);case r.InputDeviceType.Touch:return this.getTouchButtonJustReleased(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getAxis(s,e){if(!(0,r.isAxis)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not an axis`),0;switch(s){case r.InputDeviceType.Keyboard:return this.warn("Keyboard does not have axis inputs"),0;case r.InputDeviceType.Mouse:return this.getMouseAxis(e);case r.InputDeviceType.Gamepad:return this.getGamepadAxis(e);case r.InputDeviceType.Touch:return this.getTouchAxis(e);default:return this.warn(`Unknown device type: ${s}`),0}}isLeftMousePressed(){return this.mouse?this.mouse.isLeftMousePressed():!1}getKeyboardButton(s){if(!this.keyboard)return!1;let e=r.KeyboardInput[s];return this.keyboard.isKeyPressed(e)}getKeyboardButtonJustPressed(s){if(!this.keyboard)return!1;let e=r.KeyboardInput[s];return this.keyboard.isKeyJustPressed(e)}getKeyboardButtonJustReleased(s){if(!this.keyboard)return!1;let e=r.KeyboardInput[s];return this.keyboard.isKeyJustReleased(e)}getMouseButton(s){if(!this.mouse)return!1;switch(s){case r.MouseInput.LeftButton:return this.mouse.isLeftMousePressed();case r.MouseInput.RightButton:return this.mouse.isRightMousePressed();case r.MouseInput.MiddleButton:return this.mouse.isMiddleMousePressed();default:return!1}}getMouseButtonJustPressed(s){if(!this.mouse)return!1;switch(s){case r.MouseInput.LeftButton:return this.mouse.isLeftMouseJustPressed();case r.MouseInput.RightButton:return this.mouse.isRightMouseJustPressed();case r.MouseInput.MiddleButton:return this.mouse.isMiddleMouseJustPressed();default:return!1}}getMouseButtonJustReleased(s){if(!this.mouse)return!1;switch(s){case r.MouseInput.LeftButton:return this.mouse.isLeftMouseJustReleased();case r.MouseInput.RightButton:return this.mouse.isRightMouseJustReleased();case r.MouseInput.MiddleButton:return this.mouse.isMiddleMouseJustReleased();default:return!1}}getGamepadButton(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonPressed(0,s)}getGamepadButtonJustPressed(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonJustPressed(0,s)}getGamepadButtonJustReleased(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonJustReleased(0,s)}getTouchButton(s){return this.mobile?s>=100?!1:this.mobile.isTouchActive?.(s)??!1:(console.warn("\u{1F6AB} MobileInputs not initialized!"),!1)}getTouchButtonJustPressed(s){return!this.mobile||s>=100?!1:this.mobile.isTouchJustStarted?.(s)??!1}getTouchButtonJustReleased(s){return!this.mobile||s>=100?!1:this.mobile.isTouchJustReleased?.(s)??!1}getMouseAxis(s){if(!this.mouse)return 0;switch(s){case r.MouseInput.PositionX:return this.mouse.getMousePosition().x;case r.MouseInput.PositionY:return this.mouse.getMousePosition().y;case r.MouseInput.DeltaX:return this.mouse.getMouseDelta().x;case r.MouseInput.DeltaY:return this.mouse.getMouseDelta().y;case r.MouseInput.WheelDeltaY:return this.mouse.getWheelDelta();default:return 0}}getGamepadAxis(s){if(!this.gamepad||s<100)return 0;let e=s-100;return this.gamepad.getAxis(0,e)}getTouchAxis(s){if(!this.mobile)return 0;if(s>=100&&s<200){let e=Math.floor((s-100)/2),t=(s-100)%2===0,o=this.mobile.getTouchPosition?.(e);return this.config.debug&&o&&console.warn(`\u{1F3AF} getTouchAxis(${s}) - touchIndex: ${e}, ${t?"X":"Y"}: ${t?o.x:o.y}`),o?t?o.x:o.y:0}return 0}getMousePosition(){if(!this.mouse)return null;let s=this.mouse.getMousePosition();return{x:s.x,y:s.y}}setMobileTarget(s){if(!s){this.warn("setMobileTarget() called with null/undefined canvas - mobile input will remain disabled");return}if(this.config.mobileTargetElement=s,!this.config.enableMobile){this.warn("setMobileTarget() called but mobile input is disabled in config");return}this.mobile&&this.mobile.stop(),this.mobile=new w(s,this.config.mobileConfig),this.mobile.start()}getTextInputs(){return this.keyboard?this.keyboard.getTextInputs():[]}start(){this.keyboard?.start(),this.mouse?.start(),this.log("Input router started")}stop(){this.keyboard?.stop(),this.mouse?.stop(),this.log("Input router stopped")}reset(){this.keyboard?.reset(),this.mouse?.reset(),this.log("Input router reset")}poll(){this.keyboard?.poll(),this.mouse?.poll(),this.gamepad?.poll(),this.mobile?.poll()}isListening(){return this.keyboard!==null&&this.config.enableKeyboardMouse||this.gamepad!==null&&this.config.enableGamepad||this.mobile!==null&&this.config.enableMobile}destroy(){this.keyboard?.destroy(),this.mouse?.destroy(),this.keyboard=null,this.mouse=null,this.gamepad=null,this.mobile=null,this.log("Input router destroyed")}log(s){this.config.debug&&console.warn(`[InputRouter] ${s}`)}warn(s){console.warn(`[InputRouter] ${s}`)}};m(F,"UnifiedInputRouter");var L=F;var u=require("@utsp/types");var O=class O{static collectAxisSources(s,e){let t=new Map;for(let o of s)for(let n of o.sources){if(t.has(n.sourceId))continue;let i=0,a=!1;if(n.type===u.InputDeviceType.Keyboard&&n.negativeKey!==void 0&&n.positiveKey!==void 0){let c=e.getButton(u.InputDeviceType.Keyboard,n.negativeKey);e.getButton(u.InputDeviceType.Keyboard,n.positiveKey)&&(i+=1),c&&(i-=1),a=!0}else if(n.type===u.InputDeviceType.Mouse&&n.mouseAxis!==void 0)i=e.getAxis(u.InputDeviceType.Mouse,n.mouseAxis),a=!0;else if(n.type===u.InputDeviceType.Gamepad&&n.axis!==void 0)i=e.getAxis(u.InputDeviceType.Gamepad,n.axis),a=!0;else if(n.type===u.InputDeviceType.Touch&&n.touchId!==void 0&&n.touchAxis!==void 0){let c=100+n.touchId*2,h=n.touchAxis==="x"?c:c+1;i=e.getAxis(u.InputDeviceType.Touch,h),a=!0}a&&t.set(n.sourceId,i)}return t}static collectButtonSources(s,e){let t=new Map;for(let o of s)for(let n of o.sources){if(t.has(n.sourceId))continue;let i=!1,a=!1;n.type===u.InputDeviceType.Keyboard&&n.key!==void 0?(i=e.getButton(u.InputDeviceType.Keyboard,n.key),a=!0):n.type===u.InputDeviceType.Mouse&&n.mouseButton!==void 0?(i=e.getButton(u.InputDeviceType.Mouse,n.mouseButton),a=!0):n.type===u.InputDeviceType.Gamepad&&n.button!==void 0?(i=e.getButton(u.InputDeviceType.Gamepad,n.button),a=!0):n.type===u.InputDeviceType.Touch&&n.touchButton!==void 0&&(i=e.getButton(u.InputDeviceType.Touch,n.touchButton),a=!0),a&&t.set(n.sourceId,i)}return t}static collectButtonSourcesWithTransitions(s,e){let t=new Map;for(let o of s)for(let n of o.sources){if(t.has(n.sourceId))continue;let i=!1,a=!1,c=!1,h=!1;n.type===u.InputDeviceType.Keyboard&&n.key!==void 0?(i=e.getButton(u.InputDeviceType.Keyboard,n.key),a=e.getButtonJustPressed?.(u.InputDeviceType.Keyboard,n.key)??!1,c=e.getButtonJustReleased?.(u.InputDeviceType.Keyboard,n.key)??!1,h=!0):n.type===u.InputDeviceType.Mouse&&n.mouseButton!==void 0?(i=e.getButton(u.InputDeviceType.Mouse,n.mouseButton),a=e.getButtonJustPressed?.(u.InputDeviceType.Mouse,n.mouseButton)??!1,c=e.getButtonJustReleased?.(u.InputDeviceType.Mouse,n.mouseButton)??!1,h=!0):n.type===u.InputDeviceType.Gamepad&&n.button!==void 0?(i=e.getButton(u.InputDeviceType.Gamepad,n.button),a=e.getButtonJustPressed?.(u.InputDeviceType.Gamepad,n.button)??!1,c=e.getButtonJustReleased?.(u.InputDeviceType.Gamepad,n.button)??!1,h=!0):n.type===u.InputDeviceType.Touch&&n.touchButton!==void 0&&(i=e.getButton(u.InputDeviceType.Touch,n.touchButton),a=e.getButtonJustPressed?.(u.InputDeviceType.Touch,n.touchButton)??!1,c=e.getButtonJustReleased?.(u.InputDeviceType.Touch,n.touchButton)??!1,h=!0),h&&t.set(n.sourceId,{pressed:i,justPressed:a,justReleased:c})}return t}static collectMousePosition(s,e,t,o,n){let i=s.getAxis(u.InputDeviceType.Mouse,u.MouseInput.PositionX),a=s.getAxis(u.InputDeviceType.Mouse,u.MouseInput.PositionY),c=s.isLeftMousePressed?.()??!1,h=e.getBoundingClientRect(),M=e.width/e.height,g=h.width/h.height,b,p,k,E;M>g?(b=h.width,p=h.width/M,k=0,E=(h.height-p)/2):(b=h.height*M,p=h.height,k=(h.width-b)/2,E=0);let P=n?.offsetX||0,G=n?.offsetY||0;k+=P,E+=G,b-=P*2,p-=G*2;let B=i-h.left-k,v=a-h.top-E,A=b/t,q=p/o,S=Math.floor(B/A),j=Math.floor(v/q),H=B>=0&&B<b&&v>=0&&v<p;return{x:Math.max(0,Math.min(t-1,S)),y:Math.max(0,Math.min(o-1,j)),over:H,isLeftDown:c}}static collectTouchPositions(s,e,t,o,n=10,i){let a=[],c=e.getBoundingClientRect(),h=e.width/e.height,M=c.width/c.height,g,b,p,k;h>M?(g=c.width,b=c.width/h,p=0,k=(c.height-b)/2):(g=c.height*h,b=c.height,p=(c.width-g)/2,k=0);let E=i?.offsetX||0,P=i?.offsetY||0;p+=E,k+=P,g-=E*2,b-=P*2;let G=g/t,B=b/o;for(let v=0;v<n;v++){let A=v;if(s.getButton(u.InputDeviceType.Touch,A)){let S=100+v*2,j=101+v*2,H=s.getAxis(u.InputDeviceType.Touch,S),se=s.getAxis(u.InputDeviceType.Touch,j),J=H-c.left-p,$=se-c.top-k,oe=Math.floor(J/G),ne=Math.floor($/B),ie=J>=0&&J<g&&$>=0&&$<b;a.push({id:v,x:Math.max(0,Math.min(t-1,oe)),y:Math.max(0,Math.min(o-1,ne)),over:ie})}}return a}static collectTextInputs(s){return typeof s.getTextInputs=="function"?s.getTextInputs():[]}};m(O,"InputCollector");var K=O;
1
+ "use strict";var P=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var pe=(d,s,e)=>s in d?P(d,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[s]=e;var h=(d,s)=>P(d,"name",{value:s,configurable:!0});var he=(d,s)=>{for(var e in s)P(d,e,{get:s[e],enumerable:!0})},be=(d,s,e,t)=>{if(s&&typeof s=="object"||typeof s=="function")for(let o of de(s))!ce.call(d,o)&&o!==e&&P(d,o,{get:()=>s[o],enumerable:!(t=le(s,o))||t.enumerable});return d};var me=d=>be(P({},"__esModule",{value:!0}),d);var r=(d,s,e)=>(pe(d,typeof s!="symbol"?s+"":s,e),e);var ge={};he(ge,{BaseInputs:()=>v,GamepadInput:()=>M.GamepadInput,GamepadInputs:()=>C,InputCollector:()=>L,InputDeviceType:()=>M.InputDeviceType,InputEventType:()=>J,KeyboardInput:()=>M.KeyboardInput,KeyboardInputs:()=>E,MobileInputs:()=>w,MobileVibration:()=>B,MouseInput:()=>M.MouseInput,MouseInputs:()=>I,TouchInput:()=>M.TouchInput,UnifiedInputRouter:()=>A,Vector2:()=>K.Vector2,Vector3:()=>K.Vector3,VibrationPatterns:()=>g,getMobileVibration:()=>te,isInputs:()=>Q,useGamepadInputs:()=>se,useKeyboardInputs:()=>Z,useMobileInputs:()=>ee,useMouseInputs:()=>_});module.exports=me(ge);var K=require("@utsp/types"),M=require("@utsp/types");var J=(b=>(b.KeyDown="keydown",b.KeyUp="keyup",b.MouseDown="mousedown",b.MouseUp="mouseup",b.MouseMove="mousemove",b.MouseWheel="mousewheel",b.TouchStart="touchstart",b.TouchEnd="touchend",b.TouchMove="touchmove",b.GamepadConnected="gamepadconnected",b.GamepadDisconnected="gamepaddisconnected",b.GamepadButton="gamepadbutton",b.GamepadAxis="gamepadaxis",b))(J||{}),W=class W{constructor(s=window,e={}){r(this,"isActive",!1);r(this,"targetElement");r(this,"config");r(this,"callbacks",{});this.targetElement=s,this.config={enabled:!0,preventDefault:!1,stopPropagation:!1,debug:!1,...e}}isListening(){return this.isActive}destroy(){this.stop(),this.clearCallbacks()}setCallbacks(s){typeof s=="object"&&s!==null&&Object.assign(this.callbacks,s)}clearCallbacks(){this.callbacks={}}getTargetElement(){return this.targetElement}enable(){this.config.enabled=!0,this.isActive||this.start()}disable(){this.config.enabled=!1,this.isActive&&this.stop()}isEnabled(){return this.config.enabled??!0}emit(s,...e){this.callbacks[s]&&this.callbacks[s].forEach(t=>{try{t(...e)}catch(o){this.config.debug&&console.error(`Error in ${s} callback:`,o)}})}log(...s){this.config.debug&&console.warn("[InputSystem]",...s)}};h(W,"BaseInputs");var v=W;function Q(d){return typeof d=="object"&&d!==null&&"start"in d&&"stop"in d&&"reset"in d&&"isListening"in d&&"destroy"in d}h(Q,"isInputs");var U=class U extends v{constructor(e=window,t={}){super(e,t);r(this,"keys",{});r(this,"keyboardCallbacks",{});r(this,"textInputsThisFrame",[]);r(this,"boundHandlers");this.boundHandlers={keyDown:this.handleKeyDown.bind(this),keyUp:this.handleKeyUp.bind(this)}}start(){this.isActive||(this.targetElement.addEventListener("keydown",this.boundHandlers.keyDown),this.targetElement.addEventListener("keyup",this.boundHandlers.keyUp),this.isActive=!0)}stop(){this.isActive&&(this.targetElement.removeEventListener("keydown",this.boundHandlers.keyDown),this.targetElement.removeEventListener("keyup",this.boundHandlers.keyUp),this.isActive=!1)}reset(){this.keys={}}resetDelta(){}poll(){for(let e in this.keys)this.keys[e].justPressed=!1,this.keys[e].justReleased=!1;this.textInputsThisFrame=[]}getTextInputs(){return this.textInputsThisFrame}isKeyPressed(e){return this.keys[e]?.pressed||!1}isKeyJustPressed(e){return this.keys[e]?.justPressed||!1}isKeyJustReleased(e){return this.keys[e]?.justReleased||!1}getKeysPressed(){return Object.keys(this.keys).filter(e=>this.keys[e].pressed)}getKeysJustPressed(){return Object.keys(this.keys).filter(e=>this.keys[e].justPressed)}getKeysJustReleased(){return Object.keys(this.keys).filter(e=>this.keys[e].justReleased)}isAnyKeyPressed(){return Object.values(this.keys).some(e=>e.pressed)}setKeyboardCallbacks(e){this.keyboardCallbacks={...this.keyboardCallbacks,...e}}clearKeyboardCallbacks(){this.keyboardCallbacks={}}setCallbacks(e){this.isKeyboardCallbacks(e)&&this.setKeyboardCallbacks(e)}isKeyboardCallbacks(e){return typeof e=="object"&&e!==null&&("onKeyDown"in e||"onKeyUp"in e)}shouldAllowDefault(e,t){let o=/^F([1-9]|1[0-2])$/.test(e),n=(t.ctrlKey||t.metaKey)&&(e==="KeyT"||e==="KeyW"||e==="KeyR"||e==="KeyN"||e==="Tab");return o||n}handleKeyDown(e){try{let t=e.code,o=this.shouldAllowDefault(t,e);this.config.preventDefault&&!o&&e.preventDefault(),this.config.stopPropagation&&!o&&e.stopPropagation(),this.keys[t]||(this.keys[t]={pressed:!1,justPressed:!1,justReleased:!1}),this.keys[t].pressed||(this.keys[t].justPressed=!0,this.keyboardCallbacks.onKeyDown?.(t,e)),this.keys[t].pressed=!0,this.keys[t].justReleased=!1;let n=e.key;n.length===1&&!e.ctrlKey&&!e.metaKey&&this.textInputsThisFrame.push(n)}catch(t){console.error("Error in keyboard keydown handler:",t)}}handleKeyUp(e){try{let t=e.code,o=this.shouldAllowDefault(t,e);this.config.preventDefault&&!o&&e.preventDefault(),this.config.stopPropagation&&!o&&e.stopPropagation(),this.keys[t]||(this.keys[t]={pressed:!1,justPressed:!1,justReleased:!1}),this.keys[t].pressed&&(this.keys[t].justReleased=!0,this.keyboardCallbacks.onKeyUp?.(t,e)),this.keys[t].pressed=!1,this.keys[t].justPressed=!1}catch(t){console.error("Error in keyboard keyup handler:",t)}}};h(U,"KeyboardInputs");var E=U;function Z(d,s){let e=new E(d);return s&&e.setCallbacks(s),e.start(),e}h(Z,"useKeyboardInputs");var k=require("@utsp/types");var x=class x extends v{constructor(e=window,t={}){super(e,t);r(this,"mouseButtons",{left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}});r(this,"mousePosition",k.Vector2.zero());r(this,"mouseDelta",k.Vector2.zero());r(this,"wheelDelta",0);r(this,"mouseCallbacks",{});r(this,"boundHandlers");this.boundHandlers={mouseDown:this.handleMouseDown.bind(this),mouseUp:this.handleMouseUp.bind(this),mouseMove:this.handleMouseMove.bind(this),wheel:this.handleWheel.bind(this),mouseEnter:this.handleMouseEnter.bind(this),mouseLeave:this.handleMouseLeave.bind(this),contextMenu:this.handleContextMenu.bind(this)}}start(){this.isActive||(this.targetElement.addEventListener("mousedown",this.boundHandlers.mouseDown),this.targetElement.addEventListener("mouseup",this.boundHandlers.mouseUp),this.targetElement.addEventListener("mousemove",this.boundHandlers.mouseMove),this.targetElement.addEventListener("wheel",this.boundHandlers.wheel),this.targetElement.addEventListener("mouseenter",this.boundHandlers.mouseEnter),this.targetElement.addEventListener("mouseleave",this.boundHandlers.mouseLeave),this.targetElement.addEventListener("contextmenu",this.boundHandlers.contextMenu),this.isActive=!0)}stop(){this.isActive&&(this.targetElement.removeEventListener("mousedown",this.boundHandlers.mouseDown),this.targetElement.removeEventListener("mouseup",this.boundHandlers.mouseUp),this.targetElement.removeEventListener("mousemove",this.boundHandlers.mouseMove),this.targetElement.removeEventListener("wheel",this.boundHandlers.wheel),this.targetElement.removeEventListener("mouseenter",this.boundHandlers.mouseEnter),this.targetElement.removeEventListener("mouseleave",this.boundHandlers.mouseLeave),this.targetElement.removeEventListener("contextmenu",this.boundHandlers.contextMenu),this.isActive=!1)}reset(){this.mouseButtons={left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}},this.mousePosition=k.Vector2.zero(),this.mouseDelta=k.Vector2.zero(),this.wheelDelta=0}poll(){this.mouseButtons.left.justPressed=!1,this.mouseButtons.left.justReleased=!1,this.mouseButtons.middle.justPressed=!1,this.mouseButtons.middle.justReleased=!1,this.mouseButtons.right.justPressed=!1,this.mouseButtons.right.justReleased=!1,this.resetDelta()}resetDelta(){this.mouseDelta=k.Vector2.zero(),this.wheelDelta=0}isLeftMousePressed(){return this.mouseButtons.left.pressed}isLeftMouseJustPressed(){return this.mouseButtons.left.justPressed}isLeftMouseJustReleased(){return this.mouseButtons.left.justReleased}isRightMousePressed(){return this.mouseButtons.right.pressed}isRightMouseJustPressed(){return this.mouseButtons.right.justPressed}isRightMouseJustReleased(){return this.mouseButtons.right.justReleased}isMiddleMousePressed(){return this.mouseButtons.middle.pressed}isMiddleMouseJustPressed(){return this.mouseButtons.middle.justPressed}isMiddleMouseJustReleased(){return this.mouseButtons.middle.justReleased}getMousePosition(){return this.mousePosition.clone()}getMouseDelta(){return this.mouseDelta.clone()}getWheelDelta(){return this.wheelDelta}setMouseCallbacks(e){this.mouseCallbacks={...this.mouseCallbacks,...e}}clearMouseCallbacks(){this.mouseCallbacks={}}setCallbacks(e){this.isMouseCallbacks(e)&&this.setMouseCallbacks(e)}isMouseCallbacks(e){return typeof e=="object"&&e!==null&&("onMouseDown"in e||"onMouseUp"in e||"onMouseMove"in e||"onMouseWheel"in e||"onMouseEnter"in e||"onMouseLeave"in e)}getButtonByIndex(e){let t=x.BUTTON_NAMES[e];return t?{state:this.mouseButtons[t],name:t}:null}handleMouseDown(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation();let t=this.getButtonByIndex(e.button);t&&(t.state.pressed||(t.state.justPressed=!0),t.state.pressed=!0,t.state.justReleased=!1,this.mouseCallbacks.onMouseDown?.(t.name,this.mousePosition,e))}catch(t){console.error("Error in mouse down handler:",t)}}handleMouseUp(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation();let t=this.getButtonByIndex(e.button);t&&(t.state.pressed&&(t.state.justReleased=!0),t.state.pressed=!1,t.state.justPressed=!1,this.mouseCallbacks.onMouseUp?.(t.name,this.mousePosition,e))}catch(t){console.error("Error in mouse up handler:",t)}}handleMouseMove(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation();let t=new k.Vector2(e.clientX,e.clientY);this.mouseDelta=t.subtract(this.mousePosition),this.mousePosition=t,this.mouseCallbacks.onMouseMove?.(this.mousePosition,this.mouseDelta,e)}catch(t){console.error("Error in mouse move handler:",t)}}handleWheel(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),this.wheelDelta=e.deltaY,this.mouseCallbacks.onMouseWheel?.(this.wheelDelta,e)}catch(t){console.error("Error in mouse wheel handler:",t)}}handleMouseEnter(e){try{this.mouseCallbacks.onMouseEnter?.(e)}catch(t){console.error("Error in mouse enter handler:",t)}}handleMouseLeave(e){try{this.mouseCallbacks.onMouseLeave?.(e)}catch(t){console.error("Error in mouse leave handler:",t)}}handleContextMenu(e){try{e.preventDefault(),this.config.stopPropagation&&e.stopPropagation()}catch(t){console.error("Error in context menu handler:",t)}}};h(x,"MouseInputs"),r(x,"BUTTON_NAMES",["left","middle","right"]);var I=x;function _(d,s){let e=new I(d);return s&&e.setCallbacks(s),e.start(),e}h(_,"useMouseInputs");var X=require("@utsp/types");var Y=class Y extends v{constructor(e=window,t={}){super(e,t);r(this,"touches",new Map);r(this,"nativeToInternal",new Map);r(this,"mobileCallbacks",{});r(this,"mobileConfig");r(this,"maxTouches",10);r(this,"lastLogTime",0);r(this,"boundHandlers");this.mobileConfig={targetElement:e,preventDefault:t.preventDefault??!0,passive:t.passive??!1,maxTouches:t.maxTouches??10,enabled:t.enabled??!0,debug:t.debug??!1,stopPropagation:t.stopPropagation??!1},this.maxTouches=this.mobileConfig.maxTouches,this.mobileConfig.preventDefault&&this.mobileConfig.passive&&(console.warn("[MobileInputs] passive=true prevents preventDefault() from working! Setting passive=false."),this.mobileConfig.passive=!1),this.boundHandlers={touchStart:this.handleTouchStart.bind(this),touchEnd:this.handleTouchEnd.bind(this),touchMove:this.handleTouchMove.bind(this),touchCancel:this.handleTouchCancel.bind(this),orientationChange:this.handleOrientationChange.bind(this)}}start(){if(this.isActive)return;let e={passive:!this.mobileConfig.preventDefault&&this.mobileConfig.passive};this.targetElement.addEventListener("touchstart",this.boundHandlers.touchStart,e),this.targetElement.addEventListener("touchend",this.boundHandlers.touchEnd,e),this.targetElement.addEventListener("touchmove",this.boundHandlers.touchMove,e),this.targetElement.addEventListener("touchcancel",this.boundHandlers.touchCancel,e),window.addEventListener("orientationchange",this.boundHandlers.orientationChange),this.isActive=!0}stop(){this.isActive&&(this.targetElement.removeEventListener("touchstart",this.boundHandlers.touchStart),this.targetElement.removeEventListener("touchend",this.boundHandlers.touchEnd),this.targetElement.removeEventListener("touchmove",this.boundHandlers.touchMove),this.targetElement.removeEventListener("touchcancel",this.boundHandlers.touchCancel),window.removeEventListener("orientationchange",this.boundHandlers.orientationChange),this.isActive=!1)}reset(){this.touches.clear(),this.nativeToInternal.clear()}resetDelta(){}poll(){for(let e of this.touches.values())e.justTouched=!1,e.justReleased=!1}isTouchActive(e){return e<0||e>=this.maxTouches?!1:this.touches.has(e)}getTouchPosition(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.position.clone():null}getTouchStartPosition(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.startPosition.clone():null}getTouchDelta(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.position.subtract(t.startPosition):null}getTouchCount(){return this.touches.size}isTouchJustStarted(e){if(e<0||e>=this.maxTouches)return!1;let t=this.touches.get(e);return t?t.justTouched:!1}isTouchJustReleased(e){if(e<0||e>=this.maxTouches)return!1;let t=this.touches.get(e);return t?t.justReleased:!1}isAnyTouchJustStarted(){for(let e of this.touches.values())if(e.justTouched)return!0;return!1}getAllTouches(){return Array.from(this.touches.values())}setMobileCallbacks(e){this.mobileCallbacks={...this.mobileCallbacks,...e}}clearMobileCallbacks(){this.mobileCallbacks={}}setCallbacks(e){this.isMobileCallbacks(e)&&this.setMobileCallbacks(e)}isMobileCallbacks(e){return typeof e=="object"&&e!==null&&("onTouchStart"in e||"onTouchEnd"in e||"onTouchMove"in e||"onTouchCancel"in e||"onOrientationChange"in e)}handleTouchStart(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=Array.from(e.changedTouches),o=[];for(let n of t){if(this.touches.size>=this.maxTouches)break;let i=-1;for(let c=0;c<this.maxTouches;c++)if(!this.touches.has(c)){i=c;break}if(i===-1)continue;let a=new X.Vector2(n.clientX,n.clientY),p={id:i,nativeId:n.identifier,position:a.clone(),startPosition:a.clone(),active:!0,justTouched:!0,justReleased:!1};this.touches.set(i,p),this.nativeToInternal.set(n.identifier,i),o.push(p),console.warn(`\u{1F446} Touch START - ID: ${i}`)}this.mobileCallbacks.onTouchStart?.(o,e)}catch(t){console.error("Error in touch start handler:",t)}}handleTouchEnd(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=Array.from(e.changedTouches),o=[];for(let n of t){let i=this.nativeToInternal.get(n.identifier);if(i!==void 0){let a=this.touches.get(i);a&&(a.justReleased=!0,a.justTouched=!1,o.push({...a}))}}for(let n of t){let i=this.nativeToInternal.get(n.identifier);i!==void 0&&(this.touches.delete(i),this.nativeToInternal.delete(n.identifier),console.warn(`\u{1F447} Touch END - ID: ${i}`))}this.mobileCallbacks.onTouchEnd?.(o,e)}catch(t){console.error("Error in touch end handler:",t)}}handleTouchMove(e){try{let t=Array.from(e.changedTouches);this.mobileConfig.debug&&(!this.lastLogTime||Date.now()-this.lastLogTime>200)&&(console.warn(`\u{1F504} TouchMove event - ${t.length} touches changed`),this.lastLogTime=Date.now());for(let o of t){let n=this.nativeToInternal.get(o.identifier);if(n!==void 0){let i=this.touches.get(n);if(i){let a=i.position.clone();i.position=new X.Vector2(o.clientX,o.clientY),this.mobileConfig.debug&&(!this.lastLogTime||Date.now()-this.lastLogTime>200)&&console.warn(`\u{1F504} Updated touch ${i.id} (native ${o.identifier}) - ${a.x.toFixed(1)},${a.y.toFixed(1)} \u2192 ${o.clientX.toFixed(1)},${o.clientY.toFixed(1)}`)}}else this.mobileConfig.debug&&console.warn(`\u26A0\uFE0F Touch move for unknown native ID ${o.identifier}`)}this.mobileCallbacks.onTouchMove?.(this.getAllTouches(),e)}catch(t){console.error("Error in touch move handler:",t)}}handleTouchCancel(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=[],o=Array.from(e.changedTouches);for(let n of o){let i=this.nativeToInternal.get(n.identifier);if(i!==void 0){let a=this.touches.get(i);a&&(a.justReleased=!0,a.justTouched=!1,t.push({...a}))}}for(let n of o){let i=this.nativeToInternal.get(n.identifier);i!==void 0&&(this.touches.delete(i),this.nativeToInternal.delete(n.identifier),this.mobileConfig.debug&&console.warn(`\u274C Touch CANCEL - ID: ${i}, nativeId: ${n.identifier}`))}this.mobileCallbacks.onTouchCancel?.(t,e)}catch(t){console.error("Error in touch cancel handler:",t)}}handleOrientationChange(e){try{let t=(window.screen.orientation&&window.screen.orientation.angle)??window.orientation??0;this.mobileCallbacks.onOrientationChange?.(t)}catch(t){console.error("Error in orientation change handler:",t)}}};h(Y,"MobileInputs");var w=Y;function ee(d,s,e){console.warn("[MobileInputs] useMobileInputs() is deprecated and causes memory leaks. Use useMemo + useEffect instead.");let t=new w(d,e);return s&&t.setCallbacks(s),t.start(),t}h(ee,"useMobileInputs");var g={tap:10,mediumTap:25,heavyTap:50,success:[30,50,30],error:[50,30,50,30,50],warning:[100],selection:5,impactLight:15,impactMedium:30,impactHeavy:50,notification:[100,100,100,100,100],sos:[100,30,100,30,100,30,200,30,200,30,200,30,100,30,100,30,100]},N=class N{constructor(s={}){r(this,"config");r(this,"supported",!1);r(this,"userActivated",!1);this.config={enabled:s.enabled??!0,debug:s.debug??!1,intensity:Math.max(0,Math.min(1,s.intensity??1))},this.supported=typeof navigator<"u"&&"vibrate"in navigator,this.config.debug&&console.log(`[MobileVibration] Vibration API supported: ${this.supported}`)}isSupported(){return this.supported}isEnabled(){return this.config.enabled&&this.supported}setEnabled(s){this.config.enabled=s,this.config.debug&&console.log(`[MobileVibration] Enabled: ${s}`)}setIntensity(s){this.config.intensity=Math.max(0,Math.min(1,s)),this.config.debug&&console.log(`[MobileVibration] Intensity set to: ${this.config.intensity}`)}getIntensity(){return this.config.intensity}vibrate(s){if(!this.isEnabled())return!1;try{let e=this.scalePattern(s),t=typeof e=="number"?e:[...e],o=navigator.vibrate(t);return this.config.debug&&console.log(`[MobileVibration] Vibrate: ${JSON.stringify(e)} -> ${o}`),o&&(this.userActivated=!0),o}catch(e){return this.config.debug&&console.error("[MobileVibration] Vibration failed:",e),!1}}cancel(){this.supported&&(navigator.vibrate(0),this.config.debug&&console.log("[MobileVibration] Vibration cancelled"))}hasUserActivation(){return this.userActivated}tap(){return this.vibrate(g.tap)}mediumTap(){return this.vibrate(g.mediumTap)}heavyTap(){return this.vibrate(g.heavyTap)}success(){return this.vibrate(g.success)}error(){return this.vibrate(g.error)}warning(){return this.vibrate(g.warning)}selection(){return this.vibrate(g.selection)}impactLight(){return this.vibrate(g.impactLight)}impactMedium(){return this.vibrate(g.impactMedium)}impactHeavy(){return this.vibrate(g.impactHeavy)}notification(){return this.vibrate(g.notification)}scalePattern(s){return this.config.intensity===1?s:typeof s=="number"?Math.round(s*this.config.intensity):s.map((e,t)=>t%2===0?Math.round(e*this.config.intensity):e)}};h(N,"MobileVibration");var B=N,z=null;function te(){return z||(z=new B),z}h(te,"getMobileVibration");var fe=.01,O=class O extends v{constructor(e={}){super(window,e);r(this,"gamepads",new Map);r(this,"previousGamepads",new Map);r(this,"gamepadCallbacks",{});r(this,"gamepadConfig");r(this,"pollingIntervalId",null);r(this,"rafId",null);r(this,"boundHandlers");r(this,"vibrationPresets",{tap:{duration:50,strongMagnitude:.3,weakMagnitude:.5},impact:{duration:100,strongMagnitude:.7,weakMagnitude:.3},heavy:{duration:200,strongMagnitude:1,weakMagnitude:.2},success:{duration:150,strongMagnitude:.4,weakMagnitude:.6},error:{duration:300,strongMagnitude:.8,weakMagnitude:.4},explosion:{duration:400,strongMagnitude:1,weakMagnitude:.8},engine:{duration:1e3,strongMagnitude:.5,weakMagnitude:.2},heartbeat:{duration:100,strongMagnitude:.6,weakMagnitude:.1}});this.gamepadConfig={targetElement:window,maxGamepads:e.maxGamepads??4,axisDeadzone:e.axisDeadzone??.1,pollingInterval:e.pollingInterval??16,autoPolling:e.autoPolling??!0,enabled:e.enabled??!0,debug:e.debug??!1,preventDefault:e.preventDefault??!1,stopPropagation:e.stopPropagation??!1},this.boundHandlers={connected:this.handleGamepadConnected.bind(this),disconnected:this.handleGamepadDisconnected.bind(this)}}start(){this.isActive||(window.addEventListener("gamepadconnected",this.boundHandlers.connected),window.addEventListener("gamepaddisconnected",this.boundHandlers.disconnected),this.gamepadConfig.autoPolling&&this.startPolling(),this.isActive=!0,this.log("GamepadInputs started"))}stop(){this.isActive&&(window.removeEventListener("gamepadconnected",this.boundHandlers.connected),window.removeEventListener("gamepaddisconnected",this.boundHandlers.disconnected),this.stopPolling(),this.isActive=!1,this.log("GamepadInputs stopped"))}reset(){this.gamepads.clear(),this.previousGamepads.clear()}resetDelta(){this.previousGamepads.clear(),this.gamepads.forEach((e,t)=>{this.previousGamepads.set(t,this.cloneGamepadState(e))})}startPolling(){if(this.pollingIntervalId!==null||this.rafId!==null)return;let e=h(()=>{this.poll(),this.rafId=requestAnimationFrame(e)},"poll");this.rafId=requestAnimationFrame(e),this.log("Polling started")}stopPolling(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.pollingIntervalId!==null&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null),this.log("Polling stopped")}poll(){let e=navigator.getGamepads?navigator.getGamepads():[];for(let t=0;t<e.length&&t<this.gamepadConfig.maxGamepads;t++){let o=e[t];o&&this.updateGamepadState(o)}}getConnectedGamepadCount(){return this.gamepads.size}isGamepadConnected(e){return this.gamepads.has(e)&&this.gamepads.get(e).connected}getGamepadState(e){return this.gamepads.get(e)||null}getAllGamepads(){return Array.from(this.gamepads.values()).filter(e=>e.connected)}isButtonPressed(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?!1:o.buttons[t].pressed}isButtonJustPressed(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?!1:o.buttons[t].justPressed}isButtonJustReleased(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?!1:o.buttons[t].justReleased}getButtonValue(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.buttons.length?0:o.buttons[t].value}getAxis(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid axisIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);if(!o||!o.connected||t>=o.axes.length)return 0;let n=o.axes[t];return this.applyDeadzone(n)}getAxisRaw(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid axisIndex: ${t}. Must be a non-negative integer.`);let o=this.gamepads.get(e);return!o||!o.connected||t>=o.axes.length?0:o.axes[t]}getLeftStick(e){return{x:this.getAxis(e,0),y:this.getAxis(e,1)}}getRightStick(e){return{x:this.getAxis(e,2),y:this.getAxis(e,3)}}supportsVibration(e){let t=this.getNativeGamepad(e);if(!t)return!1;let o=t.vibrationActuator;if(o&&typeof o.playEffect=="function")return!0;let n=t.hapticActuators;return!!(n&&n.length>0)}async vibrate(e,t){let o=this.getNativeGamepad(e);if(!o)return this.log(`Vibrate failed: gamepad ${e} not found`),!1;let{duration:n,strongMagnitude:i=1,weakMagnitude:a=.5,startDelay:p=0}=t;try{let c=o.vibrationActuator;if(c&&typeof c.playEffect=="function"){let f=await c.playEffect("dual-rumble",{startDelay:p,duration:n,strongMagnitude:Math.min(1,Math.max(0,i)),weakMagnitude:Math.min(1,Math.max(0,a))});return this.log(`Vibration effect result: ${f}`),f==="complete"}let m=o.hapticActuators;if(m&&m.length>0){let f=Math.max(i,a);return await m[0].pulse(f,n),!0}return this.log(`Vibrate failed: gamepad ${e} does not support vibration`),!1}catch(c){return this.log("Vibrate error:",c),!1}}async stopVibration(e){let t=this.getNativeGamepad(e);if(!t)return!1;try{let o=t.vibrationActuator;return o&&typeof o.reset=="function"?(await o.reset(),!0):o&&typeof o.playEffect=="function"?(await o.playEffect("dual-rumble",{duration:0,strongMagnitude:0,weakMagnitude:0}),!0):!1}catch(o){return this.log("Stop vibration error:",o),!1}}async stopAllVibrations(){let e=[];for(let[t]of this.gamepads)e.push(this.stopVibration(t));await Promise.all(e)}async vibrateAll(e){let t=[];for(let[o]of this.gamepads)t.push(this.vibrate(o,e));await Promise.all(t)}async vibratePreset(e,t){let o=this.vibrationPresets[t];return o?this.vibrate(e,o):(this.log(`Unknown vibration preset: ${t}`),!1)}getNativeGamepad(e){return(navigator.getGamepads?navigator.getGamepads():[])[e]||null}setGamepadCallbacks(e){this.gamepadCallbacks={...this.gamepadCallbacks,...e}}clearGamepadCallbacks(){this.gamepadCallbacks={}}setCallbacks(e){this.isGamepadCallbacks(e)&&this.setGamepadCallbacks(e)}isGamepadCallbacks(e){return typeof e=="object"&&e!==null&&("onGamepadConnected"in e||"onGamepadDisconnected"in e||"onButtonDown"in e||"onButtonUp"in e||"onAxisMove"in e)}updateGamepadState(e){let t=this.gamepads.get(e.index),o=Array.from(e.buttons).map((a,p)=>{let c=t?.buttons[p],m=a.pressed,f=c?.pressed??!1;return{pressed:m,justPressed:m&&!f,justReleased:!m&&f,value:a.value,touched:a.touched??!1}}),n=Array.from(e.axes),i={id:e.id,index:e.index,connected:e.connected,buttons:o,axes:n,timestamp:e.timestamp,mapping:e.mapping};this.gamepads.set(e.index,i),this.triggerCallbacks(i,t)}triggerCallbacks(e,t){try{e.buttons.forEach((o,n)=>{o.justPressed&&this.gamepadCallbacks.onButtonDown?.(e.index,n,o.value),o.justReleased&&this.gamepadCallbacks.onButtonUp?.(e.index,n)}),e.axes.forEach((o,n)=>{let i=t?.axes[n]??0,a=this.applyDeadzone(o),p=this.applyDeadzone(i);Math.abs(a-p)>fe&&this.gamepadCallbacks.onAxisMove?.(e.index,n,a)})}catch(o){this.log("Error in gamepad callbacks:",o)}}handleGamepadConnected(e){try{this.log(`Gamepad connected: ${e.gamepad.id} at index ${e.gamepad.index}`);let t={id:e.gamepad.id,index:e.gamepad.index,connected:!0,buttons:Array.from(e.gamepad.buttons).map(o=>({pressed:o.pressed,justPressed:!1,justReleased:!1,value:o.value,touched:o.touched??!1})),axes:Array.from(e.gamepad.axes),timestamp:e.gamepad.timestamp,mapping:e.gamepad.mapping};this.gamepads.set(e.gamepad.index,t),this.gamepadCallbacks.onGamepadConnected?.(t)}catch(t){this.log("Error handling gamepad connected:",t)}}handleGamepadDisconnected(e){try{this.log(`Gamepad disconnected at index ${e.gamepad.index}`),this.gamepads.delete(e.gamepad.index),this.previousGamepads.delete(e.gamepad.index),this.gamepadCallbacks.onGamepadDisconnected?.(e.gamepad.index)}catch(t){this.log("Error handling gamepad disconnected:",t)}}applyDeadzone(e){let t=this.gamepadConfig.axisDeadzone;return Math.abs(e)<t?0:(e>0?1:-1)*((Math.abs(e)-t)/(1-t))}cloneGamepadState(e){return{...e,buttons:e.buttons.map(t=>({...t})),axes:[...e.axes]}}};h(O,"GamepadInputs");var C=O;function se(d,s){let e=new C(s);return d&&e.setGamepadCallbacks(d),e.start(),e}h(se,"useGamepadInputs");var u=require("@utsp/types");var F=class F{constructor(s={}){r(this,"keyboard",null);r(this,"mouse",null);r(this,"gamepad",null);r(this,"mobile",null);r(this,"config");this.config={enableKeyboardMouse:s.enableKeyboardMouse??!0,enableGamepad:s.enableGamepad??!0,enableMobile:s.enableMobile??!1,targetElement:s.targetElement??window,mobileTargetElement:s.mobileTargetElement??s.targetElement??window,debug:s.debug??!1,keyboardConfig:{preventDefault:!1,stopPropagation:!1,...s.keyboardConfig},mouseConfig:{preventDefault:!1,stopPropagation:!1,...s.mouseConfig},mobileConfig:{preventDefault:!0,passive:!1,maxTouches:10,...s.mobileConfig}},this.initialize()}initialize(){this.config.enableKeyboardMouse&&(this.keyboard=new E(this.config.targetElement,{preventDefault:this.config.keyboardConfig?.preventDefault??!1,stopPropagation:this.config.keyboardConfig?.stopPropagation??!1,debug:this.config.debug}),this.keyboard.start(),this.mouse=new I(this.config.targetElement,{preventDefault:this.config.mouseConfig?.preventDefault??!1,stopPropagation:this.config.mouseConfig?.stopPropagation??!1,debug:this.config.debug}),this.mouse.start(),this.log("Keyboard/Mouse initialized")),this.config.enableGamepad&&(this.gamepad=new C({debug:this.config.debug}),this.gamepad.start(),this.log("Gamepad initialized")),this.config.enableMobile&&(this.config.mobileTargetElement?(this.mobile=new w(this.config.mobileTargetElement,this.config.mobileConfig),this.mobile.start(),this.log("Mobile/Touch initialized")):this.warn("Mobile input enabled but no canvas provided - mobile input will be disabled until setMobileTarget() is called"))}getButton(s,e){if(!(0,u.isButton)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case u.InputDeviceType.Keyboard:return this.getKeyboardButton(e);case u.InputDeviceType.Mouse:return this.getMouseButton(e);case u.InputDeviceType.Gamepad:return this.getGamepadButton(e);case u.InputDeviceType.Touch:return this.getTouchButton(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getButtonJustPressed(s,e){if(!(0,u.isButton)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case u.InputDeviceType.Keyboard:return this.getKeyboardButtonJustPressed(e);case u.InputDeviceType.Mouse:return this.getMouseButtonJustPressed(e);case u.InputDeviceType.Gamepad:return this.getGamepadButtonJustPressed(e);case u.InputDeviceType.Touch:return this.getTouchButtonJustPressed(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getButtonJustReleased(s,e){if(!(0,u.isButton)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case u.InputDeviceType.Keyboard:return this.getKeyboardButtonJustReleased(e);case u.InputDeviceType.Mouse:return this.getMouseButtonJustReleased(e);case u.InputDeviceType.Gamepad:return this.getGamepadButtonJustReleased(e);case u.InputDeviceType.Touch:return this.getTouchButtonJustReleased(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getAxis(s,e){if(!(0,u.isAxis)({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not an axis`),0;switch(s){case u.InputDeviceType.Keyboard:return this.warn("Keyboard does not have axis inputs"),0;case u.InputDeviceType.Mouse:return this.getMouseAxis(e);case u.InputDeviceType.Gamepad:return this.getGamepadAxis(e);case u.InputDeviceType.Touch:return this.getTouchAxis(e);default:return this.warn(`Unknown device type: ${s}`),0}}isLeftMousePressed(){return this.mouse?this.mouse.isLeftMousePressed():!1}getKeyboardButton(s){if(!this.keyboard)return!1;let e=u.KeyboardInput[s];return this.keyboard.isKeyPressed(e)}getKeyboardButtonJustPressed(s){if(!this.keyboard)return!1;let e=u.KeyboardInput[s];return this.keyboard.isKeyJustPressed(e)}getKeyboardButtonJustReleased(s){if(!this.keyboard)return!1;let e=u.KeyboardInput[s];return this.keyboard.isKeyJustReleased(e)}getMouseButton(s){if(!this.mouse)return!1;switch(s){case u.MouseInput.LeftButton:return this.mouse.isLeftMousePressed();case u.MouseInput.RightButton:return this.mouse.isRightMousePressed();case u.MouseInput.MiddleButton:return this.mouse.isMiddleMousePressed();default:return!1}}getMouseButtonJustPressed(s){if(!this.mouse)return!1;switch(s){case u.MouseInput.LeftButton:return this.mouse.isLeftMouseJustPressed();case u.MouseInput.RightButton:return this.mouse.isRightMouseJustPressed();case u.MouseInput.MiddleButton:return this.mouse.isMiddleMouseJustPressed();default:return!1}}getMouseButtonJustReleased(s){if(!this.mouse)return!1;switch(s){case u.MouseInput.LeftButton:return this.mouse.isLeftMouseJustReleased();case u.MouseInput.RightButton:return this.mouse.isRightMouseJustReleased();case u.MouseInput.MiddleButton:return this.mouse.isMiddleMouseJustReleased();default:return!1}}getGamepadButton(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonPressed(0,s)}getGamepadButtonJustPressed(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonJustPressed(0,s)}getGamepadButtonJustReleased(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonJustReleased(0,s)}getTouchButton(s){return this.mobile?s>=100?!1:this.mobile.isTouchActive?.(s)??!1:(console.warn("\u{1F6AB} MobileInputs not initialized!"),!1)}getTouchButtonJustPressed(s){return!this.mobile||s>=100?!1:this.mobile.isTouchJustStarted?.(s)??!1}getTouchButtonJustReleased(s){return!this.mobile||s>=100?!1:this.mobile.isTouchJustReleased?.(s)??!1}getMouseAxis(s){if(!this.mouse)return 0;switch(s){case u.MouseInput.PositionX:return this.mouse.getMousePosition().x;case u.MouseInput.PositionY:return this.mouse.getMousePosition().y;case u.MouseInput.DeltaX:return this.mouse.getMouseDelta().x;case u.MouseInput.DeltaY:return this.mouse.getMouseDelta().y;case u.MouseInput.WheelDeltaY:return this.mouse.getWheelDelta();default:return 0}}getGamepadAxis(s){if(!this.gamepad||s<100)return 0;let e=s-100;return this.gamepad.getAxis(0,e)}getTouchAxis(s){if(!this.mobile)return 0;if(s>=100&&s<200){let e=Math.floor((s-100)/2),t=(s-100)%2===0,o=this.mobile.getTouchPosition?.(e);return this.config.debug&&o&&console.warn(`\u{1F3AF} getTouchAxis(${s}) - touchIndex: ${e}, ${t?"X":"Y"}: ${t?o.x:o.y}`),o?t?o.x:o.y:0}return 0}getMousePosition(){if(!this.mouse)return null;let s=this.mouse.getMousePosition();return{x:s.x,y:s.y}}setMobileTarget(s){if(!s){this.warn("setMobileTarget() called with null/undefined canvas - mobile input will remain disabled");return}if(this.config.mobileTargetElement=s,!this.config.enableMobile){this.warn("setMobileTarget() called but mobile input is disabled in config");return}this.mobile&&this.mobile.stop(),this.mobile=new w(s,this.config.mobileConfig),this.mobile.start()}getTextInputs(){return this.keyboard?this.keyboard.getTextInputs():[]}start(){this.keyboard?.start(),this.mouse?.start(),this.log("Input router started")}stop(){this.keyboard?.stop(),this.mouse?.stop(),this.log("Input router stopped")}reset(){this.keyboard?.reset(),this.mouse?.reset(),this.log("Input router reset")}poll(){this.keyboard?.poll(),this.mouse?.poll(),this.gamepad?.poll(),this.mobile?.poll()}isListening(){return this.keyboard!==null&&this.config.enableKeyboardMouse||this.gamepad!==null&&this.config.enableGamepad||this.mobile!==null&&this.config.enableMobile}getGamepad(){return this.gamepad}getKeyboard(){return this.keyboard}getMouse(){return this.mouse}getMobile(){return this.mobile}destroy(){this.keyboard?.destroy(),this.mouse?.destroy(),this.keyboard=null,this.mouse=null,this.gamepad=null,this.mobile=null,this.log("Input router destroyed")}log(s){this.config.debug&&console.warn(`[InputRouter] ${s}`)}warn(s){console.warn(`[InputRouter] ${s}`)}};h(F,"UnifiedInputRouter");var A=F;var l=require("@utsp/types");var oe=100,ne=2,D=class D{static calculateRenderMetrics(s,e){let t=s.getBoundingClientRect(),o=s.width/s.height,n=t.width/t.height,i,a,p,c;o>n?(i=t.width,a=t.width/o,p=0,c=(t.height-a)/2):(i=t.height*o,a=t.height,p=(t.width-i)/2,c=0);let m=e?.offsetX||0,f=e?.offsetY||0;return p+=m,c+=f,i-=m*2,a-=f*2,{renderWidth:i,renderHeight:a,offsetX:p,offsetY:c,rect:t}}static collectAxisSources(s,e){let t=new Map;for(let o of s)for(let n of o.sources){if(t.has(n.sourceId))continue;let i=0,a=!1;if(n.type===l.InputDeviceType.Keyboard&&n.negativeKey!==void 0&&n.positiveKey!==void 0){let p=e.getButton(l.InputDeviceType.Keyboard,n.negativeKey);e.getButton(l.InputDeviceType.Keyboard,n.positiveKey)&&(i+=1),p&&(i-=1),a=!0}else if(n.type===l.InputDeviceType.Mouse&&n.mouseAxis!==void 0)i=e.getAxis(l.InputDeviceType.Mouse,n.mouseAxis),a=!0;else if(n.type===l.InputDeviceType.Gamepad&&n.axis!==void 0)i=e.getAxis(l.InputDeviceType.Gamepad,n.axis),a=!0;else if(n.type===l.InputDeviceType.Touch&&n.touchId!==void 0&&n.touchAxis!==void 0){let p=100+n.touchId*2,c=n.touchAxis==="x"?p:p+1;i=e.getAxis(l.InputDeviceType.Touch,c),a=!0}a&&t.set(n.sourceId,i)}return t}static collectButtonSources(s,e){let t=new Map;for(let o of s)for(let n of o.sources){if(t.has(n.sourceId))continue;let i=!1,a=!1;n.type===l.InputDeviceType.Keyboard&&n.key!==void 0?(i=e.getButton(l.InputDeviceType.Keyboard,n.key),a=!0):n.type===l.InputDeviceType.Mouse&&n.mouseButton!==void 0?(i=e.getButton(l.InputDeviceType.Mouse,n.mouseButton),a=!0):n.type===l.InputDeviceType.Gamepad&&n.button!==void 0?(i=e.getButton(l.InputDeviceType.Gamepad,n.button),a=!0):n.type===l.InputDeviceType.Touch&&n.touchButton!==void 0&&(i=e.getButton(l.InputDeviceType.Touch,n.touchButton),a=!0),a&&t.set(n.sourceId,i)}return t}static collectButtonSourcesWithTransitions(s,e){let t=new Map;for(let o of s)for(let n of o.sources){if(t.has(n.sourceId))continue;let i=!1,a=!1,p=!1,c=!1;n.type===l.InputDeviceType.Keyboard&&n.key!==void 0?(i=e.getButton(l.InputDeviceType.Keyboard,n.key),a=e.getButtonJustPressed?.(l.InputDeviceType.Keyboard,n.key)??!1,p=e.getButtonJustReleased?.(l.InputDeviceType.Keyboard,n.key)??!1,c=!0):n.type===l.InputDeviceType.Mouse&&n.mouseButton!==void 0?(i=e.getButton(l.InputDeviceType.Mouse,n.mouseButton),a=e.getButtonJustPressed?.(l.InputDeviceType.Mouse,n.mouseButton)??!1,p=e.getButtonJustReleased?.(l.InputDeviceType.Mouse,n.mouseButton)??!1,c=!0):n.type===l.InputDeviceType.Gamepad&&n.button!==void 0?(i=e.getButton(l.InputDeviceType.Gamepad,n.button),a=e.getButtonJustPressed?.(l.InputDeviceType.Gamepad,n.button)??!1,p=e.getButtonJustReleased?.(l.InputDeviceType.Gamepad,n.button)??!1,c=!0):n.type===l.InputDeviceType.Touch&&n.touchButton!==void 0&&(i=e.getButton(l.InputDeviceType.Touch,n.touchButton),a=e.getButtonJustPressed?.(l.InputDeviceType.Touch,n.touchButton)??!1,p=e.getButtonJustReleased?.(l.InputDeviceType.Touch,n.touchButton)??!1,c=!0),c&&t.set(n.sourceId,{pressed:i,justPressed:a,justReleased:p})}return t}static collectMousePosition(s,e,t,o,n){let i=s.getAxis(l.InputDeviceType.Mouse,l.MouseInput.PositionX),a=s.getAxis(l.InputDeviceType.Mouse,l.MouseInput.PositionY),p=s.isLeftMousePressed?.()??!1,{renderWidth:c,renderHeight:m,offsetX:f,offsetY:G,rect:b}=D.calculateRenderMetrics(e,n),T=i-b.left-f,y=a-b.top-G,R=c/t,q=m/o,S=Math.floor(T/R),V=Math.floor(y/q),H=T>=0&&T<c&&y>=0&&y<m;return{x:Math.max(0,Math.min(t-1,S)),y:Math.max(0,Math.min(o-1,V)),over:H,isLeftDown:p}}static collectTouchPositions(s,e,t,o,n=10,i){let a=[],{renderWidth:p,renderHeight:c,offsetX:m,offsetY:f,rect:G}=D.calculateRenderMetrics(e,i),b=p/t,T=c/o;for(let y=0;y<n;y++){let R=y;if(s.getButton(l.InputDeviceType.Touch,R)){let S=oe+y*ne,V=oe+y*ne+1,H=s.getAxis(l.InputDeviceType.Touch,S),ie=s.getAxis(l.InputDeviceType.Touch,V),j=H-G.left-m,$=ie-G.top-f,ae=Math.floor(j/b),re=Math.floor($/T),ue=j>=0&&j<p&&$>=0&&$<c;a.push({id:y,x:Math.max(0,Math.min(t-1,ae)),y:Math.max(0,Math.min(o-1,re)),over:ue})}}return a}static collectTextInputs(s){return typeof s.getTextInputs=="function"?s.getTextInputs():[]}};h(D,"InputCollector");var L=D;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Vector2, Vector3, IInputSystem, InputDeviceType, AxisBinding, ButtonBinding } from '@utsp/types';
2
- export { GamepadInput, IInputSystem, InputDeviceType, KeyboardInput, MouseInput, TouchInput, Vector2, Vector3 } from '@utsp/types';
1
+ import { Vector2, Vector3, IMobileVibrationProcessor, VibrationPattern, IGamepadVibrationProcessor, GamepadVibrationOptions, IInputSystem, InputDeviceType, AxisBinding, ButtonBinding } from '@utsp/types';
2
+ export { GamepadInput, IInputSystem, InputDeviceType, KeyboardInput, MouseInput, TouchInput, Vector2, Vector3, VibrationPattern } from '@utsp/types';
3
3
 
4
4
  /**
5
5
  * Base interface for all input management systems
@@ -344,6 +344,14 @@ declare class KeyboardInputs extends BaseInputs {
344
344
  clearKeyboardCallbacks(): void;
345
345
  setCallbacks(callbacks: KeyboardCallbacks | unknown): void;
346
346
  private isKeyboardCallbacks;
347
+ /**
348
+ * Check if browser default behavior should be allowed for this keyboard event
349
+ *
350
+ * Returns true for:
351
+ * - Function keys (F1-F12)
352
+ * - Browser shortcuts (Ctrl+T, Ctrl+W, Ctrl+R, Ctrl+N, Ctrl+Tab)
353
+ */
354
+ private shouldAllowDefault;
347
355
  private handleKeyDown;
348
356
  private handleKeyUp;
349
357
  }
@@ -531,6 +539,13 @@ declare class MouseInputs extends BaseInputs {
531
539
  clearMouseCallbacks(): void;
532
540
  setCallbacks(callbacks: MouseCallbacks | unknown): void;
533
541
  private isMouseCallbacks;
542
+ /** Button index to name mapping */
543
+ private static readonly BUTTON_NAMES;
544
+ /**
545
+ * Get button state by event.button index
546
+ * @returns Button state and name, or null for unknown buttons
547
+ */
548
+ private getButtonByIndex;
534
549
  private handleMouseDown;
535
550
  private handleMouseUp;
536
551
  private handleMouseMove;
@@ -770,6 +785,175 @@ declare class MobileInputs extends BaseInputs {
770
785
  */
771
786
  declare function useMobileInputs(targetElement?: HTMLElement | Window, callbacks?: MobileCallbacks, config?: MobileInputsConfig): MobileInputs;
772
787
 
788
+ /**
789
+ * MobileVibration - Vibration feedback for mobile devices
790
+ *
791
+ * Provides vibration feedback using the Navigator Vibration API.
792
+ * Requires user interaction before first use (browser security requirement).
793
+ *
794
+ * @example
795
+ * ```typescript
796
+ * const vibration = new MobileVibration();
797
+ *
798
+ * // Simple vibration
799
+ * vibration.vibrate(100); // 100ms vibration
800
+ *
801
+ * // Pattern vibration
802
+ * vibration.vibrate([100, 50, 100]); // vibrate 100ms, pause 50ms, vibrate 100ms
803
+ *
804
+ * // Predefined patterns
805
+ * vibration.tap(); // Light tap feedback
806
+ * vibration.success(); // Success confirmation
807
+ * vibration.error(); // Error notification
808
+ * vibration.warning(); // Warning notification
809
+ * ```
810
+ */
811
+
812
+ /**
813
+ * Configuration options for MobileVibration
814
+ */
815
+ interface MobileVibrationConfig {
816
+ /** Enable vibration (default: true) */
817
+ enabled?: boolean;
818
+ /** Enable debug logging (default: false) */
819
+ debug?: boolean;
820
+ /** Global intensity multiplier 0.0-1.0 (default: 1.0) */
821
+ intensity?: number;
822
+ }
823
+ /**
824
+ * Predefined vibration patterns for common use cases
825
+ */
826
+ declare const VibrationPatterns: {
827
+ /** Light tap - single short pulse */
828
+ readonly tap: 10;
829
+ /** Medium tap - slightly longer pulse */
830
+ readonly mediumTap: 25;
831
+ /** Heavy tap - strong pulse */
832
+ readonly heavyTap: 50;
833
+ /** Success - two quick pulses */
834
+ readonly success: readonly [30, 50, 30];
835
+ /** Error - three rapid pulses */
836
+ readonly error: readonly [50, 30, 50, 30, 50];
837
+ /** Warning - one long pulse */
838
+ readonly warning: readonly [100];
839
+ /** Selection change - very light feedback */
840
+ readonly selection: 5;
841
+ /** Impact light */
842
+ readonly impactLight: 15;
843
+ /** Impact medium */
844
+ readonly impactMedium: 30;
845
+ /** Impact heavy */
846
+ readonly impactHeavy: 50;
847
+ /** Notification - attention-grabbing pattern */
848
+ readonly notification: readonly [100, 100, 100, 100, 100];
849
+ /** SOS pattern in Morse code */
850
+ readonly sos: readonly [100, 30, 100, 30, 100, 30, 200, 30, 200, 30, 200, 30, 100, 30, 100, 30, 100];
851
+ };
852
+ /**
853
+ * MobileVibration manager - implements IMobileVibrationProcessor
854
+ */
855
+ declare class MobileVibration implements IMobileVibrationProcessor {
856
+ private config;
857
+ private supported;
858
+ private userActivated;
859
+ constructor(config?: MobileVibrationConfig);
860
+ /**
861
+ * Check if vibration is supported on this device
862
+ */
863
+ isSupported(): boolean;
864
+ /**
865
+ * Check if vibration is enabled
866
+ */
867
+ isEnabled(): boolean;
868
+ /**
869
+ * Enable or disable vibration
870
+ */
871
+ setEnabled(enabled: boolean): void;
872
+ /**
873
+ * Set global intensity multiplier (0.0 to 1.0)
874
+ * This scales the duration of all vibrations
875
+ */
876
+ setIntensity(intensity: number): void;
877
+ /**
878
+ * Get current intensity setting
879
+ */
880
+ getIntensity(): number;
881
+ /**
882
+ * Vibrate with a pattern or duration
883
+ *
884
+ * @param pattern - Duration in ms, or array of [vibrate, pause, vibrate, pause, ...]
885
+ * @returns true if vibration was triggered, false otherwise
886
+ *
887
+ * @example
888
+ * ```typescript
889
+ * vibration.vibrate(100); // Vibrate for 100ms
890
+ * vibration.vibrate([100, 50, 100]); // Vibrate, pause, vibrate
891
+ * ```
892
+ */
893
+ vibrate(pattern: VibrationPattern): boolean;
894
+ /**
895
+ * Stop any ongoing vibration
896
+ */
897
+ cancel(): void;
898
+ /**
899
+ * Check if user has activated vibration (first successful vibration)
900
+ * This can be useful for UI feedback
901
+ */
902
+ hasUserActivation(): boolean;
903
+ /**
904
+ * Light tap feedback - for button presses, selections
905
+ */
906
+ tap(): boolean;
907
+ /**
908
+ * Medium tap feedback
909
+ */
910
+ mediumTap(): boolean;
911
+ /**
912
+ * Heavy tap feedback - for important actions
913
+ */
914
+ heavyTap(): boolean;
915
+ /**
916
+ * Success feedback - for completed actions
917
+ */
918
+ success(): boolean;
919
+ /**
920
+ * Error feedback - for failed actions
921
+ */
922
+ error(): boolean;
923
+ /**
924
+ * Warning feedback - for important notices
925
+ */
926
+ warning(): boolean;
927
+ /**
928
+ * Selection feedback - very light, for UI navigation
929
+ */
930
+ selection(): boolean;
931
+ /**
932
+ * Light impact feedback
933
+ */
934
+ impactLight(): boolean;
935
+ /**
936
+ * Medium impact feedback
937
+ */
938
+ impactMedium(): boolean;
939
+ /**
940
+ * Heavy impact feedback
941
+ */
942
+ impactHeavy(): boolean;
943
+ /**
944
+ * Notification feedback - attention-grabbing pattern
945
+ */
946
+ notification(): boolean;
947
+ /**
948
+ * Scale a vibration pattern by intensity
949
+ */
950
+ private scalePattern;
951
+ }
952
+ /**
953
+ * Get the default MobileVibration instance (singleton)
954
+ */
955
+ declare function getMobileVibration(): MobileVibration;
956
+
773
957
  /**
774
958
  * GamepadInputs - Gamepad/Controller input management
775
959
  * Handles gamepad events with support for multiple controllers, buttons, axes, and vibration
@@ -821,7 +1005,7 @@ interface GamepadInputsConfig extends InputConfig {
821
1005
  /** Enable automatic polling (default: true) */
822
1006
  autoPolling?: boolean;
823
1007
  }
824
- declare class GamepadInputs extends BaseInputs {
1008
+ declare class GamepadInputs extends BaseInputs implements IGamepadVibrationProcessor {
825
1009
  private gamepads;
826
1010
  private previousGamepads;
827
1011
  private gamepadCallbacks;
@@ -972,6 +1156,151 @@ declare class GamepadInputs extends BaseInputs {
972
1156
  x: number;
973
1157
  y: number;
974
1158
  };
1159
+ /**
1160
+ * Check if a gamepad supports vibration
1161
+ *
1162
+ * @param gamepadIndex - Gamepad index (0-3)
1163
+ * @returns True if gamepad supports vibration
1164
+ *
1165
+ * @example
1166
+ * ```typescript
1167
+ * if (gamepad.supportsVibration(0)) {
1168
+ * gamepad.vibrate(0, { duration: 200, strongMagnitude: 1.0 });
1169
+ * }
1170
+ * ```
1171
+ */
1172
+ supportsVibration(gamepadIndex: number): boolean;
1173
+ /**
1174
+ * Vibrate a gamepad with dual-motor control
1175
+ *
1176
+ * Modern gamepads have two motors:
1177
+ * - Strong motor (low frequency) - heavy rumble
1178
+ * - Weak motor (high frequency) - light vibration
1179
+ *
1180
+ * @param gamepadIndex - Gamepad index (0-3)
1181
+ * @param options - Vibration options
1182
+ * @returns Promise that resolves when vibration completes or fails
1183
+ *
1184
+ * @example
1185
+ * ```typescript
1186
+ * // Strong rumble for 500ms
1187
+ * await gamepad.vibrate(0, {
1188
+ * duration: 500,
1189
+ * strongMagnitude: 1.0,
1190
+ * weakMagnitude: 0.0,
1191
+ * });
1192
+ *
1193
+ * // Light vibration
1194
+ * await gamepad.vibrate(0, {
1195
+ * duration: 200,
1196
+ * strongMagnitude: 0.0,
1197
+ * weakMagnitude: 0.5,
1198
+ * });
1199
+ *
1200
+ * // Balanced rumble
1201
+ * await gamepad.vibrate(0, {
1202
+ * duration: 300,
1203
+ * strongMagnitude: 0.5,
1204
+ * weakMagnitude: 0.5,
1205
+ * });
1206
+ * ```
1207
+ */
1208
+ vibrate(gamepadIndex: number, options: GamepadVibrationOptions): Promise<boolean>;
1209
+ /**
1210
+ * Stop vibration on a gamepad
1211
+ *
1212
+ * @param gamepadIndex - Gamepad index (0-3)
1213
+ * @returns Promise that resolves when vibration is stopped
1214
+ */
1215
+ stopVibration(gamepadIndex: number): Promise<boolean>;
1216
+ /**
1217
+ * Stop vibration on all connected gamepads
1218
+ */
1219
+ stopAllVibrations(): Promise<void>;
1220
+ /**
1221
+ * Vibrate all connected gamepads
1222
+ *
1223
+ * @param options - Vibration options (same as vibrate())
1224
+ */
1225
+ vibrateAll(options: {
1226
+ duration: number;
1227
+ strongMagnitude?: number;
1228
+ weakMagnitude?: number;
1229
+ startDelay?: number;
1230
+ }): Promise<void>;
1231
+ /**
1232
+ * Preset vibration patterns for common use cases
1233
+ */
1234
+ readonly vibrationPresets: {
1235
+ /** Light tap feedback */
1236
+ tap: {
1237
+ duration: number;
1238
+ strongMagnitude: number;
1239
+ weakMagnitude: number;
1240
+ };
1241
+ /** Medium impact */
1242
+ impact: {
1243
+ duration: number;
1244
+ strongMagnitude: number;
1245
+ weakMagnitude: number;
1246
+ };
1247
+ /** Heavy rumble */
1248
+ heavy: {
1249
+ duration: number;
1250
+ strongMagnitude: number;
1251
+ weakMagnitude: number;
1252
+ };
1253
+ /** Success feedback */
1254
+ success: {
1255
+ duration: number;
1256
+ strongMagnitude: number;
1257
+ weakMagnitude: number;
1258
+ };
1259
+ /** Error/failure feedback */
1260
+ error: {
1261
+ duration: number;
1262
+ strongMagnitude: number;
1263
+ weakMagnitude: number;
1264
+ };
1265
+ /** Explosion effect */
1266
+ explosion: {
1267
+ duration: number;
1268
+ strongMagnitude: number;
1269
+ weakMagnitude: number;
1270
+ };
1271
+ /** Engine/continuous rumble */
1272
+ engine: {
1273
+ duration: number;
1274
+ strongMagnitude: number;
1275
+ weakMagnitude: number;
1276
+ };
1277
+ /** Heartbeat (use twice with delay) */
1278
+ heartbeat: {
1279
+ duration: number;
1280
+ strongMagnitude: number;
1281
+ weakMagnitude: number;
1282
+ };
1283
+ };
1284
+ /**
1285
+ * Play a preset vibration pattern
1286
+ *
1287
+ * @param gamepadIndex - Gamepad index (0-3)
1288
+ * @param preset - Preset name
1289
+ *
1290
+ * @example
1291
+ * ```typescript
1292
+ * // On hit
1293
+ * gamepad.vibratePreset(0, 'impact');
1294
+ *
1295
+ * // On explosion
1296
+ * gamepad.vibratePreset(0, 'explosion');
1297
+ * ```
1298
+ */
1299
+ vibratePreset(gamepadIndex: number, preset: keyof typeof this.vibrationPresets): Promise<boolean>;
1300
+ /**
1301
+ * Get the native Gamepad object (for advanced usage)
1302
+ */
1303
+ private getNativeGamepad;
975
1304
  /**
976
1305
  * Set gamepad-specific callbacks
977
1306
  *
@@ -1135,6 +1464,29 @@ declare class UnifiedInputRouter implements IInputSystem {
1135
1464
  */
1136
1465
  poll(): void;
1137
1466
  isListening(): boolean;
1467
+ /**
1468
+ * Get the gamepad input handler for direct access to gamepad features
1469
+ *
1470
+ * Useful for:
1471
+ * - Vibration feedback
1472
+ * - Raw gamepad state access
1473
+ * - Multi-controller support
1474
+ *
1475
+ * @returns The GamepadInputs instance, or null if gamepad is disabled
1476
+ */
1477
+ getGamepad(): GamepadInputs | null;
1478
+ /**
1479
+ * Get the keyboard input handler for direct access
1480
+ */
1481
+ getKeyboard(): KeyboardInputs | null;
1482
+ /**
1483
+ * Get the mouse input handler for direct access
1484
+ */
1485
+ getMouse(): MouseInputs | null;
1486
+ /**
1487
+ * Get the mobile/touch input handler for direct access
1488
+ */
1489
+ getMobile(): MobileInputs | null;
1138
1490
  destroy(): void;
1139
1491
  private log;
1140
1492
  private warn;
@@ -1179,6 +1531,18 @@ interface ButtonStateWithTransitions {
1179
1531
  * and prepare them for InputBindingRegistry evaluation.
1180
1532
  */
1181
1533
  declare class InputCollector {
1534
+ /**
1535
+ * Calculate canvas render metrics for proper coordinate mapping
1536
+ *
1537
+ * Handles:
1538
+ * - object-fit: contain (letterbox/pillarbox black bars)
1539
+ * - Renderer centering offsets (Terminal2D may not fill its parent)
1540
+ *
1541
+ * @param canvas - The HTML canvas element
1542
+ * @param rendererOffsets - Optional renderer content centering offsets
1543
+ * @returns Render metrics with adjusted dimensions and offsets
1544
+ */
1545
+ private static calculateRenderMetrics;
1182
1546
  /**
1183
1547
  * Collects raw source values for all axis bindings
1184
1548
  *
@@ -1362,5 +1726,5 @@ declare class InputCollector {
1362
1726
  static collectTextInputs(router: IInputSystem): string[];
1363
1727
  }
1364
1728
 
1365
- export { BaseInputs, GamepadInputs, InputCollector, InputEventType, KeyboardInputs, MobileInputs, MouseInputs, UnifiedInputRouter, isInputs, useGamepadInputs, useKeyboardInputs, useMobileInputs, useMouseInputs };
1366
- export type { ButtonState, GamepadButtonState, GamepadCallbacks, GamepadInputsConfig, GamepadState, IInputs, InputConfig, InputDevice, InputEvent, InputRouterConfig, KeyState, KeyboardCallbacks, MobileCallbacks, MobileInputsConfig, MotionData, MouseButtonState, MouseButtons, MouseCallbacks, TouchPoint };
1729
+ export { BaseInputs, GamepadInputs, InputCollector, InputEventType, KeyboardInputs, MobileInputs, MobileVibration, MouseInputs, UnifiedInputRouter, VibrationPatterns, getMobileVibration, isInputs, useGamepadInputs, useKeyboardInputs, useMobileInputs, useMouseInputs };
1730
+ export type { ButtonState, GamepadButtonState, GamepadCallbacks, GamepadInputsConfig, GamepadState, IInputs, InputConfig, InputDevice, InputEvent, InputRouterConfig, KeyState, KeyboardCallbacks, MobileCallbacks, MobileInputsConfig, MobileVibrationConfig, MotionData, MouseButtonState, MouseButtons, MouseCallbacks, TouchPoint };