Skip to content

Commit 46ff759

Browse files
authored
fix: setting defaultMonth the next year when using the dropdown mode does not render the calendar (#2783)
* Use computed navStart and navEnd values instead of props * Add InvalidMonthDefaultLimit example * Add InvalidMonthDefaultLimit tests * Refactor code * Update tests * Fix typo * Fix TS issue
1 parent e4d66a0 commit 46ff759

File tree

9 files changed

+95
-28
lines changed

9 files changed

+95
-28
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from "react";
2+
3+
import { grid } from "@/test/elements";
4+
import { render } from "@/test/render";
5+
6+
import { InvalidMonthDefaultLimit } from "./InvalidMonthDefaultLimit";
7+
8+
test("should display calendar in December", () => {
9+
render(<InvalidMonthDefaultLimit />);
10+
expect(grid()).toHaveAccessibleName(`December ${new Date().getFullYear()}`);
11+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React, { useState } from "react";
2+
3+
import { DayPicker } from "react-day-picker";
4+
5+
export function InvalidMonthDefaultLimit() {
6+
const [month, setMonth] = useState(() => {
7+
const date = new Date();
8+
date.setFullYear(date.getFullYear() + 1);
9+
return date;
10+
});
11+
12+
return (
13+
<DayPicker
14+
month={month}
15+
onMonthChange={setMonth}
16+
captionLayout="dropdown"
17+
/>
18+
);
19+
}

examples/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export * from "./Input";
3636
export * from "./InputRange";
3737
export * from "./InputTime";
3838
export * from "./InvalidMonth";
39+
export * from "./InvalidMonthDefaultLimit";
3940
export * from "./ItalianLabels";
4041
export * from "./ItalianLabels";
4142
export * from "./Keyboard";

src/DayPicker.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,13 @@ export function DayPicker(initialProps: DayPickerProps) {
160160
goToMonth
161161
} = calendar;
162162

163-
const getModifiers = createGetModifiers(days, props, dateLib);
163+
const getModifiers = createGetModifiers(
164+
days,
165+
props,
166+
navStart,
167+
navEnd,
168+
dateLib
169+
);
164170

165171
const {
166172
isSelected,

src/helpers/createGetModifiers.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ const props = {
4040

4141
describe("createGetModifiers", () => {
4242
describe("default props", () => {
43-
const getModifiers = createGetModifiers(days, props, dateLib);
43+
const getModifiers = createGetModifiers(
44+
days,
45+
props,
46+
undefined,
47+
undefined,
48+
dateLib
49+
);
4450

4551
test("return the modifiers for a given day", () => {
4652
const modifiers = getModifiers(day2);
@@ -114,7 +120,9 @@ describe("createGetModifiers", () => {
114120

115121
const getModifiers = createGetModifiers(
116122
days,
117-
{ ...props, startMonth, endMonth },
123+
props,
124+
startMonth,
125+
endMonth,
118126
dateLib
119127
);
120128
test("return the modifiers for a given day", () => {

src/helpers/createGetModifiers.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { dateMatchModifiers } from "../utils/dateMatchModifiers.js";
1919
export function createGetModifiers(
2020
days: CalendarDay[],
2121
props: DayPickerProps,
22+
navStart: Date | undefined,
23+
navEnd: Date | undefined,
2224
dateLib: DateLib
2325
) {
2426
const {
@@ -39,8 +41,8 @@ export function createGetModifiers(
3941
isAfter
4042
} = dateLib;
4143

42-
const startMonth = props.startMonth && startOfMonth(props.startMonth);
43-
const endMonth = props.endMonth && endOfMonth(props.endMonth);
44+
const computedNavStart = navStart && startOfMonth(navStart);
45+
const computedNavEnd = navEnd && endOfMonth(navEnd);
4446

4547
const internalModifiersMap: Record<DayFlag, CalendarDay[]> = {
4648
[DayFlag.focused]: [],
@@ -57,20 +59,22 @@ export function createGetModifiers(
5759

5860
const isOutside = Boolean(displayMonth && !isSameMonth(date, displayMonth));
5961

60-
const isBeforeStartMonth = Boolean(
61-
startMonth && isBefore(date, startMonth)
62+
const isBeforeNavStart = Boolean(
63+
computedNavStart && isBefore(date, computedNavStart)
6264
);
6365

64-
const isAfterEndMonth = Boolean(endMonth && isAfter(date, endMonth));
66+
const isAfterNavEnd = Boolean(
67+
computedNavEnd && isAfter(date, computedNavEnd)
68+
);
6569

6670
const isDisabled = Boolean(
6771
disabled && dateMatchModifiers(date, disabled, dateLib)
6872
);
6973

7074
const isHidden =
7175
Boolean(hidden && dateMatchModifiers(date, hidden, dateLib)) ||
72-
isBeforeStartMonth ||
73-
isAfterEndMonth ||
76+
isBeforeNavStart ||
77+
isAfterNavEnd ||
7478
// Broadcast calendar will show outside days as default
7579
(!broadcastCalendar && !showOutsideDays && isOutside) ||
7680
(broadcastCalendar && showOutsideDays === false && isOutside);

src/helpers/getInitialMonth.test.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import { getInitialMonth } from "./getInitialMonth";
66

77
it("return start of month", () => {
88
const month = new Date(2010, 11, 12);
9-
const initialMonth = getInitialMonth({ month }, defaultDateLib);
9+
const initialMonth = getInitialMonth(
10+
{ month },
11+
undefined,
12+
undefined,
13+
defaultDateLib
14+
);
1015
expect(isSameDay(initialMonth, startOfMonth(month))).toBe(true);
1116
});
1217

@@ -18,6 +23,8 @@ describe("when no startMonth or endMonth is given", () => {
1823
it("return that month", () => {
1924
const initialMonth = getInitialMonth(
2025
{ month, defaultMonth, today },
26+
undefined,
27+
undefined,
2128
defaultDateLib
2229
);
2330
expect(isSameMonth(initialMonth, month)).toBe(true);
@@ -27,14 +34,21 @@ describe("when no startMonth or endMonth is given", () => {
2734
it("return that month", () => {
2835
const initialMonth = getInitialMonth(
2936
{ defaultMonth, today },
37+
undefined,
38+
undefined,
3039
defaultDateLib
3140
);
3241
expect(isSameMonth(initialMonth, defaultMonth)).toBe(true);
3342
});
3443
});
3544
describe("when no month or defaultMonth", () => {
3645
it("return the today month", () => {
37-
const initialMonth = getInitialMonth({ today }, defaultDateLib);
46+
const initialMonth = getInitialMonth(
47+
{ today },
48+
undefined,
49+
undefined,
50+
defaultDateLib
51+
);
3852
expect(isSameMonth(initialMonth, today)).toBe(true);
3953
});
4054
});
@@ -45,7 +59,9 @@ describe("when startMonth is given and is after the default initial month", () =
4559
const month = new Date(2010, 11, 12);
4660
const startMonth = addMonths(month, 1);
4761
const initialMonth = getInitialMonth(
48-
{ month, numberOfMonths: 3, startMonth },
62+
{ month, numberOfMonths: 3 },
63+
startMonth,
64+
undefined,
4965
defaultDateLib
5066
);
5167
expect(isSameMonth(initialMonth, startMonth)).toBe(true);
@@ -59,7 +75,9 @@ describe("when endMonth is given", () => {
5975
describe("when the number of month is 1", () => {
6076
it("return the endMonth", () => {
6177
const initialMonth = getInitialMonth(
62-
{ month, endMonth },
78+
{ month },
79+
undefined,
80+
endMonth,
6381
defaultDateLib
6482
);
6583
expect(isSameMonth(initialMonth, endMonth)).toBe(true);
@@ -68,7 +86,9 @@ describe("when endMonth is given", () => {
6886
describe("when the number of month is 3", () => {
6987
it("return the endMonth plus the number of months", () => {
7088
const initialMonth = getInitialMonth(
71-
{ month, numberOfMonths: 3, endMonth },
89+
{ month, numberOfMonths: 3 },
90+
undefined,
91+
endMonth,
7292
defaultDateLib
7393
);
7494
const expectedMonth = addMonths(endMonth, -1 * (3 - 1));

src/helpers/getInitialMonth.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,33 @@ export function getInitialMonth(
1717
DayPickerProps,
1818
| "fromYear"
1919
| "toYear"
20-
| "startMonth"
21-
| "endMonth"
2220
| "month"
2321
| "defaultMonth"
2422
| "today"
2523
| "numberOfMonths"
2624
| "timeZone"
2725
>,
26+
navStart: Date | undefined,
27+
navEnd: Date | undefined,
2828
dateLib: DateLib
2929
): Date {
3030
const {
3131
month,
3232
defaultMonth,
3333
today = dateLib.today(),
34-
numberOfMonths = 1,
35-
endMonth,
36-
startMonth
34+
numberOfMonths = 1
3735
} = props;
3836
let initialMonth = month || defaultMonth || today;
3937
const { differenceInCalendarMonths, addMonths, startOfMonth } = dateLib;
4038

41-
// Adjust the initial month if it is after the endMonth
42-
if (endMonth && differenceInCalendarMonths(endMonth, initialMonth) < 0) {
39+
// Adjust the initial month if it is after the navEnd
40+
if (navEnd && differenceInCalendarMonths(navEnd, initialMonth) < 0) {
4341
const offset = -1 * (numberOfMonths - 1);
44-
initialMonth = addMonths(endMonth, offset);
42+
initialMonth = addMonths(navEnd, offset);
4543
}
46-
// Adjust the initial month if it is before the startMonth
47-
if (startMonth && differenceInCalendarMonths(initialMonth, startMonth) < 0) {
48-
initialMonth = startMonth;
44+
// Adjust the initial month if it is before the navStart
45+
if (navStart && differenceInCalendarMonths(initialMonth, navStart) < 0) {
46+
initialMonth = navStart;
4947
}
5048

5149
return startOfMonth(initialMonth);

src/useCalendar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ export function useCalendar(
101101
const [navStart, navEnd] = getNavMonths(props, dateLib);
102102

103103
const { startOfMonth, endOfMonth } = dateLib;
104-
const initialMonth = getInitialMonth(props, dateLib);
104+
const initialMonth = getInitialMonth(props, navStart, navEnd, dateLib);
105105
const [firstMonth, setFirstMonth] = useControlledValue(
106106
initialMonth,
107107
// initialMonth is always computed from props.month if provided
108108
props.month ? initialMonth : undefined
109109
);
110110

111111
useEffect(() => {
112-
const newInitialMonth = getInitialMonth(props, dateLib);
112+
const newInitialMonth = getInitialMonth(props, navStart, navEnd, dateLib);
113113
setFirstMonth(newInitialMonth);
114114
// eslint-disable-next-line react-hooks/exhaustive-deps
115115
}, [props.timeZone]);

0 commit comments

Comments
 (0)