@navios/commander-tui 1.0.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.
- package/CHANGELOG.md +25 -0
- package/README.md +275 -0
- package/coverage/__tests__/utils/factories.ts.html +1147 -0
- package/coverage/__tests__/utils/index.html +131 -0
- package/coverage/__tests__/utils/render-utils.tsx.html +202 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +959 -0
- package/coverage/components/filter/filter_bar.tsx.html +322 -0
- package/coverage/components/filter/index.html +116 -0
- package/coverage/components/log/index.html +131 -0
- package/coverage/components/log/index.ts.html +88 -0
- package/coverage/components/log/log_message.tsx.html +391 -0
- package/coverage/components/prompt/index.html +116 -0
- package/coverage/components/prompt/prompt_renderer.tsx.html +1123 -0
- package/coverage/components/screen/index.html +131 -0
- package/coverage/components/screen/loading_message.tsx.html +217 -0
- package/coverage/components/screen/progress_message.tsx.html +265 -0
- package/coverage/components/sidebar/index.html +146 -0
- package/coverage/components/sidebar/sidebar.tsx.html +391 -0
- package/coverage/components/sidebar/sidebar_item.tsx.html +235 -0
- package/coverage/components/sidebar/sidebar_separator.tsx.html +124 -0
- package/coverage/context/index.html +131 -0
- package/coverage/context/index.ts.html +88 -0
- package/coverage/context/logger_context.tsx.html +412 -0
- package/coverage/coverage-final.json +55 -0
- package/coverage/favicon.png +0 -0
- package/coverage/filter/filter_engine.ts.html +424 -0
- package/coverage/filter/index.html +116 -0
- package/coverage/hooks/index.html +131 -0
- package/coverage/hooks/index.ts.html +88 -0
- package/coverage/hooks/use_theme.ts.html +121 -0
- package/coverage/index.html +356 -0
- package/coverage/keyboard/index.html +116 -0
- package/coverage/keyboard/keyboard_manager.ts.html +784 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/schemas/index.html +161 -0
- package/coverage/schemas/index.ts.html +94 -0
- package/coverage/schemas/logger-options.ts.html +124 -0
- package/coverage/schemas/prompt-options.ts.html +112 -0
- package/coverage/schemas/screen-options.ts.html +127 -0
- package/coverage/services/index.html +146 -0
- package/coverage/services/logger.ts.html +1192 -0
- package/coverage/services/prompt.ts.html +568 -0
- package/coverage/services/screen.ts.html +1804 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/themes/dark.ts.html +604 -0
- package/coverage/themes/high-contrast.ts.html +619 -0
- package/coverage/themes/index.html +176 -0
- package/coverage/themes/index.ts.html +97 -0
- package/coverage/themes/light.ts.html +601 -0
- package/coverage/themes/utils.ts.html +334 -0
- package/coverage/tokens/index.html +161 -0
- package/coverage/tokens/index.ts.html +94 -0
- package/coverage/tokens/logger.ts.html +115 -0
- package/coverage/tokens/prompt.ts.html +115 -0
- package/coverage/tokens/screen.ts.html +115 -0
- package/coverage/types/file.types.ts.html +265 -0
- package/coverage/types/filter.types.ts.html +238 -0
- package/coverage/types/index.html +236 -0
- package/coverage/types/index.ts.html +151 -0
- package/coverage/types/keyboard.types.ts.html +364 -0
- package/coverage/types/log.types.ts.html +268 -0
- package/coverage/types/message.types.ts.html +445 -0
- package/coverage/types/prompt.types.ts.html +403 -0
- package/coverage/types/screen.types.ts.html +451 -0
- package/coverage/types/theme.types.ts.html +841 -0
- package/coverage/utils/colors/file-colors.ts.html +112 -0
- package/coverage/utils/colors/helpers.ts.html +235 -0
- package/coverage/utils/colors/index.html +221 -0
- package/coverage/utils/colors/index.ts.html +145 -0
- package/coverage/utils/colors/log-colors.ts.html +253 -0
- package/coverage/utils/colors/progress-colors.ts.html +160 -0
- package/coverage/utils/colors/prompt-colors.ts.html +175 -0
- package/coverage/utils/colors/sidebar-colors.ts.html +241 -0
- package/coverage/utils/colors/table-colors.ts.html +118 -0
- package/coverage/utils/filetype.ts.html +277 -0
- package/coverage/utils/format.ts.html +241 -0
- package/coverage/utils/index.html +161 -0
- package/coverage/utils/index.ts.html +118 -0
- package/coverage/utils/stdout-printer.ts.html +523 -0
- package/dist/src/components/file/file_log.d.ts +35 -0
- package/dist/src/components/file/file_log.d.ts.map +1 -0
- package/dist/src/components/file/index.d.ts +2 -0
- package/dist/src/components/file/index.d.ts.map +1 -0
- package/dist/src/components/filter/filter_bar.d.ts +10 -0
- package/dist/src/components/filter/filter_bar.d.ts.map +1 -0
- package/dist/src/components/filter/index.d.ts +2 -0
- package/dist/src/components/filter/index.d.ts.map +1 -0
- package/dist/src/components/help/help_overlay.d.ts +10 -0
- package/dist/src/components/help/help_overlay.d.ts.map +1 -0
- package/dist/src/components/help/index.d.ts +2 -0
- package/dist/src/components/help/index.d.ts.map +1 -0
- package/dist/src/components/index.d.ts +27 -0
- package/dist/src/components/index.d.ts.map +1 -0
- package/dist/src/components/log/debug_log.d.ts +3 -0
- package/dist/src/components/log/debug_log.d.ts.map +1 -0
- package/dist/src/components/log/error_log.d.ts +3 -0
- package/dist/src/components/log/error_log.d.ts.map +1 -0
- package/dist/src/components/log/fatal_log.d.ts +3 -0
- package/dist/src/components/log/fatal_log.d.ts.map +1 -0
- package/dist/src/components/log/index.d.ts +9 -0
- package/dist/src/components/log/index.d.ts.map +1 -0
- package/dist/src/components/log/info_log.d.ts +3 -0
- package/dist/src/components/log/info_log.d.ts.map +1 -0
- package/dist/src/components/log/log_message.d.ts +33 -0
- package/dist/src/components/log/log_message.d.ts.map +1 -0
- package/dist/src/components/log/success_log.d.ts +3 -0
- package/dist/src/components/log/success_log.d.ts.map +1 -0
- package/dist/src/components/log/trace_log.d.ts +3 -0
- package/dist/src/components/log/trace_log.d.ts.map +1 -0
- package/dist/src/components/log/warning_log.d.ts +3 -0
- package/dist/src/components/log/warning_log.d.ts.map +1 -0
- package/dist/src/components/prompt/index.d.ts +3 -0
- package/dist/src/components/prompt/index.d.ts.map +1 -0
- package/dist/src/components/prompt/prompt_renderer.d.ts +6 -0
- package/dist/src/components/prompt/prompt_renderer.d.ts.map +1 -0
- package/dist/src/components/screen/group_renderer.d.ts +19 -0
- package/dist/src/components/screen/group_renderer.d.ts.map +1 -0
- package/dist/src/components/screen/index.d.ts +13 -0
- package/dist/src/components/screen/index.d.ts.map +1 -0
- package/dist/src/components/screen/loading_message.d.ts +6 -0
- package/dist/src/components/screen/loading_message.d.ts.map +1 -0
- package/dist/src/components/screen/message_renderer.d.ts +8 -0
- package/dist/src/components/screen/message_renderer.d.ts.map +1 -0
- package/dist/src/components/screen/progress_message.d.ts +8 -0
- package/dist/src/components/screen/progress_message.d.ts.map +1 -0
- package/dist/src/components/screen/screen_bridge.d.ts +20 -0
- package/dist/src/components/screen/screen_bridge.d.ts.map +1 -0
- package/dist/src/components/screen/table_message.d.ts +6 -0
- package/dist/src/components/screen/table_message.d.ts.map +1 -0
- package/dist/src/components/screen_manager_bridge.d.ts +11 -0
- package/dist/src/components/screen_manager_bridge.d.ts.map +1 -0
- package/dist/src/components/sidebar/index.d.ts +6 -0
- package/dist/src/components/sidebar/index.d.ts.map +1 -0
- package/dist/src/components/sidebar/sidebar.d.ts +18 -0
- package/dist/src/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/src/components/sidebar/sidebar_item.d.ts +14 -0
- package/dist/src/components/sidebar/sidebar_item.d.ts.map +1 -0
- package/dist/src/components/sidebar/sidebar_separator.d.ts +2 -0
- package/dist/src/components/sidebar/sidebar_separator.d.ts.map +1 -0
- package/dist/src/context/logger_context.d.ts +60 -0
- package/dist/src/context/logger_context.d.ts.map +1 -0
- package/dist/src/filter/filter_engine.d.ts +20 -0
- package/dist/src/filter/filter_engine.d.ts.map +1 -0
- package/dist/src/filter/index.d.ts +4 -0
- package/dist/src/filter/index.d.ts.map +1 -0
- package/dist/src/hooks/index.d.ts +2 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/use_theme.d.ts +7 -0
- package/dist/src/hooks/use_theme.d.ts.map +1 -0
- package/dist/src/index.d.ts +88 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/keyboard/create_bindings.d.ts +31 -0
- package/dist/src/keyboard/create_bindings.d.ts.map +1 -0
- package/dist/src/keyboard/index.d.ts +12 -0
- package/dist/src/keyboard/index.d.ts.map +1 -0
- package/dist/src/keyboard/keyboard_manager.d.ts +69 -0
- package/dist/src/keyboard/keyboard_manager.d.ts.map +1 -0
- package/dist/src/services/index.d.ts +5 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/logger.d.ts +61 -0
- package/dist/src/services/logger.d.ts.map +1 -0
- package/dist/src/services/prompt.d.ts +37 -0
- package/dist/src/services/prompt.d.ts.map +1 -0
- package/dist/src/services/screen.d.ts +165 -0
- package/dist/src/services/screen.d.ts.map +1 -0
- package/dist/src/services/screen_manager.d.ts +124 -0
- package/dist/src/services/screen_manager.d.ts.map +1 -0
- package/dist/src/themes/dark.d.ts +7 -0
- package/dist/src/themes/dark.d.ts.map +1 -0
- package/dist/src/themes/high-contrast.d.ts +7 -0
- package/dist/src/themes/high-contrast.d.ts.map +1 -0
- package/dist/src/themes/index.d.ts +18 -0
- package/dist/src/themes/index.d.ts.map +1 -0
- package/dist/src/themes/light.d.ts +6 -0
- package/dist/src/themes/light.d.ts.map +1 -0
- package/dist/src/themes/utils.d.ts +22 -0
- package/dist/src/themes/utils.d.ts.map +1 -0
- package/dist/src/types/file.types.d.ts +40 -0
- package/dist/src/types/file.types.d.ts.map +1 -0
- package/dist/src/types/filter.types.d.ts +31 -0
- package/dist/src/types/filter.types.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +81 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/keyboard.types.d.ts +83 -0
- package/dist/src/types/keyboard.types.d.ts.map +1 -0
- package/dist/src/types/log.types.d.ts +32 -0
- package/dist/src/types/log.types.d.ts.map +1 -0
- package/dist/src/types/message.types.d.ts +91 -0
- package/dist/src/types/message.types.d.ts.map +1 -0
- package/dist/src/types/prompt.types.d.ts +89 -0
- package/dist/src/types/prompt.types.d.ts.map +1 -0
- package/dist/src/types/screen.types.d.ts +85 -0
- package/dist/src/types/screen.types.d.ts.map +1 -0
- package/dist/src/types/theme.types.d.ts +216 -0
- package/dist/src/types/theme.types.d.ts.map +1 -0
- package/dist/src/utils/colors/file-colors.d.ts +10 -0
- package/dist/src/utils/colors/file-colors.d.ts.map +1 -0
- package/dist/src/utils/colors/helpers.d.ts +29 -0
- package/dist/src/utils/colors/helpers.d.ts.map +1 -0
- package/dist/src/utils/colors/index.d.ts +13 -0
- package/dist/src/utils/colors/index.d.ts.map +1 -0
- package/dist/src/utils/colors/log-colors.d.ts +15 -0
- package/dist/src/utils/colors/log-colors.d.ts.map +1 -0
- package/dist/src/utils/colors/progress-colors.d.ts +25 -0
- package/dist/src/utils/colors/progress-colors.d.ts.map +1 -0
- package/dist/src/utils/colors/prompt-colors.d.ts +22 -0
- package/dist/src/utils/colors/prompt-colors.d.ts.map +1 -0
- package/dist/src/utils/colors/sidebar-colors.d.ts +50 -0
- package/dist/src/utils/colors/sidebar-colors.d.ts.map +1 -0
- package/dist/src/utils/colors/table-colors.d.ts +12 -0
- package/dist/src/utils/colors/table-colors.d.ts.map +1 -0
- package/dist/src/utils/filetype.d.ts +19 -0
- package/dist/src/utils/filetype.d.ts.map +1 -0
- package/dist/src/utils/format.d.ts +9 -0
- package/dist/src/utils/format.d.ts.map +1 -0
- package/dist/src/utils/index.d.ts +20 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/stdout-printer.d.ts +10 -0
- package/dist/src/utils/stdout-printer.d.ts.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/tsdown.config.d.mts +5 -0
- package/dist/tsdown.config.d.mts.map +1 -0
- package/dist/vitest.config.d.mts +3 -0
- package/dist/vitest.config.d.mts.map +1 -0
- package/lib/index.cjs +6349 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +1720 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +1720 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +6264 -0
- package/lib/index.mjs.map +1 -0
- package/lib/screen_manager_bridge-BpDgVu3e.cjs +3357 -0
- package/lib/screen_manager_bridge-BpDgVu3e.cjs.map +1 -0
- package/lib/screen_manager_bridge-CkV7637i.cjs +3 -0
- package/lib/screen_manager_bridge-DN2J6_k1.mjs +3 -0
- package/lib/screen_manager_bridge-Dfg4QUrl.mjs +3034 -0
- package/lib/screen_manager_bridge-Dfg4QUrl.mjs.map +1 -0
- package/package.json +43 -0
- package/project.json +60 -0
- package/src/__tests__/components/__snapshots__/filter_bar.spec.tsx.snap +2245 -0
- package/src/__tests__/components/__snapshots__/loading_message.spec.tsx.snap +1382 -0
- package/src/__tests__/components/__snapshots__/log_message.spec.tsx.snap +3169 -0
- package/src/__tests__/components/__snapshots__/progress_message.spec.tsx.snap +1743 -0
- package/src/__tests__/components/__snapshots__/prompt_renderer.spec.tsx.snap +3135 -0
- package/src/__tests__/components/__snapshots__/sidebar.spec.tsx.snap +2617 -0
- package/src/__tests__/components/filter_bar.spec.tsx +190 -0
- package/src/__tests__/components/loading_message.spec.tsx +110 -0
- package/src/__tests__/components/log_message.spec.tsx +166 -0
- package/src/__tests__/components/progress_message.spec.tsx +147 -0
- package/src/__tests__/components/prompt_renderer.spec.tsx +274 -0
- package/src/__tests__/components/sidebar.spec.tsx +305 -0
- package/src/__tests__/filter/filter_engine.spec.ts +325 -0
- package/src/__tests__/keyboard/keyboard_manager.spec.ts +557 -0
- package/src/__tests__/mocks/scm-mock.ts +5 -0
- package/src/__tests__/services/logger.spec.ts +630 -0
- package/src/__tests__/services/prompt.spec.ts +411 -0
- package/src/__tests__/services/screen.spec.ts +721 -0
- package/src/__tests__/setup.ts +43 -0
- package/src/__tests__/utils/factories.ts +354 -0
- package/src/__tests__/utils/filetype.spec.ts +195 -0
- package/src/__tests__/utils/format.spec.ts +178 -0
- package/src/__tests__/utils/render-utils.tsx +39 -0
- package/src/__tests__/utils/test-container.ts +48 -0
- package/src/components/file/file_log.tsx +241 -0
- package/src/components/file/index.ts +1 -0
- package/src/components/filter/filter_bar.tsx +79 -0
- package/src/components/filter/index.ts +1 -0
- package/src/components/help/help_overlay.tsx +100 -0
- package/src/components/help/index.ts +1 -0
- package/src/components/index.ts +15 -0
- package/src/components/log/index.ts +1 -0
- package/src/components/log/log_message.tsx +102 -0
- package/src/components/prompt/index.ts +2 -0
- package/src/components/prompt/prompt_renderer.tsx +346 -0
- package/src/components/screen/group_renderer.tsx +64 -0
- package/src/components/screen/index.ts +6 -0
- package/src/components/screen/loading_message.tsx +44 -0
- package/src/components/screen/message_renderer.tsx +108 -0
- package/src/components/screen/progress_message.tsx +60 -0
- package/src/components/screen/screen_bridge.tsx +149 -0
- package/src/components/screen/table_message.tsx +57 -0
- package/src/components/screen_manager_bridge.tsx +245 -0
- package/src/components/sidebar/index.ts +3 -0
- package/src/components/sidebar/sidebar.tsx +102 -0
- package/src/components/sidebar/sidebar_item.tsx +50 -0
- package/src/components/sidebar/sidebar_separator.tsx +13 -0
- package/src/context/index.ts +1 -0
- package/src/context/logger_context.tsx +109 -0
- package/src/factories/index.ts +1 -0
- package/src/factories/screen.factory.ts +22 -0
- package/src/filter/filter_engine.ts +113 -0
- package/src/filter/index.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use_theme.ts +12 -0
- package/src/index.ts +64 -0
- package/src/keyboard/create_bindings.ts +457 -0
- package/src/keyboard/index.ts +2 -0
- package/src/keyboard/keyboard_manager.ts +233 -0
- package/src/overrides/console.logger.override.ts +61 -0
- package/src/overrides/index.ts +1 -0
- package/src/schemas/index.ts +3 -0
- package/src/schemas/logger-options.ts +13 -0
- package/src/schemas/prompt-options.ts +9 -0
- package/src/schemas/screen-options.ts +14 -0
- package/src/services/index.ts +4 -0
- package/src/services/logger.ts +369 -0
- package/src/services/prompt.ts +169 -0
- package/src/services/screen.ts +590 -0
- package/src/services/screen_manager.tsx +390 -0
- package/src/themes/dark.ts +173 -0
- package/src/themes/high-contrast.ts +178 -0
- package/src/themes/index.ts +4 -0
- package/src/themes/light.ts +172 -0
- package/src/themes/utils.ts +83 -0
- package/src/tokens/index.ts +3 -0
- package/src/tokens/logger.ts +10 -0
- package/src/tokens/prompt.ts +10 -0
- package/src/tokens/screen.ts +10 -0
- package/src/types/file.types.ts +60 -0
- package/src/types/filter.types.ts +51 -0
- package/src/types/index.ts +22 -0
- package/src/types/keyboard.types.ts +93 -0
- package/src/types/log.types.ts +61 -0
- package/src/types/message.types.ts +120 -0
- package/src/types/prompt.types.ts +106 -0
- package/src/types/screen.types.ts +124 -0
- package/src/types/theme.types.ts +252 -0
- package/src/utils/colors/file-colors.ts +9 -0
- package/src/utils/colors/helpers.ts +50 -0
- package/src/utils/colors/index.ts +20 -0
- package/src/utils/colors/log-colors.ts +56 -0
- package/src/utils/colors/progress-colors.ts +25 -0
- package/src/utils/colors/prompt-colors.ts +30 -0
- package/src/utils/colors/sidebar-colors.ts +52 -0
- package/src/utils/colors/table-colors.ts +11 -0
- package/src/utils/filetype.ts +64 -0
- package/src/utils/format.ts +52 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/stdout-printer.ts +255 -0
- package/tsconfig.json +14 -0
- package/tsdown.config.mts +34 -0
- package/vitest.config.mts +10 -0
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
import type { ScreenOptions } from '../schemas/index.ts'
|
|
2
|
+
import type {
|
|
3
|
+
ChoicePromptData,
|
|
4
|
+
ConfirmPromptData,
|
|
5
|
+
InputPromptData,
|
|
6
|
+
LoadingMessageData,
|
|
7
|
+
MessageData,
|
|
8
|
+
MultiChoicePromptData,
|
|
9
|
+
ProgressMessageData,
|
|
10
|
+
PromptData,
|
|
11
|
+
ScreenStatus,
|
|
12
|
+
} from '../types/index.ts'
|
|
13
|
+
|
|
14
|
+
import type { ScreenManager } from './screen_manager.tsx'
|
|
15
|
+
|
|
16
|
+
interface PendingPrompt {
|
|
17
|
+
data: PromptData
|
|
18
|
+
resolve: (value: string | boolean | string[]) => void
|
|
19
|
+
timeoutId?: ReturnType<typeof setTimeout>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class ScreenInstance {
|
|
23
|
+
private id: string
|
|
24
|
+
private name: string
|
|
25
|
+
private icon?: string
|
|
26
|
+
private badgeCount: number = 0
|
|
27
|
+
private status: ScreenStatus = 'waiting'
|
|
28
|
+
private hidden: boolean = false
|
|
29
|
+
private messages: MessageData[] = []
|
|
30
|
+
private manager: ScreenManager | null = null
|
|
31
|
+
private changeListeners: Set<() => void> = new Set()
|
|
32
|
+
private printFn: ((messages: MessageData[], name: string, isError: boolean) => void) | null = null
|
|
33
|
+
private hasPrinted: boolean = false
|
|
34
|
+
private version: number = 0
|
|
35
|
+
|
|
36
|
+
// Prompt queue system
|
|
37
|
+
private promptQueue: PendingPrompt[] = []
|
|
38
|
+
private activePrompt: PendingPrompt | null = null
|
|
39
|
+
|
|
40
|
+
constructor(id: string, options: ScreenOptions) {
|
|
41
|
+
this.id = id
|
|
42
|
+
this.name = options.name
|
|
43
|
+
this.icon = options.icon
|
|
44
|
+
this.badgeCount = options.badgeCount ?? 0
|
|
45
|
+
this.hidden = options.hidden ?? false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
incrementVersion(): void {
|
|
49
|
+
this.version++
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getVersion(): number {
|
|
53
|
+
return this.version
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Internal: Set the manager reference
|
|
58
|
+
*/
|
|
59
|
+
_setManager(manager: ScreenManager): void {
|
|
60
|
+
this.manager = manager
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Internal: Set the print function for stdout output
|
|
65
|
+
*/
|
|
66
|
+
_setPrintFn(fn: (messages: MessageData[], name: string, isError: boolean) => void): void {
|
|
67
|
+
this.printFn = fn
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getId(): string {
|
|
71
|
+
return this.id
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getName(): string {
|
|
75
|
+
return this.name
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getIcon(): string | undefined {
|
|
79
|
+
return this.icon
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getBadgeCount(): number {
|
|
83
|
+
return this.badgeCount
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
setBadgeCount(count: number): this {
|
|
87
|
+
this.badgeCount = count
|
|
88
|
+
this.notifyChange()
|
|
89
|
+
return this
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
isHidden(): boolean {
|
|
93
|
+
return this.hidden
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setHidden(hidden: boolean): this {
|
|
97
|
+
this.hidden = hidden
|
|
98
|
+
this.manager?.onScreenVisibilityChanged(this)
|
|
99
|
+
this.notifyChange()
|
|
100
|
+
return this
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
show(): this {
|
|
104
|
+
return this.setHidden(false)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
hide(): this {
|
|
108
|
+
return this.setHidden(true)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getStatus(): ScreenStatus {
|
|
112
|
+
return this.status
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Set screen status. When success/fail and TUI is not bound, prints to stdout/stderr
|
|
117
|
+
*/
|
|
118
|
+
setStatus(status: ScreenStatus): this {
|
|
119
|
+
const wasComplete = this.status === 'success' || this.status === 'fail'
|
|
120
|
+
this.status = status
|
|
121
|
+
|
|
122
|
+
// When transitioning to complete state
|
|
123
|
+
if (!wasComplete && (status === 'success' || status === 'fail')) {
|
|
124
|
+
// Only print if TUI is NOT bound (non-interactive mode)
|
|
125
|
+
if (!this.manager?.isTuiBound()) {
|
|
126
|
+
this.printToConsole()
|
|
127
|
+
}
|
|
128
|
+
this.manager?.onScreenCompleted(this)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.notifyChange()
|
|
132
|
+
return this
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Check if this screen is complete (success or fail)
|
|
137
|
+
*/
|
|
138
|
+
isComplete(): boolean {
|
|
139
|
+
return this.status === 'success' || this.status === 'fail'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check if this screen has been printed to console
|
|
144
|
+
*/
|
|
145
|
+
hasPrintedToConsole(): boolean {
|
|
146
|
+
return this.hasPrinted
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Force print to console (called when TUI unbinds)
|
|
151
|
+
*/
|
|
152
|
+
_flushToConsole(force: boolean = false): void {
|
|
153
|
+
if (!this.hasPrinted && (this.isComplete() || force)) {
|
|
154
|
+
this.printToConsole()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get all messages for rendering
|
|
160
|
+
*/
|
|
161
|
+
getMessages(): MessageData[] {
|
|
162
|
+
return [...this.messages]
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Add a message to the screen (internal use by Logger)
|
|
167
|
+
*/
|
|
168
|
+
addMessage(message: MessageData): void {
|
|
169
|
+
this.messages.push(message)
|
|
170
|
+
this.incrementVersion()
|
|
171
|
+
this.notifyChange()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Update a loading message (internal use by Logger)
|
|
176
|
+
*/
|
|
177
|
+
updateMessage(id: string, updates: Partial<LoadingMessageData>): void {
|
|
178
|
+
const index = this.messages.findIndex((m) => m.id === id)
|
|
179
|
+
if (index !== -1) {
|
|
180
|
+
this.messages[index] = {
|
|
181
|
+
...this.messages[index],
|
|
182
|
+
...updates,
|
|
183
|
+
} as MessageData
|
|
184
|
+
this.incrementVersion()
|
|
185
|
+
this.notifyChange()
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Update a progress message (internal use by Logger)
|
|
191
|
+
*/
|
|
192
|
+
updateProgressMessage(id: string, updates: Partial<ProgressMessageData>): void {
|
|
193
|
+
const index = this.messages.findIndex((m) => m.id === id)
|
|
194
|
+
if (index !== -1) {
|
|
195
|
+
this.messages[index] = {
|
|
196
|
+
...this.messages[index],
|
|
197
|
+
...updates,
|
|
198
|
+
} as MessageData
|
|
199
|
+
this.incrementVersion()
|
|
200
|
+
this.notifyChange()
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Clear all messages
|
|
206
|
+
*/
|
|
207
|
+
clear(): this {
|
|
208
|
+
this.messages = []
|
|
209
|
+
this.incrementVersion()
|
|
210
|
+
this.notifyChange()
|
|
211
|
+
return this
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ============================================
|
|
215
|
+
// Prompt Methods
|
|
216
|
+
// ============================================
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Add a prompt to the queue (internal use by Prompt class)
|
|
220
|
+
* Returns a promise that resolves when the user responds
|
|
221
|
+
*/
|
|
222
|
+
_addPrompt(prompt: PromptData): Promise<string | boolean | string[]> {
|
|
223
|
+
return new Promise((resolve) => {
|
|
224
|
+
const pending: PendingPrompt = { data: prompt, resolve }
|
|
225
|
+
|
|
226
|
+
// If TUI is not bound (non-interactive mode), return default immediately
|
|
227
|
+
if (!this.manager?.isTuiBound()) {
|
|
228
|
+
this.resolvePromptWithDefault(prompt, resolve)
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Set up timeout if specified
|
|
233
|
+
if (prompt.timeout && prompt.timeoutStarted) {
|
|
234
|
+
pending.timeoutId = setTimeout(() => {
|
|
235
|
+
if (this.activePrompt === pending) {
|
|
236
|
+
this.resolvePromptWithDefault(prompt, resolve)
|
|
237
|
+
this.activePrompt = null
|
|
238
|
+
this.activateNextPrompt()
|
|
239
|
+
this.incrementVersion()
|
|
240
|
+
this.notifyChange()
|
|
241
|
+
} else {
|
|
242
|
+
// Remove from queue if not yet active
|
|
243
|
+
const idx = this.promptQueue.indexOf(pending)
|
|
244
|
+
if (idx !== -1) {
|
|
245
|
+
this.promptQueue.splice(idx, 1)
|
|
246
|
+
this.resolvePromptWithDefault(prompt, resolve)
|
|
247
|
+
this.incrementVersion()
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}, prompt.timeout)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Add to queue
|
|
254
|
+
this.promptQueue.push(pending)
|
|
255
|
+
|
|
256
|
+
// If no active prompt, activate this one
|
|
257
|
+
if (!this.activePrompt) {
|
|
258
|
+
this.activateNextPrompt()
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Resolve a prompt with its default value
|
|
265
|
+
*/
|
|
266
|
+
private resolvePromptWithDefault(
|
|
267
|
+
prompt: PromptData,
|
|
268
|
+
resolve: (value: string | boolean | string[]) => void,
|
|
269
|
+
): void {
|
|
270
|
+
switch (prompt.type) {
|
|
271
|
+
case 'choice':
|
|
272
|
+
resolve(prompt.defaultChoice)
|
|
273
|
+
break
|
|
274
|
+
case 'confirm':
|
|
275
|
+
resolve(prompt.defaultValue)
|
|
276
|
+
break
|
|
277
|
+
case 'input':
|
|
278
|
+
resolve(prompt.defaultValue)
|
|
279
|
+
break
|
|
280
|
+
case 'multiChoice':
|
|
281
|
+
resolve(prompt.choices.filter((_, i) => prompt.selectedIndices.has(i)).map((c) => c.value))
|
|
282
|
+
break
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get the currently active prompt (for rendering)
|
|
288
|
+
*/
|
|
289
|
+
getActivePrompt(): PromptData | null {
|
|
290
|
+
return this.activePrompt?.data ?? null
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Check if this screen has an active prompt
|
|
295
|
+
*/
|
|
296
|
+
hasActivePrompt(): boolean {
|
|
297
|
+
return this.activePrompt !== null
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Update prompt selection (for keyboard navigation)
|
|
302
|
+
*/
|
|
303
|
+
updatePromptSelection(index: number): void {
|
|
304
|
+
if (!this.activePrompt) return
|
|
305
|
+
|
|
306
|
+
const prompt = this.activePrompt.data
|
|
307
|
+
if (prompt.type === 'choice') {
|
|
308
|
+
const maxIndex = prompt.choices.length - 1
|
|
309
|
+
;(prompt as ChoicePromptData).selectedIndex = Math.max(0, Math.min(index, maxIndex))
|
|
310
|
+
} else if (prompt.type === 'multiChoice') {
|
|
311
|
+
const maxIndex = prompt.choices.length - 1
|
|
312
|
+
;(prompt as MultiChoicePromptData).focusedIndex = Math.max(0, Math.min(index, maxIndex))
|
|
313
|
+
} else if (prompt.type === 'confirm') {
|
|
314
|
+
;(prompt as ConfirmPromptData).selectedValue = index === 0
|
|
315
|
+
}
|
|
316
|
+
this.notifyChange()
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Navigate prompt selection up
|
|
321
|
+
*/
|
|
322
|
+
promptNavigateUp(): void {
|
|
323
|
+
if (!this.activePrompt) return
|
|
324
|
+
|
|
325
|
+
const prompt = this.activePrompt.data
|
|
326
|
+
if (prompt.type === 'choice') {
|
|
327
|
+
this.updatePromptSelection(prompt.selectedIndex - 1)
|
|
328
|
+
} else if (prompt.type === 'multiChoice') {
|
|
329
|
+
this.updatePromptSelection(prompt.focusedIndex - 1)
|
|
330
|
+
} else if (prompt.type === 'confirm') {
|
|
331
|
+
this.updatePromptSelection(prompt.selectedValue ? 0 : 1)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Navigate prompt selection down
|
|
337
|
+
*/
|
|
338
|
+
promptNavigateDown(): void {
|
|
339
|
+
if (!this.activePrompt) return
|
|
340
|
+
|
|
341
|
+
const prompt = this.activePrompt.data
|
|
342
|
+
if (prompt.type === 'choice') {
|
|
343
|
+
this.updatePromptSelection(prompt.selectedIndex + 1)
|
|
344
|
+
} else if (prompt.type === 'multiChoice') {
|
|
345
|
+
this.updatePromptSelection(prompt.focusedIndex + 1)
|
|
346
|
+
} else if (prompt.type === 'confirm') {
|
|
347
|
+
this.updatePromptSelection(prompt.selectedValue ? 0 : 1)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Toggle left/right for confirm prompts
|
|
353
|
+
*/
|
|
354
|
+
promptNavigateLeft(): void {
|
|
355
|
+
if (!this.activePrompt) return
|
|
356
|
+
const prompt = this.activePrompt.data
|
|
357
|
+
if (prompt.type === 'confirm') {
|
|
358
|
+
;(prompt as ConfirmPromptData).selectedValue = true
|
|
359
|
+
this.notifyChange()
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
promptNavigateRight(): void {
|
|
364
|
+
if (!this.activePrompt) return
|
|
365
|
+
const prompt = this.activePrompt.data
|
|
366
|
+
if (prompt.type === 'confirm') {
|
|
367
|
+
;(prompt as ConfirmPromptData).selectedValue = false
|
|
368
|
+
this.notifyChange()
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Toggle selection for multiChoice prompts
|
|
374
|
+
*/
|
|
375
|
+
promptToggleSelection(): void {
|
|
376
|
+
if (!this.activePrompt) return
|
|
377
|
+
const prompt = this.activePrompt.data
|
|
378
|
+
if (prompt.type === 'multiChoice') {
|
|
379
|
+
const p = prompt as MultiChoicePromptData
|
|
380
|
+
if (p.selectedIndices.has(p.focusedIndex)) {
|
|
381
|
+
p.selectedIndices.delete(p.focusedIndex)
|
|
382
|
+
} else if (p.selectedIndices.size < p.maxSelect) {
|
|
383
|
+
p.selectedIndices.add(p.focusedIndex)
|
|
384
|
+
}
|
|
385
|
+
this.notifyChange()
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Enter input mode for choice prompts (if current selection allows input)
|
|
391
|
+
* or for input prompts (always)
|
|
392
|
+
*/
|
|
393
|
+
promptEnterInputMode(): boolean {
|
|
394
|
+
if (!this.activePrompt) return false
|
|
395
|
+
|
|
396
|
+
const prompt = this.activePrompt.data
|
|
397
|
+
if (prompt.type === 'choice') {
|
|
398
|
+
const choice = prompt.choices[prompt.selectedIndex]
|
|
399
|
+
if (choice?.input) {
|
|
400
|
+
;(prompt as ChoicePromptData).inputMode = true
|
|
401
|
+
this.notifyChange()
|
|
402
|
+
return true
|
|
403
|
+
}
|
|
404
|
+
} else if (prompt.type === 'input') {
|
|
405
|
+
// Input prompts are always in input mode
|
|
406
|
+
return true
|
|
407
|
+
}
|
|
408
|
+
return false
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Exit input mode for choice prompts
|
|
413
|
+
*/
|
|
414
|
+
promptExitInputMode(): void {
|
|
415
|
+
if (!this.activePrompt) return
|
|
416
|
+
|
|
417
|
+
const prompt = this.activePrompt.data
|
|
418
|
+
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
419
|
+
;(prompt as ChoicePromptData).inputMode = false
|
|
420
|
+
this.notifyChange()
|
|
421
|
+
}
|
|
422
|
+
// Input prompts cannot exit input mode
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Check if prompt is in input mode
|
|
427
|
+
*/
|
|
428
|
+
isPromptInInputMode(): boolean {
|
|
429
|
+
if (!this.activePrompt) return false
|
|
430
|
+
const prompt = this.activePrompt.data
|
|
431
|
+
if (prompt.type === 'choice') {
|
|
432
|
+
return prompt.inputMode
|
|
433
|
+
}
|
|
434
|
+
if (prompt.type === 'input') {
|
|
435
|
+
return true // Input prompts are always in input mode
|
|
436
|
+
}
|
|
437
|
+
return false
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Update input value for choice prompts
|
|
442
|
+
*/
|
|
443
|
+
promptUpdateInput(value: string): void {
|
|
444
|
+
if (!this.activePrompt) return
|
|
445
|
+
|
|
446
|
+
const prompt = this.activePrompt.data
|
|
447
|
+
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
448
|
+
;(prompt as ChoicePromptData).inputValue = value
|
|
449
|
+
this.notifyChange()
|
|
450
|
+
} else if (prompt.type === 'input') {
|
|
451
|
+
;(prompt as InputPromptData).value = value
|
|
452
|
+
this.notifyChange()
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Append character to input
|
|
458
|
+
*/
|
|
459
|
+
promptAppendInput(char: string): void {
|
|
460
|
+
if (!this.activePrompt) return
|
|
461
|
+
|
|
462
|
+
const prompt = this.activePrompt.data
|
|
463
|
+
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
464
|
+
;(prompt as ChoicePromptData).inputValue += char
|
|
465
|
+
this.notifyChange()
|
|
466
|
+
} else if (prompt.type === 'input') {
|
|
467
|
+
;(prompt as InputPromptData).value += char
|
|
468
|
+
this.notifyChange()
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Delete last character from input
|
|
474
|
+
*/
|
|
475
|
+
promptDeleteLastChar(): void {
|
|
476
|
+
if (!this.activePrompt) return
|
|
477
|
+
|
|
478
|
+
const prompt = this.activePrompt.data
|
|
479
|
+
if (prompt.type === 'choice' && prompt.inputMode) {
|
|
480
|
+
;(prompt as ChoicePromptData).inputValue = prompt.inputValue.slice(0, -1)
|
|
481
|
+
this.notifyChange()
|
|
482
|
+
} else if (prompt.type === 'input') {
|
|
483
|
+
;(prompt as InputPromptData).value = prompt.value.slice(0, -1)
|
|
484
|
+
this.notifyChange()
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Check if multiChoice prompt can be submitted (meets minSelect requirement)
|
|
490
|
+
*/
|
|
491
|
+
canSubmitPrompt(): boolean {
|
|
492
|
+
if (!this.activePrompt) return false
|
|
493
|
+
const prompt = this.activePrompt.data
|
|
494
|
+
if (prompt.type === 'multiChoice') {
|
|
495
|
+
return prompt.selectedIndices.size >= prompt.minSelect
|
|
496
|
+
}
|
|
497
|
+
return true
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Submit the current prompt selection
|
|
502
|
+
*/
|
|
503
|
+
promptSubmit(): void {
|
|
504
|
+
if (!this.activePrompt) return
|
|
505
|
+
|
|
506
|
+
const prompt = this.activePrompt.data
|
|
507
|
+
|
|
508
|
+
// Check if can submit (for multiChoice min selection)
|
|
509
|
+
if (!this.canSubmitPrompt()) return
|
|
510
|
+
|
|
511
|
+
prompt.resolved = true
|
|
512
|
+
|
|
513
|
+
// Clear timeout if any
|
|
514
|
+
if (this.activePrompt.timeoutId) {
|
|
515
|
+
clearTimeout(this.activePrompt.timeoutId)
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
switch (prompt.type) {
|
|
519
|
+
case 'choice': {
|
|
520
|
+
const choice = prompt.choices[prompt.selectedIndex]
|
|
521
|
+
const value = choice?.input && prompt.inputValue ? prompt.inputValue : (choice?.value ?? '')
|
|
522
|
+
;(prompt as ChoicePromptData).resolvedValue = value
|
|
523
|
+
this.activePrompt.resolve(value)
|
|
524
|
+
break
|
|
525
|
+
}
|
|
526
|
+
case 'confirm': {
|
|
527
|
+
;(prompt as ConfirmPromptData).resolvedValue = prompt.selectedValue
|
|
528
|
+
this.activePrompt.resolve(prompt.selectedValue)
|
|
529
|
+
break
|
|
530
|
+
}
|
|
531
|
+
case 'input': {
|
|
532
|
+
;(prompt as InputPromptData).resolvedValue = prompt.value
|
|
533
|
+
this.activePrompt.resolve(prompt.value)
|
|
534
|
+
break
|
|
535
|
+
}
|
|
536
|
+
case 'multiChoice': {
|
|
537
|
+
const values = prompt.choices
|
|
538
|
+
.filter((_, i) => prompt.selectedIndices.has(i))
|
|
539
|
+
.map((c) => c.value)
|
|
540
|
+
;(prompt as MultiChoicePromptData).resolvedValues = values
|
|
541
|
+
this.activePrompt.resolve(values)
|
|
542
|
+
break
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Move to next prompt
|
|
547
|
+
this.activePrompt = null
|
|
548
|
+
this.activateNextPrompt()
|
|
549
|
+
this.incrementVersion()
|
|
550
|
+
this.notifyChange()
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Activate the next prompt in the queue
|
|
555
|
+
*/
|
|
556
|
+
private activateNextPrompt(): void {
|
|
557
|
+
if (this.promptQueue.length > 0) {
|
|
558
|
+
this.activePrompt = this.promptQueue.shift()!
|
|
559
|
+
// Notify manager to focus this screen
|
|
560
|
+
this.manager?.onScreenPromptActivated(this)
|
|
561
|
+
this.incrementVersion()
|
|
562
|
+
this.notifyChange()
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Register a change listener for re-renders
|
|
568
|
+
*/
|
|
569
|
+
onChange(listener: () => void): () => void {
|
|
570
|
+
this.changeListeners.add(listener)
|
|
571
|
+
return () => this.changeListeners.delete(listener)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
private notifyChange(): void {
|
|
575
|
+
this.changeListeners.forEach((listener) => listener())
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Print all messages to stdout/stderr with ANSI colors
|
|
580
|
+
*/
|
|
581
|
+
private printToConsole(): void {
|
|
582
|
+
if (this.hasPrinted) return
|
|
583
|
+
|
|
584
|
+
const isError = this.status === 'fail'
|
|
585
|
+
if (this.printFn) {
|
|
586
|
+
this.printFn(this.messages, this.name, isError)
|
|
587
|
+
this.hasPrinted = true
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|