fix(tui): preserve current selection across list updates (#39774)
This commit is contained in:
parent
a460f02f67
commit
865f512a44
2 changed files with 21 additions and 3 deletions
|
|
@ -240,7 +240,7 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
|||
on(
|
||||
() => props.options,
|
||||
() => {
|
||||
if (!props.preserveSelection) {
|
||||
if (!props.preserveSelection && props.current === undefined) {
|
||||
const count = flat().length
|
||||
if (count === 0) return
|
||||
const next = reconcileSelection(store.selected, count)
|
||||
|
|
@ -276,7 +276,7 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
|||
setStore("selected", index)
|
||||
selection = option
|
||||
if (!moved) return
|
||||
if (!props.preserveSelection || store.filter.length > 0) return
|
||||
if ((!props.preserveSelection && props.current === undefined) || store.filter.length > 0) return
|
||||
scrollAfterLayout(false, option.value)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ async function renderSelect(
|
|||
return app
|
||||
}
|
||||
|
||||
async function mountSelect(root: string, initial: DialogSelectOption<string>[]) {
|
||||
async function mountSelect(root: string, initial: DialogSelectOption<string>[], current?: string) {
|
||||
const state = path.join(root, "state")
|
||||
await mkdir(state, { recursive: true })
|
||||
const config = createTuiResolvedConfig()
|
||||
|
|
@ -114,6 +114,7 @@ async function mountSelect(root: string, initial: DialogSelectOption<string>[])
|
|||
<DialogSelect
|
||||
title="Mutable options"
|
||||
options={options()}
|
||||
current={current}
|
||||
onMove={(option) => moved.push(option.value)}
|
||||
onSelect={(option) => selected.push(option.value)}
|
||||
/>
|
||||
|
|
@ -309,3 +310,20 @@ test("keeps the cursor index while options are temporarily empty", async () => {
|
|||
select.app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
test("keeps the current option selected when options reorder", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
const options = ["first", "current", "third"].map((value) => ({ title: value, value }))
|
||||
const select = await mountSelect(tmp.path, options, "current")
|
||||
|
||||
try {
|
||||
select.replaceOptions([options[1], options[2], options[0]])
|
||||
await select.app.waitForFrame((frame) => frame.indexOf("current") < frame.indexOf("third"))
|
||||
select.app.mockInput.pressEnter()
|
||||
await select.app.waitFor(() => select.selected.length === 1)
|
||||
|
||||
expect(select.selected).toEqual(["current"])
|
||||
} finally {
|
||||
select.app.renderer.destroy()
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue