@brimveyn/aimux 1.5.4 → 1.6.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/README.md +14 -2
- package/package.json +5 -3
- package/src/app-runtime/side-effects.ts +41 -6
- package/src/app.tsx +17 -5
- package/src/config.ts +29 -4
- package/src/diff-parser/clean-last-newline.ts +5 -0
- package/src/diff-parser/constants.ts +13 -0
- package/src/diff-parser/index.ts +12 -0
- package/src/diff-parser/parse-line-type.ts +29 -0
- package/src/diff-parser/parse-patch-files.ts +369 -0
- package/src/diff-parser/types.ts +75 -0
- package/src/input/modes/bridge.ts +8 -0
- package/src/input/modes/transitions.ts +2 -1
- package/src/input/modes/types.ts +4 -1
- package/src/pty/terminal-snapshot.ts +4 -4
- package/src/state/git-tree.ts +220 -0
- package/src/state/reducers/git-mode-state.ts +232 -35
- package/src/state/reducers/git-panel-state.ts +29 -3
- package/src/state/reducers/modal-state.ts +43 -10
- package/src/state/store.ts +5 -1
- package/src/state/types.ts +41 -5
- package/src/state/workspace-save.ts +2 -0
- package/src/ui/components/create-session-modal.tsx +23 -7
- package/src/ui/components/diff-renderer/build-rows.ts +349 -0
- package/src/ui/components/diff-renderer/filetype.ts +29 -0
- package/src/ui/components/diff-renderer/fold-strip.tsx +84 -0
- package/src/ui/components/diff-renderer/highlight.ts +48 -0
- package/src/ui/components/diff-renderer/index.ts +1 -0
- package/src/ui/components/diff-renderer/pierre-diff.tsx +170 -0
- package/src/ui/components/diff-renderer/split-view.tsx +207 -0
- package/src/ui/components/diff-renderer/stacked-view.tsx +166 -0
- package/src/ui/components/git-commit-modal.tsx +14 -2
- package/src/ui/components/git-pane-widget.tsx +5 -0
- package/src/ui/components/git-panel.tsx +176 -79
- package/src/ui/components/git-view.tsx +89 -87
- package/src/ui/components/help-modal.tsx +43 -11
- package/src/ui/components/input-field.tsx +2 -2
- package/src/ui/components/list-item.tsx +9 -1
- package/src/ui/components/modal-filter-bar.tsx +1 -1
- package/src/ui/components/modal-keybinds-overlay.tsx +2 -2
- package/src/ui/components/modal-shell.tsx +3 -3
- package/src/ui/components/new-tab-modal.tsx +15 -3
- package/src/ui/components/pending-chord-overlay.tsx +3 -3
- package/src/ui/components/session-bar.tsx +10 -5
- package/src/ui/components/session-picker-modal.tsx +26 -9
- package/src/ui/components/sidebar.tsx +22 -10
- package/src/ui/components/snippet-editor-modal.tsx +16 -2
- package/src/ui/components/snippet-picker-modal.tsx +11 -3
- package/src/ui/components/split-layout.tsx +1 -1
- package/src/ui/components/status-bar.tsx +12 -9
- package/src/ui/components/surface.tsx +5 -5
- package/src/ui/components/tab-item.tsx +22 -16
- package/src/ui/components/terminal-pane.tsx +25 -15
- package/src/ui/components/theme-picker-modal.tsx +111 -16
- package/src/ui/components/update-available-modal.tsx +11 -1
- package/src/ui/filter-themes.ts +10 -0
- package/src/ui/house-themes.ts +313 -0
- package/src/ui/keymap-context.ts +10 -2
- package/src/ui/root.tsx +26 -6
- package/src/ui/shiki.ts +49 -0
- package/src/ui/status-bar-model.ts +19 -1
- package/src/ui/theme.ts +22 -10
- package/src/ui/themes.generated.ts +59794 -0
- package/src/ui/themes.ts +68 -274
- package/src/ui/syntax.ts +0 -102
|
@@ -1,51 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { useTerminalDimensions } from '@opentui/react'
|
|
3
2
|
import { memo, useEffect, useRef } from 'react'
|
|
4
3
|
|
|
5
|
-
import type { DiffData } from '../../state/types'
|
|
4
|
+
import type { DiffData, GitDiffView } from '../../state/types'
|
|
5
|
+
import type { ThemeId } from '../themes'
|
|
6
6
|
|
|
7
7
|
import { fetchDiff } from '../../git/git-diff'
|
|
8
8
|
import { useGitPanelPolling } from '../../git/git-poller'
|
|
9
9
|
import { useAppStore } from '../../state/app-store'
|
|
10
10
|
import { dispatchGlobal } from '../../state/dispatch-ref'
|
|
11
|
+
import { getSelectedGitFile, gitFileKey } from '../../state/git-tree'
|
|
11
12
|
import { setGitDiffScroller } from '../git-view-controls'
|
|
12
|
-
import { getSyntaxClient, getSyntaxStyle } from '../syntax'
|
|
13
13
|
import { theme } from '../theme'
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
interface CodePaneLike {
|
|
17
|
-
scrollY: number
|
|
18
|
-
maxScrollY: number
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface DiffRenderableInternals {
|
|
22
|
-
leftCodeRenderable?: CodePaneLike
|
|
23
|
-
rightCodeRenderable?: CodePaneLike
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function filetypeFromPath(path: string): string | undefined {
|
|
27
|
-
const dot = path.lastIndexOf('.')
|
|
28
|
-
if (dot < 0) return undefined
|
|
29
|
-
const ext = path.slice(dot + 1).toLowerCase()
|
|
30
|
-
const map: Record<string, string> = {
|
|
31
|
-
cjs: 'javascript',
|
|
32
|
-
js: 'javascript',
|
|
33
|
-
jsx: 'javascript',
|
|
34
|
-
markdown: 'markdown',
|
|
35
|
-
md: 'markdown',
|
|
36
|
-
mdx: 'markdown',
|
|
37
|
-
mjs: 'javascript',
|
|
38
|
-
ts: 'typescript',
|
|
39
|
-
tsx: 'typescript',
|
|
40
|
-
zig: 'zig',
|
|
41
|
-
}
|
|
42
|
-
return map[ext]
|
|
43
|
-
}
|
|
14
|
+
import { PierreDiff, type PierreDiffHandle } from './diff-renderer'
|
|
15
|
+
import { GitPanel } from './git-panel'
|
|
44
16
|
|
|
45
17
|
interface DiffStageProps {
|
|
46
18
|
diff: DiffData | undefined
|
|
19
|
+
diffKey: string | null
|
|
47
20
|
loading: boolean
|
|
48
|
-
diffRef: React.RefObject<
|
|
21
|
+
diffRef: React.RefObject<PierreDiffHandle | null>
|
|
22
|
+
themeId: ThemeId
|
|
23
|
+
view: GitDiffView
|
|
49
24
|
}
|
|
50
25
|
|
|
51
26
|
function placeholderText(diff: DiffData): string | null {
|
|
@@ -62,25 +37,32 @@ function placeholderText(diff: DiffData): string | null {
|
|
|
62
37
|
return null
|
|
63
38
|
}
|
|
64
39
|
|
|
65
|
-
const DiffStage = memo(function DiffStage({
|
|
40
|
+
const DiffStage = memo(function DiffStage({
|
|
41
|
+
diff,
|
|
42
|
+
diffKey,
|
|
43
|
+
diffRef,
|
|
44
|
+
loading,
|
|
45
|
+
themeId,
|
|
46
|
+
view,
|
|
47
|
+
}: DiffStageProps) {
|
|
66
48
|
if (loading && !diff) {
|
|
67
49
|
return (
|
|
68
50
|
<box flexGrow={1} padding={1}>
|
|
69
|
-
<text fg={theme.
|
|
51
|
+
<text fg={theme.colors['descriptionForeground']}>Loading diff…</text>
|
|
70
52
|
</box>
|
|
71
53
|
)
|
|
72
54
|
}
|
|
73
55
|
if (!diff) {
|
|
74
56
|
return (
|
|
75
57
|
<box flexGrow={1} padding={1}>
|
|
76
|
-
<text fg={theme.
|
|
58
|
+
<text fg={theme.colors['descriptionForeground']}>Select a file.</text>
|
|
77
59
|
</box>
|
|
78
60
|
)
|
|
79
61
|
}
|
|
80
62
|
if (diff.errorMessage) {
|
|
81
63
|
return (
|
|
82
64
|
<box flexGrow={1} padding={1}>
|
|
83
|
-
<text fg={theme.
|
|
65
|
+
<text fg={theme.colors['editorError.foreground']}>{diff.errorMessage}</text>
|
|
84
66
|
</box>
|
|
85
67
|
)
|
|
86
68
|
}
|
|
@@ -89,50 +71,45 @@ const DiffStage = memo(function DiffStage({ diff, diffRef, loading }: DiffStageP
|
|
|
89
71
|
if (placeholder) {
|
|
90
72
|
return (
|
|
91
73
|
<box flexGrow={1} padding={1}>
|
|
92
|
-
<text fg={theme.
|
|
74
|
+
<text fg={theme.colors['descriptionForeground']}>{placeholder}</text>
|
|
93
75
|
</box>
|
|
94
76
|
)
|
|
95
77
|
}
|
|
96
78
|
|
|
97
|
-
const filetype = filetypeFromPath(diff.path)
|
|
98
|
-
|
|
99
79
|
return (
|
|
100
80
|
<box flexDirection="column" flexGrow={1} overflow="hidden">
|
|
101
81
|
{diff.oldPath ? (
|
|
102
82
|
<box paddingLeft={1} paddingRight={1}>
|
|
103
|
-
<text fg={theme.
|
|
83
|
+
<text fg={theme.colors['descriptionForeground']}>
|
|
104
84
|
renamed: {diff.oldPath} → {diff.path}
|
|
105
85
|
</text>
|
|
106
86
|
</box>
|
|
107
87
|
) : null}
|
|
108
|
-
<
|
|
88
|
+
<PierreDiff
|
|
89
|
+
cacheKey={diffKey ?? diff.path}
|
|
109
90
|
ref={diffRef}
|
|
110
91
|
diff={diff.rawDiff}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
wrapMode="none"
|
|
115
|
-
filetype={filetype}
|
|
116
|
-
treeSitterClient={filetype ? getSyntaxClient() : undefined}
|
|
117
|
-
syntaxStyle={filetype ? getSyntaxStyle() : undefined}
|
|
118
|
-
addedBg={theme.diffAddBg}
|
|
119
|
-
removedBg={theme.diffRemoveBg}
|
|
120
|
-
addedSignColor={theme.success}
|
|
121
|
-
removedSignColor={theme.danger}
|
|
122
|
-
flexGrow={1}
|
|
92
|
+
path={diff.path}
|
|
93
|
+
themeId={themeId}
|
|
94
|
+
view={view}
|
|
123
95
|
/>
|
|
124
96
|
</box>
|
|
125
97
|
)
|
|
126
98
|
})
|
|
127
99
|
|
|
128
|
-
|
|
129
|
-
|
|
100
|
+
interface GitViewProps {
|
|
101
|
+
themeId: ThemeId
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const GitView = memo(function GitView({ themeId }: GitViewProps) {
|
|
105
|
+
const dimensions = useTerminalDimensions()
|
|
106
|
+
const gitPane = useAppStore((s) => s.gitPane)
|
|
130
107
|
const gitPanel = useAppStore((s) => s.gitPanel)
|
|
131
108
|
const gitMode = useAppStore((s) => s.gitMode)
|
|
132
109
|
const currentSessionId = useAppStore((s) => s.currentSessionId)
|
|
133
110
|
const sessions = useAppStore((s) => s.sessions)
|
|
134
111
|
const focusMode = useAppStore((s) => s.focusMode)
|
|
135
|
-
const diffRef = useRef<
|
|
112
|
+
const diffRef = useRef<PierreDiffHandle | null>(null)
|
|
136
113
|
|
|
137
114
|
const currentSession = currentSessionId
|
|
138
115
|
? sessions.find((s) => s.id === currentSessionId)
|
|
@@ -141,22 +118,29 @@ export const GitView = memo(function GitView() {
|
|
|
141
118
|
|
|
142
119
|
useGitPanelPolling({ enabled: focusMode === 'git', projectPath })
|
|
143
120
|
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
const
|
|
121
|
+
const fileBarWidth = Math.max(20, Math.floor(dimensions.width * gitPane.diffModeRatio))
|
|
122
|
+
|
|
123
|
+
const selectedFile = getSelectedGitFile(gitPanel.files, {
|
|
124
|
+
collapsedFolders: gitMode.collapsedFolders,
|
|
125
|
+
fileListMode: gitPane.fileListMode,
|
|
126
|
+
selectedEntryKey: gitMode.selectedEntryKey,
|
|
127
|
+
})
|
|
128
|
+
const selectedDiffKey = selectedFile ? gitFileKey(selectedFile) : null
|
|
129
|
+
const diff = selectedDiffKey ? gitMode.diffs[selectedDiffKey] : undefined
|
|
130
|
+
const loading = selectedDiffKey ? !!gitMode.loading[selectedDiffKey] : false
|
|
147
131
|
|
|
148
132
|
useEffect(() => {
|
|
149
133
|
setGitDiffScroller((delta: number) => {
|
|
150
|
-
const node = diffRef.current
|
|
134
|
+
const node = diffRef.current
|
|
151
135
|
if (!node) return
|
|
152
|
-
const left = node.
|
|
153
|
-
const right = node.
|
|
154
|
-
if (!left
|
|
155
|
-
const cap = Math.max(left.
|
|
156
|
-
const base = left.
|
|
136
|
+
const left = node.leftScroll
|
|
137
|
+
const right = node.rightScroll
|
|
138
|
+
if (!left) return
|
|
139
|
+
const cap = Math.max(left.scrollHeight - left.viewport.height, 0)
|
|
140
|
+
const base = left.scrollTop
|
|
157
141
|
const nextScroll = Math.max(0, Math.min(cap, base + delta))
|
|
158
|
-
left.
|
|
159
|
-
right.
|
|
142
|
+
left.scrollTop = nextScroll
|
|
143
|
+
if (right && right !== left) right.scrollTop = nextScroll
|
|
160
144
|
})
|
|
161
145
|
return () => setGitDiffScroller(null)
|
|
162
146
|
}, [])
|
|
@@ -164,13 +148,15 @@ export const GitView = memo(function GitView() {
|
|
|
164
148
|
useEffect(() => {
|
|
165
149
|
if (focusMode !== 'git') return
|
|
166
150
|
if (!selectedFile || !projectPath) return
|
|
167
|
-
|
|
151
|
+
if (!selectedDiffKey) return
|
|
168
152
|
if (diff || loading) return
|
|
169
|
-
dispatchGlobal({ loading: true,
|
|
153
|
+
dispatchGlobal({ key: selectedDiffKey, loading: true, type: 'git-mode-set-loading' })
|
|
170
154
|
void fetchDiff(projectPath, selectedFile)
|
|
171
|
-
.then((d) => dispatchGlobal({ diff: d,
|
|
172
|
-
.catch(() =>
|
|
173
|
-
|
|
155
|
+
.then((d) => dispatchGlobal({ diff: d, key: selectedDiffKey, type: 'git-mode-set-diff' }))
|
|
156
|
+
.catch(() =>
|
|
157
|
+
dispatchGlobal({ key: selectedDiffKey, loading: false, type: 'git-mode-set-loading' })
|
|
158
|
+
)
|
|
159
|
+
}, [focusMode, projectPath, selectedFile, selectedDiffKey, diff, loading])
|
|
174
160
|
|
|
175
161
|
const pendingPath = gitMode.pendingDeletePath
|
|
176
162
|
const pendingIsUntracked =
|
|
@@ -178,7 +164,7 @@ export const GitView = memo(function GitView() {
|
|
|
178
164
|
selectedFile?.path === pendingPath &&
|
|
179
165
|
selectedFile.section === 'untracked'
|
|
180
166
|
let pendingHint: string | null = null
|
|
181
|
-
if (pendingPath !== null) {
|
|
167
|
+
if (pendingPath !== null && selectedFile) {
|
|
182
168
|
pendingHint = pendingIsUntracked
|
|
183
169
|
? 'press d again to delete file'
|
|
184
170
|
: 'press d again to discard changes'
|
|
@@ -187,13 +173,13 @@ export const GitView = memo(function GitView() {
|
|
|
187
173
|
let footerNode: React.ReactNode = null
|
|
188
174
|
if (pendingHint) {
|
|
189
175
|
footerNode = (
|
|
190
|
-
<text fg={theme.
|
|
176
|
+
<text fg={theme.colors['editorWarning.foreground']}>
|
|
191
177
|
<strong>{pendingHint}</strong>
|
|
192
178
|
</text>
|
|
193
179
|
)
|
|
194
180
|
} else if (actionMessage) {
|
|
195
181
|
footerNode = actionMessage.split('\n').map((line, idx) => (
|
|
196
|
-
<text key={idx} fg={theme.
|
|
182
|
+
<text key={idx} fg={theme.colors['textLink.foreground']}>
|
|
197
183
|
{line}
|
|
198
184
|
</text>
|
|
199
185
|
))
|
|
@@ -203,32 +189,48 @@ export const GitView = memo(function GitView() {
|
|
|
203
189
|
<box flexDirection="column" flexGrow={1}>
|
|
204
190
|
<box flexDirection="row" flexGrow={1}>
|
|
205
191
|
<box
|
|
206
|
-
width={
|
|
192
|
+
width={fileBarWidth}
|
|
207
193
|
flexDirection="column"
|
|
208
|
-
backgroundColor={theme.
|
|
194
|
+
backgroundColor={theme.colors['sideBar.background']}
|
|
209
195
|
padding={0}
|
|
210
196
|
gap={0}
|
|
211
197
|
>
|
|
212
|
-
<text fg={theme.
|
|
198
|
+
<text fg={theme.colors['textLink.foreground']}>
|
|
213
199
|
<strong>aimux · git</strong>
|
|
214
200
|
</text>
|
|
215
201
|
{gitPanel.branch ? (
|
|
216
202
|
<box flexDirection="row">
|
|
217
|
-
<text fg={theme.
|
|
218
|
-
<text fg={theme.
|
|
203
|
+
<text fg={theme.colors['textLink.foreground']}>{'\u{e702}'} </text>
|
|
204
|
+
<text fg={theme.colors['descriptionForeground']}>{gitPanel.branch}</text>
|
|
219
205
|
</box>
|
|
220
206
|
) : null}
|
|
221
|
-
<text fg={theme.
|
|
207
|
+
<text fg={theme.colors['editor.lineHighlightBackground']}>
|
|
208
|
+
{'·'.repeat(Math.max(0, fileBarWidth - 2))}
|
|
209
|
+
</text>
|
|
222
210
|
<GitPanel
|
|
211
|
+
collapsedFolders={gitMode.collapsedFolders}
|
|
212
|
+
fileListMode={gitPane.fileListMode}
|
|
223
213
|
gitPanel={gitPanel}
|
|
224
214
|
projectPath={projectPath}
|
|
225
|
-
|
|
215
|
+
selectedEntryKey={gitMode.selectedEntryKey}
|
|
226
216
|
/>
|
|
227
217
|
</box>
|
|
228
|
-
<DiffStage
|
|
218
|
+
<DiffStage
|
|
219
|
+
diff={diff}
|
|
220
|
+
diffKey={selectedDiffKey}
|
|
221
|
+
diffRef={diffRef}
|
|
222
|
+
loading={loading}
|
|
223
|
+
themeId={themeId}
|
|
224
|
+
view={gitMode.diffView}
|
|
225
|
+
/>
|
|
229
226
|
</box>
|
|
230
227
|
{footerNode ? (
|
|
231
|
-
<box
|
|
228
|
+
<box
|
|
229
|
+
paddingLeft={1}
|
|
230
|
+
paddingRight={1}
|
|
231
|
+
backgroundColor={theme.colors['sideBar.background']}
|
|
232
|
+
flexDirection="column"
|
|
233
|
+
>
|
|
232
234
|
{footerNode}
|
|
233
235
|
</box>
|
|
234
236
|
) : null}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import type { ModeId } from '@brimveyn/aimux-config'
|
|
2
|
+
|
|
1
3
|
import { useTerminalDimensions } from '@opentui/react'
|
|
2
4
|
import { useLayoutEffect, useMemo, useRef } from 'react'
|
|
3
5
|
|
|
4
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
collectHelpEntries,
|
|
8
|
+
HELP_MODE_LABELS,
|
|
9
|
+
type HelpEntry,
|
|
10
|
+
} from '../../input/keymap/help-entries'
|
|
5
11
|
import { dispatchGlobal } from '../../state/dispatch-ref'
|
|
6
12
|
import { useKeymap } from '../keymap-context'
|
|
7
13
|
import { theme } from '../theme'
|
|
@@ -12,6 +18,7 @@ import { ModalShell } from './modal-shell'
|
|
|
12
18
|
interface HelpModalProps {
|
|
13
19
|
filter: string | null
|
|
14
20
|
selectedIndex: number
|
|
21
|
+
scope: ModeId | null
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
function matchesFilter(entry: HelpEntry, needle: string): boolean {
|
|
@@ -78,14 +85,23 @@ function computeWindowStart(
|
|
|
78
85
|
return start
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
export function HelpModal({ filter, selectedIndex }: HelpModalProps) {
|
|
88
|
+
export function HelpModal({ filter, scope, selectedIndex }: HelpModalProps) {
|
|
82
89
|
const config = useKeymap()
|
|
83
90
|
const dimensions = useTerminalDimensions()
|
|
84
91
|
const allEntries = useMemo(() => collectHelpEntries(config), [config])
|
|
92
|
+
const scoped = useMemo(
|
|
93
|
+
() => (scope ? allEntries.filter((e) => e.mode === scope) : allEntries),
|
|
94
|
+
[allEntries, scope]
|
|
95
|
+
)
|
|
85
96
|
const filtered = useMemo(
|
|
86
|
-
() =>
|
|
87
|
-
[
|
|
97
|
+
() => scoped.filter((e) => matchesFilter(e, filter ?? '')),
|
|
98
|
+
[scoped, filter]
|
|
88
99
|
)
|
|
100
|
+
const title = useMemo(() => {
|
|
101
|
+
if (!scope) return 'Keybindings'
|
|
102
|
+
const label = HELP_MODE_LABELS.find((m) => m.modeId === scope)?.label ?? scope
|
|
103
|
+
return `${label} — keybindings`
|
|
104
|
+
}, [scope])
|
|
89
105
|
const rows = useMemo(() => buildRows(filtered), [filtered])
|
|
90
106
|
|
|
91
107
|
useLayoutEffect(() => {
|
|
@@ -113,12 +129,12 @@ export function HelpModal({ filter, selectedIndex }: HelpModalProps) {
|
|
|
113
129
|
|
|
114
130
|
return (
|
|
115
131
|
<ModalShell
|
|
116
|
-
title=
|
|
132
|
+
title={title}
|
|
117
133
|
keybindsModeId="modal.help"
|
|
118
134
|
width={uiTokens.modalWidth.lg}
|
|
119
135
|
footer={
|
|
120
136
|
<box flexDirection="column" gap={0}>
|
|
121
|
-
<text fg={theme.
|
|
137
|
+
<text fg={theme.colors['editor.lineHighlightBackground']}>
|
|
122
138
|
{filtered.length === 0
|
|
123
139
|
? ''
|
|
124
140
|
: ` ${effectiveIndex + 1} / ${filtered.length}${filter ? '' : ' — type / to filter'}`}
|
|
@@ -128,7 +144,7 @@ export function HelpModal({ filter, selectedIndex }: HelpModalProps) {
|
|
|
128
144
|
}
|
|
129
145
|
>
|
|
130
146
|
{filtered.length === 0 ? (
|
|
131
|
-
<text fg={theme.
|
|
147
|
+
<text fg={theme.colors['descriptionForeground']}>
|
|
132
148
|
{filter ? 'No matching bindings.' : 'No bindings registered.'}
|
|
133
149
|
</text>
|
|
134
150
|
) : (
|
|
@@ -138,14 +154,14 @@ export function HelpModal({ filter, selectedIndex }: HelpModalProps) {
|
|
|
138
154
|
if (row.kind === 'header') {
|
|
139
155
|
return (
|
|
140
156
|
<box key={`h-${rowIndex}`} paddingLeft={1} paddingTop={i === 0 ? 0 : 1}>
|
|
141
|
-
<text fg={theme.
|
|
157
|
+
<text fg={theme.colors['editorWarning.foreground']} wrapMode="none">
|
|
142
158
|
<strong>{row.label}</strong>
|
|
143
159
|
</text>
|
|
144
160
|
</box>
|
|
145
161
|
)
|
|
146
162
|
}
|
|
147
163
|
const active = row.entryIndex === effectiveIndex
|
|
148
|
-
const bg = active ? theme.
|
|
164
|
+
const bg = active ? theme.colors['list.activeSelectionBackground'] : undefined
|
|
149
165
|
return (
|
|
150
166
|
<box
|
|
151
167
|
key={`e-${rowIndex}`}
|
|
@@ -155,12 +171,28 @@ export function HelpModal({ filter, selectedIndex }: HelpModalProps) {
|
|
|
155
171
|
backgroundColor={bg}
|
|
156
172
|
>
|
|
157
173
|
<box width={KEYS_COLUMN_WIDTH} flexShrink={0}>
|
|
158
|
-
<text
|
|
174
|
+
<text
|
|
175
|
+
fg={
|
|
176
|
+
active
|
|
177
|
+
? theme.colors['textLink.foreground']
|
|
178
|
+
: theme.colors['terminal.ansiMagenta']
|
|
179
|
+
}
|
|
180
|
+
bg={bg}
|
|
181
|
+
wrapMode="none"
|
|
182
|
+
>
|
|
159
183
|
{row.entry.keysDisplay}
|
|
160
184
|
</text>
|
|
161
185
|
</box>
|
|
162
186
|
<box flexGrow={1} overflow="hidden">
|
|
163
|
-
<text
|
|
187
|
+
<text
|
|
188
|
+
fg={
|
|
189
|
+
active
|
|
190
|
+
? theme.colors['editor.foreground']
|
|
191
|
+
: theme.colors['descriptionForeground']
|
|
192
|
+
}
|
|
193
|
+
bg={bg}
|
|
194
|
+
wrapMode="none"
|
|
195
|
+
>
|
|
164
196
|
{row.entry.description ?? ''}
|
|
165
197
|
</text>
|
|
166
198
|
</box>
|
|
@@ -8,7 +8,7 @@ interface InputFieldProps {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function InputField({ active, cursorPos, value }: InputFieldProps) {
|
|
11
|
-
const fg = active ? theme.
|
|
11
|
+
const fg = active ? theme.colors['editor.foreground'] : theme.colors['descriptionForeground']
|
|
12
12
|
if (!active) {
|
|
13
13
|
return (
|
|
14
14
|
<Surface tone="input" padding={1}>
|
|
@@ -29,7 +29,7 @@ export function InputField({ active, cursorPos, value }: InputFieldProps) {
|
|
|
29
29
|
<Surface tone="inputActive" padding={1}>
|
|
30
30
|
<text fg={fg}>
|
|
31
31
|
{before}
|
|
32
|
-
<span bg={theme.
|
|
32
|
+
<span bg={theme.colors['editor.foreground']} fg={theme.colors['editor.background']}>
|
|
33
33
|
{cursorDisplay}
|
|
34
34
|
</span>
|
|
35
35
|
{trailing}
|
|
@@ -33,7 +33,15 @@ export function ListItem({
|
|
|
33
33
|
<box flexDirection="row">
|
|
34
34
|
{isRow ? null : (
|
|
35
35
|
<>
|
|
36
|
-
<text
|
|
36
|
+
<text
|
|
37
|
+
fg={
|
|
38
|
+
active
|
|
39
|
+
? theme.colors['textLink.foreground']
|
|
40
|
+
: theme.colors['editor.lineHighlightBackground']
|
|
41
|
+
}
|
|
42
|
+
>
|
|
43
|
+
{active ? '›' : '·'}
|
|
44
|
+
</text>
|
|
37
45
|
<text> </text>
|
|
38
46
|
</>
|
|
39
47
|
)}
|
|
@@ -12,7 +12,7 @@ export function ModalFilterBar({ filter }: ModalFilterBarProps) {
|
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<Surface tone="input" paddingLeft={1} paddingRight={1} paddingTop={1} paddingBottom={1}>
|
|
15
|
-
<text fg={theme.
|
|
15
|
+
<text fg={theme.colors['editor.foreground']}>/{filter}_</text>
|
|
16
16
|
</Surface>
|
|
17
17
|
)
|
|
18
18
|
}
|
|
@@ -28,9 +28,9 @@ export function ModalKeybindsOverlay({ limit, modeId }: ModalKeybindsOverlayProp
|
|
|
28
28
|
{entries.map((binding) => (
|
|
29
29
|
<box key={`${binding.keys}-${binding.description}`} flexDirection="row">
|
|
30
30
|
<box width={KEYS_COLUMN_WIDTH}>
|
|
31
|
-
<text fg={theme.
|
|
31
|
+
<text fg={theme.colors['terminal.ansiMagenta']}>{binding.keysDisplay}</text>
|
|
32
32
|
</box>
|
|
33
|
-
<text fg={theme.
|
|
33
|
+
<text fg={theme.colors['descriptionForeground']}>{binding.description ?? ''}</text>
|
|
34
34
|
</box>
|
|
35
35
|
))}
|
|
36
36
|
</Surface>
|
|
@@ -40,14 +40,14 @@ export function ModalShell({
|
|
|
40
40
|
left={0}
|
|
41
41
|
width="100%"
|
|
42
42
|
height="100%"
|
|
43
|
-
backgroundColor={theme.
|
|
43
|
+
backgroundColor={theme.colors['editorWidget.background']}
|
|
44
44
|
opacity={0.7}
|
|
45
45
|
/>
|
|
46
46
|
<Surface tone="elevated" padding={1} gap={1} width={width}>
|
|
47
47
|
<box width="100%" flexDirection="column" gap={listGap}>
|
|
48
48
|
<box flexDirection="column">
|
|
49
|
-
<text fg={theme.
|
|
50
|
-
{subtitle ? <text fg={theme.
|
|
49
|
+
<text fg={theme.colors['terminal.ansiMagenta']}>{title}</text>
|
|
50
|
+
{subtitle ? <text fg={theme.colors['descriptionForeground']}>{subtitle}</text> : null}
|
|
51
51
|
</box>
|
|
52
52
|
{children}
|
|
53
53
|
{footer ? <box>{footer}</box> : null}
|
|
@@ -34,11 +34,23 @@ export function NewTabModal({ customCommands, editBuffer, selectedIndex }: NewTa
|
|
|
34
34
|
<ListItem
|
|
35
35
|
key={option.id}
|
|
36
36
|
active={active}
|
|
37
|
-
title={
|
|
37
|
+
title={
|
|
38
|
+
<text
|
|
39
|
+
fg={
|
|
40
|
+
active
|
|
41
|
+
? theme.colors['editor.foreground']
|
|
42
|
+
: theme.colors['descriptionForeground']
|
|
43
|
+
}
|
|
44
|
+
>
|
|
45
|
+
{option.label}
|
|
46
|
+
</text>
|
|
47
|
+
}
|
|
38
48
|
subtitle={
|
|
39
49
|
<box flexDirection="column">
|
|
40
|
-
<text fg={theme.
|
|
41
|
-
{customCmd ?
|
|
50
|
+
<text fg={theme.colors['descriptionForeground']}>{option.description}</text>
|
|
51
|
+
{customCmd ? (
|
|
52
|
+
<text fg={theme.colors['textLink.foreground']}>{customCmd}</text>
|
|
53
|
+
) : null}
|
|
42
54
|
</box>
|
|
43
55
|
}
|
|
44
56
|
/>
|
|
@@ -19,9 +19,9 @@ export function PendingChordOverlay() {
|
|
|
19
19
|
<box position="absolute" bottom={modalOpen ? 10 : 2} right={1}>
|
|
20
20
|
<Surface tone="elevated" paddingLeft={1} paddingRight={1}>
|
|
21
21
|
<box flexDirection="row">
|
|
22
|
-
<text fg={theme.
|
|
23
|
-
<text fg={theme.
|
|
24
|
-
<text fg={theme.
|
|
22
|
+
<text fg={theme.colors['descriptionForeground']}>pending: </text>
|
|
23
|
+
<text fg={theme.colors['textLink.foreground']}>{display}</text>
|
|
24
|
+
<text fg={theme.colors['descriptionForeground']}> …</text>
|
|
25
25
|
</box>
|
|
26
26
|
</Surface>
|
|
27
27
|
</box>
|
|
@@ -108,7 +108,7 @@ export function SessionBar() {
|
|
|
108
108
|
flexDirection="row"
|
|
109
109
|
paddingLeft={1}
|
|
110
110
|
paddingRight={1}
|
|
111
|
-
backgroundColor={theme.
|
|
111
|
+
backgroundColor={theme.colors['sideBarSectionHeader.background']}
|
|
112
112
|
>
|
|
113
113
|
{visibleSessions.map((session) => {
|
|
114
114
|
const displayIndex = baselineOrder.indexOf(session.id) + 1
|
|
@@ -168,9 +168,14 @@ function SessionChip({
|
|
|
168
168
|
const showSpinner = busy && !active
|
|
169
169
|
const spinner = useBusySpinner(showSpinner)
|
|
170
170
|
const indicator = showSpinner ? spinner : '●'
|
|
171
|
-
const indicatorColor =
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
const indicatorColor =
|
|
172
|
+
active || showSpinner
|
|
173
|
+
? theme.colors['textLink.foreground']
|
|
174
|
+
: theme.colors['gitDecoration.addedResourceForeground']
|
|
175
|
+
const labelColor = active
|
|
176
|
+
? theme.colors['editor.foreground']
|
|
177
|
+
: theme.colors['descriptionForeground']
|
|
178
|
+
const bgColor = dragging || active ? theme.colors['list.activeSelectionBackground'] : undefined
|
|
174
179
|
|
|
175
180
|
return (
|
|
176
181
|
<box
|
|
@@ -200,7 +205,7 @@ function SessionChip({
|
|
|
200
205
|
<text fg={labelColor} selectable={false}>
|
|
201
206
|
[{index}] {session.name}
|
|
202
207
|
</text>
|
|
203
|
-
<text fg={theme.
|
|
208
|
+
<text fg={theme.colors['editor.lineHighlightBackground']} selectable={false}>
|
|
204
209
|
{' '}
|
|
205
210
|
</text>
|
|
206
211
|
</box>
|