@claude-code-kit/ui 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,7 +1,38 @@
1
- import { Color } from '@claude-code-kit/ink-renderer';
1
+ import { Color, Styles, DOMElement, ClickEvent, FocusEvent, KeyboardEvent, ColorType } from '@claude-code-kit/ink-renderer';
2
2
  export * from '@claude-code-kit/ink-renderer';
3
- import React from 'react';
3
+ import * as React from 'react';
4
+ import React__default, { PropsWithChildren, Ref, ReactNode } from 'react';
5
+ import { Tokens } from 'marked';
4
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
+ import { Agent, AuthRegistry, LLMProvider } from '@claude-code-kit/agent';
8
+
9
+ type DiffLine = {
10
+ type: 'added' | 'removed' | 'context';
11
+ content: string;
12
+ oldLineNumber?: number;
13
+ newLineNumber?: number;
14
+ };
15
+ type DiffViewProps = {
16
+ filename: string;
17
+ lines: DiffLine[];
18
+ /** Raw unified diff string — parsed automatically if provided */
19
+ diff?: string;
20
+ /** Show line numbers (default: true) */
21
+ showLineNumbers?: boolean;
22
+ /** Max visible lines before showing a scroll hint */
23
+ maxHeight?: number;
24
+ color?: {
25
+ added?: string;
26
+ removed?: string;
27
+ context?: string;
28
+ header?: string;
29
+ };
30
+ };
31
+ declare function parseUnifiedDiff(diff: string): {
32
+ filename: string;
33
+ lines: DiffLine[];
34
+ };
35
+ declare function DiffView({ filename, lines: propLines, diff, showLineNumbers, maxHeight, color: colorOverrides, }: DiffViewProps): React__default.ReactNode;
5
36
 
6
37
  type DividerProps = {
7
38
  width?: number;
@@ -10,22 +41,22 @@ type DividerProps = {
10
41
  padding?: number;
11
42
  title?: string;
12
43
  };
13
- declare function Divider({ width, color, char, padding, title }: DividerProps): React.ReactNode;
44
+ declare function Divider({ width, color, char, padding, title }: DividerProps): React__default.ReactNode;
14
45
 
15
- type Props$2 = {
46
+ type Props$b = {
16
47
  ratio: number;
17
48
  width: number;
18
49
  fillColor?: Color;
19
50
  emptyColor?: Color;
20
51
  };
21
- declare function ProgressBar({ ratio: inputRatio, width, fillColor, emptyColor }: Props$2): React.ReactNode;
52
+ declare function ProgressBar({ ratio: inputRatio, width, fillColor, emptyColor }: Props$b): React__default.ReactNode;
22
53
 
23
54
  type Status = 'success' | 'error' | 'warning' | 'info' | 'pending' | 'loading';
24
- type Props$1 = {
55
+ type Props$a = {
25
56
  status: Status;
26
57
  withSpace?: boolean;
27
58
  };
28
- declare function StatusIcon({ status, withSpace }: Props$1): React.ReactNode;
59
+ declare function StatusIcon({ status, withSpace }: Props$a): React__default.ReactNode;
29
60
 
30
61
  type StatusLineSegment = {
31
62
  content: string;
@@ -36,11 +67,14 @@ type StatusLineProps = {
36
67
  segments?: StatusLineSegment[];
37
68
  text?: string;
38
69
  paddingX?: number;
70
+ /** @deprecated Use separator instead. Gap between segments in columns. */
39
71
  gap?: number;
72
+ /** Separator string between segments (default: ' · ') */
73
+ separator?: string;
40
74
  borderStyle?: 'none' | 'single' | 'round';
41
75
  borderColor?: Color;
42
76
  };
43
- declare function StatusLine({ segments, text, paddingX, gap, borderStyle, borderColor, }: StatusLineProps): React.ReactNode;
77
+ declare function StatusLine({ segments, text, paddingX, separator, borderStyle, borderColor, }: StatusLineProps): React__default.ReactNode;
44
78
  declare function useStatusLine(updater: () => StatusLineSegment[] | string, deps: unknown[], intervalMs?: number): StatusLineSegment[] | string;
45
79
 
46
80
  type CommandResult = {
@@ -64,7 +98,7 @@ type LocalCommand = CommandBase & {
64
98
  };
65
99
  type JSXCommand = CommandBase & {
66
100
  type: 'jsx';
67
- render: (onDone: CommandOnDone, args: string) => React.ReactNode;
101
+ render: (onDone: CommandOnDone, args: string) => React__default.ReactNode;
68
102
  };
69
103
  type Command$1 = LocalCommand | JSXCommand;
70
104
 
@@ -161,8 +195,8 @@ declare function useKeybindings(handlers: Record<string, () => void | false | Pr
161
195
  * ~/.claude/keybindings.json, with hot-reload support when the file changes.
162
196
  */
163
197
 
164
- type Props = {
165
- children: React.ReactNode;
198
+ type Props$9 = {
199
+ children: React__default.ReactNode;
166
200
  /** Optional callback invoked when keybinding warnings are present */
167
201
  onWarnings?: (message: string, isError: boolean) => void;
168
202
  };
@@ -184,10 +218,18 @@ type Props = {
184
218
  * - User bindings override defaults (later entries win)
185
219
  * - Chord support with automatic timeout
186
220
  */
187
- declare function KeybindingSetup({ children, onWarnings }: Props): React.ReactNode;
221
+ declare function KeybindingSetup({ children, onWarnings }: Props$9): React__default.ReactNode;
188
222
 
189
223
  declare const DEFAULT_BINDINGS: KeybindingBlock[];
190
224
 
225
+ declare function useDoublePress(setPending: (pending: boolean) => void, onDoublePress: () => void, onFirstPress?: () => void): () => void;
226
+
227
+ type TerminalSize = {
228
+ columns: number;
229
+ rows: number;
230
+ };
231
+ declare function useTerminalSize(): TerminalSize;
232
+
191
233
  type Command = {
192
234
  name: string;
193
235
  description: string;
@@ -203,8 +245,10 @@ type PromptInputProps = {
203
245
  commands?: Command[];
204
246
  onCommandSelect?: (name: string) => void;
205
247
  history?: string[];
248
+ vimMode?: boolean;
249
+ multiline?: boolean;
206
250
  };
207
- declare function PromptInput({ value, onChange, onSubmit, placeholder, prefix, prefixColor, disabled, commands, onCommandSelect, history, }: PromptInputProps): React.ReactNode;
251
+ declare function PromptInput({ value, onChange, onSubmit, placeholder, prefix, prefixColor, disabled, commands, onCommandSelect, history, vimMode, multiline, }: PromptInputProps): React__default.ReactNode;
208
252
 
209
253
  type SpinnerProps = {
210
254
  label?: string;
@@ -213,7 +257,46 @@ type SpinnerProps = {
213
257
  color?: string;
214
258
  showElapsed?: boolean;
215
259
  };
216
- declare function Spinner({ label, verb, verbs, color, showElapsed, }: SpinnerProps): React.ReactNode;
260
+ declare function Spinner({ label, verb, verbs, color, showElapsed, }: SpinnerProps): React__default.ReactNode;
261
+
262
+ type Props$8 = {
263
+ children: string;
264
+ /** When true, render all text content as dim */
265
+ dimColor?: boolean;
266
+ };
267
+ declare function Markdown(props: Props$8): React__default.ReactNode;
268
+ type StreamingProps = {
269
+ children: string;
270
+ };
271
+ declare function StreamingMarkdown({ children, }: StreamingProps): React__default.ReactNode;
272
+
273
+ /**
274
+ * Stub for cli-highlight. Syntax highlighting is optional — returns null
275
+ * when cli-highlight is not available, causing code blocks to render as
276
+ * plain text.
277
+ */
278
+ type CliHighlight = {
279
+ highlight: (code: string, options?: {
280
+ language?: string;
281
+ }) => string;
282
+ supportsLanguage: (lang: string) => boolean;
283
+ };
284
+
285
+ type Props$7 = {
286
+ token: Tokens.Table;
287
+ highlight: CliHighlight | null;
288
+ /** Override terminal width (useful for testing) */
289
+ forceWidth?: number;
290
+ };
291
+ /**
292
+ * Renders a markdown table using Ink's Box layout.
293
+ * Handles terminal width by:
294
+ * 1. Calculating minimum column widths based on longest word
295
+ * 2. Distributing available space proportionally
296
+ * 3. Wrapping text within cells (no truncation)
297
+ * 4. Properly aligning multi-line rows with borders
298
+ */
299
+ declare function MarkdownTable({ token, highlight, forceWidth }: Props$7): React__default.ReactNode;
217
300
 
218
301
  type SelectOption<T = string> = {
219
302
  value: T;
@@ -237,18 +320,77 @@ type MultiSelectProps<T = string> = Omit<SelectProps<T>, 'onChange'> & {
237
320
  declare function Select<T = string>({ options, defaultValue, onChange, onCancel, title, maxVisible, }: SelectProps<T>): react_jsx_runtime.JSX.Element;
238
321
  declare function MultiSelect<T = string>({ options, selectedValues, onToggle, onConfirm, onCancel, title, maxVisible, }: MultiSelectProps<T>): react_jsx_runtime.JSX.Element;
239
322
 
323
+ type PermissionAction = 'allow' | 'always_allow' | 'deny';
324
+ type PermissionRequestProps = {
325
+ toolName: string;
326
+ description: string;
327
+ /** Optional details (command, file path, diff, etc.) */
328
+ details?: string;
329
+ /** Whether to show "Always Allow" option (default true) */
330
+ showAlwaysAllow?: boolean;
331
+ /** Callback when user makes a decision */
332
+ onDecision: (action: PermissionAction, feedback?: string) => void;
333
+ /** Optional custom content between description and buttons */
334
+ children?: React__default.ReactNode;
335
+ /** Optional: render a DiffView or code preview */
336
+ preview?: React__default.ReactNode;
337
+ };
338
+ declare function BashPermissionContent({ command }: {
339
+ command: string;
340
+ }): React__default.ReactNode;
341
+ declare function FileEditPermissionContent({ filename, diff, }: {
342
+ filename: string;
343
+ diff: string;
344
+ }): React__default.ReactNode;
345
+ declare function PermissionRequest({ toolName, description, details, showAlwaysAllow, onDecision, children, preview, }: PermissionRequestProps): React__default.ReactNode;
346
+
347
+ type MessageContent = {
348
+ type: 'text';
349
+ text: string;
350
+ } | {
351
+ type: 'tool_use';
352
+ toolName: string;
353
+ input: string;
354
+ result?: string;
355
+ status?: 'running' | 'success' | 'error';
356
+ } | {
357
+ type: 'thinking';
358
+ text: string;
359
+ collapsed?: boolean;
360
+ } | {
361
+ type: 'diff';
362
+ filename: string;
363
+ diff: string;
364
+ } | {
365
+ type: 'code';
366
+ language?: string;
367
+ code: string;
368
+ } | {
369
+ type: 'error';
370
+ message: string;
371
+ details?: string;
372
+ };
373
+ /**
374
+ * Display-oriented message type for rendering in the terminal UI.
375
+ *
376
+ * This type adds `id` and `timestamp` fields for UI purposes and supports
377
+ * rich `MessageContent[]` for rendering tool calls, diffs, code blocks, etc.
378
+ * It is distinct from the protocol-level `Message` type in
379
+ * `@claude-code-kit/agent`, which represents raw LLM conversation messages.
380
+ * The `useAgent` hook handles conversion between the two formats automatically.
381
+ */
240
382
  type Message = {
241
383
  id: string;
242
384
  role: 'user' | 'assistant' | 'system';
243
- content: string;
385
+ content: string | MessageContent[];
244
386
  timestamp?: number;
245
387
  };
246
388
  type MessageListProps = {
247
389
  messages: Message[];
248
390
  streamingContent?: string | null;
249
- renderMessage?: (message: Message) => React.ReactNode;
391
+ renderMessage?: (message: Message) => React__default.ReactNode;
250
392
  };
251
- declare function MessageList({ messages, streamingContent, renderMessage, }: MessageListProps): React.ReactNode;
393
+ declare function MessageList({ messages, streamingContent, renderMessage, }: MessageListProps): React__default.ReactNode;
252
394
 
253
395
  type StreamingTextProps = {
254
396
  text: string;
@@ -257,28 +399,531 @@ type StreamingTextProps = {
257
399
  onComplete?: () => void;
258
400
  color?: string;
259
401
  };
260
- declare function StreamingText({ text, speed, interval, onComplete, color, }: StreamingTextProps): React.ReactNode;
402
+ declare function StreamingText({ text, speed, interval, onComplete, color, }: StreamingTextProps): React__default.ReactNode;
261
403
 
262
- type REPLCommand = {
404
+ type REPLCommand$1 = {
263
405
  name: string;
264
406
  description: string;
265
407
  onExecute: (args: string) => void;
266
408
  };
409
+ type PermissionRequestState = {
410
+ toolName: string;
411
+ description: string;
412
+ details?: string;
413
+ preview?: React__default.ReactNode;
414
+ onDecision: (action: PermissionAction) => void;
415
+ };
267
416
  type REPLProps = {
268
417
  onSubmit: (message: string) => Promise<void> | void;
269
418
  onExit?: () => void;
270
419
  messages: Message[];
271
420
  isLoading?: boolean;
272
421
  streamingContent?: string | null;
273
- commands?: REPLCommand[];
422
+ welcome?: React__default.ReactNode;
423
+ permissionRequest?: PermissionRequestState;
424
+ commands?: REPLCommand$1[];
274
425
  model?: string;
275
426
  statusSegments?: StatusLineSegment[];
276
427
  prefix?: string;
277
428
  placeholder?: string;
278
429
  history?: string[];
279
- renderMessage?: (message: Message) => React.ReactNode;
280
- spinner?: React.ReactNode;
430
+ renderMessage?: (message: Message) => React__default.ReactNode;
431
+ spinner?: React__default.ReactNode;
432
+ };
433
+ declare function REPL({ onSubmit, onExit, messages, isLoading, streamingContent, welcome, permissionRequest, commands, model, statusSegments, prefix, placeholder, history: externalHistory, renderMessage, spinner, }: REPLProps): React__default.ReactNode;
434
+
435
+ type ThemeName = 'dark' | 'light' | 'light-high-contrast' | 'dark-dimmed';
436
+ type ThemeSetting = ThemeName | 'auto';
437
+ type Theme = {
438
+ text: string;
439
+ dimText: string;
440
+ border: string;
441
+ accent: string;
442
+ success: string;
443
+ warning: string;
444
+ error: string;
445
+ assistant: string;
446
+ inactive: string;
447
+ inverseText: string;
448
+ permission: string;
449
+ diffAdded: string;
450
+ diffRemoved: string;
451
+ diffAddedWord: string;
452
+ diffRemovedWord: string;
453
+ diffHeader: string;
454
+ userMessage: string;
455
+ assistantMessage: string;
456
+ systemMessage: string;
457
+ toolUseMessage: string;
458
+ permissionAllow: string;
459
+ permissionDeny: string;
460
+ permissionAlways: string;
461
+ focus: string;
462
+ selection: string;
463
+ placeholder: string;
464
+ link: string;
465
+ code: string;
466
+ codeBackground: string;
467
+ blockquote: string;
468
+ info: string;
469
+ spinnerColor: string;
470
+ shimmer: string;
471
+ };
472
+ declare function getTheme(name: ThemeName): Theme;
473
+ type Props$6 = {
474
+ children: React__default.ReactNode;
475
+ initialState?: ThemeSetting;
476
+ onThemeSave?: (setting: ThemeSetting) => void;
477
+ };
478
+ declare function ThemeProvider({ children, initialState, onThemeSave, }: Props$6): react_jsx_runtime.JSX.Element;
479
+ declare function useTheme(): [ThemeName, (setting: ThemeSetting) => void];
480
+ declare function useThemeSetting(): ThemeSetting;
481
+ declare function usePreviewTheme(): {
482
+ setPreviewTheme: (setting: ThemeSetting) => void;
483
+ savePreview: () => void;
484
+ cancelPreview: () => void;
485
+ };
486
+
487
+ type ThemedColorProps = {
488
+ readonly borderColor?: keyof Theme | Color;
489
+ readonly borderTopColor?: keyof Theme | Color;
490
+ readonly borderBottomColor?: keyof Theme | Color;
491
+ readonly borderLeftColor?: keyof Theme | Color;
492
+ readonly borderRightColor?: keyof Theme | Color;
493
+ readonly backgroundColor?: keyof Theme | Color;
494
+ };
495
+ type BaseStylesWithoutColors = Omit<Styles, 'textWrap' | 'borderColor' | 'borderTopColor' | 'borderBottomColor' | 'borderLeftColor' | 'borderRightColor' | 'backgroundColor'>;
496
+ type Props$5 = BaseStylesWithoutColors & ThemedColorProps & {
497
+ ref?: Ref<DOMElement>;
498
+ tabIndex?: number;
499
+ autoFocus?: boolean;
500
+ onClick?: (event: ClickEvent) => void;
501
+ onFocus?: (event: FocusEvent) => void;
502
+ onFocusCapture?: (event: FocusEvent) => void;
503
+ onBlur?: (event: FocusEvent) => void;
504
+ onBlurCapture?: (event: FocusEvent) => void;
505
+ onKeyDown?: (event: KeyboardEvent) => void;
506
+ onKeyDownCapture?: (event: KeyboardEvent) => void;
507
+ onMouseEnter?: () => void;
508
+ onMouseLeave?: () => void;
509
+ };
510
+ declare function ThemedBox({ borderColor, borderTopColor, borderBottomColor, borderLeftColor, borderRightColor, backgroundColor, children, ref, ...rest }: PropsWithChildren<Props$5>): React__default.ReactNode;
511
+
512
+ /** Colors uncolored ThemedText in the subtree. Precedence: explicit `color` >
513
+ * this > dimColor. Crosses Box boundaries (Ink's style cascade doesn't). */
514
+ declare const TextHoverColorContext: React__default.Context<keyof Theme | undefined>;
515
+ type Props$4 = {
516
+ readonly color?: keyof Theme | Color;
517
+ readonly backgroundColor?: keyof Theme;
518
+ readonly dimColor?: boolean;
519
+ readonly bold?: boolean;
520
+ readonly italic?: boolean;
521
+ readonly underline?: boolean;
522
+ readonly strikethrough?: boolean;
523
+ readonly inverse?: boolean;
524
+ readonly wrap?: Styles['textWrap'];
525
+ readonly children?: ReactNode;
526
+ };
527
+ declare function ThemedText({ color, backgroundColor, dimColor, bold, italic, underline, strikethrough, inverse, wrap, children, }: Props$4): React__default.ReactNode;
528
+
529
+ type DialogProps = {
530
+ title: React__default.ReactNode;
531
+ subtitle?: React__default.ReactNode;
532
+ children: React__default.ReactNode;
533
+ onCancel: () => void;
534
+ color?: keyof Theme;
535
+ hideInputGuide?: boolean;
536
+ hideBorder?: boolean;
537
+ };
538
+ /**
539
+ * A dialog box with title, content, and keyboard hints.
540
+ * Press Esc to cancel/close.
541
+ */
542
+ declare function Dialog({ title, subtitle, children, onCancel, color, hideInputGuide, hideBorder, }: DialogProps): React__default.ReactNode;
543
+
544
+ type PickerAction<T> = {
545
+ action: string;
546
+ handler: (item: T) => void;
547
+ };
548
+ type Props$3<T> = {
549
+ title: string;
550
+ placeholder?: string;
551
+ initialQuery?: string;
552
+ items: readonly T[];
553
+ getKey: (item: T) => string;
554
+ renderItem: (item: T, isFocused: boolean) => React.ReactNode;
555
+ renderPreview?: (item: T) => React.ReactNode;
556
+ previewPosition?: 'bottom' | 'right';
557
+ visibleCount?: number;
558
+ direction?: 'down' | 'up';
559
+ onQueryChange: (query: string) => void;
560
+ onSelect: (item: T) => void;
561
+ onTab?: PickerAction<T>;
562
+ onShiftTab?: PickerAction<T>;
563
+ onFocus?: (item: T | undefined) => void;
564
+ onCancel: () => void;
565
+ emptyMessage?: string | ((query: string) => string);
566
+ matchLabel?: string;
567
+ selectAction?: string;
568
+ extraHints?: React.ReactNode;
569
+ };
570
+ declare function FuzzyPicker<T>({ title, placeholder, initialQuery, items, getKey, renderItem, renderPreview, previewPosition, visibleCount: requestedVisible, direction, onQueryChange, onSelect, onTab, onShiftTab, onFocus, onCancel, emptyMessage, matchLabel, selectAction, extraHints, }: Props$3<T>): React.ReactNode;
571
+
572
+ type Props$2 = {
573
+ /** The key or chord to display (e.g., "ctrl+o", "Enter", "↑/↓") */
574
+ shortcut: string;
575
+ /** The action the key performs (e.g., "expand", "select", "navigate") */
576
+ action: string;
577
+ /** Whether to wrap the hint in parentheses. Default: false */
578
+ parens?: boolean;
579
+ /** Whether to render the shortcut in bold. Default: false */
580
+ bold?: boolean;
581
+ };
582
+ /**
583
+ * Renders a keyboard shortcut hint like "ctrl+o to expand" or "(tab to toggle)"
584
+ *
585
+ * Wrap in <Text dimColor> for the common dim styling.
586
+ *
587
+ * @example
588
+ * // Simple hint wrapped in dim Text
589
+ * <Text dimColor><KeyboardShortcutHint shortcut="esc" action="cancel" /></Text>
590
+ *
591
+ * // With parentheses: "(ctrl+o to expand)"
592
+ * <Text dimColor><KeyboardShortcutHint shortcut="ctrl+o" action="expand" parens /></Text>
593
+ *
594
+ * // With bold shortcut: "Enter to confirm" (Enter is bold)
595
+ * <Text dimColor><KeyboardShortcutHint shortcut="Enter" action="confirm" bold /></Text>
596
+ *
597
+ * // Multiple hints with middot separator - use Byline
598
+ * <Text dimColor>
599
+ * <Byline>
600
+ * <KeyboardShortcutHint shortcut="Enter" action="confirm" />
601
+ * <KeyboardShortcutHint shortcut="Esc" action="cancel" />
602
+ * </Byline>
603
+ * </Text>
604
+ */
605
+ declare function KeyboardShortcutHint({ shortcut, action, parens, bold, }: Props$2): React__default.ReactNode;
606
+
607
+ type ListItemProps = {
608
+ /**
609
+ * Whether this item is currently focused (keyboard selection).
610
+ * Shows the pointer indicator (❯) when true.
611
+ */
612
+ isFocused: boolean;
613
+ /**
614
+ * Whether this item is selected (chosen/checked).
615
+ * Shows the checkmark indicator (✓) when true.
616
+ * @default false
617
+ */
618
+ isSelected?: boolean;
619
+ /** The content to display for this item. */
620
+ children: ReactNode;
621
+ /** Optional description text displayed below the main content. */
622
+ description?: string;
623
+ /**
624
+ * Show a down arrow indicator instead of pointer (for scroll hints).
625
+ * Only applies when not focused.
626
+ */
627
+ showScrollDown?: boolean;
628
+ /**
629
+ * Show an up arrow indicator instead of pointer (for scroll hints).
630
+ * Only applies when not focused.
631
+ */
632
+ showScrollUp?: boolean;
633
+ /**
634
+ * Whether to apply automatic styling to the children based on focus/selection state.
635
+ * - When true (default): children are wrapped in Text with state-based colors
636
+ * - When false: children are rendered as-is, allowing custom styling
637
+ * @default true
638
+ */
639
+ styled?: boolean;
640
+ /**
641
+ * Whether this item is disabled. Disabled items show dimmed text and no indicators.
642
+ * @default false
643
+ */
644
+ disabled?: boolean;
645
+ /**
646
+ * Whether this ListItem should declare the terminal cursor position.
647
+ * Set false when a child (e.g. BaseTextInput) declares its own cursor.
648
+ * @default true
649
+ */
650
+ declareCursor?: boolean;
651
+ };
652
+ /**
653
+ * A list item component for selection UIs (dropdowns, multi-selects, menus).
654
+ *
655
+ * Handles the common pattern of:
656
+ * - Pointer indicator (❯) for focused items
657
+ * - Checkmark indicator (✓) for selected items
658
+ * - Scroll indicators (↓↑) for truncated lists
659
+ * - Color states for focus/selection
660
+ *
661
+ * @example
662
+ * // Basic usage in a selection list
663
+ * {options.map((option, i) => (
664
+ * <ListItem
665
+ * key={option.id}
666
+ * isFocused={focusIndex === i}
667
+ * isSelected={selectedId === option.id}
668
+ * >
669
+ * {option.label}
670
+ * </ListItem>
671
+ * ))}
672
+ *
673
+ * @example
674
+ * // With scroll indicators
675
+ * <ListItem isFocused={false} showScrollUp>First visible item</ListItem>
676
+ * ...
677
+ * <ListItem isFocused={false} showScrollDown>Last visible item</ListItem>
678
+ *
679
+ * @example
680
+ * // With description
681
+ * <ListItem isFocused isSelected={false} description="Secondary text here">
682
+ * Primary text
683
+ * </ListItem>
684
+ *
685
+ * @example
686
+ * // Custom children styling (styled=false)
687
+ * <ListItem isFocused styled={false}>
688
+ * <Text color="claude">Custom styled content</Text>
689
+ * </ListItem>
690
+ */
691
+ declare function ListItem({ isFocused, isSelected, children, description, showScrollDown, showScrollUp, styled, disabled, declareCursor, }: ListItemProps): React__default.ReactNode;
692
+
693
+ type LoadingStateProps = {
694
+ /** The loading message to display next to the spinner. */
695
+ message: string;
696
+ /**
697
+ * Display the message in bold.
698
+ * @default false
699
+ */
700
+ bold?: boolean;
701
+ /**
702
+ * Display the message in dimmed color.
703
+ * @default false
704
+ */
705
+ dimColor?: boolean;
706
+ /** Optional subtitle displayed below the main message. */
707
+ subtitle?: string;
708
+ };
709
+ /**
710
+ * A spinner with loading message for async operations.
711
+ *
712
+ * @example
713
+ * <LoadingState message="Loading..." />
714
+ *
715
+ * @example
716
+ * <LoadingState message="Loading sessions" bold subtitle="Fetching your sessions..." />
717
+ */
718
+ declare function LoadingState({ message, bold, dimColor, subtitle, }: LoadingStateProps): React__default.ReactNode;
719
+
720
+ type PaneProps = {
721
+ children: React__default.ReactNode;
722
+ color?: keyof Theme;
723
+ };
724
+ /**
725
+ * A pane -- a region of the terminal bounded by a colored top line with
726
+ * horizontal padding. Used by slash-command screens.
727
+ */
728
+ declare function Pane({ children, color }: PaneProps): React__default.ReactNode;
729
+
730
+ type Props$1 = {
731
+ children: React__default.ReactNode;
732
+ lock?: 'always' | 'offscreen';
733
+ };
734
+ declare function Ratchet({ children, lock, }: Props$1): React__default.ReactNode;
735
+
736
+ type TabsProps = {
737
+ children: Array<React__default.ReactElement<TabProps>>;
738
+ title?: string;
739
+ color?: keyof Theme;
740
+ defaultTab?: string;
741
+ hidden?: boolean;
742
+ useFullWidth?: boolean;
743
+ selectedTab?: string;
744
+ onTabChange?: (tabId: string) => void;
745
+ banner?: React__default.ReactNode;
746
+ disableNavigation?: boolean;
747
+ };
748
+ declare function Tabs({ title, color, defaultTab, children, hidden, useFullWidth, selectedTab: controlledSelectedTab, onTabChange, banner, disableNavigation, }: TabsProps): React__default.ReactNode;
749
+ type TabProps = {
750
+ title: string;
751
+ id?: string;
752
+ children: React__default.ReactNode;
753
+ };
754
+ declare function Tab({ title, id, children }: TabProps): React__default.ReactNode;
755
+ declare function useTabsWidth(): number | undefined;
756
+
757
+ type Props = {
758
+ /** The items to join with a middot separator */
759
+ children: React__default.ReactNode;
760
+ };
761
+ /**
762
+ * Joins children with a middot separator (" · ") for inline metadata display.
763
+ *
764
+ * Named after the publishing term "byline" - the line of metadata typically
765
+ * shown below a title (e.g., "John Doe · 5 min read · Mar 12").
766
+ *
767
+ * Automatically filters out null/undefined/false children and only renders
768
+ * separators between valid elements.
769
+ *
770
+ * @example
771
+ * // Basic usage: "Enter to confirm · Esc to cancel"
772
+ * <Text dimColor>
773
+ * <Byline>
774
+ * <KeyboardShortcutHint shortcut="Enter" action="confirm" />
775
+ * <KeyboardShortcutHint shortcut="Esc" action="cancel" />
776
+ * </Byline>
777
+ * </Text>
778
+ *
779
+ * @example
780
+ * // With conditional children: "Esc to cancel" (only one item shown)
781
+ * <Text dimColor>
782
+ * <Byline>
783
+ * {showEnter && <KeyboardShortcutHint shortcut="Enter" action="confirm" />}
784
+ * <KeyboardShortcutHint shortcut="Esc" action="cancel" />
785
+ * </Byline>
786
+ * </Text>
787
+ */
788
+ declare function Byline({ children }: Props): React__default.ReactNode;
789
+
790
+ /**
791
+ * Curried theme-aware color function. Resolves theme keys to raw color
792
+ * values before delegating to the ink renderer's colorize.
793
+ */
794
+ declare function color(c: keyof Theme | Color | undefined, theme: ThemeName, type?: ColorType): (text: string) => string;
795
+
796
+ type VirtualScrollOptions = {
797
+ itemCount: number;
798
+ /** Lines per item (default: 3) */
799
+ estimatedItemHeight?: number;
800
+ /** Extra items rendered above/below the viewport (default: 20) */
801
+ overscan?: number;
802
+ /** Visible terminal rows */
803
+ viewportHeight: number;
804
+ };
805
+ type VirtualScrollResult = {
806
+ startIndex: number;
807
+ endIndex: number;
808
+ visibleItems: number;
809
+ totalHeight: number;
810
+ scrollOffset: number;
811
+ scrollTo: (index: number) => void;
812
+ scrollToEnd: () => void;
813
+ /** Adjust scroll by delta items (+1 = down, -1 = up) */
814
+ onScroll: (delta: number) => void;
815
+ isAtTop: boolean;
816
+ isAtEnd: boolean;
817
+ };
818
+ type VirtualListProps<T> = {
819
+ items: T[];
820
+ renderItem: (item: T, index: number) => ReactNode;
821
+ viewportHeight: number;
822
+ estimatedItemHeight?: number;
823
+ overscan?: number;
824
+ };
825
+ declare function useVirtualScroll(options: VirtualScrollOptions): VirtualScrollResult;
826
+ declare function VirtualList<T>(props: VirtualListProps<T>): ReactNode;
827
+
828
+ type SearchMatch = {
829
+ index: number;
830
+ offset: number;
831
+ length: number;
832
+ };
833
+ type SearchOverlayProps = {
834
+ isOpen: boolean;
835
+ onClose: () => void;
836
+ onSearch: (query: string) => SearchMatch[];
837
+ onNavigate: (match: SearchMatch) => void;
838
+ matchCount?: number;
839
+ currentMatch?: number;
840
+ };
841
+ type UseSearchResult = {
842
+ query: string;
843
+ matches: SearchMatch[];
844
+ currentIndex: number;
845
+ next: () => void;
846
+ previous: () => void;
847
+ setQuery: (q: string) => void;
848
+ };
849
+ type UseSearchOptions = {
850
+ content: string[];
851
+ isActive: boolean;
852
+ };
853
+ declare function useSearch({ content, isActive }: UseSearchOptions): UseSearchResult;
854
+ declare function SearchOverlay({ isOpen, onClose, onSearch, onNavigate, }: SearchOverlayProps): React__default.ReactNode;
855
+
856
+ type WelcomeScreenProps = {
857
+ appName: string;
858
+ subtitle?: string;
859
+ version?: string;
860
+ tips?: string[];
861
+ logo?: React__default.ReactNode;
862
+ model?: string;
863
+ color?: string;
864
+ };
865
+ declare function ClawdLogo({ color }: {
866
+ color?: string;
867
+ }): React__default.ReactNode;
868
+ declare function WelcomeScreen({ appName, subtitle, version, tips, logo, model, color, }: WelcomeScreenProps): React__default.ReactNode;
869
+
870
+ type PermissionUIRequest = {
871
+ toolName: string;
872
+ description: string;
873
+ details?: string;
874
+ resolve: (decision: 'allow' | 'deny') => void;
875
+ };
876
+ type UseAgentOptions = {
877
+ agent: Agent;
878
+ onError?: (error: Error) => void;
879
+ };
880
+ type UseAgentResult = {
881
+ messages: Message[];
882
+ isLoading: boolean;
883
+ streamingContent: string | null;
884
+ permissionRequest: PermissionUIRequest | null;
885
+ submit: (input: string) => void;
886
+ cancel: () => void;
887
+ clearMessages: () => void;
888
+ };
889
+ declare function useAgent({ agent, onError }: UseAgentOptions): UseAgentResult;
890
+
891
+ type AgentContextValue = UseAgentResult & {
892
+ agent: Agent;
893
+ model: string;
894
+ };
895
+ declare const AgentContext: React__default.Context<AgentContextValue | null>;
896
+ type AgentProviderProps = {
897
+ agent: Agent;
898
+ model?: string;
899
+ onError?: (error: Error) => void;
900
+ children: React__default.ReactNode;
901
+ };
902
+ declare function AgentProvider({ agent, model, onError, children, }: AgentProviderProps): React__default.ReactNode;
903
+ declare function useAgentContext(): AgentContextValue;
904
+
905
+ type REPLCommand = {
906
+ name: string;
907
+ description: string;
908
+ onExecute: (args: string) => void;
909
+ };
910
+ type AgentREPLProps = {
911
+ agent: Agent;
912
+ model?: string;
913
+ commands?: REPLCommand[];
914
+ welcome?: React__default.ReactNode;
915
+ placeholder?: string;
916
+ onError?: (error: Error) => void;
917
+ onExit?: () => void;
918
+ };
919
+ declare function AgentREPL({ agent, model, commands, welcome, placeholder, onError, onExit, }: AgentREPLProps): React__default.ReactNode;
920
+
921
+ type AuthFlowUIProps = {
922
+ auth: AuthRegistry;
923
+ onComplete: (provider: LLMProvider, providerName: string, model: string) => void;
924
+ onCancel?: () => void;
925
+ title?: string;
281
926
  };
282
- declare function REPL({ onSubmit, onExit, messages, isLoading, streamingContent, commands, model, statusSegments, prefix, placeholder, history: externalHistory, renderMessage, spinner, }: REPLProps): React.ReactNode;
927
+ declare function AuthFlowUI({ auth, onComplete, onCancel, title, }: AuthFlowUIProps): React__default.ReactNode;
283
928
 
284
- export { type Command$1 as Command, type CommandBase, type CommandOnDone, CommandRegistry, type CommandResult, DEFAULT_BINDINGS, Divider, type JSXCommand, KeybindingSetup, type LocalCommand, type Message, MessageList, type MessageListProps, MultiSelect, type MultiSelectProps, ProgressBar, PromptInput, REPL, type REPLProps, Select, type SelectOption, type SelectProps, Spinner, StatusIcon, StatusLine, type StatusLineProps, type StatusLineSegment, StreamingText, type StreamingTextProps, clearCommand, createCommandRegistry, defineCommand, defineJSXCommand, defineLocalCommand, exitCommand, helpCommand, useKeybinding, useKeybindings, useStatusLine };
929
+ export { AgentContext, type AgentContextValue, AgentProvider, type AgentProviderProps, AgentREPL, type AgentREPLProps, AuthFlowUI, type AuthFlowUIProps, BashPermissionContent, Byline, ClawdLogo, type Command$1 as Command, type CommandBase, type CommandOnDone, CommandRegistry, type CommandResult, DEFAULT_BINDINGS, Dialog, type DiffLine, DiffView, type DiffViewProps, Divider, FileEditPermissionContent, FuzzyPicker, type JSXCommand, KeybindingSetup, KeyboardShortcutHint, ListItem, LoadingState, type LocalCommand, Markdown, MarkdownTable, type Message, type MessageContent, MessageList, type MessageListProps, MultiSelect, type MultiSelectProps, Pane, type PermissionAction, PermissionRequest, type PermissionRequestProps, type PermissionUIRequest, ProgressBar, PromptInput, REPL, type REPLProps, Ratchet, type SearchMatch, SearchOverlay, type SearchOverlayProps, Select, type SelectOption, type SelectProps, Spinner, StatusIcon, StatusLine, type StatusLineProps, type StatusLineSegment, StreamingMarkdown, StreamingText, type StreamingTextProps, Tab, Tabs, type TerminalSize, TextHoverColorContext, type Theme, type ThemeName, ThemeProvider, type ThemeSetting, ThemedBox, type Props$5 as ThemedBoxProps, ThemedText, type Props$4 as ThemedTextProps, type UseAgentOptions, type UseAgentResult, type UseSearchResult, VirtualList, type VirtualListProps, type VirtualScrollOptions, type VirtualScrollResult, WelcomeScreen, type WelcomeScreenProps, clearCommand, color, createCommandRegistry, defineCommand, defineJSXCommand, defineLocalCommand, exitCommand, getTheme, helpCommand, parseUnifiedDiff, useAgent, useAgentContext, useDoublePress, useKeybinding, useKeybindings, usePreviewTheme, useSearch, useStatusLine, useTabsWidth, useTerminalSize, useTheme, useThemeSetting, useVirtualScroll };