react-day-picker 9.3.0 → 9.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/cjs/formatters/formatMonthDropdown.d.ts +2 -1
  2. package/dist/cjs/formatters/formatMonthDropdown.js +1 -2
  3. package/dist/cjs/formatters/formatMonthDropdown.js.map +1 -1
  4. package/dist/cjs/helpers/getDates.d.ts +2 -0
  5. package/dist/cjs/helpers/getDates.js +5 -3
  6. package/dist/cjs/helpers/getDates.js.map +1 -1
  7. package/dist/cjs/helpers/getMonthOptions.d.ts +1 -1
  8. package/dist/cjs/helpers/getMonthOptions.js +2 -1
  9. package/dist/cjs/helpers/getMonthOptions.js.map +1 -1
  10. package/dist/cjs/helpers/getMonths.js +5 -2
  11. package/dist/cjs/helpers/getMonths.js.map +1 -1
  12. package/dist/cjs/types/deprecated.d.ts +7 -0
  13. package/dist/cjs/types/deprecated.js +0 -1
  14. package/dist/cjs/types/deprecated.js.map +1 -1
  15. package/dist/cjs/types/props.d.ts +5 -0
  16. package/dist/cjs/useGetModifiers.d.ts +2 -0
  17. package/dist/cjs/useGetModifiers.js +9 -18
  18. package/dist/cjs/useGetModifiers.js.map +1 -1
  19. package/dist/esm/formatters/formatMonthDropdown.d.ts +2 -1
  20. package/dist/esm/formatters/formatMonthDropdown.js +1 -2
  21. package/dist/esm/formatters/formatMonthDropdown.js.map +1 -1
  22. package/dist/esm/helpers/getDates.d.ts +2 -0
  23. package/dist/esm/helpers/getDates.js +3 -2
  24. package/dist/esm/helpers/getDates.js.map +1 -1
  25. package/dist/esm/helpers/getMonthOptions.d.ts +1 -1
  26. package/dist/esm/helpers/getMonthOptions.js +2 -1
  27. package/dist/esm/helpers/getMonthOptions.js.map +1 -1
  28. package/dist/esm/helpers/getMonths.js +5 -2
  29. package/dist/esm/helpers/getMonths.js.map +1 -1
  30. package/dist/esm/types/deprecated.d.ts +7 -0
  31. package/dist/esm/types/deprecated.js +0 -1
  32. package/dist/esm/types/deprecated.js.map +1 -1
  33. package/dist/esm/types/props.d.ts +5 -0
  34. package/dist/esm/useGetModifiers.d.ts +2 -0
  35. package/dist/esm/useGetModifiers.js +10 -19
  36. package/dist/esm/useGetModifiers.js.map +1 -1
  37. package/examples/StartEndMonthsShowOutsideDays.tsx +20 -0
  38. package/examples/TestCase2585.test.tsx +11 -0
  39. package/examples/TestCase2585.tsx +20 -0
  40. package/examples/__snapshots__/Range.test.tsx.snap +5 -5
  41. package/examples/index.ts +2 -0
  42. package/package.json +13 -13
  43. package/src/formatters/formatMonthDropdown.test.ts +5 -1
  44. package/src/formatters/formatMonthDropdown.ts +2 -3
  45. package/src/helpers/getDates.test.ts +30 -3
  46. package/src/helpers/getDates.ts +3 -2
  47. package/src/helpers/getMonthOptions.ts +5 -2
  48. package/src/helpers/getMonths.ts +6 -2
  49. package/src/types/deprecated.ts +15 -0
  50. package/src/types/props.ts +5 -0
  51. package/src/useGetModifiers.test.tsx +154 -0
  52. package/src/useGetModifiers.tsx +24 -22
  53. package/website/docs/upgrading.mdx +29 -28
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+
3
+ import { DayPicker } from "react-day-picker";
4
+
5
+ /**
6
+ * Test case for issue #2585
7
+ *
8
+ * @see https://github.com/gpbl/react-day-picker/issues/2585
9
+ */
10
+ export function TestCase2585() {
11
+ return (
12
+ <DayPicker
13
+ defaultMonth={new Date(2026, 1)}
14
+ showOutsideDays
15
+ showWeekNumber
16
+ fixedWeeks
17
+ numberOfMonths={12}
18
+ />
19
+ );
20
+ }
@@ -338,7 +338,7 @@ exports[`should match the snapshot 1`] = `
338
338
  </td>
339
339
  <td
340
340
  aria-selected="true"
341
- class="rdp-day rdp-range_start rdp-selected"
341
+ class="rdp-day rdp-selected rdp-range_start"
342
342
  data-day="2020-06-15"
343
343
  data-selected="true"
344
344
  >
@@ -353,7 +353,7 @@ exports[`should match the snapshot 1`] = `
353
353
  </td>
354
354
  <td
355
355
  aria-selected="true"
356
- class="rdp-day rdp-range_middle rdp-selected"
356
+ class="rdp-day rdp-selected rdp-range_middle"
357
357
  data-day="2020-06-16"
358
358
  data-selected="true"
359
359
  >
@@ -368,7 +368,7 @@ exports[`should match the snapshot 1`] = `
368
368
  </td>
369
369
  <td
370
370
  aria-selected="true"
371
- class="rdp-day rdp-range_middle rdp-selected"
371
+ class="rdp-day rdp-selected rdp-range_middle"
372
372
  data-day="2020-06-17"
373
373
  data-selected="true"
374
374
  >
@@ -383,7 +383,7 @@ exports[`should match the snapshot 1`] = `
383
383
  </td>
384
384
  <td
385
385
  aria-selected="true"
386
- class="rdp-day rdp-range_middle rdp-selected"
386
+ class="rdp-day rdp-selected rdp-range_middle"
387
387
  data-day="2020-06-18"
388
388
  data-selected="true"
389
389
  >
@@ -398,7 +398,7 @@ exports[`should match the snapshot 1`] = `
398
398
  </td>
399
399
  <td
400
400
  aria-selected="true"
401
- class="rdp-day rdp-range_end rdp-selected"
401
+ class="rdp-day rdp-selected rdp-range_end"
402
402
  data-day="2020-06-19"
403
403
  data-selected="true"
404
404
  >
package/examples/index.ts CHANGED
@@ -61,6 +61,7 @@ export * from "./Spanish";
61
61
  export * from "./SpanishWeekStartsOn";
62
62
  export * from "./Start";
63
63
  export * from "./StartEndMonths";
64
+ export * from "./StartEndMonthsShowOutsideDays";
64
65
  export * from "./StylingCss";
65
66
  export * from "./StylingInline";
66
67
  export * from "./StylingModifiers";
@@ -69,6 +70,7 @@ export * from "./Testcase1567";
69
70
  export * from "./TestCase2047";
70
71
  export * from "./TestCase2389";
71
72
  export * from "./TestCase2511";
73
+ export * from "./TestCase2585";
72
74
  export * from "./TimeZone";
73
75
  export * from "./Utc";
74
76
  export * from "./WeekIso";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-day-picker",
3
- "version": "9.3.0",
3
+ "version": "9.3.2",
4
4
  "description": "Customizable Date Picker for React",
5
5
  "author": "Giampaolo Bellavite <io@gpbl.dev>",
6
6
  "homepage": "https://daypicker.dev",
@@ -173,34 +173,34 @@
173
173
  "locale.d.ts"
174
174
  ],
175
175
  "dependencies": {
176
- "@date-fns/tz": "^1.1.2",
176
+ "@date-fns/tz": "^1.2.0",
177
177
  "date-fns": "^4.1.0"
178
178
  },
179
179
  "devDependencies": {
180
180
  "@jest/types": "^29.6.3",
181
181
  "@testing-library/dom": "^10.4.0",
182
- "@testing-library/jest-dom": "^6.6.2",
182
+ "@testing-library/jest-dom": "^6.6.3",
183
183
  "@testing-library/react": "^16.0.1",
184
184
  "@testing-library/user-event": "^14.5.2",
185
185
  "@trivago/prettier-plugin-sort-imports": "^4.3.0",
186
- "@types/jest": "^29.5.13",
187
- "@types/node": "^22.7.7",
188
- "@types/react": "^18.3.11",
186
+ "@types/jest": "^29.5.14",
187
+ "@types/node": "^22.9.0",
188
+ "@types/react": "^18.3.12",
189
189
  "@types/react-dom": "^18.3.1",
190
- "@typescript-eslint/eslint-plugin": "^8.10.0",
191
- "@typescript-eslint/parser": "^8.10.0",
190
+ "@typescript-eslint/eslint-plugin": "^8.14.0",
191
+ "@typescript-eslint/parser": "^8.14.0",
192
192
  "date-fns-jalali": "^3.6.0-1",
193
193
  "eslint": "^8.57.1",
194
194
  "eslint-config-prettier": "^9.1.0",
195
195
  "eslint-import-resolver-typescript": "^3.6.3",
196
196
  "eslint-plugin-import": "^2.31.0",
197
- "eslint-plugin-jest": "^28.8.3",
197
+ "eslint-plugin-jest": "^28.9.0",
198
198
  "eslint-plugin-prettier": "^5.2.1",
199
- "eslint-plugin-react": "^7.37.1",
199
+ "eslint-plugin-react": "^7.37.2",
200
200
  "eslint-plugin-react-hooks": "^5.0.0",
201
201
  "eslint-plugin-require-extensions": "^0.1.3",
202
202
  "eslint-plugin-testing-library": "^6.4.0",
203
- "html-validate": "^8.24.2",
203
+ "html-validate": "^8.25.0",
204
204
  "jest": "^29.7.0",
205
205
  "jest-environment-jsdom": "^29.7.0",
206
206
  "mockdate": "^3.0.5",
@@ -210,8 +210,8 @@
210
210
  "react-dom": "^18.3.1",
211
211
  "ts-jest": "^29.2.5",
212
212
  "ts-node": "^10.9.2",
213
- "tslib": "^2.8.0",
214
- "typescript": "~5.5.4",
213
+ "tslib": "^2.8.1",
214
+ "typescript": "~5.6.3",
215
215
  "typescript-css-modules": "^1.0.4"
216
216
  },
217
217
  "peerDependencies": {
@@ -1,11 +1,15 @@
1
1
  import { es } from "date-fns/locale/es";
2
2
 
3
+ import { defaultLocale } from "../classes/DateLib";
4
+
3
5
  import { formatMonthDropdown } from "./formatMonthDropdown";
4
6
 
5
7
  const date = new Date(2022, 10, 21);
6
8
 
7
9
  test("should return the formatted month dropdown label", () => {
8
- expect(formatMonthDropdown(date.getMonth())).toEqual("November");
10
+ expect(formatMonthDropdown(date.getMonth(), defaultLocale)).toEqual(
11
+ "November"
12
+ );
9
13
  });
10
14
 
11
15
  describe("when a locale is passed in", () => {
@@ -1,5 +1,4 @@
1
- import type { DateFnsMonth } from "../classes/DateLib.js";
2
- import { defaultLocale } from "../classes/DateLib.js";
1
+ import type { DateFnsMonth, Locale } from "../classes/DateLib.js";
3
2
 
4
3
  /**
5
4
  * Format the month number for the dropdown option label.
@@ -12,7 +11,7 @@ export function formatMonthDropdown(
12
11
  /** The month number to format. */
13
12
  monthNumber: number,
14
13
  /** The locale to use for formatting. */
15
- locale = defaultLocale
14
+ locale: Locale
16
15
  ): string {
17
16
  return locale.localize?.month(monthNumber as DateFnsMonth);
18
17
  }
@@ -58,9 +58,7 @@ describe("when the first month and the last month are the same", () => {
58
58
  const dates = getDates(
59
59
  [month],
60
60
  undefined,
61
- {
62
- fixedWeeks: true
63
- },
61
+ { fixedWeeks: true },
64
62
  defaultDateLib
65
63
  );
66
64
  expect(dates).toHaveLength(42);
@@ -69,6 +67,35 @@ describe("when the first month and the last month are the same", () => {
69
67
  });
70
68
  });
71
69
  });
70
+
71
+ describe("when the month has 4 weeks", () => {
72
+ const month = new Date(2026, 1); // February 2026
73
+ describe("when not using fixed weeks", () => {
74
+ it("should return 28 dates", () => {
75
+ const dates = getDates(
76
+ [month],
77
+ undefined,
78
+ {
79
+ fixedWeeks: false
80
+ },
81
+ defaultDateLib
82
+ );
83
+ expect(dates).toHaveLength(28);
84
+ });
85
+ });
86
+ describe("when using fixed weeks", () => {
87
+ it("should return 42 dates", () => {
88
+ const dates = getDates(
89
+ [month],
90
+ undefined,
91
+ { fixedWeeks: true },
92
+ defaultDateLib
93
+ );
94
+ expect(dates).toHaveLength(42);
95
+ });
96
+ });
97
+ });
98
+
72
99
  describe("when using Monday as first day of the week", () => {
73
100
  const month = new Date(2023, 4, 1);
74
101
  it("the first day should be Monday", () => {
@@ -2,7 +2,7 @@ import { type DateLib } from "../classes/DateLib.js";
2
2
  import { type DayPickerProps } from "../types/props.js";
3
3
 
4
4
  /** The number of days in a month when having 6 weeks. */
5
- const NrOfDaysWithFixedWeeks = 42;
5
+ export const NrOfDaysWithFixedWeeks = 42;
6
6
 
7
7
  /** Return all the dates to display in the calendar. */
8
8
  export function getDates(
@@ -50,7 +50,8 @@ export function getDates(
50
50
  // If fixed weeks is enabled, add the extra dates to the array
51
51
  const extraDates = NrOfDaysWithFixedWeeks * nOfMonths;
52
52
  if (fixedWeeks && dates.length < extraDates) {
53
- for (let i = 0; i < 7; i++) {
53
+ const daysToAdd = extraDates - dates.length;
54
+ for (let i = 0; i < daysToAdd; i++) {
54
55
  const date = addDays(dates[dates.length - 1], 1);
55
56
  dates.push(date);
56
57
  }
@@ -1,4 +1,4 @@
1
- import type { DateLib } from "../classes/DateLib.js";
1
+ import { defaultLocale, type DateLib } from "../classes/DateLib.js";
2
2
  import { DropdownOption } from "../components/Dropdown.js";
3
3
  import type { Formatters } from "../types/index.js";
4
4
 
@@ -26,7 +26,10 @@ export function getMonthOptions(
26
26
  return a - b;
27
27
  });
28
28
  const options = sortedMonths.map((value) => {
29
- const label = formatters.formatMonthDropdown(value, dateLib.options.locale);
29
+ const label = formatters.formatMonthDropdown(
30
+ value,
31
+ dateLib.options.locale ?? defaultLocale
32
+ );
30
33
  const month = dateLib.Date
31
34
  ? new dateLib.Date(year, value)
32
35
  : new Date(year, value);
@@ -2,6 +2,8 @@ import type { DateLib } from "../classes/DateLib.js";
2
2
  import { CalendarWeek, CalendarDay, CalendarMonth } from "../classes/index.js";
3
3
  import type { DayPickerProps } from "../types/index.js";
4
4
 
5
+ import { NrOfDaysWithFixedWeeks } from "./getDates.js";
6
+
5
7
  /** Return the months to display in the calendar. */
6
8
  export function getMonths(
7
9
  /** The months (as dates) to display in the calendar. */
@@ -37,10 +39,12 @@ export function getMonths(
37
39
  return date >= firstDateOfFirstWeek && date <= lastDateOfLastWeek;
38
40
  });
39
41
 
40
- if (props.fixedWeeks && monthDates.length < 42) {
42
+ if (props.fixedWeeks && monthDates.length < NrOfDaysWithFixedWeeks) {
41
43
  const extraDates = dates.filter((date) => {
44
+ const daysToAdd = NrOfDaysWithFixedWeeks - monthDates.length;
42
45
  return (
43
- date > lastDateOfLastWeek && date <= addDays(lastDateOfLastWeek, 7)
46
+ date > lastDateOfLastWeek &&
47
+ date <= addDays(lastDateOfLastWeek, daysToAdd)
44
48
  );
45
49
  });
46
50
  monthDates.push(...extraDates);
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { DayFlag, SelectionState } from "../UI.js";
2
3
  import {
3
4
  MonthCaption,
4
5
  type MonthCaptionProps
@@ -99,6 +100,20 @@ export type DaySelectionMode = Mode;
99
100
  */
100
101
  export type Modifier = string;
101
102
 
103
+ /**
104
+ * @deprecated This type will be removed. Use {@link DayFlag} or
105
+ * {@link SelectionState} instead.
106
+ * @protected
107
+ */
108
+ export type InternalModifier =
109
+ | DayFlag.disabled
110
+ | DayFlag.hidden
111
+ | DayFlag.focused
112
+ | SelectionState.range_end
113
+ | SelectionState.range_middle
114
+ | SelectionState.range_start
115
+ | SelectionState.selected;
116
+
102
117
  /**
103
118
  * @deprecated This type will be removed. Use `SelectHandler<"single">` instead.
104
119
  * @protected
@@ -291,6 +291,11 @@ export interface PropsBase {
291
291
  * @see https://daypicker.dev/guides/accessibility#autofocus
292
292
  */
293
293
  autoFocus?: boolean;
294
+ /**
295
+ * @private
296
+ * @deprecated This prop will be removed. Use {@link autoFocus} instead.
297
+ */
298
+ initialFocus?: boolean;
294
299
  /**
295
300
  * Apply the `disabled` modifier to the matching days.
296
301
  *
@@ -0,0 +1,154 @@
1
+ import { DayFlag } from "./UI";
2
+ import { CalendarDay, defaultDateLib } from "./classes/index";
3
+ import { useGetModifiers } from "./useGetModifiers";
4
+
5
+ const dateLib = defaultDateLib;
6
+
7
+ const displayedMonth = new Date(2022, 10, 1);
8
+
9
+ const date1 = new Date(2022, 9, 30);
10
+ const date2 = new Date(2022, 10, 10);
11
+ const date3 = new Date(2022, 10, 11);
12
+ const date4 = new Date(2022, 10, 12);
13
+ const date5 = new Date(2022, 10, 13);
14
+ const date6 = new Date(2022, 10, 14);
15
+ const date7 = new Date(2022, 11, 1);
16
+
17
+ const day1 = new CalendarDay(date1, displayedMonth);
18
+ const day2 = new CalendarDay(date2, displayedMonth);
19
+ const day3 = new CalendarDay(date3, displayedMonth);
20
+ const day4 = new CalendarDay(date4, displayedMonth);
21
+ const day5 = new CalendarDay(date5, displayedMonth);
22
+ const day6 = new CalendarDay(date6, displayedMonth);
23
+ const day7 = new CalendarDay(date7, displayedMonth);
24
+
25
+ const days: CalendarDay[] = [day1, day2, day3, day4, day5, day6, day7];
26
+
27
+ const props = {
28
+ disabled: [date2],
29
+ hidden: [date3],
30
+ modifiers: {
31
+ custom: [date4],
32
+ selected: [date6]
33
+ },
34
+ selected: date7,
35
+ showOutsideDays: true,
36
+ today: date5,
37
+ timeZone: "UTC"
38
+ };
39
+
40
+ describe("useGetModifiers", () => {
41
+ describe("default props", () => {
42
+ // eslint-disable-next-line react-hooks/rules-of-hooks
43
+ const getModifiers = useGetModifiers(days, props, dateLib);
44
+
45
+ test("return the modifiers for a given day", () => {
46
+ const modifiers = getModifiers(day2);
47
+
48
+ expect(modifiers[DayFlag.focused]).toBe(false);
49
+ expect(modifiers[DayFlag.disabled]).toBe(true);
50
+ expect(modifiers[DayFlag.hidden]).toBe(false);
51
+ expect(modifiers[DayFlag.outside]).toBe(false);
52
+ expect(modifiers[DayFlag.today]).toBe(false);
53
+ expect(modifiers.custom).toBe(false);
54
+ });
55
+
56
+ test("return the custom modifiers for a given day", () => {
57
+ const modifiers = getModifiers(day4);
58
+ expect(modifiers.custom).toBe(true);
59
+ });
60
+
61
+ test("return the custom `selected` modifier for a given day", () => {
62
+ const modifiers = getModifiers(day6);
63
+ expect(modifiers.selected).toBe(true);
64
+ });
65
+
66
+ test("return the today modifier for a given day", () => {
67
+ const modifiers = getModifiers(day5);
68
+
69
+ expect(modifiers[DayFlag.today]).toBe(true);
70
+ expect(modifiers[DayFlag.focused]).toBe(false);
71
+ expect(modifiers[DayFlag.disabled]).toBe(false);
72
+ expect(modifiers[DayFlag.outside]).toBe(false);
73
+ expect(modifiers[DayFlag.hidden]).toBe(false);
74
+ });
75
+
76
+ test("return the hidden modifier for a given day", () => {
77
+ const modifiers = getModifiers(day3);
78
+
79
+ expect(modifiers[DayFlag.hidden]).toBe(true);
80
+ expect(modifiers[DayFlag.focused]).toBe(false);
81
+ expect(modifiers[DayFlag.disabled]).toBe(false);
82
+ expect(modifiers[DayFlag.outside]).toBe(false);
83
+ expect(modifiers[DayFlag.today]).toBe(false);
84
+ });
85
+
86
+ test("return the modifiers for a given day before the displayed month", () => {
87
+ const modifiers = getModifiers(day1);
88
+
89
+ expect(modifiers[DayFlag.focused]).toBe(false);
90
+ expect(modifiers[DayFlag.disabled]).toBe(false);
91
+ expect(modifiers[DayFlag.hidden]).toBe(false);
92
+ expect(modifiers[DayFlag.outside]).toBe(true);
93
+ expect(modifiers[DayFlag.today]).toBe(false);
94
+ expect(modifiers.selected).toBe(false);
95
+ });
96
+
97
+ test("return the modifiers for a given day after the displayed month", () => {
98
+ const modifiers = getModifiers(day7);
99
+
100
+ expect(modifiers[DayFlag.focused]).toBe(false);
101
+ expect(modifiers[DayFlag.disabled]).toBe(false);
102
+ expect(modifiers[DayFlag.hidden]).toBe(false);
103
+ expect(modifiers[DayFlag.outside]).toBe(true);
104
+ expect(modifiers[DayFlag.today]).toBe(false);
105
+ expect(modifiers.selected).toBe(false);
106
+ });
107
+ });
108
+
109
+ describe("with startMonth and endMonth props", () => {
110
+ const startMonth = new Date(displayedMonth);
111
+ startMonth.setDate(30);
112
+ const endMonth = new Date(displayedMonth);
113
+ endMonth.setDate(1);
114
+
115
+ // eslint-disable-next-line react-hooks/rules-of-hooks
116
+ const getModifiers = useGetModifiers(
117
+ days,
118
+ { ...props, startMonth, endMonth },
119
+ dateLib
120
+ );
121
+ test("return the modifiers for a given day", () => {
122
+ const modifiers = getModifiers(day2);
123
+
124
+ expect(modifiers[DayFlag.focused]).toBe(false);
125
+ expect(modifiers[DayFlag.disabled]).toBe(true);
126
+ expect(modifiers[DayFlag.hidden]).toBe(false);
127
+ expect(modifiers[DayFlag.outside]).toBe(false);
128
+ expect(modifiers[DayFlag.today]).toBe(false);
129
+ expect(modifiers.custom).toBe(false);
130
+ });
131
+
132
+ test("return the modifiers for a given day before the displayed month", () => {
133
+ const modifiers = getModifiers(day1);
134
+
135
+ expect(modifiers[DayFlag.focused]).toBe(false);
136
+ expect(modifiers[DayFlag.disabled]).toBe(false);
137
+ expect(modifiers[DayFlag.hidden]).toBe(true);
138
+ expect(modifiers[DayFlag.outside]).toBe(true);
139
+ expect(modifiers[DayFlag.today]).toBe(false);
140
+ expect(modifiers.selected).toBe(false);
141
+ });
142
+
143
+ test("return the modifiers for a given day after the displayed month", () => {
144
+ const modifiers = getModifiers(day7);
145
+
146
+ expect(modifiers[DayFlag.focused]).toBe(false);
147
+ expect(modifiers[DayFlag.disabled]).toBe(false);
148
+ expect(modifiers[DayFlag.hidden]).toBe(true);
149
+ expect(modifiers[DayFlag.outside]).toBe(true);
150
+ expect(modifiers[DayFlag.today]).toBe(false);
151
+ expect(modifiers.selected).toBe(false);
152
+ });
153
+ });
154
+ });
@@ -1,6 +1,6 @@
1
1
  import { TZDate } from "@date-fns/tz";
2
2
 
3
- import { DayFlag, SelectionState } from "./UI.js";
3
+ import { DayFlag } from "./UI.js";
4
4
  import type { CalendarDay, DateLib } from "./classes/index.js";
5
5
  import type { DayPickerProps, Modifiers } from "./types/index.js";
6
6
  import { dateMatchModifiers } from "./utils/dateMatchModifiers.js";
@@ -8,6 +8,8 @@ import { dateMatchModifiers } from "./utils/dateMatchModifiers.js";
8
8
  /**
9
9
  * Return a function to get the modifiers for a given day.
10
10
  *
11
+ * NOTE: this is not an hook, but a factory for `getModifiers`.
12
+ *
11
13
  * @private
12
14
  */
13
15
  export function useGetModifiers(
@@ -17,7 +19,17 @@ export function useGetModifiers(
17
19
  ) {
18
20
  const { disabled, hidden, modifiers, showOutsideDays, today } = props;
19
21
 
20
- const { isSameDay, isSameMonth } = dateLib;
22
+ const {
23
+ isSameDay,
24
+ isSameMonth,
25
+ startOfMonth,
26
+ isBefore,
27
+ endOfMonth,
28
+ isAfter
29
+ } = dateLib;
30
+
31
+ const startMonth = props.startMonth && startOfMonth(props.startMonth);
32
+ const endMonth = props.endMonth && endOfMonth(props.endMonth);
21
33
 
22
34
  const internalModifiersMap: Record<DayFlag, CalendarDay[]> = {
23
35
  [DayFlag.focused]: [],
@@ -29,24 +41,25 @@ export function useGetModifiers(
29
41
 
30
42
  const customModifiersMap: Record<string, CalendarDay[]> = {};
31
43
 
32
- const selectionModifiersMap: Record<SelectionState, CalendarDay[]> = {
33
- [SelectionState.range_end]: [],
34
- [SelectionState.range_middle]: [],
35
- [SelectionState.range_start]: [],
36
- [SelectionState.selected]: []
37
- };
38
-
39
44
  for (const day of days) {
40
45
  const { date, displayMonth } = day;
41
46
 
42
47
  const isOutside = Boolean(displayMonth && !isSameMonth(date, displayMonth));
43
48
 
49
+ const isBeforeStartMonth = Boolean(
50
+ startMonth && isBefore(date, startMonth)
51
+ );
52
+
53
+ const isAfterEndMonth = Boolean(endMonth && isAfter(date, endMonth));
54
+
44
55
  const isDisabled = Boolean(
45
56
  disabled && dateMatchModifiers(date, disabled, dateLib)
46
57
  );
47
58
 
48
59
  const isHidden =
49
60
  Boolean(hidden && dateMatchModifiers(date, hidden, dateLib)) ||
61
+ isBeforeStartMonth ||
62
+ isAfterEndMonth ||
50
63
  (!showOutsideDays && isOutside);
51
64
 
52
65
  const isToday = isSameDay(
@@ -81,7 +94,7 @@ export function useGetModifiers(
81
94
  }
82
95
  }
83
96
 
84
- return (day: CalendarDay) => {
97
+ return (day: CalendarDay): Modifiers => {
85
98
  // Initialize all the modifiers to false
86
99
  const dayFlags: Record<DayFlag, boolean> = {
87
100
  [DayFlag.focused]: false,
@@ -90,12 +103,6 @@ export function useGetModifiers(
90
103
  [DayFlag.outside]: false,
91
104
  [DayFlag.today]: false
92
105
  };
93
- const selectionStates: Record<SelectionState, boolean> = {
94
- [SelectionState.range_end]: false,
95
- [SelectionState.range_middle]: false,
96
- [SelectionState.range_start]: false,
97
- [SelectionState.selected]: false
98
- };
99
106
  const customModifiers: Modifiers = {};
100
107
 
101
108
  // Find the modifiers for the given day
@@ -103,19 +110,14 @@ export function useGetModifiers(
103
110
  const days = internalModifiersMap[name as DayFlag];
104
111
  dayFlags[name as DayFlag] = days.some((d) => d === day);
105
112
  }
106
- for (const name in selectionModifiersMap) {
107
- const days = selectionModifiersMap[name as SelectionState];
108
- selectionStates[name as SelectionState] = days.some((d) => d === day);
109
- }
110
113
  for (const name in customModifiersMap) {
111
114
  customModifiers[name] = customModifiersMap[name].some((d) => d === day);
112
115
  }
113
116
 
114
117
  return {
115
- ...selectionStates,
116
118
  ...dayFlags,
117
119
  // custom modifiers should override all the previous ones
118
120
  ...customModifiers
119
- } as Modifiers;
121
+ };
120
122
  };
121
123
  }