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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,540 @@
1
+ import { Vector2, Vector3 } from '@utsp/types';
2
+ export { InputDeviceType, KeyboardInput, MouseInput, Vector2 } from '@utsp/types';
3
+
4
+ /**
5
+ * Base interface for all input management systems
6
+ * This provides a common API for keyboard, mouse, gamepad, and touch inputs
7
+ */
8
+ interface IInputs {
9
+ /**
10
+ * Start listening to input events
11
+ */
12
+ start(): void;
13
+ /**
14
+ * Stop listening to input events and cleanup
15
+ */
16
+ stop(): void;
17
+ /**
18
+ * Reset all input states to default
19
+ */
20
+ reset(): void;
21
+ /**
22
+ * Check if the input system is currently active/listening
23
+ */
24
+ isListening(): boolean;
25
+ /**
26
+ * Cleanup and destroy the instance, removing all event listeners
27
+ */
28
+ destroy(): void;
29
+ /**
30
+ * Reset delta values (call at the end of each frame/update)
31
+ */
32
+ resetDelta(): void;
33
+ /**
34
+ * Set or update event callbacks
35
+ */
36
+ setCallbacks(callbacks: unknown): void;
37
+ /**
38
+ * Remove all event callbacks
39
+ */
40
+ clearCallbacks(): void;
41
+ /**
42
+ * Check if a key is currently pressed (Keyboard)
43
+ */
44
+ isKeyPressed?(key: string): boolean;
45
+ /**
46
+ * Check if left mouse button is pressed (Mouse)
47
+ */
48
+ isLeftMousePressed?(): boolean;
49
+ /**
50
+ * Get mouse position (Mouse)
51
+ */
52
+ getMousePosition?(): Vector2 | null;
53
+ /**
54
+ * Get mouse movement delta (Mouse)
55
+ */
56
+ getMouseDelta?(): Vector2 | null;
57
+ /**
58
+ * Get wheel delta (Mouse)
59
+ */
60
+ getWheelDelta?(): Vector2 | null;
61
+ /**
62
+ * Check if a button is pressed (Gamepad, TVRemote)
63
+ */
64
+ isButtonPressed?(button: string | number): boolean;
65
+ /**
66
+ * Get axis value (Gamepad, TVRemote)
67
+ */
68
+ getAxis?(axis: number): number | null;
69
+ /**
70
+ * Get motion/gyroscope data (TVRemote, Mobile)
71
+ */
72
+ getMotionData?(): MotionData | null;
73
+ }
74
+ /**
75
+ * Motion/Gyroscope data interface
76
+ */
77
+ interface MotionData extends Vector3 {
78
+ timestamp?: number;
79
+ }
80
+ /**
81
+ * Common button state interface
82
+ */
83
+ interface ButtonState {
84
+ pressed: boolean;
85
+ justPressed: boolean;
86
+ justReleased: boolean;
87
+ timestamp?: number;
88
+ }
89
+ /**
90
+ * Input event types enumeration
91
+ */
92
+ declare enum InputEventType {
93
+ KeyDown = "keydown",
94
+ KeyUp = "keyup",
95
+ MouseDown = "mousedown",
96
+ MouseUp = "mouseup",
97
+ MouseMove = "mousemove",
98
+ MouseWheel = "mousewheel",
99
+ TouchStart = "touchstart",
100
+ TouchEnd = "touchend",
101
+ TouchMove = "touchmove",
102
+ GamepadConnected = "gamepadconnected",
103
+ GamepadDisconnected = "gamepaddisconnected",
104
+ GamepadButton = "gamepadbutton",
105
+ GamepadAxis = "gamepadaxis"
106
+ }
107
+ /**
108
+ * Configuration options for input systems
109
+ */
110
+ interface InputConfig {
111
+ /**
112
+ * Target element to attach listeners to (default: window)
113
+ */
114
+ targetElement?: HTMLElement | Window;
115
+ /**
116
+ * Enable/disable specific input types
117
+ */
118
+ enabled?: boolean;
119
+ /**
120
+ * Prevent default browser behaviors
121
+ */
122
+ preventDefault?: boolean;
123
+ /**
124
+ * Stop event propagation
125
+ */
126
+ stopPropagation?: boolean;
127
+ /**
128
+ * Enable debug logging
129
+ */
130
+ debug?: boolean;
131
+ }
132
+ /**
133
+ * Abstract base class for input systems
134
+ * All input classes should extend this to maintain consistency
135
+ */
136
+ declare abstract class BaseInputs implements IInputs {
137
+ protected isActive: boolean;
138
+ protected targetElement: HTMLElement | Window;
139
+ protected config: InputConfig;
140
+ protected callbacks: Record<string, ((...args: any[]) => void)[]>;
141
+ constructor(targetElement?: HTMLElement | Window, config?: InputConfig);
142
+ abstract start(): void;
143
+ abstract stop(): void;
144
+ abstract reset(): void;
145
+ abstract resetDelta(): void;
146
+ isListening(): boolean;
147
+ destroy(): void;
148
+ setCallbacks(callbacks: unknown): void;
149
+ clearCallbacks(): void;
150
+ /**
151
+ * Get the target element
152
+ */
153
+ getTargetElement(): HTMLElement | Window;
154
+ /**
155
+ * Enable the input system
156
+ */
157
+ enable(): void;
158
+ /**
159
+ * Disable the input system
160
+ */
161
+ disable(): void;
162
+ /**
163
+ * Check if the input system is enabled
164
+ */
165
+ isEnabled(): boolean;
166
+ /**
167
+ * Emit an event to all registered callbacks
168
+ */
169
+ protected emit(eventType: string, ...args: unknown[]): void;
170
+ /**
171
+ * Log debug messages if debug mode is enabled
172
+ */
173
+ protected log(...args: unknown[]): void;
174
+ }
175
+
176
+ /**
177
+ * KeyboardInputs - Keyboard input management
178
+ * Handles keyboard events with support for vanilla JS, React, and other frameworks
179
+ */
180
+
181
+ /**
182
+ * Keyboard button state with press/release detection
183
+ */
184
+ interface KeyButtonState {
185
+ pressed: boolean;
186
+ justPressed: boolean;
187
+ justReleased: boolean;
188
+ }
189
+ interface KeyState {
190
+ [key: string]: KeyButtonState;
191
+ }
192
+ interface KeyboardCallbacks {
193
+ onKeyDown?: (key: string, event: KeyboardEvent) => void;
194
+ onKeyUp?: (key: string, event: KeyboardEvent) => void;
195
+ }
196
+ declare class KeyboardInputs extends BaseInputs {
197
+ private keys;
198
+ private keyboardCallbacks;
199
+ private textInputsThisFrame;
200
+ private boundHandlers;
201
+ constructor(targetElement?: HTMLElement | Window, config?: InputConfig);
202
+ start(): void;
203
+ stop(): void;
204
+ reset(): void;
205
+ resetDelta(): void;
206
+ /**
207
+ * Poll - Reset transient states (justPressed/justReleased)
208
+ * Should be called once per frame AFTER collecting input
209
+ */
210
+ poll(): void;
211
+ /**
212
+ * Get text inputs captured this frame
213
+ * Returns actual characters typed (handles keyboard layout, modifiers, etc.)
214
+ *
215
+ * @returns Array of character strings typed this frame
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * const textInputs = keyboard.getTextInputs();
220
+ * textInputs.forEach(char => chatBox.append(char));
221
+ * ```
222
+ */
223
+ getTextInputs(): string[];
224
+ /**
225
+ * Check if a key is currently pressed
226
+ *
227
+ * @param key - Key code (e.g., 'Space', 'KeyA', 'ArrowUp')
228
+ * @returns True if key is pressed, false otherwise
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * if (keyboard.isKeyPressed('Space')) {
233
+ * player.jump();
234
+ * }
235
+ *
236
+ * if (keyboard.isKeyPressed('KeyW')) {
237
+ * player.moveForward();
238
+ * }
239
+ * ```
240
+ */
241
+ isKeyPressed(key: string): boolean;
242
+ /**
243
+ * Check if a key was just pressed this frame
244
+ *
245
+ * @param key - Key code (e.g., 'Space', 'KeyA', 'ArrowUp')
246
+ * @returns True if key was just pressed (transition false→true), false otherwise
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * if (keyboard.isKeyJustPressed('Space')) {
251
+ * player.jump(); // Jump once per press
252
+ * }
253
+ * ```
254
+ */
255
+ isKeyJustPressed(key: string): boolean;
256
+ /**
257
+ * Check if a key was just released this frame
258
+ *
259
+ * @param key - Key code (e.g., 'Space', 'KeyA', 'ArrowUp')
260
+ * @returns True if key was just released (transition true→false), false otherwise
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * if (keyboard.isKeyJustReleased('Space')) {
265
+ * releaseChargedShot();
266
+ * }
267
+ * ```
268
+ */
269
+ isKeyJustReleased(key: string): boolean;
270
+ /**
271
+ * Get all currently pressed keys
272
+ *
273
+ * @returns Array of key codes currently pressed
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * const keys = keyboard.getKeysPressed();
278
+ * console.log('Pressed keys:', keys); // ['KeyW', 'Space']
279
+ * ```
280
+ */
281
+ getKeysPressed(): string[];
282
+ /**
283
+ * Get all keys that were just pressed this frame
284
+ */
285
+ getKeysJustPressed(): string[];
286
+ /**
287
+ * Get all keys that were just released this frame
288
+ */
289
+ getKeysJustReleased(): string[];
290
+ /**
291
+ * Check if any key is currently pressed
292
+ *
293
+ * @returns True if at least one key is pressed, false otherwise
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * if (keyboard.isAnyKeyPressed()) {
298
+ * console.log('Player is active');
299
+ * }
300
+ * ```
301
+ */
302
+ isAnyKeyPressed(): boolean;
303
+ /**
304
+ * Set keyboard-specific callbacks
305
+ *
306
+ * @param callbacks - Object containing callback functions
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * keyboard.setKeyboardCallbacks({
311
+ * onKeyDown: (key, event) => {
312
+ * console.log(`Key pressed: ${key}`);
313
+ * },
314
+ * onKeyUp: (key, event) => {
315
+ * console.log(`Key released: ${key}`);
316
+ * },
317
+ * });
318
+ * ```
319
+ */
320
+ setKeyboardCallbacks(callbacks: KeyboardCallbacks): void;
321
+ clearKeyboardCallbacks(): void;
322
+ setCallbacks(callbacks: KeyboardCallbacks | unknown): void;
323
+ private isKeyboardCallbacks;
324
+ /**
325
+ * Check if browser default behavior should be allowed for this keyboard event
326
+ *
327
+ * Returns true for:
328
+ * - Function keys (F1-F12)
329
+ * - Browser shortcuts (Ctrl+T, Ctrl+W, Ctrl+R, Ctrl+N, Ctrl+Tab)
330
+ */
331
+ private shouldAllowDefault;
332
+ private handleKeyDown;
333
+ private handleKeyUp;
334
+ }
335
+ /**
336
+ * React hook for keyboard inputs
337
+ */
338
+ declare function useKeyboardInputs(targetElement?: HTMLElement | Window, callbacks?: KeyboardCallbacks): KeyboardInputs;
339
+
340
+ /**
341
+ * MouseInputs - Mouse input management
342
+ * Handles mouse events with support for vanilla JS, React, and other frameworks
343
+ */
344
+
345
+ /**
346
+ * Mouse button state with press/release detection
347
+ */
348
+ interface MouseButtonState {
349
+ pressed: boolean;
350
+ justPressed: boolean;
351
+ justReleased: boolean;
352
+ }
353
+ interface MouseButtons {
354
+ left: MouseButtonState;
355
+ middle: MouseButtonState;
356
+ right: MouseButtonState;
357
+ }
358
+ interface MouseCallbacks {
359
+ onMouseDown?: (button: string, position: Vector2, event: MouseEvent) => void;
360
+ onMouseUp?: (button: string, position: Vector2, event: MouseEvent) => void;
361
+ onMouseMove?: (position: Vector2, delta: Vector2, event: MouseEvent) => void;
362
+ onMouseWheel?: (delta: number, event: WheelEvent) => void;
363
+ onMouseEnter?: (event: MouseEvent) => void;
364
+ onMouseLeave?: (event: MouseEvent) => void;
365
+ }
366
+ declare class MouseInputs extends BaseInputs {
367
+ private mouseButtons;
368
+ private mousePosition;
369
+ private mouseDelta;
370
+ private wheelDelta;
371
+ private mouseCallbacks;
372
+ private boundHandlers;
373
+ constructor(targetElement?: HTMLElement | Window, config?: InputConfig);
374
+ start(): void;
375
+ stop(): void;
376
+ reset(): void;
377
+ /**
378
+ * Poll - Reset transient states (justPressed/justReleased)
379
+ * Should be called once per frame AFTER collecting input
380
+ */
381
+ poll(): void;
382
+ resetDelta(): void;
383
+ /**
384
+ * Check if left mouse button is pressed
385
+ *
386
+ * @returns True if left button is pressed, false otherwise
387
+ *
388
+ * @example
389
+ * ```typescript
390
+ * if (mouse.isLeftMousePressed()) {
391
+ * console.log('Left click detected');
392
+ * }
393
+ * ```
394
+ */
395
+ isLeftMousePressed(): boolean;
396
+ /**
397
+ * Check if left mouse button was just pressed this frame
398
+ *
399
+ * @returns True if button was just pressed (transition false→true), false otherwise
400
+ *
401
+ * @example
402
+ * ```typescript
403
+ * if (mouse.isLeftMouseJustPressed()) {
404
+ * fireWeapon(); // Fires once per click
405
+ * }
406
+ * ```
407
+ */
408
+ isLeftMouseJustPressed(): boolean;
409
+ /**
410
+ * Check if left mouse button was just released this frame
411
+ *
412
+ * @returns True if button was just released (transition true→false), false otherwise
413
+ *
414
+ * @example
415
+ * ```typescript
416
+ * if (mouse.isLeftMouseJustReleased()) {
417
+ * releaseChargedAttack();
418
+ * }
419
+ * ```
420
+ */
421
+ isLeftMouseJustReleased(): boolean;
422
+ /**
423
+ * Check if right mouse button is pressed
424
+ *
425
+ * @returns True if right button is pressed, false otherwise
426
+ *
427
+ * @example
428
+ * ```typescript
429
+ * if (mouse.isRightMousePressed()) {
430
+ * showContextMenu();
431
+ * }
432
+ * ```
433
+ */
434
+ isRightMousePressed(): boolean;
435
+ /**
436
+ * Check if right mouse button was just pressed this frame
437
+ */
438
+ isRightMouseJustPressed(): boolean;
439
+ /**
440
+ * Check if right mouse button was just released this frame
441
+ */
442
+ isRightMouseJustReleased(): boolean;
443
+ /**
444
+ * Check if middle mouse button is pressed
445
+ *
446
+ * @returns True if middle button is pressed, false otherwise
447
+ */
448
+ isMiddleMousePressed(): boolean;
449
+ /**
450
+ * Check if middle mouse button was just pressed this frame
451
+ */
452
+ isMiddleMouseJustPressed(): boolean;
453
+ /**
454
+ * Check if middle mouse button was just released this frame
455
+ */
456
+ isMiddleMouseJustReleased(): boolean;
457
+ /**
458
+ * Get current mouse position
459
+ *
460
+ * @returns Vector2 with x and y coordinates in pixels
461
+ *
462
+ * @example
463
+ * ```typescript
464
+ * const pos = mouse.getMousePosition();
465
+ * console.log(`Mouse at (${pos.x}, ${pos.y})`);
466
+ * ```
467
+ */
468
+ getMousePosition(): Vector2;
469
+ /**
470
+ * Get mouse movement delta since last frame
471
+ *
472
+ * @returns Vector2 with dx and dy in pixels
473
+ *
474
+ * @example
475
+ * ```typescript
476
+ * const delta = mouse.getMouseDelta();
477
+ * camera.rotate(delta.x * sensitivity, delta.y * sensitivity);
478
+ * ```
479
+ */
480
+ getMouseDelta(): Vector2;
481
+ /**
482
+ * Get mouse wheel scroll delta
483
+ *
484
+ * @returns Wheel delta (positive = scroll down, negative = scroll up)
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * const wheel = mouse.getWheelDelta();
489
+ * if (wheel !== 0) {
490
+ * camera.zoom(wheel > 0 ? -1 : 1);
491
+ * }
492
+ * ```
493
+ */
494
+ getWheelDelta(): number;
495
+ /**
496
+ * Set mouse-specific callbacks
497
+ *
498
+ * @param callbacks - Object containing callback functions
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * mouse.setMouseCallbacks({
503
+ * onMouseDown: (button, position, event) => {
504
+ * console.log(`${button} button pressed at`, position);
505
+ * },
506
+ * onMouseMove: (position, delta, event) => {
507
+ * console.log('Mouse moved by', delta);
508
+ * },
509
+ * onMouseWheel: (delta, event) => {
510
+ * console.log('Wheel scrolled:', delta);
511
+ * },
512
+ * });
513
+ * ```
514
+ */
515
+ setMouseCallbacks(callbacks: MouseCallbacks): void;
516
+ clearMouseCallbacks(): void;
517
+ setCallbacks(callbacks: MouseCallbacks | unknown): void;
518
+ private isMouseCallbacks;
519
+ /** Button index to name mapping */
520
+ private static readonly BUTTON_NAMES;
521
+ /**
522
+ * Get button state by event.button index
523
+ * @returns Button state and name, or null for unknown buttons
524
+ */
525
+ private getButtonByIndex;
526
+ private handleMouseDown;
527
+ private handleMouseUp;
528
+ private handleMouseMove;
529
+ private handleWheel;
530
+ private handleMouseEnter;
531
+ private handleMouseLeave;
532
+ private handleContextMenu;
533
+ }
534
+ /**
535
+ * React hook for mouse inputs
536
+ */
537
+ declare function useMouseInputs(targetElement?: HTMLElement | Window, callbacks?: MouseCallbacks): MouseInputs;
538
+
539
+ export { BaseInputs, InputEventType, KeyboardInputs, MouseInputs, useKeyboardInputs, useMouseInputs };
540
+ export type { ButtonState, IInputs, InputConfig, KeyButtonState, KeyState, KeyboardCallbacks, MouseButtonState, MouseButtons, MouseCallbacks };
@@ -0,0 +1 @@
1
+ var v=Object.defineProperty;var y=(i,s,e)=>s in i?v(i,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[s]=e;var a=(i,s)=>v(i,"name",{value:s,configurable:!0});var o=(i,s,e)=>(y(i,typeof s!="symbol"?s+"":s,e),e);import{Vector2 as H}from"@utsp/types";import{InputDeviceType as U,KeyboardInput as A,MouseInput as W}from"@utsp/types";var f=(n=>(n.KeyDown="keydown",n.KeyUp="keyup",n.MouseDown="mousedown",n.MouseUp="mouseup",n.MouseMove="mousemove",n.MouseWheel="mousewheel",n.TouchStart="touchstart",n.TouchEnd="touchend",n.TouchMove="touchmove",n.GamepadConnected="gamepadconnected",n.GamepadDisconnected="gamepaddisconnected",n.GamepadButton="gamepadbutton",n.GamepadAxis="gamepadaxis",n))(f||{}),b=class b{constructor(s=window,e={}){o(this,"isActive",!1);o(this,"targetElement");o(this,"config");o(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(r){this.config.debug&&console.error(`Error in ${s} callback:`,r)}})}log(...s){this.config.debug&&console.warn("[InputSystem]",...s)}};a(b,"BaseInputs");var l=b;var m=class m extends l{constructor(e=window,t={}){super(e,t);o(this,"keys",{});o(this,"keyboardCallbacks",{});o(this,"textInputsThisFrame",[]);o(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 r=/^F([1-9]|1[0-2])$/.test(e),c=(t.ctrlKey||t.metaKey)&&(e==="KeyT"||e==="KeyW"||e==="KeyR"||e==="KeyN"||e==="Tab");return r||c}handleKeyDown(e){try{let t=e.code,r=this.shouldAllowDefault(t,e);this.config.preventDefault&&!r&&e.preventDefault(),this.config.stopPropagation&&!r&&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 c=e.key;c.length===1&&!e.ctrlKey&&!e.metaKey&&this.textInputsThisFrame.push(c)}catch(t){console.error("Error in keyboard keydown handler:",t)}}handleKeyUp(e){try{let t=e.code,r=this.shouldAllowDefault(t,e);this.config.preventDefault&&!r&&e.preventDefault(),this.config.stopPropagation&&!r&&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)}}};a(m,"KeyboardInputs");var h=m;function g(i,s){let e=new h(i);return s&&e.setCallbacks(s),e.start(),e}a(g,"useKeyboardInputs");import{Vector2 as u}from"@utsp/types";var d=class d extends l{constructor(e=window,t={}){super(e,t);o(this,"mouseButtons",{left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}});o(this,"mousePosition",u.zero());o(this,"mouseDelta",u.zero());o(this,"wheelDelta",0);o(this,"mouseCallbacks",{});o(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=u.zero(),this.mouseDelta=u.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=u.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=d.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 u(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)}}};a(d,"MouseInputs"),o(d,"BUTTON_NAMES",["left","middle","right"]);var p=d;function M(i,s){let e=new p(i);return s&&e.setCallbacks(s),e.start(),e}a(M,"useMouseInputs");export{l as BaseInputs,U as InputDeviceType,f as InputEventType,A as KeyboardInput,h as KeyboardInputs,W as MouseInput,p as MouseInputs,H as Vector2,g as useKeyboardInputs,M as useMouseInputs};
@@ -0,0 +1 @@
1
+ "use strict";var h=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var P=(i,n,e)=>n in i?h(i,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[n]=e;var m=(i,n)=>h(i,"name",{value:n,configurable:!0});var I=(i,n)=>{for(var e in n)h(i,e,{get:n[e],enumerable:!0})},E=(i,n,e,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of x(n))!A.call(i,a)&&a!==e&&h(i,a,{get:()=>n[a],enumerable:!(t=C(n,a))||t.enumerable});return i};var D=i=>E(h({},"__esModule",{value:!0}),i);var r=(i,n,e)=>(P(i,typeof n!="symbol"?n+"":n,e),e);var V={};I(V,{BaseInputs:()=>g,GamepadInput:()=>v.GamepadInput,GamepadInputs:()=>f,InputDeviceType:()=>v.InputDeviceType,InputEventType:()=>G,Vector2:()=>y.Vector2,useGamepadInputs:()=>k});module.exports=D(V);var y=require("@utsp/types"),v=require("@utsp/types");var G=(o=>(o.KeyDown="keydown",o.KeyUp="keyup",o.MouseDown="mousedown",o.MouseUp="mouseup",o.MouseMove="mousemove",o.MouseWheel="mousewheel",o.TouchStart="touchstart",o.TouchEnd="touchend",o.TouchMove="touchmove",o.GamepadConnected="gamepadconnected",o.GamepadDisconnected="gamepaddisconnected",o.GamepadButton="gamepadbutton",o.GamepadAxis="gamepadaxis",o))(G||{}),w=class w{constructor(n=window,e={}){r(this,"isActive",!1);r(this,"targetElement");r(this,"config");r(this,"callbacks",{});this.targetElement=n,this.config={enabled:!0,preventDefault:!1,stopPropagation:!1,debug:!1,...e}}isListening(){return this.isActive}destroy(){this.stop(),this.clearCallbacks()}setCallbacks(n){typeof n=="object"&&n!==null&&Object.assign(this.callbacks,n)}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(n,...e){this.callbacks[n]&&this.callbacks[n].forEach(t=>{try{t(...e)}catch(a){this.config.debug&&console.error(`Error in ${n} callback:`,a)}})}log(...n){this.config.debug&&console.warn("[InputSystem]",...n)}};m(w,"BaseInputs");var g=w;var S=.01,M=class M extends g{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=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 a=e[t];a&&this.updateGamepadState(a)}}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 a=this.gamepads.get(e);return!a||!a.connected||t>=a.buttons.length?!1:a.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 a=this.gamepads.get(e);return!a||!a.connected||t>=a.buttons.length?!1:a.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 a=this.gamepads.get(e);return!a||!a.connected||t>=a.buttons.length?!1:a.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 a=this.gamepads.get(e);return!a||!a.connected||t>=a.buttons.length?0:a.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 a=this.gamepads.get(e);if(!a||!a.connected||t>=a.axes.length)return 0;let s=a.axes[t];return this.applyDeadzone(s)}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 a=this.gamepads.get(e);return!a||!a.connected||t>=a.axes.length?0:a.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 a=t.vibrationActuator;if(a&&typeof a.playEffect=="function")return!0;let s=t.hapticActuators;return!!(s&&s.length>0)}async vibrate(e,t){let a=this.getNativeGamepad(e);if(!a)return this.log(`Vibrate failed: gamepad ${e} not found`),!1;let{duration:s,strongMagnitude:u=1,weakMagnitude:d=.5,startDelay:b=0}=t;try{let l=a.vibrationActuator;if(l&&typeof l.playEffect=="function"){let c=await l.playEffect("dual-rumble",{startDelay:b,duration:s,strongMagnitude:Math.min(1,Math.max(0,u)),weakMagnitude:Math.min(1,Math.max(0,d))});return this.log(`Vibration effect result: ${c}`),c==="complete"}let p=a.hapticActuators;if(p&&p.length>0){let c=Math.max(u,d);return await p[0].pulse(c,s),!0}return this.log(`Vibrate failed: gamepad ${e} does not support vibration`),!1}catch(l){return this.log("Vibrate error:",l),!1}}async stopVibration(e){let t=this.getNativeGamepad(e);if(!t)return!1;try{let a=t.vibrationActuator;return a&&typeof a.reset=="function"?(await a.reset(),!0):a&&typeof a.playEffect=="function"?(await a.playEffect("dual-rumble",{duration:0,strongMagnitude:0,weakMagnitude:0}),!0):!1}catch(a){return this.log("Stop vibration error:",a),!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[a]of this.gamepads)t.push(this.vibrate(a,e));await Promise.all(t)}async vibratePreset(e,t){let a=this.vibrationPresets[t];return a?this.vibrate(e,a):(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),a=Array.from(e.buttons).map((d,b)=>{let l=t?.buttons[b],p=d.pressed,c=l?.pressed??!1;return{pressed:p,justPressed:p&&!c,justReleased:!p&&c,value:d.value,touched:d.touched??!1}}),s=Array.from(e.axes),u={id:e.id,index:e.index,connected:e.connected,buttons:a,axes:s,timestamp:e.timestamp,mapping:e.mapping};this.gamepads.set(e.index,u),this.triggerCallbacks(u,t)}triggerCallbacks(e,t){try{e.buttons.forEach((a,s)=>{a.justPressed&&this.gamepadCallbacks.onButtonDown?.(e.index,s,a.value),a.justReleased&&this.gamepadCallbacks.onButtonUp?.(e.index,s)}),e.axes.forEach((a,s)=>{let u=t?.axes[s]??0,d=this.applyDeadzone(a),b=this.applyDeadzone(u);Math.abs(d-b)>S&&this.gamepadCallbacks.onAxisMove?.(e.index,s,d)})}catch(a){this.log("Error in gamepad callbacks:",a)}}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(a=>({pressed:a.pressed,justPressed:!1,justReleased:!1,value:a.value,touched:a.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(M,"GamepadInputs");var f=M;function k(i,n){let e=new f(n);return i&&e.setGamepadCallbacks(i),e.start(),e}m(k,"useGamepadInputs");