From 0dfeafef0e014bc2fafed53ae0d5e8d9707563d1 Mon Sep 17 00:00:00 2001 From: wanxiankai Date: Wed, 15 Jul 2026 09:29:50 +0800 Subject: [PATCH] fix: detect stopped outside mousedown events --- src/click_outside_wrapper.tsx | 4 ++-- src/test/click_outside_wrapper.test.tsx | 21 +++++++++++++++++++++ src/test/datepicker_test.test.tsx | 18 ++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/click_outside_wrapper.tsx b/src/click_outside_wrapper.tsx index 7b7b68e89f..0fc49627ef 100644 --- a/src/click_outside_wrapper.tsx +++ b/src/click_outside_wrapper.tsx @@ -44,9 +44,9 @@ const useDetectClickOutside = ( [ignoreClass], ); useEffect(() => { - document.addEventListener("mousedown", handleClickOutside); + document.addEventListener("mousedown", handleClickOutside, true); return () => { - document.removeEventListener("mousedown", handleClickOutside); + document.removeEventListener("mousedown", handleClickOutside, true); }; }, [handleClickOutside]); return ref; diff --git a/src/test/click_outside_wrapper.test.tsx b/src/test/click_outside_wrapper.test.tsx index 6f5ee5725a..de86cceb9b 100644 --- a/src/test/click_outside_wrapper.test.tsx +++ b/src/test/click_outside_wrapper.test.tsx @@ -42,6 +42,26 @@ describe("ClickOutsideWrapper", () => { expect(onClickOutsideMock).toHaveBeenCalledTimes(1); }); + it("calls onClickOutside when an outside element stops mousedown propagation", () => { + const { getByTestId } = render( +
+ +
Inside
+
+ +
, + ); + + fireEvent.mouseDown(getByTestId("outside")); + + expect(onClickOutsideMock).toHaveBeenCalledTimes(1); + }); + it("does not call onClickOutside when clicking inside the wrapper", () => { const { container } = render( @@ -190,6 +210,7 @@ describe("ClickOutsideWrapper", () => { expect(removeEventListenerSpy).toHaveBeenCalledWith( "mousedown", expect.any(Function), + true, ); removeEventListenerSpy.mockRestore(); diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 31b239b375..63757240b0 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -2865,6 +2865,24 @@ describe("DatePicker", () => { expect(onClickOutsideSpy).toHaveBeenCalledTimes(1); }); + it("should close when an outside element stops mousedown propagation", () => { + const { container, getByRole } = render( +
+ + +
, + ); + + fireEvent.focus(safeQuerySelector(container, "input")); + expect(container.querySelector(".react-datepicker")).not.toBeNull(); + + fireEvent.mouseDown(getByRole("button", { name: "Outside" })); + + expect(container.querySelector(".react-datepicker")).toBeNull(); + }); + it("should not close date picker when onClickOutside calls preventDefault", () => { const onClickOutside = (event: MouseEvent) => { event.preventDefault();