flexium 0.8.14

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 (154) hide show
  1. package/README.md +219 -0
  2. package/dist/DrawText-CeXBL8Ev.d.ts +309 -0
  3. package/dist/DrawText-JB58mpQT.d.cts +309 -0
  4. package/dist/Motion-BrOAJzgH.d.cts +87 -0
  5. package/dist/Motion-BrOAJzgH.d.ts +87 -0
  6. package/dist/advanced.d.cts +30 -0
  7. package/dist/advanced.d.ts +30 -0
  8. package/dist/advanced.js +2 -0
  9. package/dist/advanced.js.map +1 -0
  10. package/dist/advanced.mjs +2 -0
  11. package/dist/advanced.mjs.map +1 -0
  12. package/dist/canvas.d.cts +22 -0
  13. package/dist/canvas.d.ts +22 -0
  14. package/dist/canvas.js +2 -0
  15. package/dist/canvas.js.map +1 -0
  16. package/dist/canvas.mjs +2 -0
  17. package/dist/canvas.mjs.map +1 -0
  18. package/dist/chunk-2MVKTSFR.mjs +3 -0
  19. package/dist/chunk-2MVKTSFR.mjs.map +1 -0
  20. package/dist/chunk-2U4DW375.mjs +2 -0
  21. package/dist/chunk-2U4DW375.mjs.map +1 -0
  22. package/dist/chunk-3P6DMEGB.js +2 -0
  23. package/dist/chunk-3P6DMEGB.js.map +1 -0
  24. package/dist/chunk-5S3ZQ2LB.mjs +3 -0
  25. package/dist/chunk-5S3ZQ2LB.mjs.map +1 -0
  26. package/dist/chunk-CNY6FPKJ.js +2 -0
  27. package/dist/chunk-CNY6FPKJ.js.map +1 -0
  28. package/dist/chunk-CZYIK6FD.mjs +2 -0
  29. package/dist/chunk-CZYIK6FD.mjs.map +1 -0
  30. package/dist/chunk-DOGIWSDA.js +2 -0
  31. package/dist/chunk-DOGIWSDA.js.map +1 -0
  32. package/dist/chunk-EX2GURH5.mjs +3 -0
  33. package/dist/chunk-EX2GURH5.mjs.map +1 -0
  34. package/dist/chunk-GDBJ322I.js +2 -0
  35. package/dist/chunk-GDBJ322I.js.map +1 -0
  36. package/dist/chunk-I7UCVARB.js +2 -0
  37. package/dist/chunk-I7UCVARB.js.map +1 -0
  38. package/dist/chunk-KNF5ERPK.mjs +2 -0
  39. package/dist/chunk-KNF5ERPK.mjs.map +1 -0
  40. package/dist/chunk-MLZTCKTH.mjs +2 -0
  41. package/dist/chunk-MLZTCKTH.mjs.map +1 -0
  42. package/dist/chunk-OPAQ4R4M.mjs +2 -0
  43. package/dist/chunk-OPAQ4R4M.mjs.map +1 -0
  44. package/dist/chunk-Q7IWDVJ4.js +2 -0
  45. package/dist/chunk-Q7IWDVJ4.js.map +1 -0
  46. package/dist/chunk-R5CS7UZG.mjs +2 -0
  47. package/dist/chunk-R5CS7UZG.mjs.map +1 -0
  48. package/dist/chunk-REETNY2Z.js +3 -0
  49. package/dist/chunk-REETNY2Z.js.map +1 -0
  50. package/dist/chunk-ROYFUJN5.js +3 -0
  51. package/dist/chunk-ROYFUJN5.js.map +1 -0
  52. package/dist/chunk-U6C6VDVZ.js +2 -0
  53. package/dist/chunk-U6C6VDVZ.js.map +1 -0
  54. package/dist/chunk-V4K6WOXN.js +3 -0
  55. package/dist/chunk-V4K6WOXN.js.map +1 -0
  56. package/dist/chunk-WQFQO5LK.js +2 -0
  57. package/dist/chunk-WQFQO5LK.js.map +1 -0
  58. package/dist/chunk-WVEJT7HD.mjs +2 -0
  59. package/dist/chunk-WVEJT7HD.mjs.map +1 -0
  60. package/dist/chunk-ZNPYN2TZ.mjs +2 -0
  61. package/dist/chunk-ZNPYN2TZ.mjs.map +1 -0
  62. package/dist/core.d.cts +24 -0
  63. package/dist/core.d.ts +24 -0
  64. package/dist/core.js +2 -0
  65. package/dist/core.js.map +1 -0
  66. package/dist/core.mjs +2 -0
  67. package/dist/core.mjs.map +1 -0
  68. package/dist/dom.d.cts +36 -0
  69. package/dist/dom.d.ts +36 -0
  70. package/dist/dom.js +2 -0
  71. package/dist/dom.js.map +1 -0
  72. package/dist/dom.mjs +2 -0
  73. package/dist/dom.mjs.map +1 -0
  74. package/dist/index.d.cts +26 -0
  75. package/dist/index.d.ts +26 -0
  76. package/dist/index.js +2 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/index.mjs +2 -0
  79. package/dist/index.mjs.map +1 -0
  80. package/dist/interactive.d.cts +161 -0
  81. package/dist/interactive.d.ts +161 -0
  82. package/dist/interactive.js +2 -0
  83. package/dist/interactive.js.map +1 -0
  84. package/dist/interactive.mjs +2 -0
  85. package/dist/interactive.mjs.map +1 -0
  86. package/dist/jsx-dev-runtime.d.cts +2 -0
  87. package/dist/jsx-dev-runtime.d.ts +2 -0
  88. package/dist/jsx-dev-runtime.js +2 -0
  89. package/dist/jsx-dev-runtime.js.map +1 -0
  90. package/dist/jsx-dev-runtime.mjs +2 -0
  91. package/dist/jsx-dev-runtime.mjs.map +1 -0
  92. package/dist/jsx-runtime.d.cts +78 -0
  93. package/dist/jsx-runtime.d.ts +78 -0
  94. package/dist/jsx-runtime.js +2 -0
  95. package/dist/jsx-runtime.js.map +1 -0
  96. package/dist/jsx-runtime.mjs +2 -0
  97. package/dist/jsx-runtime.mjs.map +1 -0
  98. package/dist/metafile-cjs.json +1 -0
  99. package/dist/metafile-esm.json +1 -0
  100. package/dist/portal-BpcIlK9y.d.cts +206 -0
  101. package/dist/portal-DBwz7gD0.d.ts +206 -0
  102. package/dist/primitives/layout.d.cts +295 -0
  103. package/dist/primitives/layout.d.ts +295 -0
  104. package/dist/primitives/layout.js +2 -0
  105. package/dist/primitives/layout.js.map +1 -0
  106. package/dist/primitives/layout.mjs +2 -0
  107. package/dist/primitives/layout.mjs.map +1 -0
  108. package/dist/primitives/motion.d.cts +230 -0
  109. package/dist/primitives/motion.d.ts +230 -0
  110. package/dist/primitives/motion.js +2 -0
  111. package/dist/primitives/motion.js.map +1 -0
  112. package/dist/primitives/motion.mjs +2 -0
  113. package/dist/primitives/motion.mjs.map +1 -0
  114. package/dist/primitives/ui.d.cts +81 -0
  115. package/dist/primitives/ui.d.ts +81 -0
  116. package/dist/primitives/ui.js +2 -0
  117. package/dist/primitives/ui.js.map +1 -0
  118. package/dist/primitives/ui.mjs +2 -0
  119. package/dist/primitives/ui.mjs.map +1 -0
  120. package/dist/primitives.d.cts +92 -0
  121. package/dist/primitives.d.ts +92 -0
  122. package/dist/primitives.js +2 -0
  123. package/dist/primitives.js.map +1 -0
  124. package/dist/primitives.mjs +2 -0
  125. package/dist/primitives.mjs.map +1 -0
  126. package/dist/renderer-DSLb-FGg.d.cts +135 -0
  127. package/dist/renderer-DSLb-FGg.d.ts +135 -0
  128. package/dist/router.d.cts +126 -0
  129. package/dist/router.d.ts +126 -0
  130. package/dist/router.js +2 -0
  131. package/dist/router.js.map +1 -0
  132. package/dist/router.mjs +2 -0
  133. package/dist/router.mjs.map +1 -0
  134. package/dist/server.d.cts +3 -0
  135. package/dist/server.d.ts +3 -0
  136. package/dist/server.js +2 -0
  137. package/dist/server.js.map +1 -0
  138. package/dist/server.mjs +2 -0
  139. package/dist/server.mjs.map +1 -0
  140. package/dist/signal-PWBIM6JV.mjs +2 -0
  141. package/dist/signal-PWBIM6JV.mjs.map +1 -0
  142. package/dist/signal-XZXQ4VYQ.js +2 -0
  143. package/dist/signal-XZXQ4VYQ.js.map +1 -0
  144. package/dist/signal-mNtlF8-v.d.cts +158 -0
  145. package/dist/signal-mNtlF8-v.d.ts +158 -0
  146. package/dist/state-kK9sQh9s.d.cts +73 -0
  147. package/dist/state-kK9sQh9s.d.ts +73 -0
  148. package/dist/test-exports.d.cts +17 -0
  149. package/dist/test-exports.d.ts +17 -0
  150. package/dist/test-exports.js +2 -0
  151. package/dist/test-exports.js.map +1 -0
  152. package/dist/test-exports.mjs +2 -0
  153. package/dist/test-exports.mjs.map +1 -0
  154. package/package.json +173 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Flexium - Next-generation UI/UX library
3
+ *
4
+ * Please use explicit imports from submodules:
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * // Core reactivity
9
+ * import { state, effect, batch } from 'flexium/core'
10
+ *
11
+ * // DOM rendering
12
+ * import { render, createRoot, Portal } from 'flexium/dom'
13
+ *
14
+ * // Canvas rendering
15
+ * import { Canvas, Rect, Circle } from 'flexium/canvas'
16
+ *
17
+ * // Cross-platform primitives
18
+ * import { Row, Column, Text } from 'flexium/primitives'
19
+ *
20
+ * // Router
21
+ * import { Router, Route, Link } from 'flexium/router'
22
+ * ```
23
+ */
24
+ declare const VERSION = "0.8.14";
25
+
26
+ export { VERSION };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Flexium - Next-generation UI/UX library
3
+ *
4
+ * Please use explicit imports from submodules:
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * // Core reactivity
9
+ * import { state, effect, batch } from 'flexium/core'
10
+ *
11
+ * // DOM rendering
12
+ * import { render, createRoot, Portal } from 'flexium/dom'
13
+ *
14
+ * // Canvas rendering
15
+ * import { Canvas, Rect, Circle } from 'flexium/canvas'
16
+ *
17
+ * // Cross-platform primitives
18
+ * import { Row, Column, Text } from 'flexium/primitives'
19
+ *
20
+ * // Router
21
+ * import { Router, Route, Link } from 'flexium/router'
22
+ * ```
23
+ */
24
+ declare const VERSION = "0.8.14";
25
+
26
+ export { VERSION };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var o="0.8.14";exports.VERSION=o;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["VERSION"],"mappings":"aAwBO,IAAMA,CAAAA,CAAU","file":"index.js","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, batch } 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.8.14'\n\n// Intentionally empty - use explicit submodule imports\n// flexium/core, flexium/dom, flexium/canvas, flexium/primitives, flexium/router\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ var o="0.8.14";export{o as VERSION};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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, batch } 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.8.14'\n\n// Intentionally empty - use explicit submodule imports\n// flexium/core, flexium/dom, flexium/canvas, flexium/primitives, flexium/router\n"]}
@@ -0,0 +1,161 @@
1
+ import { S as Signal } from './signal-mNtlF8-v.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) */
8
+ fixedFps?: number;
9
+ /** Called every frame with delta time in seconds */
10
+ onUpdate?: (delta: number) => void;
11
+ /** Called at fixed intervals (for physics) */
12
+ onFixedUpdate?: (fixedDelta: number) => void;
13
+ /** Called every frame for rendering */
14
+ onRender?: (alpha: number) => void;
15
+ }
16
+ 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;
25
+ }
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
+ */
37
+
38
+ interface KeyboardState {
39
+ /** Check if a key is currently pressed */
40
+ isPressed(key: string): boolean;
41
+ /** Check if a key was just pressed this frame */
42
+ isJustPressed(key: string): boolean;
43
+ /** Check if a key was just released this frame */
44
+ isJustReleased(key: string): boolean;
45
+ /** Get all currently pressed keys */
46
+ getPressedKeys(): string[];
47
+ /** Signal that updates when any key state changes */
48
+ readonly keys: Signal<Set<string>>;
49
+ /** Clear just pressed/released state (call at end of frame) */
50
+ clearFrameState(): void;
51
+ /** Cleanup event listeners */
52
+ dispose(): void;
53
+ }
54
+ /**
55
+ * Create a keyboard input handler with reactive state
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * const kb = keyboard()
60
+ *
61
+ * effect(() => {
62
+ * if (kb.isPressed(Keys.ArrowUp)) {
63
+ * player.y -= speed
64
+ * }
65
+ * })
66
+ * ```
67
+ */
68
+ declare function keyboard(target?: EventTarget): KeyboardState;
69
+ /** Common key codes for convenience */
70
+ declare const Keys: {
71
+ readonly ArrowUp: "arrowup";
72
+ readonly ArrowDown: "arrowdown";
73
+ readonly ArrowLeft: "arrowleft";
74
+ readonly ArrowRight: "arrowright";
75
+ readonly KeyW: "keyw";
76
+ readonly KeyA: "keya";
77
+ readonly KeyS: "keys";
78
+ readonly KeyD: "keyd";
79
+ readonly Space: "space";
80
+ readonly Enter: "enter";
81
+ readonly Escape: "escape";
82
+ readonly ShiftLeft: "shiftleft";
83
+ readonly ShiftRight: "shiftright";
84
+ readonly ControlLeft: "controlleft";
85
+ readonly ControlRight: "controlright";
86
+ readonly AltLeft: "altleft";
87
+ readonly AltRight: "altright";
88
+ readonly Tab: "tab";
89
+ readonly Digit0: "digit0";
90
+ readonly Digit1: "digit1";
91
+ readonly Digit2: "digit2";
92
+ readonly Digit3: "digit3";
93
+ readonly Digit4: "digit4";
94
+ readonly Digit5: "digit5";
95
+ readonly Digit6: "digit6";
96
+ readonly Digit7: "digit7";
97
+ readonly Digit8: "digit8";
98
+ readonly Digit9: "digit9";
99
+ };
100
+
101
+ /**
102
+ * mouse - Reactive mouse input handler
103
+ *
104
+ * Creates a mouse input handler with reactive signals.
105
+ * Philosophy: No hooks, just factory functions that return signal-based state.
106
+ */
107
+
108
+ interface Vec2 {
109
+ x: number;
110
+ y: number;
111
+ }
112
+ interface MouseState {
113
+ /** Current mouse position relative to target */
114
+ readonly position: Signal<Vec2>;
115
+ /** Mouse position delta since last frame */
116
+ readonly delta: Signal<Vec2>;
117
+ /** Check if a mouse button is pressed (0=left, 1=middle, 2=right) */
118
+ isPressed(button: number): boolean;
119
+ /** Check if left mouse button is pressed */
120
+ isLeftPressed(): boolean;
121
+ /** Check if right mouse button is pressed */
122
+ isRightPressed(): boolean;
123
+ /** Check if middle mouse button is pressed */
124
+ isMiddlePressed(): boolean;
125
+ /** Wheel delta (positive = scroll down) */
126
+ readonly wheelDelta: Signal<number>;
127
+ /** Clear frame state (call at end of frame) */
128
+ clearFrameState(): void;
129
+ /** Cleanup event listeners */
130
+ dispose(): void;
131
+ }
132
+ interface MouseOptions {
133
+ /** Element to track mouse relative to (default: window) */
134
+ target?: EventTarget;
135
+ /** Canvas element for coordinate calculation (if different from target) */
136
+ canvas?: HTMLCanvasElement;
137
+ }
138
+ /**
139
+ * Create a mouse input handler with reactive state
140
+ *
141
+ * @example
142
+ * ```tsx
143
+ * const m = mouse()
144
+ *
145
+ * effect(() => {
146
+ * console.log('Mouse at:', m.position.value)
147
+ * if (m.isLeftPressed()) {
148
+ * draw(m.position.value)
149
+ * }
150
+ * })
151
+ * ```
152
+ */
153
+ declare function mouse(options?: MouseOptions): MouseState;
154
+ /** Mouse button constants */
155
+ declare const MouseButton: {
156
+ readonly Left: 0;
157
+ readonly Middle: 1;
158
+ readonly Right: 2;
159
+ };
160
+
161
+ export { type KeyboardState, Keys, type Loop, type LoopOptions, MouseButton, type MouseOptions, type MouseState, type Vec2, createLoop, keyboard, mouse };
@@ -0,0 +1,161 @@
1
+ import { S as Signal } from './signal-mNtlF8-v.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) */
8
+ fixedFps?: number;
9
+ /** Called every frame with delta time in seconds */
10
+ onUpdate?: (delta: number) => void;
11
+ /** Called at fixed intervals (for physics) */
12
+ onFixedUpdate?: (fixedDelta: number) => void;
13
+ /** Called every frame for rendering */
14
+ onRender?: (alpha: number) => void;
15
+ }
16
+ 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;
25
+ }
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
+ */
37
+
38
+ interface KeyboardState {
39
+ /** Check if a key is currently pressed */
40
+ isPressed(key: string): boolean;
41
+ /** Check if a key was just pressed this frame */
42
+ isJustPressed(key: string): boolean;
43
+ /** Check if a key was just released this frame */
44
+ isJustReleased(key: string): boolean;
45
+ /** Get all currently pressed keys */
46
+ getPressedKeys(): string[];
47
+ /** Signal that updates when any key state changes */
48
+ readonly keys: Signal<Set<string>>;
49
+ /** Clear just pressed/released state (call at end of frame) */
50
+ clearFrameState(): void;
51
+ /** Cleanup event listeners */
52
+ dispose(): void;
53
+ }
54
+ /**
55
+ * Create a keyboard input handler with reactive state
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * const kb = keyboard()
60
+ *
61
+ * effect(() => {
62
+ * if (kb.isPressed(Keys.ArrowUp)) {
63
+ * player.y -= speed
64
+ * }
65
+ * })
66
+ * ```
67
+ */
68
+ declare function keyboard(target?: EventTarget): KeyboardState;
69
+ /** Common key codes for convenience */
70
+ declare const Keys: {
71
+ readonly ArrowUp: "arrowup";
72
+ readonly ArrowDown: "arrowdown";
73
+ readonly ArrowLeft: "arrowleft";
74
+ readonly ArrowRight: "arrowright";
75
+ readonly KeyW: "keyw";
76
+ readonly KeyA: "keya";
77
+ readonly KeyS: "keys";
78
+ readonly KeyD: "keyd";
79
+ readonly Space: "space";
80
+ readonly Enter: "enter";
81
+ readonly Escape: "escape";
82
+ readonly ShiftLeft: "shiftleft";
83
+ readonly ShiftRight: "shiftright";
84
+ readonly ControlLeft: "controlleft";
85
+ readonly ControlRight: "controlright";
86
+ readonly AltLeft: "altleft";
87
+ readonly AltRight: "altright";
88
+ readonly Tab: "tab";
89
+ readonly Digit0: "digit0";
90
+ readonly Digit1: "digit1";
91
+ readonly Digit2: "digit2";
92
+ readonly Digit3: "digit3";
93
+ readonly Digit4: "digit4";
94
+ readonly Digit5: "digit5";
95
+ readonly Digit6: "digit6";
96
+ readonly Digit7: "digit7";
97
+ readonly Digit8: "digit8";
98
+ readonly Digit9: "digit9";
99
+ };
100
+
101
+ /**
102
+ * mouse - Reactive mouse input handler
103
+ *
104
+ * Creates a mouse input handler with reactive signals.
105
+ * Philosophy: No hooks, just factory functions that return signal-based state.
106
+ */
107
+
108
+ interface Vec2 {
109
+ x: number;
110
+ y: number;
111
+ }
112
+ interface MouseState {
113
+ /** Current mouse position relative to target */
114
+ readonly position: Signal<Vec2>;
115
+ /** Mouse position delta since last frame */
116
+ readonly delta: Signal<Vec2>;
117
+ /** Check if a mouse button is pressed (0=left, 1=middle, 2=right) */
118
+ isPressed(button: number): boolean;
119
+ /** Check if left mouse button is pressed */
120
+ isLeftPressed(): boolean;
121
+ /** Check if right mouse button is pressed */
122
+ isRightPressed(): boolean;
123
+ /** Check if middle mouse button is pressed */
124
+ isMiddlePressed(): boolean;
125
+ /** Wheel delta (positive = scroll down) */
126
+ readonly wheelDelta: Signal<number>;
127
+ /** Clear frame state (call at end of frame) */
128
+ clearFrameState(): void;
129
+ /** Cleanup event listeners */
130
+ dispose(): void;
131
+ }
132
+ interface MouseOptions {
133
+ /** Element to track mouse relative to (default: window) */
134
+ target?: EventTarget;
135
+ /** Canvas element for coordinate calculation (if different from target) */
136
+ canvas?: HTMLCanvasElement;
137
+ }
138
+ /**
139
+ * Create a mouse input handler with reactive state
140
+ *
141
+ * @example
142
+ * ```tsx
143
+ * const m = mouse()
144
+ *
145
+ * effect(() => {
146
+ * console.log('Mouse at:', m.position.value)
147
+ * if (m.isLeftPressed()) {
148
+ * draw(m.position.value)
149
+ * }
150
+ * })
151
+ * ```
152
+ */
153
+ declare function mouse(options?: MouseOptions): MouseState;
154
+ /** Mouse button constants */
155
+ declare const MouseButton: {
156
+ readonly Left: 0;
157
+ readonly Middle: 1;
158
+ readonly Right: 2;
159
+ };
160
+
161
+ export { type KeyboardState, Keys, type Loop, type LoopOptions, MouseButton, type MouseOptions, type MouseState, type Vec2, createLoop, keyboard, mouse };
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkROYFUJN5_js=require('./chunk-ROYFUJN5.js');function M(d={}){let{fixedFps:n=60,onUpdate:s,onFixedUpdate:v,onRender:l}=d,c=1/n,e=false,f,t=0,p=0,i=0,r=0,E=0,w=true;function L(y){if(!e)return;f=requestAnimationFrame(L);let h=y/1e3;if(w){t=h,w=false;return}let b=Math.min(h-t,.25);if(t=h,r++,E+=b,E>=1&&(i=r,r=0,E-=1),s&&s(b),v)for(p+=b;p>=c;)v(c),p-=c;if(l){let x=v?p/c:1;l(x);}}return {start(){e||(e=true,w=true,p=0,f=requestAnimationFrame(L));},stop(){e=false,f!==void 0&&(cancelAnimationFrame(f),f=void 0);},isRunning(){return e},getFps(){return i}}}function D(d=window){let n=chunkROYFUJN5_js.h(new Set),s=new Set,v=new Set;function l(t){return t.toLowerCase()}function c(t){let i=l(t.code);if(!n.value.has(i)){s.add(i);let r=new Set(n.value);r.add(i),n.value=r;}}function e(t){let i=l(t.code);if(n.value.has(i)){v.add(i);let r=new Set(n.value);r.delete(i),n.value=r;}}function f(){n.value=new Set,s.clear(),v.clear();}return d.addEventListener("keydown",c),d.addEventListener("keyup",e),d===window&&d.addEventListener("blur",f),{isPressed(t){return n.value.has(l(t))},isJustPressed(t){return s.has(l(t))},isJustReleased(t){return v.has(l(t))},getPressedKeys(){return Array.from(n.value)},get keys(){return n},clearFrameState(){s.clear(),v.clear();},dispose(){d.removeEventListener("keydown",c),d.removeEventListener("keyup",e),d===window&&d.removeEventListener("blur",f);}}}var k={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 K(d={}){let{target:n=window,canvas:s}=d,v=chunkROYFUJN5_js.h({x:0,y:0}),l=chunkROYFUJN5_js.h({x:0,y:0}),c=chunkROYFUJN5_js.h(0),e=chunkROYFUJN5_js.h(new Set),f=0,t=0,p=0,i=0,r=0;function E(o){if(s){let m=s.getBoundingClientRect(),a=s.width/m.width,S=s.height/m.height;return {x:(o.clientX-m.left)*a,y:(o.clientY-m.top)*S}}return {x:o.clientX,y:o.clientY}}function w(o){let a=E(o);p+=a.x-f,i+=a.y-t,f=a.x,t=a.y,v.value=a,l.value={x:p,y:i};}function L(o){let m=o,a=new Set(e.value);a.add(m.button),e.value=a;}function y(o){let m=o,a=new Set(e.value);a.delete(m.button),e.value=a;}function h(o){r+=Math.sign(o.deltaY),c.value=r;}function b(){e.value=new Set;}function x(o){}let u=s||n;return u.addEventListener("mousemove",w),u.addEventListener("mousedown",L),u.addEventListener("mouseup",y),u.addEventListener("wheel",h,{passive:true}),u.addEventListener("mouseleave",b),u.addEventListener("contextmenu",x),n!==window&&window.addEventListener("mouseup",y),{get position(){return v},get delta(){return l},get wheelDelta(){return c},isPressed(o){return e.value.has(o)},isLeftPressed(){return e.value.has(0)},isRightPressed(){return e.value.has(2)},isMiddlePressed(){return e.value.has(1)},clearFrameState(){p=0,i=0,r=0,l.value={x:0,y:0},c.value=0;},dispose(){u.removeEventListener("mousemove",w),u.removeEventListener("mousedown",L),u.removeEventListener("mouseup",y),u.removeEventListener("wheel",h),u.removeEventListener("mouseleave",b),u.removeEventListener("contextmenu",x),n!==window&&window.removeEventListener("mouseup",y);}}}var F={Left:0,Middle:1,Right:2};exports.Keys=k;exports.MouseButton=F;exports.createLoop=M;exports.keyboard=D;exports.mouse=K;//# sourceMappingURL=interactive.js.map
2
+ //# sourceMappingURL=interactive.js.map
@@ -0,0 +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","signal","justPressed","justReleased","normalizeKey","key","handleKeyDown","e","newKeys","handleKeyUp","handleBlur","Keys","mouse","canvas","position","wheelDelta","buttons","lastX","lastY","frameDeltaX","frameDeltaY","frameWheelDelta","getCanvasCoordinates","event","rect","scaleX","scaleY","handleMouseMove","coords","handleMouseDown","newButtons","handleMouseUp","handleWheel","handleMouseLeave","handleContextMenu","_e","eventTarget","button","MouseButton"],"mappings":"iEA6BO,SAASA,CAAAA,CAAWC,EAAuB,EAAC,CAAS,CAC1D,GAAM,CAAE,SAAAC,CAAAA,CAAW,EAAA,CAAI,SAAAC,CAAAA,CAAU,aAAA,CAAAC,EAAe,QAAA,CAAAC,CAAS,EAAIJ,CAAAA,CAEvDK,CAAAA,CAAa,CAAA,CAAIJ,CAAAA,CACnBK,CAAAA,CAAU,KAAA,CACVC,EACAC,CAAAA,CAAW,CAAA,CACXC,EAAc,CAAA,CACdC,CAAAA,CAAM,EACNC,CAAAA,CAAa,CAAA,CACbC,EAAU,CAAA,CACVC,CAAAA,CAAe,KAEnB,SAASC,CAAAA,CAAKC,EAA2B,CACvC,GAAI,CAACT,CAAAA,CAAS,OAEdC,CAAAA,CAAQ,qBAAA,CAAsBO,CAAI,CAAA,CAGlC,IAAME,CAAAA,CAAOD,CAAAA,CAAc,IAG3B,GAAIF,CAAAA,CAAc,CAChBL,CAAAA,CAAWQ,CAAAA,CACXH,EAAe,KAAA,CACf,MACF,CAEA,IAAMI,CAAAA,CAAQ,KAAK,GAAA,CAAID,CAAAA,CAAOR,EAAU,GAAI,CAAA,CAkB5C,GAjBAA,CAAAA,CAAWQ,CAAAA,CAGXL,CAAAA,EAAAA,CACAC,GAAWK,CAAAA,CACPL,CAAAA,EAAW,IACbF,CAAAA,CAAMC,CAAAA,CACNA,EAAa,CAAA,CACbC,CAAAA,EAAW,CAAA,CAAA,CAITV,CAAAA,EACFA,CAAAA,CAASe,CAAK,EAIZd,CAAAA,CAGF,IAFAM,GAAeQ,CAAAA,CAERR,CAAAA,EAAeJ,GACpBF,CAAAA,CAAcE,CAAU,CAAA,CACxBI,CAAAA,EAAeJ,CAAAA,CAKnB,GAAID,EAAU,CACZ,IAAMc,EAAQf,CAAAA,CAAgBM,CAAAA,CAAcJ,EAAa,CAAA,CACzDD,CAAAA,CAASc,CAAK,EAChB,CACF,CAEA,OAAO,CACL,OAAQ,CACFZ,CAAAA,GACJA,EAAU,IAAA,CACVO,CAAAA,CAAe,IAAA,CACfJ,CAAAA,CAAc,CAAA,CACdF,CAAAA,CAAQ,sBAAsBO,CAAI,CAAA,EACpC,EAEA,IAAA,EAAO,CACLR,EAAU,KAAA,CACNC,CAAAA,GAAU,SACZ,oBAAA,CAAqBA,CAAK,EAC1BA,CAAAA,CAAQ,MAAA,EAEZ,EAEA,SAAA,EAAY,CACV,OAAOD,CACT,CAAA,CAEA,MAAA,EAAS,CACP,OAAOI,CACT,CACF,CACF,CC5EO,SAASS,CAAAA,CAASC,CAAAA,CAAsB,OAAuB,CACpE,IAAMC,EAAOC,kBAAAA,CAAoB,IAAI,GAAK,CAAA,CACpCC,CAAAA,CAAc,IAAI,GAAA,CAClBC,CAAAA,CAAe,IAAI,GAAA,CAEzB,SAASC,CAAAA,CAAaC,CAAAA,CAAqB,CACzC,OAAOA,EAAI,WAAA,EACb,CAEA,SAASC,CAAAA,CAAcC,EAAgB,CAErC,IAAMF,CAAAA,CAAMD,CAAAA,CADEG,CAAAA,CACiB,IAAI,EAEnC,GAAI,CAACP,EAAK,KAAA,CAAM,GAAA,CAAIK,CAAG,CAAA,CAAG,CACxBH,CAAAA,CAAY,GAAA,CAAIG,CAAG,CAAA,CACnB,IAAMG,CAAAA,CAAU,IAAI,IAAIR,CAAAA,CAAK,KAAK,EAClCQ,CAAAA,CAAQ,GAAA,CAAIH,CAAG,CAAA,CACfL,CAAAA,CAAK,MAAQQ,EACf,CACF,CAEA,SAASC,CAAAA,CAAYF,EAAgB,CAEnC,IAAMF,CAAAA,CAAMD,CAAAA,CADEG,CAAAA,CACiB,IAAI,EAEnC,GAAIP,CAAAA,CAAK,MAAM,GAAA,CAAIK,CAAG,EAAG,CACvBF,CAAAA,CAAa,IAAIE,CAAG,CAAA,CACpB,IAAMG,CAAAA,CAAU,IAAI,IAAIR,CAAAA,CAAK,KAAK,EAClCQ,CAAAA,CAAQ,MAAA,CAAOH,CAAG,CAAA,CAClBL,CAAAA,CAAK,KAAA,CAAQQ,EACf,CACF,CAEA,SAASE,CAAAA,EAAmB,CAE1BV,EAAK,KAAA,CAAQ,IAAI,IACjBE,CAAAA,CAAY,KAAA,GACZC,CAAAA,CAAa,KAAA,GACf,CAGA,OAAAJ,EAAO,gBAAA,CAAiB,SAAA,CAAWO,CAAa,CAAA,CAChDP,CAAAA,CAAO,gBAAA,CAAiB,QAASU,CAAW,CAAA,CACxCV,IAAW,MAAA,EACbA,CAAAA,CAAO,iBAAiB,MAAA,CAAQW,CAAU,CAAA,CAGrC,CACL,SAAA,CAAUL,CAAAA,CAAsB,CAC9B,OAAOL,CAAAA,CAAK,MAAM,GAAA,CAAII,CAAAA,CAAaC,CAAG,CAAC,CACzC,CAAA,CAEA,aAAA,CAAcA,CAAAA,CAAsB,CAClC,OAAOH,CAAAA,CAAY,GAAA,CAAIE,EAAaC,CAAG,CAAC,CAC1C,CAAA,CAEA,cAAA,CAAeA,EAAsB,CACnC,OAAOF,EAAa,GAAA,CAAIC,CAAAA,CAAaC,CAAG,CAAC,CAC3C,EAEA,cAAA,EAA2B,CACzB,OAAO,KAAA,CAAM,IAAA,CAAKL,CAAAA,CAAK,KAAK,CAC9B,CAAA,CAEA,IAAI,IAAA,EAAO,CACT,OAAOA,CACT,CAAA,CAEA,iBAAwB,CACtBE,CAAAA,CAAY,OAAM,CAClBC,CAAAA,CAAa,QACf,CAAA,CAEA,SAAgB,CACdJ,CAAAA,CAAO,mBAAA,CAAoB,SAAA,CAAWO,CAAa,CAAA,CACnDP,EAAO,mBAAA,CAAoB,OAAA,CAASU,CAAW,CAAA,CAC3CV,CAAAA,GAAW,QACbA,CAAAA,CAAO,mBAAA,CAAoB,OAAQW,CAAU,EAEjD,CACF,CACF,KAGaC,CAAAA,CAAO,CAElB,QAAS,SAAA,CACT,SAAA,CAAW,WAAA,CACX,SAAA,CAAW,WAAA,CACX,UAAA,CAAY,aAGZ,IAAA,CAAM,MAAA,CACN,KAAM,MAAA,CACN,IAAA,CAAM,OACN,IAAA,CAAM,MAAA,CAGN,KAAA,CAAO,OAAA,CACP,KAAA,CAAO,OAAA,CACP,OAAQ,QAAA,CACR,SAAA,CAAW,YACX,UAAA,CAAY,YAAA,CACZ,YAAa,aAAA,CACb,YAAA,CAAc,cAAA,CACd,OAAA,CAAS,SAAA,CACT,QAAA,CAAU,WACV,GAAA,CAAK,KAAA,CAGL,OAAQ,QAAA,CACR,MAAA,CAAQ,SACR,MAAA,CAAQ,QAAA,CACR,OAAQ,QAAA,CACR,MAAA,CAAQ,SACR,MAAA,CAAQ,QAAA,CACR,OAAQ,QAAA,CACR,MAAA,CAAQ,SACR,MAAA,CAAQ,QAAA,CACR,MAAA,CAAQ,QACV,ECvGO,SAASC,EAAMjC,CAAAA,CAAwB,GAAgB,CAC5D,GAAM,CAAE,MAAA,CAAAoB,CAAAA,CAAS,OAAQ,MAAA,CAAAc,CAAO,EAAIlC,CAAAA,CAE9BmC,CAAAA,CAAWb,mBAAa,CAAE,CAAA,CAAG,EAAG,CAAA,CAAG,CAAE,CAAC,CAAA,CACtCL,CAAAA,CAAQK,kBAAAA,CAAa,CAAE,CAAA,CAAG,CAAA,CAAG,EAAG,CAAE,CAAC,EACnCc,CAAAA,CAAad,kBAAAA,CAAe,CAAC,CAAA,CAC7Be,CAAAA,CAAUf,mBAAoB,IAAI,GAAK,EAEzCgB,CAAAA,CAAQ,CAAA,CACRC,EAAQ,CAAA,CACRC,CAAAA,CAAc,CAAA,CACdC,CAAAA,CAAc,CAAA,CACdC,CAAAA,CAAkB,EAEtB,SAASC,CAAAA,CAAqBC,EAAyB,CACrD,GAAIV,EAAQ,CACV,IAAMW,CAAAA,CAAOX,CAAAA,CAAO,qBAAA,EAAsB,CACpCY,EAASZ,CAAAA,CAAO,KAAA,CAAQW,EAAK,KAAA,CAC7BE,CAAAA,CAASb,EAAO,MAAA,CAASW,CAAAA,CAAK,MAAA,CACpC,OAAO,CACL,CAAA,CAAA,CAAID,EAAM,OAAA,CAAUC,CAAAA,CAAK,MAAQC,CAAAA,CACjC,CAAA,CAAA,CAAIF,EAAM,OAAA,CAAUC,CAAAA,CAAK,KAAOE,CAClC,CACF,CACA,OAAO,CACL,EAAGH,CAAAA,CAAM,OAAA,CACT,EAAGA,CAAAA,CAAM,OACX,CACF,CAEA,SAASI,CAAAA,CAAgBpB,EAAgB,CAEvC,IAAMqB,EAASN,CAAAA,CADDf,CAC2B,EAEzCY,CAAAA,EAAeS,CAAAA,CAAO,EAAIX,CAAAA,CAC1BG,CAAAA,EAAeQ,EAAO,CAAA,CAAIV,CAAAA,CAC1BD,EAAQW,CAAAA,CAAO,CAAA,CACfV,EAAQU,CAAAA,CAAO,CAAA,CAEfd,CAAAA,CAAS,KAAA,CAAQc,CAAAA,CACjBhC,CAAAA,CAAM,MAAQ,CAAE,CAAA,CAAGuB,EAAa,CAAA,CAAGC,CAAY,EACjD,CAEA,SAASS,EAAgBtB,CAAAA,CAAgB,CACvC,IAAMgB,CAAAA,CAAQhB,CAAAA,CACRuB,EAAa,IAAI,GAAA,CAAId,EAAQ,KAAK,CAAA,CACxCc,CAAAA,CAAW,GAAA,CAAIP,CAAAA,CAAM,MAAM,EAC3BP,CAAAA,CAAQ,KAAA,CAAQc,EAClB,CAEA,SAASC,EAAcxB,CAAAA,CAAgB,CACrC,IAAMgB,CAAAA,CAAQhB,CAAAA,CACRuB,CAAAA,CAAa,IAAI,GAAA,CAAId,CAAAA,CAAQ,KAAK,CAAA,CACxCc,CAAAA,CAAW,OAAOP,CAAAA,CAAM,MAAM,CAAA,CAC9BP,CAAAA,CAAQ,KAAA,CAAQc,EAClB,CAEA,SAASE,CAAAA,CAAYzB,EAAgB,CAEnCc,CAAAA,EAAmB,KAAK,IAAA,CADVd,CAAAA,CACqB,MAAM,CAAA,CACzCQ,CAAAA,CAAW,MAAQM,EACrB,CAEA,SAASY,CAAAA,EAAyB,CAChCjB,EAAQ,KAAA,CAAQ,IAAI,IACtB,CAEA,SAASkB,CAAAA,CAAkBC,EAAiB,CAG5C,CAGA,IAAMC,CAAAA,CAAcvB,CAAAA,EAAUd,EAC9B,OAAAqC,CAAAA,CAAY,iBAAiB,WAAA,CAAaT,CAAe,EACzDS,CAAAA,CAAY,gBAAA,CAAiB,YAAaP,CAAe,CAAA,CACzDO,EAAY,gBAAA,CAAiB,SAAA,CAAWL,CAAa,CAAA,CACrDK,CAAAA,CAAY,gBAAA,CAAiB,QAASJ,CAAAA,CAAa,CAAE,QAAS,IAAK,CAAC,EACpEI,CAAAA,CAAY,gBAAA,CAAiB,aAAcH,CAAgB,CAAA,CAC3DG,EAAY,gBAAA,CAAiB,aAAA,CAAeF,CAAiB,CAAA,CAGzDnC,CAAAA,GAAW,QACb,MAAA,CAAO,gBAAA,CAAiB,SAAA,CAAWgC,CAAa,CAAA,CAG3C,CACL,IAAI,QAAA,EAAW,CACb,OAAOjB,CACT,CAAA,CAEA,IAAI,KAAA,EAAQ,CACV,OAAOlB,CACT,CAAA,CAEA,IAAI,YAAa,CACf,OAAOmB,CACT,CAAA,CAEA,SAAA,CAAUsB,EAAyB,CACjC,OAAOrB,CAAAA,CAAQ,KAAA,CAAM,GAAA,CAAIqB,CAAM,CACjC,CAAA,CAEA,aAAA,EAAyB,CACvB,OAAOrB,CAAAA,CAAQ,MAAM,GAAA,CAAI,CAAC,CAC5B,CAAA,CAEA,cAAA,EAA0B,CACxB,OAAOA,CAAAA,CAAQ,MAAM,GAAA,CAAI,CAAC,CAC5B,CAAA,CAEA,eAAA,EAA2B,CACzB,OAAOA,CAAAA,CAAQ,KAAA,CAAM,IAAI,CAAC,CAC5B,EAEA,eAAA,EAAwB,CACtBG,EAAc,CAAA,CACdC,CAAAA,CAAc,EACdC,CAAAA,CAAkB,CAAA,CAClBzB,EAAM,KAAA,CAAQ,CAAE,EAAG,CAAA,CAAG,CAAA,CAAG,CAAE,CAAA,CAC3BmB,CAAAA,CAAW,KAAA,CAAQ,EACrB,CAAA,CAEA,OAAA,EAAgB,CACdqB,CAAAA,CAAY,mBAAA,CAAoB,YAAaT,CAAe,CAAA,CAC5DS,EAAY,mBAAA,CAAoB,WAAA,CAAaP,CAAe,CAAA,CAC5DO,CAAAA,CAAY,oBAAoB,SAAA,CAAWL,CAAa,EACxDK,CAAAA,CAAY,mBAAA,CAAoB,QAASJ,CAAW,CAAA,CACpDI,CAAAA,CAAY,mBAAA,CAAoB,YAAA,CAAcH,CAAgB,EAC9DG,CAAAA,CAAY,mBAAA,CAAoB,cAAeF,CAAiB,CAAA,CAE5DnC,IAAW,MAAA,EACb,MAAA,CAAO,mBAAA,CAAoB,SAAA,CAAWgC,CAAa,EAEvD,CACF,CACF,KAGaO,CAAAA,CAAc,CACzB,KAAM,CAAA,CACN,MAAA,CAAQ,CAAA,CACR,KAAA,CAAO,CACT","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 { signal, type Signal } from '../core/signal'\n\nexport interface KeyboardState {\n /** Check if a key is currently pressed */\n isPressed(key: string): boolean\n /** Check if a key was just pressed this frame */\n isJustPressed(key: string): boolean\n /** Check if a key was just released this frame */\n isJustReleased(key: string): boolean\n /** Get all currently pressed keys */\n getPressedKeys(): string[]\n /** Signal that updates when any key state changes */\n readonly keys: Signal<Set<string>>\n /** Clear just pressed/released state (call at end of frame) */\n clearFrameState(): void\n /** Cleanup 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 const keys = signal<Set<string>>(new Set())\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 handleKeyDown(e: Event): void {\n const event = e as KeyboardEvent\n const key = normalizeKey(event.code)\n\n if (!keys.value.has(key)) {\n justPressed.add(key)\n const newKeys = new Set(keys.value)\n newKeys.add(key)\n keys.value = newKeys\n }\n }\n\n function handleKeyUp(e: Event): void {\n const event = e as KeyboardEvent\n const key = normalizeKey(event.code)\n\n if (keys.value.has(key)) {\n justReleased.add(key)\n const newKeys = new Set(keys.value)\n newKeys.delete(key)\n keys.value = newKeys\n }\n }\n\n function handleBlur(): void {\n // Clear all keys when window loses focus\n keys.value = new Set()\n justPressed.clear()\n justReleased.clear()\n }\n\n // Add event listeners\n target.addEventListener('keydown', handleKeyDown)\n target.addEventListener('keyup', handleKeyUp)\n if (target === window) {\n target.addEventListener('blur', handleBlur)\n }\n\n return {\n isPressed(key: string): boolean {\n return keys.value.has(normalizeKey(key))\n },\n\n isJustPressed(key: string): boolean {\n return justPressed.has(normalizeKey(key))\n },\n\n isJustReleased(key: string): boolean {\n return justReleased.has(normalizeKey(key))\n },\n\n getPressedKeys(): string[] {\n return Array.from(keys.value)\n },\n\n get keys() {\n return keys\n },\n\n clearFrameState(): void {\n justPressed.clear()\n justReleased.clear()\n },\n\n dispose(): void {\n target.removeEventListener('keydown', handleKeyDown)\n target.removeEventListener('keyup', handleKeyUp)\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 { signal, type Signal } from '../core/signal'\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: Signal<Vec2>\n /** Mouse position delta since last frame */\n readonly delta: Signal<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: Signal<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 = signal<Vec2>({ x: 0, y: 0 })\n const delta = signal<Vec2>({ x: 0, y: 0 })\n const wheelDelta = signal<number>(0)\n const buttons = signal<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 position.value = coords\n delta.value = { x: frameDeltaX, y: frameDeltaY }\n }\n\n function handleMouseDown(e: Event): void {\n const event = e as MouseEvent\n const newButtons = new Set(buttons.value)\n newButtons.add(event.button)\n buttons.value = newButtons\n }\n\n function handleMouseUp(e: Event): void {\n const event = e as MouseEvent\n const newButtons = new Set(buttons.value)\n newButtons.delete(event.button)\n buttons.value = newButtons\n }\n\n function handleWheel(e: Event): void {\n const event = e as WheelEvent\n frameWheelDelta += Math.sign(event.deltaY)\n wheelDelta.value = frameWheelDelta\n }\n\n function handleMouseLeave(): void {\n buttons.value = 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, { passive: true })\n eventTarget.addEventListener('mouseleave', handleMouseLeave)\n eventTarget.addEventListener('contextmenu', handleContextMenu)\n\n // Handle mouse up outside target\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.value.has(button)\n },\n\n isLeftPressed(): boolean {\n return buttons.value.has(0)\n },\n\n isRightPressed(): boolean {\n return buttons.value.has(2)\n },\n\n isMiddlePressed(): boolean {\n return buttons.value.has(1)\n },\n\n clearFrameState(): void {\n frameDeltaX = 0\n frameDeltaY = 0\n frameWheelDelta = 0\n delta.value = { x: 0, y: 0 }\n wheelDelta.value = 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"]}
@@ -0,0 +1,2 @@
1
+ import {h}from'./chunk-5S3ZQ2LB.mjs';function M(d={}){let{fixedFps:n=60,onUpdate:s,onFixedUpdate:v,onRender:l}=d,c=1/n,e=false,f,t=0,p=0,i=0,r=0,E=0,w=true;function L(y){if(!e)return;f=requestAnimationFrame(L);let h=y/1e3;if(w){t=h,w=false;return}let b=Math.min(h-t,.25);if(t=h,r++,E+=b,E>=1&&(i=r,r=0,E-=1),s&&s(b),v)for(p+=b;p>=c;)v(c),p-=c;if(l){let x=v?p/c:1;l(x);}}return {start(){e||(e=true,w=true,p=0,f=requestAnimationFrame(L));},stop(){e=false,f!==void 0&&(cancelAnimationFrame(f),f=void 0);},isRunning(){return e},getFps(){return i}}}function D(d=window){let n=h(new Set),s=new Set,v=new Set;function l(t){return t.toLowerCase()}function c(t){let i=l(t.code);if(!n.value.has(i)){s.add(i);let r=new Set(n.value);r.add(i),n.value=r;}}function e(t){let i=l(t.code);if(n.value.has(i)){v.add(i);let r=new Set(n.value);r.delete(i),n.value=r;}}function f(){n.value=new Set,s.clear(),v.clear();}return d.addEventListener("keydown",c),d.addEventListener("keyup",e),d===window&&d.addEventListener("blur",f),{isPressed(t){return n.value.has(l(t))},isJustPressed(t){return s.has(l(t))},isJustReleased(t){return v.has(l(t))},getPressedKeys(){return Array.from(n.value)},get keys(){return n},clearFrameState(){s.clear(),v.clear();},dispose(){d.removeEventListener("keydown",c),d.removeEventListener("keyup",e),d===window&&d.removeEventListener("blur",f);}}}var k={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 K(d={}){let{target:n=window,canvas:s}=d,v=h({x:0,y:0}),l=h({x:0,y:0}),c=h(0),e=h(new Set),f=0,t=0,p=0,i=0,r=0;function E(o){if(s){let m=s.getBoundingClientRect(),a=s.width/m.width,S=s.height/m.height;return {x:(o.clientX-m.left)*a,y:(o.clientY-m.top)*S}}return {x:o.clientX,y:o.clientY}}function w(o){let a=E(o);p+=a.x-f,i+=a.y-t,f=a.x,t=a.y,v.value=a,l.value={x:p,y:i};}function L(o){let m=o,a=new Set(e.value);a.add(m.button),e.value=a;}function y(o){let m=o,a=new Set(e.value);a.delete(m.button),e.value=a;}function h$1(o){r+=Math.sign(o.deltaY),c.value=r;}function b(){e.value=new Set;}function x(o){}let u=s||n;return u.addEventListener("mousemove",w),u.addEventListener("mousedown",L),u.addEventListener("mouseup",y),u.addEventListener("wheel",h$1,{passive:true}),u.addEventListener("mouseleave",b),u.addEventListener("contextmenu",x),n!==window&&window.addEventListener("mouseup",y),{get position(){return v},get delta(){return l},get wheelDelta(){return c},isPressed(o){return e.value.has(o)},isLeftPressed(){return e.value.has(0)},isRightPressed(){return e.value.has(2)},isMiddlePressed(){return e.value.has(1)},clearFrameState(){p=0,i=0,r=0,l.value={x:0,y:0},c.value=0;},dispose(){u.removeEventListener("mousemove",w),u.removeEventListener("mousedown",L),u.removeEventListener("mouseup",y),u.removeEventListener("wheel",h$1),u.removeEventListener("mouseleave",b),u.removeEventListener("contextmenu",x),n!==window&&window.removeEventListener("mouseup",y);}}}var F={Left:0,Middle:1,Right:2};export{k as Keys,F as MouseButton,M as createLoop,D as keyboard,K as mouse};//# sourceMappingURL=interactive.mjs.map
2
+ //# sourceMappingURL=interactive.mjs.map
@@ -0,0 +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","signal","justPressed","justReleased","normalizeKey","key","handleKeyDown","e","newKeys","handleKeyUp","handleBlur","Keys","mouse","canvas","position","wheelDelta","buttons","lastX","lastY","frameDeltaX","frameDeltaY","frameWheelDelta","getCanvasCoordinates","event","rect","scaleX","scaleY","handleMouseMove","coords","handleMouseDown","newButtons","handleMouseUp","handleWheel","handleMouseLeave","handleContextMenu","_e","eventTarget","button","MouseButton"],"mappings":"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","file":"interactive.mjs","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 { signal, type Signal } from '../core/signal'\n\nexport interface KeyboardState {\n /** Check if a key is currently pressed */\n isPressed(key: string): boolean\n /** Check if a key was just pressed this frame */\n isJustPressed(key: string): boolean\n /** Check if a key was just released this frame */\n isJustReleased(key: string): boolean\n /** Get all currently pressed keys */\n getPressedKeys(): string[]\n /** Signal that updates when any key state changes */\n readonly keys: Signal<Set<string>>\n /** Clear just pressed/released state (call at end of frame) */\n clearFrameState(): void\n /** Cleanup 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 const keys = signal<Set<string>>(new Set())\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 handleKeyDown(e: Event): void {\n const event = e as KeyboardEvent\n const key = normalizeKey(event.code)\n\n if (!keys.value.has(key)) {\n justPressed.add(key)\n const newKeys = new Set(keys.value)\n newKeys.add(key)\n keys.value = newKeys\n }\n }\n\n function handleKeyUp(e: Event): void {\n const event = e as KeyboardEvent\n const key = normalizeKey(event.code)\n\n if (keys.value.has(key)) {\n justReleased.add(key)\n const newKeys = new Set(keys.value)\n newKeys.delete(key)\n keys.value = newKeys\n }\n }\n\n function handleBlur(): void {\n // Clear all keys when window loses focus\n keys.value = new Set()\n justPressed.clear()\n justReleased.clear()\n }\n\n // Add event listeners\n target.addEventListener('keydown', handleKeyDown)\n target.addEventListener('keyup', handleKeyUp)\n if (target === window) {\n target.addEventListener('blur', handleBlur)\n }\n\n return {\n isPressed(key: string): boolean {\n return keys.value.has(normalizeKey(key))\n },\n\n isJustPressed(key: string): boolean {\n return justPressed.has(normalizeKey(key))\n },\n\n isJustReleased(key: string): boolean {\n return justReleased.has(normalizeKey(key))\n },\n\n getPressedKeys(): string[] {\n return Array.from(keys.value)\n },\n\n get keys() {\n return keys\n },\n\n clearFrameState(): void {\n justPressed.clear()\n justReleased.clear()\n },\n\n dispose(): void {\n target.removeEventListener('keydown', handleKeyDown)\n target.removeEventListener('keyup', handleKeyUp)\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 { signal, type Signal } from '../core/signal'\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: Signal<Vec2>\n /** Mouse position delta since last frame */\n readonly delta: Signal<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: Signal<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 = signal<Vec2>({ x: 0, y: 0 })\n const delta = signal<Vec2>({ x: 0, y: 0 })\n const wheelDelta = signal<number>(0)\n const buttons = signal<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 position.value = coords\n delta.value = { x: frameDeltaX, y: frameDeltaY }\n }\n\n function handleMouseDown(e: Event): void {\n const event = e as MouseEvent\n const newButtons = new Set(buttons.value)\n newButtons.add(event.button)\n buttons.value = newButtons\n }\n\n function handleMouseUp(e: Event): void {\n const event = e as MouseEvent\n const newButtons = new Set(buttons.value)\n newButtons.delete(event.button)\n buttons.value = newButtons\n }\n\n function handleWheel(e: Event): void {\n const event = e as WheelEvent\n frameWheelDelta += Math.sign(event.deltaY)\n wheelDelta.value = frameWheelDelta\n }\n\n function handleMouseLeave(): void {\n buttons.value = 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, { passive: true })\n eventTarget.addEventListener('mouseleave', handleMouseLeave)\n eventTarget.addEventListener('contextmenu', handleContextMenu)\n\n // Handle mouse up outside target\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.value.has(button)\n },\n\n isLeftPressed(): boolean {\n return buttons.value.has(0)\n },\n\n isRightPressed(): boolean {\n return buttons.value.has(2)\n },\n\n isMiddlePressed(): boolean {\n return buttons.value.has(1)\n },\n\n clearFrameState(): void {\n frameDeltaX = 0\n frameDeltaY = 0\n frameWheelDelta = 0\n delta.value = { x: 0, y: 0 }\n wheelDelta.value = 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"]}
@@ -0,0 +1,2 @@
1
+ export { Fragment, jsxDEV as jsx, jsxDEV, jsxs } from './jsx-runtime.cjs';
2
+ import './renderer-DSLb-FGg.cjs';
@@ -0,0 +1,2 @@
1
+ export { Fragment, jsxDEV as jsx, jsxDEV, jsxs } from './jsx-runtime.js';
2
+ import './renderer-DSLb-FGg.js';
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkU6C6VDVZ_js=require('./chunk-U6C6VDVZ.js');require('./chunk-WQFQO5LK.js');Object.defineProperty(exports,"Fragment",{enumerable:true,get:function(){return chunkU6C6VDVZ_js.c}});Object.defineProperty(exports,"jsx",{enumerable:true,get:function(){return chunkU6C6VDVZ_js.a}});Object.defineProperty(exports,"jsxDEV",{enumerable:true,get:function(){return chunkU6C6VDVZ_js.a}});Object.defineProperty(exports,"jsxs",{enumerable:true,get:function(){return chunkU6C6VDVZ_js.b}});//# sourceMappingURL=jsx-dev-runtime.js.map
2
+ //# sourceMappingURL=jsx-dev-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"jsx-dev-runtime.js"}
@@ -0,0 +1,2 @@
1
+ export{c as Fragment,a as jsx,a as jsxDEV,b as jsxs}from'./chunk-OPAQ4R4M.mjs';import'./chunk-KNF5ERPK.mjs';//# sourceMappingURL=jsx-dev-runtime.mjs.map
2
+ //# sourceMappingURL=jsx-dev-runtime.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"jsx-dev-runtime.mjs"}
@@ -0,0 +1,78 @@
1
+ import { F as FNode } from './renderer-DSLb-FGg.cjs';
2
+
3
+ /**
4
+ * Flexium JSX Runtime
5
+ *
6
+ * This module provides the automatic JSX runtime for Flexium.
7
+ * It implements the new JSX transform introduced in React 17+.
8
+ *
9
+ * With automatic JSX runtime, you no longer need to import `f`:
10
+ *
11
+ * Before (classic):
12
+ * ```tsx
13
+ * import { f } from 'flexium/dom'
14
+ * function App() {
15
+ * return <div>Hello</div>
16
+ * }
17
+ * ```
18
+ *
19
+ * After (automatic):
20
+ * ```tsx
21
+ * function App() {
22
+ * return <div>Hello</div>
23
+ * }
24
+ * ```
25
+ *
26
+ * Usage in tsconfig.json:
27
+ * ```json
28
+ * {
29
+ * "compilerOptions": {
30
+ * "jsx": "react-jsx",
31
+ * "jsxImportSource": "flexium"
32
+ * }
33
+ * }
34
+ * ```
35
+ */
36
+
37
+ /**
38
+ * JSX runtime function for elements with multiple children
39
+ *
40
+ * @param type - Element type (string for built-in, function for components)
41
+ * @param props - Element properties including children
42
+ * @returns Flexium node
43
+ */
44
+ declare function jsx(type: string | Function, props: Record<string, any>): FNode;
45
+ /**
46
+ * JSX runtime function for elements with static children
47
+ * (optimization hint from the compiler)
48
+ *
49
+ * @param type - Element type
50
+ * @param props - Element properties
51
+ * @returns Flexium node
52
+ */
53
+ declare function jsxs(type: string | Function, props: Record<string, any>): FNode;
54
+ /**
55
+ * Fragment component for JSX
56
+ * Renders children without a wrapper element
57
+ */
58
+ declare function Fragment(props: {
59
+ children?: any[];
60
+ }): FNode;
61
+
62
+ declare namespace JSX {
63
+ interface IntrinsicElements {
64
+ [elemName: string]: any;
65
+ }
66
+ type Element = any;
67
+ interface ElementClass {
68
+ render: any;
69
+ }
70
+ interface ElementAttributesProperty {
71
+ props: any;
72
+ }
73
+ interface ElementChildrenAttribute {
74
+ children: {};
75
+ }
76
+ }
77
+
78
+ export { Fragment, JSX, jsx, jsx as jsxDEV, jsxs };