You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Update the terminal UI library to upstream pi v1.0.1, which keeps WezTerm images while scrolling, converts non-PNG images for Kitty, and fixes ANSI color order when a styled line is cut.
`Color` is an indexed ANSI color, an sRGB color, or an OKLCH color. Every color converts to sRGB, so color math such as `mixColors()` always works. Indices 0-15 follow the user's terminal palette, so their sRGB values are approximations. `styleText()` converts colors to truecolor or 256-color output based on the requested terminal mode.
98
+
99
+
`parseColor()` also accepts OKHSL, as in `okhsl(250 60% 55%)`; `okhslColor()` builds it in code and `colorToOkhsl()` reads any color's OKHSL channels. OKHSL saturation is relative to the most the sRGB gamut allows at the hue and lightness, so every value is in gamut and equal saturation looks equally colorful across hues. OKHSL colors are converted to sRGB when created.
100
+
101
+
Conversions are not cached. OKLCH colors, especially ones outside the sRGB gamut, are more expensive to convert than sRGB or indexed colors. For colors used on every render, convert once and reuse the result:
102
+
103
+
```typescript
104
+
const { r, g, b } =colorToRgb(mixColors(accent, background, 0.2));
105
+
const foreground =rgbColor(r, g, b); // cheap to render repeatedly
`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.
112
+
113
+
```typescript
114
+
import {
115
+
Container,
116
+
isViewportTUI,
117
+
ScrollView,
118
+
Text,
119
+
VStack,
120
+
} from"@earendil-works/pi-tui";
121
+
122
+
const transcript =newContainer();
123
+
transcript.addChild(newText("History"));
124
+
125
+
const editorAndFooter =newVStack([
126
+
editor,
127
+
newText("status"),
128
+
]);
129
+
130
+
if (isViewportTUI(tui)) {
131
+
tui.setLayoutRoot(newVStack([
132
+
{
133
+
component: newScrollView(transcript, {
134
+
follow: "end",
135
+
primary: true,
136
+
overscroll: "chain",
137
+
}),
138
+
basis: 0,
139
+
grow: 1,
140
+
minSize: 1,
141
+
},
142
+
{
143
+
component: editorAndFooter,
144
+
basis: "auto",
145
+
shrink: 1,
146
+
minSize: 1,
147
+
},
148
+
]));
149
+
}
150
+
```
151
+
152
+
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. Press `Ctrl+Shift+F` to open or close its bordered search panel. The panel shows the configured previous/next shortcuts and provides clickable arrow controls; by default, `Enter`/`Ctrl+G` and `Shift+Enter`/`Ctrl+Shift+G` move between matches, and `Escape` also closes search. `TuiAltScreenOptions.searchMatchStyle` and `searchCurrentMatchStyle` customize match highlighting, while `searchNavigationButtonStyle` styles each arrow button and receives its hover state. `TuiAltScreenOptions.scrollToEndIndicator` renders a clickable label centered on the last row of a `follow: "end"` primary scroll view while it is scrolled away from the end; clicking it resumes end-following.
153
+
154
+
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.
155
+
71
156
### Overlays
72
157
73
158
Overlays render components on top of existing content without replacing it. Useful for dialogs, menus, and modal UI.
|`render(width)`| Returns an array of strings, one per line. Each line **must not exceed `width`** or the TUI will error. Use `truncateToWidth()` or manual wrapping to ensure this. |
164
250
|`handleInput?(data)`| Called when the component has focus and receives keyboard input. The `data` string contains raw terminal input (may include ANSI escape sequences). |
165
-
|`invalidate?()`| Called to clear any cached render state. Components should re-render from scratch on the next `render()` call. |
251
+
|`handleMouse?(event)`| Called by `TuiAltScreen` for normalized pointer input targeted at the component. |
252
+
|`invalidate()`| Required. Clear any cached render state so the next `render()` starts from scratch. Components without cached render state can use an empty implementation. |
166
253
167
254
The TUI appends a full SGR reset and OSC 8 reset at the end of each rendered line. Styles do not carry across lines. If you emit multi-line text with styling, reapply styles per line or use `wrapTextWithAnsi()` so styles are preserved for each wrapped line.
168
255
@@ -181,6 +268,8 @@ class MyInput implements Component, Focusable {
-**Commit:**`53816d7dcc5ebe3a0eedec3cd07196c3a66d83fd` (2026-09-14; v0.85.1 plus upstream main through this commit)
11
+
-**Commit:**`a7229ddc21810d6245105978033b7df645ecc2f7` (2026-10-03; upstream tag v1.0.1)
12
+
-**Darwin prebuilds:** rebuilt locally from `native/darwin/src/darwin-platform.m` with `native/darwin/build.sh`, not copied from upstream. Exports and linked libraries match the upstream v1.0.1 prebuilds.
12
13
-**This commit is an upstream marker.** It may not exist in this repo's object database.
0 commit comments