react-day-picker 9.0.6 → 9.0.7

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 (52) hide show
  1. package/dist/cjs/DayPicker.js +6 -3
  2. package/dist/cjs/DayPicker.js.map +1 -1
  3. package/dist/cjs/index.d.ts +1 -0
  4. package/dist/cjs/index.js +3 -0
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/selection/useMulti.js +1 -7
  7. package/dist/cjs/selection/useMulti.js.map +1 -1
  8. package/dist/cjs/selection/useRange.js +1 -7
  9. package/dist/cjs/selection/useRange.js.map +1 -1
  10. package/dist/cjs/selection/useSingle.js +2 -8
  11. package/dist/cjs/selection/useSingle.js.map +1 -1
  12. package/dist/cjs/types/props.d.ts +16 -8
  13. package/dist/cjs/useCalendar.d.ts +1 -1
  14. package/dist/cjs/useCalendar.js +26 -2
  15. package/dist/cjs/useCalendar.js.map +1 -1
  16. package/dist/cjs/useDayPicker.d.ts +1 -0
  17. package/dist/cjs/useDayPicker.js +1 -1
  18. package/dist/cjs/useDayPicker.js.map +1 -1
  19. package/dist/esm/DayPicker.js +6 -3
  20. package/dist/esm/DayPicker.js.map +1 -1
  21. package/dist/esm/index.d.ts +1 -0
  22. package/dist/esm/index.js +1 -0
  23. package/dist/esm/index.js.map +1 -1
  24. package/dist/esm/selection/useMulti.js +1 -7
  25. package/dist/esm/selection/useMulti.js.map +1 -1
  26. package/dist/esm/selection/useRange.js +1 -7
  27. package/dist/esm/selection/useRange.js.map +1 -1
  28. package/dist/esm/selection/useSingle.js +2 -8
  29. package/dist/esm/selection/useSingle.js.map +1 -1
  30. package/dist/esm/types/props.d.ts +16 -8
  31. package/dist/esm/useCalendar.d.ts +1 -1
  32. package/dist/esm/useCalendar.js +26 -2
  33. package/dist/esm/useCalendar.js.map +1 -1
  34. package/dist/esm/useDayPicker.d.ts +1 -0
  35. package/dist/esm/useDayPicker.js +1 -1
  36. package/dist/esm/useDayPicker.js.map +1 -1
  37. package/examples/SingleRequired.tsx +1 -1
  38. package/package.json +4 -4
  39. package/src/DayPicker.test.tsx +49 -5
  40. package/src/DayPicker.tsx +20 -17
  41. package/src/index.ts +2 -0
  42. package/src/selection/useMulti.tsx +1 -8
  43. package/src/selection/useRange.tsx +0 -8
  44. package/src/selection/useSingle.tsx +2 -9
  45. package/src/types/props.test.tsx +10 -3
  46. package/src/types/props.ts +16 -8
  47. package/src/useCalendar.ts +63 -6
  48. package/src/useDayPicker.ts +1 -1
  49. package/website/docs/docs/localization.mdx +21 -0
  50. package/website/docs/docs/selection-modes.mdx +9 -8
  51. package/website/docs/docs/styling.mdx +2 -2
  52. package/website/docs/upgrading.mdx +2 -2
@@ -12,8 +12,11 @@ export type DayPickerProps = PropsBase & (PropsSingle | PropsSingleRequired | Pr
12
12
  required?: undefined;
13
13
  });
14
14
  /**
15
- * Props used for customization of the calendar, localization, and event
16
- * handling.
15
+ * Props for customizing the calendar, handling localization, and managing
16
+ * events. These exclude the selection mode props.
17
+ *
18
+ * @group DayPicker
19
+ * @see https://daypicker.dev/api/interfaces/PropsBase
17
20
  */
18
21
  export interface PropsBase {
19
22
  /**
@@ -307,12 +310,17 @@ export interface PropsBase {
307
310
  /** Add the language tag to the container element. */
308
311
  lang?: HTMLDivElement["lang"];
309
312
  /**
310
- * The date-fns locale object used to localize dates.
313
+ * The locale object used to localize dates. Pass a locale from `date-fns` to
314
+ * localize the calendar.
315
+ *
316
+ * @example
317
+ * import { es } from "date-fns/locale";
318
+ * <DayPicker locale={es} />
311
319
  *
312
- * @defaultValue en-US
320
+ * @defaultValue enUS - The English locale default of `date-fns`.
313
321
  * @see https://daypicker.dev/docs/localization
314
322
  */
315
- locale?: Locale | undefined;
323
+ locale?: Partial<Locale> | undefined;
316
324
  /**
317
325
  * The index of the first day of the week (0 - Sunday). Overrides the locale's
318
326
  * one.
@@ -436,7 +444,7 @@ export interface PropsSingleRequired {
436
444
  mode: "single";
437
445
  required: true;
438
446
  /** The selected date. */
439
- selected: Date;
447
+ selected: Date | undefined;
440
448
  /** Event handler when a day is selected. */
441
449
  onSelect?: (selected: Date, triggerDate: Date, modifiers: Modifiers, e: React.MouseEvent | React.KeyboardEvent) => void | undefined;
442
450
  }
@@ -462,7 +470,7 @@ export interface PropsMultiRequired {
462
470
  mode: "multiple";
463
471
  required: true;
464
472
  /** The selected dates. */
465
- selected: Date[];
473
+ selected: Date[] | undefined;
466
474
  /** Event handler when days are selected. */
467
475
  onSelect?: (selected: Date[], triggerDate: Date, modifiers: Modifiers, e: React.MouseEvent | React.KeyboardEvent) => void;
468
476
  /** The minimum number of selectable days. */
@@ -503,7 +511,7 @@ export interface PropsRangeRequired {
503
511
  */
504
512
  excludeDisabled?: boolean | undefined;
505
513
  /** The selected range. */
506
- selected: DateRange;
514
+ selected: DateRange | undefined;
507
515
  /** Event handler when a range is selected. */
508
516
  onSelect?: (selected: DateRange, triggerDate: Date, modifiers: Modifiers, e: React.MouseEvent | React.KeyboardEvent) => void;
509
517
  /** The minimum number of days to include in the range. */
@@ -45,4 +45,4 @@ export interface Calendar {
45
45
  goToDay: (day: CalendarDay) => void;
46
46
  }
47
47
  /** @private */
48
- export declare function useCalendar(props: DayPickerProps, dateLib: DateLib): Calendar;
48
+ export declare function useCalendar(props: Pick<DayPickerProps, "captionLayout" | "endMonth" | "startMonth" | "today" | "fixedWeeks" | "ISOWeek" | "weekStartsOn" | "numberOfMonths" | "disableNavigation" | "onMonthChange" | "month" | "defaultMonth" | "fromMonth" | "fromYear" | "toMonth" | "toYear">, dateLib: DateLib): Calendar;
@@ -1,3 +1,4 @@
1
+ import { useEffect, useState } from "react";
1
2
  import { getDates } from "./helpers/getDates.js";
2
3
  import { getDays } from "./helpers/getDays.js";
3
4
  import { getDisplayMonths } from "./helpers/getDisplayMonths.js";
@@ -7,14 +8,37 @@ import { getNavMonths } from "./helpers/getNavMonth.js";
7
8
  import { getNextMonth } from "./helpers/getNextMonth.js";
8
9
  import { getPreviousMonth } from "./helpers/getPreviousMonth.js";
9
10
  import { getWeeks } from "./helpers/getWeeks.js";
10
- import { useControlledValue } from "./helpers/useControlledValue.js";
11
11
  /** @private */
12
12
  export function useCalendar(props, dateLib) {
13
+ const { fromYear, toYear, startMonth, endMonth, today, numberOfMonths, month, defaultMonth } = props;
13
14
  const [navStart, navEnd] = getNavMonths(props, dateLib);
14
15
  const { startOfMonth, endOfMonth } = dateLib;
15
16
  const initialDisplayMonth = getInitialMonth(props, dateLib);
16
17
  // The first month displayed in the calendar
17
- const [firstMonth, setFirstMonth] = useControlledValue(initialDisplayMonth, props.month ? startOfMonth(props.month) : undefined);
18
+ const [firstMonth, setFirstMonth] = useState(initialDisplayMonth);
19
+ useEffect(() => {
20
+ const initialDisplayMonth = getInitialMonth({
21
+ fromYear,
22
+ toYear,
23
+ startMonth,
24
+ endMonth,
25
+ month,
26
+ defaultMonth,
27
+ today,
28
+ numberOfMonths
29
+ }, dateLib);
30
+ setFirstMonth(initialDisplayMonth);
31
+ }, [
32
+ dateLib,
33
+ defaultMonth,
34
+ endMonth,
35
+ fromYear,
36
+ month,
37
+ numberOfMonths,
38
+ startMonth,
39
+ toYear,
40
+ today
41
+ ]);
18
42
  /** The months displayed in the calendar. */
19
43
  const displayMonths = getDisplayMonths(firstMonth, navEnd, props, dateLib);
20
44
  /** The dates displayed in the calendar. */
@@ -1 +1 @@
1
- {"version":3,"file":"useCalendar.js","sourceRoot":"","sources":["../../src/useCalendar.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useCalendar.js","sourceRoot":"","sources":["../../src/useCalendar.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { CalendarMonth } from "./classes/CalendarMonth.js";
3
3
  import type { DayPickerProps } from "./types/props.js";
4
4
  import type { SelectedValue, SelectHandler } from "./types/selection.js";
5
5
  import { Modifiers } from "./types/shared.js";
6
+ /** @private */
6
7
  export declare const dayPickerContext: import("react").Context<DayPickerContext<DayPickerProps> | undefined>;
7
8
  export type DayPickerContext<T extends DayPickerProps> = {
8
9
  /** The months displayed in the calendar. */
@@ -1,5 +1,5 @@
1
1
  import { createContext, useContext } from "react";
2
- // Create a context with a default value
2
+ /** @private */
3
3
  export const dayPickerContext = createContext(undefined);
4
4
  /**
5
5
  * Return the context to work with `<DayPicker />` inside custom components.
@@ -1 +1 @@
1
- {"version":3,"file":"useDayPicker.js","sourceRoot":"","sources":["../../src/useDayPicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAQlD,wCAAwC;AACxC,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAE3C,SAAS,CAAC,CAAC;AAqBb;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAA2B,KAAS;IAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,OAA8B,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"useDayPicker.js","sourceRoot":"","sources":["../../src/useDayPicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAQlD,eAAe;AACf,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAE3C,SAAS,CAAC,CAAC;AAqBb;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAA2B,KAAS;IAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,OAA8B,CAAC;AACxC,CAAC"}
@@ -3,7 +3,7 @@ import React, { useState } from "react";
3
3
  import { DayPicker } from "react-day-picker";
4
4
 
5
5
  export function SingleRequired() {
6
- const [selectedDay, setSelectedDay] = useState<Date>(new Date());
6
+ const [selectedDay, setSelectedDay] = useState<Date>();
7
7
 
8
8
  return (
9
9
  <DayPicker
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-day-picker",
3
- "version": "9.0.6",
3
+ "version": "9.0.7",
4
4
  "description": "Customizable Date Picker for React",
5
5
  "author": "Giampaolo Bellavite <io@gpbl.dev>",
6
6
  "homepage": "https://daypicker.dev",
@@ -141,7 +141,7 @@
141
141
  "@testing-library/user-event": "^14.5.2",
142
142
  "@trivago/prettier-plugin-sort-imports": "^4.3.0",
143
143
  "@types/jest": "^29.5.12",
144
- "@types/node": "^22.0.0",
144
+ "@types/node": "^22.1.0",
145
145
  "@types/react": "^18.3.3",
146
146
  "@types/react-dom": "^18.3.0",
147
147
  "@typescript-eslint/eslint-plugin": "^7.18.0",
@@ -152,7 +152,7 @@
152
152
  "eslint-config-prettier": "^9.1.0",
153
153
  "eslint-import-resolver-typescript": "^3.6.1",
154
154
  "eslint-plugin-import": "^2.29.1",
155
- "eslint-plugin-jest": "^28.6.0",
155
+ "eslint-plugin-jest": "^28.7.0",
156
156
  "eslint-plugin-prettier": "^5.2.1",
157
157
  "eslint-plugin-react": "^7.35.0",
158
158
  "eslint-plugin-react-hooks": "^4.6.2",
@@ -166,7 +166,7 @@
166
166
  "react": "^18.3.1",
167
167
  "react-classnaming": "^0.16.4",
168
168
  "react-dom": "^18.3.1",
169
- "ts-jest": "^29.2.3",
169
+ "ts-jest": "^29.2.4",
170
170
  "ts-node": "^10.9.2",
171
171
  "tslib": "^2.6.3",
172
172
  "typescript": "~5.5.4",
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
 
3
- import { fireEvent, render, screen } from "@testing-library/react";
4
- import { startOfDay, startOfMonth } from "date-fns";
3
+ import { addMonths, startOfDay, startOfMonth } from "date-fns";
4
+ import { defaultLocale } from "react-day-picker";
5
5
 
6
6
  import {
7
7
  activeElement,
@@ -10,11 +10,13 @@ import {
10
10
  nav,
11
11
  previousButton
12
12
  } from "@/test/elements";
13
+ import { fireEvent, render, screen } from "@/test/render";
13
14
  import { user } from "@/test/user";
14
15
 
15
16
  import { DayPicker } from "./DayPicker";
16
17
  import { MonthProps } from "./components/Month";
17
18
  import { MonthsProps } from "./components/Months";
19
+ import { labelGrid } from "./labels";
18
20
 
19
21
  const testId = "test";
20
22
  const dayPicker = () => screen.getByTestId(testId);
@@ -24,14 +26,14 @@ test("should render a date picker component", () => {
24
26
  expect(dayPicker()).toBeInTheDocument();
25
27
  });
26
28
 
27
- it("should render the navigation and month grids", () => {
29
+ test("render the navigation and month grids", () => {
28
30
  render(<DayPicker data-testid={testId} />);
29
31
 
30
32
  expect(nav()).toBeInTheDocument();
31
33
  expect(grid()).toBeInTheDocument();
32
34
  });
33
35
 
34
- it("should apply classnames and style according to props", () => {
36
+ test("apply classnames and style according to props", () => {
35
37
  render(
36
38
  <DayPicker
37
39
  data-testid={testId}
@@ -47,7 +49,7 @@ it("should apply classnames and style according to props", () => {
47
49
  expect(dayPicker()).toHaveStyle({ color: "red" });
48
50
  });
49
51
 
50
- it("should use custom components", () => {
52
+ test("use custom components", () => {
51
53
  render(
52
54
  <DayPicker
53
55
  data-testid={testId}
@@ -131,3 +133,45 @@ describe("when a day is mouse entered", () => {
131
133
  expect(handleDayMouseLeave).toHaveBeenCalled();
132
134
  });
133
135
  });
136
+
137
+ describe("when the `month` is changed programmatically", () => {
138
+ test("should update the calendar to reflect the new month", async () => {
139
+ const initialMonth = new Date(2023, 0, 1); // January 2023
140
+ const newMonth = new Date(2023, 1, 1); // February 2023
141
+ const { rerender } = render(
142
+ <DayPicker month={initialMonth} mode="single" />
143
+ );
144
+ expect(grid("January 2023")).toBeInTheDocument();
145
+ rerender(<DayPicker month={newMonth} mode="single" />);
146
+ expect(grid("February 2023")).toBeInTheDocument();
147
+ });
148
+ });
149
+
150
+ describe("when the `startMonth` is changed programmatically", () => {
151
+ test("should update the calendar to reflect the new month", async () => {
152
+ const initialStartMonth = new Date();
153
+ const newStartMonth = addMonths(new Date(), 2);
154
+ const { rerender } = render(
155
+ <DayPicker startMonth={initialStartMonth} mode="single" />
156
+ );
157
+ expect(grid(labelGrid(initialStartMonth))).toBeInTheDocument();
158
+ rerender(<DayPicker startMonth={newStartMonth} mode="single" />);
159
+ expect(grid(labelGrid(newStartMonth))).toBeInTheDocument();
160
+ });
161
+ });
162
+
163
+ test("extends the default locale", () => {
164
+ render(
165
+ <DayPicker
166
+ month={new Date(2024, 0)}
167
+ locale={{
168
+ localize: {
169
+ ...defaultLocale.localize,
170
+ month: () => "bar"
171
+ }
172
+ }}
173
+ />
174
+ );
175
+ // Check if the custom month name is rendered
176
+ expect(grid("bar 2024")).toBeInTheDocument();
177
+ });
package/src/DayPicker.tsx CHANGED
@@ -20,6 +20,7 @@ import { getWeekdays } from "./helpers/getWeekdays.js";
20
20
  import { getYearOptions } from "./helpers/getYearOptions.js";
21
21
  import * as defaultLabels from "./labels/index.js";
22
22
  import type { FormatOptions, LabelOptions } from "./lib/dateLib.js";
23
+ import { enUS } from "./lib/locales.js";
23
24
  import type {
24
25
  DayPickerProps,
25
26
  Modifiers,
@@ -43,27 +44,29 @@ import { isDateRange } from "./utils/typeguards.js";
43
44
  * @see https://daypicker.dev
44
45
  */
45
46
  export function DayPicker(props: DayPickerProps) {
46
- const { components, formatters, labels, dateLib, classNames } = useMemo(
47
- () => ({
48
- dateLib: getDateLib(props.dateLib),
49
- components: getComponents(props.components),
50
- formatters: getFormatters(props.formatters),
51
- labels: { ...defaultLabels, ...props.labels },
52
- classNames: { ...getDefaultClassNames(), ...props.classNames }
53
- }),
54
- [
55
- props.classNames,
56
- props.components,
57
- props.dateLib,
58
- props.formatters,
59
- props.labels
60
- ]
61
- );
47
+ const { components, formatters, labels, dateLib, locale, classNames } =
48
+ useMemo(
49
+ () => ({
50
+ dateLib: getDateLib(props.dateLib),
51
+ components: getComponents(props.components),
52
+ formatters: getFormatters(props.formatters),
53
+ labels: { ...defaultLabels, ...props.labels },
54
+ locale: { ...enUS, ...props.locale },
55
+ classNames: { ...getDefaultClassNames(), ...props.classNames }
56
+ }),
57
+ [
58
+ props.classNames,
59
+ props.components,
60
+ props.dateLib,
61
+ props.formatters,
62
+ props.labels,
63
+ props.locale
64
+ ]
65
+ );
62
66
 
63
67
  const {
64
68
  captionLayout,
65
69
  firstWeekContainsDate,
66
- locale,
67
70
  mode,
68
71
  onDayBlur,
69
72
  onDayClick,
package/src/index.ts CHANGED
@@ -13,3 +13,5 @@ export * from "./utils/index.js";
13
13
  export * from "./UI.js";
14
14
 
15
15
  export * from "./useDayPicker.js";
16
+
17
+ export { enUS as defaultLocale } from "./lib/locales.js";
@@ -22,14 +22,7 @@ export function useMulti<T extends DayPickerProps>(
22
22
  initiallySelected
23
23
  );
24
24
 
25
- const { isSameDay, Date } = dateLib;
26
-
27
- // Update the selected date if the required flag is set.
28
- React.useEffect(() => {
29
- if (required && selected === undefined) {
30
- setSelected([new Date()]);
31
- }
32
- }, [required, selected, Date, mode]);
25
+ const { isSameDay } = dateLib;
33
26
 
34
27
  // Update the selected date if the selected value from props changes.
35
28
  React.useEffect(() => {
@@ -16,7 +16,6 @@ export function useRange<T extends DayPickerProps>(
16
16
  dateLib: DateLib
17
17
  ): Selection<T> {
18
18
  const {
19
- mode,
20
19
  disabled,
21
20
  excludeDisabled,
22
21
  selected: initiallySelected,
@@ -28,13 +27,6 @@ export function useRange<T extends DayPickerProps>(
28
27
  initiallySelected
29
28
  );
30
29
 
31
- // Update the selected date if the required flag is set.
32
- React.useEffect(() => {
33
- if (required && selected === undefined) {
34
- setSelected({ from: undefined, to: undefined });
35
- }
36
- }, [required, selected, mode]);
37
-
38
30
  // Update the selected date if the `selected` prop changes.
39
31
  React.useEffect(() => {
40
32
  setSelected(initiallySelected);
@@ -23,21 +23,14 @@ export function useSingle<T extends DayPickerProps>(
23
23
  const {
24
24
  selected: initiallySelected,
25
25
  required,
26
- onSelect,
27
- mode
26
+ onSelect
28
27
  } = props as PropsSingle;
29
28
 
30
29
  const [selected, setSelected] = React.useState<Date | undefined>(
31
30
  initiallySelected
32
31
  );
33
32
 
34
- const { isSameDay, Date, startOfDay } = dateLib;
35
- // Update the selected date if the required flag is set.
36
- React.useEffect(() => {
37
- if (required && selected === undefined) {
38
- setSelected(startOfDay(new Date()));
39
- }
40
- }, [required, selected, Date, startOfDay, mode]);
33
+ const { isSameDay } = dateLib;
41
34
 
42
35
  // Update the selected date if the `selected` value changes.
43
36
  React.useEffect(() => {
@@ -2,6 +2,8 @@ import React from "react";
2
2
 
3
3
  import { DayPicker } from "../DayPicker";
4
4
 
5
+ import { DateRange } from "./shared";
6
+
5
7
  const Test = () => {
6
8
  return (
7
9
  <>
@@ -23,15 +25,20 @@ const Test = () => {
23
25
  required
24
26
  onSelect={(date: Date | undefined) => {}}
25
27
  />
26
- {/* @ts-expect-error selected should not be undefined. */}
28
+ {/* Allow undefined as initial selected value */}
27
29
  <DayPicker mode="single" required selected={undefined} />
28
30
  <DayPicker
29
31
  mode="multiple"
30
- required={true}
31
- // @ts-expect-error Missing `selected`
32
+ required
32
33
  selected={undefined}
33
34
  onSelect={(selected: Date[], date: Date, modifiers) => {}}
34
35
  />
36
+ <DayPicker
37
+ mode="range"
38
+ required
39
+ selected={undefined}
40
+ onSelect={(selected: DateRange, date: Date, modifiers) => {}}
41
+ />
35
42
  <DayPicker
36
43
  mode="multiple"
37
44
  required={false}
@@ -37,8 +37,11 @@ export type DayPickerProps = PropsBase &
37
37
  );
38
38
 
39
39
  /**
40
- * Props used for customization of the calendar, localization, and event
41
- * handling.
40
+ * Props for customizing the calendar, handling localization, and managing
41
+ * events. These exclude the selection mode props.
42
+ *
43
+ * @group DayPicker
44
+ * @see https://daypicker.dev/api/interfaces/PropsBase
42
45
  */
43
46
  export interface PropsBase {
44
47
  /**
@@ -335,12 +338,17 @@ export interface PropsBase {
335
338
  /** Add the language tag to the container element. */
336
339
  lang?: HTMLDivElement["lang"];
337
340
  /**
338
- * The date-fns locale object used to localize dates.
341
+ * The locale object used to localize dates. Pass a locale from `date-fns` to
342
+ * localize the calendar.
343
+ *
344
+ * @example
345
+ * import { es } from "date-fns/locale";
346
+ * <DayPicker locale={es} />
339
347
  *
340
- * @defaultValue en-US
348
+ * @defaultValue enUS - The English locale default of `date-fns`.
341
349
  * @see https://daypicker.dev/docs/localization
342
350
  */
343
- locale?: Locale | undefined;
351
+ locale?: Partial<Locale> | undefined;
344
352
  /**
345
353
  * The index of the first day of the week (0 - Sunday). Overrides the locale's
346
354
  * one.
@@ -470,7 +478,7 @@ export interface PropsSingleRequired {
470
478
  mode: "single";
471
479
  required: true;
472
480
  /** The selected date. */
473
- selected: Date;
481
+ selected: Date | undefined;
474
482
  /** Event handler when a day is selected. */
475
483
  onSelect?: (
476
484
  selected: Date,
@@ -506,7 +514,7 @@ export interface PropsMultiRequired {
506
514
  mode: "multiple";
507
515
  required: true;
508
516
  /** The selected dates. */
509
- selected: Date[];
517
+ selected: Date[] | undefined;
510
518
  /** Event handler when days are selected. */
511
519
  onSelect?: (
512
520
  selected: Date[],
@@ -557,7 +565,7 @@ export interface PropsRangeRequired {
557
565
  */
558
566
  excludeDisabled?: boolean | undefined;
559
567
  /** The selected range. */
560
- selected: DateRange;
568
+ selected: DateRange | undefined;
561
569
  /** Event handler when a range is selected. */
562
570
  onSelect?: (
563
571
  selected: DateRange,
@@ -1,3 +1,5 @@
1
+ import { useEffect, useState } from "react";
2
+
1
3
  import type {
2
4
  CalendarWeek,
3
5
  CalendarDay,
@@ -12,7 +14,6 @@ import { getNavMonths } from "./helpers/getNavMonth.js";
12
14
  import { getNextMonth } from "./helpers/getNextMonth.js";
13
15
  import { getPreviousMonth } from "./helpers/getPreviousMonth.js";
14
16
  import { getWeeks } from "./helpers/getWeeks.js";
15
- import { useControlledValue } from "./helpers/useControlledValue.js";
16
17
  import type { DayPickerProps } from "./types/props.js";
17
18
  import type { DateLib } from "./types/shared.js";
18
19
 
@@ -64,7 +65,39 @@ export interface Calendar {
64
65
  }
65
66
 
66
67
  /** @private */
67
- export function useCalendar(props: DayPickerProps, dateLib: DateLib): Calendar {
68
+ export function useCalendar(
69
+ props: Pick<
70
+ DayPickerProps,
71
+ | "captionLayout"
72
+ | "endMonth"
73
+ | "startMonth"
74
+ | "today"
75
+ | "fixedWeeks"
76
+ | "ISOWeek"
77
+ | "weekStartsOn"
78
+ | "numberOfMonths"
79
+ | "disableNavigation"
80
+ | "onMonthChange"
81
+ | "month"
82
+ | "defaultMonth"
83
+ // Deprecated:
84
+ | "fromMonth"
85
+ | "fromYear"
86
+ | "toMonth"
87
+ | "toYear"
88
+ >,
89
+ dateLib: DateLib
90
+ ): Calendar {
91
+ const {
92
+ fromYear,
93
+ toYear,
94
+ startMonth,
95
+ endMonth,
96
+ today,
97
+ numberOfMonths,
98
+ month,
99
+ defaultMonth
100
+ } = props;
68
101
  const [navStart, navEnd] = getNavMonths(props, dateLib);
69
102
 
70
103
  const { startOfMonth, endOfMonth } = dateLib;
@@ -72,10 +105,34 @@ export function useCalendar(props: DayPickerProps, dateLib: DateLib): Calendar {
72
105
  const initialDisplayMonth = getInitialMonth(props, dateLib);
73
106
 
74
107
  // The first month displayed in the calendar
75
- const [firstMonth, setFirstMonth] = useControlledValue(
76
- initialDisplayMonth,
77
- props.month ? startOfMonth(props.month) : undefined
78
- );
108
+ const [firstMonth, setFirstMonth] = useState(initialDisplayMonth);
109
+
110
+ useEffect(() => {
111
+ const initialDisplayMonth = getInitialMonth(
112
+ {
113
+ fromYear,
114
+ toYear,
115
+ startMonth,
116
+ endMonth,
117
+ month,
118
+ defaultMonth,
119
+ today,
120
+ numberOfMonths
121
+ },
122
+ dateLib
123
+ );
124
+ setFirstMonth(initialDisplayMonth);
125
+ }, [
126
+ dateLib,
127
+ defaultMonth,
128
+ endMonth,
129
+ fromYear,
130
+ month,
131
+ numberOfMonths,
132
+ startMonth,
133
+ toYear,
134
+ today
135
+ ]);
79
136
 
80
137
  /** The months displayed in the calendar. */
81
138
  const displayMonths = getDisplayMonths(firstMonth, navEnd, props, dateLib);
@@ -6,7 +6,7 @@ import type { DayPickerProps } from "./types/props.js";
6
6
  import type { SelectedValue, SelectHandler } from "./types/selection.js";
7
7
  import { Modifiers } from "./types/shared.js";
8
8
 
9
- // Create a context with a default value
9
+ /** @private */
10
10
  export const dayPickerContext = createContext<
11
11
  DayPickerContext<DayPickerProps> | undefined
12
12
  >(undefined);
@@ -41,6 +41,27 @@ import { es } from "date-fns/locale";
41
41
  <Examples.Spanish />
42
42
  </BrowserWindow>
43
43
 
44
+ :::tip Customizing the Locale
45
+
46
+ You can customize the locale by passing an object with the desired translations. Use the `defaultLocale` object for the default translations.
47
+
48
+ ```tsx
49
+ import { DayPicker, defaultLocale } from "react-day-picker";
50
+
51
+ <DayPicker
52
+ locale={{
53
+ localize: {
54
+ ...defaultLocale.localize,
55
+ day: (day) => "custom-localized-day"
56
+ }
57
+ }}
58
+ month={new Date(2023, 0, 1)}
59
+ mode="single"
60
+ />;
61
+ ```
62
+
63
+ :::
64
+
44
65
  ## First Date of the Week
45
66
 
46
67
  Use the `weekStartsOn` prop to specify the starting day of the week.