@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,155 +0,0 @@
|
|
|
1
|
-
import { TextAttributes } from '@opentui/core'
|
|
2
|
-
import { createSignal, createEffect, createMemo, For, Show, onCleanup } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import { useTheme } from '../../hooks/index.ts'
|
|
5
|
-
import { PromptRenderer } from '../prompt/index.ts'
|
|
6
|
-
|
|
7
|
-
import type { ScreenInstance } from '../../../../services/index.ts'
|
|
8
|
-
import type { MessageData } from '../../../../types/index.ts'
|
|
9
|
-
|
|
10
|
-
import { GroupRenderer } from './group_renderer.tsx'
|
|
11
|
-
import { MessageRenderer } from './message_renderer.tsx'
|
|
12
|
-
|
|
13
|
-
export interface ScreenBridgeProps {
|
|
14
|
-
screen: ScreenInstance
|
|
15
|
-
focused: boolean
|
|
16
|
-
/** Pre-filtered messages (if filtering is active) */
|
|
17
|
-
filteredMessages?: MessageData[]
|
|
18
|
-
/** Whether any filter is currently active */
|
|
19
|
-
isFiltering?: boolean
|
|
20
|
-
/** Total message count (before filtering) */
|
|
21
|
-
totalMessages?: number
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Helper to process messages and organize them into groups
|
|
25
|
-
interface ProcessedMessage {
|
|
26
|
-
type: 'single' | 'group'
|
|
27
|
-
message?: MessageData
|
|
28
|
-
label?: string
|
|
29
|
-
messages?: MessageData[]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function processMessagesIntoGroups(messages: MessageData[]): ProcessedMessage[] {
|
|
33
|
-
const result: ProcessedMessage[] = []
|
|
34
|
-
let i = 0
|
|
35
|
-
|
|
36
|
-
while (i < messages.length) {
|
|
37
|
-
const msg = messages[i]!
|
|
38
|
-
|
|
39
|
-
if (msg.type === 'group' && !msg.isEnd) {
|
|
40
|
-
// Start of a group - collect all messages until groupEnd
|
|
41
|
-
const groupLabel = msg.label
|
|
42
|
-
const groupMessages: MessageData[] = []
|
|
43
|
-
i++ // Move past the group start
|
|
44
|
-
|
|
45
|
-
while (i < messages.length) {
|
|
46
|
-
const innerMsg = messages[i]!
|
|
47
|
-
if (innerMsg.type === 'group' && innerMsg.isEnd) {
|
|
48
|
-
i++ // Move past the group end
|
|
49
|
-
break
|
|
50
|
-
}
|
|
51
|
-
groupMessages.push(innerMsg)
|
|
52
|
-
i++
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
result.push({
|
|
56
|
-
type: 'group',
|
|
57
|
-
label: groupLabel,
|
|
58
|
-
messages: groupMessages,
|
|
59
|
-
})
|
|
60
|
-
} else if (msg.type === 'group' && msg.isEnd) {
|
|
61
|
-
// Stray group end - skip it
|
|
62
|
-
i++
|
|
63
|
-
} else {
|
|
64
|
-
// Regular message
|
|
65
|
-
result.push({ type: 'single', message: msg })
|
|
66
|
-
i++
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return result
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function ScreenBridge(props: ScreenBridgeProps) {
|
|
74
|
-
const theme = useTheme()
|
|
75
|
-
const [version, setVersion] = createSignal(0)
|
|
76
|
-
|
|
77
|
-
// Subscribe to screen changes
|
|
78
|
-
createEffect(() => {
|
|
79
|
-
const unsub = props.screen.onChange(() => setVersion((v) => v + 1))
|
|
80
|
-
onCleanup(() => unsub())
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
// Use filtered messages if provided, otherwise get from screen
|
|
84
|
-
const messages = createMemo(() => {
|
|
85
|
-
version() // Track version for reactivity
|
|
86
|
-
return props.filteredMessages ?? props.screen.getMessages()
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
const activePrompt = createMemo(() => {
|
|
90
|
-
version() // Track version for reactivity
|
|
91
|
-
return props.screen.getActivePrompt()
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
const processedMessages = createMemo(() => processMessagesIntoGroups(messages()))
|
|
95
|
-
|
|
96
|
-
// Calculate filter stats
|
|
97
|
-
const filteredCount = () => messages().length
|
|
98
|
-
const total = () => props.totalMessages ?? messages().length
|
|
99
|
-
const showFilterStatus = () => props.isFiltering && filteredCount() !== total()
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<box flexDirection="column" flexGrow={1}>
|
|
103
|
-
{/* Screen header */}
|
|
104
|
-
<box
|
|
105
|
-
backgroundColor={theme.header.background}
|
|
106
|
-
borderColor={props.focused ? theme.sidebar.focusBorder : theme.header.border}
|
|
107
|
-
border={['bottom']}
|
|
108
|
-
paddingLeft={1}
|
|
109
|
-
paddingRight={1}
|
|
110
|
-
flexDirection="row"
|
|
111
|
-
justifyContent="space-between"
|
|
112
|
-
>
|
|
113
|
-
<text fg={theme.header.text} attributes={TextAttributes.BOLD}>
|
|
114
|
-
{props.screen.getName()}
|
|
115
|
-
</text>
|
|
116
|
-
<Show when={showFilterStatus()}>
|
|
117
|
-
<text fg={theme.sidebar.textDim}>
|
|
118
|
-
{filteredCount()}/{total()} messages
|
|
119
|
-
</text>
|
|
120
|
-
</Show>
|
|
121
|
-
</box>
|
|
122
|
-
|
|
123
|
-
{/* Scrollable content area */}
|
|
124
|
-
<scrollbox
|
|
125
|
-
flexGrow={1}
|
|
126
|
-
scrollY
|
|
127
|
-
stickyScroll
|
|
128
|
-
stickyStart="bottom"
|
|
129
|
-
contentOptions={{
|
|
130
|
-
paddingLeft: 1,
|
|
131
|
-
paddingRight: 1,
|
|
132
|
-
paddingTop: 1,
|
|
133
|
-
paddingBottom: 1,
|
|
134
|
-
gap: 1,
|
|
135
|
-
}}
|
|
136
|
-
>
|
|
137
|
-
<For each={processedMessages()}>
|
|
138
|
-
{(item) => (
|
|
139
|
-
<Show
|
|
140
|
-
when={item.type === 'group'}
|
|
141
|
-
fallback={<MessageRenderer message={item.message!} />}
|
|
142
|
-
>
|
|
143
|
-
<GroupRenderer label={item.label!} messages={item.messages!} />
|
|
144
|
-
</Show>
|
|
145
|
-
)}
|
|
146
|
-
</For>
|
|
147
|
-
|
|
148
|
-
{/* Render active prompt at the end of messages */}
|
|
149
|
-
<Show when={activePrompt()}>
|
|
150
|
-
<PromptRenderer prompt={activePrompt()!} />
|
|
151
|
-
</Show>
|
|
152
|
-
</scrollbox>
|
|
153
|
-
</box>
|
|
154
|
-
)
|
|
155
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { TextAttributes } from '@opentui/core'
|
|
2
|
-
import { For, Show, createMemo } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import { TABLE_COLORS } from '../../../../utils/index.ts'
|
|
5
|
-
|
|
6
|
-
import type { TableMessageData } from '../../../../types/index.ts'
|
|
7
|
-
|
|
8
|
-
export interface TableMessageProps {
|
|
9
|
-
message: TableMessageData
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function TableMessage(props: TableMessageProps) {
|
|
13
|
-
// Calculate column widths
|
|
14
|
-
const colWidths = createMemo(() =>
|
|
15
|
-
props.message.headers.map((h, i) => {
|
|
16
|
-
const headerLen = h.length
|
|
17
|
-
const maxRowLen =
|
|
18
|
-
props.message.rows.length > 0
|
|
19
|
-
? Math.max(...props.message.rows.map((r) => (r[i] ?? '').length))
|
|
20
|
-
: 0
|
|
21
|
-
return Math.max(headerLen, maxRowLen)
|
|
22
|
-
}),
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
const pad = (str: string, width: number) => str.padEnd(width)
|
|
26
|
-
|
|
27
|
-
const headerRow = createMemo(() =>
|
|
28
|
-
props.message.headers.map((h, i) => pad(h, colWidths()[i] ?? 0)).join(' │ '),
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
const separator = createMemo(() => colWidths().map((w) => '─'.repeat(w)).join('─┼─'))
|
|
32
|
-
|
|
33
|
-
const dataRows = createMemo(() =>
|
|
34
|
-
props.message.rows.map((row) => row.map((cell, i) => pad(cell, colWidths()[i] ?? 0)).join(' │ ')),
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<box
|
|
39
|
-
flexDirection="column"
|
|
40
|
-
border={['left']}
|
|
41
|
-
borderColor={TABLE_COLORS.border}
|
|
42
|
-
backgroundColor={TABLE_COLORS.background}
|
|
43
|
-
paddingLeft={1}
|
|
44
|
-
paddingRight={1}
|
|
45
|
-
>
|
|
46
|
-
<Show when={props.message.title}>
|
|
47
|
-
<text fg={TABLE_COLORS.title} attributes={TextAttributes.BOLD}>
|
|
48
|
-
{props.message.title}
|
|
49
|
-
</text>
|
|
50
|
-
</Show>
|
|
51
|
-
<text fg={TABLE_COLORS.headerText} attributes={TextAttributes.BOLD}>
|
|
52
|
-
{headerRow()}
|
|
53
|
-
</text>
|
|
54
|
-
<text fg={TABLE_COLORS.separator}>{separator()}</text>
|
|
55
|
-
<For each={dataRows()}>{(row) => <text fg={TABLE_COLORS.cellText}>{row}</text>}</For>
|
|
56
|
-
</box>
|
|
57
|
-
)
|
|
58
|
-
}
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { useKeyboard } from '@opentui/solid'
|
|
2
|
-
import { createSignal, createEffect, createMemo, onCleanup, Show } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import { LoggerProvider } from '../context/index.ts'
|
|
5
|
-
import { FilterEngine } from '../../../filter/index.ts'
|
|
6
|
-
import { KeyboardManager, createDefaultBindings, handlePrintableInput } from '../../../keyboard/index.ts'
|
|
7
|
-
import {
|
|
8
|
-
ALL_LOG_LEVELS,
|
|
9
|
-
createDefaultFilterState,
|
|
10
|
-
hasActiveFilter,
|
|
11
|
-
type FilterState,
|
|
12
|
-
type KeyboardContext,
|
|
13
|
-
type Theme,
|
|
14
|
-
} from '../../../types/index.ts'
|
|
15
|
-
|
|
16
|
-
import type { ScreenManagerInstance } from '../../../services/index.ts'
|
|
17
|
-
|
|
18
|
-
import { FilterBar } from './filter/filter_bar.tsx'
|
|
19
|
-
import { HelpOverlay } from './help/help_overlay.tsx'
|
|
20
|
-
import { ScreenBridge } from './screen/screen_bridge.tsx'
|
|
21
|
-
import { Sidebar } from './sidebar/sidebar.tsx'
|
|
22
|
-
|
|
23
|
-
export interface ScreenManagerBridgeProps {
|
|
24
|
-
manager: ScreenManagerInstance
|
|
25
|
-
theme?: Theme
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function ScreenManagerBridge(props: ScreenManagerBridgeProps) {
|
|
29
|
-
const [version, setVersion] = createSignal(0)
|
|
30
|
-
const [showHelp, setShowHelp] = createSignal(false)
|
|
31
|
-
const [filter, setFilter] = createSignal<FilterState>(createDefaultFilterState())
|
|
32
|
-
|
|
33
|
-
// Subscribe to manager changes
|
|
34
|
-
createEffect(() => {
|
|
35
|
-
const unsub = props.manager.onChange(() => setVersion((v) => v + 1))
|
|
36
|
-
onCleanup(() => unsub())
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
// Helper functions for keyboard bindings
|
|
40
|
-
const getActiveScreen = () => props.manager.getActiveScreen()
|
|
41
|
-
|
|
42
|
-
const toggleHelp = () => {
|
|
43
|
-
setShowHelp((prev) => !prev)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const toggleFilter = () => {
|
|
47
|
-
setFilter((prev) => ({
|
|
48
|
-
...prev,
|
|
49
|
-
isVisible: !prev.isVisible,
|
|
50
|
-
focusedField: 'search',
|
|
51
|
-
}))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const closeFilter = () => {
|
|
55
|
-
setFilter((prev) => ({ ...prev, isVisible: false }))
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const filterAppendChar = (char: string) => {
|
|
59
|
-
setFilter((prev) => ({
|
|
60
|
-
...prev,
|
|
61
|
-
searchQuery: prev.searchQuery + char,
|
|
62
|
-
}))
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const filterDeleteChar = () => {
|
|
66
|
-
setFilter((prev) => ({
|
|
67
|
-
...prev,
|
|
68
|
-
searchQuery: prev.searchQuery.slice(0, -1),
|
|
69
|
-
}))
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const filterToggleLevel = (index: number) => {
|
|
73
|
-
setFilter((prev) => {
|
|
74
|
-
const level = ALL_LOG_LEVELS[index]
|
|
75
|
-
if (!level) return prev
|
|
76
|
-
|
|
77
|
-
const newLevels = new Set(prev.enabledLevels)
|
|
78
|
-
if (newLevels.has(level)) {
|
|
79
|
-
newLevels.delete(level)
|
|
80
|
-
} else {
|
|
81
|
-
newLevels.add(level)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return { ...prev, enabledLevels: newLevels }
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const filterCycleField = () => {
|
|
89
|
-
setFilter((prev) => ({
|
|
90
|
-
...prev,
|
|
91
|
-
focusedField: prev.focusedField === 'search' ? 'levels' : 'search',
|
|
92
|
-
}))
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Create keyboard manager with bindings
|
|
96
|
-
const keyboardManager = createMemo(() => {
|
|
97
|
-
const km = new KeyboardManager()
|
|
98
|
-
const bindings = createDefaultBindings({
|
|
99
|
-
manager: props.manager,
|
|
100
|
-
getActiveScreen,
|
|
101
|
-
toggleHelp,
|
|
102
|
-
toggleFilter,
|
|
103
|
-
closeFilter,
|
|
104
|
-
filterAppendChar,
|
|
105
|
-
filterDeleteChar,
|
|
106
|
-
filterToggleLevel,
|
|
107
|
-
filterCycleField,
|
|
108
|
-
})
|
|
109
|
-
km.addBindings(bindings)
|
|
110
|
-
return km
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
// Keyboard handler
|
|
114
|
-
const handleKeyboard = (key: { name: string; ctrl?: boolean; meta?: boolean; sequence?: string }) => {
|
|
115
|
-
const screens = props.manager.getScreens()
|
|
116
|
-
const activeScreen = props.manager.getActiveScreen()
|
|
117
|
-
|
|
118
|
-
const context: KeyboardContext = {
|
|
119
|
-
hasSidebar: screens.length > 1,
|
|
120
|
-
focusArea: props.manager.focusArea,
|
|
121
|
-
hasPrompt: activeScreen?.hasActivePrompt() ?? false,
|
|
122
|
-
inInputMode: activeScreen?.isPromptInInputMode() ?? false,
|
|
123
|
-
isFilterActive: filter().isVisible,
|
|
124
|
-
isHelpVisible: showHelp(),
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Try keyboard manager first
|
|
128
|
-
if (keyboardManager().handleKey(key, context)) {
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Handle printable characters (for input mode and filter)
|
|
133
|
-
handlePrintableInput(key, context, {
|
|
134
|
-
manager: props.manager,
|
|
135
|
-
getActiveScreen,
|
|
136
|
-
toggleHelp,
|
|
137
|
-
toggleFilter,
|
|
138
|
-
closeFilter,
|
|
139
|
-
filterAppendChar,
|
|
140
|
-
filterDeleteChar,
|
|
141
|
-
filterToggleLevel,
|
|
142
|
-
filterCycleField,
|
|
143
|
-
})
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Handle keyboard input
|
|
147
|
-
useKeyboard(handleKeyboard)
|
|
148
|
-
|
|
149
|
-
// Derived state
|
|
150
|
-
const screens = () => {
|
|
151
|
-
version() // Track for reactivity
|
|
152
|
-
return props.manager.getScreens()
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const activeScreen = () => {
|
|
156
|
-
version() // Track for reactivity
|
|
157
|
-
return props.manager.getActiveScreen()
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const activeScreenId = () => activeScreen()?.getId() ?? screens()[0]?.getId() ?? ''
|
|
161
|
-
const bindOptions = () => props.manager.getBindOptions()
|
|
162
|
-
const hasSidebar = () => screens().length > 1
|
|
163
|
-
|
|
164
|
-
// Subscribe to active screen version for level counts
|
|
165
|
-
const [activeScreenVersion, setActiveScreenVersion] = createSignal(0)
|
|
166
|
-
|
|
167
|
-
createEffect(() => {
|
|
168
|
-
const screen = activeScreen()
|
|
169
|
-
if (screen) {
|
|
170
|
-
const unsub = screen.onChange(() => setActiveScreenVersion((v) => v + 1))
|
|
171
|
-
onCleanup(() => unsub())
|
|
172
|
-
}
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
// Get level counts for filter bar
|
|
176
|
-
const levelCounts = createMemo(() => {
|
|
177
|
-
activeScreenVersion() // Track for reactivity
|
|
178
|
-
const screen = activeScreen()
|
|
179
|
-
if (!screen) {
|
|
180
|
-
return {
|
|
181
|
-
verbose: 0,
|
|
182
|
-
debug: 0,
|
|
183
|
-
log: 0,
|
|
184
|
-
warn: 0,
|
|
185
|
-
error: 0,
|
|
186
|
-
fatal: 0,
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return FilterEngine.countByLevel(screen.getMessages())
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
// Filter messages for the active screen
|
|
193
|
-
const filteredMessages = createMemo(() => {
|
|
194
|
-
activeScreenVersion() // Track for reactivity
|
|
195
|
-
const screen = activeScreen()
|
|
196
|
-
if (!screen) return []
|
|
197
|
-
return FilterEngine.filterMessages(screen.getMessages(), filter())
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
const isFiltering = createMemo(() => hasActiveFilter(filter()))
|
|
201
|
-
|
|
202
|
-
return (
|
|
203
|
-
<LoggerProvider theme={props.theme}>
|
|
204
|
-
<box flexDirection="row" flexGrow={1}>
|
|
205
|
-
{/* Sidebar */}
|
|
206
|
-
<Show when={hasSidebar()}>
|
|
207
|
-
<Sidebar
|
|
208
|
-
screens={screens()}
|
|
209
|
-
selectedIndex={props.manager.selectedIndex}
|
|
210
|
-
activeScreenId={activeScreenId()}
|
|
211
|
-
focused={props.manager.focusArea === 'sidebar'}
|
|
212
|
-
width={bindOptions().sidebarWidth ?? 25}
|
|
213
|
-
title={bindOptions().sidebarTitle ?? 'Screens'}
|
|
214
|
-
/>
|
|
215
|
-
</Show>
|
|
216
|
-
|
|
217
|
-
{/* Main content area */}
|
|
218
|
-
<box flexDirection="column" flexGrow={1}>
|
|
219
|
-
{/* Filter bar */}
|
|
220
|
-
<Show when={filter().isVisible}>
|
|
221
|
-
<FilterBar filter={filter()} levelCounts={levelCounts()} />
|
|
222
|
-
</Show>
|
|
223
|
-
|
|
224
|
-
{/* Screen content */}
|
|
225
|
-
<Show when={activeScreen()}>
|
|
226
|
-
<ScreenBridge
|
|
227
|
-
screen={activeScreen()!}
|
|
228
|
-
focused={props.manager.focusArea === 'content'}
|
|
229
|
-
filteredMessages={filteredMessages()}
|
|
230
|
-
isFiltering={isFiltering()}
|
|
231
|
-
totalMessages={activeScreen()!.getMessages().length}
|
|
232
|
-
/>
|
|
233
|
-
</Show>
|
|
234
|
-
</box>
|
|
235
|
-
|
|
236
|
-
{/* Help overlay */}
|
|
237
|
-
<Show when={showHelp()}>
|
|
238
|
-
<HelpOverlay bindings={keyboardManager().getBindingsForHelp()} />
|
|
239
|
-
</Show>
|
|
240
|
-
</box>
|
|
241
|
-
</LoggerProvider>
|
|
242
|
-
)
|
|
243
|
-
}
|
|
@@ -1,108 +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
|
-
|
|
6
|
-
import type { ScreenInstance } from '../../../../services/index.ts'
|
|
7
|
-
|
|
8
|
-
import { SidebarItem } from './sidebar_item.tsx'
|
|
9
|
-
import { SidebarSeparator } from './sidebar_separator.tsx'
|
|
10
|
-
|
|
11
|
-
export interface SidebarProps {
|
|
12
|
-
screens: ScreenInstance[]
|
|
13
|
-
selectedIndex: number
|
|
14
|
-
activeScreenId: string
|
|
15
|
-
focused: boolean
|
|
16
|
-
width: number
|
|
17
|
-
title: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function Sidebar(props: SidebarProps) {
|
|
21
|
-
const theme = useTheme()
|
|
22
|
-
|
|
23
|
-
// Separate screens: only "pending" status on top, everything else below
|
|
24
|
-
const pendingScreens = createMemo(() => {
|
|
25
|
-
const result: { screen: ScreenInstance; originalIndex: number }[] = []
|
|
26
|
-
props.screens.forEach((screen, index) => {
|
|
27
|
-
if (screen.getStatus() === 'pending') {
|
|
28
|
-
result.push({ screen, originalIndex: index })
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
return result
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
const otherScreens = createMemo(() => {
|
|
35
|
-
const result: { screen: ScreenInstance; originalIndex: number }[] = []
|
|
36
|
-
props.screens.forEach((screen, index) => {
|
|
37
|
-
if (screen.getStatus() !== 'pending') {
|
|
38
|
-
result.push({ screen, originalIndex: index })
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
return result
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
const hasPending = () => pendingScreens().length > 0
|
|
45
|
-
const hasOther = () => otherScreens().length > 0
|
|
46
|
-
const showSeparator = () => hasPending() && hasOther()
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<box
|
|
50
|
-
flexDirection="column"
|
|
51
|
-
width={props.width}
|
|
52
|
-
borderColor={props.focused ? theme.sidebar.focusBorder : theme.sidebar.border}
|
|
53
|
-
border={['right']}
|
|
54
|
-
>
|
|
55
|
-
{/* Sidebar header */}
|
|
56
|
-
<box
|
|
57
|
-
backgroundColor={theme.header.background}
|
|
58
|
-
paddingLeft={1}
|
|
59
|
-
paddingRight={1}
|
|
60
|
-
borderColor={theme.header.border}
|
|
61
|
-
border={['bottom']}
|
|
62
|
-
>
|
|
63
|
-
<text fg={theme.header.text} attributes={TextAttributes.BOLD}>
|
|
64
|
-
{props.title}
|
|
65
|
-
</text>
|
|
66
|
-
</box>
|
|
67
|
-
|
|
68
|
-
{/* Screen list */}
|
|
69
|
-
<scrollbox scrollY stickyScroll={false} flexGrow={1} contentOptions={{ flexGrow: 1 }}>
|
|
70
|
-
<box flexDirection="column">
|
|
71
|
-
{/* Pending screens (active work) */}
|
|
72
|
-
<For each={pendingScreens()}>
|
|
73
|
-
{({ screen, originalIndex }) => (
|
|
74
|
-
<SidebarItem
|
|
75
|
-
screen={screen}
|
|
76
|
-
isSelected={originalIndex === props.selectedIndex}
|
|
77
|
-
isActive={screen.getId() === props.activeScreenId}
|
|
78
|
-
focused={props.focused}
|
|
79
|
-
/>
|
|
80
|
-
)}
|
|
81
|
-
</For>
|
|
82
|
-
|
|
83
|
-
{/* Separator between pending and other screens */}
|
|
84
|
-
<Show when={showSeparator()}>
|
|
85
|
-
<SidebarSeparator />
|
|
86
|
-
</Show>
|
|
87
|
-
|
|
88
|
-
{/* Other screens (waiting, success, fail) */}
|
|
89
|
-
<For each={otherScreens()}>
|
|
90
|
-
{({ screen, originalIndex }) => (
|
|
91
|
-
<SidebarItem
|
|
92
|
-
screen={screen}
|
|
93
|
-
isSelected={originalIndex === props.selectedIndex}
|
|
94
|
-
isActive={screen.getId() === props.activeScreenId}
|
|
95
|
-
focused={props.focused}
|
|
96
|
-
/>
|
|
97
|
-
)}
|
|
98
|
-
</For>
|
|
99
|
-
</box>
|
|
100
|
-
</scrollbox>
|
|
101
|
-
|
|
102
|
-
{/* Footer with keybindings hint */}
|
|
103
|
-
<box paddingLeft={1} paddingRight={1} borderColor={theme.sidebar.border} border={['top']}>
|
|
104
|
-
<text fg={theme.sidebar.text}>q: exit | Tab: focus | ?: help</text>
|
|
105
|
-
</box>
|
|
106
|
-
</box>
|
|
107
|
-
)
|
|
108
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { TextAttributes } from '@opentui/core'
|
|
2
|
-
import { Show } from 'solid-js'
|
|
3
|
-
|
|
4
|
-
import { useTheme } from '../../hooks/index.ts'
|
|
5
|
-
|
|
6
|
-
import type { ScreenInstance } from '../../../../services/index.ts'
|
|
7
|
-
|
|
8
|
-
export interface SidebarItemProps {
|
|
9
|
-
screen: ScreenInstance
|
|
10
|
-
isSelected: boolean
|
|
11
|
-
isActive: boolean
|
|
12
|
-
focused: boolean
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function SidebarItem(props: SidebarItemProps) {
|
|
16
|
-
const theme = useTheme()
|
|
17
|
-
const status = () => props.screen.getStatus()
|
|
18
|
-
const statusIndicator = () => theme.statusIndicators[status()]
|
|
19
|
-
|
|
20
|
-
// Determine background color based on state
|
|
21
|
-
const backgroundColor = () => {
|
|
22
|
-
if (props.isSelected && props.focused) {
|
|
23
|
-
return theme.sidebar.selectedBackground
|
|
24
|
-
} else if (props.isActive) {
|
|
25
|
-
return theme.sidebar.selectedBackground + '80'
|
|
26
|
-
}
|
|
27
|
-
return undefined
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<box flexDirection="row" paddingLeft={1} paddingRight={1} backgroundColor={backgroundColor()}>
|
|
32
|
-
{/* Selection indicator */}
|
|
33
|
-
<text fg={props.isSelected && props.focused ? theme.sidebar.focusBorder : 'transparent'}>
|
|
34
|
-
{'>'}{' '}
|
|
35
|
-
</text>
|
|
36
|
-
|
|
37
|
-
{/* Status indicator */}
|
|
38
|
-
<text fg={statusIndicator().color}>{statusIndicator().icon} </text>
|
|
39
|
-
|
|
40
|
-
{/* Screen name */}
|
|
41
|
-
<text fg={props.isActive ? theme.sidebar.text : theme.sidebar.textDim} flexGrow={1}>
|
|
42
|
-
{props.screen.getName()}
|
|
43
|
-
</text>
|
|
44
|
-
|
|
45
|
-
{/* Badge if present */}
|
|
46
|
-
<Show when={props.screen.getBadgeCount() > 0}>
|
|
47
|
-
<box backgroundColor={theme.sidebar.badge} paddingLeft={1} paddingRight={1}>
|
|
48
|
-
<text fg={theme.colors.foreground} attributes={TextAttributes.BOLD}>
|
|
49
|
-
{props.screen.getBadgeCount() > 99 ? '99+' : props.screen.getBadgeCount()}
|
|
50
|
-
</text>
|
|
51
|
-
</box>
|
|
52
|
-
</Show>
|
|
53
|
-
</box>
|
|
54
|
-
)
|
|
55
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { useTheme } from '../../hooks/index.ts'
|
|
2
|
-
|
|
3
|
-
export function SidebarSeparator() {
|
|
4
|
-
const theme = useTheme()
|
|
5
|
-
|
|
6
|
-
return (
|
|
7
|
-
<box flexDirection="row" paddingTop={1}>
|
|
8
|
-
<box flexGrow={1} />
|
|
9
|
-
<text fg={theme.separator.line}>· · ·</text>
|
|
10
|
-
<box flexGrow={1} />
|
|
11
|
-
</box>
|
|
12
|
-
)
|
|
13
|
-
}
|