@oh-my-pi/pi-tui 14.1.1 → 14.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/CHANGELOG.md +4 -0
- package/package.json +3 -3
- package/src/tui.ts +29 -13
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
- Changed truncation debug logging to run only when `debugRedraw` is enabled
|
|
14
14
|
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Fixed viewport jumping during streaming and session swap by tracking actual content height instead of high-water mark
|
|
18
|
+
|
|
15
19
|
## [14.0.5] - 2026-04-11
|
|
16
20
|
|
|
17
21
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-tui",
|
|
4
|
-
"version": "14.
|
|
4
|
+
"version": "14.2.0",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"fmt": "biome format --write ."
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@oh-my-pi/pi-natives": "
|
|
41
|
-
"@oh-my-pi/pi-utils": "
|
|
40
|
+
"@oh-my-pi/pi-natives": "14.2.0",
|
|
41
|
+
"@oh-my-pi/pi-utils": "14.2.0",
|
|
42
42
|
"marked": "^17.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
package/src/tui.ts
CHANGED
|
@@ -230,7 +230,7 @@ export class TUI extends Container {
|
|
|
230
230
|
#sixelProbeUnsubscribe?: () => void;
|
|
231
231
|
#showHardwareCursor = $flag("PI_HARDWARE_CURSOR");
|
|
232
232
|
#clearOnShrink = $flag("PI_CLEAR_ON_SHRINK"); // Clear empty rows when content shrinks (default: off)
|
|
233
|
-
#maxLinesRendered = 0; //
|
|
233
|
+
#maxLinesRendered = 0; // Line count from last render, used for viewport calculation
|
|
234
234
|
#fullRedrawCount = 0;
|
|
235
235
|
#stopped = false;
|
|
236
236
|
|
|
@@ -1066,11 +1066,11 @@ export class TUI extends Container {
|
|
|
1066
1066
|
return;
|
|
1067
1067
|
}
|
|
1068
1068
|
|
|
1069
|
-
// Content shrunk below the
|
|
1069
|
+
// Content shrunk below the previous render and no overlays - re-render to clear empty rows
|
|
1070
1070
|
// (overlays need the padding, so only do this when no overlays are active)
|
|
1071
1071
|
// Configurable via setClearOnShrink() or PI_CLEAR_ON_SHRINK=0 env var
|
|
1072
|
-
if (this.#clearOnShrink && newLines.length < this.#
|
|
1073
|
-
logRedraw(`clearOnShrink (
|
|
1072
|
+
if (this.#clearOnShrink && newLines.length < this.#previousLines.length && this.overlayStack.length === 0) {
|
|
1073
|
+
logRedraw(`clearOnShrink (prev=${this.#previousLines.length}, new=${newLines.length})`);
|
|
1074
1074
|
fullRender(true);
|
|
1075
1075
|
return;
|
|
1076
1076
|
}
|
|
@@ -1144,18 +1144,34 @@ export class TUI extends Container {
|
|
|
1144
1144
|
this.#previousLines = newLines;
|
|
1145
1145
|
this.#previousWidth = width;
|
|
1146
1146
|
this.#previousHeight = height;
|
|
1147
|
-
this.#
|
|
1147
|
+
this.#maxLinesRendered = newLines.length;
|
|
1148
|
+
this.#viewportTopRow = Math.max(0, newLines.length - height);
|
|
1148
1149
|
return;
|
|
1149
1150
|
}
|
|
1150
1151
|
|
|
1151
1152
|
// Check if firstChanged is above what was previously visible
|
|
1152
|
-
// Use previousLines.length (not maxLinesRendered) to avoid false positives after content shrinks
|
|
1153
1153
|
const previousContentViewportTop = Math.max(0, this.#previousLines.length - height);
|
|
1154
1154
|
if (firstChanged < previousContentViewportTop) {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1155
|
+
const newViewportTop = Math.max(0, newLines.length - height);
|
|
1156
|
+
if (newViewportTop < previousContentViewportTop) {
|
|
1157
|
+
// Viewport needs to shift up — can only be done with a full redraw
|
|
1158
|
+
logRedraw(`viewport shift up (new=${newViewportTop} < prev=${previousContentViewportTop})`);
|
|
1159
|
+
fullRender(true);
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
// Viewport is stable or shifting down — skip invisible above-viewport changes
|
|
1163
|
+
firstChanged = previousContentViewportTop;
|
|
1164
|
+
if (lastChanged < firstChanged) {
|
|
1165
|
+
// All changes are above the viewport — nothing visible to update
|
|
1166
|
+
this.#cursorRow = Math.max(0, newLines.length - 1);
|
|
1167
|
+
this.#maxLinesRendered = newLines.length;
|
|
1168
|
+
this.#viewportTopRow = Math.max(0, newLines.length - height);
|
|
1169
|
+
this.#positionHardwareCursor(cursorPos, newLines.length);
|
|
1170
|
+
this.#previousLines = newLines;
|
|
1171
|
+
this.#previousWidth = width;
|
|
1172
|
+
this.#previousHeight = height;
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1159
1175
|
}
|
|
1160
1176
|
|
|
1161
1177
|
// Render from first changed line to end
|
|
@@ -1272,9 +1288,9 @@ export class TUI extends Container {
|
|
|
1272
1288
|
// hardwareCursorRow tracks actual terminal cursor position (for movement)
|
|
1273
1289
|
this.#cursorRow = Math.max(0, newLines.length - 1);
|
|
1274
1290
|
this.#hardwareCursorRow = finalCursorRow;
|
|
1275
|
-
// Track
|
|
1276
|
-
this.#maxLinesRendered =
|
|
1277
|
-
this.#viewportTopRow = Math.max(0,
|
|
1291
|
+
// Track content height for viewport calculation
|
|
1292
|
+
this.#maxLinesRendered = newLines.length;
|
|
1293
|
+
this.#viewportTopRow = Math.max(0, newLines.length - height);
|
|
1278
1294
|
|
|
1279
1295
|
// Position hardware cursor for IME
|
|
1280
1296
|
this.#positionHardwareCursor(cursorPos, newLines.length);
|