diff --git a/src/components/selection_input/selection_input.ts b/src/components/selection_input/selection_input.ts index 8b699f2181..66c3f50261 100644 --- a/src/components/selection_input/selection_input.ts +++ b/src/components/selection_input/selection_input.ts @@ -129,6 +129,13 @@ export class SelectionInput extends Component { () => this.focusedInput.el?.focus(), () => [this.focusedInput.el] ); + useEffect(() => { + // Check the offsetParent to know if the input or an ancestor is `display: none` (eg. when changing side panel tab) + if (this.store.hasFocus && this.selectionRef.el?.offsetParent === null) { + this.reset(); + } + }); + this.store = useLocalStore( SelectionInputStore, this.props.ranges, diff --git a/tests/figures/chart/charts_component.test.ts b/tests/figures/chart/charts_component.test.ts index 1792d31294..821cf301db 100644 --- a/tests/figures/chart/charts_component.test.ts +++ b/tests/figures/chart/charts_component.test.ts @@ -11,6 +11,7 @@ import { import { toHex, toZone } from "../../../src/helpers"; import { ScorecardChart } from "../../../src/helpers/figures/charts"; import { getChartColorsGenerator } from "../../../src/helpers/figures/charts/runtime"; +import { HighlightStore } from "../../../src/stores/highlight_store"; import { CHART_TYPES, ChartDefinition, @@ -1128,6 +1129,22 @@ describe("charts", () => { expect(chartPanel.scrollTop).toBe(100); }); + test("selection input is closed when switching tab", async () => { + createTestChart("basicChart"); + await mountChartSidePanel(); + const highlightStore = env.getStore(HighlightStore); + + await simulateClick(".o-selection-input input"); + expect(".o-selection-ok").toHaveCount(1); + expect(highlightStore.highlights.length).toBe(1); + + await openChartDesignSidePanel(model, env, fixture, chartId); + await nextTick(); // the check is done in a `useEffect`, we need to wait for the next render + + expect(".o-selection-ok").toHaveCount(0); + expect(highlightStore.highlights.length).toBe(0); + }); + describe.each(TEST_CHART_TYPES)("selecting other chart will adapt sidepanel", (chartType) => { test.each(["click", "SELECT_FIGURE command"])("when using %s", async (selectMethod: string) => { createTestChart(chartType); diff --git a/tests/setup/jest.setup.ts b/tests/setup/jest.setup.ts index 8aaf7fc3b8..faef745c17 100644 --- a/tests/setup/jest.setup.ts +++ b/tests/setup/jest.setup.ts @@ -87,6 +87,24 @@ beforeEach(() => { const blob = new window.Blob([data], { type }); setTimeout(() => callback(blob), 0); }); + + // offsetParent should return the nearest positioned ancestor, or null if an ancestor has `display: none` + jest + .spyOn(HTMLElement.prototype, "offsetParent", "get") + .mockImplementation(function (this: HTMLElement) { + let parentEl: HTMLElement | null = this.parentElement; + while (parentEl) { + if ( + getComputedStyle(parentEl).display === "none" || + parentEl.classList.contains("d-none") + ) { + return null; + } + parentEl = parentEl.parentElement; + } + return this.parentElement; // should be nearest positioned ancestor, but simplified for tests + }); + patchSessionMove(); });