flexium 0.10.7 → 0.12.6

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.
Files changed (192) hide show
  1. package/README.md +10 -10
  2. package/dist/canvas.d.cts +83 -23
  3. package/dist/canvas.d.ts +83 -23
  4. package/dist/canvas.js +1 -1
  5. package/dist/canvas.js.map +1 -1
  6. package/dist/canvas.mjs +1 -1
  7. package/dist/canvas.mjs.map +1 -1
  8. package/dist/chunk-44RZHCII.mjs +2 -0
  9. package/dist/chunk-44RZHCII.mjs.map +1 -0
  10. package/dist/chunk-7BXR4ZFD.js +2 -0
  11. package/dist/chunk-7BXR4ZFD.js.map +1 -0
  12. package/dist/chunk-7DXFHPWZ.mjs +2 -0
  13. package/dist/chunk-7DXFHPWZ.mjs.map +1 -0
  14. package/dist/chunk-ALTO2MGI.js +2 -0
  15. package/dist/chunk-ALTO2MGI.js.map +1 -0
  16. package/dist/chunk-C452JE6C.js +2 -0
  17. package/dist/chunk-C452JE6C.js.map +1 -0
  18. package/dist/chunk-CPJRQL2C.mjs +2 -0
  19. package/dist/chunk-CPJRQL2C.mjs.map +1 -0
  20. package/dist/chunk-EJ7Z5OMU.mjs +2 -0
  21. package/dist/chunk-EJ7Z5OMU.mjs.map +1 -0
  22. package/dist/chunk-ENWGYQNU.js +2 -0
  23. package/dist/chunk-ENWGYQNU.js.map +1 -0
  24. package/dist/chunk-EXLNKYSH.js +2 -0
  25. package/dist/chunk-EXLNKYSH.js.map +1 -0
  26. package/dist/chunk-LUREDEUB.mjs +2 -0
  27. package/dist/chunk-LUREDEUB.mjs.map +1 -0
  28. package/dist/chunk-LUW7DIEW.js +2 -0
  29. package/dist/chunk-LUW7DIEW.js.map +1 -0
  30. package/dist/chunk-ZCO4NIGC.mjs +2 -0
  31. package/dist/chunk-ZCO4NIGC.mjs.map +1 -0
  32. package/dist/core.d.cts +41 -2
  33. package/dist/core.d.ts +41 -2
  34. package/dist/core.js +1 -1
  35. package/dist/core.mjs +1 -1
  36. package/dist/dom.d.cts +10 -33
  37. package/dist/dom.d.ts +10 -33
  38. package/dist/dom.js +1 -1
  39. package/dist/dom.js.map +1 -1
  40. package/dist/dom.mjs +1 -1
  41. package/dist/dom.mjs.map +1 -1
  42. package/dist/index.d.cts +1 -24
  43. package/dist/index.d.ts +1 -24
  44. package/dist/index.js +1 -1
  45. package/dist/index.js.map +1 -1
  46. package/dist/index.mjs +1 -1
  47. package/dist/index.mjs.map +1 -1
  48. package/dist/interactive.d.cts +65 -148
  49. package/dist/interactive.d.ts +65 -148
  50. package/dist/interactive.js +1 -1
  51. package/dist/interactive.js.map +1 -1
  52. package/dist/interactive.mjs +1 -1
  53. package/dist/interactive.mjs.map +1 -1
  54. package/dist/jsx-dev-runtime.d.cts +6 -2
  55. package/dist/jsx-dev-runtime.d.ts +6 -2
  56. package/dist/jsx-dev-runtime.js +1 -1
  57. package/dist/jsx-dev-runtime.js.map +1 -1
  58. package/dist/jsx-dev-runtime.mjs +1 -1
  59. package/dist/jsx-dev-runtime.mjs.map +1 -1
  60. package/dist/jsx-runtime.d.cts +6 -68
  61. package/dist/jsx-runtime.d.ts +6 -68
  62. package/dist/jsx-runtime.js +1 -1
  63. package/dist/jsx-runtime.mjs +1 -1
  64. package/dist/metafile-cjs.json +1 -1
  65. package/dist/metafile-esm.json +1 -1
  66. package/dist/router.d.cts +48 -15
  67. package/dist/router.d.ts +48 -15
  68. package/dist/router.js +1 -1
  69. package/dist/router.js.map +1 -1
  70. package/dist/router.mjs +1 -1
  71. package/dist/router.mjs.map +1 -1
  72. package/package.json +13 -53
  73. package/dist/DrawText-CVAKQ5wZ.d.cts +0 -309
  74. package/dist/DrawText-Dlh1L1Ar.d.ts +0 -309
  75. package/dist/Motion-BrOAJzgH.d.cts +0 -87
  76. package/dist/Motion-BrOAJzgH.d.ts +0 -87
  77. package/dist/advanced.d.cts +0 -32
  78. package/dist/advanced.d.ts +0 -32
  79. package/dist/advanced.js +0 -2
  80. package/dist/advanced.js.map +0 -1
  81. package/dist/advanced.mjs +0 -2
  82. package/dist/advanced.mjs.map +0 -1
  83. package/dist/chunk-5ICRQIS2.js +0 -3
  84. package/dist/chunk-5ICRQIS2.js.map +0 -1
  85. package/dist/chunk-5K55ASOD.mjs +0 -3
  86. package/dist/chunk-5K55ASOD.mjs.map +0 -1
  87. package/dist/chunk-AZEHBSBG.js +0 -3
  88. package/dist/chunk-AZEHBSBG.js.map +0 -1
  89. package/dist/chunk-BBNYMXE7.mjs +0 -2
  90. package/dist/chunk-BBNYMXE7.mjs.map +0 -1
  91. package/dist/chunk-BYHIHYRR.mjs +0 -2
  92. package/dist/chunk-BYHIHYRR.mjs.map +0 -1
  93. package/dist/chunk-DZ7L3SHV.js +0 -2
  94. package/dist/chunk-DZ7L3SHV.js.map +0 -1
  95. package/dist/chunk-ECYYIQEX.mjs +0 -3
  96. package/dist/chunk-ECYYIQEX.mjs.map +0 -1
  97. package/dist/chunk-FDMJHFN7.mjs +0 -2
  98. package/dist/chunk-FDMJHFN7.mjs.map +0 -1
  99. package/dist/chunk-GKJQEOP7.mjs +0 -2
  100. package/dist/chunk-GKJQEOP7.mjs.map +0 -1
  101. package/dist/chunk-GYDP6MFV.js +0 -3
  102. package/dist/chunk-GYDP6MFV.js.map +0 -1
  103. package/dist/chunk-HB5VPQTB.mjs +0 -2
  104. package/dist/chunk-HB5VPQTB.mjs.map +0 -1
  105. package/dist/chunk-KNF5ERPK.mjs +0 -2
  106. package/dist/chunk-KNF5ERPK.mjs.map +0 -1
  107. package/dist/chunk-OPAAGNBO.mjs +0 -2
  108. package/dist/chunk-OPAAGNBO.mjs.map +0 -1
  109. package/dist/chunk-OPAQ4R4M.mjs +0 -2
  110. package/dist/chunk-OPAQ4R4M.mjs.map +0 -1
  111. package/dist/chunk-Q7IWDVJ4.js +0 -2
  112. package/dist/chunk-Q7IWDVJ4.js.map +0 -1
  113. package/dist/chunk-QPCIDSMM.js +0 -2
  114. package/dist/chunk-QPCIDSMM.js.map +0 -1
  115. package/dist/chunk-QZIX4FXS.mjs +0 -2
  116. package/dist/chunk-QZIX4FXS.mjs.map +0 -1
  117. package/dist/chunk-RMN5IPS5.js +0 -2
  118. package/dist/chunk-RMN5IPS5.js.map +0 -1
  119. package/dist/chunk-U6C6VDVZ.js +0 -2
  120. package/dist/chunk-U6C6VDVZ.js.map +0 -1
  121. package/dist/chunk-WQFQO5LK.js +0 -2
  122. package/dist/chunk-WQFQO5LK.js.map +0 -1
  123. package/dist/chunk-WVEJT7HD.mjs +0 -2
  124. package/dist/chunk-WVEJT7HD.mjs.map +0 -1
  125. package/dist/chunk-WWEWRI6S.js +0 -2
  126. package/dist/chunk-WWEWRI6S.js.map +0 -1
  127. package/dist/chunk-XJHWMHKF.js +0 -2
  128. package/dist/chunk-XJHWMHKF.js.map +0 -1
  129. package/dist/chunk-Y6KKAHLS.mjs +0 -3
  130. package/dist/chunk-Y6KKAHLS.mjs.map +0 -1
  131. package/dist/chunk-YDZ37ZZ4.js +0 -2
  132. package/dist/chunk-YDZ37ZZ4.js.map +0 -1
  133. package/dist/chunk-YPVRQKMW.js +0 -2
  134. package/dist/chunk-YPVRQKMW.js.map +0 -1
  135. package/dist/components-BMbqsbMY.d.cts +0 -126
  136. package/dist/components-C83mBQXW.d.ts +0 -126
  137. package/dist/core-CxHP8991.d.cts +0 -32
  138. package/dist/core-D0ggvjX3.d.ts +0 -32
  139. package/dist/effect-554ONNZR.js +0 -2
  140. package/dist/effect-554ONNZR.js.map +0 -1
  141. package/dist/effect-T2GVIS3T.mjs +0 -2
  142. package/dist/effect-T2GVIS3T.mjs.map +0 -1
  143. package/dist/owner-QS9tPwPr.d.cts +0 -27
  144. package/dist/owner-QS9tPwPr.d.ts +0 -27
  145. package/dist/portal-BK_0Z0hE.d.cts +0 -206
  146. package/dist/portal-CbguxtuQ.d.ts +0 -206
  147. package/dist/primitives/layout.d.cts +0 -295
  148. package/dist/primitives/layout.d.ts +0 -295
  149. package/dist/primitives/layout.js +0 -2
  150. package/dist/primitives/layout.js.map +0 -1
  151. package/dist/primitives/layout.mjs +0 -2
  152. package/dist/primitives/layout.mjs.map +0 -1
  153. package/dist/primitives/motion.d.cts +0 -230
  154. package/dist/primitives/motion.d.ts +0 -230
  155. package/dist/primitives/motion.js +0 -2
  156. package/dist/primitives/motion.js.map +0 -1
  157. package/dist/primitives/motion.mjs +0 -2
  158. package/dist/primitives/motion.mjs.map +0 -1
  159. package/dist/primitives/ui.d.cts +0 -81
  160. package/dist/primitives/ui.d.ts +0 -81
  161. package/dist/primitives/ui.js +0 -2
  162. package/dist/primitives/ui.js.map +0 -1
  163. package/dist/primitives/ui.mjs +0 -2
  164. package/dist/primitives/ui.mjs.map +0 -1
  165. package/dist/primitives.d.cts +0 -93
  166. package/dist/primitives.d.ts +0 -93
  167. package/dist/primitives.js +0 -2
  168. package/dist/primitives.js.map +0 -1
  169. package/dist/primitives.mjs +0 -2
  170. package/dist/primitives.mjs.map +0 -1
  171. package/dist/renderer-DSLb-FGg.d.cts +0 -135
  172. package/dist/renderer-DSLb-FGg.d.ts +0 -135
  173. package/dist/server.d.cts +0 -3
  174. package/dist/server.d.ts +0 -3
  175. package/dist/server.js +0 -2
  176. package/dist/server.js.map +0 -1
  177. package/dist/server.mjs +0 -2
  178. package/dist/server.mjs.map +0 -1
  179. package/dist/state-DitsMyev.d.cts +0 -96
  180. package/dist/state-DitsMyev.d.ts +0 -96
  181. package/dist/state-RYKSC35A.mjs +0 -2
  182. package/dist/state-RYKSC35A.mjs.map +0 -1
  183. package/dist/state-XUXPMCFJ.js +0 -2
  184. package/dist/state-XUXPMCFJ.js.map +0 -1
  185. package/dist/sync-Z4QqUDjF.d.cts +0 -25
  186. package/dist/sync-Z4QqUDjF.d.ts +0 -25
  187. package/dist/test-exports.d.cts +0 -68
  188. package/dist/test-exports.d.ts +0 -68
  189. package/dist/test-exports.js +0 -2
  190. package/dist/test-exports.js.map +0 -1
  191. package/dist/test-exports.mjs +0 -2
  192. package/dist/test-exports.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["VERSION"],"mappings":"AAwBO,IAAMA,CAAAA,CAAU","file":"index.mjs","sourcesContent":["/**\n * Flexium - Next-generation UI/UX library\n *\n * Please use explicit imports from submodules:\n *\n * @example\n * ```tsx\n * // Core reactivity\n * import { state, effect } from 'flexium/core'\n *\n * // DOM rendering\n * import { render, createRoot, Portal } from 'flexium/dom'\n *\n * // Canvas rendering\n * import { Canvas, Rect, Circle } from 'flexium/canvas'\n *\n * // Cross-platform primitives\n * import { Row, Column, Text } from 'flexium/primitives'\n *\n * // Router\n * import { Router, Route, Link } from 'flexium/router'\n * ```\n */\n\nexport const VERSION = '0.10.7'\n\n// Intentionally empty - use explicit submodule imports\n// flexium/core, flexium/dom, flexium/canvas, flexium/primitives, flexium/router\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["VERSION"],"mappings":"AAAO,IAAMA,CAAAA,CAAU","file":"index.mjs","sourcesContent":["export const VERSION = '0.12.6' // Bump version to signify rebuild\n"]}
@@ -1,166 +1,83 @@
1
- import { S as StateValue } from './state-DitsMyev.cjs';
2
-
3
- /**
4
- * Loop - Core animation/game loop implementation with delta time and fixed timestep
5
- */
6
- interface LoopOptions {
7
- /** Target FPS for fixed update (default: 60) */
1
+ interface LoopCallbacks {
8
2
  fixedFps?: number;
9
- /** Called every frame with delta time in seconds */
10
3
  onUpdate?: (delta: number) => void;
11
- /** Called at fixed intervals (for physics) */
12
4
  onFixedUpdate?: (fixedDelta: number) => void;
13
- /** Called every frame for rendering */
14
5
  onRender?: (alpha: number) => void;
15
6
  }
16
7
  interface Loop {
17
- /** Start the loop */
18
- start(): void;
19
- /** Stop the loop */
20
- stop(): void;
21
- /** Check if loop is running */
22
- isRunning(): boolean;
23
- /** Get current FPS */
24
- getFps(): number;
8
+ start: () => void;
9
+ stop: () => void;
10
+ isRunning: () => boolean;
11
+ getFps: () => number;
25
12
  }
26
- /**
27
- * Create an animation loop with delta time and optional fixed timestep
28
- */
29
- declare function createLoop(options?: LoopOptions): Loop;
30
-
31
- /**
32
- * keyboard - Reactive keyboard input handler
33
- *
34
- * Creates a keyboard input handler with reactive signals.
35
- * Philosophy: No hooks, just factory functions that return signal-based state.
36
- */
13
+ declare function loop(callbacks: LoopCallbacks): Loop;
37
14
 
15
+ declare enum Keys {
16
+ ArrowUp = "ArrowUp",
17
+ ArrowDown = "ArrowDown",
18
+ ArrowLeft = "ArrowLeft",
19
+ ArrowRight = "ArrowRight",
20
+ KeyW = "KeyW",
21
+ KeyA = "KeyA",
22
+ KeyS = "KeyS",
23
+ KeyD = "KeyD",
24
+ Space = "Space",
25
+ Enter = "Enter",
26
+ Escape = "Escape",
27
+ Tab = "Tab",
28
+ ShiftLeft = "ShiftLeft",
29
+ ShiftRight = "ShiftRight",
30
+ ControlLeft = "ControlLeft",
31
+ ControlRight = "ControlRight",
32
+ AltLeft = "AltLeft",
33
+ AltRight = "AltRight",
34
+ Digit0 = "Digit0",
35
+ Digit1 = "Digit1",
36
+ Digit2 = "Digit2",
37
+ Digit3 = "Digit3",
38
+ Digit4 = "Digit4",
39
+ Digit5 = "Digit5",
40
+ Digit6 = "Digit6",
41
+ Digit7 = "Digit7",
42
+ Digit8 = "Digit8",
43
+ Digit9 = "Digit9",
44
+ KeyE = "KeyE",
45
+ KeyQ = "KeyQ",
46
+ KeyR = "KeyR",
47
+ KeyF = "KeyF"
48
+ }
38
49
  interface KeyboardState {
39
- /** Check if a key is currently pressed */
40
- isPressed(key: string): boolean;
41
- /** Check if a key was pressed in the current frame */
42
- isJustPressed(key: string): boolean;
43
- /** Check if a key was released in the current frame */
44
- isJustReleased(key: string): boolean;
45
- /** Get all currently pressed keys */
46
- getPressed(): string[];
47
- /** Get all currently pressed keys (alias) */
48
- getPressedKeys(): string[];
49
- /**
50
- * Reactive set of all currently pressed keys
51
- * @deprecated Use isPressed() or getPressed() instead for better performance
52
- */
53
- keys: StateValue<Set<string>>;
54
- /** Clear all state at end of frame */
55
- clearFrameState(): void;
56
- /** Remove event listeners */
57
- dispose(): void;
50
+ isPressed: (key: string) => boolean;
51
+ isJustPressed: (key: string) => boolean;
52
+ isJustReleased: (key: string) => boolean;
53
+ getPressedKeys: () => string[];
54
+ clearFrameState: () => void;
55
+ dispose: () => void;
58
56
  }
59
- /**
60
- * Create a keyboard input handler with reactive state
61
- *
62
- * @example
63
- * ```tsx
64
- * const kb = keyboard()
65
- *
66
- * effect(() => {
67
- * if (kb.isPressed(Keys.ArrowUp)) {
68
- * player.y -= speed
69
- * }
70
- * })
71
- * ```
72
- */
73
57
  declare function keyboard(target?: EventTarget): KeyboardState;
74
- /** Common key codes for convenience */
75
- declare const Keys: {
76
- readonly ArrowUp: "arrowup";
77
- readonly ArrowDown: "arrowdown";
78
- readonly ArrowLeft: "arrowleft";
79
- readonly ArrowRight: "arrowright";
80
- readonly KeyW: "keyw";
81
- readonly KeyA: "keya";
82
- readonly KeyS: "keys";
83
- readonly KeyD: "keyd";
84
- readonly Space: "space";
85
- readonly Enter: "enter";
86
- readonly Escape: "escape";
87
- readonly ShiftLeft: "shiftleft";
88
- readonly ShiftRight: "shiftright";
89
- readonly ControlLeft: "controlleft";
90
- readonly ControlRight: "controlright";
91
- readonly AltLeft: "altleft";
92
- readonly AltRight: "altright";
93
- readonly Tab: "tab";
94
- readonly Digit0: "digit0";
95
- readonly Digit1: "digit1";
96
- readonly Digit2: "digit2";
97
- readonly Digit3: "digit3";
98
- readonly Digit4: "digit4";
99
- readonly Digit5: "digit5";
100
- readonly Digit6: "digit6";
101
- readonly Digit7: "digit7";
102
- readonly Digit8: "digit8";
103
- readonly Digit9: "digit9";
104
- };
105
-
106
- /**
107
- * mouse - Reactive mouse input handler
108
- *
109
- * Creates a mouse input handler with reactive signals.
110
- * Philosophy: No hooks, just factory functions that return signal-based state.
111
- */
112
58
 
113
- interface Vec2 {
114
- x: number;
115
- y: number;
116
- }
117
- interface MouseState {
118
- /** Current mouse position relative to target */
119
- readonly position: StateValue<Vec2>;
120
- /** Mouse position delta since last frame */
121
- readonly delta: StateValue<Vec2>;
122
- /** Check if a mouse button is pressed (0=left, 1=middle, 2=right) */
123
- isPressed(button: number): boolean;
124
- /** Check if left mouse button is pressed */
125
- isLeftPressed(): boolean;
126
- /** Check if right mouse button is pressed */
127
- isRightPressed(): boolean;
128
- /** Check if middle mouse button is pressed */
129
- isMiddlePressed(): boolean;
130
- /** Wheel delta (positive = scroll down) */
131
- readonly wheelDelta: StateValue<number>;
132
- /** Clear frame state (call at end of frame) */
133
- clearFrameState(): void;
134
- /** Cleanup event listeners */
135
- dispose(): void;
59
+ declare enum MouseButton {
60
+ Left = 0,
61
+ Middle = 1,
62
+ Right = 2
136
63
  }
137
64
  interface MouseOptions {
138
- /** Element to track mouse relative to (default: window) */
65
+ canvas?: HTMLCanvasElement | (() => HTMLCanvasElement | undefined);
139
66
  target?: EventTarget;
140
- /** Canvas element for coordinate calculation (if different from target) */
141
- canvas?: HTMLCanvasElement;
142
67
  }
143
- /**
144
- * Create a mouse input handler with reactive state
145
- *
146
- * @example
147
- * ```tsx
148
- * const m = mouse()
149
- *
150
- * effect(() => {
151
- * console.log('Mouse at:', m.position.value)
152
- * if (m.isLeftPressed()) {
153
- * draw(m.position.value)
154
- * }
155
- * })
156
- * ```
157
- */
68
+ interface MouseState {
69
+ x: number | null;
70
+ y: number | null;
71
+ deltaX: number;
72
+ deltaY: number;
73
+ wheelDelta: number;
74
+ isPressed: (button: MouseButton) => boolean;
75
+ isLeftPressed: () => boolean;
76
+ isRightPressed: () => boolean;
77
+ isMiddlePressed: () => boolean;
78
+ clearFrameState: () => void;
79
+ dispose: () => void;
80
+ }
158
81
  declare function mouse(options?: MouseOptions): MouseState;
159
- /** Mouse button constants */
160
- declare const MouseButton: {
161
- readonly Left: 0;
162
- readonly Middle: 1;
163
- readonly Right: 2;
164
- };
165
82
 
166
- export { type KeyboardState, Keys, type Loop, type LoopOptions, MouseButton, type MouseOptions, type MouseState, type Vec2, createLoop, keyboard, mouse };
83
+ export { type KeyboardState, Keys, type Loop, type LoopCallbacks, MouseButton, type MouseOptions, type MouseState, keyboard, loop, mouse };
@@ -1,166 +1,83 @@
1
- import { S as StateValue } from './state-DitsMyev.js';
2
-
3
- /**
4
- * Loop - Core animation/game loop implementation with delta time and fixed timestep
5
- */
6
- interface LoopOptions {
7
- /** Target FPS for fixed update (default: 60) */
1
+ interface LoopCallbacks {
8
2
  fixedFps?: number;
9
- /** Called every frame with delta time in seconds */
10
3
  onUpdate?: (delta: number) => void;
11
- /** Called at fixed intervals (for physics) */
12
4
  onFixedUpdate?: (fixedDelta: number) => void;
13
- /** Called every frame for rendering */
14
5
  onRender?: (alpha: number) => void;
15
6
  }
16
7
  interface Loop {
17
- /** Start the loop */
18
- start(): void;
19
- /** Stop the loop */
20
- stop(): void;
21
- /** Check if loop is running */
22
- isRunning(): boolean;
23
- /** Get current FPS */
24
- getFps(): number;
8
+ start: () => void;
9
+ stop: () => void;
10
+ isRunning: () => boolean;
11
+ getFps: () => number;
25
12
  }
26
- /**
27
- * Create an animation loop with delta time and optional fixed timestep
28
- */
29
- declare function createLoop(options?: LoopOptions): Loop;
30
-
31
- /**
32
- * keyboard - Reactive keyboard input handler
33
- *
34
- * Creates a keyboard input handler with reactive signals.
35
- * Philosophy: No hooks, just factory functions that return signal-based state.
36
- */
13
+ declare function loop(callbacks: LoopCallbacks): Loop;
37
14
 
15
+ declare enum Keys {
16
+ ArrowUp = "ArrowUp",
17
+ ArrowDown = "ArrowDown",
18
+ ArrowLeft = "ArrowLeft",
19
+ ArrowRight = "ArrowRight",
20
+ KeyW = "KeyW",
21
+ KeyA = "KeyA",
22
+ KeyS = "KeyS",
23
+ KeyD = "KeyD",
24
+ Space = "Space",
25
+ Enter = "Enter",
26
+ Escape = "Escape",
27
+ Tab = "Tab",
28
+ ShiftLeft = "ShiftLeft",
29
+ ShiftRight = "ShiftRight",
30
+ ControlLeft = "ControlLeft",
31
+ ControlRight = "ControlRight",
32
+ AltLeft = "AltLeft",
33
+ AltRight = "AltRight",
34
+ Digit0 = "Digit0",
35
+ Digit1 = "Digit1",
36
+ Digit2 = "Digit2",
37
+ Digit3 = "Digit3",
38
+ Digit4 = "Digit4",
39
+ Digit5 = "Digit5",
40
+ Digit6 = "Digit6",
41
+ Digit7 = "Digit7",
42
+ Digit8 = "Digit8",
43
+ Digit9 = "Digit9",
44
+ KeyE = "KeyE",
45
+ KeyQ = "KeyQ",
46
+ KeyR = "KeyR",
47
+ KeyF = "KeyF"
48
+ }
38
49
  interface KeyboardState {
39
- /** Check if a key is currently pressed */
40
- isPressed(key: string): boolean;
41
- /** Check if a key was pressed in the current frame */
42
- isJustPressed(key: string): boolean;
43
- /** Check if a key was released in the current frame */
44
- isJustReleased(key: string): boolean;
45
- /** Get all currently pressed keys */
46
- getPressed(): string[];
47
- /** Get all currently pressed keys (alias) */
48
- getPressedKeys(): string[];
49
- /**
50
- * Reactive set of all currently pressed keys
51
- * @deprecated Use isPressed() or getPressed() instead for better performance
52
- */
53
- keys: StateValue<Set<string>>;
54
- /** Clear all state at end of frame */
55
- clearFrameState(): void;
56
- /** Remove event listeners */
57
- dispose(): void;
50
+ isPressed: (key: string) => boolean;
51
+ isJustPressed: (key: string) => boolean;
52
+ isJustReleased: (key: string) => boolean;
53
+ getPressedKeys: () => string[];
54
+ clearFrameState: () => void;
55
+ dispose: () => void;
58
56
  }
59
- /**
60
- * Create a keyboard input handler with reactive state
61
- *
62
- * @example
63
- * ```tsx
64
- * const kb = keyboard()
65
- *
66
- * effect(() => {
67
- * if (kb.isPressed(Keys.ArrowUp)) {
68
- * player.y -= speed
69
- * }
70
- * })
71
- * ```
72
- */
73
57
  declare function keyboard(target?: EventTarget): KeyboardState;
74
- /** Common key codes for convenience */
75
- declare const Keys: {
76
- readonly ArrowUp: "arrowup";
77
- readonly ArrowDown: "arrowdown";
78
- readonly ArrowLeft: "arrowleft";
79
- readonly ArrowRight: "arrowright";
80
- readonly KeyW: "keyw";
81
- readonly KeyA: "keya";
82
- readonly KeyS: "keys";
83
- readonly KeyD: "keyd";
84
- readonly Space: "space";
85
- readonly Enter: "enter";
86
- readonly Escape: "escape";
87
- readonly ShiftLeft: "shiftleft";
88
- readonly ShiftRight: "shiftright";
89
- readonly ControlLeft: "controlleft";
90
- readonly ControlRight: "controlright";
91
- readonly AltLeft: "altleft";
92
- readonly AltRight: "altright";
93
- readonly Tab: "tab";
94
- readonly Digit0: "digit0";
95
- readonly Digit1: "digit1";
96
- readonly Digit2: "digit2";
97
- readonly Digit3: "digit3";
98
- readonly Digit4: "digit4";
99
- readonly Digit5: "digit5";
100
- readonly Digit6: "digit6";
101
- readonly Digit7: "digit7";
102
- readonly Digit8: "digit8";
103
- readonly Digit9: "digit9";
104
- };
105
-
106
- /**
107
- * mouse - Reactive mouse input handler
108
- *
109
- * Creates a mouse input handler with reactive signals.
110
- * Philosophy: No hooks, just factory functions that return signal-based state.
111
- */
112
58
 
113
- interface Vec2 {
114
- x: number;
115
- y: number;
116
- }
117
- interface MouseState {
118
- /** Current mouse position relative to target */
119
- readonly position: StateValue<Vec2>;
120
- /** Mouse position delta since last frame */
121
- readonly delta: StateValue<Vec2>;
122
- /** Check if a mouse button is pressed (0=left, 1=middle, 2=right) */
123
- isPressed(button: number): boolean;
124
- /** Check if left mouse button is pressed */
125
- isLeftPressed(): boolean;
126
- /** Check if right mouse button is pressed */
127
- isRightPressed(): boolean;
128
- /** Check if middle mouse button is pressed */
129
- isMiddlePressed(): boolean;
130
- /** Wheel delta (positive = scroll down) */
131
- readonly wheelDelta: StateValue<number>;
132
- /** Clear frame state (call at end of frame) */
133
- clearFrameState(): void;
134
- /** Cleanup event listeners */
135
- dispose(): void;
59
+ declare enum MouseButton {
60
+ Left = 0,
61
+ Middle = 1,
62
+ Right = 2
136
63
  }
137
64
  interface MouseOptions {
138
- /** Element to track mouse relative to (default: window) */
65
+ canvas?: HTMLCanvasElement | (() => HTMLCanvasElement | undefined);
139
66
  target?: EventTarget;
140
- /** Canvas element for coordinate calculation (if different from target) */
141
- canvas?: HTMLCanvasElement;
142
67
  }
143
- /**
144
- * Create a mouse input handler with reactive state
145
- *
146
- * @example
147
- * ```tsx
148
- * const m = mouse()
149
- *
150
- * effect(() => {
151
- * console.log('Mouse at:', m.position.value)
152
- * if (m.isLeftPressed()) {
153
- * draw(m.position.value)
154
- * }
155
- * })
156
- * ```
157
- */
68
+ interface MouseState {
69
+ x: number | null;
70
+ y: number | null;
71
+ deltaX: number;
72
+ deltaY: number;
73
+ wheelDelta: number;
74
+ isPressed: (button: MouseButton) => boolean;
75
+ isLeftPressed: () => boolean;
76
+ isRightPressed: () => boolean;
77
+ isMiddlePressed: () => boolean;
78
+ clearFrameState: () => void;
79
+ dispose: () => void;
80
+ }
158
81
  declare function mouse(options?: MouseOptions): MouseState;
159
- /** Mouse button constants */
160
- declare const MouseButton: {
161
- readonly Left: 0;
162
- readonly Middle: 1;
163
- readonly Right: 2;
164
- };
165
82
 
166
- export { type KeyboardState, Keys, type Loop, type LoopOptions, MouseButton, type MouseOptions, type MouseState, type Vec2, createLoop, keyboard, mouse };
83
+ export { type KeyboardState, Keys, type Loop, type LoopCallbacks, MouseButton, type MouseOptions, type MouseState, keyboard, loop, mouse };
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkXJHWMHKF_js=require('./chunk-XJHWMHKF.js');require('./chunk-YPVRQKMW.js'),require('./chunk-WWEWRI6S.js'),require('./chunk-GYDP6MFV.js');function K(c={}){let{fixedFps:i=60,onUpdate:p,onFixedUpdate:g,onRender:m}=c,l=1/i,r=false,f,y=0,n=0,w=0,e=0,t=0,o=true;function d(b){if(!r)return;f=requestAnimationFrame(d);let L=b/1e3;if(o){y=L,o=false;return}let E=Math.min(L-y,.25);if(y=L,e++,t+=E,t>=1&&(w=e,e=0,t-=1),p&&p(E),g)for(n+=E;n>=l;)g(l),n-=l;if(m){let S=g?n/l:1;m(S);}}return {start(){r||(r=true,o=true,n=0,f=requestAnimationFrame(d));},stop(){r=false,f!==void 0&&(cancelAnimationFrame(f),f=void 0);},isRunning(){return r},getFps(){return w}}}function V(c=window){let i=new Map,[p,g]=chunkXJHWMHKF_js.k(false),m=new Set,l=new Set;function r(e){return e.toLowerCase()}function f(e){let t=i.get(e);return t||(t=chunkXJHWMHKF_js.k(false),i.set(e,t)),t}function y(e){let t=r(e.code),[o,d]=f(t);o()||(d(true),m.add(t),g(true));}function n(e){let t=r(e.code),[o,d]=f(t);if(o()){d(false),l.add(t);let b=false;for(let[L]of i.values())if(L()){b=true;break}g(b);}}function w(){for(let[,e]of i.values())e(false);g(false),m.clear(),l.clear();}return c.addEventListener("keydown",y),c.addEventListener("keyup",n),window.addEventListener("blur",w),{isPressed(e){let t=i.get(r(e));return t?t[0]():false},isJustPressed(e){return m.has(r(e))},isJustReleased(e){return l.has(r(e))},getPressedKeys(){let e=[];for(let[t,[o]]of i.entries())o()&&e.push(t);return e},getPressed(){return this.getPressedKeys()},get keys(){let[e]=chunkXJHWMHKF_js.k(()=>{let t=new Set;for(let[o,[d]]of i.entries())d()&&t.add(o);return t});return e},clearFrameState(){m.clear(),l.clear();},dispose(){c.removeEventListener("keydown",y),c.removeEventListener("keyup",n),c===window&&c.removeEventListener("blur",w);}}}var F={ArrowUp:"arrowup",ArrowDown:"arrowdown",ArrowLeft:"arrowleft",ArrowRight:"arrowright",KeyW:"keyw",KeyA:"keya",KeyS:"keys",KeyD:"keyd",Space:"space",Enter:"enter",Escape:"escape",ShiftLeft:"shiftleft",ShiftRight:"shiftright",ControlLeft:"controlleft",ControlRight:"controlright",AltLeft:"altleft",AltRight:"altright",Tab:"tab",Digit0:"digit0",Digit1:"digit1",Digit2:"digit2",Digit3:"digit3",Digit4:"digit4",Digit5:"digit5",Digit6:"digit6",Digit7:"digit7",Digit8:"digit8",Digit9:"digit9"};function R(c={}){let{target:i=window,canvas:p}=c,[g,m]=chunkXJHWMHKF_js.k({x:0,y:0}),[l,r]=chunkXJHWMHKF_js.k({x:0,y:0}),[f,y]=chunkXJHWMHKF_js.k(0),[n,w]=chunkXJHWMHKF_js.k(new Set),e=0,t=0,o=0,d=0,b=0;function L(s){if(p){let v=p.getBoundingClientRect(),a=p.width/v.width,P=p.height/v.height;return {x:(s.clientX-v.left)*a,y:(s.clientY-v.top)*P}}return {x:s.clientX,y:s.clientY}}function E(s){let a=L(s);o+=a.x-e,d+=a.y-t,e=a.x,t=a.y,m(a),r({x:o,y:d});}function S(s){let v=s,a=new Set(n());a.add(v.button),w(a);}function x(s){let v=s,a=new Set(n());a.delete(v.button),w(a);}function M(s){b+=Math.sign(s.deltaY),y(b);}function k(){w(new Set);}function D(s){}let u=p||i;return u.addEventListener("mousemove",E),u.addEventListener("mousedown",S),u.addEventListener("mouseup",x),u.addEventListener("wheel",M),u.addEventListener("mouseleave",k),u.addEventListener("contextmenu",D),i!==window&&window.addEventListener("mouseup",x),{get position(){return g},get delta(){return l},get wheelDelta(){return f},isPressed(s){return n().has(s)},isLeftPressed(){return n().has(0)},isRightPressed(){return n().has(2)},isMiddlePressed(){return n().has(1)},clearFrameState(){o=0,d=0,b=0,r({x:0,y:0}),y(0);},dispose(){u.removeEventListener("mousemove",E),u.removeEventListener("mousedown",S),u.removeEventListener("mouseup",x),u.removeEventListener("wheel",M),u.removeEventListener("mouseleave",k),u.removeEventListener("contextmenu",D),i!==window&&window.removeEventListener("mouseup",x);}}}var A={Left:0,Middle:1,Right:2};exports.Keys=F;exports.MouseButton=A;exports.createLoop=K;exports.keyboard=V;exports.mouse=R;//# sourceMappingURL=interactive.js.map
1
+ 'use strict';var chunkALTO2MGI_js=require('./chunk-ALTO2MGI.js');require('./chunk-7BXR4ZFD.js'),require('./chunk-ENWGYQNU.js');function F(a){let{fixedFps:n=60,onUpdate:b,onFixedUpdate:r,onRender:w}=a,g=1/n,S=.25,l=false,m=0,t=0,s=0,i=0,u=0,o=null;function d(h){if(!l)return;let E=Math.min((h-m)/1e3,S);if(m=h,b&&b(E),r)for(t+=E;t>=g;)r(g),t-=g;if(w){let y=t/g;w(y);}i++,h-u>=1e3&&(s=i,i=0,u=h),o=requestAnimationFrame(d);}return {start:()=>{l||(l=true,m=performance.now(),t=0,o=requestAnimationFrame(d));},stop:()=>{l=false,o!==null&&(cancelAnimationFrame(o),o=null);},isRunning:()=>l,getFps:()=>s}}var k=(e=>(e.ArrowUp="ArrowUp",e.ArrowDown="ArrowDown",e.ArrowLeft="ArrowLeft",e.ArrowRight="ArrowRight",e.KeyW="KeyW",e.KeyA="KeyA",e.KeyS="KeyS",e.KeyD="KeyD",e.Space="Space",e.Enter="Enter",e.Escape="Escape",e.Tab="Tab",e.ShiftLeft="ShiftLeft",e.ShiftRight="ShiftRight",e.ControlLeft="ControlLeft",e.ControlRight="ControlRight",e.AltLeft="AltLeft",e.AltRight="AltRight",e.Digit0="Digit0",e.Digit1="Digit1",e.Digit2="Digit2",e.Digit3="Digit3",e.Digit4="Digit4",e.Digit5="Digit5",e.Digit6="Digit6",e.Digit7="Digit7",e.Digit8="Digit8",e.Digit9="Digit9",e.KeyE="KeyE",e.KeyQ="KeyQ",e.KeyR="KeyR",e.KeyF="KeyF",e))(k||{});function C(a=window){let[n,b]=chunkALTO2MGI_js.a(new Set,{key:["keyboard","pressed"]}),[r,w]=chunkALTO2MGI_js.a(new Set,{key:["keyboard","justPressed"]}),[g,S]=chunkALTO2MGI_js.a(new Set,{key:["keyboard","justReleased"]}),l=t=>{let s=t.code,i=n;if(!i.has(s)){let u=new Set(i);u.add(s),b(u);let o=r,d=new Set(o);d.add(s),w(d);}},m=t=>{let s=t.code,i=n,u=new Set(i);u.delete(s),b(u);let o=g,d=new Set(o);d.add(s),S(d);};return a.addEventListener("keydown",l),a.addEventListener("keyup",m),{isPressed:t=>n?.has(t)||false,isJustPressed:t=>r?.has(t)||false,isJustReleased:t=>g?.has(t)||false,getPressedKeys:()=>Array.from(n||[]),clearFrameState:()=>{w(new Set),S(new Set);},dispose:()=>{a.removeEventListener("keydown",l),a.removeEventListener("keyup",m);}}}var M=(r=>(r[r.Left=0]="Left",r[r.Middle=1]="Middle",r[r.Right=2]="Right",r))(M||{});function J(a={}){let n=a.target||window,b=typeof a.canvas=="function"?a.canvas:()=>a.canvas,[r,w]=chunkALTO2MGI_js.a({x:0,y:0},{key:["mouse","position"]}),[g,S]=chunkALTO2MGI_js.a({x:0,y:0},{key:["mouse","delta"]}),[l,m]=chunkALTO2MGI_js.a(0,{key:["mouse","wheel"]}),[t,s]=chunkALTO2MGI_js.a(new Set,{key:["mouse","buttons"]}),i=0,u=0,o=p=>{let f=p,D=b(),c=f.clientX,L=f.clientY;if(D){let R=D.getBoundingClientRect();c=f.clientX-R.left,L=f.clientY-R.top;}w({x:c,y:L}),S({x:c-i,y:L-u}),i=c,u=L;},d=p=>{let f=p.button,D=t,c=new Set(D);c.add(f),s(c);},h=p=>{let f=p.button,D=t,c=new Set(D);c.delete(f),s(c);},E=p=>{m(p.deltaY);};n.addEventListener("mousemove",o),n.addEventListener("mousedown",d),n.addEventListener("mouseup",h),n.addEventListener("wheel",E);let y=t,x=r,P=g,A=l;return {get x(){return x.x},get y(){return x.y},get deltaX(){return P.x},get deltaY(){return P.y},get wheelDelta(){return A},isPressed:p=>y?.has(p)||false,isLeftPressed:()=>y?.has(0)||false,isRightPressed:()=>y?.has(2)||false,isMiddlePressed:()=>y?.has(1)||false,clearFrameState:()=>{S({x:0,y:0}),m(0);},dispose:()=>{n.removeEventListener("mousemove",o),n.removeEventListener("mousedown",d),n.removeEventListener("mouseup",h),n.removeEventListener("wheel",E);}}}exports.Keys=k;exports.MouseButton=M;exports.keyboard=C;exports.loop=F;exports.mouse=J;//# sourceMappingURL=interactive.js.map
2
2
  //# sourceMappingURL=interactive.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/interactive/loop.ts","../src/interactive/keyboard.ts","../src/interactive/mouse.ts"],"names":["createLoop","options","fixedFps","onUpdate","onFixedUpdate","onRender","fixedDelta","running","rafId","lastTime","accumulator","fps","frameCount","fpsTime","isFirstFrame","loop","currentTime","time","delta","alpha","keyboard","target","keys","anyKeyPressed","setAnyKeyPressed","state","justPressed","justReleased","normalizeKey","key","getKeySignal","code","s","handleKeyDown","setS","handleKeyUp","any","sig","handleBlur","pressed","keysSignal","Keys","mouse","canvas","position","setPosition","setDelta","wheelDelta","setWheelDelta","buttons","setButtons","lastX","lastY","frameDeltaX","frameDeltaY","frameWheelDelta","getCanvasCoordinates","event","rect","scaleX","scaleY","handleMouseMove","e","coords","handleMouseDown","newButtons","handleMouseUp","handleWheel","handleMouseLeave","handleContextMenu","_e","eventTarget","button","MouseButton"],"mappings":"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","file":"interactive.js","sourcesContent":["/**\n * Loop - Core animation/game loop implementation with delta time and fixed timestep\n */\n\nexport interface LoopOptions {\n /** Target FPS for fixed update (default: 60) */\n fixedFps?: number\n /** Called every frame with delta time in seconds */\n onUpdate?: (delta: number) => void\n /** Called at fixed intervals (for physics) */\n onFixedUpdate?: (fixedDelta: number) => void\n /** Called every frame for rendering */\n onRender?: (alpha: number) => void\n}\n\nexport interface Loop {\n /** Start the loop */\n start(): void\n /** Stop the loop */\n stop(): void\n /** Check if loop is running */\n isRunning(): boolean\n /** Get current FPS */\n getFps(): number\n}\n\n/**\n * Create an animation loop with delta time and optional fixed timestep\n */\nexport function createLoop(options: LoopOptions = {}): Loop {\n const { fixedFps = 60, onUpdate, onFixedUpdate, onRender } = options\n\n const fixedDelta = 1 / fixedFps\n let running = false\n let rafId: number | undefined\n let lastTime = 0\n let accumulator = 0\n let fps = 0\n let frameCount = 0\n let fpsTime = 0\n let isFirstFrame = true\n\n function loop(currentTime: number): void {\n if (!running) return\n\n rafId = requestAnimationFrame(loop)\n\n // Convert to seconds\n const time = currentTime / 1000\n\n // Initialize lastTime on first frame and skip processing\n if (isFirstFrame) {\n lastTime = time\n isFirstFrame = false\n return\n }\n\n const delta = Math.min(time - lastTime, 0.25) // Cap at 250ms\n lastTime = time\n\n // FPS counter\n frameCount++\n fpsTime += delta\n if (fpsTime >= 1) {\n fps = frameCount\n frameCount = 0\n fpsTime -= 1\n }\n\n // Variable update\n if (onUpdate) {\n onUpdate(delta)\n }\n\n // Fixed update (for physics)\n if (onFixedUpdate) {\n accumulator += delta\n\n while (accumulator >= fixedDelta) {\n onFixedUpdate(fixedDelta)\n accumulator -= fixedDelta\n }\n }\n\n // Render with interpolation alpha\n if (onRender) {\n const alpha = onFixedUpdate ? accumulator / fixedDelta : 1\n onRender(alpha)\n }\n }\n\n return {\n start() {\n if (running) return\n running = true\n isFirstFrame = true\n accumulator = 0\n rafId = requestAnimationFrame(loop)\n },\n\n stop() {\n running = false\n if (rafId !== undefined) {\n cancelAnimationFrame(rafId)\n rafId = undefined\n }\n },\n\n isRunning() {\n return running\n },\n\n getFps() {\n return fps\n },\n }\n}\n","/**\n * keyboard - Reactive keyboard input handler\n *\n * Creates a keyboard input handler with reactive signals.\n * Philosophy: No hooks, just factory functions that return signal-based state.\n */\n\nimport { state, type StateValue } from '../core/state'\n\nexport interface KeyboardState {\n /** Check if a key is currently pressed */\n isPressed(key: string): boolean\n /** Check if a key was pressed in the current frame */\n isJustPressed(key: string): boolean\n /** Check if a key was released in the current frame */\n isJustReleased(key: string): boolean\n /** Get all currently pressed keys */\n getPressed(): string[]\n /** Get all currently pressed keys (alias) */\n getPressedKeys(): string[]\n /** \n * Reactive set of all currently pressed keys\n * @deprecated Use isPressed() or getPressed() instead for better performance\n */\n keys: StateValue<Set<string>>\n\n /** Clear all state at end of frame */\n clearFrameState(): void\n /** Remove event listeners */\n dispose(): void\n}\n\n/**\n * Create a keyboard input handler with reactive state\n *\n * @example\n * ```tsx\n * const kb = keyboard()\n *\n * effect(() => {\n * if (kb.isPressed(Keys.ArrowUp)) {\n * player.y -= speed\n * }\n * })\n * ```\n */\nexport function keyboard(target: EventTarget = window): KeyboardState {\n // Map of key code -> [signal, setter]\n const keys = new Map<string, [StateValue<boolean>, (v: boolean) => void]>()\n const [anyKeyPressed, setAnyKeyPressed] = state(false)\n const justPressed = new Set<string>()\n const justReleased = new Set<string>()\n\n function normalizeKey(key: string): string {\n return key.toLowerCase()\n }\n\n function getKeySignal(code: string): [StateValue<boolean>, (v: boolean) => void] {\n let s = keys.get(code)\n if (!s) {\n s = state(false)\n keys.set(code, s)\n }\n return s\n }\n\n // Cleanup original handlers if they exist or just overwrite?\n // Previous replace might have mixed things.\n // Re-implement handlers fully.\n\n function handleKeyDown(e: KeyboardEvent): void {\n const key = normalizeKey(e.code)\n const [s, setS] = getKeySignal(key)\n if (!s()) {\n setS(true)\n justPressed.add(key)\n setAnyKeyPressed(true)\n }\n }\n\n function handleKeyUp(e: KeyboardEvent): void {\n const key = normalizeKey(e.code)\n const [s, setS] = getKeySignal(key)\n if (s()) {\n setS(false)\n justReleased.add(key)\n // Re-check any key\n let any = false\n for (const [sig] of keys.values()) {\n if (sig()) {\n any = true\n break\n }\n }\n setAnyKeyPressed(any)\n }\n }\n\n function handleBlur(): void {\n // Clear all keys when window loses focus\n for (const [, setS] of keys.values()) {\n setS(false)\n }\n setAnyKeyPressed(false)\n justPressed.clear()\n justReleased.clear()\n }\n\n // Attach listeners\n target.addEventListener('keydown', handleKeyDown as EventListener)\n target.addEventListener('keyup', handleKeyUp as EventListener)\n window.addEventListener('blur', handleBlur)\n\n return {\n isPressed(key: string) {\n const s = keys.get(normalizeKey(key))\n return s ? s[0]() : false\n },\n\n isJustPressed(key: string) {\n return justPressed.has(normalizeKey(key))\n },\n\n isJustReleased(key: string) {\n return justReleased.has(normalizeKey(key))\n },\n\n getPressedKeys(): string[] {\n const pressed: string[] = []\n for (const [key, [sig]] of keys.entries()) {\n if (sig()) {\n pressed.push(key)\n }\n }\n return pressed\n },\n\n getPressed(): string[] {\n return this.getPressedKeys()\n },\n\n get keys() {\n // This getter returns a computed signal that derives from the individual key signals\n const [keysSignal] = state(() => {\n const pressed = new Set<string>()\n for (const [key, [sig]] of keys.entries()) {\n if (sig()) {\n pressed.add(key)\n }\n }\n return pressed\n })\n return keysSignal as unknown as StateValue<Set<string>>\n },\n\n clearFrameState(): void {\n justPressed.clear()\n justReleased.clear()\n },\n\n dispose(): void {\n target.removeEventListener('keydown', handleKeyDown as EventListener)\n target.removeEventListener('keyup', handleKeyUp as EventListener)\n if (target === window) {\n target.removeEventListener('blur', handleBlur)\n }\n },\n }\n}\n\n/** Common key codes for convenience */\nexport const Keys = {\n // Arrow keys\n ArrowUp: 'arrowup',\n ArrowDown: 'arrowdown',\n ArrowLeft: 'arrowleft',\n ArrowRight: 'arrowright',\n\n // WASD\n KeyW: 'keyw',\n KeyA: 'keya',\n KeyS: 'keys',\n KeyD: 'keyd',\n\n // Common keys\n Space: 'space',\n Enter: 'enter',\n Escape: 'escape',\n ShiftLeft: 'shiftleft',\n ShiftRight: 'shiftright',\n ControlLeft: 'controlleft',\n ControlRight: 'controlright',\n AltLeft: 'altleft',\n AltRight: 'altright',\n Tab: 'tab',\n\n // Numbers\n Digit0: 'digit0',\n Digit1: 'digit1',\n Digit2: 'digit2',\n Digit3: 'digit3',\n Digit4: 'digit4',\n Digit5: 'digit5',\n Digit6: 'digit6',\n Digit7: 'digit7',\n Digit8: 'digit8',\n Digit9: 'digit9',\n} as const\n","/**\n * mouse - Reactive mouse input handler\n *\n * Creates a mouse input handler with reactive signals.\n * Philosophy: No hooks, just factory functions that return signal-based state.\n */\n\nimport { state, type StateValue } from '../core/state'\n\nexport interface Vec2 {\n x: number\n y: number\n}\n\nexport interface MouseState {\n /** Current mouse position relative to target */\n readonly position: StateValue<Vec2>\n /** Mouse position delta since last frame */\n readonly delta: StateValue<Vec2>\n /** Check if a mouse button is pressed (0=left, 1=middle, 2=right) */\n isPressed(button: number): boolean\n /** Check if left mouse button is pressed */\n isLeftPressed(): boolean\n /** Check if right mouse button is pressed */\n isRightPressed(): boolean\n /** Check if middle mouse button is pressed */\n isMiddlePressed(): boolean\n /** Wheel delta (positive = scroll down) */\n readonly wheelDelta: StateValue<number>\n /** Clear frame state (call at end of frame) */\n clearFrameState(): void\n /** Cleanup event listeners */\n dispose(): void\n}\n\nexport interface MouseOptions {\n /** Element to track mouse relative to (default: window) */\n target?: EventTarget\n /** Canvas element for coordinate calculation (if different from target) */\n canvas?: HTMLCanvasElement\n}\n\n/**\n * Create a mouse input handler with reactive state\n *\n * @example\n * ```tsx\n * const m = mouse()\n *\n * effect(() => {\n * console.log('Mouse at:', m.position.value)\n * if (m.isLeftPressed()) {\n * draw(m.position.value)\n * }\n * })\n * ```\n */\nexport function mouse(options: MouseOptions = {}): MouseState {\n const { target = window, canvas } = options\n\n const [position, setPosition] = state<Vec2>({ x: 0, y: 0 })\n const [delta, setDelta] = state<Vec2>({ x: 0, y: 0 })\n const [wheelDelta, setWheelDelta] = state<number>(0)\n const [buttons, setButtons] = state<Set<number>>(new Set())\n\n let lastX = 0\n let lastY = 0\n let frameDeltaX = 0\n let frameDeltaY = 0\n let frameWheelDelta = 0\n\n function getCanvasCoordinates(event: MouseEvent): Vec2 {\n if (canvas) {\n const rect = canvas.getBoundingClientRect()\n const scaleX = canvas.width / rect.width\n const scaleY = canvas.height / rect.height\n return {\n x: (event.clientX - rect.left) * scaleX,\n y: (event.clientY - rect.top) * scaleY,\n }\n }\n return {\n x: event.clientX,\n y: event.clientY,\n }\n }\n\n function handleMouseMove(e: Event): void {\n const event = e as MouseEvent\n const coords = getCanvasCoordinates(event)\n\n frameDeltaX += coords.x - lastX\n frameDeltaY += coords.y - lastY\n lastX = coords.x\n lastY = coords.y\n\n setPosition(coords)\n setDelta({ x: frameDeltaX, y: frameDeltaY })\n }\n\n function handleMouseDown(e: Event): void {\n const event = e as MouseEvent\n const newButtons = new Set(buttons())\n newButtons.add(event.button)\n setButtons(newButtons)\n }\n\n function handleMouseUp(e: Event): void {\n const event = e as MouseEvent\n const newButtons = new Set(buttons())\n newButtons.delete(event.button)\n setButtons(newButtons)\n }\n\n function handleWheel(e: Event): void {\n const event = e as WheelEvent\n frameWheelDelta += Math.sign(event.deltaY)\n setWheelDelta(frameWheelDelta)\n }\n\n function handleMouseLeave(): void {\n setButtons(new Set())\n }\n\n function handleContextMenu(_e: Event): void {\n // Prevent context menu in game contexts if needed\n // e.preventDefault()\n }\n\n // Add event listeners\n const eventTarget = canvas || target\n eventTarget.addEventListener('mousemove', handleMouseMove)\n eventTarget.addEventListener('mousedown', handleMouseDown)\n eventTarget.addEventListener('mouseup', handleMouseUp)\n eventTarget.addEventListener('wheel', handleWheel)\n eventTarget.addEventListener('mouseleave', handleMouseLeave)\n eventTarget.addEventListener('contextmenu', handleContextMenu)\n\n if (target !== window) {\n window.addEventListener('mouseup', handleMouseUp)\n }\n\n return {\n get position() {\n return position\n },\n\n get delta() {\n return delta\n },\n\n get wheelDelta() {\n return wheelDelta\n },\n\n isPressed(button: number): boolean {\n return buttons().has(button)\n },\n\n isLeftPressed(): boolean {\n return buttons().has(0)\n },\n\n isRightPressed(): boolean {\n return buttons().has(2)\n },\n\n isMiddlePressed(): boolean {\n return buttons().has(1)\n },\n\n clearFrameState(): void {\n frameDeltaX = 0\n frameDeltaY = 0\n frameWheelDelta = 0\n setDelta({ x: 0, y: 0 })\n setWheelDelta(0)\n },\n\n dispose(): void {\n eventTarget.removeEventListener('mousemove', handleMouseMove)\n eventTarget.removeEventListener('mousedown', handleMouseDown)\n eventTarget.removeEventListener('mouseup', handleMouseUp)\n eventTarget.removeEventListener('wheel', handleWheel)\n eventTarget.removeEventListener('mouseleave', handleMouseLeave)\n eventTarget.removeEventListener('contextmenu', handleContextMenu)\n\n if (target !== window) {\n window.removeEventListener('mouseup', handleMouseUp)\n }\n },\n }\n}\n\n/** Mouse button constants */\nexport const MouseButton = {\n Left: 0,\n Middle: 1,\n Right: 2,\n} as const\n"]}
1
+ {"version":3,"sources":["../src/interactive/loop.ts","../src/interactive/keyboard.ts","../src/interactive/mouse.ts"],"names":["loop","callbacks","fixedFps","onUpdate","onFixedUpdate","onRender","fixedDelta","maxDelta","running","lastTime","accumulator","fps","frameCount","fpsTime","rafId","currentTime","delta","alpha","Keys","keyboard","target","pressedKeys","setPressedKeys","state","justPressedKeys","setJustPressedKeys","justReleasedKeys","setJustReleasedKeys","handleKeyDown","e","key","currentPressed","newPressed","currentJustPressed","newJustPressed","handleKeyUp","currentJustReleased","newJustReleased","MouseButton","mouse","options","canvasGetter","position","setPosition","setDelta","wheelDelta","setWheelDelta","buttons","setButtons","lastX","lastY","handleMouseMove","me","canvas","x","y","rect","handleMouseDown","button","currentButtons","newButtons","handleMouseUp","handleWheel","currentPosition","currentDelta","currentWheelDelta"],"mappings":"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","file":"interactive.js","sourcesContent":["export interface LoopCallbacks {\n fixedFps?: number\n onUpdate?: (delta: number) => void\n onFixedUpdate?: (fixedDelta: number) => void\n onRender?: (alpha: number) => void\n}\n\nexport interface Loop {\n start: () => void\n stop: () => void\n isRunning: () => boolean\n getFps: () => number\n}\n\nexport function loop(callbacks: LoopCallbacks): Loop {\n const { fixedFps = 60, onUpdate, onFixedUpdate, onRender } = callbacks\n\n const fixedDelta = 1 / fixedFps\n const maxDelta = 0.25 // Cap delta at 250ms to prevent spiral of death\n\n let running = false\n let lastTime = 0\n let accumulator = 0\n let fps = 0\n let frameCount = 0\n let fpsTime = 0\n let rafId: number | null = null\n\n function loop(currentTime: number) {\n if (!running) return\n\n // Calculate delta in seconds\n const delta = Math.min((currentTime - lastTime) / 1000, maxDelta)\n lastTime = currentTime\n\n // Variable timestep update\n if (onUpdate) {\n onUpdate(delta)\n }\n\n // Fixed timestep update\n if (onFixedUpdate) {\n accumulator += delta\n\n while (accumulator >= fixedDelta) {\n onFixedUpdate(fixedDelta)\n accumulator -= fixedDelta\n }\n }\n\n // Render with interpolation alpha\n if (onRender) {\n const alpha = accumulator / fixedDelta\n onRender(alpha)\n }\n\n // FPS calculation\n frameCount++\n if (currentTime - fpsTime >= 1000) {\n fps = frameCount\n frameCount = 0\n fpsTime = currentTime\n }\n\n rafId = requestAnimationFrame(loop)\n }\n\n return {\n start: () => {\n if (running) return\n running = true\n lastTime = performance.now()\n accumulator = 0\n rafId = requestAnimationFrame(loop)\n },\n\n stop: () => {\n running = false\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n rafId = null\n }\n },\n\n isRunning: () => running,\n\n getFps: () => fps\n }\n}\n","import { state } from '../core/state'\n\nexport enum Keys {\n // Arrow keys\n ArrowUp = 'ArrowUp',\n ArrowDown = 'ArrowDown',\n ArrowLeft = 'ArrowLeft',\n ArrowRight = 'ArrowRight',\n\n // WASD\n KeyW = 'KeyW',\n KeyA = 'KeyA',\n KeyS = 'KeyS',\n KeyD = 'KeyD',\n\n // Common keys\n Space = 'Space',\n Enter = 'Enter',\n Escape = 'Escape',\n Tab = 'Tab',\n\n // Modifiers\n ShiftLeft = 'ShiftLeft',\n ShiftRight = 'ShiftRight',\n ControlLeft = 'ControlLeft',\n ControlRight = 'ControlRight',\n AltLeft = 'AltLeft',\n AltRight = 'AltRight',\n\n // Numbers\n Digit0 = 'Digit0',\n Digit1 = 'Digit1',\n Digit2 = 'Digit2',\n Digit3 = 'Digit3',\n Digit4 = 'Digit4',\n Digit5 = 'Digit5',\n Digit6 = 'Digit6',\n Digit7 = 'Digit7',\n Digit8 = 'Digit8',\n Digit9 = 'Digit9',\n\n // Letters (additional common ones)\n KeyE = 'KeyE',\n KeyQ = 'KeyQ',\n KeyR = 'KeyR',\n KeyF = 'KeyF',\n}\n\nexport interface KeyboardState {\n isPressed: (key: string) => boolean\n isJustPressed: (key: string) => boolean\n isJustReleased: (key: string) => boolean\n getPressedKeys: () => string[]\n clearFrameState: () => void\n dispose: () => void\n}\n\nexport function keyboard(target: EventTarget = window): KeyboardState {\n const [pressedKeys, setPressedKeys] = state<Set<string>>(new Set<string>(), { key: ['keyboard', 'pressed'] })\n const [justPressedKeys, setJustPressedKeys] = state<Set<string>>(new Set<string>(), { key: ['keyboard', 'justPressed'] })\n const [justReleasedKeys, setJustReleasedKeys] = state<Set<string>>(new Set<string>(), { key: ['keyboard', 'justReleased'] })\n\n const handleKeyDown = (e: Event) => {\n const key = (e as KeyboardEvent).code\n const currentPressed = pressedKeys as Set<string>\n\n if (!currentPressed.has(key)) {\n const newPressed = new Set(currentPressed)\n newPressed.add(key)\n setPressedKeys(newPressed)\n\n const currentJustPressed = justPressedKeys as Set<string>\n const newJustPressed = new Set(currentJustPressed)\n newJustPressed.add(key)\n setJustPressedKeys(newJustPressed)\n }\n }\n\n const handleKeyUp = (e: Event) => {\n const key = (e as KeyboardEvent).code\n const currentPressed = pressedKeys as Set<string>\n\n const newPressed = new Set(currentPressed)\n newPressed.delete(key)\n setPressedKeys(newPressed)\n\n const currentJustReleased = justReleasedKeys as Set<string>\n const newJustReleased = new Set(currentJustReleased)\n newJustReleased.add(key)\n setJustReleasedKeys(newJustReleased)\n }\n\n target.addEventListener('keydown', handleKeyDown)\n target.addEventListener('keyup', handleKeyUp)\n\n return {\n isPressed: (key: string) => {\n const current = pressedKeys as Set<string>\n return current?.has(key) || false\n },\n\n isJustPressed: (key: string) => {\n const current = justPressedKeys as Set<string>\n return current?.has(key) || false\n },\n\n isJustReleased: (key: string) => {\n const current = justReleasedKeys as Set<string>\n return current?.has(key) || false\n },\n\n getPressedKeys: () => {\n const current = pressedKeys as Set<string>\n return Array.from(current || [])\n },\n\n clearFrameState: () => {\n setJustPressedKeys(new Set<string>())\n setJustReleasedKeys(new Set<string>())\n },\n\n dispose: () => {\n target.removeEventListener('keydown', handleKeyDown)\n target.removeEventListener('keyup', handleKeyUp)\n }\n }\n}\n","import { state } from '../core/state'\n\nexport enum MouseButton {\n Left = 0,\n Middle = 1,\n Right = 2\n}\n\nexport interface MouseOptions {\n canvas?: HTMLCanvasElement | (() => HTMLCanvasElement | undefined)\n target?: EventTarget\n}\n\nexport interface MouseState {\n x: number | null\n y: number | null\n deltaX: number\n deltaY: number\n wheelDelta: number\n isPressed: (button: MouseButton) => boolean\n isLeftPressed: () => boolean\n isRightPressed: () => boolean\n isMiddlePressed: () => boolean\n clearFrameState: () => void\n dispose: () => void\n}\n\nexport function mouse(options: MouseOptions = {}): MouseState {\n const target = options.target || window\n const canvasGetter = typeof options.canvas === 'function' ? options.canvas : () => options.canvas as HTMLCanvasElement | undefined\n\n const [position, setPosition] = state({ x: 0, y: 0 }, { key: ['mouse', 'position'] })\n const [delta, setDelta] = state({ x: 0, y: 0 }, { key: ['mouse', 'delta'] })\n const [wheelDelta, setWheelDelta] = state(0, { key: ['mouse', 'wheel'] })\n const [buttons, setButtons] = state<Set<number>>(new Set<number>(), { key: ['mouse', 'buttons'] })\n\n let lastX = 0\n let lastY = 0\n\n const handleMouseMove = (e: Event) => {\n const me = e as MouseEvent\n const canvas = canvasGetter()\n\n let x = me.clientX\n let y = me.clientY\n\n // If canvas is provided, calculate position relative to canvas\n if (canvas) {\n const rect = canvas.getBoundingClientRect()\n x = me.clientX - rect.left\n y = me.clientY - rect.top\n }\n\n setPosition({ x, y })\n setDelta({ x: x - lastX, y: y - lastY })\n lastX = x\n lastY = y\n }\n\n const handleMouseDown = (e: Event) => {\n const button = (e as MouseEvent).button\n const currentButtons = buttons as Set<number>\n const newButtons = new Set(currentButtons)\n newButtons.add(button)\n setButtons(newButtons)\n }\n\n const handleMouseUp = (e: Event) => {\n const button = (e as MouseEvent).button\n const currentButtons = buttons as Set<number>\n const newButtons = new Set(currentButtons)\n newButtons.delete(button)\n setButtons(newButtons)\n }\n\n const handleWheel = (e: Event) => {\n const we = e as WheelEvent\n setWheelDelta(we.deltaY)\n }\n\n target.addEventListener('mousemove', handleMouseMove)\n target.addEventListener('mousedown', handleMouseDown)\n target.addEventListener('mouseup', handleMouseUp)\n target.addEventListener('wheel', handleWheel)\n\n const currentButtons = buttons as Set<number>\n const currentPosition = position as { x: number; y: number }\n const currentDelta = delta as { x: number; y: number }\n const currentWheelDelta = wheelDelta as number\n\n return {\n get x() { return currentPosition.x },\n get y() { return currentPosition.y },\n get deltaX() { return currentDelta.x },\n get deltaY() { return currentDelta.y },\n get wheelDelta() { return currentWheelDelta },\n\n isPressed: (button: MouseButton) => currentButtons?.has(button) || false,\n\n isLeftPressed: () => currentButtons?.has(MouseButton.Left) || false,\n\n isRightPressed: () => currentButtons?.has(MouseButton.Right) || false,\n\n isMiddlePressed: () => currentButtons?.has(MouseButton.Middle) || false,\n\n clearFrameState: () => {\n setDelta({ x: 0, y: 0 })\n setWheelDelta(0)\n },\n\n dispose: () => {\n target.removeEventListener('mousemove', handleMouseMove)\n target.removeEventListener('mousedown', handleMouseDown)\n target.removeEventListener('mouseup', handleMouseUp)\n target.removeEventListener('wheel', handleWheel)\n }\n }\n}\n"]}
@@ -1,2 +1,2 @@
1
- import {k}from'./chunk-BBNYMXE7.mjs';import'./chunk-FDMJHFN7.mjs';import'./chunk-HB5VPQTB.mjs';import'./chunk-ECYYIQEX.mjs';function K(c={}){let{fixedFps:i=60,onUpdate:p,onFixedUpdate:g,onRender:m}=c,l=1/i,r=false,f,y=0,n=0,w=0,e=0,t=0,o=true;function d(b){if(!r)return;f=requestAnimationFrame(d);let L=b/1e3;if(o){y=L,o=false;return}let E=Math.min(L-y,.25);if(y=L,e++,t+=E,t>=1&&(w=e,e=0,t-=1),p&&p(E),g)for(n+=E;n>=l;)g(l),n-=l;if(m){let S=g?n/l:1;m(S);}}return {start(){r||(r=true,o=true,n=0,f=requestAnimationFrame(d));},stop(){r=false,f!==void 0&&(cancelAnimationFrame(f),f=void 0);},isRunning(){return r},getFps(){return w}}}function V(c=window){let i=new Map,[p,g]=k(false),m=new Set,l=new Set;function r(e){return e.toLowerCase()}function f(e){let t=i.get(e);return t||(t=k(false),i.set(e,t)),t}function y(e){let t=r(e.code),[o,d]=f(t);o()||(d(true),m.add(t),g(true));}function n(e){let t=r(e.code),[o,d]=f(t);if(o()){d(false),l.add(t);let b=false;for(let[L]of i.values())if(L()){b=true;break}g(b);}}function w(){for(let[,e]of i.values())e(false);g(false),m.clear(),l.clear();}return c.addEventListener("keydown",y),c.addEventListener("keyup",n),window.addEventListener("blur",w),{isPressed(e){let t=i.get(r(e));return t?t[0]():false},isJustPressed(e){return m.has(r(e))},isJustReleased(e){return l.has(r(e))},getPressedKeys(){let e=[];for(let[t,[o]]of i.entries())o()&&e.push(t);return e},getPressed(){return this.getPressedKeys()},get keys(){let[e]=k(()=>{let t=new Set;for(let[o,[d]]of i.entries())d()&&t.add(o);return t});return e},clearFrameState(){m.clear(),l.clear();},dispose(){c.removeEventListener("keydown",y),c.removeEventListener("keyup",n),c===window&&c.removeEventListener("blur",w);}}}var F={ArrowUp:"arrowup",ArrowDown:"arrowdown",ArrowLeft:"arrowleft",ArrowRight:"arrowright",KeyW:"keyw",KeyA:"keya",KeyS:"keys",KeyD:"keyd",Space:"space",Enter:"enter",Escape:"escape",ShiftLeft:"shiftleft",ShiftRight:"shiftright",ControlLeft:"controlleft",ControlRight:"controlright",AltLeft:"altleft",AltRight:"altright",Tab:"tab",Digit0:"digit0",Digit1:"digit1",Digit2:"digit2",Digit3:"digit3",Digit4:"digit4",Digit5:"digit5",Digit6:"digit6",Digit7:"digit7",Digit8:"digit8",Digit9:"digit9"};function R(c={}){let{target:i=window,canvas:p}=c,[g,m]=k({x:0,y:0}),[l,r]=k({x:0,y:0}),[f,y]=k(0),[n,w]=k(new Set),e=0,t=0,o=0,d=0,b=0;function L(s){if(p){let v=p.getBoundingClientRect(),a=p.width/v.width,P=p.height/v.height;return {x:(s.clientX-v.left)*a,y:(s.clientY-v.top)*P}}return {x:s.clientX,y:s.clientY}}function E(s){let a=L(s);o+=a.x-e,d+=a.y-t,e=a.x,t=a.y,m(a),r({x:o,y:d});}function S(s){let v=s,a=new Set(n());a.add(v.button),w(a);}function x(s){let v=s,a=new Set(n());a.delete(v.button),w(a);}function M(s){b+=Math.sign(s.deltaY),y(b);}function k$1(){w(new Set);}function D(s){}let u=p||i;return u.addEventListener("mousemove",E),u.addEventListener("mousedown",S),u.addEventListener("mouseup",x),u.addEventListener("wheel",M),u.addEventListener("mouseleave",k$1),u.addEventListener("contextmenu",D),i!==window&&window.addEventListener("mouseup",x),{get position(){return g},get delta(){return l},get wheelDelta(){return f},isPressed(s){return n().has(s)},isLeftPressed(){return n().has(0)},isRightPressed(){return n().has(2)},isMiddlePressed(){return n().has(1)},clearFrameState(){o=0,d=0,b=0,r({x:0,y:0}),y(0);},dispose(){u.removeEventListener("mousemove",E),u.removeEventListener("mousedown",S),u.removeEventListener("mouseup",x),u.removeEventListener("wheel",M),u.removeEventListener("mouseleave",k$1),u.removeEventListener("contextmenu",D),i!==window&&window.removeEventListener("mouseup",x);}}}var A={Left:0,Middle:1,Right:2};export{F as Keys,A as MouseButton,K as createLoop,V as keyboard,R as mouse};//# sourceMappingURL=interactive.mjs.map
1
+ import {a}from'./chunk-7DXFHPWZ.mjs';import'./chunk-CPJRQL2C.mjs';import'./chunk-44RZHCII.mjs';function F(a){let{fixedFps:n=60,onUpdate:b,onFixedUpdate:r,onRender:w}=a,g=1/n,S=.25,l=false,m=0,t=0,s=0,i=0,u=0,o=null;function d(h){if(!l)return;let E=Math.min((h-m)/1e3,S);if(m=h,b&&b(E),r)for(t+=E;t>=g;)r(g),t-=g;if(w){let y=t/g;w(y);}i++,h-u>=1e3&&(s=i,i=0,u=h),o=requestAnimationFrame(d);}return {start:()=>{l||(l=true,m=performance.now(),t=0,o=requestAnimationFrame(d));},stop:()=>{l=false,o!==null&&(cancelAnimationFrame(o),o=null);},isRunning:()=>l,getFps:()=>s}}var k=(e=>(e.ArrowUp="ArrowUp",e.ArrowDown="ArrowDown",e.ArrowLeft="ArrowLeft",e.ArrowRight="ArrowRight",e.KeyW="KeyW",e.KeyA="KeyA",e.KeyS="KeyS",e.KeyD="KeyD",e.Space="Space",e.Enter="Enter",e.Escape="Escape",e.Tab="Tab",e.ShiftLeft="ShiftLeft",e.ShiftRight="ShiftRight",e.ControlLeft="ControlLeft",e.ControlRight="ControlRight",e.AltLeft="AltLeft",e.AltRight="AltRight",e.Digit0="Digit0",e.Digit1="Digit1",e.Digit2="Digit2",e.Digit3="Digit3",e.Digit4="Digit4",e.Digit5="Digit5",e.Digit6="Digit6",e.Digit7="Digit7",e.Digit8="Digit8",e.Digit9="Digit9",e.KeyE="KeyE",e.KeyQ="KeyQ",e.KeyR="KeyR",e.KeyF="KeyF",e))(k||{});function C(a$1=window){let[n,b]=a(new Set,{key:["keyboard","pressed"]}),[r,w]=a(new Set,{key:["keyboard","justPressed"]}),[g,S]=a(new Set,{key:["keyboard","justReleased"]}),l=t=>{let s=t.code,i=n;if(!i.has(s)){let u=new Set(i);u.add(s),b(u);let o=r,d=new Set(o);d.add(s),w(d);}},m=t=>{let s=t.code,i=n,u=new Set(i);u.delete(s),b(u);let o=g,d=new Set(o);d.add(s),S(d);};return a$1.addEventListener("keydown",l),a$1.addEventListener("keyup",m),{isPressed:t=>n?.has(t)||false,isJustPressed:t=>r?.has(t)||false,isJustReleased:t=>g?.has(t)||false,getPressedKeys:()=>Array.from(n||[]),clearFrameState:()=>{w(new Set),S(new Set);},dispose:()=>{a$1.removeEventListener("keydown",l),a$1.removeEventListener("keyup",m);}}}var M=(r=>(r[r.Left=0]="Left",r[r.Middle=1]="Middle",r[r.Right=2]="Right",r))(M||{});function J(a$1={}){let n=a$1.target||window,b=typeof a$1.canvas=="function"?a$1.canvas:()=>a$1.canvas,[r,w]=a({x:0,y:0},{key:["mouse","position"]}),[g,S]=a({x:0,y:0},{key:["mouse","delta"]}),[l,m]=a(0,{key:["mouse","wheel"]}),[t,s]=a(new Set,{key:["mouse","buttons"]}),i=0,u=0,o=p=>{let f=p,D=b(),c=f.clientX,L=f.clientY;if(D){let R=D.getBoundingClientRect();c=f.clientX-R.left,L=f.clientY-R.top;}w({x:c,y:L}),S({x:c-i,y:L-u}),i=c,u=L;},d=p=>{let f=p.button,D=t,c=new Set(D);c.add(f),s(c);},h=p=>{let f=p.button,D=t,c=new Set(D);c.delete(f),s(c);},E=p=>{m(p.deltaY);};n.addEventListener("mousemove",o),n.addEventListener("mousedown",d),n.addEventListener("mouseup",h),n.addEventListener("wheel",E);let y=t,x=r,P=g,A=l;return {get x(){return x.x},get y(){return x.y},get deltaX(){return P.x},get deltaY(){return P.y},get wheelDelta(){return A},isPressed:p=>y?.has(p)||false,isLeftPressed:()=>y?.has(0)||false,isRightPressed:()=>y?.has(2)||false,isMiddlePressed:()=>y?.has(1)||false,clearFrameState:()=>{S({x:0,y:0}),m(0);},dispose:()=>{n.removeEventListener("mousemove",o),n.removeEventListener("mousedown",d),n.removeEventListener("mouseup",h),n.removeEventListener("wheel",E);}}}export{k as Keys,M as MouseButton,C as keyboard,F as loop,J as mouse};//# sourceMappingURL=interactive.mjs.map
2
2
  //# sourceMappingURL=interactive.mjs.map