fix(sidebar): preserve group state after search

This commit is contained in:
Melody Ruch authored and GitHub committed 2026-08-14 22:12:44 +08:00
1 parent 26084d12e1
commit b9e63dc57e
3 files changed
+103 -8

No files matched your search

@@ -0,0 +1,25 @@
import { describe, expect, it } from "vitest";
import { createSidebarSearchExpansionState } from "@/lib/sidebar/sidebarSearchExpansionState";
describe("sidebar search expansion state", () => {
it("keeps auto-expanded ownership after a filtered group becomes an unfiltered ancestor match", () => {
const state = createSidebarSearchExpansionState();
state.markFiltered("group-tables", true);
expect(state.markUnfiltered("group-tables")).toBe(true);
expect(state.filteredNodeIds.has("group-tables")).toBe(false);
expect(state.autoExpandedNodeIds.has("group-tables")).toBe(true);
expect(state.shouldRestore("group-tables")).toBe(true);
});
it("clears tracked ownership when ordinary search exits through another mode", () => {
const state = createSidebarSearchExpansionState();
state.markFiltered("group-tables", true);
state.clear();
expect(state.hasTrackedNodes()).toBe(false);
expect(state.shouldRestore("group-tables")).toBe(false);
});
});
@@ -0,0 +1,36 @@
export interface SidebarSearchExpansionState {
readonly filteredNodeIds: Set<string>;
readonly autoExpandedNodeIds: Set<string>;
markFiltered(nodeId: string, autoExpanded: boolean): void;
markUnfiltered(nodeId: string): boolean;
shouldRestore(nodeId: string): boolean;
hasTrackedNodes(): boolean;
clear(): void;
}
export function createSidebarSearchExpansionState(): SidebarSearchExpansionState {
const filteredNodeIds = new Set<string>();
const autoExpandedNodeIds = new Set<string>();
return {
filteredNodeIds,
autoExpandedNodeIds,
markFiltered(nodeId, autoExpanded) {
filteredNodeIds.add(nodeId);
if (autoExpanded) autoExpandedNodeIds.add(nodeId);
},
markUnfiltered(nodeId) {
return filteredNodeIds.delete(nodeId);
},
shouldRestore(nodeId) {
return filteredNodeIds.has(nodeId) || autoExpandedNodeIds.has(nodeId);
},
hasTrackedNodes() {
return filteredNodeIds.size > 0 || autoExpandedNodeIds.size > 0;
},
clear() {
filteredNodeIds.clear();
autoExpandedNodeIds.clear();
},
};
}