From 31c22aa8d2b4b15a9acceecf6118d361479983e1 Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 17:44:06 +0200 Subject: [PATCH 1/7] Use computed navStart and navEnd values instead of props --- src/DayPicker.tsx | 8 +++++++- src/helpers/createGetModifiers.ts | 16 ++++++++-------- src/helpers/getInitialMonth.ts | 20 +++++++++----------- src/useCalendar.ts | 4 ++-- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/DayPicker.tsx b/src/DayPicker.tsx index 4aa979cfe..a5d0ab1ef 100644 --- a/src/DayPicker.tsx +++ b/src/DayPicker.tsx @@ -160,7 +160,13 @@ export function DayPicker(initialProps: DayPickerProps) { goToMonth } = calendar; - const getModifiers = createGetModifiers(days, props, dateLib); + const getModifiers = createGetModifiers( + days, + props, + navStart, + navEnd, + dateLib + ); const { isSelected, diff --git a/src/helpers/createGetModifiers.ts b/src/helpers/createGetModifiers.ts index bdb46eba2..8118f12ec 100644 --- a/src/helpers/createGetModifiers.ts +++ b/src/helpers/createGetModifiers.ts @@ -19,6 +19,8 @@ import { dateMatchModifiers } from "../utils/dateMatchModifiers.js"; export function createGetModifiers( days: CalendarDay[], props: DayPickerProps, + navStart: Date | undefined, + navEnd: Date | undefined, dateLib: DateLib ) { const { @@ -39,8 +41,8 @@ export function createGetModifiers( isAfter } = dateLib; - const startMonth = props.startMonth && startOfMonth(props.startMonth); - const endMonth = props.endMonth && endOfMonth(props.endMonth); + navStart = navStart && startOfMonth(navStart); + navEnd = navEnd && endOfMonth(navEnd); const internalModifiersMap: Record = { [DayFlag.focused]: [], @@ -57,11 +59,9 @@ export function createGetModifiers( const isOutside = Boolean(displayMonth && !isSameMonth(date, displayMonth)); - const isBeforeStartMonth = Boolean( - startMonth && isBefore(date, startMonth) - ); + const isBeforeNadStart = Boolean(navStart && isBefore(date, navStart)); - const isAfterEndMonth = Boolean(endMonth && isAfter(date, endMonth)); + const isAfterNavEnd = Boolean(navEnd && isAfter(date, navEnd)); const isDisabled = Boolean( disabled && dateMatchModifiers(date, disabled, dateLib) @@ -69,8 +69,8 @@ export function createGetModifiers( const isHidden = Boolean(hidden && dateMatchModifiers(date, hidden, dateLib)) || - isBeforeStartMonth || - isAfterEndMonth || + isBeforeNadStart || + isAfterNavEnd || // Broadcast calendar will show outside days as default (!broadcastCalendar && !showOutsideDays && isOutside) || (broadcastCalendar && showOutsideDays === false && isOutside); diff --git a/src/helpers/getInitialMonth.ts b/src/helpers/getInitialMonth.ts index d0fdcaed1..34b729ed2 100644 --- a/src/helpers/getInitialMonth.ts +++ b/src/helpers/getInitialMonth.ts @@ -17,35 +17,33 @@ export function getInitialMonth( DayPickerProps, | "fromYear" | "toYear" - | "startMonth" - | "endMonth" | "month" | "defaultMonth" | "today" | "numberOfMonths" | "timeZone" >, + navStart: Date | undefined, + navEnd: Date | undefined, dateLib: DateLib ): Date { const { month, defaultMonth, today = dateLib.today(), - numberOfMonths = 1, - endMonth, - startMonth + numberOfMonths = 1 } = props; let initialMonth = month || defaultMonth || today; const { differenceInCalendarMonths, addMonths, startOfMonth } = dateLib; - // Adjust the initial month if it is after the endMonth - if (endMonth && differenceInCalendarMonths(endMonth, initialMonth) < 0) { + // Adjust the initial month if it is after the navEnd + if (navEnd && differenceInCalendarMonths(navEnd, initialMonth) < 0) { const offset = -1 * (numberOfMonths - 1); - initialMonth = addMonths(endMonth, offset); + initialMonth = addMonths(navEnd, offset); } - // Adjust the initial month if it is before the startMonth - if (startMonth && differenceInCalendarMonths(initialMonth, startMonth) < 0) { - initialMonth = startMonth; + // Adjust the initial month if it is before the navStart + if (navStart && differenceInCalendarMonths(initialMonth, navStart) < 0) { + initialMonth = navStart; } return startOfMonth(initialMonth); diff --git a/src/useCalendar.ts b/src/useCalendar.ts index 1dc6d5b92..bd5ee538e 100644 --- a/src/useCalendar.ts +++ b/src/useCalendar.ts @@ -101,7 +101,7 @@ export function useCalendar( const [navStart, navEnd] = getNavMonths(props, dateLib); const { startOfMonth, endOfMonth } = dateLib; - const initialMonth = getInitialMonth(props, dateLib); + const initialMonth = getInitialMonth(props, navStart, navEnd, dateLib); const [firstMonth, setFirstMonth] = useControlledValue( initialMonth, // initialMonth is always computed from props.month if provided @@ -109,7 +109,7 @@ export function useCalendar( ); useEffect(() => { - const newInitialMonth = getInitialMonth(props, dateLib); + const newInitialMonth = getInitialMonth(props, navStart, navEnd, dateLib); setFirstMonth(newInitialMonth); // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.timeZone]); From b8bc85a528367dcca5ca1e84f7cf8e73b7dd7291 Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 17:47:28 +0200 Subject: [PATCH 2/7] Add InvalidMonthDefaultLimit example --- examples/InvalidMonthDefaultLimit.tsx | 19 +++++++++++++++++++ examples/index.ts | 1 + 2 files changed, 20 insertions(+) create mode 100644 examples/InvalidMonthDefaultLimit.tsx diff --git a/examples/InvalidMonthDefaultLimit.tsx b/examples/InvalidMonthDefaultLimit.tsx new file mode 100644 index 000000000..ec031d620 --- /dev/null +++ b/examples/InvalidMonthDefaultLimit.tsx @@ -0,0 +1,19 @@ +import React, { useState } from "react"; + +import { DayPicker } from "react-day-picker"; + +export function InvalidMonthDefaultLimit() { + const [month, setMonth] = useState(() => { + const date = new Date(); + date.setFullYear(date.getFullYear() + 1); + return date; + }); + + return ( + + ); +} diff --git a/examples/index.ts b/examples/index.ts index fc9d5bb60..6217c33e0 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -36,6 +36,7 @@ export * from "./Input"; export * from "./InputRange"; export * from "./InputTime"; export * from "./InvalidMonth"; +export * from "./InvalidMonthDefaultLimit"; export * from "./ItalianLabels"; export * from "./ItalianLabels"; export * from "./Keyboard"; From d3a8e7b4a5c1da253c5a06f75cb78daf9dd40e50 Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 17:51:12 +0200 Subject: [PATCH 3/7] Add InvalidMonthDefaultLimit tests --- examples/InvalidMonthDefaultLimit.test.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 examples/InvalidMonthDefaultLimit.test.tsx diff --git a/examples/InvalidMonthDefaultLimit.test.tsx b/examples/InvalidMonthDefaultLimit.test.tsx new file mode 100644 index 000000000..25a14766b --- /dev/null +++ b/examples/InvalidMonthDefaultLimit.test.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +import { grid } from "@/test/elements"; +import { render } from "@/test/render"; + +import { InvalidMonthDefaultLimit } from "./InvalidMonthDefaultLimit"; + +test("should display calendar in December", () => { + render(); + expect(grid()).toHaveAccessibleName(`December ${new Date().getFullYear()}`); +}); From f6207698f4b3ed38052b7e32a595af0f1c1405a6 Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 18:46:02 +0200 Subject: [PATCH 4/7] Refactor code --- src/helpers/createGetModifiers.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/helpers/createGetModifiers.ts b/src/helpers/createGetModifiers.ts index 8118f12ec..b45a483db 100644 --- a/src/helpers/createGetModifiers.ts +++ b/src/helpers/createGetModifiers.ts @@ -41,8 +41,8 @@ export function createGetModifiers( isAfter } = dateLib; - navStart = navStart && startOfMonth(navStart); - navEnd = navEnd && endOfMonth(navEnd); + const computedNavStart = navStart && startOfMonth(navStart); + const computedNavEnd = navEnd && endOfMonth(navEnd); const internalModifiersMap: Record = { [DayFlag.focused]: [], @@ -59,9 +59,13 @@ export function createGetModifiers( const isOutside = Boolean(displayMonth && !isSameMonth(date, displayMonth)); - const isBeforeNadStart = Boolean(navStart && isBefore(date, navStart)); + const isBeforeNadStart = Boolean( + computedNavStart && isBefore(date, computedNavStart) + ); - const isAfterNavEnd = Boolean(navEnd && isAfter(date, navEnd)); + const isAfterNavEnd = Boolean( + computedNavEnd && isAfter(date, computedNavEnd) + ); const isDisabled = Boolean( disabled && dateMatchModifiers(date, disabled, dateLib) From c01c349cd524e4e5be6924d1641b83a833c6a56f Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 18:49:37 +0200 Subject: [PATCH 5/7] Update tests --- src/helpers/createGetModifiers.test.ts | 14 ++++++++++-- src/helpers/getInitialMonth.test.ts | 30 +++++++++++++++++++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/helpers/createGetModifiers.test.ts b/src/helpers/createGetModifiers.test.ts index 8742a4c3b..c0982ee80 100644 --- a/src/helpers/createGetModifiers.test.ts +++ b/src/helpers/createGetModifiers.test.ts @@ -1,3 +1,5 @@ +import { start } from "repl"; + import { DayFlag } from "../UI"; import { CalendarDay, defaultDateLib } from "../classes/index"; @@ -40,7 +42,13 @@ const props = { describe("createGetModifiers", () => { describe("default props", () => { - const getModifiers = createGetModifiers(days, props, dateLib); + const getModifiers = createGetModifiers( + days, + props, + undefined, + undefined, + dateLib + ); test("return the modifiers for a given day", () => { const modifiers = getModifiers(day2); @@ -114,7 +122,9 @@ describe("createGetModifiers", () => { const getModifiers = createGetModifiers( days, - { ...props, startMonth, endMonth }, + props, + startMonth, + endMonth, dateLib ); test("return the modifiers for a given day", () => { diff --git a/src/helpers/getInitialMonth.test.ts b/src/helpers/getInitialMonth.test.ts index e0415c0b6..9519a6ef3 100644 --- a/src/helpers/getInitialMonth.test.ts +++ b/src/helpers/getInitialMonth.test.ts @@ -6,7 +6,12 @@ import { getInitialMonth } from "./getInitialMonth"; it("return start of month", () => { const month = new Date(2010, 11, 12); - const initialMonth = getInitialMonth({ month }, defaultDateLib); + const initialMonth = getInitialMonth( + { month }, + undefined, + undefined, + defaultDateLib + ); expect(isSameDay(initialMonth, startOfMonth(month))).toBe(true); }); @@ -18,6 +23,8 @@ describe("when no startMonth or endMonth is given", () => { it("return that month", () => { const initialMonth = getInitialMonth( { month, defaultMonth, today }, + undefined, + undefined, defaultDateLib ); expect(isSameMonth(initialMonth, month)).toBe(true); @@ -27,6 +34,8 @@ describe("when no startMonth or endMonth is given", () => { it("return that month", () => { const initialMonth = getInitialMonth( { defaultMonth, today }, + undefined, + undefined, defaultDateLib ); expect(isSameMonth(initialMonth, defaultMonth)).toBe(true); @@ -34,7 +43,12 @@ describe("when no startMonth or endMonth is given", () => { }); describe("when no month or defaultMonth", () => { it("return the today month", () => { - const initialMonth = getInitialMonth({ today }, defaultDateLib); + const initialMonth = getInitialMonth( + { today }, + undefined, + undefined, + defaultDateLib + ); expect(isSameMonth(initialMonth, today)).toBe(true); }); }); @@ -45,7 +59,9 @@ describe("when startMonth is given and is after the default initial month", () = const month = new Date(2010, 11, 12); const startMonth = addMonths(month, 1); const initialMonth = getInitialMonth( - { month, numberOfMonths: 3, startMonth }, + { month, numberOfMonths: 3 }, + startMonth, + undefined, defaultDateLib ); expect(isSameMonth(initialMonth, startMonth)).toBe(true); @@ -59,7 +75,9 @@ describe("when endMonth is given", () => { describe("when the number of month is 1", () => { it("return the endMonth", () => { const initialMonth = getInitialMonth( - { month, endMonth }, + { month }, + undefined, + endMonth, defaultDateLib ); expect(isSameMonth(initialMonth, endMonth)).toBe(true); @@ -68,7 +86,9 @@ describe("when endMonth is given", () => { describe("when the number of month is 3", () => { it("return the endMonth plus the number of months", () => { const initialMonth = getInitialMonth( - { month, numberOfMonths: 3, endMonth }, + { month, numberOfMonths: 3 }, + undefined, + endMonth, defaultDateLib ); const expectedMonth = addMonths(endMonth, -1 * (3 - 1)); From 66710767754d7b8ddd5c127ea6fb578f9fc01adf Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 19:04:03 +0200 Subject: [PATCH 6/7] Fix typo --- src/helpers/createGetModifiers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/createGetModifiers.ts b/src/helpers/createGetModifiers.ts index b45a483db..3ddc8ee1e 100644 --- a/src/helpers/createGetModifiers.ts +++ b/src/helpers/createGetModifiers.ts @@ -59,7 +59,7 @@ export function createGetModifiers( const isOutside = Boolean(displayMonth && !isSameMonth(date, displayMonth)); - const isBeforeNadStart = Boolean( + const isBeforeNavStart = Boolean( computedNavStart && isBefore(date, computedNavStart) ); @@ -73,7 +73,7 @@ export function createGetModifiers( const isHidden = Boolean(hidden && dateMatchModifiers(date, hidden, dateLib)) || - isBeforeNadStart || + isBeforeNavStart || isAfterNavEnd || // Broadcast calendar will show outside days as default (!broadcastCalendar && !showOutsideDays && isOutside) || From 926194ca2531ae0911c1ac7191b28d07771b0853 Mon Sep 17 00:00:00 2001 From: Rodolfo Gobbi De Angeli Date: Sun, 29 Jun 2025 19:15:06 +0200 Subject: [PATCH 7/7] Fix TS issue --- src/helpers/createGetModifiers.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/helpers/createGetModifiers.test.ts b/src/helpers/createGetModifiers.test.ts index c0982ee80..947896840 100644 --- a/src/helpers/createGetModifiers.test.ts +++ b/src/helpers/createGetModifiers.test.ts @@ -1,5 +1,3 @@ -import { start } from "repl"; - import { DayFlag } from "../UI"; import { CalendarDay, defaultDateLib } from "../classes/index";