fix(tui): only cycle history at input boundaries on arrows

Follow-up on #13726 from blitz feedback: Up/Down history cycling should only trigger when the caret is at the start/end boundary (or the input is empty).\n\nPreviously useInputHandlers intercepted arrows whenever inputBuf was empty, which still stole Up/Down from normal multiline editing. textInput now publishes caret position through inputSelectionStore even with no active selection, and useInputHandlers gates history/queue cycling on those boundaries.
This commit is contained in:
Brooklyn Nicholson
2026-04-21 18:48:35 -05:00
parent d30f6ac44e
commit 95fd023eeb
2 changed files with 26 additions and 16 deletions

View File

@@ -288,15 +288,27 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
}
if (key.upArrow && !cState.inputBuf.length) {
cycleQueue(1) || cycleHistory(-1)
const inputSel = getInputSelection()
const atStart = !cState.input || (!!inputSel && inputSel.start === 0 && inputSel.end === 0)
return
if (atStart) {
cycleQueue(1) || cycleHistory(-1)
return
}
}
if (key.downArrow && !cState.inputBuf.length) {
cycleQueue(-1) || cycleHistory(1)
const inputSel = getInputSelection()
const atEnd =
!cState.input ||
(!!inputSel && inputSel.start === cState.input.length && inputSel.end === cState.input.length)
return
if (atEnd || cState.historyIdx !== null) {
cycleQueue(-1) || cycleHistory(1)
return
}
}
if (isAction(key, ch, 'c')) {

View File

@@ -400,22 +400,20 @@ export function TextInput({
return
}
if (selected) {
setInputSelection({
clear: () => {
setInputSelection({
clear: () => {
if (selRef.current) {
selRef.current = null
setSel(null)
},
end: selected.end,
start: selected.start,
value: vRef.current
})
} else {
setInputSelection(null)
}
}
},
end: selected?.end ?? curRef.current,
start: selected?.start ?? curRef.current,
value: vRef.current
})
return () => setInputSelection(null)
}, [focus, selected])
}, [cur, focus, selected])
useEffect(
() => () => {