arc402-cli 0.8.0 → 0.9.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.
Files changed (65) hide show
  1. package/INK6-UX-SPEC.md +446 -0
  2. package/dist/tui/App.d.ts.map +1 -1
  3. package/dist/tui/App.js +43 -3
  4. package/dist/tui/App.js.map +1 -1
  5. package/dist/tui/Header.d.ts +1 -1
  6. package/dist/tui/Header.d.ts.map +1 -1
  7. package/dist/tui/Header.js +6 -5
  8. package/dist/tui/Header.js.map +1 -1
  9. package/dist/tui/InputLine.d.ts +1 -2
  10. package/dist/tui/InputLine.d.ts.map +1 -1
  11. package/dist/tui/InputLine.js +76 -24
  12. package/dist/tui/InputLine.js.map +1 -1
  13. package/dist/tui/components/Button.d.ts +7 -0
  14. package/dist/tui/components/Button.d.ts.map +1 -0
  15. package/dist/tui/components/Button.js +18 -0
  16. package/dist/tui/components/Button.js.map +1 -0
  17. package/dist/tui/components/CeremonyView.d.ts +13 -0
  18. package/dist/tui/components/CeremonyView.d.ts.map +1 -0
  19. package/dist/tui/components/CeremonyView.js +7 -0
  20. package/dist/tui/components/CeremonyView.js.map +1 -0
  21. package/dist/tui/components/CompletionDropdown.d.ts +7 -0
  22. package/dist/tui/components/CompletionDropdown.d.ts.map +1 -0
  23. package/dist/tui/components/CompletionDropdown.js +20 -0
  24. package/dist/tui/components/CompletionDropdown.js.map +1 -0
  25. package/dist/tui/components/ConfirmPrompt.d.ts +9 -0
  26. package/dist/tui/components/ConfirmPrompt.d.ts.map +1 -0
  27. package/dist/tui/components/ConfirmPrompt.js +7 -0
  28. package/dist/tui/components/ConfirmPrompt.js.map +1 -0
  29. package/dist/tui/components/InteractiveTable.d.ts +14 -0
  30. package/dist/tui/components/InteractiveTable.d.ts.map +1 -0
  31. package/dist/tui/components/InteractiveTable.js +58 -0
  32. package/dist/tui/components/InteractiveTable.js.map +1 -0
  33. package/dist/tui/components/StepSpinner.d.ts +11 -0
  34. package/dist/tui/components/StepSpinner.d.ts.map +1 -0
  35. package/dist/tui/components/StepSpinner.js +29 -0
  36. package/dist/tui/components/StepSpinner.js.map +1 -0
  37. package/dist/tui/components/Toast.d.ts +18 -0
  38. package/dist/tui/components/Toast.d.ts.map +1 -0
  39. package/dist/tui/components/Toast.js +25 -0
  40. package/dist/tui/components/Toast.js.map +1 -0
  41. package/dist/tui/index.d.ts.map +1 -1
  42. package/dist/tui/index.js +15 -1
  43. package/dist/tui/index.js.map +1 -1
  44. package/dist/tui/useNotifications.d.ts +9 -0
  45. package/dist/tui/useNotifications.d.ts.map +1 -0
  46. package/dist/tui/useNotifications.js +14 -0
  47. package/dist/tui/useNotifications.js.map +1 -0
  48. package/dist/ui/banner.d.ts +12 -0
  49. package/dist/ui/banner.d.ts.map +1 -1
  50. package/dist/ui/banner.js +23 -0
  51. package/dist/ui/banner.js.map +1 -1
  52. package/package.json +1 -1
  53. package/src/tui/App.tsx +53 -9
  54. package/src/tui/Header.tsx +25 -4
  55. package/src/tui/InputLine.tsx +107 -32
  56. package/src/tui/components/Button.tsx +38 -0
  57. package/src/tui/components/CeremonyView.tsx +39 -0
  58. package/src/tui/components/CompletionDropdown.tsx +59 -0
  59. package/src/tui/components/ConfirmPrompt.tsx +36 -0
  60. package/src/tui/components/InteractiveTable.tsx +112 -0
  61. package/src/tui/components/StepSpinner.tsx +84 -0
  62. package/src/tui/components/Toast.tsx +59 -0
  63. package/src/tui/index.tsx +20 -1
  64. package/src/tui/useNotifications.ts +28 -0
  65. package/src/ui/banner.ts +27 -0
@@ -0,0 +1,446 @@
1
+ # Ink 6 UX Enhancement Spec
2
+
3
+ ## Context
4
+ CLI is now on Ink 6 + React 19 + ESM. The WalletConnect native component exists.
5
+ This spec covers ALL remaining Ink 6 UX capabilities to build before the article demo.
6
+
7
+ ## Current TUI Architecture
8
+ ```
9
+ src/tui/
10
+ ├── App.tsx — Root component, layout, command dispatch
11
+ ├── Header.tsx — ASCII banner + network/wallet/balance
12
+ ├── Viewport.tsx — Scrollable output buffer
13
+ ├── InputLine.tsx — Text input with history + tab completion
14
+ ├── Footer.tsx — Footer wrapper
15
+ ├── WalletConnectPairing.tsx — Native WC QR + status (new from Phase 3)
16
+ ├── index.tsx — TUI launcher
17
+ ├── useCommand.ts — Command dispatch (in-process + child process)
18
+ ├── useChat.ts — Chat gateway integration
19
+ └── useScroll.ts — Viewport scroll state
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Feature 1: Full-Screen Mode
25
+
26
+ ### What
27
+ Use Ink 6's `fullScreen` option on `render()` to use the alternate screen buffer.
28
+
29
+ ### Why
30
+ - Clean entry: terminal history preserved, TUI gets a blank canvas
31
+ - Clean exit: original terminal content restored
32
+ - Proper resize: Ink reflows on SIGWINCH in full-screen mode
33
+ - No visual artifacts from previous commands bleeding into the TUI
34
+
35
+ ### Implementation
36
+ In `src/tui/index.tsx`, change the render call:
37
+ ```tsx
38
+ const { waitUntilExit } = render(<App ... />, {
39
+ exitOnCtrlC: true,
40
+ });
41
+ ```
42
+ Ink 6's `render()` supports a second options argument. Check if `fullScreen` is a boolean option or if it's handled via `<Box height="100%">` with the alternate buffer.
43
+
44
+ If Ink 6 doesn't have a built-in fullScreen option, implement manually:
45
+ ```tsx
46
+ // Enter alternate buffer
47
+ process.stdout.write('\x1b[?1049h');
48
+ // ... render ...
49
+ // On exit, restore
50
+ process.stdout.write('\x1b[?1049l');
51
+ ```
52
+
53
+ ### Files to change
54
+ - `src/tui/index.tsx` — add alternate screen buffer enter/exit
55
+
56
+ ---
57
+
58
+ ## Feature 2: Static Banner with `<Static>`
59
+
60
+ ### What
61
+ Wrap the ASCII art banner in Ink's `<Static>` component so it renders once and never re-renders.
62
+
63
+ ### Why
64
+ - The banner is ~12 lines of ASCII art that NEVER changes after launch
65
+ - Currently re-renders on every state change (output buffer update, scroll, input change)
66
+ - `<Static>` renders items once above the dynamic area — perfect for the banner
67
+
68
+ ### Implementation
69
+ In `App.tsx`, replace the `<Header>` component with a `<Static>` block:
70
+ ```tsx
71
+ import { Static } from "ink";
72
+
73
+ // Banner lines computed once
74
+ const [bannerItems] = useState(() => getBannerLines({ network, wallet, balance }));
75
+
76
+ return (
77
+ <Box flexDirection="column" height="100%">
78
+ <Static items={bannerItems}>
79
+ {(line, i) => <Text key={i}>{line}</Text>}
80
+ </Static>
81
+ <Text>{separator}</Text>
82
+ <Viewport ... />
83
+ <Text>{separator}</Text>
84
+ <InputLine ... />
85
+ </Box>
86
+ );
87
+ ```
88
+
89
+ ### Files to change
90
+ - `src/tui/App.tsx` — use `<Static>` for banner
91
+ - `src/tui/Header.tsx` — may become unnecessary (inline into App)
92
+
93
+ ---
94
+
95
+ ## Feature 3: Spinner Components for Deploy Ceremony
96
+
97
+ ### What
98
+ Create reusable `<StepSpinner>` and `<StepComplete>` components for multi-step flows.
99
+
100
+ ### Why
101
+ The deploy + onboarding ceremony has 8+ sequential steps. Each should show:
102
+ - `◈ Step 3/8 — Setting guardian...` (spinning) while in progress
103
+ - `✓ Step 3/8 — Guardian set` (static) when done
104
+ - `✗ Step 3/8 — Failed: reason` (static) on error
105
+
106
+ ### Implementation
107
+ Create `src/tui/components/StepSpinner.tsx`:
108
+ ```tsx
109
+ interface StepSpinnerProps {
110
+ step: number;
111
+ total: number;
112
+ label: string;
113
+ status: "pending" | "running" | "done" | "error";
114
+ detail?: string; // e.g. tx hash, address
115
+ error?: string;
116
+ }
117
+ ```
118
+
119
+ Uses Ink's built-in spinner frames (or a simple `◈ ◇ ◆ ◈` cycle):
120
+ ```
121
+ ◈ Step 1/8 — Deploying wallet...
122
+ ✓ Step 1/8 — Wallet deployed
123
+ └ 0xA34B...a5dc
124
+ ◈ Step 2/8 — Authorizing machine key...
125
+ ```
126
+
127
+ Create `src/tui/components/CeremonyView.tsx`:
128
+ A container that manages the step list and renders each StepSpinner.
129
+ ```tsx
130
+ interface CeremonyStep {
131
+ label: string;
132
+ status: "pending" | "running" | "done" | "error";
133
+ detail?: string;
134
+ error?: string;
135
+ }
136
+
137
+ interface CeremonyViewProps {
138
+ title: string;
139
+ steps: CeremonyStep[];
140
+ }
141
+ ```
142
+
143
+ ### Files to create
144
+ - `src/tui/components/StepSpinner.tsx`
145
+ - `src/tui/components/CeremonyView.tsx`
146
+
147
+ ### Integration
148
+ Wire into `useCommand.ts` — when `wallet deploy` runs, instead of spawning a child process, render `<CeremonyView>` in the viewport with steps updating via React state.
149
+
150
+ ---
151
+
152
+ ## Feature 4: Focus Management (`useFocus` / `useFocusManager`)
153
+
154
+ ### What
155
+ Tab-navigable interactive elements in the TUI.
156
+
157
+ ### Why
158
+ - Deploy wizard: Tab between "Confirm" / "Cancel" / "Change settings"
159
+ - WalletConnect: Tab between QR display and wallet link list
160
+ - Any confirmation prompt: focus on Yes/No buttons
161
+
162
+ ### Implementation
163
+ Create `src/tui/components/Button.tsx`:
164
+ ```tsx
165
+ interface ButtonProps {
166
+ label: string;
167
+ onPress: () => void;
168
+ variant?: "primary" | "danger" | "dim";
169
+ }
170
+
171
+ function Button({ label, onPress, variant = "primary" }: ButtonProps) {
172
+ const { isFocused } = useFocus();
173
+ return (
174
+ <Box>
175
+ <Text
176
+ color={isFocused ? "cyan" : "white"}
177
+ bold={isFocused}
178
+ >
179
+ {isFocused ? "▸ " : " "}{label}
180
+ </Text>
181
+ </Box>
182
+ );
183
+ }
184
+ ```
185
+
186
+ Create `src/tui/components/ConfirmPrompt.tsx`:
187
+ ```tsx
188
+ interface ConfirmPromptProps {
189
+ message: string;
190
+ onConfirm: () => void;
191
+ onCancel: () => void;
192
+ }
193
+ ```
194
+ Renders two focusable buttons. Enter on focused button triggers action.
195
+
196
+ ### Files to create
197
+ - `src/tui/components/Button.tsx`
198
+ - `src/tui/components/ConfirmPrompt.tsx`
199
+
200
+ ---
201
+
202
+ ## Feature 5: Enhanced Input (useInput)
203
+
204
+ ### What
205
+ Better keyboard handling in the TUI.
206
+
207
+ ### Why
208
+ - Ctrl+C: graceful shutdown (cleanup WC sessions, save state)
209
+ - Ctrl+L: clear viewport (like terminal clear)
210
+ - Page Up/Down: fast viewport scrolling
211
+ - Escape: cancel current operation / close prompts
212
+
213
+ ### Implementation
214
+ In `App.tsx`, add a top-level `useInput` handler:
215
+ ```tsx
216
+ useInput((input, key) => {
217
+ if (key.ctrl && input === 'l') {
218
+ setOutputBuffer([]);
219
+ return;
220
+ }
221
+ if (key.pageUp) {
222
+ scrollUp(viewportHeight);
223
+ return;
224
+ }
225
+ if (key.pageDown) {
226
+ scrollDown(viewportHeight);
227
+ return;
228
+ }
229
+ if (key.escape) {
230
+ // Cancel current operation if any
231
+ return;
232
+ }
233
+ });
234
+ ```
235
+
236
+ ### Files to change
237
+ - `src/tui/App.tsx` — add useInput handler
238
+ - `src/tui/useScroll.ts` — expose page-size scroll functions
239
+
240
+ ---
241
+
242
+ ## Feature 6: FlexWrap for Status Bar
243
+
244
+ ### What
245
+ Use `flexWrap="wrap"` on the header status info so it wraps on narrow terminals.
246
+
247
+ ### Why
248
+ `Network Base Mainnet Wallet 0xa9e0...83bE Balance 0.0042 ETH`
249
+ On a narrow terminal this truncates. With flexWrap it becomes:
250
+ ```
251
+ Network Base Mainnet
252
+ Wallet 0xa9e0...83bE
253
+ Balance 0.0042 ETH
254
+ ```
255
+
256
+ ### Implementation
257
+ In the banner/header, wrap status items in a `<Box flexWrap="wrap">`:
258
+ ```tsx
259
+ <Box flexWrap="wrap" columnGap={2}>
260
+ <Box><Text dimColor>Network</Text><Text> {network}</Text></Box>
261
+ <Box><Text dimColor>Wallet</Text><Text> {wallet}</Text></Box>
262
+ <Box><Text dimColor>Balance</Text><Text> {balance}</Text></Box>
263
+ </Box>
264
+ ```
265
+
266
+ ### Files to change
267
+ - `src/ui/banner.ts` — return structured data instead of pre-formatted strings
268
+ - `src/tui/Header.tsx` — use flexWrap Box layout
269
+
270
+ ---
271
+
272
+ ## Feature 7: Notification Toasts
273
+
274
+ ### What
275
+ Non-blocking notifications that appear briefly in the TUI when background events occur.
276
+
277
+ ### Why
278
+ When the daemon is running and receives a hire request, dispute, or payment — show it.
279
+
280
+ ### Implementation
281
+ Create `src/tui/components/Toast.tsx`:
282
+ ```tsx
283
+ interface ToastProps {
284
+ message: string;
285
+ variant: "info" | "success" | "warning" | "error";
286
+ duration?: number; // ms, default 5000
287
+ }
288
+ ```
289
+
290
+ Create `src/tui/useNotifications.ts`:
291
+ ```tsx
292
+ function useNotifications() {
293
+ const [toasts, setToasts] = useState<Toast[]>([]);
294
+ const push = (toast: Omit<Toast, "id">) => { ... };
295
+ const dismiss = (id: string) => { ... };
296
+ return { toasts, push, dismiss };
297
+ }
298
+ ```
299
+
300
+ Toasts render in a fixed position above the input line, auto-dismiss after duration.
301
+
302
+ ### Files to create
303
+ - `src/tui/components/Toast.tsx`
304
+ - `src/tui/useNotifications.ts`
305
+
306
+ ### Integration
307
+ The daemon WebSocket connection (if running) emits events → push toast.
308
+
309
+ ---
310
+
311
+ ## Feature 8: Tab-Completion Dropdown
312
+
313
+ ### What
314
+ Show a dropdown list of completion candidates when Tab is pressed.
315
+
316
+ ### Why
317
+ Current tab completion silently completes in the input. Users don't know what's available.
318
+
319
+ ### Implementation
320
+ Create `src/tui/components/CompletionDropdown.tsx`:
321
+ ```tsx
322
+ interface CompletionDropdownProps {
323
+ candidates: string[];
324
+ selectedIndex: number;
325
+ visible: boolean;
326
+ }
327
+ ```
328
+
329
+ Renders a floating box above the input line showing matching commands:
330
+ ```
331
+ wallet deploy
332
+ wallet status
333
+ wallet balance
334
+ wallet freeze
335
+ ◈ arc402 > wallet d_
336
+ ```
337
+
338
+ Arrow keys navigate, Tab/Enter selects, Escape dismisses.
339
+
340
+ ### Files to create
341
+ - `src/tui/components/CompletionDropdown.tsx`
342
+
343
+ ### Files to change
344
+ - `src/tui/InputLine.tsx` — manage dropdown state, render above input
345
+
346
+ ---
347
+
348
+ ## Feature 9: Interactive Tables
349
+
350
+ ### What
351
+ Scrollable, selectable table component for list views.
352
+
353
+ ### Why
354
+ `discover`, `agreements list`, `wallet list`, `list-machine-keys` all return tabular data.
355
+ Currently rendered as plain text. Should be interactive: arrow keys to navigate rows, Enter to drill in.
356
+
357
+ ### Implementation
358
+ Create `src/tui/components/InteractiveTable.tsx`:
359
+ ```tsx
360
+ interface Column {
361
+ header: string;
362
+ key: string;
363
+ width?: number;
364
+ align?: "left" | "right";
365
+ }
366
+
367
+ interface InteractiveTableProps {
368
+ columns: Column[];
369
+ rows: Record<string, string>[];
370
+ onSelect?: (row: Record<string, string>, index: number) => void;
371
+ selectedIndex?: number;
372
+ }
373
+ ```
374
+
375
+ Renders with box-drawing borders for the header row:
376
+ ```
377
+ Agent Service Trust Endpoint
378
+ ─────────────────────────────────────────────────
379
+ ▸ GigaBrain intelligence 850 gigabrain.arc402.xyz
380
+ CodeReviewer code.review 720 reviewer.arc402.xyz
381
+ DataOracle data.feed 690 oracle.arc402.xyz
382
+ ```
383
+
384
+ ### Files to create
385
+ - `src/tui/components/InteractiveTable.tsx`
386
+
387
+ ---
388
+
389
+ ## Feature 10: Split Pane (Future — Post-Launch)
390
+
391
+ ### What
392
+ Side-by-side panes: command output left, daemon logs right.
393
+
394
+ ### Why
395
+ Power users running the daemon want to see live events while issuing commands.
396
+
397
+ ### Implementation (design only — build post-launch)
398
+ Create `src/tui/components/SplitPane.tsx`:
399
+ ```tsx
400
+ interface SplitPaneProps {
401
+ left: React.ReactNode;
402
+ right: React.ReactNode;
403
+ ratio?: number; // 0.0-1.0, default 0.6
404
+ }
405
+ ```
406
+
407
+ Uses Ink 6's `<Box width="60%">` + `<Box width="40%">` for the split.
408
+
409
+ ### Files to create (post-launch)
410
+ - `src/tui/components/SplitPane.tsx`
411
+
412
+ ---
413
+
414
+ ## Build Order
415
+
416
+ 1. Full-screen mode (Feature 1) — foundational
417
+ 2. Static banner (Feature 2) — performance
418
+ 3. Enhanced input / keyboard (Feature 5) — UX basics
419
+ 4. Spinner components (Feature 3) — deploy ceremony visual
420
+ 5. Focus management + buttons (Feature 4) — interactive deploy wizard
421
+ 6. FlexWrap status bar (Feature 6) — responsive layout
422
+ 7. Tab-completion dropdown (Feature 8) — discoverability
423
+ 8. Interactive tables (Feature 9) — list views
424
+ 9. Notification toasts (Feature 7) — daemon integration
425
+ 10. Split pane (Feature 10) — post-launch
426
+
427
+ Features 1-8 are for the article demo. Feature 9 is nice-to-have. Feature 10 is post-launch.
428
+
429
+ ---
430
+
431
+ ## Testing Checklist
432
+
433
+ After build:
434
+ - [ ] `arc402` launches in full-screen mode, clean entry
435
+ - [ ] Ctrl+C exits cleanly, original terminal restored
436
+ - [ ] Ctrl+L clears viewport
437
+ - [ ] Page Up/Down scrolls viewport
438
+ - [ ] Tab shows completion dropdown
439
+ - [ ] `wallet deploy` shows QR inside viewport
440
+ - [ ] Deploy ceremony shows step spinners
441
+ - [ ] Confirmation prompts are focusable (Tab between buttons)
442
+ - [ ] `discover` renders interactive table
443
+ - [ ] Narrow terminal: status bar wraps correctly
444
+ - [ ] `exit` / `quit` restores terminal cleanly
445
+ - [ ] `arc402 wallet status` (one-shot mode) still works outside TUI
446
+ - [ ] `arc402 --help` still works
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAiBA,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,2CA+LlE"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAmBA,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,2CAyOlE"}
package/dist/tui/App.js CHANGED
@@ -1,15 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useCallback } from "react";
3
3
  import { createRequire } from "node:module";
4
- import { Box, Text, useApp } from "ink";
5
- import { Header } from "./Header.js";
4
+ import { Box, Text, Static, useApp, useInput } from "ink";
6
5
  import { Viewport } from "./Viewport.js";
7
6
  import { Footer } from "./Footer.js";
8
7
  import { InputLine } from "./InputLine.js";
9
8
  import { useCommand } from "./useCommand.js";
10
9
  import { useChat } from "./useChat.js";
11
10
  import { useScroll } from "./useScroll.js";
11
+ import { useNotifications } from "./useNotifications.js";
12
+ import { ToastContainer } from "./components/Toast.js";
12
13
  import { createProgram } from "../program.js";
14
+ import { getBannerArt, getStatusItems } from "../ui/banner.js";
13
15
  import chalk from "chalk";
14
16
  const pkg = createRequire(import.meta.url)("../../package.json");
15
17
  const BUILTIN_CMDS = ["help", "exit", "quit", "clear", "status"];
@@ -18,6 +20,30 @@ const BUILTIN_CMDS = ["help", "exit", "quit", "clear", "status"];
18
20
  */
19
21
  export function App({ version, network, wallet, balance }) {
20
22
  const { exit } = useApp();
23
+ // Banner computed once — rendered via <Static> so it never re-renders
24
+ const [bannerData] = useState(() => {
25
+ const { artLines, subtitle, separator } = getBannerArt();
26
+ const statusItems = getStatusItems({ network, wallet, balance });
27
+ // Build static items: art lines + subtitle + separator + status + help hint
28
+ const items = [];
29
+ artLines.forEach((line, i) => items.push({ id: `art-${i}`, text: line }));
30
+ items.push({ id: "blank-1", text: "" });
31
+ items.push({ id: "subtitle", text: subtitle });
32
+ items.push({ id: "separator", text: separator });
33
+ if (statusItems.length > 0) {
34
+ items.push({ id: "blank-2", text: "" });
35
+ // Status items as a single formatted line for <Static>
36
+ // (FlexWrap rendering happens in the Header component for non-Static contexts)
37
+ const statusLine = statusItems
38
+ .map((s) => `\x1b[2m${s.label}\x1b[22m ${s.value}`)
39
+ .join(" ");
40
+ items.push({ id: "status", text: ` ${statusLine}` });
41
+ }
42
+ items.push({ id: "blank-3", text: "" });
43
+ items.push({ id: "hint", text: " \x1b[2mType 'help' to get started\x1b[22m" });
44
+ items.push({ id: "blank-4", text: "" });
45
+ return items;
46
+ });
21
47
  const [outputBuffer, setOutputBuffer] = useState([
22
48
  chalk.dim(" Type 'help' to see available commands"),
23
49
  "",
@@ -31,6 +57,7 @@ export function App({ version, network, wallet, balance }) {
31
57
  const rows = process.stdout.rows ?? 24;
32
58
  const viewportHeight = Math.max(1, rows - HEADER_ROWS - FOOTER_ROWS);
33
59
  const { scrollOffset, isAutoScroll, scrollUp, scrollDown, snapToBottom } = useScroll(viewportHeight);
60
+ const { toasts, dismiss: dismissToast } = useNotifications();
34
61
  // Get top-level command names for dispatch detection
35
62
  const [topCmds] = useState(() => {
36
63
  try {
@@ -41,6 +68,19 @@ export function App({ version, network, wallet, balance }) {
41
68
  return [];
42
69
  }
43
70
  });
71
+ // ── Enhanced keyboard shortcuts ────────────────────────────────────────
72
+ useInput((input, key) => {
73
+ // Ctrl+L — clear viewport
74
+ if (key.ctrl && input === "l") {
75
+ setOutputBuffer([]);
76
+ return;
77
+ }
78
+ // Escape — cancel / clear (snap to bottom if scrolled)
79
+ if (key.escape) {
80
+ snapToBottom();
81
+ return;
82
+ }
83
+ });
44
84
  const appendLine = useCallback((line) => {
45
85
  setOutputBuffer((prev) => [...prev, line]);
46
86
  }, []);
@@ -143,6 +183,6 @@ export function App({ version, network, wallet, balance }) {
143
183
  setIsProcessing(false);
144
184
  }, [appendLine, execute, send, snapToBottom, topCmds, network, wallet, balance, exit]);
145
185
  const isDisabled = isProcessing || isRunning || isSending;
146
- return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(Header, { version: version, network: network, wallet: wallet, balance: balance }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "─".repeat(60) }) }), _jsx(Viewport, { lines: outputBuffer, scrollOffset: scrollOffset, isAutoScroll: isAutoScroll }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "─".repeat(60) }) }), _jsx(Footer, { children: _jsx(InputLine, { onSubmit: handleCommand, isDisabled: isDisabled }) })] }));
186
+ return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(Static, { items: bannerData, children: (item) => _jsx(Text, { children: item.text }, item.id) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "─".repeat(60) }) }), _jsx(Viewport, { lines: outputBuffer, scrollOffset: scrollOffset, isAutoScroll: isAutoScroll }), _jsx(ToastContainer, { toasts: toasts, onDismiss: dismissToast }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: "─".repeat(60) }) }), _jsx(Footer, { children: _jsx(InputLine, { onSubmit: handleCommand, isDisabled: isDisabled }) })] }));
147
187
  }
148
188
  //# sourceMappingURL=App.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,WAAW,EAAa,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,CAAC;AAExF,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AASjE;;GAEG;AACH,MAAM,UAAU,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAY;IACjE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAW;QACzD,KAAK,CAAC,GAAG,CAAC,yCAAyC,CAAC;QACpD,EAAE;KACH,CAAC,CAAC;IACH,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAAC;IAC5C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,CAAC;IAEtC,oDAAoD;IACpD,MAAM,WAAW,GAAG,EAAE,CAAC;IACvB,MAAM,WAAW,GAAG,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;IAErE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,GACtE,SAAS,CAAC,cAAc,CAAC,CAAC;IAE5B,qDAAqD;IACrD,MAAM,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAW,GAAG,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,IAAY,EAAE,EAAE;QAC9C,eAAe,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,aAAa,GAAG,WAAW,CAC/B,KAAK,EAAE,KAAa,EAAiB,EAAE;QACrC,2BAA2B;QAC3B,UAAU,CACR,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;YACnB,GAAG;YACH,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,GAAG;YACH,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;YAChB,GAAG;YACH,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CACrB,CAAC;QAEF,gCAAgC;QAChC,YAAY,EAAE,CAAC;QACf,eAAe,CAAC,IAAI,CAAC,CAAC;QAEtB,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC,CAAC;QAE/C,0EAA0E;QAC1E,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACzC,UAAU,CACR,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CACpD,CAAC;YACF,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,eAAe,CAAC,EAAE,CAAC,CAAC;YACpB,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;gBAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,MAAM,QAAQ,GAAa,EAAE,CAAC;gBAC9B,IAAI,CAAC,eAAe,CAAC;oBACnB,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;oBACrC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;iBACtC,CAAC,CAAC;gBACH,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACtD,CAAC;gBAAC,MAAM,CAAC;oBACP,0CAA0C;gBAC5C,CAAC;gBACD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;oBAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;wBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;YACrC,KAAK,CAAC,IAAI,CACR,IAAI;gBACF,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC;gBACxB,KAAK,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAC1D,CAAC;YACF,KAAK,CAAC,IAAI,CACR,IAAI;gBACF,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC;gBAC9B,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAC3C,CAAC;YACF,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,GAAG,CACP,6DAA6D,CAC9D,CACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,KAAK;gBAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YACrC,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,IAAI,OAAO;gBACT,UAAU,CACR,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CACrD,CAAC;YACJ,IAAI,MAAM;gBACR,UAAU,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAClE,IAAI,OAAO;gBACT,UAAU,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACnE,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO;gBACjC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC,CAAC;YAChF,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,WAAW,GACf,cAAc,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,KAAK,EAAE,CAAC,CAAC;QAExE,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC3D,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAC9B,CAAC;YACD,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,MAAM,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACjC,UAAU,CAAC,EAAE,CAAC,CAAC;QACf,eAAe,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,EACD,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CACnF,CAAC;IAEF,MAAM,UAAU,GAAG,YAAY,IAAI,SAAS,IAAI,SAAS,CAAC;IAE1D,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,MAAM,EAAC,MAAM,aAEvC,KAAC,MAAM,IACL,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,GAChB,EAGF,KAAC,GAAG,cACF,KAAC,IAAI,IAAC,QAAQ,kBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAQ,GAClC,EAGN,KAAC,QAAQ,IACP,KAAK,EAAE,YAAY,EACnB,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,GAC1B,EAGF,KAAC,GAAG,cACF,KAAC,IAAI,IAAC,QAAQ,kBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAQ,GAClC,EAGN,KAAC,MAAM,cACL,KAAC,SAAS,IAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,GAAI,GACvD,IACL,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ interface HeaderProps {
7
7
  }
8
8
  /**
9
9
  * Fixed header showing the ASCII art banner + status info.
10
- * Never re-renders unless config changes.
10
+ * Status items use flexWrap to adapt to narrow terminals.
11
11
  */
12
12
  export declare const Header: React.NamedExoticComponent<HeaderProps>;
13
13
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,yCAcjB,CAAC"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,yCAkCjB,CAAC"}
@@ -1,13 +1,14 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import { Box, Text } from "ink";
4
- import { getBannerLines } from "../ui/banner.js";
4
+ import { getBannerArt, getStatusItems } from "../ui/banner.js";
5
5
  /**
6
6
  * Fixed header showing the ASCII art banner + status info.
7
- * Never re-renders unless config changes.
7
+ * Status items use flexWrap to adapt to narrow terminals.
8
8
  */
9
9
  export const Header = React.memo(function Header({ network, wallet, balance, }) {
10
- const bannerLines = getBannerLines({ network, wallet, balance });
11
- return (_jsx(Box, { flexDirection: "column", children: bannerLines.map((line, i) => (_jsx(Text, { children: line }, i))) }));
10
+ const { artLines, subtitle, separator } = getBannerArt();
11
+ const statusItems = getStatusItems({ network, wallet, balance });
12
+ return (_jsxs(Box, { flexDirection: "column", children: [artLines.map((line, i) => (_jsx(Text, { children: line }, i))), _jsx(Text, { children: "" }), _jsx(Text, { children: subtitle }), _jsx(Text, { children: separator }), statusItems.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: "" }), _jsx(Box, { flexWrap: "wrap", columnGap: 2, children: statusItems.map((item) => (_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: item.label }), _jsxs(Text, { children: [" ", item.value] })] }, item.label))) })] })), _jsx(Text, { children: "" }), _jsx(Text, { dimColor: true, children: " Type 'help' to get started" }), _jsx(Text, { children: "" })] }));
12
13
  });
13
14
  //# sourceMappingURL=Header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AASjD;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,GACK;IACZ,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAEjE,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACxB,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC5B,KAAC,IAAI,cAAU,IAAI,IAAR,CAAC,CAAe,CAC5B,CAAC,GACE,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/tui/Header.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAU/D;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,GACK;IACZ,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IACzD,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAEjE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,IAAI,cAAU,IAAI,IAAR,CAAC,CAAe,CAC5B,CAAC,EACF,KAAC,IAAI,cAAE,EAAE,GAAQ,EACjB,KAAC,IAAI,cAAE,QAAQ,GAAQ,EACvB,KAAC,IAAI,cAAE,SAAS,GAAQ,EACvB,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CACzB,8BACE,KAAC,IAAI,cAAE,EAAE,GAAQ,EACjB,KAAC,GAAG,IAAC,QAAQ,EAAC,MAAM,EAAC,SAAS,EAAE,CAAC,YAC9B,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,QAAQ,kBAAE,IAAI,CAAC,KAAK,GAAQ,EAClC,MAAC,IAAI,qBAAI,IAAI,CAAC,KAAK,IAAQ,KAFnB,IAAI,CAAC,KAAK,CAGd,CACP,CAAC,GACE,IACL,CACJ,EACD,KAAC,IAAI,cAAE,EAAE,GAAQ,EACjB,KAAC,IAAI,IAAC,QAAQ,kBAAE,6BAA6B,GAAQ,EACrD,KAAC,IAAI,cAAE,EAAE,GAAQ,IACb,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -3,8 +3,7 @@ interface InputLineProps {
3
3
  isDisabled?: boolean;
4
4
  }
5
5
  /**
6
- * Input line with command history navigation and tab completion.
7
- * Uses ink-text-input for text input with cursor.
6
+ * Input line with command history navigation, tab completion, and dropdown.
8
7
  */
9
8
  export declare function InputLine({ onSubmit, isDisabled }: InputLineProps): import("react/jsx-runtime").JSX.Element;
10
9
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"InputLine.d.ts","sourceRoot":"","sources":["../../src/tui/InputLine.tsx"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,UAAkB,EAAE,EAAE,cAAc,2CAmJzE"}
1
+ {"version":3,"file":"InputLine.d.ts","sourceRoot":"","sources":["../../src/tui/InputLine.tsx"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,UAAkB,EAAE,EAAE,cAAc,2CA8NzE"}