From b1150b11e53a0cb1fa79d180bfc6f7fc34e50fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20M=C3=A9riouma-Caron?= Date: Thu, 22 May 2025 14:14:24 -0400 Subject: [PATCH 1/6] feat: expose outsideClickIgnoreClass --- src/calendar.tsx | 4 ++++ src/index.tsx | 11 +++++------ src/test/datepicker_test.test.tsx | 23 +++++++++++++++-------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/calendar.tsx b/src/calendar.tsx index 6194b0ffe4..7e0d8f260d 100644 --- a/src/calendar.tsx +++ b/src/calendar.tsx @@ -80,6 +80,9 @@ const DROPDOWN_FOCUS_CLASSNAMES = [ "react-datepicker__month-year-select", ]; +export const OUTSIDE_CLICK_IGNORE_CLASS = + "react-datepicker-ignore-onclickoutside"; + const isDropdownSelect = (element: HTMLDivElement) => { const classNames = (element.className || "").split(/\s+/); return DROPDOWN_FOCUS_CLASSNAMES.some( @@ -221,6 +224,7 @@ export default class Calendar extends Component { return { monthsShown: 1, forceShowMonthNavigation: false, + outsideClickIgnoreClass: OUTSIDE_CLICK_IGNORE_CLASS, timeCaption: "Time", previousYearButtonLabel: "Previous Year", nextYearButtonLabel: "Next Year", diff --git a/src/index.tsx b/src/index.tsx index ccd6ad996a..003e02005c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,7 @@ import { clsx } from "clsx"; import React, { Component, cloneElement } from "react"; -import Calendar from "./calendar"; +import Calendar, { OUTSIDE_CLICK_IGNORE_CLASS } from "./calendar"; import CalendarIcon from "./calendar_icon"; import { newDate, @@ -61,8 +61,6 @@ export { default as CalendarContainer } from "./calendar_container"; export { registerLocale, setDefaultLocale, getDefaultLocale }; -const outsideClickIgnoreClass = "react-datepicker-ignore-onclickoutside"; - export { ReactDatePickerCustomHeaderProps } from "./calendar"; // Compares dates year+month combinations @@ -112,7 +110,6 @@ export type DatePickerProps = OmitUnion< | "highlightDates" | "holidays" | "shouldFocusDayInline" - | "outsideClickIgnoreClass" | "monthSelectedIn" | "onDropdownFocus" | "onTimeChange" @@ -266,6 +263,7 @@ export default class DatePicker extends Component< dropdownMode: "scroll" as const, preventOpenOnFocus: false, monthsShown: 1, + outsideClickIgnoreClass: OUTSIDE_CLICK_IGNORE_CLASS, readOnly: false, withPortal: false, selectsDisabledDaysInRange: false, @@ -1236,7 +1234,7 @@ export default class DatePicker extends Component< onSelect={this.handleSelect} onClickOutside={this.handleCalendarClickOutside} holidays={getHolidaysMap(this.modifyHolidays())} - outsideClickIgnoreClass={outsideClickIgnoreClass} + outsideClickIgnoreClass={this.props.outsideClickIgnoreClass} onDropdownFocus={this.handleDropdownFocus} onTimeChange={this.handleTimeChange} className={this.props.calendarClassName} @@ -1325,7 +1323,8 @@ export default class DatePicker extends Component< renderDateInput = () => { const className = clsx(this.props.className, { - [outsideClickIgnoreClass]: this.state.open, + [this.props.outsideClickIgnoreClass || + DatePicker.defaultProps.outsideClickIgnoreClass]: this.state.open, }); const customInput = this.props.customInput || ; diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 31e8890c6b..6d88351ac3 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -2,6 +2,7 @@ import { render, act, waitFor, fireEvent } from "@testing-library/react"; import { userEvent } from "@testing-library/user-event"; import { enUS, enGB } from "date-fns/locale"; import React, { useState } from "react"; +import { OUTSIDE_CLICK_IGNORE_CLASS } from "../calendar"; import { KeyType, @@ -687,21 +688,27 @@ describe("DatePicker", () => { }); }); - it("should not apply the react-datepicker-ignore-onclickoutside class to the date input when closed", () => { + it("should not apply the default outsideClickIgnoreClass class to the date input when closed", () => { const { container } = render(); const input = safeQuerySelector(container, "input"); - expect( - input?.classList.contains("react-datepicker-ignore-onclickoutside"), - ).toBeFalsy(); + expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(false); }); - it("should apply the react-datepicker-ignore-onclickoutside class to date input when open", () => { + it("should apply the default outsideClickIgnoreClass class to date input when open", () => { const { container } = render(); const input = safeQuerySelector(container, "input"); fireEvent.focus(input); - expect( - input?.classList.contains("react-datepicker-ignore-onclickoutside"), - ).toBeTruthy(); + expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(true); + }); + + it("should apply the outsideClickIgnoreClass class to date input when open", () => { + const outsideClickIgnoreClass = "ignore-onclickoutside"; + const { container } = render( + , + ); + const input = safeQuerySelector(container, "input"); + fireEvent.focus(input); + expect(input?.classList.contains(outsideClickIgnoreClass)).toBe(true); }); it("should toggle the open status of calendar on click of the icon when toggleCalendarOnIconClick is set to true", () => { From f1c6da0ff889d36dea7fa99c5051f000cea22e4a Mon Sep 17 00:00:00 2001 From: Martijn Russchen Date: Sun, 25 May 2025 14:38:09 +0200 Subject: [PATCH 2/6] test: add coverage for outsideClickIgnoreClass undefined fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds test case to cover the scenario where outsideClickIgnoreClass is explicitly set to undefined, ensuring the fallback to default props is properly tested and improves test coverage for line 1327 in index.tsx. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/test/datepicker_test.test.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 6d88351ac3..9efe68b1b9 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -711,6 +711,15 @@ describe("DatePicker", () => { expect(input?.classList.contains(outsideClickIgnoreClass)).toBe(true); }); + it("should apply the default outsideClickIgnoreClass when prop is undefined", () => { + const { container } = render( + , + ); + const input = safeQuerySelector(container, "input"); + fireEvent.focus(input); + expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(true); + }); + it("should toggle the open status of calendar on click of the icon when toggleCalendarOnIconClick is set to true", () => { const { container } = render( Date: Sun, 25 May 2025 14:45:48 +0200 Subject: [PATCH 3/6] test: add coverage for outsideClickIgnoreClass falsy fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/test/datepicker_test.test.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 9efe68b1b9..3a531bb971 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -720,6 +720,15 @@ describe("DatePicker", () => { expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(true); }); + it("should apply the default outsideClickIgnoreClass when prop is falsy", () => { + const { container } = render( + , + ); + const input = safeQuerySelector(container, "input"); + fireEvent.focus(input); + expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(true); + }); + it("should toggle the open status of calendar on click of the icon when toggleCalendarOnIconClick is set to true", () => { const { container } = render( Date: Sun, 25 May 2025 14:48:00 +0200 Subject: [PATCH 4/6] fix: remove unnecessary 'as any' type assertion in test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/test/datepicker_test.test.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 3a531bb971..a67df83a32 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -721,9 +721,7 @@ describe("DatePicker", () => { }); it("should apply the default outsideClickIgnoreClass when prop is falsy", () => { - const { container } = render( - , - ); + const { container } = render(); const input = safeQuerySelector(container, "input"); fireEvent.focus(input); expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(true); From 24c5e6b5dbca81a49e706189dfd70cfeeca02495 Mon Sep 17 00:00:00 2001 From: Martijn Russchen Date: Sun, 25 May 2025 14:48:30 +0200 Subject: [PATCH 5/6] Add claude memory --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..c337c6161b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +Use yarn instead of npm for running commands From 3e3d80f6db58e1bc5fbd4aff9f47002604be3fef Mon Sep 17 00:00:00 2001 From: Martijn Russchen Date: Sun, 25 May 2025 14:51:07 +0200 Subject: [PATCH 6/6] fix: use undefined instead of null for outsideClickIgnoreClass prop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/test/datepicker_test.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index a67df83a32..45d0fc5a97 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -721,7 +721,9 @@ describe("DatePicker", () => { }); it("should apply the default outsideClickIgnoreClass when prop is falsy", () => { - const { container } = render(); + const { container } = render( + , + ); const input = safeQuerySelector(container, "input"); fireEvent.focus(input); expect(input?.classList.contains(OUTSIDE_CLICK_IGNORE_CLASS)).toBe(true);