@gajae-code/tui 0.12.5 → 0.12.6
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 +24 -0
- package/dist/types/tui.d.ts +41 -0
- package/package.json +3 -3
- package/src/components/select-list.ts +1 -1
- package/src/tui.ts +140 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.12.6] - 2026-07-31
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Select-list no-match rows now stay within the requested render width instead of wrapping into extra terminal lines after narrow resizes (#3600).
|
|
9
|
+
|
|
10
|
+
## [0.12.5] - 2026-07-30
|
|
11
|
+
|
|
5
12
|
## [0.12.5] - 2026-07-30
|
|
6
13
|
|
|
7
14
|
## [0.12.4] - 2026-07-30
|
|
@@ -10,6 +17,23 @@
|
|
|
10
17
|
|
|
11
18
|
## [0.12.2] - 2026-07-30
|
|
12
19
|
|
|
20
|
+
## [0.12.1] - 2026-07-29
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- `Tui` now exposes renderer-owned viewport observations so tests and evidence capture can assert against committed paint state instead of re-deriving geometry: `getViewportObservation()` (returns a defensive copy of the latest committed observation), `getViewportAnchorSnapshot()`, `getViewportAnchorComponent()`, `getFocusedComponent()`, and `setViewportSelection()`, plus the `TuiViewportObservation` and `MouseSelectionPoint` types.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Alternate-scroll mode (`DECSET 1007`) is now explicitly disabled at startup, on every mouse-capture toggle, at stop, and during emergency restore, so no host translates wheel input into cursor keys. While mouse capture is off this leaves wheel scrollback to the host terminal or multiplexer; while capture is on GJC consumes SGR wheel reports itself, and the reset removes a conflicting second translation path. Hosts that never answer a `DECRQM ?1007$p` query (Apple Terminal among them) cannot report this mode, so it is reset unconditionally rather than conditionally on a reported state.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- The renderer's reported cursor column is now clamped to the last real cell, so it always names a column that exists in the current terminal width. On the wire this is unchanged (a terminal already clamps `CHA` to the last column), but the reported value is now truthful for callers reading it through the viewport observation.
|
|
32
|
+
|
|
33
|
+
## [0.12.3] - 2026-07-30
|
|
34
|
+
|
|
35
|
+
## [0.12.2] - 2026-07-30
|
|
36
|
+
|
|
13
37
|
## [0.12.1] - 2026-07-29
|
|
14
38
|
|
|
15
39
|
### Fixed
|
package/dist/types/tui.d.ts
CHANGED
|
@@ -29,6 +29,10 @@ type OverlayMouseBounds = {
|
|
|
29
29
|
termWidth: number;
|
|
30
30
|
termHeight: number;
|
|
31
31
|
};
|
|
32
|
+
export type MouseSelectionPoint = {
|
|
33
|
+
line: number;
|
|
34
|
+
column: number;
|
|
35
|
+
};
|
|
32
36
|
/** Parse xterm SGR mouse reports for wheel, left-click, drag, and release events. */
|
|
33
37
|
export declare function parseSgrMouseEvent(data: string): MouseEvent | undefined;
|
|
34
38
|
export interface Component {
|
|
@@ -84,6 +88,30 @@ export declare const CURSOR_MARKER = "\u001B_pi:c\u0007";
|
|
|
84
88
|
export { visibleWidth };
|
|
85
89
|
/** Durable source identifier for a semantically anchored viewport row. */
|
|
86
90
|
export type ViewportAnchorId = string;
|
|
91
|
+
/** Immutable renderer-owned details of the most recently rendered viewport. */
|
|
92
|
+
export interface TuiViewportObservation {
|
|
93
|
+
transcriptCapacity: number;
|
|
94
|
+
pinBoundary: {
|
|
95
|
+
row: number;
|
|
96
|
+
pinned: boolean;
|
|
97
|
+
};
|
|
98
|
+
manualHistory: boolean;
|
|
99
|
+
newOutputNoticeVisible: boolean;
|
|
100
|
+
outputRevision: string | null;
|
|
101
|
+
focused: boolean;
|
|
102
|
+
cursor: {
|
|
103
|
+
row: number;
|
|
104
|
+
col: number;
|
|
105
|
+
visible: boolean;
|
|
106
|
+
} | null;
|
|
107
|
+
selection: {
|
|
108
|
+
start: MouseSelectionPoint;
|
|
109
|
+
end: MouseSelectionPoint;
|
|
110
|
+
} | null;
|
|
111
|
+
semanticAnchor: (ViewportAnchorRow & {
|
|
112
|
+
frameRow: number;
|
|
113
|
+
}) | null;
|
|
114
|
+
}
|
|
87
115
|
export interface ViewportAnchorRow {
|
|
88
116
|
id: ViewportAnchorId;
|
|
89
117
|
graphemeStart: number;
|
|
@@ -258,6 +286,17 @@ export declare class TUI extends Container {
|
|
|
258
286
|
*/
|
|
259
287
|
setClearOnShrink(enabled: boolean): void;
|
|
260
288
|
setFocus(component: Component | null): void;
|
|
289
|
+
/** Returns the currently focused component without exposing mutable focus state. */
|
|
290
|
+
getFocusedComponent(): Component | null;
|
|
291
|
+
/** Returns a defensive snapshot of the latest renderer-owned viewport anchors. */
|
|
292
|
+
getViewportAnchorSnapshot(): {
|
|
293
|
+
startRow: number;
|
|
294
|
+
anchors: Array<ViewportAnchorRow | null>;
|
|
295
|
+
} | null;
|
|
296
|
+
/** Returns a defensive snapshot of renderer-owned viewport geometry. */
|
|
297
|
+
getViewportObservation(): TuiViewportObservation | null;
|
|
298
|
+
/** Selects a zero-based painted viewport cell range using the same renderer path as mouse dragging. */
|
|
299
|
+
setViewportSelection(start: MouseSelectionPoint, end: MouseSelectionPoint): void;
|
|
261
300
|
removeChild(component: Component): void;
|
|
262
301
|
clear(): void;
|
|
263
302
|
setBottomPinnedComponent(component: Component | null): void;
|
|
@@ -265,6 +304,8 @@ export declare class TUI extends Container {
|
|
|
265
304
|
setViewportOutputSource(source: ViewportOutputSource | null): void;
|
|
266
305
|
/** Register the direct child whose rows are eligible for semantic viewport anchoring. */
|
|
267
306
|
setViewportAnchorComponent(component: Component | null): void;
|
|
307
|
+
/** Returns the direct component registered as the semantic viewport anchor source. */
|
|
308
|
+
getViewportAnchorComponent(): Component | null;
|
|
268
309
|
/** Clear manual viewport ownership before replacing the transcript identity namespace. */
|
|
269
310
|
resetViewportAnchorIntent(): void;
|
|
270
311
|
/** Allow one semantic-neighbor reconciliation after a definitive same-transcript rebuild. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/tui",
|
|
4
|
-
"version": "0.12.
|
|
4
|
+
"version": "0.12.6",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"fmt": "biome format --write ."
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@gajae-code/natives": "0.12.
|
|
40
|
-
"@gajae-code/utils": "0.12.
|
|
39
|
+
"@gajae-code/natives": "0.12.6",
|
|
40
|
+
"@gajae-code/utils": "0.12.6",
|
|
41
41
|
"lru-cache": "11.3.6",
|
|
42
42
|
"marked": "18.0.6"
|
|
43
43
|
},
|
|
@@ -118,7 +118,7 @@ export class SelectList implements Component {
|
|
|
118
118
|
|
|
119
119
|
// If no items match filter, show message
|
|
120
120
|
if (this.#filteredItems.length === 0) {
|
|
121
|
-
lines.push(this.theme.noMatch(" No matching commands"));
|
|
121
|
+
lines.push(truncateToWidth(this.theme.noMatch(" No matching commands"), Math.max(0, width), Ellipsis.Omit));
|
|
122
122
|
return lines;
|
|
123
123
|
}
|
|
124
124
|
|
package/src/tui.ts
CHANGED
|
@@ -83,7 +83,7 @@ type OverlayMouseBounds = {
|
|
|
83
83
|
termHeight: number;
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
type MouseSelectionPoint = {
|
|
86
|
+
export type MouseSelectionPoint = {
|
|
87
87
|
line: number;
|
|
88
88
|
column: number;
|
|
89
89
|
};
|
|
@@ -176,6 +176,18 @@ export { visibleWidth };
|
|
|
176
176
|
|
|
177
177
|
/** Durable source identifier for a semantically anchored viewport row. */
|
|
178
178
|
export type ViewportAnchorId = string;
|
|
179
|
+
/** Immutable renderer-owned details of the most recently rendered viewport. */
|
|
180
|
+
export interface TuiViewportObservation {
|
|
181
|
+
transcriptCapacity: number;
|
|
182
|
+
pinBoundary: { row: number; pinned: boolean };
|
|
183
|
+
manualHistory: boolean;
|
|
184
|
+
newOutputNoticeVisible: boolean;
|
|
185
|
+
outputRevision: string | null;
|
|
186
|
+
focused: boolean;
|
|
187
|
+
cursor: { row: number; col: number; visible: boolean } | null;
|
|
188
|
+
selection: { start: MouseSelectionPoint; end: MouseSelectionPoint } | null;
|
|
189
|
+
semanticAnchor: (ViewportAnchorRow & { frameRow: number }) | null;
|
|
190
|
+
}
|
|
179
191
|
|
|
180
192
|
export interface ViewportAnchorRow {
|
|
181
193
|
id: ViewportAnchorId;
|
|
@@ -731,6 +743,7 @@ export class TUI extends Container {
|
|
|
731
743
|
#manualViewportFallbackAnchors: ManualViewportAnchor[] = [];
|
|
732
744
|
#reconcileMissingViewportAnchor = false;
|
|
733
745
|
#lastCursorPosition: { row: number; col: number } | null = null;
|
|
746
|
+
#latestViewportObservation: TuiViewportObservation | null = null;
|
|
734
747
|
#sixelProbePendingDa = false;
|
|
735
748
|
#sixelProbePendingGraphics = false;
|
|
736
749
|
#sixelProbeBuffer = "";
|
|
@@ -890,6 +903,61 @@ export class TUI extends Container {
|
|
|
890
903
|
component.focused = true;
|
|
891
904
|
}
|
|
892
905
|
}
|
|
906
|
+
/** Returns the currently focused component without exposing mutable focus state. */
|
|
907
|
+
getFocusedComponent(): Component | null {
|
|
908
|
+
return this.#focusedComponent;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/** Returns a defensive snapshot of the latest renderer-owned viewport anchors. */
|
|
912
|
+
getViewportAnchorSnapshot(): { startRow: number; anchors: Array<ViewportAnchorRow | null> } | null {
|
|
913
|
+
if (this.#viewportAnchorFrame === null) return null;
|
|
914
|
+
return {
|
|
915
|
+
startRow: this.#viewportAnchorFrame.startRow,
|
|
916
|
+
anchors: this.#viewportAnchorFrame.anchors.map(anchor => (anchor ? { ...anchor } : null)),
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/** Returns a defensive snapshot of renderer-owned viewport geometry. */
|
|
921
|
+
getViewportObservation(): TuiViewportObservation | null {
|
|
922
|
+
const observation = this.#latestViewportObservation;
|
|
923
|
+
return observation
|
|
924
|
+
? {
|
|
925
|
+
...observation,
|
|
926
|
+
pinBoundary: { ...observation.pinBoundary },
|
|
927
|
+
cursor: observation.cursor ? { ...observation.cursor } : null,
|
|
928
|
+
selection: observation.selection
|
|
929
|
+
? { start: { ...observation.selection.start }, end: { ...observation.selection.end } }
|
|
930
|
+
: null,
|
|
931
|
+
semanticAnchor: observation.semanticAnchor ? { ...observation.semanticAnchor } : null,
|
|
932
|
+
}
|
|
933
|
+
: null;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/** Selects a zero-based painted viewport cell range using the same renderer path as mouse dragging. */
|
|
937
|
+
setViewportSelection(start: MouseSelectionPoint, end: MouseSelectionPoint): void {
|
|
938
|
+
if (!this.options.copySelection) return;
|
|
939
|
+
// Non-finite coordinates would survive the clamp below as NaN, latch
|
|
940
|
+
// #mouseSelectionDragged, and force a repaint every frame while reporting a
|
|
941
|
+
// NaN selection through getViewportObservation(). Reject them the same way
|
|
942
|
+
// scrollViewportBy does rather than storing an unpaintable selection.
|
|
943
|
+
if (![start.line, start.column, end.line, end.column].every(value => Number.isFinite(value))) return;
|
|
944
|
+
const map = (point: MouseSelectionPoint): MouseSelectionPoint | null => {
|
|
945
|
+
const row = Math.max(0, Math.min(this.terminal.rows - 1, point.line));
|
|
946
|
+
const column = Math.max(0, Math.min(this.terminal.columns - 1, point.column));
|
|
947
|
+
return this.#mouseSelectionPoint({ x: column + 1, y: row + 1, kind: "drag" });
|
|
948
|
+
};
|
|
949
|
+
const mappedStart = map(start);
|
|
950
|
+
const mappedEnd = map(end);
|
|
951
|
+
if (mappedStart === null || mappedEnd === null) {
|
|
952
|
+
this.#clearMouseSelection();
|
|
953
|
+
this.requestRender(false, "selection");
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
this.#mouseSelectionStart = mappedStart;
|
|
957
|
+
this.#mouseSelectionEnd = mappedEnd;
|
|
958
|
+
this.#mouseSelectionDragged = true;
|
|
959
|
+
this.requestRender(false, "selection");
|
|
960
|
+
}
|
|
893
961
|
|
|
894
962
|
override removeChild(component: Component): void {
|
|
895
963
|
this.#invalidateFocusForRemovedTree(component);
|
|
@@ -952,6 +1020,10 @@ export class TUI extends Container {
|
|
|
952
1020
|
this.#viewportAnchorComponent = component;
|
|
953
1021
|
this.#viewportAnchorFrame = null;
|
|
954
1022
|
}
|
|
1023
|
+
/** Returns the direct component registered as the semantic viewport anchor source. */
|
|
1024
|
+
getViewportAnchorComponent(): Component | null {
|
|
1025
|
+
return this.#viewportAnchorComponent;
|
|
1026
|
+
}
|
|
955
1027
|
|
|
956
1028
|
/** Clear manual viewport ownership before replacing the transcript identity namespace. */
|
|
957
1029
|
resetViewportAnchorIntent(): void {
|
|
@@ -2439,7 +2511,7 @@ export class TUI extends Container {
|
|
|
2439
2511
|
if (markerIndex !== -1) {
|
|
2440
2512
|
// Calculate visual column (width of text before marker)
|
|
2441
2513
|
const beforeMarker = line.slice(0, markerIndex);
|
|
2442
|
-
const col = visibleWidth(beforeMarker);
|
|
2514
|
+
const col = Math.max(0, Math.min(Math.max(0, this.terminal.columns - 1), visibleWidth(beforeMarker)));
|
|
2443
2515
|
|
|
2444
2516
|
// Strip marker from the line
|
|
2445
2517
|
lines[row] = line.slice(0, markerIndex) + line.slice(markerIndex + CURSOR_MARKER.length);
|
|
@@ -2909,6 +2981,8 @@ export class TUI extends Container {
|
|
|
2909
2981
|
emittedRegions,
|
|
2910
2982
|
);
|
|
2911
2983
|
onPainted?.();
|
|
2984
|
+
this.#paintedManualOutputNotice = paintManual && this.#manualOutputNotice;
|
|
2985
|
+
this.#recordPaintedViewportObservation(nextViewportTop, height, paintManual);
|
|
2912
2986
|
});
|
|
2913
2987
|
if (!contentWritten) return false;
|
|
2914
2988
|
|
|
@@ -2918,6 +2992,63 @@ export class TUI extends Container {
|
|
|
2918
2992
|
}
|
|
2919
2993
|
return writeSucceeded;
|
|
2920
2994
|
}
|
|
2995
|
+
#recordPaintedViewportObservation(viewportTop: number, height: number, paintManual: boolean): void {
|
|
2996
|
+
const transcriptCapacity = this.#manualTranscriptCapacity(height);
|
|
2997
|
+
const anchorFrame = this.#viewportAnchorFrame;
|
|
2998
|
+
const semanticAnchor =
|
|
2999
|
+
anchorFrame === null
|
|
3000
|
+
? null
|
|
3001
|
+
: (this.#committedTranscriptRows
|
|
3002
|
+
.map((transcriptRow, screenRow) => {
|
|
3003
|
+
if (transcriptRow === null) return null;
|
|
3004
|
+
const anchor = anchorFrame.anchors[transcriptRow - anchorFrame.startRow];
|
|
3005
|
+
return anchor ? { ...anchor, frameRow: screenRow } : null;
|
|
3006
|
+
})
|
|
3007
|
+
.find(anchor => anchor !== null) ?? null);
|
|
3008
|
+
const cursor = this.#lastCursorPosition;
|
|
3009
|
+
let cursorRow: number | null = null;
|
|
3010
|
+
if (cursor !== null) {
|
|
3011
|
+
if (paintManual && cursor.row >= this.#manualTranscriptLineCount) {
|
|
3012
|
+
const noticeRows = this.#manualOutputNotice && height > this.#manualSuffixLineCount ? 1 : 0;
|
|
3013
|
+
cursorRow = transcriptCapacity + noticeRows + (cursor.row - this.#manualTranscriptLineCount);
|
|
3014
|
+
} else if (paintManual) {
|
|
3015
|
+
cursorRow = this.#committedTranscriptRows.indexOf(cursor.row);
|
|
3016
|
+
} else {
|
|
3017
|
+
cursorRow = cursor.row - viewportTop;
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
const cursorVisible = cursorRow !== null && cursorRow >= 0 && cursorRow < height;
|
|
3021
|
+
const selectedRange = this.#mouseSelectionDragged ? this.#orderedMouseSelection() : null;
|
|
3022
|
+
const paintedSelection =
|
|
3023
|
+
selectedRange === null
|
|
3024
|
+
? null
|
|
3025
|
+
: {
|
|
3026
|
+
start: { line: selectedRange.start.line - viewportTop, column: selectedRange.start.column },
|
|
3027
|
+
end: { line: selectedRange.end.line - viewportTop, column: selectedRange.end.column },
|
|
3028
|
+
};
|
|
3029
|
+
this.#latestViewportObservation = {
|
|
3030
|
+
transcriptCapacity,
|
|
3031
|
+
pinBoundary: { row: transcriptCapacity, pinned: this.#bottomPinnedComponent !== null },
|
|
3032
|
+
manualHistory: paintManual,
|
|
3033
|
+
newOutputNoticeVisible: paintManual && this.#paintedManualOutputNotice,
|
|
3034
|
+
outputRevision: this.#viewportOutputSource?.revision.toString() ?? null,
|
|
3035
|
+
focused: this.#focusedComponent !== null,
|
|
3036
|
+
cursor: cursor
|
|
3037
|
+
? { row: cursorVisible ? cursorRow! : cursor.row, col: cursor.col, visible: cursorVisible }
|
|
3038
|
+
: null,
|
|
3039
|
+
selection: paintedSelection,
|
|
3040
|
+
semanticAnchor,
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
#refreshPaintedLiveViewportObservation(height: number): void {
|
|
3045
|
+
this.#committedTranscriptRows = Array.from({ length: height }, (_, screenRow) => {
|
|
3046
|
+
const transcriptRow = this.#viewportTopRow + screenRow;
|
|
3047
|
+
return transcriptRow < this.#manualTranscriptLineCount ? transcriptRow : null;
|
|
3048
|
+
});
|
|
3049
|
+
this.#paintedManualOutputNotice = false;
|
|
3050
|
+
this.#recordPaintedViewportObservation(this.#viewportTopRow, height, false);
|
|
3051
|
+
}
|
|
2921
3052
|
|
|
2922
3053
|
#doRender(): void {
|
|
2923
3054
|
if (this.#stopped || !this.terminalAvailable) return;
|
|
@@ -3147,6 +3278,7 @@ export class TUI extends Container {
|
|
|
3147
3278
|
}
|
|
3148
3279
|
const nextViewportTop = resolvedAnchorTop ?? this.#manualViewportTop;
|
|
3149
3280
|
if (
|
|
3281
|
+
!this.#mouseSelectionDragged &&
|
|
3150
3282
|
this.#previousWidth === width &&
|
|
3151
3283
|
this.#previousHeight === height &&
|
|
3152
3284
|
nextViewportTop === this.#manualViewportTop &&
|
|
@@ -3248,6 +3380,7 @@ export class TUI extends Container {
|
|
|
3248
3380
|
);
|
|
3249
3381
|
this.#manualTranscriptLineCount = nextTranscriptLineCount;
|
|
3250
3382
|
this.#manualSuffixLineCount = nextSuffixLineCount;
|
|
3383
|
+
this.#refreshPaintedLiveViewportObservation(height);
|
|
3251
3384
|
})
|
|
3252
3385
|
)
|
|
3253
3386
|
return;
|
|
@@ -3310,6 +3443,7 @@ export class TUI extends Container {
|
|
|
3310
3443
|
);
|
|
3311
3444
|
this.#manualTranscriptLineCount = nextTranscriptLineCount;
|
|
3312
3445
|
this.#manualSuffixLineCount = nextSuffixLineCount;
|
|
3446
|
+
this.#refreshPaintedLiveViewportObservation(height);
|
|
3313
3447
|
});
|
|
3314
3448
|
if (!contentWritten) return false;
|
|
3315
3449
|
|
|
@@ -3436,8 +3570,8 @@ export class TUI extends Container {
|
|
|
3436
3570
|
|
|
3437
3571
|
// No changes - but still need to update hardware cursor position if it moved
|
|
3438
3572
|
if (firstChanged === -1) {
|
|
3439
|
-
this.#writeCursorPosition(cursorPos, newLines.length);
|
|
3440
3573
|
this.#viewportTopRow = Math.max(0, this.#maxLinesRendered - height);
|
|
3574
|
+
if (this.#writeCursorPosition(cursorPos, newLines.length)) this.#refreshPaintedLiveViewportObservation(height);
|
|
3441
3575
|
return;
|
|
3442
3576
|
}
|
|
3443
3577
|
|
|
@@ -3548,6 +3682,7 @@ export class TUI extends Container {
|
|
|
3548
3682
|
);
|
|
3549
3683
|
this.#manualTranscriptLineCount = nextTranscriptLineCount;
|
|
3550
3684
|
this.#manualSuffixLineCount = nextSuffixLineCount;
|
|
3685
|
+
this.#refreshPaintedLiveViewportObservation(height);
|
|
3551
3686
|
})
|
|
3552
3687
|
)
|
|
3553
3688
|
return;
|
|
@@ -3559,6 +3694,7 @@ export class TUI extends Container {
|
|
|
3559
3694
|
this.#viewportTopRow = Math.max(0, newLines.length - height);
|
|
3560
3695
|
this.#manualTranscriptLineCount = nextTranscriptLineCount;
|
|
3561
3696
|
this.#manualSuffixLineCount = nextSuffixLineCount;
|
|
3697
|
+
this.#refreshPaintedLiveViewportObservation(height);
|
|
3562
3698
|
return;
|
|
3563
3699
|
}
|
|
3564
3700
|
|
|
@@ -3724,6 +3860,7 @@ export class TUI extends Container {
|
|
|
3724
3860
|
);
|
|
3725
3861
|
this.#manualTranscriptLineCount = nextTranscriptLineCount;
|
|
3726
3862
|
this.#manualSuffixLineCount = nextSuffixLineCount;
|
|
3863
|
+
this.#refreshPaintedLiveViewportObservation(height);
|
|
3727
3864
|
})
|
|
3728
3865
|
)
|
|
3729
3866
|
return;
|