brainfile 0.18.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 (360) hide show
  1. package/README.md +222 -0
  2. package/dist/__tests__/helpers/v2.d.ts +12 -0
  3. package/dist/__tests__/helpers/v2.d.ts.map +1 -0
  4. package/dist/__tests__/helpers/v2.js +73 -0
  5. package/dist/__tests__/helpers/v2.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +480 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/add.d.ts +34 -0
  11. package/dist/commands/add.d.ts.map +1 -0
  12. package/dist/commands/add.js +255 -0
  13. package/dist/commands/add.js.map +1 -0
  14. package/dist/commands/adr.d.ts +22 -0
  15. package/dist/commands/adr.d.ts.map +1 -0
  16. package/dist/commands/adr.js +195 -0
  17. package/dist/commands/adr.js.map +1 -0
  18. package/dist/commands/archive.d.ts +20 -0
  19. package/dist/commands/archive.d.ts.map +1 -0
  20. package/dist/commands/archive.js +590 -0
  21. package/dist/commands/archive.js.map +1 -0
  22. package/dist/commands/auth.d.ts +26 -0
  23. package/dist/commands/auth.d.ts.map +1 -0
  24. package/dist/commands/auth.js +245 -0
  25. package/dist/commands/auth.js.map +1 -0
  26. package/dist/commands/complete.d.ts +30 -0
  27. package/dist/commands/complete.d.ts.map +1 -0
  28. package/dist/commands/complete.js +267 -0
  29. package/dist/commands/complete.js.map +1 -0
  30. package/dist/commands/config.d.ts +29 -0
  31. package/dist/commands/config.d.ts.map +1 -0
  32. package/dist/commands/config.js +210 -0
  33. package/dist/commands/config.js.map +1 -0
  34. package/dist/commands/contract.d.ts +84 -0
  35. package/dist/commands/contract.d.ts.map +1 -0
  36. package/dist/commands/contract.js +715 -0
  37. package/dist/commands/contract.js.map +1 -0
  38. package/dist/commands/delete.d.ts +8 -0
  39. package/dist/commands/delete.d.ts.map +1 -0
  40. package/dist/commands/delete.js +139 -0
  41. package/dist/commands/delete.js.map +1 -0
  42. package/dist/commands/hooks.d.ts +35 -0
  43. package/dist/commands/hooks.d.ts.map +1 -0
  44. package/dist/commands/hooks.js +324 -0
  45. package/dist/commands/hooks.js.map +1 -0
  46. package/dist/commands/init.d.ts +7 -0
  47. package/dist/commands/init.d.ts.map +1 -0
  48. package/dist/commands/init.js +118 -0
  49. package/dist/commands/init.js.map +1 -0
  50. package/dist/commands/lint.d.ts +16 -0
  51. package/dist/commands/lint.d.ts.map +1 -0
  52. package/dist/commands/lint.js +123 -0
  53. package/dist/commands/lint.js.map +1 -0
  54. package/dist/commands/list.d.ts +20 -0
  55. package/dist/commands/list.d.ts.map +1 -0
  56. package/dist/commands/list.js +175 -0
  57. package/dist/commands/list.js.map +1 -0
  58. package/dist/commands/log.d.ts +52 -0
  59. package/dist/commands/log.d.ts.map +1 -0
  60. package/dist/commands/log.js +246 -0
  61. package/dist/commands/log.js.map +1 -0
  62. package/dist/commands/mcp.d.ts +3 -0
  63. package/dist/commands/mcp.d.ts.map +1 -0
  64. package/dist/commands/mcp.js +96 -0
  65. package/dist/commands/mcp.js.map +1 -0
  66. package/dist/commands/migrate.d.ts +16 -0
  67. package/dist/commands/migrate.d.ts.map +1 -0
  68. package/dist/commands/migrate.js +388 -0
  69. package/dist/commands/migrate.js.map +1 -0
  70. package/dist/commands/move.d.ts +16 -0
  71. package/dist/commands/move.d.ts.map +1 -0
  72. package/dist/commands/move.js +225 -0
  73. package/dist/commands/move.js.map +1 -0
  74. package/dist/commands/patch.d.ts +17 -0
  75. package/dist/commands/patch.d.ts.map +1 -0
  76. package/dist/commands/patch.js +226 -0
  77. package/dist/commands/patch.js.map +1 -0
  78. package/dist/commands/restore.d.ts +8 -0
  79. package/dist/commands/restore.d.ts.map +1 -0
  80. package/dist/commands/restore.js +111 -0
  81. package/dist/commands/restore.js.map +1 -0
  82. package/dist/commands/rules.d.ts +68 -0
  83. package/dist/commands/rules.d.ts.map +1 -0
  84. package/dist/commands/rules.js +322 -0
  85. package/dist/commands/rules.js.map +1 -0
  86. package/dist/commands/schema.d.ts +31 -0
  87. package/dist/commands/schema.d.ts.map +1 -0
  88. package/dist/commands/schema.js +374 -0
  89. package/dist/commands/schema.js.map +1 -0
  90. package/dist/commands/search.d.ts +33 -0
  91. package/dist/commands/search.d.ts.map +1 -0
  92. package/dist/commands/search.js +209 -0
  93. package/dist/commands/search.js.map +1 -0
  94. package/dist/commands/show.d.ts +20 -0
  95. package/dist/commands/show.d.ts.map +1 -0
  96. package/dist/commands/show.js +272 -0
  97. package/dist/commands/show.js.map +1 -0
  98. package/dist/commands/subtask.d.ts +12 -0
  99. package/dist/commands/subtask.d.ts.map +1 -0
  100. package/dist/commands/subtask.js +212 -0
  101. package/dist/commands/subtask.js.map +1 -0
  102. package/dist/commands/template.d.ts +17 -0
  103. package/dist/commands/template.d.ts.map +1 -0
  104. package/dist/commands/template.js +149 -0
  105. package/dist/commands/template.js.map +1 -0
  106. package/dist/commands/tui.d.ts +6 -0
  107. package/dist/commands/tui.d.ts.map +1 -0
  108. package/dist/commands/tui.js +79 -0
  109. package/dist/commands/tui.js.map +1 -0
  110. package/dist/commands/types.d.ts +40 -0
  111. package/dist/commands/types.d.ts.map +1 -0
  112. package/dist/commands/types.js +242 -0
  113. package/dist/commands/types.js.map +1 -0
  114. package/dist/index.d.ts +10 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.js +29 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/lib/contractRunner.d.ts +59 -0
  119. package/dist/lib/contractRunner.d.ts.map +1 -0
  120. package/dist/lib/contractRunner.js +511 -0
  121. package/dist/lib/contractRunner.js.map +1 -0
  122. package/dist/mcp/helpers.d.ts +32 -0
  123. package/dist/mcp/helpers.d.ts.map +1 -0
  124. package/dist/mcp/helpers.js +125 -0
  125. package/dist/mcp/helpers.js.map +1 -0
  126. package/dist/mcp/tools/contract.d.ts +25 -0
  127. package/dist/mcp/tools/contract.d.ts.map +1 -0
  128. package/dist/mcp/tools/contract.js +33 -0
  129. package/dist/mcp/tools/contract.js.map +1 -0
  130. package/dist/mcp/tools/contract_tool.d.ts +3 -0
  131. package/dist/mcp/tools/contract_tool.d.ts.map +1 -0
  132. package/dist/mcp/tools/contract_tool.js +328 -0
  133. package/dist/mcp/tools/contract_tool.js.map +1 -0
  134. package/dist/mcp/tools/get_task_tool.d.ts +3 -0
  135. package/dist/mcp/tools/get_task_tool.d.ts.map +1 -0
  136. package/dist/mcp/tools/get_task_tool.js +55 -0
  137. package/dist/mcp/tools/get_task_tool.js.map +1 -0
  138. package/dist/mcp/tools/list_tasks_tool.d.ts +3 -0
  139. package/dist/mcp/tools/list_tasks_tool.d.ts.map +1 -0
  140. package/dist/mcp/tools/list_tasks_tool.js +82 -0
  141. package/dist/mcp/tools/list_tasks_tool.js.map +1 -0
  142. package/dist/mcp/tools/search_tool.d.ts +3 -0
  143. package/dist/mcp/tools/search_tool.d.ts.map +1 -0
  144. package/dist/mcp/tools/search_tool.js +155 -0
  145. package/dist/mcp/tools/search_tool.js.map +1 -0
  146. package/dist/mcp/tools/subtask_tool.d.ts +3 -0
  147. package/dist/mcp/tools/subtask_tool.d.ts.map +1 -0
  148. package/dist/mcp/tools/subtask_tool.js +321 -0
  149. package/dist/mcp/tools/subtask_tool.js.map +1 -0
  150. package/dist/mcp/tools/task_add_tool.d.ts +3 -0
  151. package/dist/mcp/tools/task_add_tool.d.ts.map +1 -0
  152. package/dist/mcp/tools/task_add_tool.js +196 -0
  153. package/dist/mcp/tools/task_add_tool.js.map +1 -0
  154. package/dist/mcp/tools/task_complete_tool.d.ts +3 -0
  155. package/dist/mcp/tools/task_complete_tool.d.ts.map +1 -0
  156. package/dist/mcp/tools/task_complete_tool.js +265 -0
  157. package/dist/mcp/tools/task_complete_tool.js.map +1 -0
  158. package/dist/mcp/tools/task_delete_tool.d.ts +3 -0
  159. package/dist/mcp/tools/task_delete_tool.d.ts.map +1 -0
  160. package/dist/mcp/tools/task_delete_tool.js +87 -0
  161. package/dist/mcp/tools/task_delete_tool.js.map +1 -0
  162. package/dist/mcp/tools/task_move_tool.d.ts +3 -0
  163. package/dist/mcp/tools/task_move_tool.d.ts.map +1 -0
  164. package/dist/mcp/tools/task_move_tool.js +187 -0
  165. package/dist/mcp/tools/task_move_tool.js.map +1 -0
  166. package/dist/mcp/tools/task_patch_tool.d.ts +3 -0
  167. package/dist/mcp/tools/task_patch_tool.d.ts.map +1 -0
  168. package/dist/mcp/tools/task_patch_tool.js +189 -0
  169. package/dist/mcp/tools/task_patch_tool.js.map +1 -0
  170. package/dist/schemas/base.json +159 -0
  171. package/dist/schemas/board.json +290 -0
  172. package/dist/tui/BrainfileTUI.d.ts +4 -0
  173. package/dist/tui/BrainfileTUI.d.ts.map +1 -0
  174. package/dist/tui/BrainfileTUI.js +272 -0
  175. package/dist/tui/BrainfileTUI.js.map +1 -0
  176. package/dist/tui/actions.d.ts +84 -0
  177. package/dist/tui/actions.d.ts.map +1 -0
  178. package/dist/tui/actions.js +1251 -0
  179. package/dist/tui/actions.js.map +1 -0
  180. package/dist/tui/components/ColumnTabs.d.ts +9 -0
  181. package/dist/tui/components/ColumnTabs.d.ts.map +1 -0
  182. package/dist/tui/components/ColumnTabs.js +34 -0
  183. package/dist/tui/components/ColumnTabs.js.map +1 -0
  184. package/dist/tui/components/Header.d.ts +15 -0
  185. package/dist/tui/components/Header.d.ts.map +1 -0
  186. package/dist/tui/components/Header.js +48 -0
  187. package/dist/tui/components/Header.js.map +1 -0
  188. package/dist/tui/components/HelpOverlay.d.ts +9 -0
  189. package/dist/tui/components/HelpOverlay.d.ts.map +1 -0
  190. package/dist/tui/components/HelpOverlay.js +116 -0
  191. package/dist/tui/components/HelpOverlay.js.map +1 -0
  192. package/dist/tui/components/LogsPanel.d.ts +16 -0
  193. package/dist/tui/components/LogsPanel.d.ts.map +1 -0
  194. package/dist/tui/components/LogsPanel.js +115 -0
  195. package/dist/tui/components/LogsPanel.js.map +1 -0
  196. package/dist/tui/components/MainPanelTabs.d.ts +10 -0
  197. package/dist/tui/components/MainPanelTabs.d.ts.map +1 -0
  198. package/dist/tui/components/MainPanelTabs.js +56 -0
  199. package/dist/tui/components/MainPanelTabs.js.map +1 -0
  200. package/dist/tui/components/ManualBorder.d.ts +42 -0
  201. package/dist/tui/components/ManualBorder.d.ts.map +1 -0
  202. package/dist/tui/components/ManualBorder.js +56 -0
  203. package/dist/tui/components/ManualBorder.js.map +1 -0
  204. package/dist/tui/components/Overlays.d.ts +41 -0
  205. package/dist/tui/components/Overlays.d.ts.map +1 -0
  206. package/dist/tui/components/Overlays.js +127 -0
  207. package/dist/tui/components/Overlays.js.map +1 -0
  208. package/dist/tui/components/ProgressBar.d.ts +8 -0
  209. package/dist/tui/components/ProgressBar.d.ts.map +1 -0
  210. package/dist/tui/components/ProgressBar.js +35 -0
  211. package/dist/tui/components/ProgressBar.js.map +1 -0
  212. package/dist/tui/components/RulesPanel.d.ts +25 -0
  213. package/dist/tui/components/RulesPanel.d.ts.map +1 -0
  214. package/dist/tui/components/RulesPanel.js +139 -0
  215. package/dist/tui/components/RulesPanel.js.map +1 -0
  216. package/dist/tui/components/SearchBar.d.ts +8 -0
  217. package/dist/tui/components/SearchBar.d.ts.map +1 -0
  218. package/dist/tui/components/SearchBar.js +38 -0
  219. package/dist/tui/components/SearchBar.js.map +1 -0
  220. package/dist/tui/components/StackedTaskList.d.ts +27 -0
  221. package/dist/tui/components/StackedTaskList.d.ts.map +1 -0
  222. package/dist/tui/components/StackedTaskList.js +120 -0
  223. package/dist/tui/components/StackedTaskList.js.map +1 -0
  224. package/dist/tui/components/StatusBar.d.ts +14 -0
  225. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  226. package/dist/tui/components/StatusBar.js +42 -0
  227. package/dist/tui/components/StatusBar.js.map +1 -0
  228. package/dist/tui/components/TaskCard.d.ts +25 -0
  229. package/dist/tui/components/TaskCard.d.ts.map +1 -0
  230. package/dist/tui/components/TaskCard.js +221 -0
  231. package/dist/tui/components/TaskCard.js.map +1 -0
  232. package/dist/tui/components/TaskCardMeasure.d.ts +31 -0
  233. package/dist/tui/components/TaskCardMeasure.d.ts.map +1 -0
  234. package/dist/tui/components/TaskCardMeasure.js +133 -0
  235. package/dist/tui/components/TaskCardMeasure.js.map +1 -0
  236. package/dist/tui/components/TaskDetail.d.ts +13 -0
  237. package/dist/tui/components/TaskDetail.d.ts.map +1 -0
  238. package/dist/tui/components/TaskDetail.js +64 -0
  239. package/dist/tui/components/TaskDetail.js.map +1 -0
  240. package/dist/tui/components/TaskList.d.ts +12 -0
  241. package/dist/tui/components/TaskList.d.ts.map +1 -0
  242. package/dist/tui/components/TaskList.js +75 -0
  243. package/dist/tui/components/TaskList.js.map +1 -0
  244. package/dist/tui/components/index.d.ts +31 -0
  245. package/dist/tui/components/index.d.ts.map +1 -0
  246. package/dist/tui/components/index.js +43 -0
  247. package/dist/tui/components/index.js.map +1 -0
  248. package/dist/tui/hooks/index.d.ts +3 -0
  249. package/dist/tui/hooks/index.d.ts.map +1 -0
  250. package/dist/tui/hooks/index.js +8 -0
  251. package/dist/tui/hooks/index.js.map +1 -0
  252. package/dist/tui/hooks/useBrainfileLoader.d.ts +5 -0
  253. package/dist/tui/hooks/useBrainfileLoader.d.ts.map +1 -0
  254. package/dist/tui/hooks/useBrainfileLoader.js +237 -0
  255. package/dist/tui/hooks/useBrainfileLoader.js.map +1 -0
  256. package/dist/tui/hooks/useKeyboardNavigation.d.ts +20 -0
  257. package/dist/tui/hooks/useKeyboardNavigation.d.ts.map +1 -0
  258. package/dist/tui/hooks/useKeyboardNavigation.js +806 -0
  259. package/dist/tui/hooks/useKeyboardNavigation.js.map +1 -0
  260. package/dist/tui/index.d.ts +10 -0
  261. package/dist/tui/index.d.ts.map +1 -0
  262. package/dist/tui/index.js +38 -0
  263. package/dist/tui/index.js.map +1 -0
  264. package/dist/tui/theme.d.ts +119 -0
  265. package/dist/tui/theme.d.ts.map +1 -0
  266. package/dist/tui/theme.js +138 -0
  267. package/dist/tui/theme.js.map +1 -0
  268. package/dist/tui/types.d.ts +53 -0
  269. package/dist/tui/types.d.ts.map +1 -0
  270. package/dist/tui/types.js +12 -0
  271. package/dist/tui/types.js.map +1 -0
  272. package/dist/tui/utils.d.ts +24 -0
  273. package/dist/tui/utils.d.ts.map +1 -0
  274. package/dist/tui/utils.js +161 -0
  275. package/dist/tui/utils.js.map +1 -0
  276. package/dist/utils/archive.d.ts +57 -0
  277. package/dist/utils/archive.d.ts.map +1 -0
  278. package/dist/utils/archive.js +304 -0
  279. package/dist/utils/archive.js.map +1 -0
  280. package/dist/utils/auth-store.d.ts +69 -0
  281. package/dist/utils/auth-store.d.ts.map +1 -0
  282. package/dist/utils/auth-store.js +308 -0
  283. package/dist/utils/auth-store.js.map +1 -0
  284. package/dist/utils/board-types.d.ts +13 -0
  285. package/dist/utils/board-types.d.ts.map +1 -0
  286. package/dist/utils/board-types.js +7 -0
  287. package/dist/utils/board-types.js.map +1 -0
  288. package/dist/utils/brainfile-finder.d.ts +12 -0
  289. package/dist/utils/brainfile-finder.d.ts.map +1 -0
  290. package/dist/utils/brainfile-finder.js +69 -0
  291. package/dist/utils/brainfile-finder.js.map +1 -0
  292. package/dist/utils/brainfile-path.d.ts +10 -0
  293. package/dist/utils/brainfile-path.d.ts.map +1 -0
  294. package/dist/utils/brainfile-path.js +88 -0
  295. package/dist/utils/brainfile-path.js.map +1 -0
  296. package/dist/utils/cli-error.d.ts +44 -0
  297. package/dist/utils/cli-error.d.ts.map +1 -0
  298. package/dist/utils/cli-error.js +85 -0
  299. package/dist/utils/cli-error.js.map +1 -0
  300. package/dist/utils/config.d.ts +119 -0
  301. package/dist/utils/config.d.ts.map +1 -0
  302. package/dist/utils/config.js +304 -0
  303. package/dist/utils/config.js.map +1 -0
  304. package/dist/utils/contractSpec.d.ts +13 -0
  305. package/dist/utils/contractSpec.d.ts.map +1 -0
  306. package/dist/utils/contractSpec.js +61 -0
  307. package/dist/utils/contractSpec.js.map +1 -0
  308. package/dist/utils/dot-brainfile.d.ts +9 -0
  309. package/dist/utils/dot-brainfile.d.ts.map +1 -0
  310. package/dist/utils/dot-brainfile.js +74 -0
  311. package/dist/utils/dot-brainfile.js.map +1 -0
  312. package/dist/utils/errorHandler.d.ts +106 -0
  313. package/dist/utils/errorHandler.d.ts.map +1 -0
  314. package/dist/utils/errorHandler.js +223 -0
  315. package/dist/utils/errorHandler.js.map +1 -0
  316. package/dist/utils/git-helper.d.ts +17 -0
  317. package/dist/utils/git-helper.d.ts.map +1 -0
  318. package/dist/utils/git-helper.js +62 -0
  319. package/dist/utils/git-helper.js.map +1 -0
  320. package/dist/utils/github-auth.d.ts +56 -0
  321. package/dist/utils/github-auth.d.ts.map +1 -0
  322. package/dist/utils/github-auth.js +341 -0
  323. package/dist/utils/github-auth.js.map +1 -0
  324. package/dist/utils/hook-parser.d.ts +15 -0
  325. package/dist/utils/hook-parser.d.ts.map +1 -0
  326. package/dist/utils/hook-parser.js +69 -0
  327. package/dist/utils/hook-parser.js.map +1 -0
  328. package/dist/utils/hook-settings.d.ts +27 -0
  329. package/dist/utils/hook-settings.d.ts.map +1 -0
  330. package/dist/utils/hook-settings.js +364 -0
  331. package/dist/utils/hook-settings.js.map +1 -0
  332. package/dist/utils/linear-auth.d.ts +59 -0
  333. package/dist/utils/linear-auth.d.ts.map +1 -0
  334. package/dist/utils/linear-auth.js +295 -0
  335. package/dist/utils/linear-auth.js.map +1 -0
  336. package/dist/utils/logger.d.ts +34 -0
  337. package/dist/utils/logger.d.ts.map +1 -0
  338. package/dist/utils/logger.js +56 -0
  339. package/dist/utils/logger.js.map +1 -0
  340. package/dist/utils/strict-validation.d.ts +8 -0
  341. package/dist/utils/strict-validation.d.ts.map +1 -0
  342. package/dist/utils/strict-validation.js +41 -0
  343. package/dist/utils/strict-validation.js.map +1 -0
  344. package/dist/utils/v2-detect.d.ts +28 -0
  345. package/dist/utils/v2-detect.d.ts.map +1 -0
  346. package/dist/utils/v2-detect.js +112 -0
  347. package/dist/utils/v2-detect.js.map +1 -0
  348. package/dist/utils/v2-only.d.ts +9 -0
  349. package/dist/utils/v2-only.d.ts.map +1 -0
  350. package/dist/utils/v2-only.js +64 -0
  351. package/dist/utils/v2-only.js.map +1 -0
  352. package/dist/utils/workspace-format.d.ts +25 -0
  353. package/dist/utils/workspace-format.d.ts.map +1 -0
  354. package/dist/utils/workspace-format.js +106 -0
  355. package/dist/utils/workspace-format.js.map +1 -0
  356. package/dist/validation/command-lint.d.ts +11 -0
  357. package/dist/validation/command-lint.d.ts.map +1 -0
  358. package/dist/validation/command-lint.js +88 -0
  359. package/dist/validation/command-lint.js.map +1 -0
  360. package/package.json +69 -0
@@ -0,0 +1,806 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useKeyboardNavigation = useKeyboardNavigation;
4
+ const ink_1 = require("ink");
5
+ const actions_js_1 = require("../actions.js");
6
+ const RULE_TYPES = ['always', 'never', 'prefer', 'context'];
7
+ // Helper to show status message
8
+ function showStatus(setState, text, type) {
9
+ const timestamp = Date.now();
10
+ setState(prev => ({
11
+ ...prev,
12
+ statusMessage: { text, type, timestamp },
13
+ }));
14
+ // Clear message after 3 seconds
15
+ setTimeout(() => {
16
+ setState(prev => {
17
+ // Only clear if it's the same message
18
+ if (prev.statusMessage?.timestamp === timestamp) {
19
+ return { ...prev, statusMessage: null };
20
+ }
21
+ return prev;
22
+ });
23
+ }, 3000);
24
+ }
25
+ function useKeyboardNavigation({ state, setState, currentTasks, maxTaskIndex, filteredColumnsLength, viewportHeight, loadBrainfile, filePath, allColumns, layoutMode, flatTasks, maxGlobalIndex, }) {
26
+ const { exit } = (0, ink_1.useApp)();
27
+ // Get current task based on layout mode
28
+ const currentTask = layoutMode === 'wide'
29
+ ? currentTasks[state.selectedTaskIndex]
30
+ : flatTasks[state.selectedGlobalIndex]?.task;
31
+ (0, ink_1.useInput)((input, key) => {
32
+ // Help mode - any key closes
33
+ if (state.mode === 'help') {
34
+ setState(prev => ({ ...prev, mode: 'browse' }));
35
+ return;
36
+ }
37
+ // Delete confirmation mode
38
+ if (state.mode === 'delete-confirm') {
39
+ if (input === 'y' || input === 'Y') {
40
+ if (currentTask) {
41
+ const result = (0, actions_js_1.deleteTaskAction)(filePath, currentTask.id);
42
+ if (result.success) {
43
+ showStatus(setState, `Deleted ${currentTask.id}`, 'success');
44
+ loadBrainfile(true);
45
+ }
46
+ else {
47
+ showStatus(setState, result.error || 'Failed to delete', 'error');
48
+ }
49
+ }
50
+ setState(prev => ({ ...prev, mode: 'browse' }));
51
+ return;
52
+ }
53
+ if (input === 'n' || input === 'N' || key.escape) {
54
+ setState(prev => ({ ...prev, mode: 'browse' }));
55
+ showStatus(setState, 'Delete cancelled', 'info');
56
+ return;
57
+ }
58
+ return;
59
+ }
60
+ // Move mode - column picker
61
+ if (state.mode === 'move') {
62
+ if (key.escape) {
63
+ setState(prev => ({ ...prev, mode: 'browse' }));
64
+ return;
65
+ }
66
+ if (key.leftArrow || input === 'h') {
67
+ setState(prev => ({
68
+ ...prev,
69
+ moveTargetIndex: Math.max(0, prev.moveTargetIndex - 1),
70
+ }));
71
+ return;
72
+ }
73
+ if (key.rightArrow || input === 'l') {
74
+ setState(prev => ({
75
+ ...prev,
76
+ moveTargetIndex: Math.min(allColumns.length - 1, prev.moveTargetIndex + 1),
77
+ }));
78
+ return;
79
+ }
80
+ if (key.return) {
81
+ if (currentTask) {
82
+ const targetColumn = allColumns[state.moveTargetIndex];
83
+ if (targetColumn) {
84
+ const result = (0, actions_js_1.moveTaskAction)(filePath, currentTask.id, targetColumn.id);
85
+ if (result.success) {
86
+ showStatus(setState, result.message || `Moved to ${targetColumn.title}`, 'success');
87
+ loadBrainfile(true);
88
+ }
89
+ else {
90
+ showStatus(setState, result.error || 'Failed to move', 'error');
91
+ }
92
+ }
93
+ }
94
+ setState(prev => ({ ...prev, mode: 'browse' }));
95
+ return;
96
+ }
97
+ // Number keys 1-9 to jump to column
98
+ const num = parseInt(input, 10);
99
+ if (num >= 1 && num <= allColumns.length) {
100
+ setState(prev => ({ ...prev, moveTargetIndex: num - 1 }));
101
+ return;
102
+ }
103
+ return;
104
+ }
105
+ // Subtask mode - toggle subtasks
106
+ if (state.mode === 'subtask') {
107
+ const subtasks = currentTask?.subtasks || [];
108
+ if (key.escape) {
109
+ setState(prev => ({ ...prev, mode: 'browse' }));
110
+ return;
111
+ }
112
+ if (key.upArrow || input === 'k') {
113
+ setState(prev => ({
114
+ ...prev,
115
+ selectedSubtaskIndex: Math.max(0, prev.selectedSubtaskIndex - 1),
116
+ }));
117
+ return;
118
+ }
119
+ if (key.downArrow || input === 'j') {
120
+ setState(prev => ({
121
+ ...prev,
122
+ selectedSubtaskIndex: Math.min(subtasks.length - 1, prev.selectedSubtaskIndex + 1),
123
+ }));
124
+ return;
125
+ }
126
+ if (key.return || input === ' ') {
127
+ const subtask = subtasks[state.selectedSubtaskIndex];
128
+ if (currentTask && subtask) {
129
+ const result = (0, actions_js_1.toggleSubtaskAction)(filePath, currentTask.id, subtask.id);
130
+ if (result.success) {
131
+ showStatus(setState, `Toggled ${subtask.id}`, 'success');
132
+ loadBrainfile(true);
133
+ }
134
+ else {
135
+ showStatus(setState, result.error || 'Failed to toggle', 'error');
136
+ }
137
+ }
138
+ return;
139
+ }
140
+ return;
141
+ }
142
+ // New task mode - inline title input
143
+ if (state.mode === 'new-task') {
144
+ if (key.escape) {
145
+ setState(prev => ({ ...prev, mode: 'browse', newTaskTitle: '' }));
146
+ return;
147
+ }
148
+ if (key.return) {
149
+ const title = state.newTaskTitle.trim();
150
+ if (title) {
151
+ const currentCol = allColumns[state.activeColumnIndex];
152
+ if (currentCol) {
153
+ const result = (0, actions_js_1.addTaskAction)(filePath, currentCol.id, { title });
154
+ if (result.success) {
155
+ showStatus(setState, result.message || 'Task added', 'success');
156
+ loadBrainfile(true);
157
+ }
158
+ else {
159
+ showStatus(setState, result.error || 'Failed to add task', 'error');
160
+ }
161
+ }
162
+ }
163
+ else {
164
+ showStatus(setState, 'Title required', 'error');
165
+ }
166
+ setState(prev => ({ ...prev, mode: 'browse', newTaskTitle: '' }));
167
+ return;
168
+ }
169
+ if (key.backspace || key.delete) {
170
+ setState(prev => ({ ...prev, newTaskTitle: prev.newTaskTitle.slice(0, -1) }));
171
+ return;
172
+ }
173
+ if (input && !key.ctrl && !key.meta) {
174
+ setState(prev => ({ ...prev, newTaskTitle: prev.newTaskTitle + input }));
175
+ return;
176
+ }
177
+ return;
178
+ }
179
+ // Search mode handling (Tasks panel)
180
+ if (state.mode === 'search') {
181
+ if (key.escape) {
182
+ setState(prev => ({ ...prev, mode: 'browse', searchQuery: '' }));
183
+ return;
184
+ }
185
+ if (key.return) {
186
+ setState(prev => ({ ...prev, mode: 'browse' }));
187
+ return;
188
+ }
189
+ if (key.backspace || key.delete) {
190
+ setState(prev => ({ ...prev, searchQuery: prev.searchQuery.slice(0, -1) }));
191
+ return;
192
+ }
193
+ if (input && !key.ctrl && !key.meta) {
194
+ setState(prev => ({ ...prev, searchQuery: prev.searchQuery + input }));
195
+ return;
196
+ }
197
+ return;
198
+ }
199
+ // Rule add/edit mode
200
+ if (state.mode === 'rule-add' || state.mode === 'rule-edit') {
201
+ if (key.escape) {
202
+ setState(prev => ({ ...prev, mode: 'browse', ruleEditText: '', ruleEditId: null }));
203
+ return;
204
+ }
205
+ if (key.return) {
206
+ const text = state.ruleEditText.trim();
207
+ if (!text) {
208
+ showStatus(setState, 'Rule text required', 'error');
209
+ return;
210
+ }
211
+ if (state.mode === 'rule-add') {
212
+ const result = (0, actions_js_1.addRuleAction)(filePath, state.activeRuleType, text);
213
+ if (result.success) {
214
+ showStatus(setState, result.message || 'Rule added', 'success');
215
+ loadBrainfile(true);
216
+ }
217
+ else {
218
+ showStatus(setState, result.error || 'Failed to add rule', 'error');
219
+ }
220
+ }
221
+ else if (state.ruleEditId !== null) {
222
+ const result = (0, actions_js_1.updateRuleAction)(filePath, state.activeRuleType, state.ruleEditId, text);
223
+ if (result.success) {
224
+ showStatus(setState, result.message || 'Rule updated', 'success');
225
+ loadBrainfile(true);
226
+ }
227
+ else {
228
+ showStatus(setState, result.error || 'Failed to update rule', 'error');
229
+ }
230
+ }
231
+ setState(prev => ({ ...prev, mode: 'browse', ruleEditText: '', ruleEditId: null }));
232
+ return;
233
+ }
234
+ if (key.backspace || key.delete) {
235
+ setState(prev => ({ ...prev, ruleEditText: prev.ruleEditText.slice(0, -1) }));
236
+ return;
237
+ }
238
+ if (input && !key.ctrl && !key.meta) {
239
+ setState(prev => ({ ...prev, ruleEditText: prev.ruleEditText + input }));
240
+ return;
241
+ }
242
+ return;
243
+ }
244
+ // Rule delete confirmation
245
+ if (state.mode === 'rule-delete-confirm') {
246
+ const rules = state.board?.rules?.[state.activeRuleType] || [];
247
+ const rule = rules[state.selectedRuleIndex];
248
+ if (input === 'y' || input === 'Y') {
249
+ if (rule) {
250
+ const result = (0, actions_js_1.deleteRuleAction)(filePath, state.activeRuleType, rule.id);
251
+ if (result.success) {
252
+ showStatus(setState, result.message || 'Rule deleted', 'success');
253
+ loadBrainfile(true);
254
+ // Adjust selection if needed
255
+ setState(prev => ({
256
+ ...prev,
257
+ mode: 'browse',
258
+ selectedRuleIndex: Math.max(0, prev.selectedRuleIndex - 1),
259
+ }));
260
+ }
261
+ else {
262
+ showStatus(setState, result.error || 'Failed to delete rule', 'error');
263
+ setState(prev => ({ ...prev, mode: 'browse' }));
264
+ }
265
+ }
266
+ return;
267
+ }
268
+ if (input === 'n' || input === 'N' || key.escape) {
269
+ setState(prev => ({ ...prev, mode: 'browse' }));
270
+ showStatus(setState, 'Delete cancelled', 'info');
271
+ return;
272
+ }
273
+ return;
274
+ }
275
+ // Logs restore mode - column picker
276
+ if (state.mode === 'logs-restore') {
277
+ if (key.escape) {
278
+ setState(prev => ({ ...prev, mode: 'browse' }));
279
+ return;
280
+ }
281
+ if (key.downArrow || input === 'j') {
282
+ setState(prev => ({
283
+ ...prev,
284
+ logRestoreColumnIndex: Math.min(prev.logRestoreColumnIndex + 1, allColumns.length - 1),
285
+ }));
286
+ return;
287
+ }
288
+ if (key.upArrow || input === 'k') {
289
+ setState(prev => ({
290
+ ...prev,
291
+ logRestoreColumnIndex: Math.max(prev.logRestoreColumnIndex - 1, 0),
292
+ }));
293
+ return;
294
+ }
295
+ if (key.return) {
296
+ const task = state.logs[state.selectedLogIndex];
297
+ const column = allColumns[state.logRestoreColumnIndex];
298
+ if (task && column) {
299
+ const result = (0, actions_js_1.restoreTaskAction)(filePath, task.id, column.id);
300
+ if (result.success) {
301
+ showStatus(setState, result.message || 'Task restored', 'success');
302
+ loadBrainfile(true);
303
+ // Reload logs
304
+ const logResult = (0, actions_js_1.loadLogs)(filePath);
305
+ setState(prev => ({
306
+ ...prev,
307
+ mode: 'browse',
308
+ logs: logResult.logs,
309
+ selectedLogIndex: Math.max(0, prev.selectedLogIndex - 1),
310
+ }));
311
+ }
312
+ else {
313
+ showStatus(setState, result.error || 'Failed to restore task', 'error');
314
+ setState(prev => ({ ...prev, mode: 'browse' }));
315
+ }
316
+ }
317
+ return;
318
+ }
319
+ return;
320
+ }
321
+ // Logs delete confirmation
322
+ if (state.mode === 'logs-delete-confirm') {
323
+ const task = state.logs[state.selectedLogIndex];
324
+ if (input === 'y' || input === 'Y') {
325
+ if (task) {
326
+ const result = (0, actions_js_1.deleteArchivedTaskAction)(filePath, task.id);
327
+ if (result.success) {
328
+ showStatus(setState, result.message || 'Task permanently deleted', 'success');
329
+ // Reload logs
330
+ const logResult = (0, actions_js_1.loadLogs)(filePath);
331
+ setState(prev => ({
332
+ ...prev,
333
+ mode: 'browse',
334
+ logs: logResult.logs,
335
+ selectedLogIndex: Math.max(0, prev.selectedLogIndex - 1),
336
+ }));
337
+ }
338
+ else {
339
+ showStatus(setState, result.error || 'Failed to delete task', 'error');
340
+ setState(prev => ({ ...prev, mode: 'browse' }));
341
+ }
342
+ }
343
+ return;
344
+ }
345
+ if (input === 'n' || input === 'N' || key.escape) {
346
+ setState(prev => ({ ...prev, mode: 'browse' }));
347
+ showStatus(setState, 'Delete cancelled', 'info');
348
+ return;
349
+ }
350
+ return;
351
+ }
352
+ // ============================================================
353
+ // GLOBAL KEYS (work in browse mode across all panels)
354
+ // ============================================================
355
+ if (input === 'q' || (key.ctrl && input === 'c')) {
356
+ exit();
357
+ return;
358
+ }
359
+ if (input === '?') {
360
+ setState(prev => ({ ...prev, mode: 'help' }));
361
+ return;
362
+ }
363
+ // Panel switching: 1/2/3
364
+ if (input === '1') {
365
+ setState(prev => ({ ...prev, activePanel: 'tasks', mode: 'browse' }));
366
+ return;
367
+ }
368
+ if (input === '2') {
369
+ setState(prev => ({ ...prev, activePanel: 'rules', mode: 'browse' }));
370
+ return;
371
+ }
372
+ if (input === '3') {
373
+ setState(prev => ({ ...prev, activePanel: 'logs', mode: 'browse' }));
374
+ // Logs are loaded via useEffect in BrainfileTUI
375
+ return;
376
+ }
377
+ // Refresh (force refresh bypasses hash check)
378
+ if (input === 'r' && state.activePanel !== 'logs') {
379
+ loadBrainfile(true);
380
+ showStatus(setState, 'Refreshed', 'info');
381
+ return;
382
+ }
383
+ // ============================================================
384
+ // TASKS PANEL - Browse mode
385
+ // ============================================================
386
+ if (state.activePanel === 'tasks') {
387
+ if (input === '/') {
388
+ setState(prev => ({ ...prev, mode: 'search', searchQuery: '' }));
389
+ return;
390
+ }
391
+ // 'e' - Edit task in $EDITOR
392
+ if (input === 'e') {
393
+ if (!currentTask) {
394
+ showStatus(setState, 'No task selected', 'error');
395
+ return;
396
+ }
397
+ const result = (0, actions_js_1.editTaskInEditor)(filePath, currentTask.id);
398
+ if (result.success) {
399
+ showStatus(setState, result.message || 'Task updated', 'success');
400
+ loadBrainfile(true);
401
+ }
402
+ else {
403
+ showStatus(setState, result.error || 'Edit failed', 'error');
404
+ }
405
+ return;
406
+ }
407
+ // 'm' - Move task
408
+ if (input === 'm') {
409
+ if (!currentTask) {
410
+ showStatus(setState, 'No task selected', 'error');
411
+ return;
412
+ }
413
+ setState(prev => ({ ...prev, mode: 'move', moveTargetIndex: prev.activeColumnIndex }));
414
+ return;
415
+ }
416
+ // 'd' - Delete task
417
+ if (input === 'd') {
418
+ if (!currentTask) {
419
+ showStatus(setState, 'No task selected', 'error');
420
+ return;
421
+ }
422
+ setState(prev => ({ ...prev, mode: 'delete-confirm' }));
423
+ return;
424
+ }
425
+ // 'A' - Move task to logs (supports external destinations)
426
+ if (input === 'A') {
427
+ if (!currentTask) {
428
+ showStatus(setState, 'No task selected', 'error');
429
+ return;
430
+ }
431
+ // Show status while async operation runs
432
+ showStatus(setState, 'Moving to logs...', 'info');
433
+ // Call async archive function (supports GitHub/Linear destinations)
434
+ (0, actions_js_1.archiveTaskActionAsync)(filePath, currentTask.id).then((result) => {
435
+ if (result.success) {
436
+ showStatus(setState, result.message || 'Task moved to logs', 'success');
437
+ loadBrainfile(true);
438
+ }
439
+ else {
440
+ showStatus(setState, result.error || 'Move to logs failed', 'error');
441
+ }
442
+ }).catch((err) => {
443
+ showStatus(setState, `Move to logs failed: ${err}`, 'error');
444
+ });
445
+ return;
446
+ }
447
+ // 'p' - Cycle priority
448
+ if (input === 'p') {
449
+ if (!currentTask) {
450
+ showStatus(setState, 'No task selected', 'error');
451
+ return;
452
+ }
453
+ const result = (0, actions_js_1.cyclePriorityAction)(filePath, currentTask.id);
454
+ if (result.success) {
455
+ showStatus(setState, result.message || 'Priority updated', 'success');
456
+ loadBrainfile(true);
457
+ }
458
+ else {
459
+ showStatus(setState, result.error || 'Failed to update priority', 'error');
460
+ }
461
+ return;
462
+ }
463
+ // 't' - Toggle subtask
464
+ if (input === 't') {
465
+ if (!currentTask) {
466
+ showStatus(setState, 'No task selected', 'error');
467
+ return;
468
+ }
469
+ if (!currentTask.subtasks || currentTask.subtasks.length === 0) {
470
+ showStatus(setState, 'No subtasks', 'info');
471
+ return;
472
+ }
473
+ setState(prev => ({ ...prev, mode: 'subtask', selectedSubtaskIndex: 0 }));
474
+ return;
475
+ }
476
+ // 'y' - Copy task ID
477
+ if (input === 'y') {
478
+ if (!currentTask) {
479
+ showStatus(setState, 'No task selected', 'error');
480
+ return;
481
+ }
482
+ const result = (0, actions_js_1.copyToClipboard)(currentTask.id);
483
+ if (result.success) {
484
+ showStatus(setState, `Copied ${currentTask.id}`, 'success');
485
+ }
486
+ else {
487
+ showStatus(setState, result.error || 'Copy failed', 'error');
488
+ }
489
+ return;
490
+ }
491
+ // 'n' - New task (quick)
492
+ if (input === 'n') {
493
+ setState(prev => ({ ...prev, mode: 'new-task', newTaskTitle: '' }));
494
+ return;
495
+ }
496
+ // 'N' - New task (editor)
497
+ if (input === 'N') {
498
+ const currentCol = allColumns[state.activeColumnIndex];
499
+ if (currentCol) {
500
+ const result = (0, actions_js_1.newTaskInEditor)(filePath, currentCol.id);
501
+ if (result.success) {
502
+ showStatus(setState, result.message || 'Task created', 'success');
503
+ loadBrainfile(true);
504
+ }
505
+ else {
506
+ showStatus(setState, result.error || 'Failed to create task', 'error');
507
+ }
508
+ }
509
+ return;
510
+ }
511
+ // Navigation: up/down
512
+ if (key.downArrow || input === 'j') {
513
+ if (layoutMode === 'narrow') {
514
+ setState(prev => ({
515
+ ...prev,
516
+ selectedGlobalIndex: Math.min(prev.selectedGlobalIndex + 1, maxGlobalIndex),
517
+ }));
518
+ }
519
+ else {
520
+ setState(prev => ({
521
+ ...prev,
522
+ selectedTaskIndex: Math.min(prev.selectedTaskIndex + 1, maxTaskIndex),
523
+ }));
524
+ }
525
+ return;
526
+ }
527
+ if (key.upArrow || input === 'k') {
528
+ if (layoutMode === 'narrow') {
529
+ setState(prev => ({
530
+ ...prev,
531
+ selectedGlobalIndex: Math.max(prev.selectedGlobalIndex - 1, 0),
532
+ }));
533
+ }
534
+ else {
535
+ setState(prev => ({
536
+ ...prev,
537
+ selectedTaskIndex: Math.max(prev.selectedTaskIndex - 1, 0),
538
+ }));
539
+ }
540
+ return;
541
+ }
542
+ // Page scrolling
543
+ if (key.ctrl && input === 'd') {
544
+ if (layoutMode === 'narrow') {
545
+ setState(prev => ({
546
+ ...prev,
547
+ selectedGlobalIndex: Math.min(prev.selectedGlobalIndex + Math.floor(viewportHeight / 2), maxGlobalIndex),
548
+ }));
549
+ }
550
+ else {
551
+ setState(prev => ({
552
+ ...prev,
553
+ selectedTaskIndex: Math.min(prev.selectedTaskIndex + Math.floor(viewportHeight / 2), maxTaskIndex),
554
+ }));
555
+ }
556
+ return;
557
+ }
558
+ if (key.ctrl && input === 'u') {
559
+ if (layoutMode === 'narrow') {
560
+ setState(prev => ({
561
+ ...prev,
562
+ selectedGlobalIndex: Math.max(prev.selectedGlobalIndex - Math.floor(viewportHeight / 2), 0),
563
+ }));
564
+ }
565
+ else {
566
+ setState(prev => ({
567
+ ...prev,
568
+ selectedTaskIndex: Math.max(prev.selectedTaskIndex - Math.floor(viewportHeight / 2), 0),
569
+ }));
570
+ }
571
+ return;
572
+ }
573
+ // Column switching (wide mode only - narrow mode navigates all tasks with j/k)
574
+ if (layoutMode === 'wide') {
575
+ if (key.tab || key.rightArrow || input === 'l') {
576
+ setState(prev => ({
577
+ ...prev,
578
+ activeColumnIndex: (prev.activeColumnIndex + 1) % filteredColumnsLength,
579
+ selectedTaskIndex: 0,
580
+ }));
581
+ return;
582
+ }
583
+ if ((key.shift && key.tab) || key.leftArrow || input === 'h') {
584
+ setState(prev => ({
585
+ ...prev,
586
+ activeColumnIndex: prev.activeColumnIndex === 0
587
+ ? filteredColumnsLength - 1
588
+ : prev.activeColumnIndex - 1,
589
+ selectedTaskIndex: 0,
590
+ }));
591
+ return;
592
+ }
593
+ }
594
+ // Home/End
595
+ if (input === 'g') {
596
+ if (layoutMode === 'narrow') {
597
+ setState(prev => ({ ...prev, selectedGlobalIndex: 0 }));
598
+ }
599
+ else {
600
+ setState(prev => ({ ...prev, selectedTaskIndex: 0 }));
601
+ }
602
+ return;
603
+ }
604
+ if (input === 'G') {
605
+ if (layoutMode === 'narrow') {
606
+ setState(prev => ({ ...prev, selectedGlobalIndex: maxGlobalIndex }));
607
+ }
608
+ else {
609
+ setState(prev => ({ ...prev, selectedTaskIndex: maxTaskIndex }));
610
+ }
611
+ return;
612
+ }
613
+ // Expand/collapse task
614
+ if (key.return) {
615
+ const task = layoutMode === 'wide'
616
+ ? currentTasks[state.selectedTaskIndex]
617
+ : flatTasks[state.selectedGlobalIndex]?.task;
618
+ if (task) {
619
+ setState(prev => {
620
+ const newExpanded = new Set(prev.expandedTaskIds);
621
+ if (newExpanded.has(task.id)) {
622
+ newExpanded.delete(task.id);
623
+ }
624
+ else {
625
+ newExpanded.add(task.id);
626
+ }
627
+ return { ...prev, expandedTaskIds: newExpanded };
628
+ });
629
+ }
630
+ return;
631
+ }
632
+ // Escape: collapse all or clear search
633
+ if (key.escape) {
634
+ setState(prev => ({
635
+ ...prev,
636
+ expandedTaskIds: new Set(),
637
+ searchQuery: '',
638
+ }));
639
+ return;
640
+ }
641
+ }
642
+ // ============================================================
643
+ // RULES PANEL - Browse mode
644
+ // ============================================================
645
+ if (state.activePanel === 'rules') {
646
+ const rules = state.board?.rules?.[state.activeRuleType] || [];
647
+ const maxRuleIndex = Math.max(0, rules.length - 1);
648
+ // h/l or left/right or Shift+TAB to switch rule type left
649
+ if (key.leftArrow || input === 'h' || (key.shift && key.tab)) {
650
+ const currentIdx = RULE_TYPES.indexOf(state.activeRuleType);
651
+ const newIdx = currentIdx === 0 ? RULE_TYPES.length - 1 : currentIdx - 1;
652
+ setState(prev => ({ ...prev, activeRuleType: RULE_TYPES[newIdx], selectedRuleIndex: 0 }));
653
+ return;
654
+ }
655
+ // TAB or l or right to switch rule type right
656
+ if (key.tab || key.rightArrow || input === 'l') {
657
+ const currentIdx = RULE_TYPES.indexOf(state.activeRuleType);
658
+ const newIdx = (currentIdx + 1) % RULE_TYPES.length;
659
+ setState(prev => ({ ...prev, activeRuleType: RULE_TYPES[newIdx], selectedRuleIndex: 0 }));
660
+ return;
661
+ }
662
+ // j/k to navigate rules
663
+ if (key.downArrow || input === 'j') {
664
+ setState(prev => ({
665
+ ...prev,
666
+ selectedRuleIndex: Math.min(prev.selectedRuleIndex + 1, maxRuleIndex),
667
+ }));
668
+ return;
669
+ }
670
+ if (key.upArrow || input === 'k') {
671
+ setState(prev => ({
672
+ ...prev,
673
+ selectedRuleIndex: Math.max(prev.selectedRuleIndex - 1, 0),
674
+ }));
675
+ return;
676
+ }
677
+ // n - New rule
678
+ if (input === 'n') {
679
+ setState(prev => ({ ...prev, mode: 'rule-add', ruleEditText: '', ruleEditId: null }));
680
+ return;
681
+ }
682
+ // e - Edit rule
683
+ if (input === 'e') {
684
+ const rule = rules[state.selectedRuleIndex];
685
+ if (rule) {
686
+ setState(prev => ({
687
+ ...prev,
688
+ mode: 'rule-edit',
689
+ ruleEditText: rule.rule,
690
+ ruleEditId: rule.id,
691
+ }));
692
+ }
693
+ else {
694
+ showStatus(setState, 'No rule selected', 'error');
695
+ }
696
+ return;
697
+ }
698
+ // d - Delete rule
699
+ if (input === 'd') {
700
+ const rule = rules[state.selectedRuleIndex];
701
+ if (rule) {
702
+ setState(prev => ({ ...prev, mode: 'rule-delete-confirm' }));
703
+ }
704
+ else {
705
+ showStatus(setState, 'No rule selected', 'error');
706
+ }
707
+ return;
708
+ }
709
+ // Home/End
710
+ if (input === 'g') {
711
+ setState(prev => ({ ...prev, selectedRuleIndex: 0 }));
712
+ return;
713
+ }
714
+ if (input === 'G') {
715
+ setState(prev => ({ ...prev, selectedRuleIndex: maxRuleIndex }));
716
+ return;
717
+ }
718
+ // Escape
719
+ if (key.escape) {
720
+ setState(prev => ({ ...prev, selectedRuleIndex: 0 }));
721
+ return;
722
+ }
723
+ }
724
+ // ============================================================
725
+ // LOGS PANEL - Browse mode
726
+ // ============================================================
727
+ if (state.activePanel === 'logs') {
728
+ const maxArchiveIndex = Math.max(0, state.logs.length - 1);
729
+ // r - Refresh logs
730
+ if (input === 'r') {
731
+ const result = (0, actions_js_1.loadLogs)(filePath);
732
+ setState(prev => ({ ...prev, logs: result.logs }));
733
+ showStatus(setState, 'Logs refreshed', 'info');
734
+ return;
735
+ }
736
+ // j/k navigation
737
+ if (key.downArrow || input === 'j') {
738
+ setState(prev => ({
739
+ ...prev,
740
+ selectedLogIndex: Math.min(prev.selectedLogIndex + 1, maxArchiveIndex),
741
+ }));
742
+ return;
743
+ }
744
+ if (key.upArrow || input === 'k') {
745
+ setState(prev => ({
746
+ ...prev,
747
+ selectedLogIndex: Math.max(prev.selectedLogIndex - 1, 0),
748
+ }));
749
+ return;
750
+ }
751
+ // Enter - Expand/collapse
752
+ if (key.return) {
753
+ const task = state.logs[state.selectedLogIndex];
754
+ if (task) {
755
+ setState(prev => {
756
+ const newExpanded = new Set(prev.expandedLogIds);
757
+ if (newExpanded.has(task.id)) {
758
+ newExpanded.delete(task.id);
759
+ }
760
+ else {
761
+ newExpanded.add(task.id);
762
+ }
763
+ return { ...prev, expandedLogIds: newExpanded };
764
+ });
765
+ }
766
+ return;
767
+ }
768
+ // r key for restore (use 'R' to avoid conflict with refresh)
769
+ if (input === 'R') {
770
+ if (state.logs.length === 0) {
771
+ showStatus(setState, 'No logged tasks', 'error');
772
+ return;
773
+ }
774
+ setState(prev => ({ ...prev, mode: 'logs-restore', logRestoreColumnIndex: 0 }));
775
+ return;
776
+ }
777
+ // d - Delete permanently
778
+ if (input === 'd') {
779
+ if (state.logs.length === 0) {
780
+ showStatus(setState, 'No logged tasks', 'error');
781
+ return;
782
+ }
783
+ setState(prev => ({ ...prev, mode: 'logs-delete-confirm' }));
784
+ return;
785
+ }
786
+ // Home/End
787
+ if (input === 'g') {
788
+ setState(prev => ({ ...prev, selectedLogIndex: 0 }));
789
+ return;
790
+ }
791
+ if (input === 'G') {
792
+ setState(prev => ({ ...prev, selectedLogIndex: maxArchiveIndex }));
793
+ return;
794
+ }
795
+ // Escape - collapse all expanded
796
+ if (key.escape) {
797
+ setState(prev => ({
798
+ ...prev,
799
+ expandedLogIds: new Set(),
800
+ }));
801
+ return;
802
+ }
803
+ }
804
+ });
805
+ }
806
+ //# sourceMappingURL=useKeyboardNavigation.js.map