@brimveyn/aimux 1.6.0 → 1.6.1
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/package.json +2 -2
- package/src/git/git-diff.ts +24 -12
- package/src/git/git-poller.ts +11 -3
- package/src/git/git-status.ts +98 -17
- package/src/pty/terminal-snapshot.ts +5 -5
- package/src/state/git-tree.ts +1 -1
- package/src/state/reducers/git-mode-state.ts +44 -1
- package/src/state/reducers/git-panel-state.ts +6 -1
- package/src/state/types.ts +5 -1
- package/src/ui/components/create-session-modal.tsx +5 -4
- package/src/ui/components/diff-renderer/fold-strip.tsx +3 -1
- package/src/ui/components/diff-renderer/pierre-diff.tsx +2 -1
- package/src/ui/components/diff-renderer/split-view.tsx +5 -1
- package/src/ui/components/diff-renderer/stacked-view.tsx +3 -1
- package/src/ui/components/git-commit-modal.tsx +2 -1
- package/src/ui/components/git-pane-widget.tsx +1 -1
- package/src/ui/components/git-panel.tsx +77 -45
- package/src/ui/components/git-view.tsx +15 -4
- package/src/ui/components/help-modal.tsx +2 -1
- package/src/ui/components/input-field.tsx +2 -1
- package/src/ui/components/list-item.tsx +2 -1
- package/src/ui/components/modal-filter-bar.tsx +2 -1
- package/src/ui/components/modal-keybinds-overlay.tsx +2 -1
- package/src/ui/components/modal-shell.tsx +2 -1
- package/src/ui/components/new-tab-modal.tsx +2 -1
- package/src/ui/components/pending-chord-overlay.tsx +2 -1
- package/src/ui/components/session-bar.tsx +3 -1
- package/src/ui/components/session-picker-modal.tsx +2 -1
- package/src/ui/components/sidebar.tsx +8 -5
- package/src/ui/components/snippet-editor-modal.tsx +2 -1
- package/src/ui/components/snippet-picker-modal.tsx +2 -1
- package/src/ui/components/split-layout.tsx +2 -1
- package/src/ui/components/status-bar.tsx +8 -6
- package/src/ui/components/surface.tsx +6 -6
- package/src/ui/components/tab-item.tsx +14 -9
- package/src/ui/components/terminal-pane.tsx +7 -5
- package/src/ui/components/theme-picker-modal.tsx +2 -1
- package/src/ui/components/update-available-modal.tsx +2 -1
- package/src/ui/filter-themes.ts +7 -2
- package/src/ui/root.tsx +3 -1
- package/src/ui/status-bar-model.ts +13 -3
- package/src/ui/theme-store.ts +36 -0
- package/src/ui/theme.ts +4 -29
- package/src/ui/themes.ts +15 -63
- package/src/ui/house-themes.ts +0 -313
- package/src/ui/themes.generated.ts +0 -59794
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
|
|
14
14
|
import { dispatchGlobal, runSideEffectGlobal } from '../../state/dispatch-ref'
|
|
15
15
|
import { buildGitTreeRows, type GitTreeFileRow, type GitTreeFolderRow } from '../../state/git-tree'
|
|
16
|
-
import {
|
|
16
|
+
import { getCurrentTheme, useTheme } from '../theme'
|
|
17
17
|
|
|
18
18
|
interface GitPanelProps {
|
|
19
19
|
collapsedFolders?: Record<string, true>
|
|
@@ -23,22 +23,40 @@ interface GitPanelProps {
|
|
|
23
23
|
selectedEntryKey?: string | null
|
|
24
24
|
pathConfig?: GitPanePathConfig
|
|
25
25
|
diffCountConfig?: GitPaneDiffCountConfig
|
|
26
|
+
headOffset?: number
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
function sectionTitle(section: GitFileSection, headOffset: number): string {
|
|
30
|
+
switch (section) {
|
|
31
|
+
case 'historical':
|
|
32
|
+
return `HEAD~${headOffset}`
|
|
33
|
+
case 'staged':
|
|
34
|
+
return 'Staged Changes'
|
|
35
|
+
case 'unstaged':
|
|
36
|
+
return 'Changes'
|
|
37
|
+
case 'untracked':
|
|
38
|
+
return 'Untracked'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const BASE_SECTION_ORDER: GitFileSection[] = ['staged', 'unstaged', 'untracked']
|
|
43
|
+
const HISTORICAL_SECTION_ORDER: GitFileSection[] = ['historical', 'untracked']
|
|
33
44
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
function statusColor(status: GitFileEntry['status']): string {
|
|
46
|
+
const t = getCurrentTheme()
|
|
47
|
+
switch (status) {
|
|
48
|
+
case '?':
|
|
49
|
+
case 'A':
|
|
50
|
+
return t.colors['gitDecoration.addedResourceForeground']
|
|
51
|
+
case 'C':
|
|
52
|
+
case 'R':
|
|
53
|
+
return t.colors['textLink.foreground']
|
|
54
|
+
case 'D':
|
|
55
|
+
case 'U':
|
|
56
|
+
return t.colors['editorError.foreground']
|
|
57
|
+
case 'M':
|
|
58
|
+
return t.colors['editorWarning.foreground']
|
|
59
|
+
}
|
|
42
60
|
}
|
|
43
61
|
|
|
44
62
|
function displayStatus(file: GitFileEntry): string {
|
|
@@ -83,8 +101,10 @@ function renderFileLabel(
|
|
|
83
101
|
if (!file.renamedFrom) {
|
|
84
102
|
return (
|
|
85
103
|
<text wrapMode="none">
|
|
86
|
-
<span fg={
|
|
87
|
-
{showDir ?
|
|
104
|
+
<span fg={getCurrentTheme().colors['editor.foreground']}>{basename}</span>
|
|
105
|
+
{showDir ? (
|
|
106
|
+
<span fg={getCurrentTheme().colors['descriptionForeground']}> {dir}</span>
|
|
107
|
+
) : null}
|
|
88
108
|
</text>
|
|
89
109
|
)
|
|
90
110
|
}
|
|
@@ -93,13 +113,13 @@ function renderFileLabel(
|
|
|
93
113
|
const renamedDir = stripTrailingSlash(renamed.prefix)
|
|
94
114
|
return (
|
|
95
115
|
<text wrapMode="none">
|
|
96
|
-
<span fg={
|
|
116
|
+
<span fg={getCurrentTheme().colors['descriptionForeground']}>{renamed.basename}</span>
|
|
97
117
|
{showDir && renamedDir ? (
|
|
98
|
-
<span fg={
|
|
118
|
+
<span fg={getCurrentTheme().colors['descriptionForeground']}> {renamedDir}</span>
|
|
99
119
|
) : null}
|
|
100
|
-
<span fg={
|
|
101
|
-
<span fg={
|
|
102
|
-
{showDir ? <span fg={
|
|
120
|
+
<span fg={getCurrentTheme().colors['descriptionForeground']}> → </span>
|
|
121
|
+
<span fg={getCurrentTheme().colors['editor.foreground']}>{basename}</span>
|
|
122
|
+
{showDir ? <span fg={getCurrentTheme().colors['descriptionForeground']}> {dir}</span> : null}
|
|
103
123
|
</text>
|
|
104
124
|
)
|
|
105
125
|
}
|
|
@@ -115,7 +135,7 @@ function renderDiffCount(
|
|
|
115
135
|
if (!diffCountConfig.enabled) return null
|
|
116
136
|
if (!hasNumstat) {
|
|
117
137
|
return (
|
|
118
|
-
<text fg={
|
|
138
|
+
<text fg={getCurrentTheme().colors['descriptionForeground']} bg={bg} flexShrink={0}>
|
|
119
139
|
—
|
|
120
140
|
</text>
|
|
121
141
|
)
|
|
@@ -123,14 +143,14 @@ function renderDiffCount(
|
|
|
123
143
|
return (
|
|
124
144
|
<box flexDirection="row" flexShrink={0}>
|
|
125
145
|
<text
|
|
126
|
-
fg={
|
|
146
|
+
fg={getCurrentTheme().colors['gitDecoration.addedResourceForeground']}
|
|
127
147
|
bg={bg}
|
|
128
148
|
>{`+${padRight(file.added, addedW)}`}</text>
|
|
129
|
-
<text fg={
|
|
149
|
+
<text fg={getCurrentTheme().colors['editor.lineHighlightBackground']} bg={bg}>
|
|
130
150
|
{' '}
|
|
131
151
|
</text>
|
|
132
152
|
<text
|
|
133
|
-
fg={
|
|
153
|
+
fg={getCurrentTheme().colors['editorError.foreground']}
|
|
134
154
|
bg={bg}
|
|
135
155
|
>{`−${padRight(file.removed, removedW)}`}</text>
|
|
136
156
|
</box>
|
|
@@ -138,7 +158,7 @@ function renderDiffCount(
|
|
|
138
158
|
}
|
|
139
159
|
|
|
140
160
|
function renderFolderRow(row: GitTreeFolderRow, isSelected: boolean): ReactNode {
|
|
141
|
-
const bg = isSelected ?
|
|
161
|
+
const bg = isSelected ? getCurrentTheme().colors['list.activeSelectionBackground'] : undefined
|
|
142
162
|
const onSelect = (): void => {
|
|
143
163
|
dispatchGlobal({ key: row.key, type: 'git-mode-select-entry-by-key' })
|
|
144
164
|
}
|
|
@@ -149,10 +169,10 @@ function renderFolderRow(row: GitTreeFolderRow, isSelected: boolean): ReactNode
|
|
|
149
169
|
<box key={row.key} flexDirection="row" gap={1} backgroundColor={bg} onMouseDown={onSelect}>
|
|
150
170
|
<box flexGrow={1} overflow="hidden" paddingLeft={row.depth * 2}>
|
|
151
171
|
<box flexDirection="row" gap={1} onMouseDown={onToggle}>
|
|
152
|
-
<text fg={
|
|
172
|
+
<text fg={getCurrentTheme().colors['descriptionForeground']} bg={bg}>
|
|
153
173
|
{row.isCollapsed ? '▸' : '▾'}
|
|
154
174
|
</text>
|
|
155
|
-
<text fg={
|
|
175
|
+
<text fg={getCurrentTheme().colors['terminal.ansiMagenta']} bg={bg} wrapMode="none">
|
|
156
176
|
{row.name}
|
|
157
177
|
</text>
|
|
158
178
|
</box>
|
|
@@ -172,14 +192,14 @@ function renderFileRow(
|
|
|
172
192
|
): ReactNode {
|
|
173
193
|
const file = row.file
|
|
174
194
|
const hasNumstat = file.added !== null || file.removed !== null
|
|
175
|
-
const bg = isSelected ?
|
|
195
|
+
const bg = isSelected ? getCurrentTheme().colors['list.activeSelectionBackground'] : undefined
|
|
176
196
|
const onSelect = (): void => {
|
|
177
197
|
dispatchGlobal({ key: row.key, type: 'git-mode-select-entry-by-key' })
|
|
178
198
|
}
|
|
179
199
|
return (
|
|
180
200
|
<box key={row.key} flexDirection="row" gap={1} backgroundColor={bg} onMouseDown={onSelect}>
|
|
181
201
|
<box width={2} flexShrink={0} justifyContent="center">
|
|
182
|
-
<text fg={
|
|
202
|
+
<text fg={statusColor(file.status)} bg={bg}>
|
|
183
203
|
<strong>{displayStatus(file)}</strong>
|
|
184
204
|
</text>
|
|
185
205
|
</box>
|
|
@@ -213,7 +233,7 @@ function renderTreeSection(
|
|
|
213
233
|
return (
|
|
214
234
|
<box key={section} flexDirection="column">
|
|
215
235
|
<box flexDirection="row" justifyContent="space-between">
|
|
216
|
-
<text fg={
|
|
236
|
+
<text fg={getCurrentTheme().colors['terminal.ansiMagenta']}>
|
|
217
237
|
<strong>
|
|
218
238
|
{title} ({files.length})
|
|
219
239
|
</strong>
|
|
@@ -223,18 +243,18 @@ function renderTreeSection(
|
|
|
223
243
|
<text
|
|
224
244
|
fg={
|
|
225
245
|
fileListMode === 'tree'
|
|
226
|
-
?
|
|
227
|
-
:
|
|
246
|
+
? getCurrentTheme().colors['textLink.foreground']
|
|
247
|
+
: getCurrentTheme().colors['descriptionForeground']
|
|
228
248
|
}
|
|
229
249
|
>
|
|
230
250
|
tree
|
|
231
251
|
</text>
|
|
232
|
-
<text fg={
|
|
252
|
+
<text fg={getCurrentTheme().colors['descriptionForeground']}>|</text>
|
|
233
253
|
<text
|
|
234
254
|
fg={
|
|
235
255
|
fileListMode === 'flat'
|
|
236
|
-
?
|
|
237
|
-
:
|
|
256
|
+
? getCurrentTheme().colors['textLink.foreground']
|
|
257
|
+
: getCurrentTheme().colors['descriptionForeground']
|
|
238
258
|
}
|
|
239
259
|
>
|
|
240
260
|
flat
|
|
@@ -279,16 +299,25 @@ function computeStatusPlaceholder(
|
|
|
279
299
|
hasProjectPath: boolean
|
|
280
300
|
): StatusPlaceholder | null {
|
|
281
301
|
if (!hasProjectPath) {
|
|
282
|
-
return {
|
|
302
|
+
return {
|
|
303
|
+
label: 'No active session',
|
|
304
|
+
labelColor: getCurrentTheme().colors['descriptionForeground'],
|
|
305
|
+
}
|
|
283
306
|
}
|
|
284
307
|
if (gitPanel.error === 'not-a-repo') {
|
|
285
|
-
return {
|
|
308
|
+
return {
|
|
309
|
+
label: 'Not a git repository',
|
|
310
|
+
labelColor: getCurrentTheme().colors['descriptionForeground'],
|
|
311
|
+
}
|
|
286
312
|
}
|
|
287
313
|
if (gitPanel.error === 'unknown') {
|
|
288
|
-
return { label: 'Git error', labelColor:
|
|
314
|
+
return { label: 'Git error', labelColor: getCurrentTheme().colors['editorError.foreground'] }
|
|
289
315
|
}
|
|
290
316
|
if (gitPanel.files.length === 0) {
|
|
291
|
-
return {
|
|
317
|
+
return {
|
|
318
|
+
label: 'Working tree clean',
|
|
319
|
+
labelColor: getCurrentTheme().colors['descriptionForeground'],
|
|
320
|
+
}
|
|
292
321
|
}
|
|
293
322
|
return null
|
|
294
323
|
}
|
|
@@ -301,10 +330,13 @@ export const GitPanel = memo(function GitPanel({
|
|
|
301
330
|
diffCountConfig = DEFAULT_DIFF_COUNT_CONFIG,
|
|
302
331
|
fileListMode = 'tree',
|
|
303
332
|
gitPanel,
|
|
333
|
+
headOffset = 0,
|
|
304
334
|
pathConfig = DEFAULT_PATH_CONFIG,
|
|
305
335
|
projectPath,
|
|
306
336
|
selectedEntryKey,
|
|
307
337
|
}: GitPanelProps) {
|
|
338
|
+
const theme = useTheme()
|
|
339
|
+
const sectionOrder = headOffset > 0 ? HISTORICAL_SECTION_ORDER : BASE_SECTION_ORDER
|
|
308
340
|
const scrollRef = useRef<ScrollBoxRenderable | null>(null)
|
|
309
341
|
const tree = useMemo(
|
|
310
342
|
() => buildGitTreeRows(gitPanel.files, collapsedFolders, fileListMode),
|
|
@@ -350,18 +382,18 @@ export const GitPanel = memo(function GitPanel({
|
|
|
350
382
|
viewportCulling
|
|
351
383
|
contentOptions={{ flexDirection: 'column', gap: 0 }}
|
|
352
384
|
>
|
|
353
|
-
{
|
|
354
|
-
const section = tree.sections.find((entry) => entry.section ===
|
|
385
|
+
{sectionOrder.map((key) => {
|
|
386
|
+
const section = tree.sections.find((entry) => entry.section === key)
|
|
355
387
|
return renderTreeSection(
|
|
356
|
-
|
|
357
|
-
|
|
388
|
+
key,
|
|
389
|
+
sectionTitle(key, headOffset),
|
|
358
390
|
section?.files ?? [],
|
|
359
391
|
section?.rows ?? [],
|
|
360
392
|
addedW,
|
|
361
393
|
removedW,
|
|
362
394
|
fileListMode,
|
|
363
395
|
selectedEntryKey,
|
|
364
|
-
|
|
396
|
+
key === toggleSection,
|
|
365
397
|
pathConfig,
|
|
366
398
|
diffCountConfig
|
|
367
399
|
)
|
|
@@ -10,7 +10,7 @@ import { useAppStore } from '../../state/app-store'
|
|
|
10
10
|
import { dispatchGlobal } from '../../state/dispatch-ref'
|
|
11
11
|
import { getSelectedGitFile, gitFileKey } from '../../state/git-tree'
|
|
12
12
|
import { setGitDiffScroller } from '../git-view-controls'
|
|
13
|
-
import {
|
|
13
|
+
import { useTheme } from '../theme'
|
|
14
14
|
import { PierreDiff, type PierreDiffHandle } from './diff-renderer'
|
|
15
15
|
import { GitPanel } from './git-panel'
|
|
16
16
|
|
|
@@ -45,6 +45,7 @@ const DiffStage = memo(function DiffStage({
|
|
|
45
45
|
themeId,
|
|
46
46
|
view,
|
|
47
47
|
}: DiffStageProps) {
|
|
48
|
+
const theme = useTheme()
|
|
48
49
|
if (loading && !diff) {
|
|
49
50
|
return (
|
|
50
51
|
<box flexGrow={1} padding={1}>
|
|
@@ -102,6 +103,7 @@ interface GitViewProps {
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
export const GitView = memo(function GitView({ themeId }: GitViewProps) {
|
|
106
|
+
const theme = useTheme()
|
|
105
107
|
const dimensions = useTerminalDimensions()
|
|
106
108
|
const gitPane = useAppStore((s) => s.gitPane)
|
|
107
109
|
const gitPanel = useAppStore((s) => s.gitPanel)
|
|
@@ -116,7 +118,7 @@ export const GitView = memo(function GitView({ themeId }: GitViewProps) {
|
|
|
116
118
|
: undefined
|
|
117
119
|
const projectPath = currentSession?.projectPath
|
|
118
120
|
|
|
119
|
-
useGitPanelPolling({ enabled: focusMode === 'git', projectPath })
|
|
121
|
+
useGitPanelPolling({ enabled: focusMode === 'git', headOffset: gitMode.headOffset, projectPath })
|
|
120
122
|
|
|
121
123
|
const fileBarWidth = Math.max(20, Math.floor(dimensions.width * gitPane.diffModeRatio))
|
|
122
124
|
|
|
@@ -151,12 +153,12 @@ export const GitView = memo(function GitView({ themeId }: GitViewProps) {
|
|
|
151
153
|
if (!selectedDiffKey) return
|
|
152
154
|
if (diff || loading) return
|
|
153
155
|
dispatchGlobal({ key: selectedDiffKey, loading: true, type: 'git-mode-set-loading' })
|
|
154
|
-
void fetchDiff(projectPath, selectedFile)
|
|
156
|
+
void fetchDiff(projectPath, selectedFile, gitMode.headOffset)
|
|
155
157
|
.then((d) => dispatchGlobal({ diff: d, key: selectedDiffKey, type: 'git-mode-set-diff' }))
|
|
156
158
|
.catch(() =>
|
|
157
159
|
dispatchGlobal({ key: selectedDiffKey, loading: false, type: 'git-mode-set-loading' })
|
|
158
160
|
)
|
|
159
|
-
}, [focusMode, projectPath, selectedFile, selectedDiffKey, diff, loading])
|
|
161
|
+
}, [focusMode, projectPath, selectedFile, selectedDiffKey, diff, loading, gitMode.headOffset])
|
|
160
162
|
|
|
161
163
|
const pendingPath = gitMode.pendingDeletePath
|
|
162
164
|
const pendingIsUntracked =
|
|
@@ -204,6 +206,14 @@ export const GitView = memo(function GitView({ themeId }: GitViewProps) {
|
|
|
204
206
|
<text fg={theme.colors['descriptionForeground']}>{gitPanel.branch}</text>
|
|
205
207
|
</box>
|
|
206
208
|
) : null}
|
|
209
|
+
{gitMode.headOffset > 0 ? (
|
|
210
|
+
<box flexDirection="row" gap={1}>
|
|
211
|
+
<text fg={theme.colors['editorWarning.foreground']}>
|
|
212
|
+
<strong>HEAD~{gitMode.headOffset}</strong>
|
|
213
|
+
</text>
|
|
214
|
+
<text fg={theme.colors['descriptionForeground']}>[ newer · ] older</text>
|
|
215
|
+
</box>
|
|
216
|
+
) : null}
|
|
207
217
|
<text fg={theme.colors['editor.lineHighlightBackground']}>
|
|
208
218
|
{'·'.repeat(Math.max(0, fileBarWidth - 2))}
|
|
209
219
|
</text>
|
|
@@ -211,6 +221,7 @@ export const GitView = memo(function GitView({ themeId }: GitViewProps) {
|
|
|
211
221
|
collapsedFolders={gitMode.collapsedFolders}
|
|
212
222
|
fileListMode={gitPane.fileListMode}
|
|
213
223
|
gitPanel={gitPanel}
|
|
224
|
+
headOffset={gitMode.headOffset}
|
|
214
225
|
projectPath={projectPath}
|
|
215
226
|
selectedEntryKey={gitMode.selectedEntryKey}
|
|
216
227
|
/>
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '../../input/keymap/help-entries'
|
|
11
11
|
import { dispatchGlobal } from '../../state/dispatch-ref'
|
|
12
12
|
import { useKeymap } from '../keymap-context'
|
|
13
|
-
import {
|
|
13
|
+
import { useTheme } from '../theme'
|
|
14
14
|
import { uiTokens } from '../ui-tokens'
|
|
15
15
|
import { ModalFilterBar } from './modal-filter-bar'
|
|
16
16
|
import { ModalShell } from './modal-shell'
|
|
@@ -86,6 +86,7 @@ function computeWindowStart(
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
export function HelpModal({ filter, scope, selectedIndex }: HelpModalProps) {
|
|
89
|
+
const theme = useTheme()
|
|
89
90
|
const config = useKeymap()
|
|
90
91
|
const dimensions = useTerminalDimensions()
|
|
91
92
|
const allEntries = useMemo(() => collectHelpEntries(config), [config])
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useTheme } from '../theme'
|
|
2
2
|
import { Surface } from './surface'
|
|
3
3
|
|
|
4
4
|
interface InputFieldProps {
|
|
@@ -8,6 +8,7 @@ interface InputFieldProps {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function InputField({ active, cursorPos, value }: InputFieldProps) {
|
|
11
|
+
const theme = useTheme()
|
|
11
12
|
const fg = active ? theme.colors['editor.foreground'] : theme.colors['descriptionForeground']
|
|
12
13
|
if (!active) {
|
|
13
14
|
return (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useTheme } from '../theme'
|
|
4
4
|
import { Surface } from './surface'
|
|
5
5
|
|
|
6
6
|
export type ListItemDirection = 'row' | 'column'
|
|
@@ -22,6 +22,7 @@ export function ListItem({
|
|
|
22
22
|
title,
|
|
23
23
|
trailing,
|
|
24
24
|
}: ListItemProps) {
|
|
25
|
+
const theme = useTheme()
|
|
25
26
|
const isRow = direction === 'row'
|
|
26
27
|
return (
|
|
27
28
|
<Surface
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useTheme } from '../theme'
|
|
2
2
|
import { Surface } from './surface'
|
|
3
3
|
|
|
4
4
|
interface ModalFilterBarProps {
|
|
@@ -6,6 +6,7 @@ interface ModalFilterBarProps {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function ModalFilterBar({ filter }: ModalFilterBarProps) {
|
|
9
|
+
const theme = useTheme()
|
|
9
10
|
if (filter === null) {
|
|
10
11
|
return null
|
|
11
12
|
}
|
|
@@ -2,7 +2,7 @@ import type { ModeId } from '@brimveyn/aimux-config'
|
|
|
2
2
|
|
|
3
3
|
import { describeBindings } from '../../input/keymap/describe-bindings'
|
|
4
4
|
import { useKeymap } from '../keymap-context'
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from '../theme'
|
|
6
6
|
import { Surface } from './surface'
|
|
7
7
|
|
|
8
8
|
const KEYS_COLUMN_WIDTH = 12
|
|
@@ -13,6 +13,7 @@ interface ModalKeybindsOverlayProps {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function ModalKeybindsOverlay({ limit, modeId }: ModalKeybindsOverlayProps) {
|
|
16
|
+
const theme = useTheme()
|
|
16
17
|
const config = useKeymap()
|
|
17
18
|
const bindings = describeBindings(config, modeId, {
|
|
18
19
|
dedupeByDescription: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ModeId } from '@brimveyn/aimux-config'
|
|
2
2
|
import type { ReactNode } from 'react'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { useTheme } from '../theme'
|
|
5
5
|
import { ModalKeybindsOverlay } from './modal-keybinds-overlay'
|
|
6
6
|
import { Surface } from './surface'
|
|
7
7
|
|
|
@@ -24,6 +24,7 @@ export function ModalShell({
|
|
|
24
24
|
title,
|
|
25
25
|
width,
|
|
26
26
|
}: ModalShellProps) {
|
|
27
|
+
const theme = useTheme()
|
|
27
28
|
return (
|
|
28
29
|
<box
|
|
29
30
|
position="absolute"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getAllAssistantOptions } from '../../pty/command-registry'
|
|
2
|
-
import {
|
|
2
|
+
import { useTheme } from '../theme'
|
|
3
3
|
import { uiTokens } from '../ui-tokens'
|
|
4
4
|
import { InputField } from './input-field'
|
|
5
5
|
import { ListItem } from './list-item'
|
|
@@ -12,6 +12,7 @@ interface NewTabModalProps {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function NewTabModal({ customCommands, editBuffer, selectedIndex }: NewTabModalProps) {
|
|
15
|
+
const theme = useTheme()
|
|
15
16
|
const options = getAllAssistantOptions(customCommands)
|
|
16
17
|
const selectedOption = options[selectedIndex]
|
|
17
18
|
const isEditing = editBuffer !== null
|
|
@@ -2,10 +2,11 @@ import { parseKeyNotation } from '../../input/keymap/key-chord'
|
|
|
2
2
|
import { formatChord } from '../../input/keymap/key-format'
|
|
3
3
|
import { useAppStore } from '../../state/app-store'
|
|
4
4
|
import { useKeymap } from '../keymap-context'
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from '../theme'
|
|
6
6
|
import { Surface } from './surface'
|
|
7
7
|
|
|
8
8
|
export function PendingChordOverlay() {
|
|
9
|
+
const theme = useTheme()
|
|
9
10
|
const pendingChords = useAppStore((s) => s.pendingChords)
|
|
10
11
|
const modalOpen = useAppStore((s) => s.modal.type !== null)
|
|
11
12
|
const config = useKeymap()
|
|
@@ -8,9 +8,10 @@ import { useAppStore } from '../../state/app-store'
|
|
|
8
8
|
import { dispatchGlobal, runSideEffectGlobal } from '../../state/dispatch-ref'
|
|
9
9
|
import { useBusySpinner } from '../hooks/use-busy-spinner'
|
|
10
10
|
import { moveIdToIdPosition, orderSessionsForDisplay } from '../session-ordering'
|
|
11
|
-
import {
|
|
11
|
+
import { useTheme } from '../theme'
|
|
12
12
|
|
|
13
13
|
export function SessionBar() {
|
|
14
|
+
const theme = useTheme()
|
|
14
15
|
const sessions = useAppStore((s) => s.sessions)
|
|
15
16
|
const currentId = useAppStore((s) => s.currentSessionId)
|
|
16
17
|
const bar = useAppStore((s) => s.sessionBar)
|
|
@@ -165,6 +166,7 @@ function SessionChip({
|
|
|
165
166
|
onRef,
|
|
166
167
|
session,
|
|
167
168
|
}: SessionChipProps) {
|
|
169
|
+
const theme = useTheme()
|
|
168
170
|
const showSpinner = busy && !active
|
|
169
171
|
const spinner = useBusySpinner(showSpinner)
|
|
170
172
|
const indicator = showSpinner ? spinner : '●'
|
|
@@ -3,7 +3,7 @@ import type { SessionRecord } from '../../state/types'
|
|
|
3
3
|
import { filterSessions } from '../../state/selectors'
|
|
4
4
|
import { abbreviatePath } from '../path-format'
|
|
5
5
|
import { orderSessionsForDisplay } from '../session-ordering'
|
|
6
|
-
import {
|
|
6
|
+
import { useTheme } from '../theme'
|
|
7
7
|
import { uiTokens } from '../ui-tokens'
|
|
8
8
|
import { ListItem } from './list-item'
|
|
9
9
|
import { ModalFilterBar } from './modal-filter-bar'
|
|
@@ -45,6 +45,7 @@ export function SessionPickerModal({
|
|
|
45
45
|
selectedIndex,
|
|
46
46
|
sessions,
|
|
47
47
|
}: SessionPickerModalProps) {
|
|
48
|
+
const theme = useTheme()
|
|
48
49
|
const ordered = orderSessionsForDisplay(sessions)
|
|
49
50
|
const baselineOrder = ordered.map((s) => s.id)
|
|
50
51
|
const filtered = filterSessions(ordered, filter)
|
|
@@ -3,7 +3,7 @@ import type { ScrollBoxRenderable } from '@opentui/core'
|
|
|
3
3
|
import { memo, useMemo, useRef } from 'react'
|
|
4
4
|
|
|
5
5
|
import { useAppStore } from '../../state/app-store'
|
|
6
|
-
import {
|
|
6
|
+
import { getCurrentTheme, useTheme } from '../theme'
|
|
7
7
|
import { GitPaneWidget } from './git-pane-widget'
|
|
8
8
|
import { buildTabGroupInfo } from './sidebar-group-metadata'
|
|
9
9
|
import { TabItem } from './tab-item'
|
|
@@ -20,6 +20,7 @@ const GUTTER_END = '╰'
|
|
|
20
20
|
const GUTTER_PAD = '│'
|
|
21
21
|
|
|
22
22
|
const SidebarTop = memo(function SidebarTop() {
|
|
23
|
+
const theme = useTheme()
|
|
23
24
|
const sidebarWidth = useAppStore((s) => s.sidebar.width)
|
|
24
25
|
const currentSessionId = useAppStore((s) => s.currentSessionId)
|
|
25
26
|
const sessions = useAppStore((s) => s.sessions)
|
|
@@ -59,15 +60,15 @@ function renderGroupGutter(
|
|
|
59
60
|
return (
|
|
60
61
|
<box flexDirection="column" width={1} overflow="hidden">
|
|
61
62
|
<text
|
|
62
|
-
fg={
|
|
63
|
-
bg={isActive ?
|
|
63
|
+
fg={getCurrentTheme().colors['terminal.ansiMagenta']}
|
|
64
|
+
bg={isActive ? getCurrentTheme().colors['list.activeSelectionBackground'] : undefined}
|
|
64
65
|
>
|
|
65
66
|
{/* oxlint-disable-next-line no-nested-ternary */}
|
|
66
67
|
{isGroupStart ? GUTTER_START : isGroupMiddle ? GUTTER_MIDDLE : GUTTER_PAD}
|
|
67
68
|
</text>
|
|
68
69
|
<text
|
|
69
|
-
fg={
|
|
70
|
-
bg={isActive ?
|
|
70
|
+
fg={getCurrentTheme().colors['terminal.ansiMagenta']}
|
|
71
|
+
bg={isActive ? getCurrentTheme().colors['list.activeSelectionBackground'] : undefined}
|
|
71
72
|
>
|
|
72
73
|
{isGroupEnd ? GUTTER_END : GUTTER_PAD}
|
|
73
74
|
</text>
|
|
@@ -80,6 +81,7 @@ interface TabsBodyProps {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
const TabsBody = memo(function TabsBody({ onTabActivate }: TabsBodyProps) {
|
|
84
|
+
const theme = useTheme()
|
|
83
85
|
const tabs = useAppStore((s) => s.tabs)
|
|
84
86
|
const activeTabId = useAppStore((s) => s.activeTabId)
|
|
85
87
|
const focusMode = useAppStore((s) => s.focusMode)
|
|
@@ -149,6 +151,7 @@ const TabsBody = memo(function TabsBody({ onTabActivate }: TabsBodyProps) {
|
|
|
149
151
|
})
|
|
150
152
|
|
|
151
153
|
export function Sidebar({ onTabActivate }: SidebarProps) {
|
|
154
|
+
const theme = useTheme()
|
|
152
155
|
const sidebarVisible = useAppStore((s) => s.sidebar.visible)
|
|
153
156
|
const sidebarWidth = useAppStore((s) => s.sidebar.width)
|
|
154
157
|
const gitPane = useAppStore((s) => s.gitPane)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useTheme } from '../theme'
|
|
2
2
|
import { uiTokens } from '../ui-tokens'
|
|
3
3
|
import { InputField } from './input-field'
|
|
4
4
|
import { ModalShell } from './modal-shell'
|
|
@@ -16,6 +16,7 @@ export function SnippetEditorModal({
|
|
|
16
16
|
snippetContent,
|
|
17
17
|
snippetName,
|
|
18
18
|
}: SnippetEditorModalProps) {
|
|
19
|
+
const theme = useTheme()
|
|
19
20
|
const nameActive = activeField === 'name'
|
|
20
21
|
const contentActive = activeField === 'content'
|
|
21
22
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SnippetRecord } from '../../state/types'
|
|
2
2
|
|
|
3
3
|
import { filterSnippets } from '../../state/selectors'
|
|
4
|
-
import {
|
|
4
|
+
import { useTheme } from '../theme'
|
|
5
5
|
import { uiTokens } from '../ui-tokens'
|
|
6
6
|
import { ListItem } from './list-item'
|
|
7
7
|
import { ModalFilterBar } from './modal-filter-bar'
|
|
@@ -22,6 +22,7 @@ function truncateContent(content: string): string {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function SnippetPickerModal({ filter, selectedIndex, snippets }: SnippetPickerModalProps) {
|
|
25
|
+
const theme = useTheme()
|
|
25
26
|
const filtered = filterSnippets(snippets, filter)
|
|
26
27
|
|
|
27
28
|
return (
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type PaneRect,
|
|
12
12
|
type SplitDirection,
|
|
13
13
|
} from '../../state/layout-tree'
|
|
14
|
-
import {
|
|
14
|
+
import { useTheme } from '../theme'
|
|
15
15
|
import { TerminalPane } from './terminal-pane'
|
|
16
16
|
|
|
17
17
|
const PANE_CHROME = PANE_BORDER
|
|
@@ -58,6 +58,7 @@ export function SplitLayout({
|
|
|
58
58
|
onTerminalScrollEvent,
|
|
59
59
|
tabs,
|
|
60
60
|
}: SplitLayoutProps) {
|
|
61
|
+
const theme = useTheme()
|
|
61
62
|
if (node.type === 'leaf') {
|
|
62
63
|
const tab = tabs.find((t) => t.id === node.tabId)
|
|
63
64
|
const isActive = node.tabId === activeTabId
|
|
@@ -4,21 +4,22 @@ import { version as APP_VERSION } from '../../../package.json'
|
|
|
4
4
|
import { useAppStore } from '../../state/app-store'
|
|
5
5
|
import { useKeymap } from '../keymap-context'
|
|
6
6
|
import { getStatusBarModel } from '../status-bar-model'
|
|
7
|
-
import {
|
|
7
|
+
import { getCurrentTheme, useTheme } from '../theme'
|
|
8
8
|
|
|
9
9
|
function getModeColor(focusMode: AppState['focusMode']): string {
|
|
10
|
+
const t = getCurrentTheme()
|
|
10
11
|
switch (focusMode) {
|
|
11
12
|
case 'terminal-input':
|
|
12
|
-
return
|
|
13
|
+
return t.colors['textLink.foreground']
|
|
13
14
|
case 'modal':
|
|
14
|
-
return
|
|
15
|
+
return t.colors['editorWarning.foreground']
|
|
15
16
|
case 'command-edit':
|
|
16
|
-
return
|
|
17
|
+
return t.colors['editorWarning.foreground']
|
|
17
18
|
case 'git':
|
|
18
|
-
return
|
|
19
|
+
return t.colors['gitDecoration.addedResourceForeground']
|
|
19
20
|
case 'navigation':
|
|
20
21
|
default:
|
|
21
|
-
return
|
|
22
|
+
return t.colors['terminal.ansiMagenta']
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -39,6 +40,7 @@ function getModeLabel(focusMode: AppState['focusMode']): string {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export function StatusBar() {
|
|
43
|
+
const theme = useTheme()
|
|
42
44
|
const state = useAppStore((s) => s)
|
|
43
45
|
const activeTab = state.tabs.find((tab) => tab.id === state.activeTabId)
|
|
44
46
|
const config = useKeymap()
|