Skip to content

Commit 7628b08

Browse files
committed
chore: add confirm dialog
1 parent f0644cc commit 7628b08

File tree

3 files changed

+112
-29
lines changed

3 files changed

+112
-29
lines changed

bun.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"@eslint/js": "^9.33.0",
88
"@stylistic/eslint-plugin": "^5.2.3",
99
"@types/bun": "latest",
10+
"@types/pluralize": "^0.0.33",
1011
"@types/react": "^19.1.10",
1112
"chalk": "^5.5.0",
1213
"eslint": "^9.33.0",
@@ -18,6 +19,7 @@
1819
"ink": "^6.2.0",
1920
"ink-gradient": "^3.0.0",
2021
"ink-select-input": "^6.2.0",
22+
"pluralize": "^8.0.0",
2123
"react": "^19.1.1",
2224
"react-devtools-core": "^6.1.5",
2325
"strip-ansi": "^7.1.0",
@@ -194,6 +196,8 @@
194196

195197
"@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw=="],
196198

199+
"@types/pluralize": ["@types/[email protected]", "", {}, "sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg=="],
200+
197201
"@types/react": ["@types/[email protected]", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg=="],
198202

199203
"@types/tinycolor2": ["@types/[email protected]", "", {}, "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw=="],
@@ -678,6 +682,8 @@
678682

679683
"picomatch": ["[email protected]", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
680684

685+
"pluralize": ["[email protected]", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="],
686+
681687
"possible-typed-array-names": ["[email protected]", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
682688

683689
"postcss": ["[email protected]", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
"typescript": "^5.9.2",
4343
"typescript-eslint": "^8.39.1",
4444
"vitest": "^3.2.4",
45-
"zod": "^4.0.17"
45+
"zod": "^4.0.17",
46+
"pluralize": "^8.0.0",
47+
"@types/pluralize": "^0.0.33"
4648
},
4749
"keywords": [
4850
"claude",

src/tui/components/LineSelector.tsx

Lines changed: 103 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ import {
33
Text,
44
useInput
55
} from 'ink';
6-
import React, { useState } from 'react';
6+
import pluralize from 'pluralize';
7+
import React, {
8+
useMemo,
9+
useState
10+
} from 'react';
711

812
import type { Settings } from '../../types/Settings';
913
import type { WidgetItem } from '../../types/Widget';
1014

15+
import { ConfirmDialog } from './ConfirmDialog';
16+
1117
interface LineSelectorProps {
1218
lines: WidgetItem[][];
1319
onAppend: () => void;
@@ -32,6 +38,12 @@ const LineSelector: React.FC<LineSelectorProps> = ({
3238
settings
3339
}) => {
3440
const [selectedIndex, setSelectedIndex] = useState(initialSelection);
41+
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
42+
43+
const selectedLine = useMemo(
44+
() => lines[selectedIndex],
45+
[lines, selectedIndex]
46+
);
3547

3648
// Check if powerline theme is managing colors
3749
const powerlineEnabled = settings ? settings.powerline.enabled : false;
@@ -44,7 +56,11 @@ const LineSelector: React.FC<LineSelectorProps> = ({
4456

4557
// Handle keyboard input
4658
useInput((input, key) => {
47-
// If theme-managed and blocking is enabled, any key goes back
59+
if (showDeleteDialog) {
60+
return;
61+
}
62+
63+
// If theme-managed and blocking is enabled, any key goes back
4864
if (isThemeManaged) {
4965
onBack();
5066
return;
@@ -56,8 +72,7 @@ const LineSelector: React.FC<LineSelectorProps> = ({
5672
setSelectedIndex(lines.length);
5773
return;
5874
case 'd':
59-
onDelete(selectedIndex);
60-
setSelectedIndex(Math.max(0, selectedIndex - 1));
75+
setShowDeleteDialog(true);
6176
return;
6277
}
6378

@@ -109,35 +124,95 @@ const LineSelector: React.FC<LineSelectorProps> = ({
109124
);
110125
}
111126

112-
return (
113-
<Box flexDirection='column'>
114-
<Text bold>{title ?? 'Select Line to Edit'}</Text>
115-
<Text dimColor>
116-
Choose which status line to configure (up to 3 lines supported)
117-
</Text>
118-
<Text dimColor>
119-
(i) to append new line, (d) to delete line, ESC to go back
120-
</Text>
121-
<Box marginTop={1} flexDirection='column'>
122-
{lines.map((line, index) => (
123-
<Box key={index}>
124-
<Text color={selectedIndex === index ? 'green' : undefined}>
125-
{selectedIndex === index ? '▶ ' : ' '}
126-
☰ Line
127-
{index + 1}
128-
{line.length > 0 ? ` (${line.length} widgets)` : ' (empty)'}
127+
if (showDeleteDialog && selectedLine) {
128+
const suffix
129+
= selectedLine.length > 0
130+
? pluralize('widget', selectedLine.length, true)
131+
: 'empty';
132+
133+
return (
134+
<Box flexDirection='column'>
135+
<Box flexDirection='column' gap={1}>
136+
<Text bold>
137+
<Text>
138+
<Text>
139+
☰ Line
140+
{selectedIndex + 1}
141+
</Text>
142+
<Text dimColor>
143+
(
144+
{suffix}
145+
)
146+
</Text>
129147
</Text>
130-
</Box>
131-
))}
148+
</Text>
149+
<Text bold>Are you sure you want to delete line?</Text>
150+
</Box>
132151

133152
<Box marginTop={1}>
134-
<Text color={selectedIndex === lines.length ? 'green' : undefined}>
135-
{selectedIndex === lines.length ? '▶ ' : ' '}
136-
← Back
137-
</Text>
153+
<ConfirmDialog
154+
inline={true}
155+
onConfirm={() => {
156+
onDelete(selectedIndex);
157+
setSelectedIndex(Math.max(0, selectedIndex - 1));
158+
setShowDeleteDialog(false);
159+
}}
160+
onCancel={() => {
161+
setShowDeleteDialog(false);
162+
}}
163+
/>
164+
</Box>
165+
</Box>
166+
);
167+
}
168+
169+
return (
170+
<>
171+
<Box flexDirection='column'>
172+
<Text bold>{title ?? 'Select Line to Edit'}</Text>
173+
<Text dimColor>
174+
Choose which status line to configure (up to 3 lines supported)
175+
</Text>
176+
<Text dimColor>
177+
(i) to append new line, (d) to delete line, ESC to go back
178+
</Text>
179+
180+
<Box marginTop={1} flexDirection='column'>
181+
{lines.map((line, index) => {
182+
const isSelected = selectedIndex === index;
183+
const suffix = line.length
184+
? pluralize('widget', line.length, true)
185+
: 'empty';
186+
187+
return (
188+
<Box key={index}>
189+
<Text color={isSelected ? 'green' : undefined}>
190+
<Text>{isSelected ? '▶ ' : ' '}</Text>
191+
<Text>
192+
<Text>
193+
☰ Line
194+
{index + 1}
195+
</Text>
196+
<Text dimColor={!isSelected}>
197+
(
198+
{suffix}
199+
)
200+
</Text>
201+
</Text>
202+
</Text>
203+
</Box>
204+
);
205+
})}
206+
207+
<Box marginTop={1}>
208+
<Text color={selectedIndex === lines.length ? 'green' : undefined}>
209+
{selectedIndex === lines.length ? '▶ ' : ' '}
210+
← Back
211+
</Text>
212+
</Box>
138213
</Box>
139214
</Box>
140-
</Box>
215+
</>
141216
);
142217
};
143218

0 commit comments

Comments
 (0)