From 5608c116a931fcf7f46f5472908beb554a53e447 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Tue, 17 Feb 2026 19:02:48 +0200 Subject: [PATCH 1/3] feat(ui): enhance resize handling to maintain selected package visibility --- src/interactive-ui.ts | 2 +- src/ui/state/navigation-manager.ts | 4 ++-- src/ui/state/state-manager.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/interactive-ui.ts b/src/interactive-ui.ts index e1653a6..1d11b3e 100644 --- a/src/interactive-ui.ts +++ b/src/interactive-ui.ts @@ -253,7 +253,7 @@ export class InteractiveUI { case 'resize': const heightChanged = stateManager.updateTerminalHeight(action.height) if (heightChanged) { - stateManager.resetForResize() + stateManager.resetForResize(filteredStates.length) } else { // Even if height didn't change, width might have changed // Force a full re-render to clear any wrapping issues diff --git a/src/ui/state/navigation-manager.ts b/src/ui/state/navigation-manager.ts index fe55373..7b202f5 100644 --- a/src/ui/state/navigation-manager.ts +++ b/src/ui/state/navigation-manager.ts @@ -156,9 +156,9 @@ export class NavigationManager { if (targetVisualIndex < this.state.scrollOffset) { this.state.scrollOffset = targetVisualIndex } - // Scrolling down: scroll down by 1 item (smooth scrolling) + // Scrolling down: adjust scroll to keep item visible else if (visualIndex >= this.state.scrollOffset + this.maxVisibleItems) { - this.state.scrollOffset += 1 + this.state.scrollOffset = visualIndex - this.maxVisibleItems + 1 } // Ensure scrollOffset doesn't go negative or beyond bounds diff --git a/src/ui/state/state-manager.ts b/src/ui/state/state-manager.ts index 1f32000..3606d51 100644 --- a/src/ui/state/state-manager.ts +++ b/src/ui/state/state-manager.ts @@ -272,8 +272,8 @@ export class StateManager { this.renderState.forceFullRender = isInitial } - resetForResize(): void { - const totalItems = this.renderState.renderableItems.length || this.displayState.maxVisibleItems + resetForResize(totalFilteredItems?: number): void { + const totalItems = totalFilteredItems || this.renderState.renderableItems.length || this.displayState.maxVisibleItems this.navigationManager.resetForResize(totalItems) this.renderState.forceFullRender = true } From 14a3eac552cafea81304e932aaf14df5816a307d Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Tue, 17 Feb 2026 19:05:03 +0200 Subject: [PATCH 2/3] fix(ui): update resize handling to maintain filtered package states --- src/interactive-ui.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/interactive-ui.ts b/src/interactive-ui.ts index 1d11b3e..c942ddc 100644 --- a/src/interactive-ui.ts +++ b/src/interactive-ui.ts @@ -451,7 +451,8 @@ export class InteractiveUI { // This handles cases where process.stdout.rows might not be accurate at startup const currentHeight = this.getTerminalHeight() if (stateManager.updateTerminalHeight(currentHeight)) { - stateManager.resetForResize() + const initialFiltered = stateManager.getFilteredStates(states) + stateManager.resetForResize(initialFiltered.length) } // Initial render From c57e9216ddeb843b5263e5c91c3b8436433a8da5 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Tue, 17 Feb 2026 19:07:49 +0200 Subject: [PATCH 3/3] fix(ui): preserve navigation state when exiting filter mode Only reset navigation (current row and scroll offset) when clearQuery is true. This maintains the selected package position when exiting filter mode without clearing the query, such as during resize events. --- src/ui/state/state-manager.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ui/state/state-manager.ts b/src/ui/state/state-manager.ts index 3606d51..635b6f9 100644 --- a/src/ui/state/state-manager.ts +++ b/src/ui/state/state-manager.ts @@ -208,8 +208,10 @@ export class StateManager { exitFilterMode(clearQuery: boolean = false): void { this.filterManager.exitFilterMode(clearQuery) - this.navigationManager.setCurrentRow(0) - this.navigationManager.setScrollOffset(0) + if (clearQuery) { + this.navigationManager.setCurrentRow(0) + this.navigationManager.setScrollOffset(0) + } // Use incremental render for search mode toggle (no blink) }