brainrot-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +372 -0
  2. package/dist/AchievementNotification.d.ts +28 -0
  3. package/dist/AchievementNotification.d.ts.map +1 -0
  4. package/dist/AchievementNotification.js +74 -0
  5. package/dist/AchievementNotification.js.map +1 -0
  6. package/dist/GameSelector.d.ts +25 -0
  7. package/dist/GameSelector.d.ts.map +1 -0
  8. package/dist/GameSelector.js +105 -0
  9. package/dist/GameSelector.js.map +1 -0
  10. package/dist/HelpOverlay.d.ts +15 -0
  11. package/dist/HelpOverlay.d.ts.map +1 -0
  12. package/dist/HelpOverlay.js +134 -0
  13. package/dist/HelpOverlay.js.map +1 -0
  14. package/dist/Layout.d.ts +49 -0
  15. package/dist/Layout.d.ts.map +1 -0
  16. package/dist/Layout.js +83 -0
  17. package/dist/Layout.js.map +1 -0
  18. package/dist/Leaderboard.d.ts +46 -0
  19. package/dist/Leaderboard.d.ts.map +1 -0
  20. package/dist/Leaderboard.js +68 -0
  21. package/dist/Leaderboard.js.map +1 -0
  22. package/dist/LogViewer.d.ts +33 -0
  23. package/dist/LogViewer.d.ts.map +1 -0
  24. package/dist/LogViewer.js +179 -0
  25. package/dist/LogViewer.js.map +1 -0
  26. package/dist/LoopAlertOverlay.d.ts +15 -0
  27. package/dist/LoopAlertOverlay.d.ts.map +1 -0
  28. package/dist/LoopAlertOverlay.js +17 -0
  29. package/dist/LoopAlertOverlay.js.map +1 -0
  30. package/dist/LoopManagementPanel.d.ts +44 -0
  31. package/dist/LoopManagementPanel.d.ts.map +1 -0
  32. package/dist/LoopManagementPanel.js +220 -0
  33. package/dist/LoopManagementPanel.js.map +1 -0
  34. package/dist/SettingsMenu.d.ts +22 -0
  35. package/dist/SettingsMenu.d.ts.map +1 -0
  36. package/dist/SettingsMenu.js +367 -0
  37. package/dist/SettingsMenu.js.map +1 -0
  38. package/dist/SplitPane.d.ts +63 -0
  39. package/dist/SplitPane.d.ts.map +1 -0
  40. package/dist/SplitPane.js +104 -0
  41. package/dist/SplitPane.js.map +1 -0
  42. package/dist/StatsMenu.d.ts +15 -0
  43. package/dist/StatsMenu.d.ts.map +1 -0
  44. package/dist/StatsMenu.js +230 -0
  45. package/dist/StatsMenu.js.map +1 -0
  46. package/dist/StatusBar.d.ts +58 -0
  47. package/dist/StatusBar.d.ts.map +1 -0
  48. package/dist/StatusBar.js +106 -0
  49. package/dist/StatusBar.js.map +1 -0
  50. package/dist/__tests__/ralph-loop-parser.test.d.ts +2 -0
  51. package/dist/__tests__/ralph-loop-parser.test.d.ts.map +1 -0
  52. package/dist/__tests__/ralph-loop-parser.test.js +143 -0
  53. package/dist/__tests__/ralph-loop-parser.test.js.map +1 -0
  54. package/dist/claude-code-process.d.ts +76 -0
  55. package/dist/claude-code-process.d.ts.map +1 -0
  56. package/dist/claude-code-process.js +221 -0
  57. package/dist/claude-code-process.js.map +1 -0
  58. package/dist/cli.d.ts +42 -0
  59. package/dist/cli.d.ts.map +1 -0
  60. package/dist/cli.js +265 -0
  61. package/dist/cli.js.map +1 -0
  62. package/dist/config.d.ts +206 -0
  63. package/dist/config.d.ts.map +1 -0
  64. package/dist/config.js +270 -0
  65. package/dist/config.js.map +1 -0
  66. package/dist/game-types.d.ts +177 -0
  67. package/dist/game-types.d.ts.map +1 -0
  68. package/dist/game-types.js +55 -0
  69. package/dist/game-types.js.map +1 -0
  70. package/dist/games/MinesweeperGame.d.ts +15 -0
  71. package/dist/games/MinesweeperGame.d.ts.map +1 -0
  72. package/dist/games/MinesweeperGame.js +555 -0
  73. package/dist/games/MinesweeperGame.js.map +1 -0
  74. package/dist/games/PongGame.d.ts +15 -0
  75. package/dist/games/PongGame.d.ts.map +1 -0
  76. package/dist/games/PongGame.js +379 -0
  77. package/dist/games/PongGame.js.map +1 -0
  78. package/dist/games/SnakeGame.d.ts +15 -0
  79. package/dist/games/SnakeGame.d.ts.map +1 -0
  80. package/dist/games/SnakeGame.js +333 -0
  81. package/dist/games/SnakeGame.js.map +1 -0
  82. package/dist/games/TetrisGame.d.ts +15 -0
  83. package/dist/games/TetrisGame.d.ts.map +1 -0
  84. package/dist/games/TetrisGame.js +654 -0
  85. package/dist/games/TetrisGame.js.map +1 -0
  86. package/dist/games/index.d.ts +23 -0
  87. package/dist/games/index.d.ts.map +1 -0
  88. package/dist/games/index.js +47 -0
  89. package/dist/games/index.js.map +1 -0
  90. package/dist/high-scores.d.ts +57 -0
  91. package/dist/high-scores.d.ts.map +1 -0
  92. package/dist/high-scores.js +230 -0
  93. package/dist/high-scores.js.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +264 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/ralph-loop-parser.d.ts +58 -0
  99. package/dist/ralph-loop-parser.d.ts.map +1 -0
  100. package/dist/ralph-loop-parser.js +315 -0
  101. package/dist/ralph-loop-parser.js.map +1 -0
  102. package/dist/stats.d.ts +142 -0
  103. package/dist/stats.d.ts.map +1 -0
  104. package/dist/stats.js +521 -0
  105. package/dist/stats.js.map +1 -0
  106. package/dist/styled-components.d.ts +231 -0
  107. package/dist/styled-components.d.ts.map +1 -0
  108. package/dist/styled-components.js +192 -0
  109. package/dist/styled-components.js.map +1 -0
  110. package/dist/theme.d.ts +301 -0
  111. package/dist/theme.d.ts.map +1 -0
  112. package/dist/theme.js +372 -0
  113. package/dist/theme.js.map +1 -0
  114. package/dist/themes.d.ts +117 -0
  115. package/dist/themes.d.ts.map +1 -0
  116. package/dist/themes.js +296 -0
  117. package/dist/themes.js.map +1 -0
  118. package/dist/ui/index.d.ts +13 -0
  119. package/dist/ui/index.d.ts.map +1 -0
  120. package/dist/ui/index.js +29 -0
  121. package/dist/ui/index.js.map +1 -0
  122. package/dist/use-claude-code.d.ts +30 -0
  123. package/dist/use-claude-code.d.ts.map +1 -0
  124. package/dist/use-claude-code.js +84 -0
  125. package/dist/use-claude-code.js.map +1 -0
  126. package/dist/use-config.d.ts +58 -0
  127. package/dist/use-config.d.ts.map +1 -0
  128. package/dist/use-config.js +113 -0
  129. package/dist/use-config.js.map +1 -0
  130. package/dist/use-game-loop.d.ts +47 -0
  131. package/dist/use-game-loop.d.ts.map +1 -0
  132. package/dist/use-game-loop.js +136 -0
  133. package/dist/use-game-loop.js.map +1 -0
  134. package/dist/use-high-scores.d.ts +41 -0
  135. package/dist/use-high-scores.d.ts.map +1 -0
  136. package/dist/use-high-scores.js +94 -0
  137. package/dist/use-high-scores.js.map +1 -0
  138. package/dist/use-layout-state.d.ts +77 -0
  139. package/dist/use-layout-state.d.ts.map +1 -0
  140. package/dist/use-layout-state.js +160 -0
  141. package/dist/use-layout-state.js.map +1 -0
  142. package/dist/use-ralph-loop.d.ts +41 -0
  143. package/dist/use-ralph-loop.d.ts.map +1 -0
  144. package/dist/use-ralph-loop.js +106 -0
  145. package/dist/use-ralph-loop.js.map +1 -0
  146. package/dist/use-spinner.d.ts +46 -0
  147. package/dist/use-spinner.d.ts.map +1 -0
  148. package/dist/use-spinner.js +71 -0
  149. package/dist/use-spinner.js.map +1 -0
  150. package/dist/use-stats.d.ts +59 -0
  151. package/dist/use-stats.d.ts.map +1 -0
  152. package/dist/use-stats.js +150 -0
  153. package/dist/use-stats.js.map +1 -0
  154. package/dist/use-terminal-size.d.ts +29 -0
  155. package/dist/use-terminal-size.d.ts.map +1 -0
  156. package/dist/use-terminal-size.js +48 -0
  157. package/dist/use-terminal-size.js.map +1 -0
  158. package/dist/useTheme.d.ts +76 -0
  159. package/dist/useTheme.d.ts.map +1 -0
  160. package/dist/useTheme.js +136 -0
  161. package/dist/useTheme.js.map +1 -0
  162. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,372 @@
1
+ # BrainRot CLI
2
+
3
+ ```
4
+ ____ _ ____ _ ____ _ ___
5
+ | __ ) _ __ __ _(_)_ __ | _ \ ___ | |_ / ___| | |_ _|
6
+ | _ \| '__/ _` | | '_ \| |_) / _ \| __| | | | | | |
7
+ | |_) | | | (_| | | | | | _ < (_) | |_ | |___| |___ | |
8
+ |____/|_| \__,_|_|_| |_|_| \_\___/ \__| \____|_____|___|
9
+ ```
10
+
11
+ > Play games while Claude Code works
12
+
13
+ [![Version](https://img.shields.io/badge/version-0.1.0-blue.svg)](package.json)
14
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
15
+ [![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](package.json)
16
+
17
+ A terminal-native CLI application that wraps Claude Code with built-in games to play while AI agents work. Built with TypeScript, React 19, and Ink 6.
18
+
19
+ ## Features
20
+
21
+ - **4 Built-in Games**: Snake, Pong, Tetris, and Minesweeper
22
+ - **Split-Pane Interface**: Play games while monitoring Claude Code output
23
+ - **4 Color Themes**: Default, Dark, Light, and Retro
24
+ - **Auto-Pause**: Games pause automatically when Claude Code needs your attention
25
+ - **Persistent High Scores**: Compete against yourself with local leaderboards
26
+ - **Full Keyboard Navigation**: No mouse needed
27
+
28
+ ## Installation
29
+
30
+ ### Prerequisites
31
+
32
+ - Node.js 18.0.0 or higher
33
+ - [Claude Code](https://claude.ai/code) installed and available in PATH
34
+
35
+ ### Install Globally
36
+
37
+ ```bash
38
+ npm install -g brainrot-cli
39
+ ```
40
+
41
+ ### Or Run from Source
42
+
43
+ ```bash
44
+ git clone https://github.com/brainrot-cli/brainrot.git
45
+ cd brainrot
46
+ npm install
47
+ npm run build
48
+ npm start
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ```bash
54
+ # Start with defaults
55
+ brainrot
56
+
57
+ # Start with vertical layout
58
+ brainrot --layout-direction vertical
59
+
60
+ # Start with dark theme
61
+ brainrot --color-scheme dark
62
+
63
+ # Start directly in Snake
64
+ brainrot --default-game snake
65
+ ```
66
+
67
+ ## Keyboard Shortcuts
68
+
69
+ ### Global Controls
70
+
71
+ | Key | Action |
72
+ |-----|--------|
73
+ | `Tab` | Switch focus between game and management panes |
74
+ | `?` | Toggle help overlay |
75
+ | `Ctrl+S` | Open settings menu |
76
+ | `Ctrl+C` | Exit application |
77
+ | `[` / `]` | Resize panes (when focused) |
78
+
79
+ ### In-Game Controls
80
+
81
+ | Key | Action |
82
+ |-----|--------|
83
+ | `P` | Pause / Resume game |
84
+ | `R` | Restart game |
85
+ | `Q` or `Esc` | Return to game menu |
86
+ | `H` | View high scores (where available) |
87
+
88
+ ## Games
89
+
90
+ ### Snake
91
+
92
+ Classic snake game - eat food to grow, avoid walls and yourself!
93
+
94
+ | Key | Action |
95
+ |-----|--------|
96
+ | `Arrow Keys` or `WASD` | Move snake |
97
+ | `P` | Pause |
98
+ | `R` | Restart |
99
+ | `H` | High scores |
100
+
101
+ ### Pong
102
+
103
+ Single-player pong against AI - first to 5 wins!
104
+
105
+ | Key | Action |
106
+ |-----|--------|
107
+ | `Up/Down` or `W/S` | Move paddle |
108
+ | `P` | Pause |
109
+ | `R` | Restart |
110
+
111
+ ### Tetris
112
+
113
+ Classic Tetris - clear lines with falling blocks!
114
+
115
+ | Key | Action |
116
+ |-----|--------|
117
+ | `Left/Right` | Move piece |
118
+ | `Up` or `W` | Rotate piece |
119
+ | `Down` | Soft drop |
120
+ | `Space` | Hard drop |
121
+ | `P` | Pause |
122
+ | `R` | Restart |
123
+
124
+ ### Minesweeper
125
+
126
+ Find all mines without triggering them!
127
+
128
+ | Key | Action |
129
+ |-----|--------|
130
+ | `Arrow Keys` | Move cursor |
131
+ | `Space` or `Enter` | Reveal cell |
132
+ | `F` | Flag/unflag cell |
133
+ | `P` | Pause |
134
+ | `R` | Restart |
135
+
136
+ ## Configuration
137
+
138
+ BrainRot CLI uses XDG Base Directory conventions for configuration storage.
139
+
140
+ ### File Locations
141
+
142
+ | Type | Location |
143
+ |------|----------|
144
+ | Config | `~/.config/brainrot-cli/config.json` |
145
+ | High Scores | `~/.local/share/brainrot-cli/high-scores.json` |
146
+ | Stats | `~/.local/share/brainrot-cli/stats.json` |
147
+
148
+ ### Example Configuration
149
+
150
+ ```json
151
+ {
152
+ "version": 1,
153
+ "games": {
154
+ "defaultDifficulty": "medium",
155
+ "snake": {
156
+ "initialSpeed": 5,
157
+ "growthRate": 1
158
+ },
159
+ "tetris": {
160
+ "startingLevel": 1,
161
+ "showGhostPiece": true
162
+ },
163
+ "minesweeper": {
164
+ "defaultDifficulty": "easy",
165
+ "showTimer": true
166
+ },
167
+ "pong": {
168
+ "aiDifficulty": 5,
169
+ "ballSpeedMultiplier": 1.0
170
+ }
171
+ },
172
+ "layout": {
173
+ "direction": "horizontal",
174
+ "splitRatio": 0.5,
175
+ "minRatio": 0.25,
176
+ "maxRatio": 0.75,
177
+ "resizeStep": 0.05,
178
+ "showSecondary": true,
179
+ "defaultFocusedPane": 0
180
+ },
181
+ "theme": {
182
+ "colorScheme": "default",
183
+ "borderStyle": "round",
184
+ "spinnerStyle": "spinner",
185
+ "enableAnimations": true,
186
+ "colors": {
187
+ "primary": "cyan",
188
+ "secondary": "magenta",
189
+ "accent": "yellow"
190
+ }
191
+ },
192
+ "claudeCode": {
193
+ "executablePath": "claude",
194
+ "workingDirectory": null,
195
+ "defaultArgs": [],
196
+ "shutdownTimeout": 5000
197
+ },
198
+ "app": {
199
+ "maxScoresPerGame": 10,
200
+ "defaultGame": null,
201
+ "debugMode": false,
202
+ "logLevel": "info"
203
+ }
204
+ }
205
+ ```
206
+
207
+ ### Configuration Options
208
+
209
+ #### Games
210
+
211
+ | Option | Type | Default | Description |
212
+ |--------|------|---------|-------------|
213
+ | `defaultDifficulty` | `easy` \| `medium` \| `hard` | `medium` | Default difficulty for games |
214
+ | `snake.initialSpeed` | `1-10` | `5` | Snake movement speed |
215
+ | `snake.growthRate` | `number` | `1` | Segments added per food |
216
+ | `tetris.startingLevel` | `1-10` | `1` | Starting level |
217
+ | `tetris.showGhostPiece` | `boolean` | `true` | Show piece preview |
218
+ | `minesweeper.defaultDifficulty` | `easy` \| `medium` \| `hard` | `easy` | Board size/mines |
219
+ | `minesweeper.showTimer` | `boolean` | `true` | Display timer |
220
+ | `pong.aiDifficulty` | `1-10` | `5` | AI opponent skill |
221
+ | `pong.ballSpeedMultiplier` | `0.5-2.0` | `1.0` | Ball speed modifier |
222
+
223
+ #### Layout
224
+
225
+ | Option | Type | Default | Description |
226
+ |--------|------|---------|-------------|
227
+ | `direction` | `horizontal` \| `vertical` | `horizontal` | Split direction |
228
+ | `splitRatio` | `0.0-1.0` | `0.5` | Initial split ratio |
229
+ | `minRatio` | `0.0-1.0` | `0.25` | Minimum pane size |
230
+ | `maxRatio` | `0.0-1.0` | `0.75` | Maximum pane size |
231
+ | `resizeStep` | `number` | `0.05` | Keyboard resize increment |
232
+ | `showSecondary` | `boolean` | `true` | Show management pane |
233
+ | `defaultFocusedPane` | `0` \| `1` | `0` | Initial focus (0=game) |
234
+
235
+ #### Theme
236
+
237
+ | Option | Type | Default | Description |
238
+ |--------|------|---------|-------------|
239
+ | `colorScheme` | `default` \| `dark` \| `light` \| `retro` | `default` | Color theme |
240
+ | `borderStyle` | `single` \| `round` \| `double` \| `heavy` | `round` | Border characters |
241
+ | `spinnerStyle` | `spinner` \| `dots` \| `braille` | `spinner` | Loading animation |
242
+ | `enableAnimations` | `boolean` | `true` | Enable animations |
243
+ | `colors.*` | `string` | varies | Custom color overrides |
244
+
245
+ #### Claude Code
246
+
247
+ | Option | Type | Default | Description |
248
+ |--------|------|---------|-------------|
249
+ | `executablePath` | `string` | `claude` | Path to Claude Code |
250
+ | `workingDirectory` | `string` | `null` | Default working directory |
251
+ | `defaultArgs` | `string[]` | `[]` | CLI arguments to pass |
252
+ | `shutdownTimeout` | `number` | `5000` | Graceful shutdown timeout (ms) |
253
+
254
+ #### App
255
+
256
+ | Option | Type | Default | Description |
257
+ |--------|------|---------|-------------|
258
+ | `maxScoresPerGame` | `number` | `10` | Leaderboard entries to keep |
259
+ | `defaultGame` | `string` | `null` | Auto-select game on start |
260
+ | `debugMode` | `boolean` | `false` | Enable debug output |
261
+ | `logLevel` | `error` \| `warn` \| `info` \| `debug` | `info` | Log verbosity |
262
+
263
+ ## Themes
264
+
265
+ BrainRot CLI includes four color themes:
266
+
267
+ | Theme | Description |
268
+ |-------|-------------|
269
+ | `default` | Modern terminal - cyan/magenta/yellow |
270
+ | `dark` | Muted colors for extended sessions |
271
+ | `light` | High contrast for light backgrounds |
272
+ | `retro` | Classic green phosphor terminal |
273
+
274
+ Switch themes via settings menu (`Ctrl+S`) or CLI flag:
275
+
276
+ ```bash
277
+ brainrot --color-scheme retro
278
+ ```
279
+
280
+ ## CLI Flags
281
+
282
+ ```
283
+ USAGE:
284
+ brainrot [OPTIONS]
285
+
286
+ OPTIONS:
287
+ -h, --help Show help message and exit
288
+ -v, --version Show version and exit
289
+ -c, --config <path> Use custom config file path
290
+
291
+ LAYOUT OPTIONS:
292
+ --layout-direction <dir> Split direction: horizontal, vertical
293
+ --split-ratio <ratio> Split ratio (0.0-1.0)
294
+
295
+ THEME OPTIONS:
296
+ --color-scheme <scheme> Color scheme: default, dark, light, retro
297
+ --border-style <style> Border style: single, round, double, heavy
298
+
299
+ CLAUDE CODE OPTIONS:
300
+ --claude-executable <path> Path to Claude Code executable
301
+ --claude-args <args> Arguments to pass (comma-separated)
302
+ -w, --working-dir <path> Working directory for Claude Code
303
+
304
+ APP OPTIONS:
305
+ -d, --debug Enable debug mode
306
+ --log-level <level> Log level: error, warn, info, debug
307
+ -g, --default-game <id> Default game: snake, tetris, pong, minesweeper
308
+ ```
309
+
310
+ ### Examples
311
+
312
+ ```bash
313
+ # Start with vertical layout and 70% game pane
314
+ brainrot --layout-direction vertical --split-ratio 0.7
315
+
316
+ # Use retro theme with heavy borders
317
+ brainrot --color-scheme retro --border-style heavy
318
+
319
+ # Debug mode with verbose logging
320
+ brainrot --debug --log-level debug
321
+
322
+ # Custom config file
323
+ brainrot -c ~/.my-brainrot-config.json
324
+
325
+ # Pass arguments to Claude Code
326
+ brainrot --claude-args "--model,claude-3-opus"
327
+ ```
328
+
329
+ ## Troubleshooting
330
+
331
+ ### Claude Code not found
332
+
333
+ If you see "claude: command not found":
334
+
335
+ 1. Ensure Claude Code is installed
336
+ 2. Add it to your PATH, or use `--claude-executable` to specify the full path:
337
+ ```bash
338
+ brainrot --claude-executable /path/to/claude
339
+ ```
340
+
341
+ ### Terminal too small
342
+
343
+ Games require minimum terminal dimensions. If you see dimension warnings:
344
+
345
+ 1. Resize your terminal window
346
+ 2. Or try vertical layout which may fit better:
347
+ ```bash
348
+ brainrot --layout-direction vertical
349
+ ```
350
+
351
+ ### Configuration not saving
352
+
353
+ Ensure you have write permissions to the config directory:
354
+
355
+ ```bash
356
+ mkdir -p ~/.config/brainrot-cli
357
+ chmod 755 ~/.config/brainrot-cli
358
+ ```
359
+
360
+ ### Games not responding to input
361
+
362
+ Make sure the game pane has focus (use `Tab` to switch). The focused pane has a highlighted border.
363
+
364
+ ## Development
365
+
366
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
367
+
368
+ See [docs/GAME_DEVELOPMENT.md](docs/GAME_DEVELOPMENT.md) for creating new games.
369
+
370
+ ## License
371
+
372
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Achievement Notification Component
3
+ *
4
+ * Displays a notification when an achievement is unlocked.
5
+ * Supports queuing multiple achievements and auto-dismiss.
6
+ */
7
+ export interface AchievementNotificationProps {
8
+ /** Achievement IDs to display */
9
+ achievementIds: string[];
10
+ /** Callback when all notifications have been shown */
11
+ onComplete?: () => void;
12
+ /** Duration to show each notification (ms) */
13
+ duration?: number;
14
+ }
15
+ /**
16
+ * Achievement notification queue manager
17
+ */
18
+ export declare function AchievementNotification({ achievementIds, onComplete, duration, }: AchievementNotificationProps): import("react/jsx-runtime").JSX.Element | null;
19
+ /**
20
+ * Hook for managing achievement notifications
21
+ */
22
+ export declare function useAchievementNotifications(): {
23
+ addAchievements: (ids: string[]) => void;
24
+ NotificationComponent: import("react/jsx-runtime").JSX.Element | null;
25
+ hasNotifications: boolean;
26
+ };
27
+ export default AchievementNotification;
28
+ //# sourceMappingURL=AchievementNotification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AchievementNotification.d.ts","sourceRoot":"","sources":["../src/AchievementNotification.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,4BAA4B;IAC3C,iCAAiC;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAkCD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,cAAc,EACd,UAAU,EACV,QAAe,GAChB,EAAE,4BAA4B,kDA+B9B;AAED;;GAEG;AACH,wBAAgB,2BAA2B;2BAIC,MAAM,EAAE;;;EAuBnD;AAED,eAAe,uBAAuB,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Achievement Notification Component
4
+ *
5
+ * Displays a notification when an achievement is unlocked.
6
+ * Supports queuing multiple achievements and auto-dismiss.
7
+ */
8
+ import { Box, Text } from "ink";
9
+ import { useState, useEffect, useCallback } from "react";
10
+ import { getAchievementById } from "./stats.js";
11
+ import { useThemeColors } from "./useTheme.js";
12
+ /**
13
+ * Single achievement notification display
14
+ */
15
+ function AchievementBanner({ achievement }) {
16
+ const colors = useThemeColors();
17
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "double", borderColor: colors.warning, paddingX: 2, paddingY: 1, alignItems: "center", children: [_jsx(Box, { children: _jsxs(Text, { color: colors.warning, bold: true, children: [achievement.icon, " ACHIEVEMENT UNLOCKED ", achievement.icon] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: colors.primary, children: achievement.name }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: achievement.description }) })] }));
18
+ }
19
+ /**
20
+ * Achievement notification queue manager
21
+ */
22
+ export function AchievementNotification({ achievementIds, onComplete, duration = 3000, }) {
23
+ const [currentIndex, setCurrentIndex] = useState(0);
24
+ const [currentAchievement, setCurrentAchievement] = useState(null);
25
+ // Get current achievement details
26
+ useEffect(() => {
27
+ if (currentIndex < achievementIds.length) {
28
+ const achievement = getAchievementById(achievementIds[currentIndex]);
29
+ setCurrentAchievement(achievement ?? null);
30
+ }
31
+ else {
32
+ setCurrentAchievement(null);
33
+ onComplete?.();
34
+ }
35
+ }, [currentIndex, achievementIds, onComplete]);
36
+ // Auto-advance to next achievement
37
+ useEffect(() => {
38
+ if (!currentAchievement)
39
+ return;
40
+ const timer = setTimeout(() => {
41
+ setCurrentIndex((prev) => prev + 1);
42
+ }, duration);
43
+ return () => clearTimeout(timer);
44
+ }, [currentAchievement, duration]);
45
+ if (!currentAchievement) {
46
+ return null;
47
+ }
48
+ return _jsx(AchievementBanner, { achievement: currentAchievement });
49
+ }
50
+ /**
51
+ * Hook for managing achievement notifications
52
+ */
53
+ export function useAchievementNotifications() {
54
+ const [queue, setQueue] = useState([]);
55
+ const [isShowing, setIsShowing] = useState(false);
56
+ const addAchievements = useCallback((ids) => {
57
+ if (ids.length === 0)
58
+ return;
59
+ setQueue((prev) => [...prev, ...ids]);
60
+ setIsShowing(true);
61
+ }, []);
62
+ const handleComplete = useCallback(() => {
63
+ setQueue([]);
64
+ setIsShowing(false);
65
+ }, []);
66
+ const NotificationComponent = isShowing && queue.length > 0 ? (_jsx(AchievementNotification, { achievementIds: queue, onComplete: handleComplete })) : null;
67
+ return {
68
+ addAchievements,
69
+ NotificationComponent,
70
+ hasNotifications: isShowing && queue.length > 0,
71
+ };
72
+ }
73
+ export default AchievementNotification;
74
+ //# sourceMappingURL=AchievementNotification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AchievementNotification.js","sourceRoot":"","sources":["../src/AchievementNotification.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * GameSelector Component
3
+ *
4
+ * A menu component for selecting and launching games.
5
+ * Supports keyboard navigation with arrow keys and Enter to select.
6
+ */
7
+ import type { GameInfo, GameDimensions } from "./game-types.js";
8
+ export interface GameSelectorProps {
9
+ /** Available games to select from */
10
+ games: GameInfo[];
11
+ /** Whether the selector has keyboard focus */
12
+ hasFocus: boolean;
13
+ /** Available dimensions */
14
+ dimensions: GameDimensions;
15
+ /** Callback when a game is selected */
16
+ onSelectGame: (gameId: string) => void;
17
+ /** Callback when stats menu is requested */
18
+ onOpenStats?: () => void;
19
+ }
20
+ /**
21
+ * Game selector menu component
22
+ */
23
+ export declare function GameSelector({ games, hasFocus, dimensions, onSelectGame, onOpenStats, }: GameSelectorProps): import("react/jsx-runtime").JSX.Element;
24
+ export default GameSelector;
25
+ //# sourceMappingURL=GameSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GameSelector.d.ts","sourceRoot":"","sources":["../src/GameSelector.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKhE,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,2BAA2B;IAC3B,UAAU,EAAE,cAAc,CAAC;IAC3B,uCAAuC;IACvC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAgHD;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,WAAW,GACZ,EAAE,iBAAiB,2CA8GnB;AAED,eAAe,YAAY,CAAC"}
@@ -0,0 +1,105 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * GameSelector Component
4
+ *
5
+ * A menu component for selecting and launching games.
6
+ * Supports keyboard navigation with arrow keys and Enter to select.
7
+ */
8
+ import { Box, Text, useInput } from "ink";
9
+ import { useState, useCallback, useEffect } from "react";
10
+ import { navIcons } from "./theme.js";
11
+ import { useThemeColors } from "./useTheme.js";
12
+ import { getAchievementCount } from "./stats.js";
13
+ function GameCard({ game, isSelected, isHighlighted, dimensions }) {
14
+ const colors = useThemeColors();
15
+ const borderColor = isHighlighted ? colors.primary : isSelected ? colors.accent : colors.border;
16
+ const titleColor = isHighlighted ? colors.primary : isSelected ? colors.accent : colors.text;
17
+ // Calculate card width based on available space
18
+ const cardWidth = Math.min(Math.max(dimensions.width - 4, 30), 50);
19
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: borderColor, paddingX: 1, width: cardWidth, children: [_jsx(Box, { children: _jsxs(Text, { bold: true, color: titleColor, children: [isHighlighted ? `${navIcons.arrowRight} ` : " ", game.name] }) }), _jsx(Text, { dimColor: true, wrap: "truncate", children: game.description }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: colors.textMuted, children: "Controls: " }), _jsx(Text, { dimColor: true, children: game.controls })] }), game.minWidth && game.minHeight && (_jsxs(Text, { dimColor: true, children: ["Min size: ", game.minWidth, "x", game.minHeight] }))] }));
20
+ }
21
+ function SelectorHeader({ hasFocus }) {
22
+ const colors = useThemeColors();
23
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: colors.primary, children: "Select a Game" }), _jsx(Text, { dimColor: true, children: hasFocus
24
+ ? "↑/↓: Navigate | Enter: Select | S: Stats | Q: Back"
25
+ : "Press Tab to focus game selector" })] }));
26
+ }
27
+ function StatsMenuCard({ isHighlighted, dimensions, achievementCount }) {
28
+ const colors = useThemeColors();
29
+ const borderColor = isHighlighted ? colors.warning : colors.border;
30
+ const titleColor = isHighlighted ? colors.warning : colors.textMuted;
31
+ const cardWidth = Math.min(Math.max(dimensions.width - 4, 30), 50);
32
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: borderColor, paddingX: 1, width: cardWidth, children: [_jsx(Box, { children: _jsxs(Text, { bold: true, color: titleColor, children: [isHighlighted ? `${navIcons.arrowRight} ` : " ", "Stats & Achievements"] }) }), _jsx(Text, { dimColor: true, children: "View your gameplay statistics and unlock achievements" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: colors.textMuted, children: "Progress: " }), _jsxs(Text, { color: colors.success, children: [achievementCount.unlocked, "/", achievementCount.total, " achievements"] })] })] }));
33
+ }
34
+ function EmptyState() {
35
+ const colors = useThemeColors();
36
+ return (_jsxs(Box, { flexDirection: "column", padding: 2, children: [_jsx(Text, { color: colors.accent, children: "No games available" }), _jsx(Text, { dimColor: true, children: "Check back later for new games!" })] }));
37
+ }
38
+ /**
39
+ * Game selector menu component
40
+ */
41
+ export function GameSelector({ games, hasFocus, dimensions, onSelectGame, onOpenStats, }) {
42
+ const [selectedIndex, setSelectedIndex] = useState(0);
43
+ const [achievementCount, setAchievementCount] = useState({ unlocked: 0, total: 0 });
44
+ // Total items: games + stats menu
45
+ const totalItems = games.length + 1;
46
+ const statsIndex = games.length; // Stats is always last
47
+ // Load achievement count
48
+ useEffect(() => {
49
+ const loadCount = async () => {
50
+ const count = await getAchievementCount();
51
+ setAchievementCount(count);
52
+ };
53
+ void loadCount();
54
+ }, []);
55
+ const handleSelect = useCallback(() => {
56
+ if (selectedIndex === statsIndex) {
57
+ onOpenStats?.();
58
+ }
59
+ else if (games.length > 0 && games[selectedIndex]) {
60
+ onSelectGame(games[selectedIndex].id);
61
+ }
62
+ }, [games, selectedIndex, onSelectGame, onOpenStats, statsIndex]);
63
+ useInput((input, key) => {
64
+ if (!hasFocus)
65
+ return;
66
+ // Navigate up
67
+ if (key.upArrow || input === "k") {
68
+ setSelectedIndex((prev) => (prev > 0 ? prev - 1 : totalItems - 1));
69
+ return;
70
+ }
71
+ // Navigate down
72
+ if (key.downArrow || input === "j") {
73
+ setSelectedIndex((prev) => (prev < totalItems - 1 ? prev + 1 : 0));
74
+ return;
75
+ }
76
+ // Select item
77
+ if (key.return || input === " ") {
78
+ handleSelect();
79
+ return;
80
+ }
81
+ // Quick open stats with S key
82
+ if (input === "s" || input === "S") {
83
+ onOpenStats?.();
84
+ return;
85
+ }
86
+ // Quick select game by number (1-9)
87
+ const num = parseInt(input, 10);
88
+ if (!isNaN(num) && num >= 1 && num <= games.length) {
89
+ setSelectedIndex(num - 1);
90
+ if (games[num - 1]) {
91
+ onSelectGame(games[num - 1].id);
92
+ }
93
+ return;
94
+ }
95
+ }, { isActive: hasFocus });
96
+ // Keep selected index in bounds
97
+ if (selectedIndex >= totalItems && totalItems > 0) {
98
+ setSelectedIndex(totalItems - 1);
99
+ }
100
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, height: "100%", children: [_jsx(SelectorHeader, { hasFocus: hasFocus }), games.length === 0 ? (_jsx(EmptyState, {})) : (_jsxs(Box, { flexDirection: "column", gap: 1, children: [games.map((game, index) => (_jsx(GameCard, { game: game, isSelected: index === selectedIndex, isHighlighted: hasFocus && index === selectedIndex, dimensions: dimensions }, game.id))), _jsx(StatsMenuCard, { isHighlighted: hasFocus && selectedIndex === statsIndex, dimensions: dimensions, achievementCount: achievementCount })] })), totalItems > 0 && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: selectedIndex === statsIndex
101
+ ? "Stats & Achievements"
102
+ : `Game ${selectedIndex + 1} of ${games.length}` }) }))] }));
103
+ }
104
+ export default GameSelector;
105
+ //# sourceMappingURL=GameSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GameSelector.js","sourceRoot":"","sources":["../src/GameSelector.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * HelpOverlay Component
3
+ *
4
+ * Modal overlay that displays comprehensive keyboard shortcuts organized by context.
5
+ * Triggered by ? or F1 key globally.
6
+ */
7
+ export interface HelpOverlayProps {
8
+ /** Whether the overlay has focus */
9
+ hasFocus: boolean;
10
+ /** Callback to close the overlay */
11
+ onClose: () => void;
12
+ }
13
+ export declare function HelpOverlay({ hasFocus, onClose }: HelpOverlayProps): import("react/jsx-runtime").JSX.Element;
14
+ export default HelpOverlay;
15
+ //# sourceMappingURL=HelpOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HelpOverlay.d.ts","sourceRoot":"","sources":["../src/HelpOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,oCAAoC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA+ID,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CAoFlE;AAED,eAAe,WAAW,CAAC"}