@compilr-dev/cli 0.4.0 → 0.5.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 (315) hide show
  1. package/README.md +30 -12
  2. package/dist/agent.d.ts +74 -1
  3. package/dist/agent.js +259 -76
  4. package/dist/anchors/index.d.ts +9 -0
  5. package/dist/anchors/index.js +9 -0
  6. package/dist/anchors/project-anchors.d.ts +79 -0
  7. package/dist/anchors/project-anchors.js +202 -0
  8. package/dist/commands/handler-types.d.ts +68 -0
  9. package/dist/commands/handler-types.js +8 -0
  10. package/dist/commands/handlers/agent-commands.d.ts +13 -0
  11. package/dist/commands/handlers/agent-commands.js +305 -0
  12. package/dist/commands/handlers/design-commands.d.ts +15 -0
  13. package/dist/commands/handlers/design-commands.js +334 -0
  14. package/dist/commands/handlers/index.d.ts +20 -0
  15. package/dist/commands/handlers/index.js +43 -0
  16. package/dist/commands/handlers/overlay-commands.d.ts +21 -0
  17. package/dist/commands/handlers/overlay-commands.js +287 -0
  18. package/dist/commands/handlers/project-commands.d.ts +11 -0
  19. package/dist/commands/handlers/project-commands.js +167 -0
  20. package/dist/commands/handlers/simple-commands.d.ts +19 -0
  21. package/dist/commands/handlers/simple-commands.js +144 -0
  22. package/dist/commands/index.d.ts +2 -1
  23. package/dist/commands/registry.d.ts +50 -0
  24. package/dist/commands/registry.js +75 -0
  25. package/dist/commands-v2/handlers/context.d.ts +13 -0
  26. package/dist/commands-v2/handlers/context.js +348 -0
  27. package/dist/commands-v2/handlers/core.d.ts +13 -0
  28. package/dist/commands-v2/handlers/core.js +165 -0
  29. package/dist/commands-v2/handlers/debug.d.ts +11 -0
  30. package/dist/commands-v2/handlers/debug.js +159 -0
  31. package/dist/commands-v2/handlers/index.d.ts +12 -0
  32. package/dist/commands-v2/handlers/index.js +24 -0
  33. package/dist/commands-v2/handlers/project.d.ts +22 -0
  34. package/dist/commands-v2/handlers/project.js +814 -0
  35. package/dist/commands-v2/handlers/settings.d.ts +15 -0
  36. package/dist/commands-v2/handlers/settings.js +235 -0
  37. package/dist/commands-v2/index.d.ts +13 -0
  38. package/dist/commands-v2/index.js +15 -0
  39. package/dist/commands-v2/registry.d.ts +37 -0
  40. package/dist/commands-v2/registry.js +80 -0
  41. package/dist/commands-v2/types.d.ts +75 -0
  42. package/dist/commands-v2/types.js +7 -0
  43. package/dist/commands.js +110 -7
  44. package/dist/index.js +288 -29
  45. package/dist/input-handlers/index.d.ts +7 -0
  46. package/dist/input-handlers/index.js +7 -0
  47. package/dist/input-handlers/memory-handler.d.ts +26 -0
  48. package/dist/input-handlers/memory-handler.js +68 -0
  49. package/dist/repl-helpers.d.ts +63 -0
  50. package/dist/repl-helpers.js +318 -0
  51. package/dist/repl-v2.d.ts +155 -0
  52. package/dist/repl-v2.js +774 -0
  53. package/dist/repl.d.ts +32 -4
  54. package/dist/repl.js +250 -977
  55. package/dist/settings/index.d.ts +23 -0
  56. package/dist/settings/index.js +48 -0
  57. package/dist/settings/paths.d.ts +110 -0
  58. package/dist/settings/paths.js +264 -0
  59. package/dist/templates/compilr-md.js +7 -4
  60. package/dist/templates/index.js +3 -4
  61. package/dist/themes/colors.js +3 -1
  62. package/dist/themes/registry.d.ts +5 -36
  63. package/dist/themes/registry.js +11 -95
  64. package/dist/themes/types.d.ts +3 -38
  65. package/dist/themes/types.js +2 -2
  66. package/dist/tools/anchor-tools.d.ts +31 -0
  67. package/dist/tools/anchor-tools.js +255 -0
  68. package/dist/tools/backlog-wrappers.d.ts +54 -0
  69. package/dist/tools/backlog-wrappers.js +338 -0
  70. package/dist/tools/backlog.js +1 -1
  71. package/dist/tools/db-tools.d.ts +65 -0
  72. package/dist/tools/db-tools.js +19 -0
  73. package/dist/tools/document-db.d.ts +43 -0
  74. package/dist/tools/document-db.js +220 -0
  75. package/dist/tools/project-db.d.ts +102 -0
  76. package/dist/tools/project-db.js +370 -0
  77. package/dist/tools/workitem-db.d.ts +103 -0
  78. package/dist/tools/workitem-db.js +549 -0
  79. package/dist/tools.js +13 -3
  80. package/dist/ui/agents-overlay-v2.d.ts +43 -0
  81. package/dist/ui/agents-overlay-v2.js +809 -0
  82. package/dist/ui/agents-overlay.d.ts +5 -5
  83. package/dist/ui/agents-overlay.js +782 -420
  84. package/dist/ui/anchors-overlay.d.ts +12 -0
  85. package/dist/ui/anchors-overlay.js +775 -0
  86. package/dist/ui/arch-type-overlay.d.ts +1 -6
  87. package/dist/ui/arch-type-overlay.js +175 -203
  88. package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
  89. package/dist/ui/ask-user-overlay-v2.js +555 -0
  90. package/dist/ui/ask-user-overlay.d.ts +2 -2
  91. package/dist/ui/ask-user-overlay.js +443 -535
  92. package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
  93. package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
  94. package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
  95. package/dist/ui/ask-user-simple-overlay.js +182 -209
  96. package/dist/ui/backlog-overlay.d.ts +16 -1
  97. package/dist/ui/backlog-overlay.js +525 -659
  98. package/dist/ui/base/index.d.ts +26 -0
  99. package/dist/ui/base/index.js +33 -0
  100. package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
  101. package/dist/ui/base/inline-overlay-utils.js +320 -0
  102. package/dist/ui/base/inline-overlay.d.ts +159 -0
  103. package/dist/ui/base/inline-overlay.js +257 -0
  104. package/dist/ui/base/key-utils.d.ts +15 -0
  105. package/dist/ui/base/key-utils.js +30 -0
  106. package/dist/ui/base/overlay-base-v2.d.ts +193 -0
  107. package/dist/ui/base/overlay-base-v2.js +246 -0
  108. package/dist/ui/base/overlay-base.d.ts +156 -0
  109. package/dist/ui/base/overlay-base.js +238 -0
  110. package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
  111. package/dist/ui/base/overlay-lifecycle.js +159 -0
  112. package/dist/ui/base/overlay-types.d.ts +185 -0
  113. package/dist/ui/base/overlay-types.js +7 -0
  114. package/dist/ui/base/render-utils.d.ts +8 -0
  115. package/dist/ui/base/render-utils.js +11 -0
  116. package/dist/ui/base/screen-stack.d.ts +148 -0
  117. package/dist/ui/base/screen-stack.js +184 -0
  118. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
  119. package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
  120. package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
  121. package/dist/ui/base/tabbed-list-overlay.js +369 -0
  122. package/dist/ui/commands-overlay-v2.d.ts +33 -0
  123. package/dist/ui/commands-overlay-v2.js +441 -0
  124. package/dist/ui/commands-overlay.d.ts +7 -2
  125. package/dist/ui/commands-overlay.js +384 -355
  126. package/dist/ui/config-overlay.d.ts +5 -4
  127. package/dist/ui/config-overlay.js +243 -513
  128. package/dist/ui/conversation.d.ts +75 -4
  129. package/dist/ui/conversation.js +374 -161
  130. package/dist/ui/docs-overlay.d.ts +17 -0
  131. package/dist/ui/docs-overlay.js +303 -0
  132. package/dist/ui/ephemeral.d.ts +1 -1
  133. package/dist/ui/ephemeral.js +1 -1
  134. package/dist/ui/features/index.d.ts +34 -0
  135. package/dist/ui/features/index.js +34 -0
  136. package/dist/ui/features/input-feature.d.ts +85 -0
  137. package/dist/ui/features/input-feature.js +238 -0
  138. package/dist/ui/features/list-feature.d.ts +155 -0
  139. package/dist/ui/features/list-feature.js +244 -0
  140. package/dist/ui/features/pagination-feature.d.ts +154 -0
  141. package/dist/ui/features/pagination-feature.js +238 -0
  142. package/dist/ui/features/search-feature.d.ts +148 -0
  143. package/dist/ui/features/search-feature.js +185 -0
  144. package/dist/ui/features/tab-feature.d.ts +194 -0
  145. package/dist/ui/features/tab-feature.js +307 -0
  146. package/dist/ui/footer-v2.d.ts +222 -0
  147. package/dist/ui/footer-v2.js +1349 -0
  148. package/dist/ui/footer.d.ts +107 -0
  149. package/dist/ui/footer.js +359 -67
  150. package/dist/ui/guardrail-overlay.d.ts +29 -0
  151. package/dist/ui/guardrail-overlay.js +145 -0
  152. package/dist/ui/help-overlay-v2.d.ts +34 -0
  153. package/dist/ui/help-overlay-v2.js +309 -0
  154. package/dist/ui/help-overlay.d.ts +16 -0
  155. package/dist/ui/help-overlay.js +316 -0
  156. package/dist/ui/index.d.ts +1 -1
  157. package/dist/ui/index.js +1 -3
  158. package/dist/ui/init-overlay-v2.d.ts +34 -0
  159. package/dist/ui/init-overlay-v2.js +600 -0
  160. package/dist/ui/init-overlay.d.ts +12 -2
  161. package/dist/ui/init-overlay.js +349 -270
  162. package/dist/ui/input-prompt-v2.d.ts +1 -0
  163. package/dist/ui/input-prompt-v2.js +14 -6
  164. package/dist/ui/input-prompt.d.ts +116 -33
  165. package/dist/ui/input-prompt.js +536 -337
  166. package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
  167. package/dist/ui/iteration-limit-overlay-v2.js +114 -0
  168. package/dist/ui/iteration-limit-overlay.d.ts +2 -2
  169. package/dist/ui/iteration-limit-overlay.js +92 -128
  170. package/dist/ui/keys-overlay-v2.d.ts +41 -0
  171. package/dist/ui/keys-overlay-v2.js +248 -0
  172. package/dist/ui/keys-overlay.d.ts +1 -0
  173. package/dist/ui/keys-overlay.js +203 -141
  174. package/dist/ui/line-utils.d.ts +88 -0
  175. package/dist/ui/line-utils.js +150 -0
  176. package/dist/ui/live-region.d.ts +161 -0
  177. package/dist/ui/live-region.js +387 -0
  178. package/dist/ui/mascot/expressions.d.ts +32 -0
  179. package/dist/ui/mascot/expressions.js +213 -0
  180. package/dist/ui/mascot/index.d.ts +8 -0
  181. package/dist/ui/mascot/index.js +8 -0
  182. package/dist/ui/mascot/renderer.d.ts +19 -0
  183. package/dist/ui/mascot/renderer.js +97 -0
  184. package/dist/ui/mascot-overlay-v2.d.ts +41 -0
  185. package/dist/ui/mascot-overlay-v2.js +138 -0
  186. package/dist/ui/mascot-overlay.d.ts +21 -0
  187. package/dist/ui/mascot-overlay.js +146 -0
  188. package/dist/ui/model-overlay-v2.d.ts +49 -0
  189. package/dist/ui/model-overlay-v2.js +118 -0
  190. package/dist/ui/model-overlay.d.ts +27 -0
  191. package/dist/ui/model-overlay.js +221 -0
  192. package/dist/ui/model-warning-overlay.js +3 -5
  193. package/dist/ui/new-overlay.d.ts +34 -0
  194. package/dist/ui/new-overlay.js +604 -0
  195. package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
  196. package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
  197. package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
  198. package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
  199. package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
  200. package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
  201. package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
  202. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
  203. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
  204. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
  205. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
  206. package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
  207. package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
  208. package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
  209. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
  210. package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
  211. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
  212. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
  213. package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
  214. package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
  215. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
  216. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
  217. package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
  218. package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
  219. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
  220. package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
  221. package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
  222. package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
  223. package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
  224. package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
  225. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
  226. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
  227. package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
  228. package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
  229. package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
  230. package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
  231. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
  232. package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
  233. package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
  234. package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
  235. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
  236. package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
  237. package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
  238. package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
  239. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
  240. package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
  241. package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
  242. package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
  243. package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
  244. package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
  245. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
  246. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
  247. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
  248. package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
  249. package/dist/ui/overlay/index.d.ts +33 -0
  250. package/dist/ui/overlay/index.js +35 -0
  251. package/dist/ui/overlay/key-utils.d.ts +6 -0
  252. package/dist/ui/overlay/key-utils.js +6 -0
  253. package/dist/ui/overlay/overlay-types.d.ts +128 -0
  254. package/dist/ui/overlay/overlay-types.js +22 -0
  255. package/dist/ui/overlay/types.d.ts +135 -0
  256. package/dist/ui/overlay/types.js +22 -0
  257. package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
  258. package/dist/ui/overlays/help-overlay-v2.js +198 -0
  259. package/dist/ui/overlays/index.d.ts +11 -0
  260. package/dist/ui/overlays/index.js +11 -0
  261. package/dist/ui/overlays.d.ts +0 -4
  262. package/dist/ui/overlays.js +0 -444
  263. package/dist/ui/permission-overlay-v2.d.ts +36 -0
  264. package/dist/ui/permission-overlay-v2.js +380 -0
  265. package/dist/ui/permission-overlay.d.ts +1 -1
  266. package/dist/ui/permission-overlay.js +186 -298
  267. package/dist/ui/projects-overlay.d.ts +19 -0
  268. package/dist/ui/projects-overlay.js +484 -0
  269. package/dist/ui/providers/types.d.ts +178 -0
  270. package/dist/ui/providers/types.js +9 -0
  271. package/dist/ui/render-modes.d.ts +36 -0
  272. package/dist/ui/render-modes.js +44 -0
  273. package/dist/ui/startup-menu.d.ts +36 -0
  274. package/dist/ui/startup-menu.js +236 -0
  275. package/dist/ui/subagent-renderer.d.ts +117 -0
  276. package/dist/ui/subagent-renderer.js +334 -0
  277. package/dist/ui/terminal-codes.d.ts +94 -0
  278. package/dist/ui/terminal-codes.js +124 -0
  279. package/dist/ui/terminal-renderer.d.ts +221 -0
  280. package/dist/ui/terminal-renderer.js +751 -0
  281. package/dist/ui/terminal-ui.d.ts +463 -0
  282. package/dist/ui/terminal-ui.js +2296 -0
  283. package/dist/ui/terminal.d.ts +20 -0
  284. package/dist/ui/terminal.js +72 -0
  285. package/dist/ui/theme-overlay-v2.d.ts +42 -0
  286. package/dist/ui/theme-overlay-v2.js +135 -0
  287. package/dist/ui/theme-overlay.d.ts +24 -0
  288. package/dist/ui/theme-overlay.js +127 -0
  289. package/dist/ui/todo-zone.js +53 -25
  290. package/dist/ui/tool-formatters.d.ts +16 -0
  291. package/dist/ui/tool-formatters.js +516 -0
  292. package/dist/ui/tools-overlay-v2.d.ts +47 -0
  293. package/dist/ui/tools-overlay-v2.js +218 -0
  294. package/dist/ui/tools-overlay.d.ts +10 -2
  295. package/dist/ui/tools-overlay.js +172 -220
  296. package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
  297. package/dist/ui/tutorial-overlay-v2.js +1035 -0
  298. package/dist/ui/tutorial-overlay.d.ts +1 -0
  299. package/dist/ui/tutorial-overlay.js +400 -302
  300. package/dist/ui/workflow-overlay.d.ts +22 -0
  301. package/dist/ui/workflow-overlay.js +636 -0
  302. package/dist/utils/debug-log.d.ts +28 -0
  303. package/dist/utils/debug-log.js +57 -0
  304. package/dist/utils/model-tiers.js +1 -1
  305. package/dist/utils/path-safety.d.ts +56 -0
  306. package/dist/utils/path-safety.js +239 -0
  307. package/dist/workflow/guided-mode-injector.d.ts +42 -0
  308. package/dist/workflow/guided-mode-injector.js +191 -0
  309. package/dist/workflow/index.d.ts +8 -0
  310. package/dist/workflow/index.js +8 -0
  311. package/dist/workflow/step-criteria.d.ts +62 -0
  312. package/dist/workflow/step-criteria.js +150 -0
  313. package/dist/workflow/step-tracker.d.ts +92 -0
  314. package/dist/workflow/step-tracker.js +141 -0
  315. package/package.json +12 -5
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Overlay Lifecycle Manager
3
+ *
4
+ * Handles the common setup and cleanup operations for all overlays:
5
+ * - Raw mode management
6
+ * - Cursor visibility
7
+ * - Event listener setup/teardown
8
+ * - Line clearing on close
9
+ */
10
+ import * as terminal from '../terminal.js';
11
+ import { pauseForOverlay, resumeAfterOverlay } from '../overlay-controller.js';
12
+ import { debugLog } from '../../utils/debug-log.js';
13
+ // =============================================================================
14
+ // OverlayLifecycle Class
15
+ // =============================================================================
16
+ /**
17
+ * Manages the lifecycle of an overlay.
18
+ *
19
+ * Usage:
20
+ * ```typescript
21
+ * const lifecycle = new OverlayLifecycle(config, (data) => handleKey(data));
22
+ *
23
+ * // Setup - call before first render
24
+ * lifecycle.setup();
25
+ *
26
+ * // ... overlay logic ...
27
+ *
28
+ * // Cleanup - call when closing
29
+ * lifecycle.cleanup(lineCount);
30
+ * ```
31
+ */
32
+ export class OverlayLifecycle {
33
+ config;
34
+ onKey;
35
+ wasRawMode = false;
36
+ dataHandler = null;
37
+ isActive = false;
38
+ constructor(config, onKey) {
39
+ this.config = config;
40
+ this.onKey = onKey;
41
+ }
42
+ // ===========================================================================
43
+ // Public Methods
44
+ // ===========================================================================
45
+ /**
46
+ * Setup the overlay for interaction.
47
+ * Call this before the first render.
48
+ */
49
+ setup() {
50
+ if (this.isActive) {
51
+ return; // Already set up
52
+ }
53
+ debugLog('OverlayLifecycle:setup', 'start');
54
+ // Pause footer animation and clear it
55
+ // This is done HERE (not in REPL) so constructor I/O doesn't cause blank screen
56
+ pauseForOverlay();
57
+ debugLog('OverlayLifecycle:setup', 'footer paused');
58
+ // Save current raw mode state
59
+ this.wasRawMode = process.stdin.isRaw;
60
+ // Enter raw mode for character-by-character input
61
+ terminal.enableRawMode();
62
+ // Hide cursor (unless config says not to)
63
+ if (this.config.hideCursor !== false) {
64
+ terminal.hideCursor();
65
+ }
66
+ // Setup key handler
67
+ this.dataHandler = (data) => {
68
+ if (this.isActive) {
69
+ this.onKey(data);
70
+ }
71
+ };
72
+ process.stdin.on('data', this.dataHandler);
73
+ this.isActive = true;
74
+ debugLog('OverlayLifecycle:setup', 'done');
75
+ }
76
+ /**
77
+ * Cleanup after overlay closes.
78
+ * Restores terminal state and removes event listeners.
79
+ *
80
+ * @param lineCount - Number of lines to clear (typically maxLineCount)
81
+ */
82
+ cleanup(lineCount) {
83
+ if (!this.isActive) {
84
+ return; // Already cleaned up
85
+ }
86
+ debugLog('OverlayLifecycle:cleanup', 'start');
87
+ this.isActive = false;
88
+ // Remove event listener
89
+ if (this.dataHandler) {
90
+ process.stdin.removeListener('data', this.dataHandler);
91
+ this.dataHandler = null;
92
+ }
93
+ // Clear the overlay content
94
+ if (lineCount > 0) {
95
+ terminal.clearLinesAbove(lineCount);
96
+ }
97
+ // Restore cursor visibility
98
+ if (this.config.hideCursor !== false) {
99
+ terminal.showCursor();
100
+ }
101
+ // Restore raw mode state
102
+ if (!this.wasRawMode) {
103
+ terminal.disableRawMode();
104
+ }
105
+ // Resume footer animation
106
+ resumeAfterOverlay();
107
+ debugLog('OverlayLifecycle:cleanup', 'footer resumed');
108
+ }
109
+ /**
110
+ * Check if the lifecycle is currently active.
111
+ */
112
+ isSetUp() {
113
+ return this.isActive;
114
+ }
115
+ }
116
+ // =============================================================================
117
+ // Standalone Helper Functions
118
+ // =============================================================================
119
+ /**
120
+ * Create a standard overlay setup without using the class.
121
+ * Returns a cleanup function.
122
+ *
123
+ * This is useful for simple overlays that don't need the full class.
124
+ *
125
+ * @param onKey - Key handler callback
126
+ * @param config - Optional configuration
127
+ * @returns Cleanup function
128
+ */
129
+ export function setupOverlay(onKey, config = {}) {
130
+ const wasRawMode = process.stdin.isRaw;
131
+ // Pause footer animation and clear it
132
+ pauseForOverlay();
133
+ // Enter raw mode
134
+ terminal.enableRawMode();
135
+ // Hide cursor
136
+ if (config.hideCursor !== false) {
137
+ terminal.hideCursor();
138
+ }
139
+ // Setup handler
140
+ const dataHandler = (data) => {
141
+ onKey(data);
142
+ };
143
+ process.stdin.on('data', dataHandler);
144
+ // Return cleanup function
145
+ return (lineCount = 0) => {
146
+ process.stdin.removeListener('data', dataHandler);
147
+ if (lineCount > 0) {
148
+ terminal.clearLinesAbove(lineCount);
149
+ }
150
+ if (config.hideCursor !== false) {
151
+ terminal.showCursor();
152
+ }
153
+ if (!wasRawMode) {
154
+ terminal.disableRawMode();
155
+ }
156
+ // Resume footer animation
157
+ resumeAfterOverlay();
158
+ };
159
+ }
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Overlay Type Definitions
3
+ *
4
+ * Core interfaces and types for the overlay system.
5
+ * These provide the foundation for BaseOverlay and composable features.
6
+ */
7
+ /**
8
+ * Result of handling a key press within a feature or overlay.
9
+ *
10
+ * - `handled: false` - Key was not handled, try next handler
11
+ * - `handled: true` - Key was handled
12
+ * - `action: 'render'` - State changed, re-render needed
13
+ * - `action: 'close'` - Overlay should close
14
+ * - No action - Key was consumed but no visual change
15
+ */
16
+ export type KeyResult = {
17
+ handled: false;
18
+ } | {
19
+ handled: true;
20
+ action?: 'render' | 'close';
21
+ };
22
+ /**
23
+ * Result of handling a key press within a screen.
24
+ *
25
+ * - `action: 'stay'` - Stay on current screen (optionally re-render)
26
+ * - `action: 'push'` - Push a new screen onto the stack
27
+ * - `action: 'pop'` - Go back to previous screen
28
+ * - `action: 'close'` - Close the entire overlay with a result
29
+ */
30
+ export type ScreenResult<TResult = unknown> = {
31
+ action: 'stay';
32
+ render?: boolean;
33
+ } | {
34
+ action: 'push';
35
+ screen: BaseScreenInterface;
36
+ } | {
37
+ action: 'pop';
38
+ } | {
39
+ action: 'close';
40
+ result: TResult;
41
+ };
42
+ /**
43
+ * Base state that all overlays must include.
44
+ * Tracks line counts for proper terminal clearing.
45
+ */
46
+ export interface OverlayState {
47
+ /** Current rendered line count */
48
+ lineCount: number;
49
+ /** Maximum line count seen (for clearing) */
50
+ maxLineCount: number;
51
+ }
52
+ /**
53
+ * State for list-based selection.
54
+ */
55
+ export interface ListState {
56
+ /** Currently selected index */
57
+ selectedIndex: number;
58
+ }
59
+ /**
60
+ * State for tabbed overlays.
61
+ */
62
+ export interface TabState {
63
+ /** Current tab index (0-based) */
64
+ currentTab: number;
65
+ }
66
+ /**
67
+ * State for paginated overlays.
68
+ */
69
+ export interface PaginationState {
70
+ /** Current page (0-based) */
71
+ currentPage: number;
72
+ /** Items per page */
73
+ pageSize: number;
74
+ /** Total number of items */
75
+ totalItems: number;
76
+ }
77
+ /**
78
+ * State for text input.
79
+ */
80
+ export interface InputState {
81
+ /** Current input buffer */
82
+ inputBuffer: string;
83
+ /** Whether input mode is active */
84
+ isInputMode: boolean;
85
+ /** Validation error message (if any) */
86
+ error?: string | null;
87
+ }
88
+ /**
89
+ * State for search functionality.
90
+ */
91
+ export interface SearchState {
92
+ /** Current search query */
93
+ searchQuery: string;
94
+ /** Whether search mode is active */
95
+ isSearchMode: boolean;
96
+ }
97
+ /**
98
+ * Configuration options for an overlay.
99
+ */
100
+ export interface OverlayConfig {
101
+ /** Minimum height in lines (for consistent sizing) */
102
+ minHeight?: number;
103
+ /** Whether to show border (default: true) */
104
+ showBorder?: boolean;
105
+ /** Whether to hide cursor during overlay (default: true) */
106
+ hideCursor?: boolean;
107
+ /** Whether to enable vim-style navigation (default: true) */
108
+ enableVimNav?: boolean;
109
+ /** Whether to enable number keys for tabs (default: true for tabbed overlays) */
110
+ enableNumberKeys?: boolean;
111
+ }
112
+ /**
113
+ * Tab definition for tabbed overlays.
114
+ */
115
+ export interface TabDefinition {
116
+ /** Unique identifier for the tab */
117
+ id: string;
118
+ /** Display label */
119
+ label: string;
120
+ /** Optional keyboard shortcut (1-9) */
121
+ shortcut?: number;
122
+ }
123
+ /**
124
+ * Interface for composable features.
125
+ * Features handle specific aspects of overlay behavior (list, tabs, pagination, etc.)
126
+ */
127
+ export interface Feature<TState = unknown> {
128
+ /**
129
+ * Handle a key press.
130
+ * @param data - Raw key buffer
131
+ * @param state - Current state (feature-specific portion)
132
+ * @returns KeyResult if handled, null if not handled
133
+ */
134
+ handleKey(data: Buffer, state: TState): KeyResult | null;
135
+ /**
136
+ * Optional render method for feature-specific content.
137
+ * @param state - Current state
138
+ * @returns Array of lines to render
139
+ */
140
+ render?(state: TState): string[];
141
+ }
142
+ /**
143
+ * Interface for screens in a multi-screen overlay.
144
+ */
145
+ export interface BaseScreenInterface {
146
+ /**
147
+ * Render the screen content.
148
+ * @returns Array of lines to render
149
+ */
150
+ render(): string[];
151
+ /**
152
+ * Handle a key press.
153
+ * @param data - Raw key buffer
154
+ * @returns ScreenResult indicating what action to take
155
+ */
156
+ handleKey(data: Buffer): ScreenResult;
157
+ /**
158
+ * Optional lifecycle hook called when screen becomes active.
159
+ */
160
+ onEnter?(): void;
161
+ /**
162
+ * Optional lifecycle hook called when screen is deactivated.
163
+ */
164
+ onExit?(): void;
165
+ /**
166
+ * Optional: Return minimum height for stable rendering.
167
+ * Override to prevent visual jitter when screen content varies.
168
+ */
169
+ getMinHeight?(): number;
170
+ }
171
+ /**
172
+ * Options for rendering an item in a list.
173
+ */
174
+ export interface ListItemRenderOptions<T> {
175
+ /** The item to render */
176
+ item: T;
177
+ /** Whether this item is selected */
178
+ isSelected: boolean;
179
+ /** Index in the list */
180
+ index: number;
181
+ }
182
+ /**
183
+ * Function type for custom list item rendering.
184
+ */
185
+ export type ListItemRenderer<T> = (options: ListItemRenderOptions<T>) => string;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Overlay Type Definitions
3
+ *
4
+ * Core interfaces and types for the overlay system.
5
+ * These provide the foundation for BaseOverlay and composable features.
6
+ */
7
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Render Utilities
3
+ *
4
+ * Re-exported from @compilr-dev/ui-core for consistency.
5
+ * CLI-specific aliases provided for backward compatibility.
6
+ */
7
+ export { renderBorder, wrapText, truncatePlain, truncateAnsi, normalizeText, padToHeight, emptyLines, padToWidth, } from '@compilr-dev/ui-core/utils';
8
+ export { truncatePlain as truncate } from '@compilr-dev/ui-core/utils';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Render Utilities
3
+ *
4
+ * Re-exported from @compilr-dev/ui-core for consistency.
5
+ * CLI-specific aliases provided for backward compatibility.
6
+ */
7
+ export { renderBorder, wrapText, truncatePlain, truncateAnsi, normalizeText, padToHeight, emptyLines, padToWidth, } from '@compilr-dev/ui-core/utils';
8
+ // Re-export truncatePlain as truncate for CLI compatibility
9
+ // (ui-core's truncate in ansi.ts is ANSI-aware with '...' suffix,
10
+ // CLI expects plain text truncate with '…' suffix)
11
+ export { truncatePlain as truncate } from '@compilr-dev/ui-core/utils';
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Screen Stack
3
+ *
4
+ * Navigation stack for multi-screen overlays.
5
+ * Enables proper "back" behavior where Esc goes to previous screen.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * class MyOverlay extends BaseOverlay<MyState, MyResult> {
10
+ * private screenStack = new ScreenStack();
11
+ *
12
+ * constructor() {
13
+ * super(initialState);
14
+ * this.screenStack.push(new ListScreen());
15
+ * }
16
+ *
17
+ * handleKey(data: Buffer): void {
18
+ * if (isEscape(data)) {
19
+ * if (this.screenStack.size() > 1) {
20
+ * this.screenStack.pop();
21
+ * this.update();
22
+ * } else {
23
+ * this.close(null);
24
+ * }
25
+ * return;
26
+ * }
27
+ *
28
+ * const result = this.screenStack.current()?.handleKey(data);
29
+ * this.handleScreenResult(result);
30
+ * }
31
+ *
32
+ * render(): string[] {
33
+ * return [
34
+ * ...this.renderHeader('My Overlay'),
35
+ * ...this.screenStack.current()?.render() ?? [],
36
+ * ...this.renderFooter(this.getCurrentHints())
37
+ * ];
38
+ * }
39
+ * }
40
+ * ```
41
+ */
42
+ import type { BaseScreenInterface, ScreenResult } from './overlay-types.js';
43
+ export type { BaseScreenInterface, ScreenResult };
44
+ /**
45
+ * Abstract base class for screens.
46
+ * Extend this to create screens for multi-screen overlays.
47
+ */
48
+ export declare abstract class BaseScreen implements BaseScreenInterface {
49
+ /**
50
+ * Render the screen content.
51
+ * @returns Array of lines to render
52
+ */
53
+ abstract render(): string[];
54
+ /**
55
+ * Handle a key press.
56
+ * @param data - Raw key buffer
57
+ * @returns ScreenResult indicating what action to take
58
+ */
59
+ abstract handleKey(data: Buffer): ScreenResult;
60
+ /**
61
+ * Optional lifecycle hook called when screen becomes active.
62
+ * Override to perform setup when navigating to this screen.
63
+ */
64
+ onEnter?(): void;
65
+ /**
66
+ * Optional lifecycle hook called when screen is deactivated.
67
+ * Override to perform cleanup when navigating away.
68
+ */
69
+ onExit?(): void;
70
+ /**
71
+ * Optional: Return minimum height for stable rendering.
72
+ * Override to prevent visual jitter when screen content varies.
73
+ * @returns Minimum number of lines this screen should occupy
74
+ */
75
+ getMinHeight(): number;
76
+ }
77
+ /**
78
+ * Stack-based navigation for multi-screen overlays.
79
+ *
80
+ * The stack maintains a history of screens, allowing:
81
+ * - push() to navigate forward to a new screen
82
+ * - pop() to go back to the previous screen
83
+ * - current() to get the active screen
84
+ */
85
+ export declare class ScreenStack {
86
+ private readonly screens;
87
+ /**
88
+ * Push a new screen onto the stack.
89
+ * Calls onExit() on current screen and onEnter() on new screen.
90
+ *
91
+ * @param screen - Screen to push
92
+ */
93
+ push(screen: BaseScreenInterface): void;
94
+ /**
95
+ * Pop the current screen and return to the previous one.
96
+ * Calls onExit() on popped screen and onEnter() on revealed screen.
97
+ *
98
+ * @returns The popped screen, or null if stack was empty
99
+ */
100
+ pop(): BaseScreenInterface | null;
101
+ /**
102
+ * Get the current (topmost) screen.
103
+ *
104
+ * @returns Current screen, or undefined if stack is empty
105
+ */
106
+ current(): BaseScreenInterface | undefined;
107
+ /**
108
+ * Get the number of screens in the stack.
109
+ */
110
+ size(): number;
111
+ /**
112
+ * Check if the stack is empty.
113
+ */
114
+ isEmpty(): boolean;
115
+ /**
116
+ * Check if there's more than one screen (can go back).
117
+ */
118
+ canGoBack(): boolean;
119
+ /**
120
+ * Clear all screens from the stack.
121
+ * Calls onExit() on each screen in reverse order.
122
+ */
123
+ clear(): void;
124
+ /**
125
+ * Replace the current screen with a new one.
126
+ * Useful for "replace" navigation (no back).
127
+ *
128
+ * @param screen - Screen to replace with
129
+ */
130
+ replace(screen: BaseScreenInterface): void;
131
+ }
132
+ /**
133
+ * Helper to create a ScreenResult for staying on the current screen.
134
+ */
135
+ export declare function stay(render?: boolean): ScreenResult;
136
+ /**
137
+ * Helper to create a ScreenResult for pushing a new screen.
138
+ */
139
+ export declare function pushScreen(screen: BaseScreenInterface): ScreenResult;
140
+ /**
141
+ * Helper to create a ScreenResult for popping the current screen.
142
+ */
143
+ export declare function popScreen(): ScreenResult;
144
+ /**
145
+ * Helper to create a ScreenResult for closing the overlay.
146
+ * Result is optional for void result types.
147
+ */
148
+ export declare function closeOverlay<T = void>(result?: T): ScreenResult<T>;
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Screen Stack
3
+ *
4
+ * Navigation stack for multi-screen overlays.
5
+ * Enables proper "back" behavior where Esc goes to previous screen.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * class MyOverlay extends BaseOverlay<MyState, MyResult> {
10
+ * private screenStack = new ScreenStack();
11
+ *
12
+ * constructor() {
13
+ * super(initialState);
14
+ * this.screenStack.push(new ListScreen());
15
+ * }
16
+ *
17
+ * handleKey(data: Buffer): void {
18
+ * if (isEscape(data)) {
19
+ * if (this.screenStack.size() > 1) {
20
+ * this.screenStack.pop();
21
+ * this.update();
22
+ * } else {
23
+ * this.close(null);
24
+ * }
25
+ * return;
26
+ * }
27
+ *
28
+ * const result = this.screenStack.current()?.handleKey(data);
29
+ * this.handleScreenResult(result);
30
+ * }
31
+ *
32
+ * render(): string[] {
33
+ * return [
34
+ * ...this.renderHeader('My Overlay'),
35
+ * ...this.screenStack.current()?.render() ?? [],
36
+ * ...this.renderFooter(this.getCurrentHints())
37
+ * ];
38
+ * }
39
+ * }
40
+ * ```
41
+ */
42
+ // =============================================================================
43
+ // BaseScreen Abstract Class
44
+ // =============================================================================
45
+ /**
46
+ * Abstract base class for screens.
47
+ * Extend this to create screens for multi-screen overlays.
48
+ */
49
+ export class BaseScreen {
50
+ /**
51
+ * Optional: Return minimum height for stable rendering.
52
+ * Override to prevent visual jitter when screen content varies.
53
+ * @returns Minimum number of lines this screen should occupy
54
+ */
55
+ getMinHeight() {
56
+ return 0; // Default: no minimum, use overlay's minHeight
57
+ }
58
+ }
59
+ // =============================================================================
60
+ // ScreenStack Class
61
+ // =============================================================================
62
+ /**
63
+ * Stack-based navigation for multi-screen overlays.
64
+ *
65
+ * The stack maintains a history of screens, allowing:
66
+ * - push() to navigate forward to a new screen
67
+ * - pop() to go back to the previous screen
68
+ * - current() to get the active screen
69
+ */
70
+ export class ScreenStack {
71
+ screens = [];
72
+ /**
73
+ * Push a new screen onto the stack.
74
+ * Calls onExit() on current screen and onEnter() on new screen.
75
+ *
76
+ * @param screen - Screen to push
77
+ */
78
+ push(screen) {
79
+ // Call exit hook on current screen
80
+ this.current()?.onExit?.();
81
+ // Push new screen
82
+ this.screens.push(screen);
83
+ // Call enter hook on new screen
84
+ screen.onEnter?.();
85
+ }
86
+ /**
87
+ * Pop the current screen and return to the previous one.
88
+ * Calls onExit() on popped screen and onEnter() on revealed screen.
89
+ *
90
+ * @returns The popped screen, or null if stack was empty
91
+ */
92
+ pop() {
93
+ if (this.screens.length === 0) {
94
+ return null;
95
+ }
96
+ // Pop and call exit hook
97
+ const screen = this.screens.pop();
98
+ if (screen) {
99
+ screen.onExit?.();
100
+ }
101
+ // Call enter hook on now-current screen
102
+ this.current()?.onEnter?.();
103
+ return screen ?? null;
104
+ }
105
+ /**
106
+ * Get the current (topmost) screen.
107
+ *
108
+ * @returns Current screen, or undefined if stack is empty
109
+ */
110
+ current() {
111
+ return this.screens[this.screens.length - 1];
112
+ }
113
+ /**
114
+ * Get the number of screens in the stack.
115
+ */
116
+ size() {
117
+ return this.screens.length;
118
+ }
119
+ /**
120
+ * Check if the stack is empty.
121
+ */
122
+ isEmpty() {
123
+ return this.screens.length === 0;
124
+ }
125
+ /**
126
+ * Check if there's more than one screen (can go back).
127
+ */
128
+ canGoBack() {
129
+ return this.screens.length > 1;
130
+ }
131
+ /**
132
+ * Clear all screens from the stack.
133
+ * Calls onExit() on each screen in reverse order.
134
+ */
135
+ clear() {
136
+ while (this.screens.length > 0) {
137
+ this.pop();
138
+ }
139
+ }
140
+ /**
141
+ * Replace the current screen with a new one.
142
+ * Useful for "replace" navigation (no back).
143
+ *
144
+ * @param screen - Screen to replace with
145
+ */
146
+ replace(screen) {
147
+ if (this.screens.length > 0) {
148
+ const current = this.screens.pop();
149
+ if (current) {
150
+ current.onExit?.();
151
+ }
152
+ }
153
+ this.screens.push(screen);
154
+ screen.onEnter?.();
155
+ }
156
+ }
157
+ // =============================================================================
158
+ // Helper Types
159
+ // =============================================================================
160
+ /**
161
+ * Helper to create a ScreenResult for staying on the current screen.
162
+ */
163
+ export function stay(render = true) {
164
+ return { action: 'stay', render };
165
+ }
166
+ /**
167
+ * Helper to create a ScreenResult for pushing a new screen.
168
+ */
169
+ export function pushScreen(screen) {
170
+ return { action: 'push', screen };
171
+ }
172
+ /**
173
+ * Helper to create a ScreenResult for popping the current screen.
174
+ */
175
+ export function popScreen() {
176
+ return { action: 'pop' };
177
+ }
178
+ /**
179
+ * Helper to create a ScreenResult for closing the overlay.
180
+ * Result is optional for void result types.
181
+ */
182
+ export function closeOverlay(result) {
183
+ return { action: 'close', result: result };
184
+ }