@navios/commander-tui 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/{src/__tests__/mocks/scm-mock.ts → dist/base/src/__tests__/mocks/scm-mock.d.ts} +3 -1
- package/dist/base/src/__tests__/mocks/scm-mock.d.ts.map +1 -0
- package/dist/base/src/__tests__/setup.d.ts +2 -0
- package/dist/base/src/__tests__/setup.d.ts.map +1 -0
- package/dist/base/src/__tests__/utils/factories.d.ts +67 -0
- package/dist/base/src/__tests__/utils/factories.d.ts.map +1 -0
- package/dist/base/src/__tests__/utils/render-utils.d.ts +21 -0
- package/dist/base/src/__tests__/utils/render-utils.d.ts.map +1 -0
- package/dist/base/src/__tests__/utils/test-container.d.ts +20 -0
- package/dist/base/src/__tests__/utils/test-container.d.ts.map +1 -0
- package/dist/base/src/adapters/interface.d.ts +9 -2
- package/dist/base/src/adapters/interface.d.ts.map +1 -1
- package/dist/base/src/overrides/missing-adapter.override.d.ts +10 -0
- package/dist/base/src/overrides/missing-adapter.override.d.ts.map +1 -1
- package/dist/base/src/services/index.d.ts +1 -0
- package/dist/base/src/services/index.d.ts.map +1 -1
- package/dist/base/src/services/logger.d.ts.map +1 -1
- package/dist/base/src/services/readline_prompt.d.ts +27 -0
- package/dist/base/src/services/readline_prompt.d.ts.map +1 -0
- package/dist/base/src/services/screen.d.ts +14 -8
- package/dist/base/src/services/screen.d.ts.map +1 -1
- package/dist/base/src/services/screen_manager.d.ts +62 -12
- package/dist/base/src/services/screen_manager.d.ts.map +1 -1
- package/dist/base/src/tokens/logger.d.ts +2 -2
- package/dist/base/src/types/events.types.d.ts +40 -0
- package/dist/base/src/types/events.types.d.ts.map +1 -0
- package/dist/base/src/types/index.d.ts +1 -0
- package/dist/base/src/types/index.d.ts.map +1 -1
- package/dist/base/src/types/screen.types.d.ts +28 -0
- package/dist/base/src/types/screen.types.d.ts.map +1 -1
- package/dist/base/src/utils/colors/helpers.d.ts +0 -16
- package/dist/base/src/utils/colors/helpers.d.ts.map +1 -1
- package/dist/base/src/utils/index.d.ts +2 -0
- package/dist/base/src/utils/index.d.ts.map +1 -1
- package/dist/base/src/utils/prompt.d.ts +7 -0
- package/dist/base/src/utils/prompt.d.ts.map +1 -0
- package/dist/base/src/utils/runtime.d.ts +10 -0
- package/dist/base/src/utils/runtime.d.ts.map +1 -0
- package/dist/base/src/utils/stdout-printer.d.ts +5 -0
- package/dist/base/src/utils/stdout-printer.d.ts.map +1 -1
- package/dist/base/tsconfig.base.tsbuildinfo +1 -1
- package/dist/base/tsconfig.tsbuildinfo +1 -0
- package/dist/ink/src/adapters/ink/components/file/file_log.d.ts +28 -0
- package/dist/ink/src/adapters/ink/components/file/file_log.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/file/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/file/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/filter/filter_bar.d.ts +7 -0
- package/dist/ink/src/adapters/ink/components/filter/filter_bar.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/filter/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/filter/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/help/help_overlay.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/help/help_overlay.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/help/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/help/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/index.d.ts +9 -0
- package/dist/ink/src/adapters/ink/components/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/log/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/log/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/log/log_message.d.ts +15 -0
- package/dist/ink/src/adapters/ink/components/log/log_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/prompt/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/prompt/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/prompt/prompt_renderer.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/prompt/prompt_renderer.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/group_renderer.d.ts +14 -0
- package/dist/ink/src/adapters/ink/components/screen/group_renderer.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/index.d.ts +7 -0
- package/dist/ink/src/adapters/ink/components/screen/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/loading_message.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/loading_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/message_renderer.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/message_renderer.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/progress_message.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/progress_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/screen_bridge.d.ts +14 -0
- package/dist/ink/src/adapters/ink/components/screen/screen_bridge.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/table_message.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/table_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen_manager_bridge.d.ts +8 -0
- package/dist/ink/src/adapters/ink/components/screen_manager_bridge.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/index.d.ts +4 -0
- package/dist/ink/src/adapters/ink/components/sidebar/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar.d.ts +11 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_item.d.ts +9 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_item.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_separator.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_separator.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/context/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/context/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/context/logger_context.d.ts +33 -0
- package/dist/ink/src/adapters/ink/context/logger_context.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/hooks/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/hooks/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/hooks/use_theme.d.ts +7 -0
- package/dist/ink/src/adapters/ink/hooks/use_theme.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/index.d.ts +18 -0
- package/dist/ink/src/adapters/ink/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/index.d.ts +4 -0
- package/dist/ink/src/adapters/react-shared/hooks/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_filter_state.d.ts +18 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_filter_state.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts +26 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_manager_subscription.d.ts +7 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_manager_subscription.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/index.d.ts +2 -0
- package/dist/ink/src/adapters/react-shared/index.d.ts.map +1 -0
- package/dist/ink/tsconfig.ink.tsbuildinfo +1 -0
- package/dist/react/src/adapters/react-shared/hooks/index.d.ts +4 -0
- package/dist/react/src/adapters/react-shared/hooks/index.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/hooks/use_filter_state.d.ts +18 -0
- package/dist/react/src/adapters/react-shared/hooks/use_filter_state.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts +26 -0
- package/dist/react/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/hooks/use_manager_subscription.d.ts +7 -0
- package/dist/react/src/adapters/react-shared/hooks/use_manager_subscription.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/index.d.ts +2 -0
- package/dist/react/src/adapters/react-shared/index.d.ts.map +1 -0
- package/dist/react/tsconfig.react.tsbuildinfo +1 -1
- package/dist/solid/tsconfig.solid.tsbuildinfo +1 -1
- package/lib/index.cjs +2180 -181
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +3199 -277
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +3199 -277
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +2101 -138
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -31
- package/src/__tests__/services/logger.spec.ts +32 -0
- package/src/__tests__/services/screen.spec.ts +114 -101
- package/src/__tests__/utils/factories.ts +2 -0
- package/src/adapters/interface.ts +10 -2
- package/src/overrides/missing-adapter.override.ts +16 -6
- package/src/services/index.ts +1 -0
- package/src/services/logger.ts +7 -1
- package/src/services/readline_prompt.ts +194 -0
- package/src/services/screen.ts +108 -57
- package/src/services/screen_manager.ts +287 -74
- package/src/types/events.types.ts +84 -0
- package/src/types/index.ts +3 -0
- package/src/types/screen.types.ts +34 -0
- package/src/utils/colors/helpers.ts +0 -25
- package/src/utils/index.ts +6 -0
- package/src/utils/prompt.ts +18 -0
- package/src/utils/runtime.ts +14 -0
- package/src/utils/stdout-printer.ts +16 -5
- package/tsconfig.base.json +1 -17
- package/tsconfig.json +1 -6
- package/tsdown.config.mts +13 -70
- package/lib/adapters/react/index.cjs +0 -1768
- package/lib/adapters/react/index.cjs.map +0 -1
- package/lib/adapters/react/index.d.cts +0 -80
- package/lib/adapters/react/index.d.mts +0 -80
- package/lib/adapters/react/index.mjs +0 -1760
- package/lib/adapters/react/index.mjs.map +0 -1
- package/lib/adapters/solid/index.cjs +0 -3855
- package/lib/adapters/solid/index.cjs.map +0 -1
- package/lib/adapters/solid/index.d.cts +0 -74
- package/lib/adapters/solid/index.d.mts +0 -74
- package/lib/adapters/solid/index.mjs +0 -3847
- package/lib/adapters/solid/index.mjs.map +0 -1
- package/lib/filter_engine-DXqu9Vaq.cjs +0 -1836
- package/lib/filter_engine-DXqu9Vaq.cjs.map +0 -1
- package/lib/filter_engine-DmqhEhpA.mjs +0 -1609
- package/lib/filter_engine-DmqhEhpA.mjs.map +0 -1
- package/lib/interface-CTHQ08aY.d.mts +0 -699
- package/lib/interface-DQEIz9Mb.d.cts +0 -699
- package/src/__tests__/components/__snapshots__/filter_bar.spec.tsx.snap +0 -2293
- package/src/__tests__/components/__snapshots__/loading_message.spec.tsx.snap +0 -1414
- package/src/__tests__/components/__snapshots__/log_message.spec.tsx.snap +0 -3245
- package/src/__tests__/components/__snapshots__/progress_message.spec.tsx.snap +0 -1783
- package/src/__tests__/components/__snapshots__/prompt_renderer.spec.tsx.snap +0 -3203
- package/src/__tests__/components/__snapshots__/sidebar.spec.tsx.snap +0 -2857
- package/src/__tests__/components/filter_bar.spec.tsx +0 -190
- package/src/__tests__/components/loading_message.spec.tsx +0 -110
- package/src/__tests__/components/log_message.spec.tsx +0 -166
- package/src/__tests__/components/progress_message.spec.tsx +0 -147
- package/src/__tests__/components/prompt_renderer.spec.tsx +0 -274
- package/src/__tests__/components/sidebar.spec.tsx +0 -322
- package/src/__tests__/utils/render-utils.tsx +0 -39
- package/src/adapters/react/components/file/file_log.tsx +0 -241
- package/src/adapters/react/components/file/index.ts +0 -1
- package/src/adapters/react/components/filter/filter_bar.tsx +0 -79
- package/src/adapters/react/components/filter/index.ts +0 -1
- package/src/adapters/react/components/help/help_overlay.tsx +0 -100
- package/src/adapters/react/components/help/index.ts +0 -1
- package/src/adapters/react/components/log/index.ts +0 -1
- package/src/adapters/react/components/log/log_message.tsx +0 -102
- package/src/adapters/react/components/prompt/index.ts +0 -2
- package/src/adapters/react/components/prompt/prompt_renderer.tsx +0 -346
- package/src/adapters/react/components/screen/group_renderer.tsx +0 -64
- package/src/adapters/react/components/screen/index.ts +0 -6
- package/src/adapters/react/components/screen/loading_message.tsx +0 -43
- package/src/adapters/react/components/screen/message_renderer.tsx +0 -108
- package/src/adapters/react/components/screen/progress_message.tsx +0 -60
- package/src/adapters/react/components/screen/screen_bridge.tsx +0 -149
- package/src/adapters/react/components/screen/table_message.tsx +0 -57
- package/src/adapters/react/components/screen_manager_bridge.tsx +0 -245
- package/src/adapters/react/components/sidebar/index.ts +0 -3
- package/src/adapters/react/components/sidebar/sidebar.tsx +0 -102
- package/src/adapters/react/components/sidebar/sidebar_item.tsx +0 -50
- package/src/adapters/react/components/sidebar/sidebar_separator.tsx +0 -13
- package/src/adapters/react/context/index.ts +0 -1
- package/src/adapters/react/context/logger_context.tsx +0 -109
- package/src/adapters/react/hooks/index.ts +0 -1
- package/src/adapters/react/hooks/use_theme.ts +0 -12
- package/src/adapters/react/index.ts +0 -39
- package/src/adapters/solid/components/file/file_log.tsx +0 -221
- package/src/adapters/solid/components/file/index.ts +0 -1
- package/src/adapters/solid/components/filter/filter_bar.tsx +0 -84
- package/src/adapters/solid/components/filter/index.ts +0 -1
- package/src/adapters/solid/components/help/help_overlay.tsx +0 -106
- package/src/adapters/solid/components/help/index.ts +0 -1
- package/src/adapters/solid/components/log/index.ts +0 -1
- package/src/adapters/solid/components/log/log_message.tsx +0 -92
- package/src/adapters/solid/components/prompt/index.ts +0 -2
- package/src/adapters/solid/components/prompt/prompt_renderer.tsx +0 -350
- package/src/adapters/solid/components/screen/group_renderer.tsx +0 -61
- package/src/adapters/solid/components/screen/index.ts +0 -6
- package/src/adapters/solid/components/screen/loading_message.tsx +0 -39
- package/src/adapters/solid/components/screen/message_renderer.tsx +0 -122
- package/src/adapters/solid/components/screen/progress_message.tsx +0 -61
- package/src/adapters/solid/components/screen/screen_bridge.tsx +0 -155
- package/src/adapters/solid/components/screen/table_message.tsx +0 -58
- package/src/adapters/solid/components/screen_manager_bridge.tsx +0 -243
- package/src/adapters/solid/components/sidebar/index.ts +0 -3
- package/src/adapters/solid/components/sidebar/sidebar.tsx +0 -108
- package/src/adapters/solid/components/sidebar/sidebar_item.tsx +0 -55
- package/src/adapters/solid/components/sidebar/sidebar_separator.tsx +0 -13
- package/src/adapters/solid/context/index.ts +0 -2
- package/src/adapters/solid/context/logger_context.tsx +0 -95
- package/src/adapters/solid/hooks/index.ts +0 -1
- package/src/adapters/solid/hooks/use_theme.ts +0 -12
- package/src/adapters/solid/index.tsx +0 -43
- package/src/adapters/solid/jsx.d.ts +0 -98
- package/tsconfig.react.json +0 -16
- package/tsconfig.solid.json +0 -16
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { SyntaxStyle, type TreeSitterClient } from '@opentui/core'
|
|
2
|
-
import { createContext, useContext, useMemo, type ReactNode } from 'react'
|
|
3
|
-
|
|
4
|
-
import { darkTheme, resolveTheme } from '../../../themes/index.ts'
|
|
5
|
-
|
|
6
|
-
import type { LoggerContextValue, LogLevelColorMap, Theme, ThemePreset } from '../../../types/index.ts'
|
|
7
|
-
|
|
8
|
-
const LoggerContext = createContext<LoggerContextValue | null>(null)
|
|
9
|
-
|
|
10
|
-
export interface LoggerProviderProps {
|
|
11
|
-
children: ReactNode
|
|
12
|
-
|
|
13
|
-
/** Custom syntax style for code highlighting */
|
|
14
|
-
syntaxStyle?: SyntaxStyle
|
|
15
|
-
|
|
16
|
-
/** Tree-sitter client for parsing */
|
|
17
|
-
treeSitterClient?: TreeSitterClient
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Theme configuration.
|
|
21
|
-
* Can be a preset name ("dark", "light", "high-contrast") or a Theme object.
|
|
22
|
-
* @default "dark"
|
|
23
|
-
*/
|
|
24
|
-
theme?: Theme | ThemePreset
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @deprecated Use `theme` instead. Custom log level colors.
|
|
28
|
-
* If both `theme` and `levelColors` are provided, `levelColors` takes precedence.
|
|
29
|
-
*/
|
|
30
|
-
levelColors?: Partial<LogLevelColorMap>
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* LoggerProvider - Provides shared context for logger components.
|
|
35
|
-
*
|
|
36
|
-
* This context provides:
|
|
37
|
-
* - Shared SyntaxStyle instance for consistent code highlighting
|
|
38
|
-
* - Optional TreeSitterClient for advanced parsing
|
|
39
|
-
* - Theme configuration for consistent styling
|
|
40
|
-
* - Log level color configuration (for backwards compatibility)
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* // Using a preset theme
|
|
44
|
-
* <LoggerProvider theme="dark">
|
|
45
|
-
* <ScreenManager screens={screens} activeScreenId={activeId}>
|
|
46
|
-
* <Screen name="Logs">
|
|
47
|
-
* <LogMessage level="info">Hello</LogMessage>
|
|
48
|
-
* </Screen>
|
|
49
|
-
* </ScreenManager>
|
|
50
|
-
* </LoggerProvider>
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* // Using a custom theme
|
|
54
|
-
* <LoggerProvider theme={myCustomTheme}>
|
|
55
|
-
* ...
|
|
56
|
-
* </LoggerProvider>
|
|
57
|
-
*/
|
|
58
|
-
export function LoggerProvider({
|
|
59
|
-
children,
|
|
60
|
-
syntaxStyle: customSyntaxStyle,
|
|
61
|
-
treeSitterClient,
|
|
62
|
-
theme: themeProp = 'dark',
|
|
63
|
-
levelColors: customLevelColors,
|
|
64
|
-
}: LoggerProviderProps) {
|
|
65
|
-
// Create or use provided SyntaxStyle
|
|
66
|
-
const syntaxStyle = useMemo(() => customSyntaxStyle ?? SyntaxStyle.create(), [customSyntaxStyle])
|
|
67
|
-
|
|
68
|
-
// Resolve theme (could be a preset name or a theme object)
|
|
69
|
-
const theme = useMemo(() => resolveTheme(themeProp), [themeProp])
|
|
70
|
-
|
|
71
|
-
// Derive levelColors from theme, allowing custom overrides for backwards compatibility
|
|
72
|
-
const levelColors = useMemo(
|
|
73
|
-
() => ({
|
|
74
|
-
...theme.logLevels,
|
|
75
|
-
...customLevelColors,
|
|
76
|
-
}),
|
|
77
|
-
[theme.logLevels, customLevelColors],
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
const value: LoggerContextValue = useMemo(
|
|
81
|
-
() => ({
|
|
82
|
-
syntaxStyle,
|
|
83
|
-
treeSitterClient,
|
|
84
|
-
levelColors,
|
|
85
|
-
theme,
|
|
86
|
-
}),
|
|
87
|
-
[syntaxStyle, treeSitterClient, levelColors, theme],
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
return <LoggerContext.Provider value={value}>{children}</LoggerContext.Provider>
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Hook to access logger context.
|
|
95
|
-
* Returns default values if used outside LoggerProvider.
|
|
96
|
-
*/
|
|
97
|
-
export function useLoggerContext(): LoggerContextValue {
|
|
98
|
-
const context = useContext(LoggerContext)
|
|
99
|
-
if (!context) {
|
|
100
|
-
// Return defaults if not in a provider (allows standalone usage)
|
|
101
|
-
return {
|
|
102
|
-
syntaxStyle: undefined,
|
|
103
|
-
treeSitterClient: undefined,
|
|
104
|
-
levelColors: darkTheme.logLevels,
|
|
105
|
-
theme: darkTheme,
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return context
|
|
109
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './use_theme.ts'
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { useLoggerContext } from '../context/index.ts'
|
|
2
|
-
|
|
3
|
-
import type { Theme } from '../../../types/index.ts'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hook to access the current theme.
|
|
7
|
-
* Returns the theme from LoggerContext.
|
|
8
|
-
*/
|
|
9
|
-
export function useTheme(): Theme {
|
|
10
|
-
const { theme } = useLoggerContext()
|
|
11
|
-
return theme
|
|
12
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@navios/core'
|
|
2
|
-
import { createRoot as reactCreateRoot } from '@opentui/react'
|
|
3
|
-
import { createElement } from 'react'
|
|
4
|
-
|
|
5
|
-
import type { CliRenderer } from '@opentui/core'
|
|
6
|
-
|
|
7
|
-
import { Adapter } from '../../tokens/adapter.ts'
|
|
8
|
-
|
|
9
|
-
import type { AdapterInterface, AdapterRoot, AdapterRenderProps } from '../interface.ts'
|
|
10
|
-
|
|
11
|
-
import { ScreenManagerBridge } from './components/screen_manager_bridge.tsx'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* React adapter for TUI rendering.
|
|
15
|
-
* Automatically registers to DI when this module is imported.
|
|
16
|
-
*/
|
|
17
|
-
@Injectable({ token: Adapter })
|
|
18
|
-
export class ReactAdapter implements AdapterInterface {
|
|
19
|
-
createRoot(renderer: CliRenderer): AdapterRoot {
|
|
20
|
-
const root = reactCreateRoot(renderer)
|
|
21
|
-
return {
|
|
22
|
-
render(element: unknown): void {
|
|
23
|
-
root.render(element as React.ReactNode)
|
|
24
|
-
},
|
|
25
|
-
unmount(): void {
|
|
26
|
-
root.unmount()
|
|
27
|
-
},
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
renderToRoot(root: AdapterRoot, props: AdapterRenderProps): void {
|
|
32
|
-
const element = createElement(ScreenManagerBridge, props as any)
|
|
33
|
-
root.render(element)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Re-export context and hooks for external use
|
|
38
|
-
export * from './context/index.ts'
|
|
39
|
-
export * from './hooks/index.ts'
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import { Show, For, createMemo } from 'solid-js'
|
|
2
|
-
|
|
3
|
-
import { useLoggerContext } from '../../context/index.ts'
|
|
4
|
-
import { ERROR_HIGHLIGHT_COLORS, HEADER_COLORS, resolveFiletype } from '../../../../utils/index.ts'
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
FileLogProps,
|
|
8
|
-
FileLogFullProps,
|
|
9
|
-
FileLogDiffProps,
|
|
10
|
-
FileLogPartialProps,
|
|
11
|
-
} from '../../../../types/index.ts'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* FileLog - Displays file content, diffs, or partial files with error highlighting.
|
|
15
|
-
*
|
|
16
|
-
* Three modes:
|
|
17
|
-
* 1. "full" - Display complete file with syntax highlighting
|
|
18
|
-
* 2. "diff" - Display unified diff using <diff> component
|
|
19
|
-
* 3. "partial" - Display file excerpt with optional error line highlighting
|
|
20
|
-
*
|
|
21
|
-
* @example Full file
|
|
22
|
-
* <FileLog
|
|
23
|
-
* mode="full"
|
|
24
|
-
* filePath="src/index.ts"
|
|
25
|
-
* content={fileContent}
|
|
26
|
-
* />
|
|
27
|
-
*
|
|
28
|
-
* @example Diff
|
|
29
|
-
* <FileLog
|
|
30
|
-
* mode="diff"
|
|
31
|
-
* filePath="src/api.ts"
|
|
32
|
-
* diff={unifiedDiff}
|
|
33
|
-
* view="unified"
|
|
34
|
-
* />
|
|
35
|
-
*
|
|
36
|
-
* @example Partial with error
|
|
37
|
-
* <FileLog
|
|
38
|
-
* mode="partial"
|
|
39
|
-
* filePath="src/utils.ts"
|
|
40
|
-
* content={excerpt}
|
|
41
|
-
* startLine={42}
|
|
42
|
-
* errorLines={[45, 46]}
|
|
43
|
-
* />
|
|
44
|
-
*/
|
|
45
|
-
export function FileLog(props: FileLogProps) {
|
|
46
|
-
const { syntaxStyle, treeSitterClient } = useLoggerContext()
|
|
47
|
-
|
|
48
|
-
// Auto-detect filetype from path
|
|
49
|
-
const filetype = () => props.filetype ?? resolveFiletype(props.filePath)
|
|
50
|
-
const showHeader = () => props.showHeader ?? true
|
|
51
|
-
const showLineNumbers = () => props.showLineNumbers ?? true
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<box flexDirection="column" marginBottom={1}>
|
|
55
|
-
{/* File header */}
|
|
56
|
-
<Show when={showHeader()}>
|
|
57
|
-
<box
|
|
58
|
-
backgroundColor={props.headerBackgroundColor ?? HEADER_COLORS.background}
|
|
59
|
-
paddingLeft={1}
|
|
60
|
-
paddingRight={1}
|
|
61
|
-
border={['bottom']}
|
|
62
|
-
borderColor={HEADER_COLORS.border}
|
|
63
|
-
>
|
|
64
|
-
<text fg={HEADER_COLORS.text}>{props.filePath}</text>
|
|
65
|
-
</box>
|
|
66
|
-
</Show>
|
|
67
|
-
|
|
68
|
-
{/* Content based on mode */}
|
|
69
|
-
<Show when={props.mode === 'full'}>
|
|
70
|
-
<FileLogFull
|
|
71
|
-
{...(props as FileLogFullProps)}
|
|
72
|
-
filetype={filetype()}
|
|
73
|
-
syntaxStyle={syntaxStyle}
|
|
74
|
-
treeSitterClient={treeSitterClient}
|
|
75
|
-
showLineNumbers={showLineNumbers()}
|
|
76
|
-
/>
|
|
77
|
-
</Show>
|
|
78
|
-
|
|
79
|
-
<Show when={props.mode === 'diff'}>
|
|
80
|
-
<FileLogDiff
|
|
81
|
-
{...(props as FileLogDiffProps)}
|
|
82
|
-
filetype={filetype()}
|
|
83
|
-
syntaxStyle={syntaxStyle}
|
|
84
|
-
treeSitterClient={treeSitterClient}
|
|
85
|
-
/>
|
|
86
|
-
</Show>
|
|
87
|
-
|
|
88
|
-
<Show when={props.mode === 'partial'}>
|
|
89
|
-
<FileLogPartial
|
|
90
|
-
{...(props as FileLogPartialProps)}
|
|
91
|
-
filetype={filetype()}
|
|
92
|
-
syntaxStyle={syntaxStyle}
|
|
93
|
-
treeSitterClient={treeSitterClient}
|
|
94
|
-
showLineNumbers={showLineNumbers()}
|
|
95
|
-
/>
|
|
96
|
-
</Show>
|
|
97
|
-
</box>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
interface FileLogInternalProps {
|
|
102
|
-
filetype?: string
|
|
103
|
-
syntaxStyle?: ReturnType<typeof useLoggerContext>['syntaxStyle']
|
|
104
|
-
treeSitterClient?: ReturnType<typeof useLoggerContext>['treeSitterClient']
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Full file display with syntax highlighting.
|
|
109
|
-
*/
|
|
110
|
-
function FileLogFull(props: FileLogFullProps & FileLogInternalProps) {
|
|
111
|
-
return (
|
|
112
|
-
<Show
|
|
113
|
-
when={props.syntaxStyle}
|
|
114
|
-
fallback={
|
|
115
|
-
<box paddingLeft={1} paddingRight={1}>
|
|
116
|
-
<text>{props.content}</text>
|
|
117
|
-
</box>
|
|
118
|
-
}
|
|
119
|
-
>
|
|
120
|
-
<code
|
|
121
|
-
content={props.content}
|
|
122
|
-
filetype={props.filetype}
|
|
123
|
-
syntaxStyle={props.syntaxStyle}
|
|
124
|
-
treeSitterClient={props.treeSitterClient}
|
|
125
|
-
/>
|
|
126
|
-
</Show>
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Diff display using the built-in <diff> component.
|
|
132
|
-
*/
|
|
133
|
-
function FileLogDiff(props: FileLogDiffProps & FileLogInternalProps) {
|
|
134
|
-
const view = () => props.view ?? 'unified'
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<Show
|
|
138
|
-
when={props.syntaxStyle}
|
|
139
|
-
fallback={
|
|
140
|
-
<box paddingLeft={1} paddingRight={1}>
|
|
141
|
-
<text>{props.diff}</text>
|
|
142
|
-
</box>
|
|
143
|
-
}
|
|
144
|
-
>
|
|
145
|
-
<diff
|
|
146
|
-
diff={props.diff}
|
|
147
|
-
view={view()}
|
|
148
|
-
filetype={props.filetype}
|
|
149
|
-
syntaxStyle={props.syntaxStyle}
|
|
150
|
-
treeSitterClient={props.treeSitterClient}
|
|
151
|
-
/>
|
|
152
|
-
</Show>
|
|
153
|
-
)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Partial file display with error line highlighting.
|
|
158
|
-
*
|
|
159
|
-
* This component renders a file excerpt and highlights specific lines
|
|
160
|
-
* as errors using box overlays with colored backgrounds.
|
|
161
|
-
*/
|
|
162
|
-
function FileLogPartial(props: FileLogPartialProps & FileLogInternalProps) {
|
|
163
|
-
// Parse content into lines for error highlighting
|
|
164
|
-
const lines = createMemo(() => props.content.split('\n'))
|
|
165
|
-
|
|
166
|
-
// Calculate which lines are errors (relative to startLine)
|
|
167
|
-
const errorLineSet = createMemo(() => new Set(props.errorLines ?? []))
|
|
168
|
-
|
|
169
|
-
// Error colors
|
|
170
|
-
const errorBg = () => props.errorLineBackground ?? ERROR_HIGHLIGHT_COLORS.background
|
|
171
|
-
const errorBorder = () => props.errorLineBorderColor ?? ERROR_HIGHLIGHT_COLORS.border
|
|
172
|
-
|
|
173
|
-
// Line number width based on max line number
|
|
174
|
-
const maxLineNum = () => props.startLine + lines().length - 1
|
|
175
|
-
const lineNumWidth = () => Math.max(4, String(maxLineNum()).length + 1)
|
|
176
|
-
|
|
177
|
-
return (
|
|
178
|
-
<box flexDirection="column">
|
|
179
|
-
<For each={lines()}>
|
|
180
|
-
{(line, index) => {
|
|
181
|
-
const lineNumber = () => props.startLine + index()
|
|
182
|
-
const isError = () => errorLineSet().has(lineNumber())
|
|
183
|
-
|
|
184
|
-
return (
|
|
185
|
-
<box
|
|
186
|
-
flexDirection="row"
|
|
187
|
-
backgroundColor={isError() ? errorBg() : undefined}
|
|
188
|
-
border={isError() ? ['left'] : undefined}
|
|
189
|
-
borderColor={isError() ? errorBorder() : undefined}
|
|
190
|
-
>
|
|
191
|
-
{/* Line number gutter */}
|
|
192
|
-
<Show when={props.showLineNumbers}>
|
|
193
|
-
<box
|
|
194
|
-
width={lineNumWidth()}
|
|
195
|
-
backgroundColor={
|
|
196
|
-
isError() ? ERROR_HIGHLIGHT_COLORS.gutterBackground : HEADER_COLORS.background
|
|
197
|
-
}
|
|
198
|
-
paddingRight={1}
|
|
199
|
-
>
|
|
200
|
-
<text fg="#6B7280">{String(lineNumber()).padStart(lineNumWidth() - 1)}</text>
|
|
201
|
-
</box>
|
|
202
|
-
</Show>
|
|
203
|
-
|
|
204
|
-
{/* Code line */}
|
|
205
|
-
<box flexGrow={1} paddingLeft={1}>
|
|
206
|
-
<Show when={props.syntaxStyle} fallback={<text>{line}</text>}>
|
|
207
|
-
<code
|
|
208
|
-
content={line}
|
|
209
|
-
filetype={props.filetype}
|
|
210
|
-
syntaxStyle={props.syntaxStyle}
|
|
211
|
-
treeSitterClient={props.treeSitterClient}
|
|
212
|
-
/>
|
|
213
|
-
</Show>
|
|
214
|
-
</box>
|
|
215
|
-
</box>
|
|
216
|
-
)
|
|
217
|
-
}}
|
|
218
|
-
</For>
|
|
219
|
-
</box>
|
|
220
|
-
)
|
|
221
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './file_log.tsx'
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { TextAttributes } from '@opentui/core'
|
|
2
|
-
import { Show, For } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import type { LogLevel } from '@navios/core'
|
|
5
|
-
|
|
6
|
-
import { useTheme } from '../../hooks/index.ts'
|
|
7
|
-
import { ALL_LOG_LEVELS } from '../../../../types/index.ts'
|
|
8
|
-
|
|
9
|
-
import type { FilterState, LevelCounts } from '../../../../types/index.ts'
|
|
10
|
-
|
|
11
|
-
export interface FilterBarProps {
|
|
12
|
-
filter: FilterState
|
|
13
|
-
levelCounts: LevelCounts
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const LEVEL_LABELS: Record<LogLevel, string> = {
|
|
17
|
-
verbose: 'V',
|
|
18
|
-
debug: 'D',
|
|
19
|
-
log: 'L',
|
|
20
|
-
warn: 'W',
|
|
21
|
-
error: 'E',
|
|
22
|
-
fatal: 'F',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function FilterBar(props: FilterBarProps) {
|
|
26
|
-
const theme = useTheme()
|
|
27
|
-
const isSearchFocused = () => props.filter.focusedField === 'search'
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<box
|
|
31
|
-
flexDirection="column"
|
|
32
|
-
backgroundColor={theme.filter.background}
|
|
33
|
-
borderColor={theme.filter.border}
|
|
34
|
-
border={['bottom']}
|
|
35
|
-
paddingLeft={1}
|
|
36
|
-
paddingRight={1}
|
|
37
|
-
>
|
|
38
|
-
{/* Search input row */}
|
|
39
|
-
<box flexDirection="row" gap={1}>
|
|
40
|
-
<text fg={isSearchFocused() ? theme.colors.primary : theme.filter.textDim}>/</text>
|
|
41
|
-
<text fg={props.filter.searchQuery ? theme.filter.inputText : theme.filter.inputPlaceholder}>
|
|
42
|
-
{props.filter.searchQuery || 'Search logs...'}
|
|
43
|
-
</text>
|
|
44
|
-
<Show when={isSearchFocused()}>
|
|
45
|
-
<text fg={theme.filter.cursor} attributes={TextAttributes.BLINK}>
|
|
46
|
-
_
|
|
47
|
-
</text>
|
|
48
|
-
</Show>
|
|
49
|
-
</box>
|
|
50
|
-
|
|
51
|
-
{/* Level filters row */}
|
|
52
|
-
<box flexDirection="row" gap={1}>
|
|
53
|
-
<text fg={theme.filter.textDim}>Levels:</text>
|
|
54
|
-
<For each={ALL_LOG_LEVELS}>
|
|
55
|
-
{(level, index) => {
|
|
56
|
-
const isEnabled = () => props.filter.enabledLevels.has(level)
|
|
57
|
-
const count = () => props.levelCounts[level]
|
|
58
|
-
const levelColor = () => theme.logLevels[level].border
|
|
59
|
-
const isLevelsFocused = () => props.filter.focusedField === 'levels'
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<box flexDirection="row">
|
|
63
|
-
<text
|
|
64
|
-
fg={isEnabled() ? levelColor() : theme.filter.inactiveLevel}
|
|
65
|
-
attributes={isLevelsFocused() ? TextAttributes.BOLD : undefined}
|
|
66
|
-
>
|
|
67
|
-
{index() + 1}:{LEVEL_LABELS[level]}
|
|
68
|
-
</text>
|
|
69
|
-
<Show when={count() > 0}>
|
|
70
|
-
<text fg={theme.filter.textDim}>({count() > 99 ? '99+' : count()})</text>
|
|
71
|
-
</Show>
|
|
72
|
-
</box>
|
|
73
|
-
)
|
|
74
|
-
}}
|
|
75
|
-
</For>
|
|
76
|
-
</box>
|
|
77
|
-
|
|
78
|
-
{/* Hints */}
|
|
79
|
-
<box flexDirection="row">
|
|
80
|
-
<text fg={theme.filter.textDim}>Tab: switch fields | 1-7: toggle levels | Esc: close</text>
|
|
81
|
-
</box>
|
|
82
|
-
</box>
|
|
83
|
-
)
|
|
84
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { FilterBar } from './filter_bar.tsx'
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { TextAttributes } from '@opentui/core'
|
|
2
|
-
import { For, Show, createMemo } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import { useTheme } from '../../hooks/index.ts'
|
|
5
|
-
import { formatKeyBinding } from '../../../../keyboard/index.ts'
|
|
6
|
-
|
|
7
|
-
import type { KeyBinding, KeyBindingCategory } from '../../../../types/index.ts'
|
|
8
|
-
|
|
9
|
-
export interface HelpOverlayProps {
|
|
10
|
-
bindings: KeyBinding[]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const CATEGORY_ORDER: KeyBindingCategory[] = ['general', 'navigation', 'screen', 'filter', 'prompt']
|
|
14
|
-
|
|
15
|
-
const CATEGORY_LABELS: Record<KeyBindingCategory, string> = {
|
|
16
|
-
general: 'General',
|
|
17
|
-
navigation: 'Navigation',
|
|
18
|
-
screen: 'Screen',
|
|
19
|
-
filter: 'Filter',
|
|
20
|
-
prompt: 'Prompts',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function groupByCategory(bindings: KeyBinding[]): Record<KeyBindingCategory, KeyBinding[]> {
|
|
24
|
-
const grouped: Record<KeyBindingCategory, KeyBinding[]> = {
|
|
25
|
-
general: [],
|
|
26
|
-
navigation: [],
|
|
27
|
-
screen: [],
|
|
28
|
-
filter: [],
|
|
29
|
-
prompt: [],
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
for (const binding of bindings) {
|
|
33
|
-
if (binding.description) {
|
|
34
|
-
grouped[binding.category].push(binding)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return grouped
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function HelpOverlay(props: HelpOverlayProps) {
|
|
42
|
-
const theme = useTheme()
|
|
43
|
-
const grouped = createMemo(() => groupByCategory(props.bindings))
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<box
|
|
47
|
-
position="absolute"
|
|
48
|
-
top={1}
|
|
49
|
-
left={2}
|
|
50
|
-
right={2}
|
|
51
|
-
bottom={1}
|
|
52
|
-
backgroundColor={theme.help.background}
|
|
53
|
-
borderColor={theme.help.border}
|
|
54
|
-
border={['top', 'bottom', 'left', 'right']}
|
|
55
|
-
flexDirection="column"
|
|
56
|
-
paddingLeft={2}
|
|
57
|
-
paddingRight={2}
|
|
58
|
-
paddingTop={1}
|
|
59
|
-
paddingBottom={1}
|
|
60
|
-
>
|
|
61
|
-
{/* Header */}
|
|
62
|
-
<box marginBottom={1}>
|
|
63
|
-
<text fg={theme.help.title} attributes={TextAttributes.BOLD}>
|
|
64
|
-
Keyboard Shortcuts
|
|
65
|
-
</text>
|
|
66
|
-
</box>
|
|
67
|
-
|
|
68
|
-
{/* Categories */}
|
|
69
|
-
<scrollbox scrollY flexGrow={1}>
|
|
70
|
-
<box flexDirection="column" gap={1}>
|
|
71
|
-
<For each={CATEGORY_ORDER}>
|
|
72
|
-
{(category) => {
|
|
73
|
-
const categoryBindings = () => grouped()[category]
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<Show when={categoryBindings().length > 0}>
|
|
77
|
-
<box flexDirection="column">
|
|
78
|
-
<text fg={theme.help.category} attributes={TextAttributes.BOLD}>
|
|
79
|
-
{CATEGORY_LABELS[category]}
|
|
80
|
-
</text>
|
|
81
|
-
|
|
82
|
-
<For each={categoryBindings()}>
|
|
83
|
-
{(binding) => (
|
|
84
|
-
<box flexDirection="row" paddingLeft={2}>
|
|
85
|
-
<text fg={theme.help.key} width={14}>
|
|
86
|
-
{formatKeyBinding(binding)}
|
|
87
|
-
</text>
|
|
88
|
-
<text fg={theme.help.description}>{binding.description}</text>
|
|
89
|
-
</box>
|
|
90
|
-
)}
|
|
91
|
-
</For>
|
|
92
|
-
</box>
|
|
93
|
-
</Show>
|
|
94
|
-
)
|
|
95
|
-
}}
|
|
96
|
-
</For>
|
|
97
|
-
</box>
|
|
98
|
-
</scrollbox>
|
|
99
|
-
|
|
100
|
-
{/* Footer */}
|
|
101
|
-
<box marginTop={1} borderColor={theme.separator.line} border={['top']} paddingTop={1}>
|
|
102
|
-
<text fg={theme.help.hint}>Press ? or Esc to close</text>
|
|
103
|
-
</box>
|
|
104
|
-
</box>
|
|
105
|
-
)
|
|
106
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { HelpOverlay } from './help_overlay.tsx'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './log_message.tsx'
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { TextAttributes } from '@opentui/core'
|
|
2
|
-
import { Show, type JSX } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import { useTheme } from '../../hooks/index.ts'
|
|
5
|
-
import { VARIANT_COLORS } from '../../../../utils/index.ts'
|
|
6
|
-
|
|
7
|
-
import type { LogMessageProps } from '../../../../types/index.ts'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* LogMessage - A chat-like styled log message with level-based coloring.
|
|
11
|
-
*
|
|
12
|
-
* Features:
|
|
13
|
-
* - Left border with prominent color based on log level
|
|
14
|
-
* - Subtle tinted background matching the log level
|
|
15
|
-
* - Optional timestamp and label display
|
|
16
|
-
* - Supports both simple text and complex children
|
|
17
|
-
* - Optional variant for semantic styling (e.g., 'success', 'trace')
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* <LogMessage level="error">
|
|
21
|
-
* Connection failed: timeout after 30s
|
|
22
|
-
* </LogMessage>
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* <LogMessage level="log" timestamp={new Date()} label="API">
|
|
26
|
-
* Request completed successfully
|
|
27
|
-
* </LogMessage>
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* <LogMessage level="log" variant="success">
|
|
31
|
-
* Operation completed successfully
|
|
32
|
-
* </LogMessage>
|
|
33
|
-
*/
|
|
34
|
-
export function LogMessage(props: LogMessageProps & { children?: JSX.Element }) {
|
|
35
|
-
const theme = useTheme()
|
|
36
|
-
|
|
37
|
-
// Get colors: variant colors take precedence over level colors
|
|
38
|
-
const levelColors = () => (props.variant ? VARIANT_COLORS[props.variant] : theme.logLevels[props.level])
|
|
39
|
-
|
|
40
|
-
// Resolve final colors (custom overrides level colors)
|
|
41
|
-
const borderColor = () => props.borderColor ?? levelColors().border
|
|
42
|
-
const backgroundColor = () => props.backgroundColor ?? levelColors().background
|
|
43
|
-
|
|
44
|
-
// Text color: use level-specific text color if defined, otherwise use foreground
|
|
45
|
-
const textColor = () => levelColors().text ?? theme.colors.foreground
|
|
46
|
-
|
|
47
|
-
// Determine border sides based on style
|
|
48
|
-
const borderSides = (): ('left' | 'top' | 'bottom')[] =>
|
|
49
|
-
props.borderStyle === 'thin' || props.borderStyle === undefined ? ['left'] : ['left', 'top', 'bottom']
|
|
50
|
-
|
|
51
|
-
// Format timestamp if provided
|
|
52
|
-
const formattedTimestamp = () => {
|
|
53
|
-
if (!props.timestamp) return null
|
|
54
|
-
return props.timestamp instanceof Date ? props.timestamp.toLocaleTimeString() : props.timestamp
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<box
|
|
59
|
-
flexDirection="column"
|
|
60
|
-
border={borderSides()}
|
|
61
|
-
borderColor={borderColor()}
|
|
62
|
-
backgroundColor={backgroundColor()}
|
|
63
|
-
paddingLeft={props.padding ?? 1}
|
|
64
|
-
paddingRight={props.padding ?? 1}
|
|
65
|
-
marginBottom={props.margin ?? 0}
|
|
66
|
-
>
|
|
67
|
-
{/* Header row with timestamp and label */}
|
|
68
|
-
<Show when={formattedTimestamp() || props.label}>
|
|
69
|
-
<box flexDirection="row" gap={1}>
|
|
70
|
-
<Show when={formattedTimestamp()}>
|
|
71
|
-
<text fg={theme.colors.muted}>{formattedTimestamp()}</text>
|
|
72
|
-
</Show>
|
|
73
|
-
<Show when={props.label}>
|
|
74
|
-
<text fg={levelColors().border} attributes={TextAttributes.BOLD}>
|
|
75
|
-
[{props.label}]
|
|
76
|
-
</text>
|
|
77
|
-
</Show>
|
|
78
|
-
</box>
|
|
79
|
-
</Show>
|
|
80
|
-
|
|
81
|
-
{/* Message content */}
|
|
82
|
-
<text fg={textColor()}>{props.children}</text>
|
|
83
|
-
|
|
84
|
-
{/* Stack trace (for trace level) */}
|
|
85
|
-
<Show when={props.trace}>
|
|
86
|
-
<box marginTop={1}>
|
|
87
|
-
<text fg={theme.colors.muted}>{props.trace}</text>
|
|
88
|
-
</box>
|
|
89
|
-
</Show>
|
|
90
|
-
</box>
|
|
91
|
-
)
|
|
92
|
-
}
|