@navios/commander-tui 1.3.0 → 1.4.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 (240) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/{src/__tests__/mocks/scm-mock.ts → dist/base/src/__tests__/mocks/scm-mock.d.ts} +3 -1
  3. package/dist/base/src/__tests__/mocks/scm-mock.d.ts.map +1 -0
  4. package/dist/base/src/__tests__/setup.d.ts +2 -0
  5. package/dist/base/src/__tests__/setup.d.ts.map +1 -0
  6. package/dist/base/src/__tests__/utils/factories.d.ts +67 -0
  7. package/dist/base/src/__tests__/utils/factories.d.ts.map +1 -0
  8. package/dist/base/src/__tests__/utils/render-utils.d.ts +21 -0
  9. package/dist/base/src/__tests__/utils/render-utils.d.ts.map +1 -0
  10. package/dist/base/src/__tests__/utils/test-container.d.ts +20 -0
  11. package/dist/base/src/__tests__/utils/test-container.d.ts.map +1 -0
  12. package/dist/base/src/adapters/interface.d.ts +9 -2
  13. package/dist/base/src/adapters/interface.d.ts.map +1 -1
  14. package/dist/base/src/overrides/missing-adapter.override.d.ts +10 -0
  15. package/dist/base/src/overrides/missing-adapter.override.d.ts.map +1 -1
  16. package/dist/base/src/schemas/logger-options.d.ts +1 -1
  17. package/dist/base/src/services/index.d.ts +1 -0
  18. package/dist/base/src/services/index.d.ts.map +1 -1
  19. package/dist/base/src/services/logger.d.ts.map +1 -1
  20. package/dist/base/src/services/readline_prompt.d.ts +27 -0
  21. package/dist/base/src/services/readline_prompt.d.ts.map +1 -0
  22. package/dist/base/src/services/screen.d.ts +14 -8
  23. package/dist/base/src/services/screen.d.ts.map +1 -1
  24. package/dist/base/src/services/screen_manager.d.ts +62 -12
  25. package/dist/base/src/services/screen_manager.d.ts.map +1 -1
  26. package/dist/base/src/types/events.types.d.ts +40 -0
  27. package/dist/base/src/types/events.types.d.ts.map +1 -0
  28. package/dist/base/src/types/index.d.ts +1 -0
  29. package/dist/base/src/types/index.d.ts.map +1 -1
  30. package/dist/base/src/types/screen.types.d.ts +28 -0
  31. package/dist/base/src/types/screen.types.d.ts.map +1 -1
  32. package/dist/base/src/utils/colors/helpers.d.ts +0 -16
  33. package/dist/base/src/utils/colors/helpers.d.ts.map +1 -1
  34. package/dist/base/src/utils/index.d.ts +2 -0
  35. package/dist/base/src/utils/index.d.ts.map +1 -1
  36. package/dist/base/src/utils/prompt.d.ts +7 -0
  37. package/dist/base/src/utils/prompt.d.ts.map +1 -0
  38. package/dist/base/src/utils/runtime.d.ts +10 -0
  39. package/dist/base/src/utils/runtime.d.ts.map +1 -0
  40. package/dist/base/src/utils/stdout-printer.d.ts +5 -0
  41. package/dist/base/src/utils/stdout-printer.d.ts.map +1 -1
  42. package/dist/base/tsconfig.base.tsbuildinfo +1 -1
  43. package/dist/base/tsconfig.tsbuildinfo +1 -0
  44. package/dist/ink/src/adapters/ink/components/file/file_log.d.ts +28 -0
  45. package/dist/ink/src/adapters/ink/components/file/file_log.d.ts.map +1 -0
  46. package/dist/ink/src/adapters/ink/components/file/index.d.ts +2 -0
  47. package/dist/ink/src/adapters/ink/components/file/index.d.ts.map +1 -0
  48. package/dist/ink/src/adapters/ink/components/filter/filter_bar.d.ts +7 -0
  49. package/dist/ink/src/adapters/ink/components/filter/filter_bar.d.ts.map +1 -0
  50. package/dist/ink/src/adapters/ink/components/filter/index.d.ts +2 -0
  51. package/dist/ink/src/adapters/ink/components/filter/index.d.ts.map +1 -0
  52. package/dist/ink/src/adapters/ink/components/help/help_overlay.d.ts +6 -0
  53. package/dist/ink/src/adapters/ink/components/help/help_overlay.d.ts.map +1 -0
  54. package/dist/ink/src/adapters/ink/components/help/index.d.ts +2 -0
  55. package/dist/ink/src/adapters/ink/components/help/index.d.ts.map +1 -0
  56. package/dist/ink/src/adapters/ink/components/index.d.ts +9 -0
  57. package/dist/ink/src/adapters/ink/components/index.d.ts.map +1 -0
  58. package/dist/ink/src/adapters/ink/components/log/index.d.ts +2 -0
  59. package/dist/ink/src/adapters/ink/components/log/index.d.ts.map +1 -0
  60. package/dist/ink/src/adapters/ink/components/log/log_message.d.ts +15 -0
  61. package/dist/ink/src/adapters/ink/components/log/log_message.d.ts.map +1 -0
  62. package/dist/ink/src/adapters/ink/components/prompt/index.d.ts +2 -0
  63. package/dist/ink/src/adapters/ink/components/prompt/index.d.ts.map +1 -0
  64. package/dist/ink/src/adapters/ink/components/prompt/prompt_renderer.d.ts +6 -0
  65. package/dist/ink/src/adapters/ink/components/prompt/prompt_renderer.d.ts.map +1 -0
  66. package/dist/ink/src/adapters/ink/components/screen/group_renderer.d.ts +14 -0
  67. package/dist/ink/src/adapters/ink/components/screen/group_renderer.d.ts.map +1 -0
  68. package/dist/ink/src/adapters/ink/components/screen/index.d.ts +7 -0
  69. package/dist/ink/src/adapters/ink/components/screen/index.d.ts.map +1 -0
  70. package/dist/ink/src/adapters/ink/components/screen/loading_message.d.ts +6 -0
  71. package/dist/ink/src/adapters/ink/components/screen/loading_message.d.ts.map +1 -0
  72. package/dist/ink/src/adapters/ink/components/screen/message_renderer.d.ts +6 -0
  73. package/dist/ink/src/adapters/ink/components/screen/message_renderer.d.ts.map +1 -0
  74. package/dist/ink/src/adapters/ink/components/screen/progress_message.d.ts +6 -0
  75. package/dist/ink/src/adapters/ink/components/screen/progress_message.d.ts.map +1 -0
  76. package/dist/ink/src/adapters/ink/components/screen/screen_bridge.d.ts +14 -0
  77. package/dist/ink/src/adapters/ink/components/screen/screen_bridge.d.ts.map +1 -0
  78. package/dist/ink/src/adapters/ink/components/screen/table_message.d.ts +6 -0
  79. package/dist/ink/src/adapters/ink/components/screen/table_message.d.ts.map +1 -0
  80. package/dist/ink/src/adapters/ink/components/screen_manager_bridge.d.ts +8 -0
  81. package/dist/ink/src/adapters/ink/components/screen_manager_bridge.d.ts.map +1 -0
  82. package/dist/ink/src/adapters/ink/components/sidebar/index.d.ts +4 -0
  83. package/dist/ink/src/adapters/ink/components/sidebar/index.d.ts.map +1 -0
  84. package/dist/ink/src/adapters/ink/components/sidebar/sidebar.d.ts +11 -0
  85. package/dist/ink/src/adapters/ink/components/sidebar/sidebar.d.ts.map +1 -0
  86. package/dist/ink/src/adapters/ink/components/sidebar/sidebar_item.d.ts +9 -0
  87. package/dist/ink/src/adapters/ink/components/sidebar/sidebar_item.d.ts.map +1 -0
  88. package/dist/ink/src/adapters/ink/components/sidebar/sidebar_separator.d.ts +2 -0
  89. package/dist/ink/src/adapters/ink/components/sidebar/sidebar_separator.d.ts.map +1 -0
  90. package/dist/ink/src/adapters/ink/context/index.d.ts +2 -0
  91. package/dist/ink/src/adapters/ink/context/index.d.ts.map +1 -0
  92. package/dist/ink/src/adapters/ink/context/logger_context.d.ts +33 -0
  93. package/dist/ink/src/adapters/ink/context/logger_context.d.ts.map +1 -0
  94. package/dist/ink/src/adapters/ink/hooks/index.d.ts +2 -0
  95. package/dist/ink/src/adapters/ink/hooks/index.d.ts.map +1 -0
  96. package/dist/ink/src/adapters/ink/hooks/use_theme.d.ts +7 -0
  97. package/dist/ink/src/adapters/ink/hooks/use_theme.d.ts.map +1 -0
  98. package/dist/ink/src/adapters/ink/index.d.ts +18 -0
  99. package/dist/ink/src/adapters/ink/index.d.ts.map +1 -0
  100. package/dist/ink/src/adapters/react-shared/hooks/index.d.ts +4 -0
  101. package/dist/ink/src/adapters/react-shared/hooks/index.d.ts.map +1 -0
  102. package/dist/ink/src/adapters/react-shared/hooks/use_filter_state.d.ts +18 -0
  103. package/dist/ink/src/adapters/react-shared/hooks/use_filter_state.d.ts.map +1 -0
  104. package/dist/ink/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts +26 -0
  105. package/dist/ink/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts.map +1 -0
  106. package/dist/ink/src/adapters/react-shared/hooks/use_manager_subscription.d.ts +7 -0
  107. package/dist/ink/src/adapters/react-shared/hooks/use_manager_subscription.d.ts.map +1 -0
  108. package/dist/ink/src/adapters/react-shared/index.d.ts +2 -0
  109. package/dist/ink/src/adapters/react-shared/index.d.ts.map +1 -0
  110. package/dist/ink/tsconfig.ink.tsbuildinfo +1 -0
  111. package/dist/react/src/adapters/react-shared/hooks/index.d.ts +4 -0
  112. package/dist/react/src/adapters/react-shared/hooks/index.d.ts.map +1 -0
  113. package/dist/react/src/adapters/react-shared/hooks/use_filter_state.d.ts +18 -0
  114. package/dist/react/src/adapters/react-shared/hooks/use_filter_state.d.ts.map +1 -0
  115. package/dist/react/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts +26 -0
  116. package/dist/react/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts.map +1 -0
  117. package/dist/react/src/adapters/react-shared/hooks/use_manager_subscription.d.ts +7 -0
  118. package/dist/react/src/adapters/react-shared/hooks/use_manager_subscription.d.ts.map +1 -0
  119. package/dist/react/src/adapters/react-shared/index.d.ts +2 -0
  120. package/dist/react/src/adapters/react-shared/index.d.ts.map +1 -0
  121. package/dist/react/tsconfig.react.tsbuildinfo +1 -1
  122. package/dist/solid/tsconfig.solid.tsbuildinfo +1 -1
  123. package/lib/index.cjs +2177 -178
  124. package/lib/index.cjs.map +1 -1
  125. package/lib/index.d.cts +942 -78
  126. package/lib/index.d.cts.map +1 -0
  127. package/lib/index.d.mts +902 -38
  128. package/lib/index.d.mts.map +1 -0
  129. package/lib/index.mjs +2098 -135
  130. package/lib/index.mjs.map +1 -1
  131. package/package.json +1 -31
  132. package/src/__tests__/services/logger.spec.ts +32 -0
  133. package/src/__tests__/services/screen.spec.ts +106 -95
  134. package/src/__tests__/utils/factories.ts +2 -0
  135. package/src/adapters/interface.ts +10 -2
  136. package/src/overrides/missing-adapter.override.ts +16 -6
  137. package/src/services/index.ts +1 -0
  138. package/src/services/logger.ts +7 -1
  139. package/src/services/readline_prompt.ts +194 -0
  140. package/src/services/screen.ts +106 -54
  141. package/src/services/screen_manager.ts +282 -74
  142. package/src/types/events.types.ts +84 -0
  143. package/src/types/index.ts +3 -0
  144. package/src/types/screen.types.ts +34 -0
  145. package/src/utils/colors/helpers.ts +0 -25
  146. package/src/utils/index.ts +6 -0
  147. package/src/utils/prompt.ts +18 -0
  148. package/src/utils/runtime.ts +14 -0
  149. package/src/utils/stdout-printer.ts +16 -5
  150. package/tsconfig.base.json +1 -17
  151. package/tsconfig.json +1 -6
  152. package/tsdown.config.mts +13 -70
  153. package/lib/adapters/react/index.cjs +0 -1768
  154. package/lib/adapters/react/index.cjs.map +0 -1
  155. package/lib/adapters/react/index.d.cts +0 -80
  156. package/lib/adapters/react/index.d.mts +0 -80
  157. package/lib/adapters/react/index.mjs +0 -1760
  158. package/lib/adapters/react/index.mjs.map +0 -1
  159. package/lib/adapters/solid/index.cjs +0 -3855
  160. package/lib/adapters/solid/index.cjs.map +0 -1
  161. package/lib/adapters/solid/index.d.cts +0 -74
  162. package/lib/adapters/solid/index.d.mts +0 -74
  163. package/lib/adapters/solid/index.mjs +0 -3847
  164. package/lib/adapters/solid/index.mjs.map +0 -1
  165. package/lib/filter_engine-DXqu9Vaq.cjs +0 -1836
  166. package/lib/filter_engine-DXqu9Vaq.cjs.map +0 -1
  167. package/lib/filter_engine-DmqhEhpA.mjs +0 -1609
  168. package/lib/filter_engine-DmqhEhpA.mjs.map +0 -1
  169. package/lib/interface-CTHQ08aY.d.mts +0 -699
  170. package/lib/interface-DQEIz9Mb.d.cts +0 -699
  171. package/src/__tests__/components/__snapshots__/filter_bar.spec.tsx.snap +0 -2293
  172. package/src/__tests__/components/__snapshots__/loading_message.spec.tsx.snap +0 -1414
  173. package/src/__tests__/components/__snapshots__/log_message.spec.tsx.snap +0 -3245
  174. package/src/__tests__/components/__snapshots__/progress_message.spec.tsx.snap +0 -1783
  175. package/src/__tests__/components/__snapshots__/prompt_renderer.spec.tsx.snap +0 -3203
  176. package/src/__tests__/components/__snapshots__/sidebar.spec.tsx.snap +0 -2857
  177. package/src/__tests__/components/filter_bar.spec.tsx +0 -190
  178. package/src/__tests__/components/loading_message.spec.tsx +0 -110
  179. package/src/__tests__/components/log_message.spec.tsx +0 -166
  180. package/src/__tests__/components/progress_message.spec.tsx +0 -147
  181. package/src/__tests__/components/prompt_renderer.spec.tsx +0 -274
  182. package/src/__tests__/components/sidebar.spec.tsx +0 -322
  183. package/src/__tests__/utils/render-utils.tsx +0 -39
  184. package/src/adapters/react/components/file/file_log.tsx +0 -241
  185. package/src/adapters/react/components/file/index.ts +0 -1
  186. package/src/adapters/react/components/filter/filter_bar.tsx +0 -79
  187. package/src/adapters/react/components/filter/index.ts +0 -1
  188. package/src/adapters/react/components/help/help_overlay.tsx +0 -100
  189. package/src/adapters/react/components/help/index.ts +0 -1
  190. package/src/adapters/react/components/log/index.ts +0 -1
  191. package/src/adapters/react/components/log/log_message.tsx +0 -102
  192. package/src/adapters/react/components/prompt/index.ts +0 -2
  193. package/src/adapters/react/components/prompt/prompt_renderer.tsx +0 -346
  194. package/src/adapters/react/components/screen/group_renderer.tsx +0 -64
  195. package/src/adapters/react/components/screen/index.ts +0 -6
  196. package/src/adapters/react/components/screen/loading_message.tsx +0 -43
  197. package/src/adapters/react/components/screen/message_renderer.tsx +0 -108
  198. package/src/adapters/react/components/screen/progress_message.tsx +0 -60
  199. package/src/adapters/react/components/screen/screen_bridge.tsx +0 -149
  200. package/src/adapters/react/components/screen/table_message.tsx +0 -57
  201. package/src/adapters/react/components/screen_manager_bridge.tsx +0 -245
  202. package/src/adapters/react/components/sidebar/index.ts +0 -3
  203. package/src/adapters/react/components/sidebar/sidebar.tsx +0 -102
  204. package/src/adapters/react/components/sidebar/sidebar_item.tsx +0 -50
  205. package/src/adapters/react/components/sidebar/sidebar_separator.tsx +0 -13
  206. package/src/adapters/react/context/index.ts +0 -1
  207. package/src/adapters/react/context/logger_context.tsx +0 -109
  208. package/src/adapters/react/hooks/index.ts +0 -1
  209. package/src/adapters/react/hooks/use_theme.ts +0 -12
  210. package/src/adapters/react/index.ts +0 -39
  211. package/src/adapters/solid/components/file/file_log.tsx +0 -221
  212. package/src/adapters/solid/components/file/index.ts +0 -1
  213. package/src/adapters/solid/components/filter/filter_bar.tsx +0 -84
  214. package/src/adapters/solid/components/filter/index.ts +0 -1
  215. package/src/adapters/solid/components/help/help_overlay.tsx +0 -106
  216. package/src/adapters/solid/components/help/index.ts +0 -1
  217. package/src/adapters/solid/components/log/index.ts +0 -1
  218. package/src/adapters/solid/components/log/log_message.tsx +0 -92
  219. package/src/adapters/solid/components/prompt/index.ts +0 -2
  220. package/src/adapters/solid/components/prompt/prompt_renderer.tsx +0 -350
  221. package/src/adapters/solid/components/screen/group_renderer.tsx +0 -61
  222. package/src/adapters/solid/components/screen/index.ts +0 -6
  223. package/src/adapters/solid/components/screen/loading_message.tsx +0 -39
  224. package/src/adapters/solid/components/screen/message_renderer.tsx +0 -122
  225. package/src/adapters/solid/components/screen/progress_message.tsx +0 -61
  226. package/src/adapters/solid/components/screen/screen_bridge.tsx +0 -155
  227. package/src/adapters/solid/components/screen/table_message.tsx +0 -58
  228. package/src/adapters/solid/components/screen_manager_bridge.tsx +0 -243
  229. package/src/adapters/solid/components/sidebar/index.ts +0 -3
  230. package/src/adapters/solid/components/sidebar/sidebar.tsx +0 -108
  231. package/src/adapters/solid/components/sidebar/sidebar_item.tsx +0 -55
  232. package/src/adapters/solid/components/sidebar/sidebar_separator.tsx +0 -13
  233. package/src/adapters/solid/context/index.ts +0 -2
  234. package/src/adapters/solid/context/logger_context.tsx +0 -95
  235. package/src/adapters/solid/hooks/index.ts +0 -1
  236. package/src/adapters/solid/hooks/use_theme.ts +0 -12
  237. package/src/adapters/solid/index.tsx +0 -43
  238. package/src/adapters/solid/jsx.d.ts +0 -98
  239. package/tsconfig.react.json +0 -16
  240. package/tsconfig.solid.json +0 -16
@@ -1,350 +0,0 @@
1
- import { TextAttributes } from '@opentui/core'
2
- import { Show, For, Switch, Match } from 'solid-js'
3
-
4
- import { useTheme } from '../../hooks/index.ts'
5
-
6
- import type {
7
- PromptData,
8
- ChoicePromptData,
9
- ConfirmPromptData,
10
- InputPromptData,
11
- MultiChoicePromptData,
12
- PromptTheme,
13
- } from '../../../../types/index.ts'
14
-
15
- export interface PromptRendererProps {
16
- prompt: PromptData
17
- }
18
-
19
- export function PromptRenderer(props: PromptRendererProps) {
20
- const theme = useTheme()
21
- // Calculate timeout remaining if applicable
22
- const timeoutRemaining = () => getTimeoutRemaining(props.prompt)
23
-
24
- return (
25
- <Switch fallback={null}>
26
- <Match when={props.prompt.type === 'choice'}>
27
- <ChoicePromptRenderer
28
- prompt={props.prompt as ChoicePromptData}
29
- timeoutRemaining={timeoutRemaining()}
30
- colors={theme.prompt}
31
- />
32
- </Match>
33
- <Match when={props.prompt.type === 'confirm'}>
34
- <ConfirmPromptRenderer
35
- prompt={props.prompt as ConfirmPromptData}
36
- timeoutRemaining={timeoutRemaining()}
37
- colors={theme.prompt}
38
- />
39
- </Match>
40
- <Match when={props.prompt.type === 'input'}>
41
- <InputPromptRenderer
42
- prompt={props.prompt as InputPromptData}
43
- timeoutRemaining={timeoutRemaining()}
44
- colors={theme.prompt}
45
- />
46
- </Match>
47
- <Match when={props.prompt.type === 'multiChoice'}>
48
- <MultiChoicePromptRenderer
49
- prompt={props.prompt as MultiChoicePromptData}
50
- timeoutRemaining={timeoutRemaining()}
51
- colors={theme.prompt}
52
- />
53
- </Match>
54
- </Switch>
55
- )
56
- }
57
-
58
- function getTimeoutRemaining(prompt: PromptData): number | null {
59
- if (!prompt.timeout || !prompt.timeoutStarted) return null
60
- const elapsed = Date.now() - prompt.timeoutStarted
61
- const remaining = Math.max(0, prompt.timeout - elapsed)
62
- return Math.ceil(remaining / 1000)
63
- }
64
-
65
- function TimeoutIndicator(props: { seconds: number | null; colors: PromptTheme }) {
66
- return (
67
- <Show when={props.seconds !== null}>
68
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
69
- {' '}
70
- (auto-select in {props.seconds}s)
71
- </text>
72
- </Show>
73
- )
74
- }
75
-
76
- interface ChoicePromptRendererProps {
77
- prompt: ChoicePromptData
78
- timeoutRemaining: number | null
79
- colors: PromptTheme
80
- }
81
-
82
- function ChoicePromptRenderer(props: ChoicePromptRendererProps) {
83
- return (
84
- <box
85
- flexDirection="column"
86
- borderColor={props.colors.focusBorder}
87
- border={['left']}
88
- paddingLeft={1}
89
- paddingRight={1}
90
- gap={1}
91
- >
92
- {/* Question */}
93
- <box flexDirection="row">
94
- <text fg={props.colors.question} attributes={TextAttributes.BOLD}>
95
- ? {props.prompt.question}
96
- </text>
97
- <TimeoutIndicator seconds={props.timeoutRemaining} colors={props.colors} />
98
- </box>
99
-
100
- {/* Choices */}
101
- <box flexDirection="column">
102
- <For each={props.prompt.choices}>
103
- {(choice, index) => {
104
- const isSelected = () => index() === props.prompt.selectedIndex
105
- const showInput = () => isSelected() && choice.input && props.prompt.inputMode
106
-
107
- return (
108
- <box flexDirection="row">
109
- {/* Selection indicator */}
110
- <text fg={isSelected() ? props.colors.optionSelected : 'transparent'}>{'>'} </text>
111
-
112
- {/* Choice label */}
113
- <text
114
- fg={isSelected() ? props.colors.optionText : props.colors.optionTextDim}
115
- attributes={isSelected() ? TextAttributes.BOLD : undefined}
116
- >
117
- {choice.label}
118
- </text>
119
-
120
- {/* Input field (if applicable) */}
121
- <Show when={showInput()}>
122
- <box flexDirection="row" marginLeft={1}>
123
- <text fg={props.colors.inputText}>: </text>
124
- <text fg={props.colors.inputText}>{props.prompt.inputValue}</text>
125
- <text fg={props.colors.inputCursor} attributes={TextAttributes.BLINK}>
126
- _
127
- </text>
128
- </box>
129
- </Show>
130
-
131
- {/* Show hint for input option when selected but not in input mode */}
132
- <Show when={isSelected() && choice.input && !props.prompt.inputMode}>
133
- <text fg={props.colors.optionTextDim}> (press Enter to type)</text>
134
- </Show>
135
- </box>
136
- )
137
- }}
138
- </For>
139
- </box>
140
-
141
- {/* Instructions */}
142
- <Show
143
- when={props.prompt.inputMode}
144
- fallback={
145
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
146
- ↑/↓ to navigate, Enter to select
147
- </text>
148
- }
149
- >
150
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
151
- Type your answer, Enter to submit, Esc to cancel
152
- </text>
153
- </Show>
154
- </box>
155
- )
156
- }
157
-
158
- interface ConfirmPromptRendererProps {
159
- prompt: ConfirmPromptData
160
- timeoutRemaining: number | null
161
- colors: PromptTheme
162
- }
163
-
164
- function ConfirmPromptRenderer(props: ConfirmPromptRendererProps) {
165
- const confirmSelected = () => props.prompt.selectedValue === true
166
- const cancelSelected = () => props.prompt.selectedValue === false
167
-
168
- return (
169
- <box
170
- flexDirection="column"
171
- borderColor={props.colors.focusBorder}
172
- border={['left']}
173
- paddingLeft={1}
174
- paddingRight={1}
175
- gap={1}
176
- >
177
- {/* Question */}
178
- <box flexDirection="row">
179
- <text fg={props.colors.question} attributes={TextAttributes.BOLD}>
180
- ? {props.prompt.question}
181
- </text>
182
- <TimeoutIndicator seconds={props.timeoutRemaining} colors={props.colors} />
183
- </box>
184
-
185
- {/* Buttons */}
186
- <box flexDirection="row" gap={2}>
187
- {/* Confirm button */}
188
- <box
189
- backgroundColor={confirmSelected() ? props.colors.buttonSelectedBackground : undefined}
190
- paddingLeft={1}
191
- paddingRight={1}
192
- >
193
- <text
194
- fg={confirmSelected() ? props.colors.confirmButton : props.colors.optionTextDim}
195
- attributes={confirmSelected() ? TextAttributes.BOLD : undefined}
196
- >
197
- {confirmSelected() ? '>' : ' '} {props.prompt.confirmText}
198
- </text>
199
- </box>
200
-
201
- {/* Cancel button */}
202
- <box
203
- backgroundColor={cancelSelected() ? props.colors.buttonSelectedBackground : undefined}
204
- paddingLeft={1}
205
- paddingRight={1}
206
- >
207
- <text
208
- fg={cancelSelected() ? props.colors.cancelButton : props.colors.optionTextDim}
209
- attributes={cancelSelected() ? TextAttributes.BOLD : undefined}
210
- >
211
- {cancelSelected() ? '>' : ' '} {props.prompt.cancelText}
212
- </text>
213
- </box>
214
- </box>
215
-
216
- {/* Instructions */}
217
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
218
- ←/→ to select, Enter to confirm
219
- </text>
220
- </box>
221
- )
222
- }
223
-
224
- interface InputPromptRendererProps {
225
- prompt: InputPromptData
226
- timeoutRemaining: number | null
227
- colors: PromptTheme
228
- }
229
-
230
- function InputPromptRenderer(props: InputPromptRendererProps) {
231
- const hasValue = () => props.prompt.value.length > 0
232
-
233
- return (
234
- <box
235
- flexDirection="column"
236
- borderColor={props.colors.focusBorder}
237
- border={['left']}
238
- paddingLeft={1}
239
- paddingRight={1}
240
- gap={1}
241
- >
242
- {/* Question */}
243
- <box flexDirection="row">
244
- <text fg={props.colors.question} attributes={TextAttributes.BOLD}>
245
- ? {props.prompt.question}
246
- </text>
247
- <TimeoutIndicator seconds={props.timeoutRemaining} colors={props.colors} />
248
- </box>
249
-
250
- {/* Input field */}
251
- <box flexDirection="row" borderColor={props.colors.inputBorder} border={['left']} paddingLeft={1}>
252
- <text fg={hasValue() ? props.colors.inputText : props.colors.inputPlaceholder}>
253
- {hasValue() ? props.prompt.value : props.prompt.placeholder}
254
- </text>
255
- <text fg={props.colors.inputCursor} attributes={TextAttributes.BLINK}>
256
- _
257
- </text>
258
- </box>
259
-
260
- {/* Instructions */}
261
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
262
- Type your answer, Enter to submit
263
- </text>
264
- </box>
265
- )
266
- }
267
-
268
- interface MultiChoicePromptRendererProps {
269
- prompt: MultiChoicePromptData
270
- timeoutRemaining: number | null
271
- colors: PromptTheme
272
- }
273
-
274
- function MultiChoicePromptRenderer(props: MultiChoicePromptRendererProps) {
275
- const selectedCount = () => props.prompt.selectedIndices.size
276
- const canSubmit = () => selectedCount() >= props.prompt.minSelect
277
-
278
- return (
279
- <box
280
- flexDirection="column"
281
- borderColor={props.colors.focusBorder}
282
- border={['left']}
283
- paddingLeft={1}
284
- paddingRight={1}
285
- gap={1}
286
- >
287
- {/* Question */}
288
- <box flexDirection="row">
289
- <text fg={props.colors.question} attributes={TextAttributes.BOLD}>
290
- ? {props.prompt.question}
291
- </text>
292
- <text fg={props.colors.optionTextDim}>
293
- {' '}
294
- ({selectedCount()}/{props.prompt.maxSelect} selected)
295
- </text>
296
- <TimeoutIndicator seconds={props.timeoutRemaining} colors={props.colors} />
297
- </box>
298
-
299
- {/* Choices */}
300
- <box flexDirection="column">
301
- <For each={props.prompt.choices}>
302
- {(choice, index) => {
303
- const isFocused = () => index() === props.prompt.focusedIndex
304
- const isChecked = () => props.prompt.selectedIndices.has(index())
305
-
306
- return (
307
- <box flexDirection="row">
308
- {/* Focus indicator */}
309
- <text fg={isFocused() ? props.colors.optionSelected : 'transparent'}>{'>'} </text>
310
-
311
- {/* Checkbox */}
312
- <text fg={isChecked() ? props.colors.optionSelected : props.colors.optionTextDim}>
313
- {isChecked() ? '[✓]' : '[ ]'}{' '}
314
- </text>
315
-
316
- {/* Choice label */}
317
- <text
318
- fg={isFocused() ? props.colors.optionText : props.colors.optionTextDim}
319
- attributes={isFocused() ? TextAttributes.BOLD : undefined}
320
- >
321
- {choice.label}
322
- </text>
323
- </box>
324
- )
325
- }}
326
- </For>
327
- </box>
328
-
329
- {/* Instructions */}
330
- <box flexDirection="column">
331
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
332
- ↑/↓ to navigate, Space to toggle
333
- </text>
334
- <Show
335
- when={canSubmit()}
336
- fallback={
337
- <text fg={props.colors.cancelButton} attributes={TextAttributes.DIM}>
338
- Select at least {props.prompt.minSelect} option
339
- {props.prompt.minSelect > 1 ? 's' : ''}
340
- </text>
341
- }
342
- >
343
- <text fg={props.colors.optionTextDim} attributes={TextAttributes.DIM}>
344
- Enter to confirm
345
- </text>
346
- </Show>
347
- </box>
348
- </box>
349
- )
350
- }
@@ -1,61 +0,0 @@
1
- import { TextAttributes } from '@opentui/core'
2
- import { For, Show } from 'solid-js'
3
-
4
- import { useTheme } from '../../hooks/index.ts'
5
-
6
- import type { MessageData, GroupMessageData } from '../../../../types/index.ts'
7
-
8
- import { MessageRenderer } from './message_renderer.tsx'
9
-
10
- export interface GroupRendererProps {
11
- label: string
12
- messages: MessageData[]
13
- }
14
-
15
- export function GroupRenderer(props: GroupRendererProps) {
16
- const theme = useTheme()
17
-
18
- return (
19
- <box
20
- flexDirection="column"
21
- border={['left']}
22
- borderColor={theme.group.border}
23
- backgroundColor={theme.group.background}
24
- paddingLeft={1}
25
- >
26
- {/* Group header */}
27
- <box flexDirection="row" marginBottom={1}>
28
- <text fg={theme.group.icon}>▼ </text>
29
- <text fg={theme.group.headerText} attributes={TextAttributes.BOLD}>
30
- {props.label}
31
- </text>
32
- </box>
33
-
34
- {/* Group content */}
35
- <box flexDirection="column" gap={1}>
36
- <For each={props.messages}>{(msg) => <MessageRenderer message={msg} />}</For>
37
- </box>
38
- </box>
39
- )
40
- }
41
-
42
- export interface GroupMessageRendererProps {
43
- message: GroupMessageData
44
- }
45
-
46
- /**
47
- * Fallback renderer for group markers (when not processed at higher level)
48
- */
49
- export function GroupMessageRenderer(props: GroupMessageRendererProps) {
50
- const theme = useTheme()
51
-
52
- return (
53
- <Show when={!props.message.isEnd}>
54
- <box flexDirection="row" borderColor={theme.group.border} border={['left']} paddingLeft={1}>
55
- <text fg={theme.group.headerText} attributes={TextAttributes.BOLD}>
56
- ▼ {props.message.label}
57
- </text>
58
- </box>
59
- </Show>
60
- )
61
- }
@@ -1,6 +0,0 @@
1
- export * from './screen_bridge.tsx'
2
- export * from './message_renderer.tsx'
3
- export * from './group_renderer.tsx'
4
- export * from './loading_message.tsx'
5
- export * from './progress_message.tsx'
6
- export * from './table_message.tsx'
@@ -1,39 +0,0 @@
1
- import { createSignal, createEffect, onCleanup } from 'solid-js'
2
-
3
- import { LogMessage } from '../log/index.ts'
4
-
5
- import type { LoadingMessageData, LogMessageVariant } from '../../../../types/index.ts'
6
-
7
- const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
8
-
9
- export interface LoadingMessageProps {
10
- message: LoadingMessageData
11
- }
12
-
13
- export function LoadingMessage(props: LoadingMessageProps) {
14
- const [frameIndex, setFrameIndex] = createSignal(0)
15
-
16
- createEffect(() => {
17
- if (props.message.status === 'loading') {
18
- const interval = setInterval(() => {
19
- setFrameIndex((prev) => (prev + 1) % SPINNER_FRAMES.length)
20
- }, 80)
21
-
22
- onCleanup(() => clearInterval(interval))
23
- }
24
- })
25
-
26
- // Map loading status to log level and variant for display
27
- const level = () => (props.message.status === 'fail' ? 'error' : 'log')
28
- const variant = (): LogMessageVariant | undefined =>
29
- props.message.status === 'success' ? 'success' : undefined
30
-
31
- const displayContent = () => props.message.resolvedContent ?? props.message.content
32
- const spinner = () => (props.message.status === 'loading' ? SPINNER_FRAMES[frameIndex()] + ' ' : '')
33
-
34
- return (
35
- <LogMessage level={level()} variant={variant()} timestamp={props.message.timestamp}>
36
- {spinner() + displayContent()}
37
- </LogMessage>
38
- )
39
- }
@@ -1,122 +0,0 @@
1
- import { Switch, Match } from 'solid-js'
2
-
3
- import { useTheme } from '../../hooks/index.ts'
4
- import { FileLog } from '../file/index.ts'
5
- import { LogMessage } from '../log/index.ts'
6
-
7
- import type {
8
- MessageData,
9
- LogMessageData,
10
- FileMessageData,
11
- DiffMessageData,
12
- FileErrorMessageData,
13
- LoadingMessageData,
14
- ProgressMessageData,
15
- GroupMessageData,
16
- TableMessageData,
17
- } from '../../../../types/index.ts'
18
-
19
- import { GroupMessageRenderer } from './group_renderer.tsx'
20
- import { LoadingMessage } from './loading_message.tsx'
21
- import { ProgressMessage } from './progress_message.tsx'
22
- import { TableMessage } from './table_message.tsx'
23
-
24
- export interface MessageRendererProps {
25
- message: MessageData
26
- }
27
-
28
- export function MessageRenderer(props: MessageRendererProps) {
29
- const theme = useTheme()
30
- const msg = () => props.message
31
-
32
- return (
33
- <Switch fallback={null}>
34
- <Match when={msg().type === 'log' && (msg() as LogMessageData)}>
35
- {(logMsg) => (
36
- <LogMessage
37
- level={logMsg().level}
38
- timestamp={logMsg().timestamp}
39
- variant={logMsg().variant}
40
- label={logMsg().label}
41
- trace={logMsg().trace}
42
- >
43
- {logMsg().content}
44
- </LogMessage>
45
- )}
46
- </Match>
47
-
48
- <Match when={msg().type === 'file' && (msg() as FileMessageData)}>
49
- {(fileMsg) => (
50
- <box
51
- flexDirection="column"
52
- border={['left']}
53
- borderColor={theme.file.border}
54
- backgroundColor={theme.file.background}
55
- >
56
- <FileLog
57
- mode="full"
58
- filePath={fileMsg().filePath}
59
- content={fileMsg().content}
60
- headerBackgroundColor={theme.file.headerBackground}
61
- />
62
- </box>
63
- )}
64
- </Match>
65
-
66
- <Match when={msg().type === 'diff' && (msg() as DiffMessageData)}>
67
- {(diffMsg) => (
68
- <box
69
- flexDirection="column"
70
- border={['left']}
71
- borderColor={theme.file.border}
72
- backgroundColor={theme.file.background}
73
- >
74
- <FileLog
75
- mode="diff"
76
- filePath={diffMsg().filePath}
77
- diff={diffMsg().diff}
78
- view={diffMsg().view}
79
- headerBackgroundColor={theme.file.headerBackground}
80
- />
81
- </box>
82
- )}
83
- </Match>
84
-
85
- <Match when={msg().type === 'fileError' && (msg() as FileErrorMessageData)}>
86
- {(errorMsg) => (
87
- <box
88
- flexDirection="column"
89
- border={['left']}
90
- borderColor={theme.file.border}
91
- backgroundColor={theme.file.background}
92
- >
93
- <FileLog
94
- mode="partial"
95
- filePath={errorMsg().filePath}
96
- content={errorMsg().content}
97
- startLine={errorMsg().startLine}
98
- errorLines={errorMsg().errorLines}
99
- headerBackgroundColor={theme.file.headerBackground}
100
- />
101
- </box>
102
- )}
103
- </Match>
104
-
105
- <Match when={msg().type === 'loading' && (msg() as LoadingMessageData)}>
106
- {(loadingMsg) => <LoadingMessage message={loadingMsg()} />}
107
- </Match>
108
-
109
- <Match when={msg().type === 'progress' && (msg() as ProgressMessageData)}>
110
- {(progressMsg) => <ProgressMessage message={progressMsg()} />}
111
- </Match>
112
-
113
- <Match when={msg().type === 'group' && (msg() as GroupMessageData)}>
114
- {(groupMsg) => <GroupMessageRenderer message={groupMsg()} />}
115
- </Match>
116
-
117
- <Match when={msg().type === 'table' && (msg() as TableMessageData)}>
118
- {(tableMsg) => <TableMessage message={tableMsg()} />}
119
- </Match>
120
- </Switch>
121
- )
122
- }
@@ -1,61 +0,0 @@
1
- import { useTheme } from '../../hooks/index.ts'
2
-
3
- import type { ProgressMessageData } from '../../../../types/index.ts'
4
-
5
- export interface ProgressMessageProps {
6
- message: ProgressMessageData
7
- }
8
-
9
- export function ProgressMessage(props: ProgressMessageProps) {
10
- const theme = useTheme()
11
-
12
- const percent = () => Math.round((props.message.current / props.message.total) * 100)
13
- const barWidth = 20
14
- const filled = () => Math.round((percent() / 100) * barWidth)
15
- const empty = () => barWidth - filled()
16
-
17
- const barFilled = () => '█'.repeat(filled())
18
- const barEmpty = () => '░'.repeat(empty())
19
-
20
- // Determine colors based on status
21
- const borderColor = () =>
22
- props.message.status === 'complete'
23
- ? theme.progress.complete
24
- : props.message.status === 'failed'
25
- ? theme.progress.failed
26
- : theme.progress.border
27
-
28
- const backgroundColor = () =>
29
- props.message.status === 'complete'
30
- ? theme.progress.completeBackground
31
- : props.message.status === 'failed'
32
- ? theme.progress.failedBackground
33
- : theme.progress.background
34
-
35
- const barColor = () =>
36
- props.message.status === 'complete'
37
- ? theme.progress.complete
38
- : props.message.status === 'failed'
39
- ? theme.progress.failed
40
- : theme.progress.barFilled
41
-
42
- const displayLabel = () => props.message.resolvedContent ?? props.message.label
43
-
44
- return (
45
- <box
46
- flexDirection="column"
47
- border={['left']}
48
- borderColor={borderColor()}
49
- backgroundColor={backgroundColor()}
50
- paddingLeft={1}
51
- paddingRight={1}
52
- >
53
- <box flexDirection="row" gap={1}>
54
- <text fg={barColor()}>[{barFilled()}</text>
55
- <text fg={theme.progress.barEmpty}>{barEmpty()}]</text>
56
- <text fg={theme.progress.textDim}>{percent()}%</text>
57
- <text fg={theme.progress.text}>{displayLabel()}</text>
58
- </box>
59
- </box>
60
- )
61
- }