@navios/commander-tui 1.2.0 → 1.3.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 (362) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +42 -1
  3. package/dist/base/src/adapters/index.d.ts +2 -0
  4. package/dist/base/src/adapters/index.d.ts.map +1 -0
  5. package/dist/base/src/adapters/interface.d.ts +45 -0
  6. package/dist/base/src/adapters/interface.d.ts.map +1 -0
  7. package/dist/base/src/components/index.d.ts +2 -0
  8. package/dist/base/src/components/index.d.ts.map +1 -0
  9. package/dist/base/src/context/index.d.ts +2 -0
  10. package/dist/base/src/context/index.d.ts.map +1 -0
  11. package/dist/base/src/factories/index.d.ts +3 -0
  12. package/dist/base/src/factories/index.d.ts.map +1 -0
  13. package/dist/base/src/factories/isomorphic-logger.factory.d.ts +8 -0
  14. package/dist/base/src/factories/isomorphic-logger.factory.d.ts.map +1 -0
  15. package/dist/base/src/factories/screen.factory.d.ts +8 -0
  16. package/dist/base/src/factories/screen.factory.d.ts.map +1 -0
  17. package/dist/base/src/filter/filter_engine.d.ts +19 -0
  18. package/dist/base/src/filter/filter_engine.d.ts.map +1 -0
  19. package/dist/base/src/filter/index.d.ts +2 -0
  20. package/dist/base/src/filter/index.d.ts.map +1 -0
  21. package/dist/base/src/hooks/index.d.ts +2 -0
  22. package/dist/base/src/hooks/index.d.ts.map +1 -0
  23. package/dist/base/src/index.d.ts +16 -0
  24. package/dist/base/src/index.d.ts.map +1 -0
  25. package/dist/base/src/interfaces/index.d.ts +2 -0
  26. package/dist/base/src/interfaces/index.d.ts.map +1 -0
  27. package/dist/base/src/interfaces/isomorphic-logger.d.ts +9 -0
  28. package/dist/base/src/interfaces/isomorphic-logger.d.ts.map +1 -0
  29. package/dist/base/src/keyboard/create_bindings.d.ts +26 -0
  30. package/dist/base/src/keyboard/create_bindings.d.ts.map +1 -0
  31. package/dist/base/src/keyboard/index.d.ts +3 -0
  32. package/dist/base/src/keyboard/index.d.ts.map +1 -0
  33. package/dist/base/src/keyboard/keyboard_manager.d.ts +63 -0
  34. package/dist/base/src/keyboard/keyboard_manager.d.ts.map +1 -0
  35. package/dist/base/src/overrides/console.logger.override.d.ts +3 -0
  36. package/dist/base/src/overrides/console.logger.override.d.ts.map +1 -0
  37. package/dist/base/src/overrides/index.d.ts +3 -0
  38. package/dist/base/src/overrides/index.d.ts.map +1 -0
  39. package/dist/base/src/overrides/missing-adapter.override.d.ts +6 -0
  40. package/dist/base/src/overrides/missing-adapter.override.d.ts.map +1 -0
  41. package/dist/base/src/schemas/index.d.ts +4 -0
  42. package/dist/base/src/schemas/index.d.ts.map +1 -0
  43. package/dist/base/src/schemas/logger-options.d.ts +21 -0
  44. package/dist/base/src/schemas/logger-options.d.ts.map +1 -0
  45. package/dist/base/src/schemas/prompt-options.d.ts +12 -0
  46. package/dist/base/src/schemas/prompt-options.d.ts.map +1 -0
  47. package/dist/base/src/schemas/screen-options.d.ts +10 -0
  48. package/dist/base/src/schemas/screen-options.d.ts.map +1 -0
  49. package/dist/base/src/services/index.d.ts +5 -0
  50. package/dist/base/src/services/index.d.ts.map +1 -0
  51. package/dist/base/src/services/logger.d.ts +52 -0
  52. package/dist/base/src/services/logger.d.ts.map +1 -0
  53. package/dist/base/src/services/prompt.d.ts +31 -0
  54. package/dist/base/src/services/prompt.d.ts.map +1 -0
  55. package/dist/base/src/services/screen.d.ts +161 -0
  56. package/dist/base/src/services/screen.d.ts.map +1 -0
  57. package/dist/base/src/services/screen_manager.d.ts +130 -0
  58. package/dist/base/src/services/screen_manager.d.ts.map +1 -0
  59. package/dist/base/src/themes/dark.d.ts +7 -0
  60. package/dist/base/src/themes/dark.d.ts.map +1 -0
  61. package/dist/base/src/themes/high-contrast.d.ts +7 -0
  62. package/dist/base/src/themes/high-contrast.d.ts.map +1 -0
  63. package/dist/base/src/themes/index.d.ts +5 -0
  64. package/dist/base/src/themes/index.d.ts.map +1 -0
  65. package/dist/base/src/themes/light.d.ts +6 -0
  66. package/dist/base/src/themes/light.d.ts.map +1 -0
  67. package/dist/base/src/themes/utils.d.ts +22 -0
  68. package/dist/base/src/themes/utils.d.ts.map +1 -0
  69. package/dist/base/src/tokens/adapter.d.ts +9 -0
  70. package/dist/base/src/tokens/adapter.d.ts.map +1 -0
  71. package/dist/base/src/tokens/index.d.ts +6 -0
  72. package/dist/base/src/tokens/index.d.ts.map +1 -0
  73. package/dist/base/src/tokens/logger.d.ts +44 -0
  74. package/dist/base/src/tokens/logger.d.ts.map +1 -0
  75. package/dist/base/src/tokens/prompt.d.ts +12 -0
  76. package/dist/base/src/tokens/prompt.d.ts.map +1 -0
  77. package/dist/base/src/tokens/screen-manager.d.ts +8 -0
  78. package/dist/base/src/tokens/screen-manager.d.ts.map +1 -0
  79. package/dist/base/src/tokens/screen.d.ts +10 -0
  80. package/dist/base/src/tokens/screen.d.ts.map +1 -0
  81. package/dist/base/src/types/file.types.d.ts +40 -0
  82. package/dist/base/src/types/file.types.d.ts.map +1 -0
  83. package/dist/base/src/types/filter.types.d.ts +31 -0
  84. package/dist/base/src/types/filter.types.d.ts.map +1 -0
  85. package/dist/base/src/types/index.d.ts +9 -0
  86. package/dist/base/src/types/index.d.ts.map +1 -0
  87. package/dist/base/src/types/keyboard.types.d.ts +83 -0
  88. package/dist/base/src/types/keyboard.types.d.ts.map +1 -0
  89. package/dist/base/src/types/log.types.d.ts +39 -0
  90. package/dist/base/src/types/log.types.d.ts.map +1 -0
  91. package/dist/base/src/types/message.types.d.ts +82 -0
  92. package/dist/base/src/types/message.types.d.ts.map +1 -0
  93. package/dist/base/src/types/prompt.types.d.ts +85 -0
  94. package/dist/base/src/types/prompt.types.d.ts.map +1 -0
  95. package/dist/base/src/types/screen.types.d.ts +79 -0
  96. package/dist/base/src/types/screen.types.d.ts.map +1 -0
  97. package/dist/base/src/types/theme.types.d.ts +217 -0
  98. package/dist/base/src/types/theme.types.d.ts.map +1 -0
  99. package/dist/base/src/utils/colors/file-colors.d.ts +10 -0
  100. package/dist/base/src/utils/colors/file-colors.d.ts.map +1 -0
  101. package/dist/base/src/utils/colors/helpers.d.ts +26 -0
  102. package/dist/base/src/utils/colors/helpers.d.ts.map +1 -0
  103. package/dist/base/src/utils/colors/index.d.ts +8 -0
  104. package/dist/base/src/utils/colors/index.d.ts.map +1 -0
  105. package/dist/base/src/utils/colors/log-colors.d.ts +19 -0
  106. package/dist/base/src/utils/colors/log-colors.d.ts.map +1 -0
  107. package/dist/base/src/utils/colors/progress-colors.d.ts +25 -0
  108. package/dist/base/src/utils/colors/progress-colors.d.ts.map +1 -0
  109. package/dist/base/src/utils/colors/prompt-colors.d.ts +22 -0
  110. package/dist/base/src/utils/colors/prompt-colors.d.ts.map +1 -0
  111. package/dist/base/src/utils/colors/sidebar-colors.d.ts +50 -0
  112. package/dist/base/src/utils/colors/sidebar-colors.d.ts.map +1 -0
  113. package/dist/base/src/utils/colors/table-colors.d.ts +12 -0
  114. package/dist/base/src/utils/colors/table-colors.d.ts.map +1 -0
  115. package/dist/base/src/utils/filetype.d.ts +19 -0
  116. package/dist/base/src/utils/filetype.d.ts.map +1 -0
  117. package/dist/base/src/utils/format.d.ts +9 -0
  118. package/dist/base/src/utils/format.d.ts.map +1 -0
  119. package/dist/base/src/utils/index.d.ts +5 -0
  120. package/dist/base/src/utils/index.d.ts.map +1 -0
  121. package/dist/base/src/utils/stdout-printer.d.ts +6 -0
  122. package/dist/base/src/utils/stdout-printer.d.ts.map +1 -0
  123. package/dist/base/tsconfig.base.tsbuildinfo +1 -0
  124. package/dist/react/src/adapters/react/components/file/file_log.d.ts +35 -0
  125. package/dist/react/src/adapters/react/components/file/file_log.d.ts.map +1 -0
  126. package/dist/react/src/adapters/react/components/file/index.d.ts +2 -0
  127. package/dist/react/src/adapters/react/components/file/index.d.ts.map +1 -0
  128. package/dist/react/src/adapters/react/components/filter/filter_bar.d.ts +7 -0
  129. package/dist/react/src/adapters/react/components/filter/filter_bar.d.ts.map +1 -0
  130. package/dist/react/src/adapters/react/components/filter/index.d.ts +2 -0
  131. package/dist/react/src/adapters/react/components/filter/index.d.ts.map +1 -0
  132. package/dist/react/src/adapters/react/components/help/help_overlay.d.ts +6 -0
  133. package/dist/react/src/adapters/react/components/help/help_overlay.d.ts.map +1 -0
  134. package/dist/react/src/adapters/react/components/help/index.d.ts +2 -0
  135. package/dist/react/src/adapters/react/components/help/index.d.ts.map +1 -0
  136. package/dist/react/src/adapters/react/components/log/index.d.ts +2 -0
  137. package/dist/react/src/adapters/react/components/log/index.d.ts.map +1 -0
  138. package/dist/react/src/adapters/react/components/log/log_message.d.ts +28 -0
  139. package/dist/react/src/adapters/react/components/log/log_message.d.ts.map +1 -0
  140. package/dist/react/src/adapters/react/components/prompt/index.d.ts +3 -0
  141. package/dist/react/src/adapters/react/components/prompt/index.d.ts.map +1 -0
  142. package/dist/react/src/adapters/react/components/prompt/prompt_renderer.d.ts +6 -0
  143. package/dist/react/src/adapters/react/components/prompt/prompt_renderer.d.ts.map +1 -0
  144. package/dist/react/src/adapters/react/components/screen/group_renderer.d.ts +14 -0
  145. package/dist/react/src/adapters/react/components/screen/group_renderer.d.ts.map +1 -0
  146. package/dist/react/src/adapters/react/components/screen/index.d.ts +7 -0
  147. package/dist/react/src/adapters/react/components/screen/index.d.ts.map +1 -0
  148. package/dist/react/src/adapters/react/components/screen/loading_message.d.ts +6 -0
  149. package/dist/react/src/adapters/react/components/screen/loading_message.d.ts.map +1 -0
  150. package/dist/react/src/adapters/react/components/screen/message_renderer.d.ts +6 -0
  151. package/dist/react/src/adapters/react/components/screen/message_renderer.d.ts.map +1 -0
  152. package/dist/react/src/adapters/react/components/screen/progress_message.d.ts +6 -0
  153. package/dist/react/src/adapters/react/components/screen/progress_message.d.ts.map +1 -0
  154. package/dist/react/src/adapters/react/components/screen/screen_bridge.d.ts +14 -0
  155. package/dist/react/src/adapters/react/components/screen/screen_bridge.d.ts.map +1 -0
  156. package/dist/react/src/adapters/react/components/screen/table_message.d.ts +6 -0
  157. package/dist/react/src/adapters/react/components/screen/table_message.d.ts.map +1 -0
  158. package/dist/react/src/adapters/react/components/screen_manager_bridge.d.ts +8 -0
  159. package/dist/react/src/adapters/react/components/screen_manager_bridge.d.ts.map +1 -0
  160. package/dist/react/src/adapters/react/components/sidebar/index.d.ts +4 -0
  161. package/dist/react/src/adapters/react/components/sidebar/index.d.ts.map +1 -0
  162. package/dist/react/src/adapters/react/components/sidebar/sidebar.d.ts +11 -0
  163. package/dist/react/src/adapters/react/components/sidebar/sidebar.d.ts.map +1 -0
  164. package/dist/react/src/adapters/react/components/sidebar/sidebar_item.d.ts +9 -0
  165. package/dist/react/src/adapters/react/components/sidebar/sidebar_item.d.ts.map +1 -0
  166. package/dist/react/src/adapters/react/components/sidebar/sidebar_separator.d.ts +2 -0
  167. package/dist/react/src/adapters/react/components/sidebar/sidebar_separator.d.ts.map +1 -0
  168. package/dist/react/src/adapters/react/context/index.d.ts +2 -0
  169. package/dist/react/src/adapters/react/context/index.d.ts.map +1 -0
  170. package/dist/react/src/adapters/react/context/logger_context.d.ts +53 -0
  171. package/dist/react/src/adapters/react/context/logger_context.d.ts.map +1 -0
  172. package/dist/react/src/adapters/react/hooks/index.d.ts +2 -0
  173. package/dist/react/src/adapters/react/hooks/index.d.ts.map +1 -0
  174. package/dist/react/src/adapters/react/hooks/use_theme.d.ts +7 -0
  175. package/dist/react/src/adapters/react/hooks/use_theme.d.ts.map +1 -0
  176. package/dist/react/src/adapters/react/index.d.ts +13 -0
  177. package/dist/react/src/adapters/react/index.d.ts.map +1 -0
  178. package/dist/react/tsconfig.react.tsbuildinfo +1 -0
  179. package/dist/solid/src/adapters/solid/components/file/file_log.d.ts +35 -0
  180. package/dist/solid/src/adapters/solid/components/file/file_log.d.ts.map +1 -0
  181. package/dist/solid/src/adapters/solid/components/file/index.d.ts +2 -0
  182. package/dist/solid/src/adapters/solid/components/file/index.d.ts.map +1 -0
  183. package/dist/solid/src/adapters/solid/components/filter/filter_bar.d.ts +7 -0
  184. package/dist/solid/src/adapters/solid/components/filter/filter_bar.d.ts.map +1 -0
  185. package/dist/solid/src/adapters/solid/components/filter/index.d.ts +2 -0
  186. package/dist/solid/src/adapters/solid/components/filter/index.d.ts.map +1 -0
  187. package/dist/solid/src/adapters/solid/components/help/help_overlay.d.ts +6 -0
  188. package/dist/solid/src/adapters/solid/components/help/help_overlay.d.ts.map +1 -0
  189. package/dist/solid/src/adapters/solid/components/help/index.d.ts +2 -0
  190. package/dist/solid/src/adapters/solid/components/help/index.d.ts.map +1 -0
  191. package/dist/solid/src/adapters/solid/components/log/index.d.ts +2 -0
  192. package/dist/solid/src/adapters/solid/components/log/index.d.ts.map +1 -0
  193. package/dist/solid/src/adapters/solid/components/log/log_message.d.ts +31 -0
  194. package/dist/solid/src/adapters/solid/components/log/log_message.d.ts.map +1 -0
  195. package/dist/solid/src/adapters/solid/components/prompt/index.d.ts +3 -0
  196. package/dist/solid/src/adapters/solid/components/prompt/index.d.ts.map +1 -0
  197. package/dist/solid/src/adapters/solid/components/prompt/prompt_renderer.d.ts +6 -0
  198. package/dist/solid/src/adapters/solid/components/prompt/prompt_renderer.d.ts.map +1 -0
  199. package/dist/solid/src/adapters/solid/components/screen/group_renderer.d.ts +14 -0
  200. package/dist/solid/src/adapters/solid/components/screen/group_renderer.d.ts.map +1 -0
  201. package/dist/solid/src/adapters/solid/components/screen/index.d.ts +7 -0
  202. package/dist/solid/src/adapters/solid/components/screen/index.d.ts.map +1 -0
  203. package/dist/solid/src/adapters/solid/components/screen/loading_message.d.ts +6 -0
  204. package/dist/solid/src/adapters/solid/components/screen/loading_message.d.ts.map +1 -0
  205. package/dist/solid/src/adapters/solid/components/screen/message_renderer.d.ts +6 -0
  206. package/dist/solid/src/adapters/solid/components/screen/message_renderer.d.ts.map +1 -0
  207. package/dist/solid/src/adapters/solid/components/screen/progress_message.d.ts +6 -0
  208. package/dist/solid/src/adapters/solid/components/screen/progress_message.d.ts.map +1 -0
  209. package/dist/solid/src/adapters/solid/components/screen/screen_bridge.d.ts +14 -0
  210. package/dist/solid/src/adapters/solid/components/screen/screen_bridge.d.ts.map +1 -0
  211. package/dist/solid/src/adapters/solid/components/screen/table_message.d.ts +6 -0
  212. package/dist/solid/src/adapters/solid/components/screen/table_message.d.ts.map +1 -0
  213. package/dist/solid/src/adapters/solid/components/screen_manager_bridge.d.ts +8 -0
  214. package/dist/solid/src/adapters/solid/components/screen_manager_bridge.d.ts.map +1 -0
  215. package/dist/solid/src/adapters/solid/components/sidebar/index.d.ts +4 -0
  216. package/dist/solid/src/adapters/solid/components/sidebar/index.d.ts.map +1 -0
  217. package/dist/solid/src/adapters/solid/components/sidebar/sidebar.d.ts +11 -0
  218. package/dist/solid/src/adapters/solid/components/sidebar/sidebar.d.ts.map +1 -0
  219. package/dist/solid/src/adapters/solid/components/sidebar/sidebar_item.d.ts +9 -0
  220. package/dist/solid/src/adapters/solid/components/sidebar/sidebar_item.d.ts.map +1 -0
  221. package/dist/solid/src/adapters/solid/components/sidebar/sidebar_separator.d.ts +2 -0
  222. package/dist/solid/src/adapters/solid/components/sidebar/sidebar_separator.d.ts.map +1 -0
  223. package/dist/solid/src/adapters/solid/context/index.d.ts +3 -0
  224. package/dist/solid/src/adapters/solid/context/index.d.ts.map +1 -0
  225. package/dist/solid/src/adapters/solid/context/logger_context.d.ts +52 -0
  226. package/dist/solid/src/adapters/solid/context/logger_context.d.ts.map +1 -0
  227. package/dist/solid/src/adapters/solid/hooks/index.d.ts +2 -0
  228. package/dist/solid/src/adapters/solid/hooks/index.d.ts.map +1 -0
  229. package/dist/solid/src/adapters/solid/hooks/use_theme.d.ts +7 -0
  230. package/dist/solid/src/adapters/solid/hooks/use_theme.d.ts.map +1 -0
  231. package/dist/solid/src/adapters/solid/index.d.ts +13 -0
  232. package/dist/solid/src/adapters/solid/index.d.ts.map +1 -0
  233. package/dist/solid/tsconfig.solid.tsbuildinfo +1 -0
  234. package/dist/tsconfig.base.tsbuildinfo +1 -0
  235. package/dist/tsconfig.react.tsbuildinfo +1 -0
  236. package/dist/tsconfig.solid.tsbuildinfo +1 -0
  237. package/dist/tsconfig.tsbuildinfo +1 -1
  238. package/lib/adapters/react/index.cjs +1768 -0
  239. package/lib/adapters/react/index.cjs.map +1 -0
  240. package/lib/adapters/react/index.d.cts +80 -0
  241. package/lib/adapters/react/index.d.mts +80 -0
  242. package/lib/adapters/react/index.mjs +1760 -0
  243. package/lib/adapters/react/index.mjs.map +1 -0
  244. package/lib/adapters/solid/index.cjs +3855 -0
  245. package/lib/adapters/solid/index.cjs.map +1 -0
  246. package/lib/adapters/solid/index.d.cts +74 -0
  247. package/lib/adapters/solid/index.d.mts +74 -0
  248. package/lib/adapters/solid/index.mjs +3847 -0
  249. package/lib/adapters/solid/index.mjs.map +1 -0
  250. package/lib/filter_engine-DXqu9Vaq.cjs +1836 -0
  251. package/lib/filter_engine-DXqu9Vaq.cjs.map +1 -0
  252. package/lib/filter_engine-DmqhEhpA.mjs +1609 -0
  253. package/lib/filter_engine-DmqhEhpA.mjs.map +1 -0
  254. package/lib/index.cjs +1424 -1125
  255. package/lib/index.cjs.map +1 -1
  256. package/lib/index.d.cts +263 -1152
  257. package/lib/index.d.mts +263 -1152
  258. package/lib/index.mjs +1378 -1070
  259. package/lib/index.mjs.map +1 -1
  260. package/lib/interface-CTHQ08aY.d.mts +699 -0
  261. package/lib/interface-DQEIz9Mb.d.cts +699 -0
  262. package/package.json +25 -1
  263. package/project.json +2 -2
  264. package/src/__tests__/components/__snapshots__/filter_bar.spec.tsx.snap +0 -2556
  265. package/src/__tests__/components/__snapshots__/loading_message.spec.tsx.snap +0 -1589
  266. package/src/__tests__/components/__snapshots__/log_message.spec.tsx.snap +0 -3681
  267. package/src/__tests__/components/__snapshots__/progress_message.spec.tsx.snap +0 -2002
  268. package/src/__tests__/components/__snapshots__/prompt_renderer.spec.tsx.snap +0 -3584
  269. package/src/__tests__/components/__snapshots__/sidebar.spec.tsx.snap +0 -3186
  270. package/src/__tests__/components/filter_bar.spec.tsx +1 -1
  271. package/src/__tests__/components/loading_message.spec.tsx +1 -1
  272. package/src/__tests__/components/log_message.spec.tsx +1 -1
  273. package/src/__tests__/components/progress_message.spec.tsx +1 -1
  274. package/src/__tests__/components/prompt_renderer.spec.tsx +1 -1
  275. package/src/__tests__/components/sidebar.spec.tsx +1 -1
  276. package/src/__tests__/utils/render-utils.tsx +1 -1
  277. package/src/adapters/index.ts +2 -0
  278. package/src/adapters/interface.ts +50 -0
  279. package/src/{components → adapters/react/components}/file/file_log.tsx +2 -2
  280. package/src/{components → adapters/react/components}/filter/filter_bar.tsx +2 -2
  281. package/src/{components → adapters/react/components}/help/help_overlay.tsx +2 -2
  282. package/src/{components → adapters/react/components}/log/log_message.tsx +2 -2
  283. package/src/{components → adapters/react/components}/prompt/prompt_renderer.tsx +1 -1
  284. package/src/{components → adapters/react/components}/screen/group_renderer.tsx +1 -1
  285. package/src/{components → adapters/react/components}/screen/loading_message.tsx +2 -3
  286. package/src/{components → adapters/react/components}/screen/message_renderer.tsx +1 -1
  287. package/src/{components → adapters/react/components}/screen/progress_message.tsx +1 -1
  288. package/src/{components → adapters/react/components}/screen/screen_bridge.tsx +2 -2
  289. package/src/{components → adapters/react/components}/screen/table_message.tsx +2 -2
  290. package/src/{components → adapters/react/components}/screen_manager_bridge.tsx +5 -5
  291. package/src/{components → adapters/react/components}/sidebar/sidebar.tsx +1 -1
  292. package/src/{components → adapters/react/components}/sidebar/sidebar_item.tsx +1 -1
  293. package/src/adapters/react/context/index.ts +1 -0
  294. package/src/{context → adapters/react/context}/logger_context.tsx +2 -2
  295. package/src/adapters/react/hooks/index.ts +1 -0
  296. package/src/{hooks → adapters/react/hooks}/use_theme.ts +1 -1
  297. package/src/adapters/react/index.ts +39 -0
  298. package/src/adapters/solid/components/file/file_log.tsx +221 -0
  299. package/src/adapters/solid/components/file/index.ts +1 -0
  300. package/src/adapters/solid/components/filter/filter_bar.tsx +84 -0
  301. package/src/adapters/solid/components/filter/index.ts +1 -0
  302. package/src/adapters/solid/components/help/help_overlay.tsx +106 -0
  303. package/src/adapters/solid/components/help/index.ts +1 -0
  304. package/src/adapters/solid/components/log/index.ts +1 -0
  305. package/src/adapters/solid/components/log/log_message.tsx +92 -0
  306. package/src/adapters/solid/components/prompt/index.ts +2 -0
  307. package/src/adapters/solid/components/prompt/prompt_renderer.tsx +350 -0
  308. package/src/adapters/solid/components/screen/group_renderer.tsx +61 -0
  309. package/src/adapters/solid/components/screen/index.ts +6 -0
  310. package/src/adapters/solid/components/screen/loading_message.tsx +39 -0
  311. package/src/adapters/solid/components/screen/message_renderer.tsx +122 -0
  312. package/src/adapters/solid/components/screen/progress_message.tsx +61 -0
  313. package/src/adapters/solid/components/screen/screen_bridge.tsx +155 -0
  314. package/src/adapters/solid/components/screen/table_message.tsx +58 -0
  315. package/src/adapters/solid/components/screen_manager_bridge.tsx +243 -0
  316. package/src/adapters/solid/components/sidebar/index.ts +3 -0
  317. package/src/adapters/solid/components/sidebar/sidebar.tsx +108 -0
  318. package/src/adapters/solid/components/sidebar/sidebar_item.tsx +55 -0
  319. package/src/adapters/solid/components/sidebar/sidebar_separator.tsx +13 -0
  320. package/src/adapters/solid/context/index.ts +2 -0
  321. package/src/adapters/solid/context/logger_context.tsx +95 -0
  322. package/src/adapters/solid/hooks/index.ts +1 -0
  323. package/src/adapters/solid/hooks/use_theme.ts +12 -0
  324. package/src/adapters/solid/index.tsx +43 -0
  325. package/src/adapters/solid/jsx.d.ts +98 -0
  326. package/src/components/index.ts +3 -15
  327. package/src/context/index.ts +3 -1
  328. package/src/factories/isomorphic-logger.factory.ts +1 -2
  329. package/src/factories/screen.factory.ts +2 -2
  330. package/src/hooks/index.ts +3 -1
  331. package/src/index.ts +5 -0
  332. package/src/keyboard/create_bindings.ts +2 -2
  333. package/src/overrides/index.ts +1 -0
  334. package/src/overrides/missing-adapter.override.ts +20 -0
  335. package/src/services/index.ts +1 -1
  336. package/src/services/screen.ts +3 -3
  337. package/src/services/{screen_manager.tsx → screen_manager.ts} +21 -10
  338. package/src/tokens/adapter.ts +10 -0
  339. package/src/tokens/index.ts +2 -0
  340. package/src/tokens/screen-manager.ts +9 -0
  341. package/tsconfig.base.json +31 -0
  342. package/tsconfig.json +6 -12
  343. package/tsconfig.react.json +16 -0
  344. package/tsconfig.solid.json +16 -0
  345. package/tsdown.config.mts +69 -16
  346. package/vitest.config.mts +20 -0
  347. package/lib/index.d.cts.map +0 -1
  348. package/lib/index.d.mts.map +0 -1
  349. package/lib/screen_manager_bridge-Bk1i53h5.mjs +0 -3
  350. package/lib/screen_manager_bridge-BwPVr0bX.mjs +0 -3048
  351. package/lib/screen_manager_bridge-BwPVr0bX.mjs.map +0 -1
  352. package/lib/screen_manager_bridge-CWxLO0CK.cjs +0 -3371
  353. package/lib/screen_manager_bridge-CWxLO0CK.cjs.map +0 -1
  354. package/lib/screen_manager_bridge-DXc57iXW.cjs +0 -3
  355. /package/src/{components → adapters/react/components}/file/index.ts +0 -0
  356. /package/src/{components → adapters/react/components}/filter/index.ts +0 -0
  357. /package/src/{components → adapters/react/components}/help/index.ts +0 -0
  358. /package/src/{components → adapters/react/components}/log/index.ts +0 -0
  359. /package/src/{components → adapters/react/components}/prompt/index.ts +0 -0
  360. /package/src/{components → adapters/react/components}/screen/index.ts +0 -0
  361. /package/src/{components → adapters/react/components}/sidebar/index.ts +0 -0
  362. /package/src/{components → adapters/react/components}/sidebar/sidebar_separator.tsx +0 -0
@@ -1,3371 +0,0 @@
1
- let _opentui_react_jsx_runtime = require("@opentui/react/jsx-runtime");
2
- let _opentui_core = require("@opentui/core");
3
- let react = require("react");
4
- let _opentui_react = require("@opentui/react");
5
-
6
- //#region src/types/filter.types.ts
7
- /**
8
- * All log levels in order.
9
- */ const ALL_LOG_LEVELS = [
10
- "verbose",
11
- "debug",
12
- "log",
13
- "warn",
14
- "error",
15
- "fatal"
16
- ];
17
- /**
18
- * Create a default filter state.
19
- */ function createDefaultFilterState() {
20
- return {
21
- enabledLevels: new Set(ALL_LOG_LEVELS),
22
- searchQuery: "",
23
- isVisible: false,
24
- focusedField: "search"
25
- };
26
- }
27
- /**
28
- * Check if any filtering is active.
29
- */ function hasActiveFilter(filter) {
30
- return filter.searchQuery !== "" || filter.enabledLevels.size < ALL_LOG_LEVELS.length;
31
- }
32
-
33
- //#endregion
34
- //#region src/themes/dark.ts
35
- /**
36
- * Default dark theme.
37
- * Migrated from the scattered color files in utils/colors/.
38
- */ const darkTheme = {
39
- name: "dark",
40
- logLevels: {
41
- verbose: {
42
- border: "#6B7280",
43
- background: "#6B728015"
44
- },
45
- debug: {
46
- border: "#8B5CF6",
47
- background: "#8B5CF615"
48
- },
49
- log: {
50
- border: "#3B82F6",
51
- background: "#3B82F615"
52
- },
53
- warn: {
54
- border: "#F59E0B",
55
- background: "#F59E0B15"
56
- },
57
- error: {
58
- border: "#EF4444",
59
- background: "#EF444415"
60
- },
61
- fatal: {
62
- border: "#DC2626",
63
- background: "#DC262625",
64
- text: "#FCA5A5"
65
- }
66
- },
67
- sidebar: {
68
- background: void 0,
69
- selectedBackground: "#1F293780",
70
- hoverBackground: "#374151",
71
- text: "#E5E7EB",
72
- textDim: "#6B7280",
73
- border: "#374151",
74
- badge: "#3B82F6",
75
- focusBorder: "#3B82F6"
76
- },
77
- header: {
78
- background: void 0,
79
- text: "#F9FAFB",
80
- border: "#374151"
81
- },
82
- statusIndicators: {
83
- waiting: {
84
- icon: "○",
85
- color: "#6B7280"
86
- },
87
- pending: {
88
- icon: "◐",
89
- color: "#F59E0B"
90
- },
91
- success: {
92
- icon: "✓",
93
- color: "#22C55E"
94
- },
95
- fail: {
96
- icon: "✗",
97
- color: "#EF4444"
98
- },
99
- static: {
100
- icon: "●",
101
- color: "#3B82F6"
102
- }
103
- },
104
- separator: {
105
- line: "#374151",
106
- text: "#6B7280"
107
- },
108
- progress: {
109
- border: "#3B82F6",
110
- background: "#3B82F615",
111
- barFilled: "#3B82F6",
112
- barEmpty: "#374151",
113
- text: "#E5E7EB",
114
- textDim: "#9CA3AF",
115
- complete: "#22C55E",
116
- completeBackground: "#22C55E15",
117
- failed: "#EF4444",
118
- failedBackground: "#EF444415"
119
- },
120
- group: {
121
- border: "#6B7280",
122
- background: "#6B728010",
123
- headerText: "#E5E7EB",
124
- icon: "#9CA3AF"
125
- },
126
- table: {
127
- border: "#3B82F6",
128
- background: "#3B82F615",
129
- headerText: "#F9FAFB",
130
- cellText: "#E5E7EB",
131
- title: "#F9FAFB",
132
- separator: "#3B82F650"
133
- },
134
- file: {
135
- border: "#3B82F6",
136
- background: "#3B82F615",
137
- headerText: "#F9FAFB",
138
- headerBackground: "#3B82F625"
139
- },
140
- prompt: {
141
- question: "#F9FAFB",
142
- optionText: "#E5E7EB",
143
- optionTextDim: "#9CA3AF",
144
- optionSelected: "#3B82F6",
145
- optionSelectedBackground: "#1E3A5F",
146
- confirmButton: "#22C55E",
147
- cancelButton: "#EF4444",
148
- buttonBackground: "#374151",
149
- buttonSelectedBackground: "#1F2937",
150
- inputBorder: "#3B82F6",
151
- inputBackground: "#1F2937",
152
- inputText: "#F9FAFB",
153
- inputPlaceholder: "#6B7280",
154
- inputCursor: "#3B82F6",
155
- border: "#374151",
156
- focusBorder: "#3B82F6"
157
- },
158
- errorHighlight: {
159
- background: "#EF444425",
160
- border: "#EF4444",
161
- gutterBackground: "#EF444440"
162
- },
163
- filter: {
164
- background: "#1F293780",
165
- border: "#3B82F6",
166
- text: "#E5E7EB",
167
- textDim: "#6B7280",
168
- inputBackground: "#1F2937",
169
- inputText: "#F9FAFB",
170
- inputPlaceholder: "#6B7280",
171
- cursor: "#3B82F6",
172
- activeLevel: "#3B82F6",
173
- inactiveLevel: "#4B5563"
174
- },
175
- help: {
176
- background: "#1F2937",
177
- border: "#3B82F6",
178
- title: "#F9FAFB",
179
- category: "#3B82F6",
180
- key: "#F59E0B",
181
- description: "#E5E7EB",
182
- hint: "#6B7280"
183
- },
184
- colors: {
185
- primary: "#3B82F6",
186
- secondary: "#8B5CF6",
187
- success: "#22C55E",
188
- warning: "#F59E0B",
189
- error: "#EF4444",
190
- muted: "#6B7280",
191
- background: "#111827",
192
- foreground: "#F9FAFB"
193
- }
194
- };
195
-
196
- //#endregion
197
- //#region src/themes/light.ts
198
- /**
199
- * Light theme for terminals with light backgrounds.
200
- */ const lightTheme = {
201
- name: "light",
202
- logLevels: {
203
- verbose: {
204
- border: "#9CA3AF",
205
- background: "#F3F4F6"
206
- },
207
- debug: {
208
- border: "#7C3AED",
209
- background: "#EDE9FE"
210
- },
211
- log: {
212
- border: "#2563EB",
213
- background: "#DBEAFE"
214
- },
215
- warn: {
216
- border: "#D97706",
217
- background: "#FEF3C7"
218
- },
219
- error: {
220
- border: "#DC2626",
221
- background: "#FEE2E2"
222
- },
223
- fatal: {
224
- border: "#991B1B",
225
- background: "#FECACA",
226
- text: "#7F1D1D"
227
- }
228
- },
229
- sidebar: {
230
- background: "#F9FAFB",
231
- selectedBackground: "#E5E7EB",
232
- hoverBackground: "#F3F4F6",
233
- text: "#1F2937",
234
- textDim: "#6B7280",
235
- border: "#D1D5DB",
236
- badge: "#2563EB",
237
- focusBorder: "#2563EB"
238
- },
239
- header: {
240
- background: "#F9FAFB",
241
- text: "#111827",
242
- border: "#D1D5DB"
243
- },
244
- statusIndicators: {
245
- waiting: {
246
- icon: "○",
247
- color: "#9CA3AF"
248
- },
249
- pending: {
250
- icon: "◐",
251
- color: "#D97706"
252
- },
253
- success: {
254
- icon: "✓",
255
- color: "#16A34A"
256
- },
257
- fail: {
258
- icon: "✗",
259
- color: "#DC2626"
260
- },
261
- static: {
262
- icon: "●",
263
- color: "#2563EB"
264
- }
265
- },
266
- separator: {
267
- line: "#D1D5DB",
268
- text: "#6B7280"
269
- },
270
- progress: {
271
- border: "#2563EB",
272
- background: "#DBEAFE",
273
- barFilled: "#2563EB",
274
- barEmpty: "#E5E7EB",
275
- text: "#1F2937",
276
- textDim: "#6B7280",
277
- complete: "#16A34A",
278
- completeBackground: "#DCFCE7",
279
- failed: "#DC2626",
280
- failedBackground: "#FEE2E2"
281
- },
282
- group: {
283
- border: "#9CA3AF",
284
- background: "#F3F4F6",
285
- headerText: "#1F2937",
286
- icon: "#6B7280"
287
- },
288
- table: {
289
- border: "#2563EB",
290
- background: "#DBEAFE",
291
- headerText: "#111827",
292
- cellText: "#1F2937",
293
- title: "#111827",
294
- separator: "#93C5FD"
295
- },
296
- file: {
297
- border: "#2563EB",
298
- background: "#DBEAFE",
299
- headerText: "#111827",
300
- headerBackground: "#BFDBFE"
301
- },
302
- prompt: {
303
- question: "#111827",
304
- optionText: "#1F2937",
305
- optionTextDim: "#6B7280",
306
- optionSelected: "#2563EB",
307
- optionSelectedBackground: "#DBEAFE",
308
- confirmButton: "#16A34A",
309
- cancelButton: "#DC2626",
310
- buttonBackground: "#E5E7EB",
311
- buttonSelectedBackground: "#D1D5DB",
312
- inputBorder: "#2563EB",
313
- inputBackground: "#FFFFFF",
314
- inputText: "#111827",
315
- inputPlaceholder: "#9CA3AF",
316
- inputCursor: "#2563EB",
317
- border: "#D1D5DB",
318
- focusBorder: "#2563EB"
319
- },
320
- errorHighlight: {
321
- background: "#FEE2E2",
322
- border: "#DC2626",
323
- gutterBackground: "#FECACA"
324
- },
325
- filter: {
326
- background: "#F3F4F6",
327
- border: "#2563EB",
328
- text: "#1F2937",
329
- textDim: "#6B7280",
330
- inputBackground: "#FFFFFF",
331
- inputText: "#111827",
332
- inputPlaceholder: "#9CA3AF",
333
- cursor: "#2563EB",
334
- activeLevel: "#2563EB",
335
- inactiveLevel: "#D1D5DB"
336
- },
337
- help: {
338
- background: "#FFFFFF",
339
- border: "#2563EB",
340
- title: "#111827",
341
- category: "#2563EB",
342
- key: "#D97706",
343
- description: "#1F2937",
344
- hint: "#6B7280"
345
- },
346
- colors: {
347
- primary: "#2563EB",
348
- secondary: "#7C3AED",
349
- success: "#16A34A",
350
- warning: "#D97706",
351
- error: "#DC2626",
352
- muted: "#6B7280",
353
- background: "#FFFFFF",
354
- foreground: "#111827"
355
- }
356
- };
357
-
358
- //#endregion
359
- //#region src/themes/high-contrast.ts
360
- /**
361
- * High contrast theme for accessibility.
362
- * Uses pure black/white with saturated colors for maximum visibility.
363
- */ const highContrastTheme = {
364
- name: "high-contrast",
365
- logLevels: {
366
- verbose: {
367
- border: "#FFFFFF",
368
- background: "#1A1A1A",
369
- text: "#FFFFFF"
370
- },
371
- debug: {
372
- border: "#A855F7",
373
- background: "#1A1A1A",
374
- text: "#E9D5FF"
375
- },
376
- log: {
377
- border: "#3B82F6",
378
- background: "#1A1A1A",
379
- text: "#BFDBFE"
380
- },
381
- warn: {
382
- border: "#FBBF24",
383
- background: "#1A1A1A",
384
- text: "#FEF08A"
385
- },
386
- error: {
387
- border: "#EF4444",
388
- background: "#1A1A1A",
389
- text: "#FECACA"
390
- },
391
- fatal: {
392
- border: "#FF0000",
393
- background: "#330000",
394
- text: "#FFFFFF"
395
- }
396
- },
397
- sidebar: {
398
- background: "#000000",
399
- selectedBackground: "#333333",
400
- hoverBackground: "#1A1A1A",
401
- text: "#FFFFFF",
402
- textDim: "#AAAAAA",
403
- border: "#FFFFFF",
404
- badge: "#FFFF00",
405
- focusBorder: "#FFFF00"
406
- },
407
- header: {
408
- background: "#000000",
409
- text: "#FFFFFF",
410
- border: "#FFFFFF"
411
- },
412
- statusIndicators: {
413
- waiting: {
414
- icon: "○",
415
- color: "#AAAAAA"
416
- },
417
- pending: {
418
- icon: "◐",
419
- color: "#FBBF24"
420
- },
421
- success: {
422
- icon: "✓",
423
- color: "#22C55E"
424
- },
425
- fail: {
426
- icon: "✗",
427
- color: "#EF4444"
428
- },
429
- static: {
430
- icon: "●",
431
- color: "#00FFFF"
432
- }
433
- },
434
- separator: {
435
- line: "#FFFFFF",
436
- text: "#AAAAAA"
437
- },
438
- progress: {
439
- border: "#3B82F6",
440
- background: "#1A1A1A",
441
- barFilled: "#3B82F6",
442
- barEmpty: "#333333",
443
- text: "#FFFFFF",
444
- textDim: "#AAAAAA",
445
- complete: "#22C55E",
446
- completeBackground: "#1A1A1A",
447
- failed: "#EF4444",
448
- failedBackground: "#1A1A1A"
449
- },
450
- group: {
451
- border: "#FFFFFF",
452
- background: "#1A1A1A",
453
- headerText: "#FFFFFF",
454
- icon: "#AAAAAA"
455
- },
456
- table: {
457
- border: "#FFFFFF",
458
- background: "#1A1A1A",
459
- headerText: "#FFFFFF",
460
- cellText: "#FFFFFF",
461
- title: "#FFFFFF",
462
- separator: "#666666"
463
- },
464
- file: {
465
- border: "#FFFFFF",
466
- background: "#1A1A1A",
467
- headerText: "#FFFFFF",
468
- headerBackground: "#333333"
469
- },
470
- prompt: {
471
- question: "#FFFFFF",
472
- optionText: "#FFFFFF",
473
- optionTextDim: "#AAAAAA",
474
- optionSelected: "#FFFF00",
475
- optionSelectedBackground: "#333333",
476
- confirmButton: "#22C55E",
477
- cancelButton: "#EF4444",
478
- buttonBackground: "#333333",
479
- buttonSelectedBackground: "#1A1A1A",
480
- inputBorder: "#FFFF00",
481
- inputBackground: "#1A1A1A",
482
- inputText: "#FFFFFF",
483
- inputPlaceholder: "#666666",
484
- inputCursor: "#FFFF00",
485
- border: "#FFFFFF",
486
- focusBorder: "#FFFF00"
487
- },
488
- errorHighlight: {
489
- background: "#330000",
490
- border: "#FF0000",
491
- gutterBackground: "#660000"
492
- },
493
- filter: {
494
- background: "#1A1A1A",
495
- border: "#FFFF00",
496
- text: "#FFFFFF",
497
- textDim: "#AAAAAA",
498
- inputBackground: "#000000",
499
- inputText: "#FFFFFF",
500
- inputPlaceholder: "#666666",
501
- cursor: "#FFFF00",
502
- activeLevel: "#FFFF00",
503
- inactiveLevel: "#666666"
504
- },
505
- help: {
506
- background: "#000000",
507
- border: "#FFFFFF",
508
- title: "#FFFFFF",
509
- category: "#FFFF00",
510
- key: "#00FFFF",
511
- description: "#FFFFFF",
512
- hint: "#AAAAAA"
513
- },
514
- colors: {
515
- primary: "#3B82F6",
516
- secondary: "#A855F7",
517
- success: "#22C55E",
518
- warning: "#FBBF24",
519
- error: "#EF4444",
520
- muted: "#AAAAAA",
521
- background: "#000000",
522
- foreground: "#FFFFFF"
523
- }
524
- };
525
-
526
- //#endregion
527
- //#region src/themes/utils.ts
528
- /**
529
- * Deep merge two objects, with source taking precedence.
530
- */ function deepMerge(target, source) {
531
- const result = { ...target };
532
- for (const key in source) if (Object.prototype.hasOwnProperty.call(source, key)) {
533
- const sourceValue = source[key];
534
- const targetValue = target[key];
535
- if (sourceValue !== void 0 && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) result[key] = deepMerge(targetValue, sourceValue);
536
- else if (sourceValue !== void 0) result[key] = sourceValue;
537
- }
538
- return result;
539
- }
540
- /**
541
- * Get a theme by preset name.
542
- */ function getThemePreset(preset) {
543
- switch (preset) {
544
- case "dark": return darkTheme;
545
- case "light": return lightTheme;
546
- case "high-contrast": return highContrastTheme;
547
- default: return darkTheme;
548
- }
549
- }
550
- /**
551
- * Merge a base theme with partial overrides.
552
- */ function mergeThemes(base, overrides) {
553
- return deepMerge(base, overrides);
554
- }
555
- /**
556
- * Create a custom theme by extending the dark theme with overrides.
557
- */ function createTheme(overrides) {
558
- return mergeThemes(darkTheme, overrides);
559
- }
560
- /**
561
- * Create a custom theme by extending a specific base theme.
562
- */ function createThemeFrom(base, overrides) {
563
- return mergeThemes(typeof base === "string" ? getThemePreset(base) : base, overrides);
564
- }
565
- /**
566
- * Resolve a theme value which can be a Theme object or a preset name.
567
- */ function resolveTheme(theme) {
568
- return typeof theme === "string" ? getThemePreset(theme) : theme;
569
- }
570
-
571
- //#endregion
572
- //#region src/context/logger_context.tsx
573
- const LoggerContext = /* @__PURE__ */ (0, react.createContext)(null);
574
- /**
575
- * LoggerProvider - Provides shared context for logger components.
576
- *
577
- * This context provides:
578
- * - Shared SyntaxStyle instance for consistent code highlighting
579
- * - Optional TreeSitterClient for advanced parsing
580
- * - Theme configuration for consistent styling
581
- * - Log level color configuration (for backwards compatibility)
582
- *
583
- * @example
584
- * // Using a preset theme
585
- * <LoggerProvider theme="dark">
586
- * <ScreenManager screens={screens} activeScreenId={activeId}>
587
- * <Screen name="Logs">
588
- * <LogMessage level="info">Hello</LogMessage>
589
- * </Screen>
590
- * </ScreenManager>
591
- * </LoggerProvider>
592
- *
593
- * @example
594
- * // Using a custom theme
595
- * <LoggerProvider theme={myCustomTheme}>
596
- * ...
597
- * </LoggerProvider>
598
- */ function LoggerProvider({ children, syntaxStyle: customSyntaxStyle, treeSitterClient, theme: themeProp = "dark", levelColors: customLevelColors }) {
599
- const syntaxStyle = (0, react.useMemo)(() => customSyntaxStyle ?? _opentui_core.SyntaxStyle.create(), [customSyntaxStyle]);
600
- const theme = (0, react.useMemo)(() => resolveTheme(themeProp), [themeProp]);
601
- const levelColors = (0, react.useMemo)(() => ({
602
- ...theme.logLevels,
603
- ...customLevelColors
604
- }), [theme.logLevels, customLevelColors]);
605
- const value = (0, react.useMemo)(() => ({
606
- syntaxStyle,
607
- treeSitterClient,
608
- levelColors,
609
- theme
610
- }), [
611
- syntaxStyle,
612
- treeSitterClient,
613
- levelColors,
614
- theme
615
- ]);
616
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(LoggerContext.Provider, {
617
- value,
618
- children
619
- });
620
- }
621
- /**
622
- * Hook to access logger context.
623
- * Returns default values if used outside LoggerProvider.
624
- */ function useLoggerContext() {
625
- const context = (0, react.useContext)(LoggerContext);
626
- if (!context) return {
627
- syntaxStyle: void 0,
628
- treeSitterClient: void 0,
629
- levelColors: darkTheme.logLevels,
630
- theme: darkTheme
631
- };
632
- return context;
633
- }
634
-
635
- //#endregion
636
- //#region src/hooks/use_theme.ts
637
- /**
638
- * Hook to access the current theme.
639
- * Returns the theme from LoggerContext.
640
- */ function useTheme() {
641
- const { theme } = useLoggerContext();
642
- return theme;
643
- }
644
-
645
- //#endregion
646
- //#region src/utils/colors/log-colors.ts
647
- /**
648
- * Default color scheme for all log levels.
649
- * Each level has a prominent border color and a subtle background tint.
650
- */ const DEFAULT_LOG_LEVEL_COLORS = {
651
- verbose: {
652
- border: "#6B7280",
653
- background: "#6B728015"
654
- },
655
- debug: {
656
- border: "#8B5CF6",
657
- background: "#8B5CF615"
658
- },
659
- log: {
660
- border: "#3B82F6",
661
- background: "#3B82F615"
662
- },
663
- warn: {
664
- border: "#F59E0B",
665
- background: "#F59E0B15"
666
- },
667
- error: {
668
- border: "#EF4444",
669
- background: "#EF444415"
670
- },
671
- fatal: {
672
- border: "#DC2626",
673
- background: "#DC262625",
674
- text: "#FCA5A5"
675
- }
676
- };
677
- /**
678
- * Colors for semantic variants (override level colors when variant is set).
679
- */ const VARIANT_COLORS = {
680
- success: {
681
- border: "#22C55E",
682
- background: "#22C55E15"
683
- },
684
- trace: {
685
- border: "#6B7280",
686
- background: "#6B728015"
687
- }
688
- };
689
- /**
690
- * Error highlighting colors.
691
- */ const ERROR_HIGHLIGHT_COLORS = {
692
- background: "#EF444425",
693
- border: "#EF4444",
694
- gutterBackground: "#EF444440"
695
- };
696
-
697
- //#endregion
698
- //#region src/utils/colors/sidebar-colors.ts
699
- /**
700
- * Sidebar colors.
701
- */ const SIDEBAR_COLORS = {
702
- background: void 0,
703
- selectedBackground: "#1F293780",
704
- hoverBackground: "#374151",
705
- text: "#E5E7EB",
706
- textDim: "#6B7280",
707
- border: "#374151",
708
- badge: "#3B82F6",
709
- focusBorder: "#3B82F6"
710
- };
711
- /**
712
- * Screen header colors.
713
- */ const HEADER_COLORS = {
714
- background: void 0,
715
- text: "#F9FAFB",
716
- border: "#374151"
717
- };
718
- /**
719
- * Screen status indicator colors and icons.
720
- */ const STATUS_INDICATORS = {
721
- waiting: {
722
- icon: "○",
723
- color: "#6B7280"
724
- },
725
- pending: {
726
- icon: "◐",
727
- color: "#F59E0B"
728
- },
729
- success: {
730
- icon: "✓",
731
- color: "#22C55E"
732
- },
733
- fail: {
734
- icon: "✗",
735
- color: "#EF4444"
736
- }
737
- };
738
- /**
739
- * Separator colors for sidebar sections.
740
- */ const SEPARATOR_COLORS = {
741
- line: "#374151",
742
- text: "#6B7280"
743
- };
744
-
745
- //#endregion
746
- //#region src/utils/colors/progress-colors.ts
747
- /**
748
- * Progress bar colors.
749
- */ const PROGRESS_COLORS = {
750
- border: "#3B82F6",
751
- background: "#3B82F615",
752
- barFilled: "#3B82F6",
753
- barEmpty: "#374151",
754
- text: "#E5E7EB",
755
- textDim: "#9CA3AF",
756
- complete: "#22C55E",
757
- completeBackground: "#22C55E15",
758
- failed: "#EF4444",
759
- failedBackground: "#EF444415"
760
- };
761
- /**
762
- * Group colors for collapsible log groups.
763
- */ const GROUP_COLORS = {
764
- border: "#6B7280",
765
- background: "#6B728010",
766
- headerText: "#E5E7EB",
767
- icon: "#9CA3AF"
768
- };
769
-
770
- //#endregion
771
- //#region src/utils/colors/table-colors.ts
772
- /**
773
- * Table colors (uses info/blue scheme).
774
- */ const TABLE_COLORS = {
775
- border: "#3B82F6",
776
- background: "#3B82F615",
777
- headerText: "#F9FAFB",
778
- cellText: "#E5E7EB",
779
- title: "#F9FAFB",
780
- separator: "#3B82F650"
781
- };
782
-
783
- //#endregion
784
- //#region src/utils/colors/file-colors.ts
785
- /**
786
- * File display colors (uses info/blue scheme).
787
- */ const FILE_COLORS = {
788
- border: "#3B82F6",
789
- background: "#3B82F615",
790
- headerText: "#F9FAFB",
791
- headerBackground: "#3B82F625"
792
- };
793
-
794
- //#endregion
795
- //#region src/utils/colors/prompt-colors.ts
796
- /**
797
- * Prompt colors for interactive prompts.
798
- */ const PROMPT_COLORS = {
799
- question: "#F9FAFB",
800
- optionText: "#E5E7EB",
801
- optionTextDim: "#9CA3AF",
802
- optionSelected: "#3B82F6",
803
- optionSelectedBackground: "#1E3A5F",
804
- confirmButton: "#22C55E",
805
- cancelButton: "#EF4444",
806
- buttonBackground: "#374151",
807
- buttonSelectedBackground: "#1F2937",
808
- inputBorder: "#3B82F6",
809
- inputBackground: "#1F2937",
810
- inputText: "#F9FAFB",
811
- inputPlaceholder: "#6B7280",
812
- inputCursor: "#3B82F6",
813
- border: "#374151",
814
- focusBorder: "#3B82F6"
815
- };
816
-
817
- //#endregion
818
- //#region src/utils/colors/helpers.ts
819
- /**
820
- * Creates a tinted (subtle) version of a color by setting alpha.
821
- *
822
- * @param color - The base color (hex string or RGBA)
823
- * @param alpha - Target alpha value (0-1), default 0.08 for subtle tinting
824
- * @returns New RGBA with adjusted alpha
825
- */ function createTintedColor(color, alpha = .08) {
826
- const rgba = typeof color === "string" ? _opentui_core.RGBA.fromHex(color) : color;
827
- return _opentui_core.RGBA.fromValues(rgba.r, rgba.g, rgba.b, alpha);
828
- }
829
- /**
830
- * Creates a more prominent version of a color for borders.
831
- *
832
- * @param color - The base color
833
- * @param alpha - Target alpha, default 1.0 for solid borders
834
- */ function createBorderColor(color, alpha = 1) {
835
- const rgba = typeof color === "string" ? _opentui_core.RGBA.fromHex(color) : color;
836
- return _opentui_core.RGBA.fromValues(rgba.r, rgba.g, rgba.b, alpha);
837
- }
838
- /**
839
- * Gets colors for a specific log level.
840
- *
841
- * @param level - The log level
842
- * @param customColors - Optional custom color map
843
- */ function getLogLevelColors(level, customColors) {
844
- const defaultColors = DEFAULT_LOG_LEVEL_COLORS[level];
845
- const custom = customColors?.[level];
846
- return {
847
- border: custom?.border ?? defaultColors.border,
848
- background: custom?.background ?? defaultColors.background,
849
- text: custom?.text ?? defaultColors.text
850
- };
851
- }
852
-
853
- //#endregion
854
- //#region src/utils/filetype.ts
855
- /**
856
- * Common file extension to filetype mapping for syntax highlighting.
857
- */ const COMMON_FILETYPES = {
858
- ts: "typescript",
859
- tsx: "tsx",
860
- js: "javascript",
861
- jsx: "javascript",
862
- json: "json",
863
- md: "markdown",
864
- py: "python",
865
- rs: "rust",
866
- go: "go",
867
- java: "java",
868
- c: "c",
869
- cpp: "cpp",
870
- h: "c",
871
- hpp: "cpp",
872
- css: "css",
873
- html: "html",
874
- yaml: "yaml",
875
- yml: "yaml",
876
- sh: "bash",
877
- bash: "bash",
878
- zsh: "bash",
879
- toml: "toml",
880
- xml: "xml",
881
- sql: "sql",
882
- rb: "ruby",
883
- php: "php",
884
- swift: "swift",
885
- kt: "kotlin",
886
- scala: "scala",
887
- hs: "haskell",
888
- elm: "elm",
889
- vue: "vue",
890
- svelte: "svelte"
891
- };
892
- /**
893
- * Resolves filetype from file path for syntax highlighting.
894
- *
895
- * @param filePath - Full file path or just filename
896
- * @returns Filetype string for tree-sitter, or undefined
897
- */ function resolveFiletype(filePath) {
898
- const lastDot = filePath.lastIndexOf(".");
899
- if (lastDot === -1) return void 0;
900
- return COMMON_FILETYPES[filePath.slice(lastDot + 1).toLowerCase()];
901
- }
902
- /**
903
- * Gets the filename from a full path.
904
- *
905
- * @param filePath - Full file path
906
- * @returns Just the filename
907
- */ function getFileName(filePath) {
908
- const lastSlash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
909
- return lastSlash === -1 ? filePath : filePath.slice(lastSlash + 1);
910
- }
911
-
912
- //#endregion
913
- //#region src/utils/stdout-printer.ts
914
- const RESET = "\x1B[0m";
915
- const BOLD = "\x1B[1m";
916
- const DIM = "\x1B[2m";
917
- function hexToAnsi(hex, isForeground = true) {
918
- const cleanHex = hex.replace("#", "").slice(0, 6);
919
- if (!/^[0-9A-Fa-f]{6}$/.test(cleanHex)) return "";
920
- const r = parseInt(cleanHex.slice(0, 2), 16);
921
- const g = parseInt(cleanHex.slice(2, 4), 16);
922
- const b = parseInt(cleanHex.slice(4, 6), 16);
923
- return `\x1b[${isForeground ? 38 : 48};2;${r};${g};${b}m`;
924
- }
925
- function getLogLevelAnsiColor(level, variant) {
926
- return hexToAnsi((variant ? VARIANT_COLORS[variant] : DEFAULT_LOG_LEVEL_COLORS[level]).border, true);
927
- }
928
- function formatLevel(level, variant) {
929
- return `${getLogLevelAnsiColor(level, variant)}${BOLD}[${(variant ?? level).toUpperCase().padEnd(7)}]${RESET}`;
930
- }
931
- function formatTimestamp(date) {
932
- return `${DIM}${date.toLocaleTimeString()}${RESET}`;
933
- }
934
- function printMessage(message, stream) {
935
- switch (message.type) {
936
- case "log": {
937
- const logMessage = message;
938
- const timestamp = formatTimestamp(message.timestamp);
939
- const level = formatLevel(logMessage.level, logMessage.variant);
940
- const label = logMessage.label ? ` ${DIM}[${logMessage.label}]${RESET}` : "";
941
- stream.write(`${timestamp} ${level}${label} ${logMessage.content}\n`);
942
- break;
943
- }
944
- case "file": {
945
- const header = `${DIM}─── ${message.filePath} ───${RESET}`;
946
- stream.write(`${header}\n${message.content}\n`);
947
- break;
948
- }
949
- case "diff": {
950
- const header = `${DIM}─── ${message.filePath} (diff) ───${RESET}`;
951
- const coloredDiff = message.diff.split("\n").map((line) => {
952
- if (line.startsWith("+") && !line.startsWith("+++")) return `\x1b[32m${line}${RESET}`;
953
- else if (line.startsWith("-") && !line.startsWith("---")) return `\x1b[31m${line}${RESET}`;
954
- else if (line.startsWith("@@")) return `\x1b[36m${line}${RESET}`;
955
- return line;
956
- }).join("\n");
957
- stream.write(`${header}\n${coloredDiff}\n`);
958
- break;
959
- }
960
- case "fileError": {
961
- const header = `${DIM}─── ${message.filePath} ───${RESET}`;
962
- const errorLineSet = new Set(message.errorLines);
963
- const startLine = message.startLine ?? 1;
964
- const numberedLines = message.content.split("\n").map((line, index) => {
965
- const lineNum = startLine + index;
966
- const numStr = String(lineNum).padStart(4);
967
- if (errorLineSet.has(lineNum)) return `\x1b[31m${numStr} │ ${line}${RESET}`;
968
- return `${DIM}${numStr}${RESET} │ ${line}`;
969
- });
970
- stream.write(`${header}\n${numberedLines.join("\n")}\n`);
971
- break;
972
- }
973
- case "loading": {
974
- const loadingMessage = message;
975
- const status = loadingMessage.status;
976
- const content = loadingMessage.resolvedContent ?? loadingMessage.content;
977
- let level = "log";
978
- let variant;
979
- if (status === "success") {
980
- level = "log";
981
- variant = "success";
982
- } else if (status === "fail") level = "error";
983
- const timestamp = formatTimestamp(message.timestamp);
984
- const levelStr = formatLevel(level, variant);
985
- const prefix = status === "loading" ? "... " : "";
986
- stream.write(`${timestamp} ${levelStr} ${prefix}${content}\n`);
987
- break;
988
- }
989
- case "progress": {
990
- const { label, current, total, status, resolvedContent } = message;
991
- const percentage = total > 0 ? Math.round(current / total * 100) : 0;
992
- const barWidth = 20;
993
- const filledWidth = Math.round(percentage / 100 * barWidth);
994
- const emptyWidth = barWidth - filledWidth;
995
- const progressColor = hexToAnsi(PROGRESS_COLORS.barFilled);
996
- const emptyColor = hexToAnsi(PROGRESS_COLORS.barEmpty);
997
- const filledBar = "█".repeat(filledWidth);
998
- const emptyBar = "░".repeat(emptyWidth);
999
- let statusIcon = "";
1000
- let statusColor = "";
1001
- if (status === "complete") {
1002
- statusIcon = "✓";
1003
- statusColor = hexToAnsi(PROGRESS_COLORS.complete);
1004
- } else if (status === "failed") {
1005
- statusIcon = "✗";
1006
- statusColor = hexToAnsi(PROGRESS_COLORS.failed);
1007
- }
1008
- const displayLabel = resolvedContent ?? label;
1009
- const progressBar = `${progressColor}${filledBar}${RESET}${emptyColor}${emptyBar}${RESET}`;
1010
- const percentStr = `${String(percentage).padStart(3)}%`;
1011
- if (statusIcon) stream.write(`${statusColor}${statusIcon}${RESET} ${displayLabel} [${progressBar}] ${percentStr}\n`);
1012
- else stream.write(` ${displayLabel} [${progressBar}] ${percentStr} (${current}/${total})\n`);
1013
- break;
1014
- }
1015
- case "group": {
1016
- const { label, collapsed, isEnd } = message;
1017
- const groupColor = hexToAnsi(GROUP_COLORS.border);
1018
- const iconColor = hexToAnsi(GROUP_COLORS.icon);
1019
- if (isEnd) stream.write(`${groupColor}└─${RESET} ${DIM}end ${label}${RESET}\n`);
1020
- else {
1021
- const icon = collapsed ? "▶" : "▼";
1022
- stream.write(`${groupColor}┌─${RESET} ${iconColor}${icon}${RESET} ${BOLD}${label}${RESET}\n`);
1023
- }
1024
- break;
1025
- }
1026
- case "table": {
1027
- const { headers, rows, title } = message;
1028
- const tableColor = hexToAnsi(TABLE_COLORS.border);
1029
- const headerColor = hexToAnsi(TABLE_COLORS.headerText);
1030
- const cellColor = hexToAnsi(TABLE_COLORS.cellText);
1031
- const colWidths = headers.map((h, i) => {
1032
- const maxRowWidth = rows.reduce((max, row) => Math.max(max, (row[i] ?? "").length), 0);
1033
- return Math.max(h.length, maxRowWidth);
1034
- });
1035
- const separator = `${tableColor}├${colWidths.map((w) => "─".repeat(w + 2)).join("┼")}┤${RESET}`;
1036
- const topBorder = `${tableColor}┌${colWidths.map((w) => "─".repeat(w + 2)).join("┬")}┐${RESET}`;
1037
- const bottomBorder = `${tableColor}└${colWidths.map((w) => "─".repeat(w + 2)).join("┴")}┘${RESET}`;
1038
- if (title) stream.write(`${BOLD}${title}${RESET}\n`);
1039
- stream.write(`${topBorder}\n`);
1040
- const headerRow = headers.map((h, i) => ` ${h.padEnd(colWidths[i])} `).join(`${tableColor}│${RESET}`);
1041
- stream.write(`${tableColor}│${RESET}${headerColor}${headerRow}${RESET}${tableColor}│${RESET}\n`);
1042
- stream.write(`${separator}\n`);
1043
- for (const row of rows) {
1044
- const rowStr = headers.map((_, i) => ` ${(row[i] ?? "").padEnd(colWidths[i])} `).join(`${tableColor}│${RESET}`);
1045
- stream.write(`${tableColor}│${RESET}${cellColor}${rowStr}${RESET}${tableColor}│${RESET}\n`);
1046
- }
1047
- stream.write(`${bottomBorder}\n`);
1048
- break;
1049
- }
1050
- }
1051
- }
1052
- /**
1053
- * Print all messages to stdout (or stderr if isError)
1054
- */ function printMessagesToStdout(messages, screenName, isError = false) {
1055
- const stream = isError ? process.stderr : process.stdout;
1056
- const headerColor = isError ? "\x1B[31m" : "\x1B[32m";
1057
- const status = isError ? "FAILED" : "COMPLETED";
1058
- stream.write(`\n${headerColor}${BOLD}═══ ${screenName} [${status}] ═══${RESET}\n\n`);
1059
- for (const message of messages) printMessage(message, stream);
1060
- stream.write("\n");
1061
- }
1062
-
1063
- //#endregion
1064
- //#region src/utils/format.ts
1065
- /**
1066
- * Format an object for display with configurable depth
1067
- */ function formatObject(obj, depth = 2, currentDepth = 0) {
1068
- if (currentDepth >= depth) {
1069
- if (Array.isArray(obj)) return "[Array]";
1070
- if (typeof obj === "object" && obj !== null) return `[${obj.constructor?.name ?? "Object"}]`;
1071
- return String(obj);
1072
- }
1073
- if (obj === null) return "null";
1074
- if (obj === void 0) return "undefined";
1075
- if (typeof obj === "string") return `"${obj}"`;
1076
- if (typeof obj === "number" || typeof obj === "boolean") return String(obj);
1077
- if (typeof obj === "function") return "[Function]";
1078
- if (obj instanceof Date) return obj.toISOString();
1079
- if (obj instanceof Error) return `${obj.name}: ${obj.message}`;
1080
- const indent = " ".repeat(currentDepth);
1081
- const childIndent = " ".repeat(currentDepth + 1);
1082
- if (Array.isArray(obj)) {
1083
- if (obj.length === 0) return "[]";
1084
- return `[\n${childIndent}${obj.map((item) => formatObject(item, depth, currentDepth + 1)).join(`,\n${childIndent}`)}\n${indent}]`;
1085
- }
1086
- if (typeof obj === "object") {
1087
- const entries = Object.entries(obj);
1088
- if (entries.length === 0) return "{}";
1089
- return `{\n${childIndent}${entries.map(([key, value]) => `${key}: ${formatObject(value, depth, currentDepth + 1)}`).join(`,\n${childIndent}`)}\n${indent}}`;
1090
- }
1091
- return String(obj);
1092
- }
1093
- /**
1094
- * Capture a stack trace, filtering out internal frames
1095
- */ function captureTrace(offset = 0) {
1096
- const lines = ((/* @__PURE__ */ new Error()).stack ?? "").split("\n");
1097
- const begin = lines.findIndex((line) => line.includes("captureTrace"));
1098
- return lines.slice(begin !== -1 ? begin + 1 + offset : 4).join("\n");
1099
- }
1100
-
1101
- //#endregion
1102
- //#region src/components/log/log_message.tsx
1103
- /**
1104
- * LogMessage - A chat-like styled log message with level-based coloring.
1105
- *
1106
- * Features:
1107
- * - Left border with prominent color based on log level
1108
- * - Subtle tinted background matching the log level
1109
- * - Optional timestamp and label display
1110
- * - Supports both simple text and complex React children
1111
- * - Optional variant for semantic styling (e.g., 'success', 'trace')
1112
- *
1113
- * @example
1114
- * <LogMessage level="error">
1115
- * Connection failed: timeout after 30s
1116
- * </LogMessage>
1117
- *
1118
- * @example
1119
- * <LogMessage level="log" timestamp={new Date()} label="API">
1120
- * Request completed successfully
1121
- * </LogMessage>
1122
- *
1123
- * @example
1124
- * <LogMessage level="log" variant="success">
1125
- * Operation completed successfully
1126
- * </LogMessage>
1127
- */ function LogMessage({ level, variant, children, timestamp, label, trace, borderColor: customBorderColor, backgroundColor: customBackgroundColor, borderStyle = "thin", padding = 1, margin = 0 }) {
1128
- const theme = useTheme();
1129
- const levelColors = variant ? VARIANT_COLORS[variant] : theme.logLevels[level];
1130
- const borderColor = customBorderColor ?? levelColors.border;
1131
- const backgroundColor = customBackgroundColor ?? levelColors.background;
1132
- const textColor = levelColors.text ?? theme.colors.foreground;
1133
- const borderSides = borderStyle === "thin" ? ["left"] : [
1134
- "left",
1135
- "top",
1136
- "bottom"
1137
- ];
1138
- const formattedTimestamp = timestamp ? timestamp instanceof Date ? timestamp.toLocaleTimeString() : timestamp : null;
1139
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1140
- flexDirection: "column",
1141
- border: borderSides,
1142
- borderColor,
1143
- backgroundColor,
1144
- paddingLeft: padding,
1145
- paddingRight: padding,
1146
- marginBottom: margin,
1147
- children: [
1148
- (formattedTimestamp || label) && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1149
- flexDirection: "row",
1150
- gap: 1,
1151
- children: [formattedTimestamp && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1152
- fg: theme.colors.muted,
1153
- children: formattedTimestamp
1154
- }), label && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1155
- fg: levelColors.border,
1156
- attributes: _opentui_core.TextAttributes.BOLD,
1157
- children: [
1158
- "[",
1159
- label,
1160
- "]"
1161
- ]
1162
- })]
1163
- }),
1164
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1165
- fg: textColor,
1166
- children
1167
- }),
1168
- trace && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1169
- marginTop: 1,
1170
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1171
- fg: theme.colors.muted,
1172
- children: trace
1173
- })
1174
- })
1175
- ]
1176
- });
1177
- }
1178
-
1179
- //#endregion
1180
- //#region src/components/file/file_log.tsx
1181
- /**
1182
- * FileLog - Displays file content, diffs, or partial files with error highlighting.
1183
- *
1184
- * Three modes:
1185
- * 1. "full" - Display complete file with syntax highlighting
1186
- * 2. "diff" - Display unified diff using <diff> component
1187
- * 3. "partial" - Display file excerpt with optional error line highlighting
1188
- *
1189
- * @example Full file
1190
- * <FileLog
1191
- * mode="full"
1192
- * filePath="src/index.ts"
1193
- * content={fileContent}
1194
- * />
1195
- *
1196
- * @example Diff
1197
- * <FileLog
1198
- * mode="diff"
1199
- * filePath="src/api.ts"
1200
- * diff={unifiedDiff}
1201
- * view="unified"
1202
- * />
1203
- *
1204
- * @example Partial with error
1205
- * <FileLog
1206
- * mode="partial"
1207
- * filePath="src/utils.ts"
1208
- * content={excerpt}
1209
- * startLine={42}
1210
- * errorLines={[45, 46]}
1211
- * />
1212
- */ function FileLog(props) {
1213
- const { syntaxStyle, treeSitterClient } = useLoggerContext();
1214
- const filetype = props.filetype ?? resolveFiletype(props.filePath);
1215
- const showHeader = props.showHeader ?? true;
1216
- const showLineNumbers = props.showLineNumbers ?? true;
1217
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1218
- flexDirection: "column",
1219
- marginBottom: 1,
1220
- children: [
1221
- showHeader && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1222
- backgroundColor: props.headerBackgroundColor ?? HEADER_COLORS.background,
1223
- paddingLeft: 1,
1224
- paddingRight: 1,
1225
- border: ["bottom"],
1226
- borderColor: HEADER_COLORS.border,
1227
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1228
- fg: HEADER_COLORS.text,
1229
- children: props.filePath
1230
- })
1231
- }),
1232
- props.mode === "full" && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FileLogFull, {
1233
- ...props,
1234
- filetype,
1235
- syntaxStyle,
1236
- treeSitterClient,
1237
- showLineNumbers
1238
- }),
1239
- props.mode === "diff" && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FileLogDiff, {
1240
- ...props,
1241
- filetype,
1242
- syntaxStyle,
1243
- treeSitterClient
1244
- }),
1245
- props.mode === "partial" && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FileLogPartial, {
1246
- ...props,
1247
- filetype,
1248
- syntaxStyle,
1249
- treeSitterClient,
1250
- showLineNumbers
1251
- })
1252
- ]
1253
- });
1254
- }
1255
- /**
1256
- * Full file display with syntax highlighting.
1257
- */ function FileLogFull({ content, filetype, syntaxStyle, treeSitterClient }) {
1258
- if (!syntaxStyle) return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1259
- paddingLeft: 1,
1260
- paddingRight: 1,
1261
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", { children: content })
1262
- });
1263
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("code", {
1264
- content,
1265
- filetype,
1266
- syntaxStyle,
1267
- treeSitterClient
1268
- });
1269
- }
1270
- /**
1271
- * Diff display using the built-in <diff> component.
1272
- */ function FileLogDiff({ diff, view = "unified", filetype, syntaxStyle, treeSitterClient }) {
1273
- if (!syntaxStyle) return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1274
- paddingLeft: 1,
1275
- paddingRight: 1,
1276
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", { children: diff })
1277
- });
1278
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("diff", {
1279
- diff,
1280
- view,
1281
- filetype,
1282
- syntaxStyle,
1283
- treeSitterClient
1284
- });
1285
- }
1286
- /**
1287
- * Partial file display with error line highlighting.
1288
- *
1289
- * This component renders a file excerpt and highlights specific lines
1290
- * as errors using box overlays with colored backgrounds.
1291
- */ function FileLogPartial({ content, startLine, errorLines = [], errorLineBackground, errorLineBorderColor, filetype, syntaxStyle, treeSitterClient, showLineNumbers }) {
1292
- const lines = (0, react.useMemo)(() => content.split("\n"), [content]);
1293
- const errorLineSet = (0, react.useMemo)(() => new Set(errorLines), [errorLines]);
1294
- const errorBg = errorLineBackground ?? ERROR_HIGHLIGHT_COLORS.background;
1295
- const errorBorder = errorLineBorderColor ?? ERROR_HIGHLIGHT_COLORS.border;
1296
- const maxLineNum = startLine + lines.length - 1;
1297
- const lineNumWidth = Math.max(4, String(maxLineNum).length + 1);
1298
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1299
- flexDirection: "column",
1300
- children: lines.map((line, index) => {
1301
- const lineNumber = startLine + index;
1302
- const isError = errorLineSet.has(lineNumber);
1303
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1304
- flexDirection: "row",
1305
- backgroundColor: isError ? errorBg : void 0,
1306
- border: isError ? ["left"] : void 0,
1307
- borderColor: isError ? errorBorder : void 0,
1308
- children: [showLineNumbers && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1309
- width: lineNumWidth,
1310
- backgroundColor: isError ? ERROR_HIGHLIGHT_COLORS.gutterBackground : HEADER_COLORS.background,
1311
- paddingRight: 1,
1312
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1313
- fg: "#6B7280",
1314
- children: String(lineNumber).padStart(lineNumWidth - 1)
1315
- })
1316
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1317
- flexGrow: 1,
1318
- paddingLeft: 1,
1319
- children: syntaxStyle ? /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("code", {
1320
- content: line,
1321
- filetype,
1322
- syntaxStyle,
1323
- treeSitterClient
1324
- }) : /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", { children: line })
1325
- })]
1326
- }, lineNumber);
1327
- })
1328
- });
1329
- }
1330
-
1331
- //#endregion
1332
- //#region src/components/prompt/prompt_renderer.tsx
1333
- function PromptRenderer({ prompt }) {
1334
- const theme = useTheme();
1335
- const timeoutRemaining = getTimeoutRemaining(prompt);
1336
- switch (prompt.type) {
1337
- case "choice": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(ChoicePromptRenderer, {
1338
- prompt,
1339
- timeoutRemaining,
1340
- colors: theme.prompt
1341
- });
1342
- case "confirm": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(ConfirmPromptRenderer, {
1343
- prompt,
1344
- timeoutRemaining,
1345
- colors: theme.prompt
1346
- });
1347
- case "input": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(InputPromptRenderer, {
1348
- prompt,
1349
- timeoutRemaining,
1350
- colors: theme.prompt
1351
- });
1352
- case "multiChoice": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(MultiChoicePromptRenderer, {
1353
- prompt,
1354
- timeoutRemaining,
1355
- colors: theme.prompt
1356
- });
1357
- default: return null;
1358
- }
1359
- }
1360
- function getTimeoutRemaining(prompt) {
1361
- if (!prompt.timeout || !prompt.timeoutStarted) return null;
1362
- const elapsed = Date.now() - prompt.timeoutStarted;
1363
- const remaining = Math.max(0, prompt.timeout - elapsed);
1364
- return Math.ceil(remaining / 1e3);
1365
- }
1366
- function TimeoutIndicator({ seconds, colors }) {
1367
- if (seconds === null) return null;
1368
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1369
- fg: colors.optionTextDim,
1370
- attributes: _opentui_core.TextAttributes.DIM,
1371
- children: [
1372
- " ",
1373
- "(auto-select in ",
1374
- seconds,
1375
- "s)"
1376
- ]
1377
- });
1378
- }
1379
- function ChoicePromptRenderer({ prompt, timeoutRemaining, colors }) {
1380
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1381
- flexDirection: "column",
1382
- borderColor: colors.focusBorder,
1383
- border: ["left"],
1384
- paddingLeft: 1,
1385
- paddingRight: 1,
1386
- gap: 1,
1387
- children: [
1388
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1389
- flexDirection: "row",
1390
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1391
- fg: colors.question,
1392
- attributes: _opentui_core.TextAttributes.BOLD,
1393
- children: ["? ", prompt.question]
1394
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(TimeoutIndicator, {
1395
- seconds: timeoutRemaining,
1396
- colors
1397
- })]
1398
- }),
1399
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1400
- flexDirection: "column",
1401
- children: prompt.choices.map((choice, index) => {
1402
- const isSelected = index === prompt.selectedIndex;
1403
- const showInput = isSelected && choice.input && prompt.inputMode;
1404
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1405
- flexDirection: "row",
1406
- children: [
1407
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1408
- fg: isSelected ? colors.optionSelected : "transparent",
1409
- children: [">", " "]
1410
- }),
1411
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1412
- fg: isSelected ? colors.optionText : colors.optionTextDim,
1413
- attributes: isSelected ? _opentui_core.TextAttributes.BOLD : void 0,
1414
- children: choice.label
1415
- }),
1416
- showInput && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1417
- flexDirection: "row",
1418
- marginLeft: 1,
1419
- children: [
1420
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1421
- fg: colors.inputText,
1422
- children: ": "
1423
- }),
1424
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1425
- fg: colors.inputText,
1426
- children: prompt.inputValue
1427
- }),
1428
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1429
- fg: colors.inputCursor,
1430
- attributes: _opentui_core.TextAttributes.BLINK,
1431
- children: "_"
1432
- })
1433
- ]
1434
- }),
1435
- isSelected && choice.input && !prompt.inputMode && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1436
- fg: colors.optionTextDim,
1437
- children: " (press Enter to type)"
1438
- })
1439
- ]
1440
- }, choice.value);
1441
- })
1442
- }),
1443
- prompt.inputMode ? /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1444
- fg: colors.optionTextDim,
1445
- attributes: _opentui_core.TextAttributes.DIM,
1446
- children: "Type your answer, Enter to submit, Esc to cancel"
1447
- }) : /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1448
- fg: colors.optionTextDim,
1449
- attributes: _opentui_core.TextAttributes.DIM,
1450
- children: "↑/↓ to navigate, Enter to select"
1451
- })
1452
- ]
1453
- });
1454
- }
1455
- function ConfirmPromptRenderer({ prompt, timeoutRemaining, colors }) {
1456
- const confirmSelected = prompt.selectedValue === true;
1457
- const cancelSelected = prompt.selectedValue === false;
1458
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1459
- flexDirection: "column",
1460
- borderColor: colors.focusBorder,
1461
- border: ["left"],
1462
- paddingLeft: 1,
1463
- paddingRight: 1,
1464
- gap: 1,
1465
- children: [
1466
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1467
- flexDirection: "row",
1468
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1469
- fg: colors.question,
1470
- attributes: _opentui_core.TextAttributes.BOLD,
1471
- children: ["? ", prompt.question]
1472
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(TimeoutIndicator, {
1473
- seconds: timeoutRemaining,
1474
- colors
1475
- })]
1476
- }),
1477
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1478
- flexDirection: "row",
1479
- gap: 2,
1480
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1481
- backgroundColor: confirmSelected ? colors.buttonSelectedBackground : void 0,
1482
- paddingLeft: 1,
1483
- paddingRight: 1,
1484
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1485
- fg: confirmSelected ? colors.confirmButton : colors.optionTextDim,
1486
- attributes: confirmSelected ? _opentui_core.TextAttributes.BOLD : void 0,
1487
- children: [
1488
- confirmSelected ? ">" : " ",
1489
- " ",
1490
- prompt.confirmText
1491
- ]
1492
- })
1493
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1494
- backgroundColor: cancelSelected ? colors.buttonSelectedBackground : void 0,
1495
- paddingLeft: 1,
1496
- paddingRight: 1,
1497
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1498
- fg: cancelSelected ? colors.cancelButton : colors.optionTextDim,
1499
- attributes: cancelSelected ? _opentui_core.TextAttributes.BOLD : void 0,
1500
- children: [
1501
- cancelSelected ? ">" : " ",
1502
- " ",
1503
- prompt.cancelText
1504
- ]
1505
- })
1506
- })]
1507
- }),
1508
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1509
- fg: colors.optionTextDim,
1510
- attributes: _opentui_core.TextAttributes.DIM,
1511
- children: "←/→ to select, Enter to confirm"
1512
- })
1513
- ]
1514
- });
1515
- }
1516
- function InputPromptRenderer({ prompt, timeoutRemaining, colors }) {
1517
- const hasValue = prompt.value.length > 0;
1518
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1519
- flexDirection: "column",
1520
- borderColor: colors.focusBorder,
1521
- border: ["left"],
1522
- paddingLeft: 1,
1523
- paddingRight: 1,
1524
- gap: 1,
1525
- children: [
1526
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1527
- flexDirection: "row",
1528
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1529
- fg: colors.question,
1530
- attributes: _opentui_core.TextAttributes.BOLD,
1531
- children: ["? ", prompt.question]
1532
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(TimeoutIndicator, {
1533
- seconds: timeoutRemaining,
1534
- colors
1535
- })]
1536
- }),
1537
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1538
- flexDirection: "row",
1539
- borderColor: colors.inputBorder,
1540
- border: ["left"],
1541
- paddingLeft: 1,
1542
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1543
- fg: hasValue ? colors.inputText : colors.inputPlaceholder,
1544
- children: hasValue ? prompt.value : prompt.placeholder
1545
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1546
- fg: colors.inputCursor,
1547
- attributes: _opentui_core.TextAttributes.BLINK,
1548
- children: "_"
1549
- })]
1550
- }),
1551
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1552
- fg: colors.optionTextDim,
1553
- attributes: _opentui_core.TextAttributes.DIM,
1554
- children: "Type your answer, Enter to submit"
1555
- })
1556
- ]
1557
- });
1558
- }
1559
- function MultiChoicePromptRenderer({ prompt, timeoutRemaining, colors }) {
1560
- const selectedCount = prompt.selectedIndices.size;
1561
- const canSubmit = selectedCount >= prompt.minSelect;
1562
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1563
- flexDirection: "column",
1564
- borderColor: colors.focusBorder,
1565
- border: ["left"],
1566
- paddingLeft: 1,
1567
- paddingRight: 1,
1568
- gap: 1,
1569
- children: [
1570
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1571
- flexDirection: "row",
1572
- children: [
1573
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1574
- fg: colors.question,
1575
- attributes: _opentui_core.TextAttributes.BOLD,
1576
- children: ["? ", prompt.question]
1577
- }),
1578
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1579
- fg: colors.optionTextDim,
1580
- children: [
1581
- " ",
1582
- "(",
1583
- selectedCount,
1584
- "/",
1585
- prompt.maxSelect,
1586
- " selected)"
1587
- ]
1588
- }),
1589
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(TimeoutIndicator, {
1590
- seconds: timeoutRemaining,
1591
- colors
1592
- })
1593
- ]
1594
- }),
1595
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1596
- flexDirection: "column",
1597
- children: prompt.choices.map((choice, index) => {
1598
- const isFocused = index === prompt.focusedIndex;
1599
- const isChecked = prompt.selectedIndices.has(index);
1600
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1601
- flexDirection: "row",
1602
- children: [
1603
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1604
- fg: isFocused ? colors.optionSelected : "transparent",
1605
- children: [">", " "]
1606
- }),
1607
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1608
- fg: isChecked ? colors.optionSelected : colors.optionTextDim,
1609
- children: [isChecked ? "[✓]" : "[ ]", " "]
1610
- }),
1611
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1612
- fg: isFocused ? colors.optionText : colors.optionTextDim,
1613
- attributes: isFocused ? _opentui_core.TextAttributes.BOLD : void 0,
1614
- children: choice.label
1615
- })
1616
- ]
1617
- }, choice.value);
1618
- })
1619
- }),
1620
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1621
- flexDirection: "column",
1622
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1623
- fg: colors.optionTextDim,
1624
- attributes: _opentui_core.TextAttributes.DIM,
1625
- children: "↑/↓ to navigate, Space to toggle"
1626
- }), canSubmit ? /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1627
- fg: colors.optionTextDim,
1628
- attributes: _opentui_core.TextAttributes.DIM,
1629
- children: "Enter to confirm"
1630
- }) : /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1631
- fg: colors.cancelButton,
1632
- attributes: _opentui_core.TextAttributes.DIM,
1633
- children: [
1634
- "Select at least ",
1635
- prompt.minSelect,
1636
- " option",
1637
- prompt.minSelect > 1 ? "s" : ""
1638
- ]
1639
- })]
1640
- })
1641
- ]
1642
- });
1643
- }
1644
-
1645
- //#endregion
1646
- //#region src/components/screen/loading_message.tsx
1647
- const SPINNER_FRAMES = [
1648
- "⠋",
1649
- "⠙",
1650
- "⠹",
1651
- "⠸",
1652
- "⠼",
1653
- "⠴",
1654
- "⠦",
1655
- "⠧",
1656
- "⠇",
1657
- "⠏"
1658
- ];
1659
- function LoadingMessage({ message }) {
1660
- const [frameIndex, setFrameIndex] = (0, react.useState)(0);
1661
- const intervalRef = (0, react.useRef)(null);
1662
- (0, react.useEffect)(() => {
1663
- if (message.status === "loading") intervalRef.current = setInterval(() => {
1664
- setFrameIndex((prev) => (prev + 1) % SPINNER_FRAMES.length);
1665
- }, 80);
1666
- return () => {
1667
- if (intervalRef.current) clearInterval(intervalRef.current);
1668
- };
1669
- }, [message.status]);
1670
- const level = message.status === "fail" ? "error" : "log";
1671
- const variant = message.status === "success" ? "success" : void 0;
1672
- const displayContent = message.resolvedContent ?? message.content;
1673
- const spinner = message.status === "loading" ? SPINNER_FRAMES[frameIndex] + " " : "";
1674
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)(LogMessage, {
1675
- level,
1676
- variant,
1677
- timestamp: message.timestamp,
1678
- children: [spinner, displayContent]
1679
- });
1680
- }
1681
-
1682
- //#endregion
1683
- //#region src/components/screen/progress_message.tsx
1684
- function ProgressMessage({ message }) {
1685
- const theme = useTheme();
1686
- const percent = Math.round(message.current / message.total * 100);
1687
- const barWidth = 20;
1688
- const filled = Math.round(percent / 100 * barWidth);
1689
- const empty = barWidth - filled;
1690
- const barFilled = "█".repeat(filled);
1691
- const barEmpty = "░".repeat(empty);
1692
- const borderColor = message.status === "complete" ? theme.progress.complete : message.status === "failed" ? theme.progress.failed : theme.progress.border;
1693
- const backgroundColor = message.status === "complete" ? theme.progress.completeBackground : message.status === "failed" ? theme.progress.failedBackground : theme.progress.background;
1694
- const barColor = message.status === "complete" ? theme.progress.complete : message.status === "failed" ? theme.progress.failed : theme.progress.barFilled;
1695
- const displayLabel = message.resolvedContent ?? message.label;
1696
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1697
- flexDirection: "column",
1698
- border: ["left"],
1699
- borderColor,
1700
- backgroundColor,
1701
- paddingLeft: 1,
1702
- paddingRight: 1,
1703
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1704
- flexDirection: "row",
1705
- gap: 1,
1706
- children: [
1707
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1708
- fg: barColor,
1709
- children: ["[", barFilled]
1710
- }),
1711
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1712
- fg: theme.progress.barEmpty,
1713
- children: [barEmpty, "]"]
1714
- }),
1715
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1716
- fg: theme.progress.textDim,
1717
- children: [percent, "%"]
1718
- }),
1719
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1720
- fg: theme.progress.text,
1721
- children: displayLabel
1722
- })
1723
- ]
1724
- })
1725
- });
1726
- }
1727
-
1728
- //#endregion
1729
- //#region src/components/screen/table_message.tsx
1730
- function TableMessage({ message }) {
1731
- const colWidths = message.headers.map((h, i) => {
1732
- const headerLen = h.length;
1733
- const maxRowLen = message.rows.length > 0 ? Math.max(...message.rows.map((r) => (r[i] ?? "").length)) : 0;
1734
- return Math.max(headerLen, maxRowLen);
1735
- });
1736
- const pad = (str, width) => str.padEnd(width);
1737
- const headerRow = message.headers.map((h, i) => pad(h, colWidths[i] ?? 0)).join(" │ ");
1738
- const separator = colWidths.map((w) => "─".repeat(w)).join("─┼─");
1739
- const dataRows = message.rows.map((row) => row.map((cell, i) => pad(cell, colWidths[i] ?? 0)).join(" │ "));
1740
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1741
- flexDirection: "column",
1742
- border: ["left"],
1743
- borderColor: TABLE_COLORS.border,
1744
- backgroundColor: TABLE_COLORS.background,
1745
- paddingLeft: 1,
1746
- paddingRight: 1,
1747
- children: [
1748
- message.title && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1749
- fg: TABLE_COLORS.title,
1750
- attributes: _opentui_core.TextAttributes.BOLD,
1751
- children: message.title
1752
- }),
1753
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1754
- fg: TABLE_COLORS.headerText,
1755
- attributes: _opentui_core.TextAttributes.BOLD,
1756
- children: headerRow
1757
- }),
1758
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1759
- fg: TABLE_COLORS.separator,
1760
- children: separator
1761
- }),
1762
- dataRows.map((row, i) => /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1763
- fg: TABLE_COLORS.cellText,
1764
- children: row
1765
- }, i))
1766
- ]
1767
- });
1768
- }
1769
-
1770
- //#endregion
1771
- //#region src/components/screen/message_renderer.tsx
1772
- function MessageRenderer({ message }) {
1773
- const theme = useTheme();
1774
- switch (message.type) {
1775
- case "log": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(LogMessage, {
1776
- level: message.level,
1777
- timestamp: message.timestamp,
1778
- variant: message.variant,
1779
- label: message.label,
1780
- trace: message.trace,
1781
- children: message.content
1782
- });
1783
- case "file": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1784
- flexDirection: "column",
1785
- border: ["left"],
1786
- borderColor: theme.file.border,
1787
- backgroundColor: theme.file.background,
1788
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FileLog, {
1789
- mode: "full",
1790
- filePath: message.filePath,
1791
- content: message.content,
1792
- headerBackgroundColor: theme.file.headerBackground
1793
- })
1794
- });
1795
- case "diff": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1796
- flexDirection: "column",
1797
- border: ["left"],
1798
- borderColor: theme.file.border,
1799
- backgroundColor: theme.file.background,
1800
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FileLog, {
1801
- mode: "diff",
1802
- filePath: message.filePath,
1803
- diff: message.diff,
1804
- view: message.view,
1805
- headerBackgroundColor: theme.file.headerBackground
1806
- })
1807
- });
1808
- case "fileError": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1809
- flexDirection: "column",
1810
- border: ["left"],
1811
- borderColor: theme.file.border,
1812
- backgroundColor: theme.file.background,
1813
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FileLog, {
1814
- mode: "partial",
1815
- filePath: message.filePath,
1816
- content: message.content,
1817
- startLine: message.startLine,
1818
- errorLines: message.errorLines,
1819
- headerBackgroundColor: theme.file.headerBackground
1820
- })
1821
- });
1822
- case "loading": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(LoadingMessage, { message });
1823
- case "progress": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(ProgressMessage, { message });
1824
- case "group": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(GroupMessageRenderer, { message });
1825
- case "table": return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(TableMessage, { message });
1826
- default: return null;
1827
- }
1828
- }
1829
-
1830
- //#endregion
1831
- //#region src/components/screen/group_renderer.tsx
1832
- function GroupRenderer({ label, messages }) {
1833
- const theme = useTheme();
1834
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1835
- flexDirection: "column",
1836
- border: ["left"],
1837
- borderColor: theme.group.border,
1838
- backgroundColor: theme.group.background,
1839
- paddingLeft: 1,
1840
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1841
- flexDirection: "row",
1842
- marginBottom: 1,
1843
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1844
- fg: theme.group.icon,
1845
- children: "▼ "
1846
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1847
- fg: theme.group.headerText,
1848
- attributes: _opentui_core.TextAttributes.BOLD,
1849
- children: label
1850
- })]
1851
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1852
- flexDirection: "column",
1853
- gap: 1,
1854
- children: messages.map((msg) => /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(MessageRenderer, { message: msg }, msg.id))
1855
- })]
1856
- });
1857
- }
1858
- /**
1859
- * Fallback renderer for group markers (when not processed at higher level)
1860
- */ function GroupMessageRenderer({ message }) {
1861
- const theme = useTheme();
1862
- if (message.isEnd) return null;
1863
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
1864
- flexDirection: "row",
1865
- borderColor: theme.group.border,
1866
- border: ["left"],
1867
- paddingLeft: 1,
1868
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1869
- fg: theme.group.headerText,
1870
- attributes: _opentui_core.TextAttributes.BOLD,
1871
- children: ["▼ ", message.label]
1872
- })
1873
- });
1874
- }
1875
-
1876
- //#endregion
1877
- //#region src/components/screen/screen_bridge.tsx
1878
- function processMessagesIntoGroups(messages) {
1879
- const result = [];
1880
- let i = 0;
1881
- while (i < messages.length) {
1882
- const msg = messages[i];
1883
- if (msg.type === "group" && !msg.isEnd) {
1884
- const groupLabel = msg.label;
1885
- const groupMessages = [];
1886
- i++;
1887
- while (i < messages.length) {
1888
- const innerMsg = messages[i];
1889
- if (innerMsg.type === "group" && innerMsg.isEnd) {
1890
- i++;
1891
- break;
1892
- }
1893
- groupMessages.push(innerMsg);
1894
- i++;
1895
- }
1896
- result.push({
1897
- type: "group",
1898
- label: groupLabel,
1899
- messages: groupMessages
1900
- });
1901
- } else if (msg.type === "group" && msg.isEnd) i++;
1902
- else {
1903
- result.push({
1904
- type: "single",
1905
- message: msg
1906
- });
1907
- i++;
1908
- }
1909
- }
1910
- return result;
1911
- }
1912
- function ScreenBridge({ screen, focused, filteredMessages, isFiltering, totalMessages }) {
1913
- const theme = useTheme();
1914
- const [, forceUpdate] = (0, react.useState)({});
1915
- (0, react.useEffect)(() => {
1916
- return screen.onChange(() => forceUpdate({}));
1917
- }, [screen]);
1918
- const messages = filteredMessages ?? screen.getMessages();
1919
- const activePrompt = screen.getActivePrompt();
1920
- const processedMessages = processMessagesIntoGroups(messages);
1921
- const filteredCount = messages.length;
1922
- const total = totalMessages ?? messages.length;
1923
- const showFilterStatus = isFiltering && filteredCount !== total;
1924
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1925
- flexDirection: "column",
1926
- flexGrow: 1,
1927
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1928
- backgroundColor: theme.header.background,
1929
- borderColor: focused ? theme.sidebar.focusBorder : theme.header.border,
1930
- border: ["bottom"],
1931
- paddingLeft: 1,
1932
- paddingRight: 1,
1933
- flexDirection: "row",
1934
- justifyContent: "space-between",
1935
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1936
- fg: theme.header.text,
1937
- attributes: _opentui_core.TextAttributes.BOLD,
1938
- children: screen.getName()
1939
- }), showFilterStatus && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1940
- fg: theme.sidebar.textDim,
1941
- children: [
1942
- filteredCount,
1943
- "/",
1944
- total,
1945
- " messages"
1946
- ]
1947
- })]
1948
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("scrollbox", {
1949
- flexGrow: 1,
1950
- scrollY: true,
1951
- stickyScroll: true,
1952
- stickyStart: "bottom",
1953
- contentOptions: {
1954
- paddingLeft: 1,
1955
- paddingRight: 1,
1956
- paddingTop: 1,
1957
- paddingBottom: 1,
1958
- gap: 1
1959
- },
1960
- children: [processedMessages.map((item, index) => {
1961
- if (item.type === "group") return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(GroupRenderer, {
1962
- label: item.label,
1963
- messages: item.messages
1964
- }, `group-${index}`);
1965
- else return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(MessageRenderer, { message: item.message }, item.message.id);
1966
- }), activePrompt && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(PromptRenderer, { prompt: activePrompt })]
1967
- })]
1968
- });
1969
- }
1970
-
1971
- //#endregion
1972
- //#region src/components/sidebar/sidebar_item.tsx
1973
- function SidebarItem({ screen, isSelected, isActive, focused }) {
1974
- const theme = useTheme();
1975
- const status = screen.getStatus();
1976
- const statusIndicator = theme.statusIndicators[status];
1977
- let backgroundColor = void 0;
1978
- if (isSelected && focused) backgroundColor = theme.sidebar.selectedBackground;
1979
- else if (isActive) backgroundColor = theme.sidebar.selectedBackground + "80";
1980
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
1981
- flexDirection: "row",
1982
- paddingLeft: 1,
1983
- paddingRight: 1,
1984
- backgroundColor,
1985
- children: [
1986
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1987
- fg: isSelected && focused ? theme.sidebar.focusBorder : "transparent",
1988
- children: [">", " "]
1989
- }),
1990
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
1991
- fg: statusIndicator.color,
1992
- children: [statusIndicator.icon, " "]
1993
- }),
1994
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
1995
- fg: isActive ? theme.sidebar.text : theme.sidebar.textDim,
1996
- flexGrow: 1,
1997
- children: screen.getName()
1998
- }),
1999
- screen.getBadgeCount() > 0 && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2000
- backgroundColor: theme.sidebar.badge,
2001
- paddingLeft: 1,
2002
- paddingRight: 1,
2003
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2004
- fg: theme.colors.foreground,
2005
- attributes: _opentui_core.TextAttributes.BOLD,
2006
- children: screen.getBadgeCount() > 99 ? "99+" : screen.getBadgeCount()
2007
- })
2008
- })
2009
- ]
2010
- });
2011
- }
2012
-
2013
- //#endregion
2014
- //#region src/components/sidebar/sidebar_separator.tsx
2015
- function SidebarSeparator() {
2016
- const theme = useTheme();
2017
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2018
- flexDirection: "row",
2019
- paddingTop: 1,
2020
- children: [
2021
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", { flexGrow: 1 }),
2022
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2023
- fg: theme.separator.line,
2024
- children: "· · ·"
2025
- }),
2026
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", { flexGrow: 1 })
2027
- ]
2028
- });
2029
- }
2030
-
2031
- //#endregion
2032
- //#region src/components/sidebar/sidebar.tsx
2033
- function Sidebar({ screens, selectedIndex, activeScreenId, focused, width, title }) {
2034
- const theme = useTheme();
2035
- const pendingScreens = [];
2036
- const otherScreens = [];
2037
- screens.forEach((screen, index) => {
2038
- if (screen.getStatus() === "pending") pendingScreens.push({
2039
- screen,
2040
- originalIndex: index
2041
- });
2042
- else otherScreens.push({
2043
- screen,
2044
- originalIndex: index
2045
- });
2046
- });
2047
- const hasPending = pendingScreens.length > 0;
2048
- const hasOther = otherScreens.length > 0;
2049
- const showSeparator = hasPending && hasOther;
2050
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2051
- flexDirection: "column",
2052
- width,
2053
- borderColor: focused ? theme.sidebar.focusBorder : theme.sidebar.border,
2054
- border: ["right"],
2055
- children: [
2056
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2057
- backgroundColor: theme.header.background,
2058
- paddingLeft: 1,
2059
- paddingRight: 1,
2060
- borderColor: theme.header.border,
2061
- border: ["bottom"],
2062
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2063
- fg: theme.header.text,
2064
- attributes: _opentui_core.TextAttributes.BOLD,
2065
- children: title
2066
- })
2067
- }),
2068
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("scrollbox", {
2069
- scrollY: true,
2070
- stickyScroll: false,
2071
- flexGrow: 1,
2072
- contentOptions: { flexGrow: 1 },
2073
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2074
- flexDirection: "column",
2075
- children: [
2076
- pendingScreens.map(({ screen, originalIndex }) => /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(SidebarItem, {
2077
- screen,
2078
- isSelected: originalIndex === selectedIndex,
2079
- isActive: screen.getId() === activeScreenId,
2080
- focused
2081
- }, screen.getId())),
2082
- showSeparator && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(SidebarSeparator, {}),
2083
- otherScreens.map(({ screen, originalIndex }) => /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(SidebarItem, {
2084
- screen,
2085
- isSelected: originalIndex === selectedIndex,
2086
- isActive: screen.getId() === activeScreenId,
2087
- focused
2088
- }, screen.getId()))
2089
- ]
2090
- })
2091
- }),
2092
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2093
- paddingLeft: 1,
2094
- paddingRight: 1,
2095
- borderColor: theme.sidebar.border,
2096
- border: ["top"],
2097
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2098
- fg: theme.sidebar.text,
2099
- children: "q: exit | Tab: focus | ?: help"
2100
- })
2101
- })
2102
- ]
2103
- });
2104
- }
2105
-
2106
- //#endregion
2107
- //#region src/filter/filter_engine.ts
2108
- /**
2109
- * Filter engine for filtering log messages.
2110
- */ var FilterEngine = class {
2111
- /**
2112
- * Apply filter to messages array.
2113
- */ static filterMessages(messages, filter) {
2114
- if (filter.searchQuery === "" && filter.enabledLevels.size === ALL_LOG_LEVELS.length) return messages;
2115
- return messages.filter((msg) => {
2116
- if (msg.type !== "log") {
2117
- if (filter.searchQuery) return this.messageMatchesSearch(msg, filter.searchQuery);
2118
- if (msg.type === "group") return true;
2119
- return true;
2120
- }
2121
- const logMsg = msg;
2122
- if (!filter.enabledLevels.has(logMsg.level)) return false;
2123
- if (filter.searchQuery && !this.messageMatchesSearch(logMsg, filter.searchQuery)) return false;
2124
- return true;
2125
- });
2126
- }
2127
- /**
2128
- * Check if a message matches the search query.
2129
- */ static messageMatchesSearch(msg, query) {
2130
- const lowerQuery = query.toLowerCase();
2131
- switch (msg.type) {
2132
- case "log": return msg.content.toLowerCase().includes(lowerQuery) || (msg.label?.toLowerCase().includes(lowerQuery) ?? false);
2133
- case "file":
2134
- case "fileError": return msg.filePath.toLowerCase().includes(lowerQuery) || msg.content.toLowerCase().includes(lowerQuery);
2135
- case "diff": return msg.filePath.toLowerCase().includes(lowerQuery) || msg.diff.toLowerCase().includes(lowerQuery);
2136
- case "loading": return msg.content.toLowerCase().includes(lowerQuery) || (msg.resolvedContent?.toLowerCase().includes(lowerQuery) ?? false);
2137
- case "progress": return msg.label.toLowerCase().includes(lowerQuery);
2138
- case "group": return msg.label.toLowerCase().includes(lowerQuery);
2139
- case "table": return (msg.title?.toLowerCase().includes(lowerQuery) ?? false) || msg.headers.some((h) => h.toLowerCase().includes(lowerQuery)) || msg.rows.some((row) => row.some((cell) => cell.toLowerCase().includes(lowerQuery)));
2140
- default: return false;
2141
- }
2142
- }
2143
- /**
2144
- * Count messages by log level.
2145
- */ static countByLevel(messages) {
2146
- const counts = {
2147
- debug: 0,
2148
- log: 0,
2149
- verbose: 0,
2150
- error: 0,
2151
- fatal: 0,
2152
- warn: 0
2153
- };
2154
- for (const msg of messages) if (msg.type === "log") counts[msg.level]++;
2155
- return counts;
2156
- }
2157
- };
2158
-
2159
- //#endregion
2160
- //#region src/keyboard/keyboard_manager.ts
2161
- /**
2162
- * Manages keyboard bindings and dispatches key events to handlers.
2163
- */ var KeyboardManager = class {
2164
- bindings = [];
2165
- disabled = /* @__PURE__ */ new Set();
2166
- constructor(config) {
2167
- if (config?.bindings) this.bindings = [...config.bindings];
2168
- if (config?.disabled) this.disabled = new Set(config.disabled);
2169
- this.sortBindings();
2170
- }
2171
- /**
2172
- * Add bindings to the manager.
2173
- */ addBindings(bindings) {
2174
- this.bindings.push(...bindings);
2175
- this.sortBindings();
2176
- }
2177
- /**
2178
- * Remove a binding by key name.
2179
- */ removeBinding(key) {
2180
- this.bindings = this.bindings.filter((b) => {
2181
- return !(Array.isArray(b.key) ? b.key : [b.key]).includes(key);
2182
- });
2183
- }
2184
- /**
2185
- * Disable a key (prevents it from being matched).
2186
- */ disableKey(key) {
2187
- this.disabled.add(key);
2188
- }
2189
- /**
2190
- * Enable a previously disabled key.
2191
- */ enableKey(key) {
2192
- this.disabled.delete(key);
2193
- }
2194
- /**
2195
- * Handle a key event, dispatching to the appropriate handler.
2196
- * Returns true if a handler consumed the event.
2197
- */ handleKey(key, context) {
2198
- const binding = this.findMatchingBinding(key, context);
2199
- if (binding) return binding.handler(key, context) !== false;
2200
- return false;
2201
- }
2202
- /**
2203
- * Get all bindings for display in help overlay.
2204
- */ getBindingsForHelp() {
2205
- return this.bindings.filter((b) => b.description);
2206
- }
2207
- /**
2208
- * Get bindings grouped by category.
2209
- */ getBindingsByCategory() {
2210
- const grouped = {
2211
- general: [],
2212
- navigation: [],
2213
- screen: [],
2214
- prompt: [],
2215
- filter: []
2216
- };
2217
- for (const binding of this.bindings) if (binding.description) grouped[binding.category].push(binding);
2218
- return grouped;
2219
- }
2220
- /**
2221
- * Find a matching binding for the given key and context.
2222
- */ findMatchingBinding(key, context) {
2223
- for (const binding of this.bindings) if (this.keyMatches(key, binding) && this.conditionMatches(binding.when, context) && !this.isDisabled(binding)) return binding;
2224
- return null;
2225
- }
2226
- /**
2227
- * Check if a key event matches a binding's key specification.
2228
- */ keyMatches(key, binding) {
2229
- const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
2230
- if (!(keys.includes(key.name) || key.sequence && keys.includes(key.sequence))) return false;
2231
- const ctrlMatches = (binding.ctrl ?? false) === (key.ctrl ?? false);
2232
- const metaMatches = (binding.meta ?? false) === (key.meta ?? false);
2233
- const shiftMatches = (binding.shift ?? false) === (key.shift ?? false);
2234
- return ctrlMatches && metaMatches && shiftMatches;
2235
- }
2236
- /**
2237
- * Check if context matches a binding's condition.
2238
- */ conditionMatches(condition, context) {
2239
- if (!condition) return true;
2240
- if (condition.hasPrompt !== void 0 && condition.hasPrompt !== context.hasPrompt) return false;
2241
- if (condition.inInputMode !== void 0 && condition.inInputMode !== context.inInputMode) return false;
2242
- if (condition.focusArea !== void 0 && condition.focusArea !== context.focusArea) return false;
2243
- if (condition.isFilterActive !== void 0 && condition.isFilterActive !== context.isFilterActive) return false;
2244
- if (condition.isHelpVisible !== void 0 && condition.isHelpVisible !== context.isHelpVisible) return false;
2245
- if (condition.hasSidebar !== void 0 && condition.hasSidebar !== context.hasSidebar) return false;
2246
- return true;
2247
- }
2248
- /**
2249
- * Check if a binding is disabled.
2250
- */ isDisabled(binding) {
2251
- return (Array.isArray(binding.key) ? binding.key : [binding.key]).some((k) => this.disabled.has(k));
2252
- }
2253
- /**
2254
- * Sort bindings by priority (higher first).
2255
- */ sortBindings() {
2256
- this.bindings.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
2257
- }
2258
- };
2259
- /**
2260
- * Format a key binding for display.
2261
- */ function formatKeyBinding(binding) {
2262
- const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
2263
- const parts = [];
2264
- if (binding.ctrl) parts.push("Ctrl");
2265
- if (binding.meta) parts.push("Cmd");
2266
- if (binding.shift) parts.push("Shift");
2267
- const keyDisplay = keys.map((k) => {
2268
- switch (k) {
2269
- case "up": return "↑";
2270
- case "down": return "↓";
2271
- case "left": return "←";
2272
- case "right": return "→";
2273
- case "return": return "Enter";
2274
- case "escape": return "Esc";
2275
- case "space": return "Space";
2276
- case "tab": return "Tab";
2277
- case "\\": return "\\";
2278
- default: return k;
2279
- }
2280
- }).join("/");
2281
- parts.push(keyDisplay);
2282
- return parts.join("+");
2283
- }
2284
-
2285
- //#endregion
2286
- //#region src/keyboard/create_bindings.ts
2287
- /**
2288
- * Create the default keybindings with access to manager and screens.
2289
- */ function createDefaultBindings(handlers) {
2290
- const { manager, getActiveScreen, toggleHelp, toggleFilter, closeFilter } = handlers;
2291
- const bindings = [];
2292
- bindings.push({
2293
- key: "escape",
2294
- handler: () => {
2295
- const screen = getActiveScreen();
2296
- if (screen?.isPromptInInputMode()) {
2297
- screen.promptExitInputMode();
2298
- return true;
2299
- }
2300
- },
2301
- description: "Exit input mode",
2302
- category: "prompt",
2303
- when: {
2304
- hasPrompt: true,
2305
- inInputMode: true
2306
- },
2307
- priority: 100
2308
- });
2309
- bindings.push({
2310
- key: "return",
2311
- handler: () => {
2312
- const screen = getActiveScreen();
2313
- if (screen?.isPromptInInputMode()) {
2314
- screen.promptSubmit();
2315
- return true;
2316
- }
2317
- },
2318
- description: "Submit input",
2319
- category: "prompt",
2320
- when: {
2321
- hasPrompt: true,
2322
- inInputMode: true
2323
- },
2324
- priority: 100
2325
- });
2326
- bindings.push({
2327
- key: "backspace",
2328
- handler: () => {
2329
- const screen = getActiveScreen();
2330
- if (screen?.isPromptInInputMode()) {
2331
- screen.promptDeleteLastChar();
2332
- return true;
2333
- }
2334
- },
2335
- description: "Delete character",
2336
- category: "prompt",
2337
- when: {
2338
- hasPrompt: true,
2339
- inInputMode: true
2340
- },
2341
- priority: 100
2342
- });
2343
- bindings.push({
2344
- key: ["up", "k"],
2345
- handler: () => {
2346
- const screen = getActiveScreen();
2347
- const prompt = screen?.getActivePrompt();
2348
- if (prompt?.type === "choice" || prompt?.type === "multiChoice") {
2349
- screen?.promptNavigateUp();
2350
- return true;
2351
- }
2352
- },
2353
- description: "Navigate up",
2354
- category: "prompt",
2355
- when: {
2356
- hasPrompt: true,
2357
- inInputMode: false
2358
- },
2359
- priority: 90
2360
- });
2361
- bindings.push({
2362
- key: ["down", "j"],
2363
- handler: () => {
2364
- const screen = getActiveScreen();
2365
- const prompt = screen?.getActivePrompt();
2366
- if (prompt?.type === "choice" || prompt?.type === "multiChoice") {
2367
- screen?.promptNavigateDown();
2368
- return true;
2369
- }
2370
- },
2371
- description: "Navigate down",
2372
- category: "prompt",
2373
- when: {
2374
- hasPrompt: true,
2375
- inInputMode: false
2376
- },
2377
- priority: 90
2378
- });
2379
- bindings.push({
2380
- key: ["left", "h"],
2381
- handler: () => {
2382
- const screen = getActiveScreen();
2383
- if ((screen?.getActivePrompt())?.type === "confirm") {
2384
- screen?.promptNavigateLeft();
2385
- return true;
2386
- }
2387
- },
2388
- description: "Select confirm",
2389
- category: "prompt",
2390
- when: {
2391
- hasPrompt: true,
2392
- inInputMode: false
2393
- },
2394
- priority: 90
2395
- });
2396
- bindings.push({
2397
- key: ["right", "l"],
2398
- handler: () => {
2399
- const screen = getActiveScreen();
2400
- if ((screen?.getActivePrompt())?.type === "confirm") {
2401
- screen?.promptNavigateRight();
2402
- return true;
2403
- }
2404
- },
2405
- description: "Select cancel",
2406
- category: "prompt",
2407
- when: {
2408
- hasPrompt: true,
2409
- inInputMode: false
2410
- },
2411
- priority: 90
2412
- });
2413
- bindings.push({
2414
- key: "space",
2415
- handler: () => {
2416
- const screen = getActiveScreen();
2417
- if ((screen?.getActivePrompt())?.type === "multiChoice") {
2418
- screen?.promptToggleSelection();
2419
- return true;
2420
- }
2421
- },
2422
- description: "Toggle selection",
2423
- category: "prompt",
2424
- when: {
2425
- hasPrompt: true,
2426
- inInputMode: false
2427
- },
2428
- priority: 90
2429
- });
2430
- bindings.push({
2431
- key: "return",
2432
- handler: () => {
2433
- const screen = getActiveScreen();
2434
- const prompt = screen?.getActivePrompt();
2435
- if (!prompt) return false;
2436
- if (prompt.type === "choice") {
2437
- if (!screen?.promptEnterInputMode()) screen?.promptSubmit();
2438
- return true;
2439
- } else if (prompt.type === "confirm") {
2440
- screen?.promptSubmit();
2441
- return true;
2442
- } else if (prompt.type === "multiChoice") {
2443
- if (screen?.canSubmitPrompt()) screen.promptSubmit();
2444
- return true;
2445
- }
2446
- },
2447
- description: "Submit selection",
2448
- category: "prompt",
2449
- when: {
2450
- hasPrompt: true,
2451
- inInputMode: false
2452
- },
2453
- priority: 90
2454
- });
2455
- bindings.push({
2456
- key: "?",
2457
- handler: () => {
2458
- toggleHelp();
2459
- return true;
2460
- },
2461
- description: "Toggle help",
2462
- category: "general",
2463
- when: {
2464
- hasPrompt: false,
2465
- isFilterActive: false
2466
- },
2467
- priority: 50
2468
- });
2469
- bindings.push({
2470
- key: "escape",
2471
- handler: () => {
2472
- toggleHelp();
2473
- return true;
2474
- },
2475
- description: "Close help",
2476
- category: "general",
2477
- when: { isHelpVisible: true },
2478
- priority: 80
2479
- });
2480
- bindings.push({
2481
- key: "/",
2482
- handler: () => {
2483
- toggleFilter();
2484
- return true;
2485
- },
2486
- description: "Toggle filter",
2487
- category: "filter",
2488
- when: {
2489
- hasPrompt: false,
2490
- isHelpVisible: false
2491
- },
2492
- priority: 50
2493
- });
2494
- bindings.push({
2495
- key: "escape",
2496
- handler: () => {
2497
- closeFilter();
2498
- return true;
2499
- },
2500
- description: "Close filter",
2501
- category: "filter",
2502
- when: { isFilterActive: true },
2503
- priority: 70
2504
- });
2505
- bindings.push({
2506
- key: "tab",
2507
- handler: () => {
2508
- handlers.filterCycleField();
2509
- return true;
2510
- },
2511
- description: "Cycle filter fields",
2512
- category: "filter",
2513
- when: { isFilterActive: true },
2514
- priority: 70
2515
- });
2516
- bindings.push({
2517
- key: "backspace",
2518
- handler: () => {
2519
- handlers.filterDeleteChar();
2520
- return true;
2521
- },
2522
- description: "Delete character",
2523
- category: "filter",
2524
- when: { isFilterActive: true },
2525
- priority: 70
2526
- });
2527
- for (let i = 1; i <= 7; i++) bindings.push({
2528
- key: String(i),
2529
- handler: () => {
2530
- handlers.filterToggleLevel(i - 1);
2531
- return true;
2532
- },
2533
- description: `Toggle level ${i}`,
2534
- category: "filter",
2535
- when: { isFilterActive: true },
2536
- priority: 70
2537
- });
2538
- bindings.push({
2539
- key: "q",
2540
- handler: () => {
2541
- manager.unbind();
2542
- return true;
2543
- },
2544
- description: "Exit",
2545
- category: "general",
2546
- when: {
2547
- hasPrompt: false,
2548
- isFilterActive: false,
2549
- isHelpVisible: false
2550
- },
2551
- priority: 10
2552
- });
2553
- bindings.push({
2554
- key: "tab",
2555
- handler: (_, ctx) => {
2556
- if (ctx.hasSidebar) {
2557
- manager.toggleFocus();
2558
- return true;
2559
- }
2560
- },
2561
- description: "Toggle focus",
2562
- category: "navigation",
2563
- when: {
2564
- hasPrompt: false,
2565
- isFilterActive: false
2566
- },
2567
- priority: 20
2568
- });
2569
- bindings.push({
2570
- key: "\\",
2571
- handler: (_, ctx) => {
2572
- if (ctx.hasSidebar) {
2573
- manager.toggleFocus();
2574
- return true;
2575
- }
2576
- },
2577
- description: "Toggle focus",
2578
- category: "navigation",
2579
- when: {
2580
- hasPrompt: false,
2581
- isFilterActive: false
2582
- },
2583
- priority: 20
2584
- });
2585
- bindings.push({
2586
- key: ["up", "k"],
2587
- handler: () => {
2588
- manager.navigateUp();
2589
- return true;
2590
- },
2591
- description: "Navigate up",
2592
- category: "navigation",
2593
- when: {
2594
- focusArea: "sidebar",
2595
- hasPrompt: false
2596
- },
2597
- priority: 30
2598
- });
2599
- bindings.push({
2600
- key: ["down", "j"],
2601
- handler: () => {
2602
- manager.navigateDown();
2603
- return true;
2604
- },
2605
- description: "Navigate down",
2606
- category: "navigation",
2607
- when: {
2608
- focusArea: "sidebar",
2609
- hasPrompt: false
2610
- },
2611
- priority: 30
2612
- });
2613
- bindings.push({
2614
- key: "return",
2615
- handler: () => {
2616
- manager.selectCurrent();
2617
- return true;
2618
- },
2619
- description: "Select screen",
2620
- category: "navigation",
2621
- when: {
2622
- focusArea: "sidebar",
2623
- hasPrompt: false
2624
- },
2625
- priority: 30
2626
- });
2627
- for (let i = 1; i <= 9; i++) bindings.push({
2628
- key: String(i),
2629
- handler: () => {
2630
- const screens = manager.getScreens();
2631
- if (i <= screens.length) {
2632
- manager.setActiveScreen(screens[i - 1]);
2633
- manager.setSelectedIndex(i - 1);
2634
- return true;
2635
- }
2636
- },
2637
- description: `Jump to screen ${i}`,
2638
- category: "screen",
2639
- when: {
2640
- hasPrompt: false,
2641
- isFilterActive: false
2642
- },
2643
- priority: 15
2644
- });
2645
- bindings.push({
2646
- key: "c",
2647
- handler: () => {
2648
- getActiveScreen()?.clear();
2649
- return true;
2650
- },
2651
- description: "Clear screen",
2652
- category: "screen",
2653
- when: {
2654
- focusArea: "content",
2655
- hasPrompt: false,
2656
- isFilterActive: false
2657
- },
2658
- priority: 15
2659
- });
2660
- return bindings;
2661
- }
2662
- /**
2663
- * Handle printable character input for prompts and filter.
2664
- * This should be called for any key not handled by bindings.
2665
- */ function handlePrintableInput(key, context, handlers) {
2666
- if (!key.sequence || key.sequence.length !== 1 || key.ctrl || key.meta) return false;
2667
- const charCode = key.sequence.charCodeAt(0);
2668
- if (charCode < 32 || charCode > 126) return false;
2669
- if (context.isFilterActive) {
2670
- handlers.filterAppendChar(key.sequence);
2671
- return true;
2672
- }
2673
- if (context.hasPrompt && context.inInputMode) {
2674
- handlers.getActiveScreen()?.promptAppendInput(key.sequence);
2675
- return true;
2676
- }
2677
- return false;
2678
- }
2679
-
2680
- //#endregion
2681
- //#region src/components/filter/filter_bar.tsx
2682
- const LEVEL_LABELS = {
2683
- verbose: "V",
2684
- debug: "D",
2685
- log: "L",
2686
- warn: "W",
2687
- error: "E",
2688
- fatal: "F"
2689
- };
2690
- function FilterBar({ filter, levelCounts }) {
2691
- const theme = useTheme();
2692
- const isSearchFocused = filter.focusedField === "search";
2693
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2694
- flexDirection: "column",
2695
- backgroundColor: theme.filter.background,
2696
- borderColor: theme.filter.border,
2697
- border: ["bottom"],
2698
- paddingLeft: 1,
2699
- paddingRight: 1,
2700
- children: [
2701
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2702
- flexDirection: "row",
2703
- gap: 1,
2704
- children: [
2705
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2706
- fg: isSearchFocused ? theme.colors.primary : theme.filter.textDim,
2707
- children: "/"
2708
- }),
2709
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2710
- fg: filter.searchQuery ? theme.filter.inputText : theme.filter.inputPlaceholder,
2711
- children: filter.searchQuery || "Search logs..."
2712
- }),
2713
- isSearchFocused && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2714
- fg: theme.filter.cursor,
2715
- attributes: _opentui_core.TextAttributes.BLINK,
2716
- children: "_"
2717
- })
2718
- ]
2719
- }),
2720
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2721
- flexDirection: "row",
2722
- gap: 1,
2723
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2724
- fg: theme.filter.textDim,
2725
- children: "Levels:"
2726
- }), ALL_LOG_LEVELS.map((level, index) => {
2727
- const isEnabled = filter.enabledLevels.has(level);
2728
- const count = levelCounts[level];
2729
- const levelColor = theme.logLevels[level].border;
2730
- const isLevelsFocused = filter.focusedField === "levels";
2731
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2732
- flexDirection: "row",
2733
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
2734
- fg: isEnabled ? levelColor : theme.filter.inactiveLevel,
2735
- attributes: isLevelsFocused ? _opentui_core.TextAttributes.BOLD : void 0,
2736
- children: [
2737
- index + 1,
2738
- ":",
2739
- LEVEL_LABELS[level]
2740
- ]
2741
- }), count > 0 && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("text", {
2742
- fg: theme.filter.textDim,
2743
- children: [
2744
- "(",
2745
- count > 99 ? "99+" : count,
2746
- ")"
2747
- ]
2748
- })]
2749
- }, level);
2750
- })]
2751
- }),
2752
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2753
- flexDirection: "row",
2754
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2755
- fg: theme.filter.textDim,
2756
- children: "Tab: switch fields | 1-7: toggle levels | Esc: close"
2757
- })
2758
- })
2759
- ]
2760
- });
2761
- }
2762
-
2763
- //#endregion
2764
- //#region src/components/help/help_overlay.tsx
2765
- const CATEGORY_ORDER = [
2766
- "general",
2767
- "navigation",
2768
- "screen",
2769
- "filter",
2770
- "prompt"
2771
- ];
2772
- const CATEGORY_LABELS = {
2773
- general: "General",
2774
- navigation: "Navigation",
2775
- screen: "Screen",
2776
- filter: "Filter",
2777
- prompt: "Prompts"
2778
- };
2779
- function groupByCategory(bindings) {
2780
- const grouped = {
2781
- general: [],
2782
- navigation: [],
2783
- screen: [],
2784
- filter: [],
2785
- prompt: []
2786
- };
2787
- for (const binding of bindings) if (binding.description) grouped[binding.category].push(binding);
2788
- return grouped;
2789
- }
2790
- function HelpOverlay({ bindings }) {
2791
- const theme = useTheme();
2792
- const grouped = groupByCategory(bindings);
2793
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2794
- position: "absolute",
2795
- top: 1,
2796
- left: 2,
2797
- right: 2,
2798
- bottom: 1,
2799
- backgroundColor: theme.help.background,
2800
- borderColor: theme.help.border,
2801
- border: [
2802
- "top",
2803
- "bottom",
2804
- "left",
2805
- "right"
2806
- ],
2807
- flexDirection: "column",
2808
- paddingLeft: 2,
2809
- paddingRight: 2,
2810
- paddingTop: 1,
2811
- paddingBottom: 1,
2812
- children: [
2813
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2814
- marginBottom: 1,
2815
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2816
- fg: theme.help.title,
2817
- attributes: _opentui_core.TextAttributes.BOLD,
2818
- children: "Keyboard Shortcuts"
2819
- })
2820
- }),
2821
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("scrollbox", {
2822
- scrollY: true,
2823
- flexGrow: 1,
2824
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2825
- flexDirection: "column",
2826
- gap: 1,
2827
- children: CATEGORY_ORDER.map((category) => {
2828
- const categoryBindings = grouped[category];
2829
- if (categoryBindings.length === 0) return null;
2830
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2831
- flexDirection: "column",
2832
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2833
- fg: theme.help.category,
2834
- attributes: _opentui_core.TextAttributes.BOLD,
2835
- children: CATEGORY_LABELS[category]
2836
- }), categoryBindings.map((binding, index) => /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
2837
- flexDirection: "row",
2838
- paddingLeft: 2,
2839
- children: [/* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2840
- fg: theme.help.key,
2841
- width: 14,
2842
- children: formatKeyBinding(binding)
2843
- }), /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2844
- fg: theme.help.description,
2845
- children: binding.description
2846
- })]
2847
- }, `${binding.key}-${index}`))]
2848
- }, category);
2849
- })
2850
- })
2851
- }),
2852
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("box", {
2853
- marginTop: 1,
2854
- borderColor: theme.separator.line,
2855
- border: ["top"],
2856
- paddingTop: 1,
2857
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)("text", {
2858
- fg: theme.help.hint,
2859
- children: "Press ? or Esc to close"
2860
- })
2861
- })
2862
- ]
2863
- });
2864
- }
2865
-
2866
- //#endregion
2867
- //#region src/components/screen_manager_bridge.tsx
2868
- function ScreenManagerBridge({ manager, theme }) {
2869
- const [, forceUpdate] = (0, react.useState)({});
2870
- const [showHelp, setShowHelp] = (0, react.useState)(false);
2871
- const [filter, setFilter] = (0, react.useState)(createDefaultFilterState);
2872
- (0, react.useEffect)(() => {
2873
- return manager.onChange(() => forceUpdate({}));
2874
- }, [manager]);
2875
- const getActiveScreen = (0, react.useCallback)(() => manager.getActiveScreen(), [manager]);
2876
- const toggleHelp = (0, react.useCallback)(() => {
2877
- setShowHelp((prev) => !prev);
2878
- }, []);
2879
- const toggleFilter = (0, react.useCallback)(() => {
2880
- setFilter((prev) => ({
2881
- ...prev,
2882
- isVisible: !prev.isVisible,
2883
- focusedField: "search"
2884
- }));
2885
- }, []);
2886
- const closeFilter = (0, react.useCallback)(() => {
2887
- setFilter((prev) => ({
2888
- ...prev,
2889
- isVisible: false
2890
- }));
2891
- }, []);
2892
- const filterAppendChar = (0, react.useCallback)((char) => {
2893
- setFilter((prev) => ({
2894
- ...prev,
2895
- searchQuery: prev.searchQuery + char
2896
- }));
2897
- }, []);
2898
- const filterDeleteChar = (0, react.useCallback)(() => {
2899
- setFilter((prev) => ({
2900
- ...prev,
2901
- searchQuery: prev.searchQuery.slice(0, -1)
2902
- }));
2903
- }, []);
2904
- const filterToggleLevel = (0, react.useCallback)((index) => {
2905
- setFilter((prev) => {
2906
- const level = ALL_LOG_LEVELS[index];
2907
- if (!level) return prev;
2908
- const newLevels = new Set(prev.enabledLevels);
2909
- if (newLevels.has(level)) newLevels.delete(level);
2910
- else newLevels.add(level);
2911
- return {
2912
- ...prev,
2913
- enabledLevels: newLevels
2914
- };
2915
- });
2916
- }, []);
2917
- const filterCycleField = (0, react.useCallback)(() => {
2918
- setFilter((prev) => ({
2919
- ...prev,
2920
- focusedField: prev.focusedField === "search" ? "levels" : "search"
2921
- }));
2922
- }, []);
2923
- const keyboardManager = (0, react.useMemo)(() => {
2924
- const km = new KeyboardManager();
2925
- const bindings = createDefaultBindings({
2926
- manager,
2927
- getActiveScreen,
2928
- toggleHelp,
2929
- toggleFilter,
2930
- closeFilter,
2931
- filterAppendChar,
2932
- filterDeleteChar,
2933
- filterToggleLevel,
2934
- filterCycleField
2935
- });
2936
- km.addBindings(bindings);
2937
- return km;
2938
- }, [
2939
- manager,
2940
- getActiveScreen,
2941
- toggleHelp,
2942
- toggleFilter,
2943
- closeFilter,
2944
- filterAppendChar,
2945
- filterDeleteChar,
2946
- filterToggleLevel,
2947
- filterCycleField
2948
- ]);
2949
- (0, _opentui_react.useKeyboard)((0, react.useCallback)((key) => {
2950
- const screens$1 = manager.getScreens();
2951
- const activeScreen$1 = manager.getActiveScreen();
2952
- const context = {
2953
- hasSidebar: screens$1.length > 1,
2954
- focusArea: manager.focusArea,
2955
- hasPrompt: activeScreen$1?.hasActivePrompt() ?? false,
2956
- inInputMode: activeScreen$1?.isPromptInInputMode() ?? false,
2957
- isFilterActive: filter.isVisible,
2958
- isHelpVisible: showHelp
2959
- };
2960
- if (keyboardManager.handleKey(key, context)) return;
2961
- handlePrintableInput(key, context, {
2962
- manager,
2963
- getActiveScreen,
2964
- toggleHelp,
2965
- toggleFilter,
2966
- closeFilter,
2967
- filterAppendChar,
2968
- filterDeleteChar,
2969
- filterToggleLevel,
2970
- filterCycleField
2971
- });
2972
- }, [
2973
- manager,
2974
- keyboardManager,
2975
- filter.isVisible,
2976
- showHelp,
2977
- getActiveScreen,
2978
- toggleHelp,
2979
- toggleFilter,
2980
- closeFilter,
2981
- filterAppendChar,
2982
- filterDeleteChar,
2983
- filterToggleLevel,
2984
- filterCycleField
2985
- ]));
2986
- const screens = manager.getScreens();
2987
- const activeScreen = manager.getActiveScreen();
2988
- const activeScreenId = activeScreen?.getId() ?? screens[0]?.getId() ?? "";
2989
- const bindOptions = manager.getBindOptions();
2990
- const hasSidebar = screens.length > 1;
2991
- const activeScreenVersion = (0, react.useSyncExternalStore)((updater) => activeScreen?.onChange(updater) ?? (() => {}), () => activeScreen?.getVersion() ?? -1);
2992
- const levelCounts = (0, react.useMemo)(() => {
2993
- if (!activeScreen) return {
2994
- verbose: 0,
2995
- debug: 0,
2996
- log: 0,
2997
- warn: 0,
2998
- error: 0,
2999
- fatal: 0
3000
- };
3001
- return FilterEngine.countByLevel(activeScreen.getMessages());
3002
- }, [activeScreenVersion, activeScreen]);
3003
- const filteredMessages = (0, react.useMemo)(() => {
3004
- if (!activeScreen) return [];
3005
- return FilterEngine.filterMessages(activeScreen.getMessages(), filter);
3006
- }, [
3007
- activeScreenVersion,
3008
- activeScreen,
3009
- filter
3010
- ]);
3011
- const isFiltering = (0, react.useMemo)(() => hasActiveFilter(filter), [filter]);
3012
- return /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(LoggerProvider, {
3013
- theme,
3014
- children: /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
3015
- flexDirection: "row",
3016
- flexGrow: 1,
3017
- children: [
3018
- hasSidebar && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(Sidebar, {
3019
- screens,
3020
- selectedIndex: manager.selectedIndex,
3021
- activeScreenId,
3022
- focused: manager.focusArea === "sidebar",
3023
- width: bindOptions.sidebarWidth ?? 25,
3024
- title: bindOptions.sidebarTitle ?? "Screens"
3025
- }),
3026
- /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsxs)("box", {
3027
- flexDirection: "column",
3028
- flexGrow: 1,
3029
- children: [filter.isVisible && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(FilterBar, {
3030
- filter,
3031
- levelCounts
3032
- }), activeScreen && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(ScreenBridge, {
3033
- screen: activeScreen,
3034
- focused: manager.focusArea === "content",
3035
- filteredMessages,
3036
- isFiltering,
3037
- totalMessages: activeScreen.getMessages().length
3038
- }, activeScreen.getId())]
3039
- }),
3040
- showHelp && /* @__PURE__ */ (0, _opentui_react_jsx_runtime.jsx)(HelpOverlay, { bindings: keyboardManager.getBindingsForHelp() })
3041
- ]
3042
- })
3043
- });
3044
- }
3045
-
3046
- //#endregion
3047
- Object.defineProperty(exports, 'ALL_LOG_LEVELS', {
3048
- enumerable: true,
3049
- get: function () {
3050
- return ALL_LOG_LEVELS;
3051
- }
3052
- });
3053
- Object.defineProperty(exports, 'COMMON_FILETYPES', {
3054
- enumerable: true,
3055
- get: function () {
3056
- return COMMON_FILETYPES;
3057
- }
3058
- });
3059
- Object.defineProperty(exports, 'DEFAULT_LOG_LEVEL_COLORS', {
3060
- enumerable: true,
3061
- get: function () {
3062
- return DEFAULT_LOG_LEVEL_COLORS;
3063
- }
3064
- });
3065
- Object.defineProperty(exports, 'ERROR_HIGHLIGHT_COLORS', {
3066
- enumerable: true,
3067
- get: function () {
3068
- return ERROR_HIGHLIGHT_COLORS;
3069
- }
3070
- });
3071
- Object.defineProperty(exports, 'FILE_COLORS', {
3072
- enumerable: true,
3073
- get: function () {
3074
- return FILE_COLORS;
3075
- }
3076
- });
3077
- Object.defineProperty(exports, 'FileLog', {
3078
- enumerable: true,
3079
- get: function () {
3080
- return FileLog;
3081
- }
3082
- });
3083
- Object.defineProperty(exports, 'FilterEngine', {
3084
- enumerable: true,
3085
- get: function () {
3086
- return FilterEngine;
3087
- }
3088
- });
3089
- Object.defineProperty(exports, 'GROUP_COLORS', {
3090
- enumerable: true,
3091
- get: function () {
3092
- return GROUP_COLORS;
3093
- }
3094
- });
3095
- Object.defineProperty(exports, 'GroupMessageRenderer', {
3096
- enumerable: true,
3097
- get: function () {
3098
- return GroupMessageRenderer;
3099
- }
3100
- });
3101
- Object.defineProperty(exports, 'GroupRenderer', {
3102
- enumerable: true,
3103
- get: function () {
3104
- return GroupRenderer;
3105
- }
3106
- });
3107
- Object.defineProperty(exports, 'HEADER_COLORS', {
3108
- enumerable: true,
3109
- get: function () {
3110
- return HEADER_COLORS;
3111
- }
3112
- });
3113
- Object.defineProperty(exports, 'KeyboardManager', {
3114
- enumerable: true,
3115
- get: function () {
3116
- return KeyboardManager;
3117
- }
3118
- });
3119
- Object.defineProperty(exports, 'LoadingMessage', {
3120
- enumerable: true,
3121
- get: function () {
3122
- return LoadingMessage;
3123
- }
3124
- });
3125
- Object.defineProperty(exports, 'LogMessage', {
3126
- enumerable: true,
3127
- get: function () {
3128
- return LogMessage;
3129
- }
3130
- });
3131
- Object.defineProperty(exports, 'LoggerProvider', {
3132
- enumerable: true,
3133
- get: function () {
3134
- return LoggerProvider;
3135
- }
3136
- });
3137
- Object.defineProperty(exports, 'MessageRenderer', {
3138
- enumerable: true,
3139
- get: function () {
3140
- return MessageRenderer;
3141
- }
3142
- });
3143
- Object.defineProperty(exports, 'PROGRESS_COLORS', {
3144
- enumerable: true,
3145
- get: function () {
3146
- return PROGRESS_COLORS;
3147
- }
3148
- });
3149
- Object.defineProperty(exports, 'PROMPT_COLORS', {
3150
- enumerable: true,
3151
- get: function () {
3152
- return PROMPT_COLORS;
3153
- }
3154
- });
3155
- Object.defineProperty(exports, 'ProgressMessage', {
3156
- enumerable: true,
3157
- get: function () {
3158
- return ProgressMessage;
3159
- }
3160
- });
3161
- Object.defineProperty(exports, 'PromptRenderer', {
3162
- enumerable: true,
3163
- get: function () {
3164
- return PromptRenderer;
3165
- }
3166
- });
3167
- Object.defineProperty(exports, 'SEPARATOR_COLORS', {
3168
- enumerable: true,
3169
- get: function () {
3170
- return SEPARATOR_COLORS;
3171
- }
3172
- });
3173
- Object.defineProperty(exports, 'SIDEBAR_COLORS', {
3174
- enumerable: true,
3175
- get: function () {
3176
- return SIDEBAR_COLORS;
3177
- }
3178
- });
3179
- Object.defineProperty(exports, 'STATUS_INDICATORS', {
3180
- enumerable: true,
3181
- get: function () {
3182
- return STATUS_INDICATORS;
3183
- }
3184
- });
3185
- Object.defineProperty(exports, 'ScreenBridge', {
3186
- enumerable: true,
3187
- get: function () {
3188
- return ScreenBridge;
3189
- }
3190
- });
3191
- Object.defineProperty(exports, 'ScreenManagerBridge', {
3192
- enumerable: true,
3193
- get: function () {
3194
- return ScreenManagerBridge;
3195
- }
3196
- });
3197
- Object.defineProperty(exports, 'Sidebar', {
3198
- enumerable: true,
3199
- get: function () {
3200
- return Sidebar;
3201
- }
3202
- });
3203
- Object.defineProperty(exports, 'SidebarItem', {
3204
- enumerable: true,
3205
- get: function () {
3206
- return SidebarItem;
3207
- }
3208
- });
3209
- Object.defineProperty(exports, 'SidebarSeparator', {
3210
- enumerable: true,
3211
- get: function () {
3212
- return SidebarSeparator;
3213
- }
3214
- });
3215
- Object.defineProperty(exports, 'TABLE_COLORS', {
3216
- enumerable: true,
3217
- get: function () {
3218
- return TABLE_COLORS;
3219
- }
3220
- });
3221
- Object.defineProperty(exports, 'TableMessage', {
3222
- enumerable: true,
3223
- get: function () {
3224
- return TableMessage;
3225
- }
3226
- });
3227
- Object.defineProperty(exports, 'VARIANT_COLORS', {
3228
- enumerable: true,
3229
- get: function () {
3230
- return VARIANT_COLORS;
3231
- }
3232
- });
3233
- Object.defineProperty(exports, 'captureTrace', {
3234
- enumerable: true,
3235
- get: function () {
3236
- return captureTrace;
3237
- }
3238
- });
3239
- Object.defineProperty(exports, 'createBorderColor', {
3240
- enumerable: true,
3241
- get: function () {
3242
- return createBorderColor;
3243
- }
3244
- });
3245
- Object.defineProperty(exports, 'createDefaultBindings', {
3246
- enumerable: true,
3247
- get: function () {
3248
- return createDefaultBindings;
3249
- }
3250
- });
3251
- Object.defineProperty(exports, 'createDefaultFilterState', {
3252
- enumerable: true,
3253
- get: function () {
3254
- return createDefaultFilterState;
3255
- }
3256
- });
3257
- Object.defineProperty(exports, 'createTheme', {
3258
- enumerable: true,
3259
- get: function () {
3260
- return createTheme;
3261
- }
3262
- });
3263
- Object.defineProperty(exports, 'createThemeFrom', {
3264
- enumerable: true,
3265
- get: function () {
3266
- return createThemeFrom;
3267
- }
3268
- });
3269
- Object.defineProperty(exports, 'createTintedColor', {
3270
- enumerable: true,
3271
- get: function () {
3272
- return createTintedColor;
3273
- }
3274
- });
3275
- Object.defineProperty(exports, 'darkTheme', {
3276
- enumerable: true,
3277
- get: function () {
3278
- return darkTheme;
3279
- }
3280
- });
3281
- Object.defineProperty(exports, 'formatKeyBinding', {
3282
- enumerable: true,
3283
- get: function () {
3284
- return formatKeyBinding;
3285
- }
3286
- });
3287
- Object.defineProperty(exports, 'formatObject', {
3288
- enumerable: true,
3289
- get: function () {
3290
- return formatObject;
3291
- }
3292
- });
3293
- Object.defineProperty(exports, 'getFileName', {
3294
- enumerable: true,
3295
- get: function () {
3296
- return getFileName;
3297
- }
3298
- });
3299
- Object.defineProperty(exports, 'getLogLevelColors', {
3300
- enumerable: true,
3301
- get: function () {
3302
- return getLogLevelColors;
3303
- }
3304
- });
3305
- Object.defineProperty(exports, 'getThemePreset', {
3306
- enumerable: true,
3307
- get: function () {
3308
- return getThemePreset;
3309
- }
3310
- });
3311
- Object.defineProperty(exports, 'handlePrintableInput', {
3312
- enumerable: true,
3313
- get: function () {
3314
- return handlePrintableInput;
3315
- }
3316
- });
3317
- Object.defineProperty(exports, 'hasActiveFilter', {
3318
- enumerable: true,
3319
- get: function () {
3320
- return hasActiveFilter;
3321
- }
3322
- });
3323
- Object.defineProperty(exports, 'highContrastTheme', {
3324
- enumerable: true,
3325
- get: function () {
3326
- return highContrastTheme;
3327
- }
3328
- });
3329
- Object.defineProperty(exports, 'lightTheme', {
3330
- enumerable: true,
3331
- get: function () {
3332
- return lightTheme;
3333
- }
3334
- });
3335
- Object.defineProperty(exports, 'mergeThemes', {
3336
- enumerable: true,
3337
- get: function () {
3338
- return mergeThemes;
3339
- }
3340
- });
3341
- Object.defineProperty(exports, 'printMessagesToStdout', {
3342
- enumerable: true,
3343
- get: function () {
3344
- return printMessagesToStdout;
3345
- }
3346
- });
3347
- Object.defineProperty(exports, 'resolveFiletype', {
3348
- enumerable: true,
3349
- get: function () {
3350
- return resolveFiletype;
3351
- }
3352
- });
3353
- Object.defineProperty(exports, 'resolveTheme', {
3354
- enumerable: true,
3355
- get: function () {
3356
- return resolveTheme;
3357
- }
3358
- });
3359
- Object.defineProperty(exports, 'useLoggerContext', {
3360
- enumerable: true,
3361
- get: function () {
3362
- return useLoggerContext;
3363
- }
3364
- });
3365
- Object.defineProperty(exports, 'useTheme', {
3366
- enumerable: true,
3367
- get: function () {
3368
- return useTheme;
3369
- }
3370
- });
3371
- //# sourceMappingURL=screen_manager_bridge-CWxLO0CK.cjs.map