From 3700259f92f7161f7d0a41e031a9326ebd9c2186 Mon Sep 17 00:00:00 2001 From: Martijn Russchen Date: Thu, 18 Dec 2025 21:38:56 +0100 Subject: [PATCH] feat: allow onClickOutside to prevent calendar from closing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call the onClickOutside callback before closing the calendar, allowing users to call event.preventDefault() to keep the calendar open. This is useful when using custom portal-based dropdowns in the calendar header that would otherwise trigger the click outside handler. Fixes #5666 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/index.tsx | 7 +++++-- src/test/datepicker_test.test.tsx | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 419a316f8..e6a9cd3d7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -717,10 +717,13 @@ export class DatePicker extends Component { }; handleCalendarClickOutside = (event: MouseEvent) => { - if (!this.props.inline) { + // Call user's onClickOutside first, allowing them to call preventDefault() + this.props.onClickOutside?.(event); + + // Only close if not prevented and not inline + if (!this.props.inline && !event.defaultPrevented) { this.setOpen(false); } - this.props.onClickOutside?.(event); if (this.props.withPortal) { event.preventDefault(); } diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 65f61e47e..32cbb423c 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -2793,6 +2793,28 @@ describe("DatePicker", () => { expect(onClickOutsideSpy).toHaveBeenCalledTimes(1); }); + it("should not close date picker when onClickOutside calls preventDefault", () => { + const onClickOutside = (event: MouseEvent) => { + event.preventDefault(); + }; + const { container } = render( +
+ outside + +
, + ); + + const input = safeQuerySelector(container, "input"); + fireEvent.focus(input); + expect(container.querySelector(".react-datepicker")).not.toBeNull(); + + const outsideElement = safeQuerySelector(container, ".outsideElement"); + fireEvent.mouseDown(outsideElement); + + // Calendar should remain open because preventDefault was called + expect(container.querySelector(".react-datepicker")).not.toBeNull(); + }); + it("should not close date picker on input click", () => { const onClickOutsideSpy = jest.fn(); const { container } = render(