@code-yeongyu/senpi-tui 2026.7.31 → 2026.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -14
- package/dist/TuiAltScreen.d.ts +83 -0
- package/dist/TuiAltScreen.d.ts.map +1 -0
- package/dist/TuiAltScreen.js +687 -0
- package/dist/TuiAltScreen.js.map +1 -0
- package/dist/TuiMainScreen.d.ts +5 -0
- package/dist/TuiMainScreen.d.ts.map +1 -0
- package/dist/TuiMainScreen.js +5 -0
- package/dist/TuiMainScreen.js.map +1 -0
- package/dist/components/alt-screen-flash.d.ts +13 -0
- package/dist/components/alt-screen-flash.d.ts.map +1 -0
- package/dist/components/alt-screen-flash.js +36 -0
- package/dist/components/alt-screen-flash.js.map +1 -0
- package/dist/components/h-stack.d.ts +7 -0
- package/dist/components/h-stack.d.ts.map +1 -0
- package/dist/components/h-stack.js +43 -0
- package/dist/components/h-stack.js.map +1 -0
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/image.js +4 -4
- package/dist/components/image.js.map +1 -1
- package/dist/components/markdown.d.ts +2 -0
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +3 -2
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/scroll-view.d.ts +51 -0
- package/dist/components/scroll-view.d.ts.map +1 -0
- package/dist/components/scroll-view.js +163 -0
- package/dist/components/scroll-view.js.map +1 -0
- package/dist/components/settings-list.d.ts.map +1 -1
- package/dist/components/settings-list.js +3 -6
- package/dist/components/settings-list.js.map +1 -1
- package/dist/components/stack.d.ts +32 -0
- package/dist/components/stack.d.ts.map +1 -0
- package/dist/components/stack.js +109 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/v-stack.d.ts +8 -0
- package/dist/components/v-stack.d.ts.map +1 -0
- package/dist/components/v-stack.js +21 -0
- package/dist/components/v-stack.js.map +1 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/keybindings.d.ts +30 -0
- package/dist/keybindings.d.ts.map +1 -1
- package/dist/keybindings.js +18 -0
- package/dist/keybindings.js.map +1 -1
- package/dist/layout-node.d.ts +40 -0
- package/dist/layout-node.d.ts.map +1 -0
- package/dist/layout-node.js +6 -0
- package/dist/layout-node.js.map +1 -0
- package/dist/layout.d.ts +40 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +315 -0
- package/dist/layout.js.map +1 -0
- package/dist/mux.js +1 -1
- package/dist/mux.js.map +1 -1
- package/dist/terminal-image.d.ts +10 -0
- package/dist/terminal-image.d.ts.map +1 -1
- package/dist/terminal-image.js +61 -3
- package/dist/terminal-image.js.map +1 -1
- package/dist/terminal-text.d.ts +1 -0
- package/dist/terminal-text.d.ts.map +1 -1
- package/dist/terminal-text.js +12 -2
- package/dist/terminal-text.js.map +1 -1
- package/dist/tui.d.ts +37 -16
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +89 -21
- package/dist/tui.js.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +95 -4
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,25 +4,27 @@ Minimal terminal UI framework with differential rendering and synchronized outpu
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
7
|
+
- **Interchangeable Renderers**: Shared `TUI` interface with main-screen and alternate-screen implementations
|
|
8
|
+
- **Differential Rendering**: Updates only changed lines or viewport rows
|
|
9
|
+
- **Application-owned Scrolling**: Alternate-screen viewport supports mouse, trackpad, and keyboard navigation
|
|
8
10
|
- **Synchronized Output**: Uses CSI 2026 for atomic screen updates (no flicker)
|
|
9
11
|
- **Bracketed Paste Mode**: Handles large pastes correctly with markers for >10 line pastes
|
|
10
12
|
- **Component-based**: Simple Component interface with render() method
|
|
11
13
|
- **Theme Support**: Components accept theme interfaces for customizable styling
|
|
12
|
-
- **Built-in Components**: Text, TruncatedText, Input, Editor, Markdown, Loader, SelectList, SettingsList, Spacer, Image, Box, Container
|
|
14
|
+
- **Built-in Components**: Text, TruncatedText, Input, Editor, Markdown, Loader, SelectList, SettingsList, Spacer, Image, Box, Container, VStack, HStack, ScrollView
|
|
13
15
|
- **Inline Images**: Renders images in terminals that support Kitty or iTerm2 graphics protocols
|
|
14
16
|
- **Autocomplete Support**: File paths and slash commands
|
|
15
17
|
|
|
16
18
|
## Quick Start
|
|
17
19
|
|
|
18
20
|
```typescript
|
|
19
|
-
import { TUI, Text, Editor, ProcessTerminal, matchesKey } from "@earendil-works/pi-tui";
|
|
21
|
+
import { type TUI, Text, Editor, ProcessTerminal, TuiMainScreen, matchesKey } from "@earendil-works/pi-tui";
|
|
20
22
|
|
|
21
23
|
// Create terminal
|
|
22
24
|
const terminal = new ProcessTerminal();
|
|
23
25
|
|
|
24
|
-
// Create TUI
|
|
25
|
-
const tui = new
|
|
26
|
+
// Create the default main-screen renderer through the shared TUI interface
|
|
27
|
+
const tui: TUI = new TuiMainScreen(terminal);
|
|
26
28
|
|
|
27
29
|
// Add components
|
|
28
30
|
tui.addChild(new Text("Welcome to my app!"));
|
|
@@ -52,12 +54,20 @@ tui.start();
|
|
|
52
54
|
|
|
53
55
|
## Core API
|
|
54
56
|
|
|
55
|
-
### TUI
|
|
57
|
+
### TUI interface and renderers
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
`TUI` is the shared interface for component management, focus, overlays, input, lifecycle, terminal queries, and rendering. Choose a concrete renderer only when constructing the application:
|
|
60
|
+
|
|
61
|
+
- `TuiMainScreen` renders into the main terminal buffer and preserves terminal scrollback.
|
|
62
|
+
- `TuiAltScreen` renders a fixed-height viewport in the alternate terminal buffer with application-owned scrolling. When stopped, it restores the main buffer and prints the complete final document.
|
|
58
63
|
|
|
59
64
|
```typescript
|
|
60
|
-
|
|
65
|
+
import { type TUI, TuiAltScreen, TuiMainScreen } from "@earendil-works/pi-tui";
|
|
66
|
+
|
|
67
|
+
const tui: TUI = new TuiMainScreen(terminal);
|
|
68
|
+
// To use an application-owned viewport in the alternate terminal buffer instead:
|
|
69
|
+
// const tui: TUI = new TuiAltScreen(terminal);
|
|
70
|
+
|
|
61
71
|
tui.addChild(component);
|
|
62
72
|
tui.removeChild(component);
|
|
63
73
|
tui.start();
|
|
@@ -68,6 +78,53 @@ tui.requestRender(); // Request a re-render
|
|
|
68
78
|
tui.onDebug = () => console.log("Debug triggered");
|
|
69
79
|
```
|
|
70
80
|
|
|
81
|
+
### Alternate-screen viewport layouts
|
|
82
|
+
|
|
83
|
+
`TuiAltScreen` can render an explicit terminal-height layout. `VStack` and `HStack` allocate constrained regions, while `ScrollView` owns scrolling for one region. These semantics are intentionally unavailable on `TuiMainScreen`, where the terminal owns scrollback.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import {
|
|
87
|
+
Container,
|
|
88
|
+
isViewportTUI,
|
|
89
|
+
ScrollView,
|
|
90
|
+
Text,
|
|
91
|
+
VStack,
|
|
92
|
+
} from "@earendil-works/pi-tui";
|
|
93
|
+
|
|
94
|
+
const transcript = new Container();
|
|
95
|
+
transcript.addChild(new Text("History"));
|
|
96
|
+
|
|
97
|
+
const editorAndFooter = new VStack([
|
|
98
|
+
editor,
|
|
99
|
+
new Text("status"),
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
if (isViewportTUI(tui)) {
|
|
103
|
+
tui.setLayoutRoot(new VStack([
|
|
104
|
+
{
|
|
105
|
+
component: new ScrollView(transcript, {
|
|
106
|
+
follow: "end",
|
|
107
|
+
primary: true,
|
|
108
|
+
overscroll: "chain",
|
|
109
|
+
}),
|
|
110
|
+
basis: 0,
|
|
111
|
+
grow: 1,
|
|
112
|
+
minSize: 1,
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
component: editorAndFooter,
|
|
116
|
+
basis: "auto",
|
|
117
|
+
shrink: 1,
|
|
118
|
+
minSize: 1,
|
|
119
|
+
},
|
|
120
|
+
]));
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Stack entries support `basis`, `grow`, `shrink`, `minSize`, `maxSize`, and responsive `visible` callbacks. Mouse-wheel input targets the scroll view under the pointer and unused delta chains to outer scroll views by default. The primary scroll view receives the alternate-screen keyboard navigation actions and wheel input over non-scrollable regions. It can also jump between OSC 133 semantic prompt markers, matching common terminal prompt-navigation shortcuts.
|
|
125
|
+
|
|
126
|
+
Layout geometry is rebuilt for each requested frame. Stateful components are retained, and their existing rendered-line caches remain effective. Calling `render(width)` directly on these layout components produces an unbounded document, which is also used when alt mode restores the main screen.
|
|
127
|
+
|
|
71
128
|
### Overlays
|
|
72
129
|
|
|
73
130
|
Overlays render components on top of existing content without replacing it. Useful for dialogs, menus, and modal UI.
|
|
@@ -190,7 +247,7 @@ When a `Focusable` component has focus, TUI:
|
|
|
190
247
|
3. Positions the hardware terminal cursor at that location
|
|
191
248
|
4. Shows the hardware cursor only when `showHardwareCursor` is enabled
|
|
192
249
|
|
|
193
|
-
The cursor remains hidden by default. This keeps the fake cursor rendering, while still positioning the hardware cursor for terminals that track IME candidate windows with hidden cursors. Some terminals require a visible hardware cursor for IME positioning; enable it with the `
|
|
250
|
+
The cursor remains hidden by default. This keeps the fake cursor rendering, while still positioning the hardware cursor for terminals that track IME candidate windows with hidden cursors. Some terminals require a visible hardware cursor for IME positioning; enable it with the renderer constructor's `showHardwareCursor` argument, `setShowHardwareCursor(true)`, or `PI_HARDWARE_CURSOR=1`. The `Editor` and `Input` built-in components already implement this interface.
|
|
194
251
|
|
|
195
252
|
**Container components with embedded inputs:** When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child:
|
|
196
253
|
|
|
@@ -535,6 +592,10 @@ tui.addChild(image);
|
|
|
535
592
|
|
|
536
593
|
Supported formats: PNG, JPEG, GIF, WebP. Dimensions are parsed from the image headers automatically.
|
|
537
594
|
|
|
595
|
+
#### Alternate-screen image compatibility
|
|
596
|
+
|
|
597
|
+
`TuiAltScreen` supports inline images and partial viewport cropping in terminals that implement the Kitty graphics protocol, including Kitty and Ghostty. iTerm2's inline-image protocol does not provide operations to delete an existing placement or crop its source while scrolling. To prevent stale images from remaining over repainted content, `TuiAltScreen` renders image components as text placeholders in iTerm2. `TuiMainScreen` continues to render iTerm2 inline images normally.
|
|
598
|
+
|
|
538
599
|
## Autocomplete
|
|
539
600
|
|
|
540
601
|
### CombinedAutocompleteProvider
|
|
@@ -588,15 +649,17 @@ if (matchesKey(data, Key.enter)) {
|
|
|
588
649
|
- With modifiers: `Key.ctrl("c")`, `Key.shift("tab")`, `Key.alt("left")`, `Key.ctrlShift("p")`
|
|
589
650
|
- String format also works: `"enter"`, `"ctrl+c"`, `"shift+tab"`, `"ctrl+shift+p"`
|
|
590
651
|
|
|
591
|
-
##
|
|
652
|
+
## Rendering modes
|
|
592
653
|
|
|
593
|
-
|
|
654
|
+
`TuiMainScreen` uses three rendering strategies:
|
|
594
655
|
|
|
595
656
|
1. **First Render**: Output all lines without clearing scrollback
|
|
596
|
-
2. **Width Changed or Change Above Viewport**: Clear screen and
|
|
597
|
-
3. **Normal Update**: Move cursor to first changed line, clear to end, render changed lines
|
|
657
|
+
2. **Width Changed or Change Above Viewport**: Clear screen and fully re-render
|
|
658
|
+
3. **Normal Update**: Move the cursor to the first changed line, clear to the end, and render changed lines
|
|
659
|
+
|
|
660
|
+
`TuiAltScreen` owns a terminal-height viewport. Without an explicit layout root it preserves the legacy single-document scrolling behavior. With `setLayoutRoot()`, `VStack`, `HStack`, and nested `ScrollView` components can reserve fixed regions and independently scroll constrained regions. It updates changed viewport rows in place, follows streaming output while at the bottom, and preserves a manually selected scroll position while content grows. Mouse-wheel and configurable keyboard navigation scroll without modifying terminal scrollback, including jumps between OSC 133 semantic prompt markers. Clicking an OSC 8 hyperlink opens it with the configured URL handler. Dragging with the primary mouse button selects text and copies it to the clipboard with OSC 52; holding the drag at a scroll view's top or bottom edge auto-scrolls and extends the selection into off-screen content. Kitty images support vertical viewport cropping; iTerm2 inline images fall back to text because the iTerm2 protocol cannot delete or crop placements during viewport repainting.
|
|
598
661
|
|
|
599
|
-
|
|
662
|
+
Both renderers wrap updates in **synchronized output** (`\x1b[?2026h` ... `\x1b[?2026l`) for atomic, flicker-free rendering.
|
|
600
663
|
|
|
601
664
|
## Terminal Interface
|
|
602
665
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Terminal } from "./terminal.ts";
|
|
2
|
+
import { type Component, TuiBase, VIEWPORT_TUI, type ViewportTUI } from "./tui.ts";
|
|
3
|
+
export interface TuiAltScreenOptions {
|
|
4
|
+
/** Number of logical lines moved for each mouse-wheel event. */
|
|
5
|
+
wheelScrollLines?: number;
|
|
6
|
+
/** Capture mouse events for viewport scrolling and application-owned text selection. */
|
|
7
|
+
mouse?: boolean;
|
|
8
|
+
/** Open an OSC 8 hyperlink activated with a primary-button click. */
|
|
9
|
+
openUrl?: (url: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/** Alternate-screen TUI with a scrollable, application-owned viewport. */
|
|
12
|
+
export declare class TuiAltScreen extends TuiBase implements ViewportTUI {
|
|
13
|
+
readonly [VIEWPORT_TUI]: true;
|
|
14
|
+
private previousScreen;
|
|
15
|
+
private lastDocument;
|
|
16
|
+
private previousScreenWidth;
|
|
17
|
+
private previousScreenHeight;
|
|
18
|
+
private layoutRoot;
|
|
19
|
+
private currentLayout;
|
|
20
|
+
private readonly implicitDocument;
|
|
21
|
+
private readonly implicitScrollView;
|
|
22
|
+
private readonly flashes;
|
|
23
|
+
private altScreenActive;
|
|
24
|
+
private imageProtocol;
|
|
25
|
+
private savedCapabilities?;
|
|
26
|
+
private selectionAnchor?;
|
|
27
|
+
private selectionFocus?;
|
|
28
|
+
private selectionDragPointer?;
|
|
29
|
+
private selectionAutoScrollDirection;
|
|
30
|
+
private selectionAutoScrollTimer?;
|
|
31
|
+
private selectionPressActive;
|
|
32
|
+
private scrollbarDrag?;
|
|
33
|
+
private scrollbarHover?;
|
|
34
|
+
private pressedUrl?;
|
|
35
|
+
private selectionDragged;
|
|
36
|
+
private readonly wheelScrollLines;
|
|
37
|
+
private readonly mouseEnabled;
|
|
38
|
+
private readonly openUrl?;
|
|
39
|
+
constructor(terminal: Terminal, showHardwareCursor?: boolean, logDirectory?: string, options?: TuiAltScreenOptions);
|
|
40
|
+
get viewportTop(): number;
|
|
41
|
+
get isFollowingOutput(): boolean;
|
|
42
|
+
setLayoutRoot(component: Component | undefined): void;
|
|
43
|
+
render(width: number): string[];
|
|
44
|
+
invalidate(): void;
|
|
45
|
+
protected getMountedRoots(): readonly Component[];
|
|
46
|
+
private getPrimaryScrollView;
|
|
47
|
+
protected beforeTerminalStart(): void;
|
|
48
|
+
protected beforeTerminalStop(): void;
|
|
49
|
+
protected afterTerminalStop(): void;
|
|
50
|
+
private deleteAltScreenKittyImages;
|
|
51
|
+
protected resetRenderState(): void;
|
|
52
|
+
scrollBy(lines: number): void;
|
|
53
|
+
scrollToTop(): void;
|
|
54
|
+
scrollToBottom(): void;
|
|
55
|
+
private scrollToPrompt;
|
|
56
|
+
/** Show a transient message in the alternate-screen flash stack. */
|
|
57
|
+
flash(message: string, durationMs?: number): void;
|
|
58
|
+
private handleViewportInput;
|
|
59
|
+
private parseWheelEvent;
|
|
60
|
+
private routeWheel;
|
|
61
|
+
private parseSgrMouseEvent;
|
|
62
|
+
private getScrollbarTargetAt;
|
|
63
|
+
private setScrollbarHover;
|
|
64
|
+
private updateScrollbarHover;
|
|
65
|
+
private stopScrollbarHover;
|
|
66
|
+
private handleScrollbarMouseEvent;
|
|
67
|
+
private stopScrollbarDrag;
|
|
68
|
+
private getScrollSelectionPoint;
|
|
69
|
+
private getSelectionPoint;
|
|
70
|
+
private updateSelectionAutoScroll;
|
|
71
|
+
private autoScrollSelection;
|
|
72
|
+
private stopSelectionAutoScroll;
|
|
73
|
+
private handleSelectionMouseEvent;
|
|
74
|
+
private getSelectionBounds;
|
|
75
|
+
private getSelectionColumns;
|
|
76
|
+
private copySelectionToClipboard;
|
|
77
|
+
private applySelectionHighlight;
|
|
78
|
+
private applySelection;
|
|
79
|
+
private isMouseSequence;
|
|
80
|
+
private compositeFlashes;
|
|
81
|
+
protected doRender(): void;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=TuiAltScreen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TuiAltScreen.d.ts","sourceRoot":"","sources":["../src/TuiAltScreen.ts"],"names":[],"mappings":"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"}
|