@brimveyn/aimux 1.14.10 → 1.14.11
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/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MouseEvent as OtuiMouseEvent } from '@opentui/core'
|
|
1
|
+
import type { MouseEvent as OtuiMouseEvent, TextRenderable } from '@opentui/core'
|
|
2
2
|
|
|
3
3
|
import { memo, type ReactNode, useCallback, useMemo } from 'react'
|
|
4
4
|
|
|
@@ -104,6 +104,27 @@ interface TerminalViewportProps {
|
|
|
104
104
|
buffer: string
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
const NOOP = (): void => {}
|
|
108
|
+
|
|
109
|
+
// aimux renders the exact visible window and owns scrollback through the backend
|
|
110
|
+
// xterm buffer (viewportY); opentui's built-in text scroll (_scrollY) must never
|
|
111
|
+
// engage. During any transient where the rendered content is briefly taller than
|
|
112
|
+
// the box (resize lag, or — with the old default wrapMode="word" — a line that
|
|
113
|
+
// wraps) a wheel event bumps _scrollY, and opentui's onResize never re-clamps it,
|
|
114
|
+
// so the offset sticks for the renderable's life: the viewport shifts up, dead
|
|
115
|
+
// rows appear at the bottom, and the prompt scrolls off-screen after `clear`.
|
|
116
|
+
// Pin the offset to 0 and disable the built-in wheel handler outright (it also
|
|
117
|
+
// drives horizontal scroll once wrapMode is "none"). The event still bubbles to
|
|
118
|
+
// forwardScrollEvent, so local scrollback / mouse-forwarding keep working, and
|
|
119
|
+
// selection is unaffected (it's driven by the renderer, not handleScroll).
|
|
120
|
+
// handleScroll is protected; reach it via Reflect, mirroring the scrollY reset
|
|
121
|
+
// already used in TerminalPane.
|
|
122
|
+
const pinTerminalScroll = (node: TextRenderable | null): void => {
|
|
123
|
+
if (!node) return
|
|
124
|
+
Reflect.set(node, 'handleScroll', NOOP)
|
|
125
|
+
if (node.scrollY !== 0) node.scrollY = 0
|
|
126
|
+
}
|
|
127
|
+
|
|
107
128
|
const TerminalViewport = memo(function TerminalViewport({
|
|
108
129
|
buffer,
|
|
109
130
|
viewport,
|
|
@@ -112,7 +133,7 @@ const TerminalViewport = memo(function TerminalViewport({
|
|
|
112
133
|
if (viewport && viewport.lines.length > 0) {
|
|
113
134
|
const lines = viewport.lines
|
|
114
135
|
return (
|
|
115
|
-
<text fg={t.text}>
|
|
136
|
+
<text ref={pinTerminalScroll} fg={t.text} wrapMode="none">
|
|
116
137
|
{lines.map((line, lineIndex) => (
|
|
117
138
|
// Terminal rows are a fixed positional grid; the row index is the identity.
|
|
118
139
|
// eslint-disable-next-line react/no-array-index-key
|
|
@@ -125,7 +146,11 @@ const TerminalViewport = memo(function TerminalViewport({
|
|
|
125
146
|
)
|
|
126
147
|
}
|
|
127
148
|
|
|
128
|
-
return
|
|
149
|
+
return (
|
|
150
|
+
<text ref={pinTerminalScroll} fg={t.text} wrapMode="none">
|
|
151
|
+
{buffer.length > 0 ? buffer : 'Waiting for workspace output...'}
|
|
152
|
+
</text>
|
|
153
|
+
)
|
|
129
154
|
})
|
|
130
155
|
|
|
131
156
|
export function TerminalPane({
|