Skip to content

Commit 567cc8a

Browse files
committed
2 parents 26fdd03 + 16191b2 commit 567cc8a

4 files changed

Lines changed: 112 additions & 24 deletions

File tree

src/DayPicker.test.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
nextButton,
1010
previousButton,
1111
} from "@/test/elements";
12-
import { fireEvent, render, screen } from "@/test/render";
12+
import { act, fireEvent, render, screen } from "@/test/render";
1313
import { setTestTime } from "@/test/setTestTime";
1414
import { user } from "@/test/user";
1515
import { defaultLocale } from "./classes/DateLib";
@@ -122,6 +122,31 @@ describe("when the grid is focused", () => {
122122
});
123123
});
124124

125+
describe("when a disabled day is focused", () => {
126+
test("keyboard and mouse interactions do not select it", async () => {
127+
const disabledDay = new Date(2024, 8, 5);
128+
const handleSelect = jest.fn();
129+
130+
render(
131+
<DayPicker
132+
defaultMonth={disabledDay}
133+
disabled={[disabledDay]}
134+
mode="single"
135+
onSelect={handleSelect}
136+
/>,
137+
);
138+
139+
const disabledElement = dateButton(disabledDay);
140+
act(() => disabledElement.focus());
141+
142+
await user.keyboard("{Enter}");
143+
await user.click(disabledElement);
144+
145+
expect(handleSelect).not.toHaveBeenCalled();
146+
expect(disabledElement).toHaveAttribute("aria-disabled", "true");
147+
});
148+
});
149+
125150
describe("when navigation is disabled", () => {
126151
beforeEach(() => {
127152
jest.useFakeTimers();

src/DayPicker.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ export function DayPicker(initialProps: DayPickerProps) {
242242
e.preventDefault();
243243
e.stopPropagation();
244244
setFocused(day);
245+
if (m.disabled) {
246+
return;
247+
}
245248
select?.(day.date, m, e);
246249
onDayClick?.(day.date, m, e);
247250
},

src/helpers/getDates.test.ts

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,18 @@ describe("when the first month and the last month are the same", () => {
113113
describe("when using a max date", () => {
114114
const month = new Date(2023, 4, 1);
115115
const maxDate = new Date(2023, 4, 15);
116+
const dateLib = new DateLib({ weekStartsOn: 1 });
117+
const expectedLastDay = dateLib.addDays(dateLib.startOfWeek(maxDate), 6);
118+
const expectedLength =
119+
dateLib.differenceInCalendarDays(
120+
expectedLastDay,
121+
dateLib.startOfWeek(month),
122+
) + 1;
116123

117-
it("the last day should be the max date", () => {
118-
const dates = getDates(
119-
[month],
120-
maxDate,
121-
{},
122-
new DateLib({ weekStartsOn: 1 }),
123-
);
124-
expect(dates).toHaveLength(15);
125-
expect(dates[dates.length - 1]).toEqual(maxDate);
124+
it("the last day should be the end of that week", () => {
125+
const dates = getDates([month], maxDate, {}, dateLib);
126+
expect(dates).toHaveLength(expectedLength);
127+
expect(dates[dates.length - 1]).toEqual(expectedLastDay);
126128
});
127129
});
128130
describe("when using ISO weeks", () => {
@@ -139,6 +141,50 @@ describe("when the first month and the last month are the same", () => {
139141
expect(dates[dates.length - 1]).toEqual(new Date(2023, 5, 4));
140142
});
141143
});
144+
145+
describe("when using a custom week start with a max date", () => {
146+
const month = new Date(2023, 4, 1); // May 2023
147+
const maxDate = new Date(2023, 4, 15);
148+
const dateLib = new DateLib({ weekStartsOn: 3 }); // Wednesday start
149+
150+
const expectedLastDay = dateLib.addDays(dateLib.startOfWeek(maxDate), 6);
151+
const expectedLength =
152+
dateLib.differenceInCalendarDays(
153+
expectedLastDay,
154+
dateLib.startOfWeek(month),
155+
) + 1;
156+
157+
it("clamps to the end of the custom week", () => {
158+
const dates = getDates([month], maxDate, {}, dateLib);
159+
expect(dates[dates.length - 1]).toEqual(expectedLastDay);
160+
expect(dates).toHaveLength(expectedLength);
161+
});
162+
});
163+
164+
describe("when using ISO weeks with a max date", () => {
165+
const month = new Date(2023, 4, 1); // May 2023
166+
const maxDate = new Date(2023, 4, 15);
167+
const expectedLastDay = defaultDateLib.addDays(
168+
defaultDateLib.startOfISOWeek(maxDate),
169+
6,
170+
);
171+
const expectedLength =
172+
defaultDateLib.differenceInCalendarDays(
173+
expectedLastDay,
174+
defaultDateLib.startOfISOWeek(month),
175+
) + 1;
176+
177+
it("clamps to the end of the ISO week", () => {
178+
const dates = getDates(
179+
[month],
180+
maxDate,
181+
{ ISOWeek: true },
182+
defaultDateLib,
183+
);
184+
expect(dates[dates.length - 1]).toEqual(expectedLastDay);
185+
expect(dates).toHaveLength(expectedLength);
186+
});
187+
});
142188
});
143189

144190
describe("when the first month and the last month are different", () => {
@@ -161,16 +207,18 @@ describe("when the first month and the last month are different", () => {
161207
const firstMonth = new Date(2023, 4, 1);
162208
const lastMonth = new Date(2023, 11, 1);
163209
const maxDate = new Date(2023, 5, 15);
210+
const dateLib = new DateLib({ weekStartsOn: 1 });
211+
const expectedLastDay = dateLib.addDays(dateLib.startOfWeek(maxDate), 6);
212+
const expectedLength =
213+
dateLib.differenceInCalendarDays(
214+
expectedLastDay,
215+
dateLib.startOfWeek(firstMonth),
216+
) + 1;
164217

165-
it("the last day should be the max date", () => {
166-
const dates = getDates(
167-
[firstMonth, lastMonth],
168-
maxDate,
169-
{},
170-
new DateLib({ weekStartsOn: 1 }),
171-
);
172-
expect(dates).toHaveLength(46);
173-
expect(dates[dates.length - 1]).toEqual(maxDate);
218+
it("the last day should be the end of that week", () => {
219+
const dates = getDates([firstMonth, lastMonth], maxDate, {}, dateLib);
220+
expect(dates).toHaveLength(expectedLength);
221+
expect(dates[dates.length - 1]).toEqual(expectedLastDay);
174222
});
175223
});
176224
describe("when using ISO weeks", () => {

src/helpers/getDates.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,33 @@ export function getDates(
4343
? startOfISOWeek(firstMonth)
4444
: startOfWeek(firstMonth);
4545

46-
const endWeekLastDate = broadcastCalendar
46+
const displayMonthsWeekEnd = broadcastCalendar
4747
? endOfBroadcastWeek(lastMonth)
4848
: ISOWeek
4949
? endOfISOWeek(endOfMonth(lastMonth))
5050
: endOfWeek(endOfMonth(lastMonth));
5151

52-
const nOfDays = differenceInCalendarDays(endWeekLastDate, startWeekFirstDate);
52+
// If maxDate is set, clamp the grid to the end of that week.
53+
const constraintWeekEnd =
54+
maxDate &&
55+
(broadcastCalendar
56+
? endOfBroadcastWeek(maxDate)
57+
: ISOWeek
58+
? endOfISOWeek(maxDate)
59+
: endOfWeek(maxDate));
60+
61+
// Pick the earliest week end between the displayed months and the constraint.
62+
const gridEndDate =
63+
constraintWeekEnd && isAfter(displayMonthsWeekEnd, constraintWeekEnd)
64+
? constraintWeekEnd
65+
: displayMonthsWeekEnd;
66+
67+
const nOfDays = differenceInCalendarDays(gridEndDate, startWeekFirstDate);
5368
const nOfMonths = differenceInCalendarMonths(lastMonth, firstMonth) + 1;
5469

5570
const dates: Date[] = [];
5671
for (let i = 0; i <= nOfDays; i++) {
5772
const date = addDays(startWeekFirstDate, i);
58-
if (maxDate && isAfter(date, maxDate)) {
59-
break;
60-
}
6173
dates.push(date);
6274
}
6375

0 commit comments

Comments
 (0)