react-day-picker 8.0.3 → 8.0.6

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 (207) hide show
  1. package/README.md +1 -1
  2. package/dist/hooks/useDayRender/useDayRender.d.ts +1 -1
  3. package/dist/hooks/useInput/useInput.d.ts +2 -2
  4. package/dist/index.esm.js +3 -3
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.js +3 -3
  7. package/dist/index.js.map +1 -1
  8. package/dist/react-day-picker.min.js +1 -0
  9. package/dist/style.css +11 -10
  10. package/dist/style.module.css +11 -10
  11. package/dist/types/Styles.d.ts +8 -2
  12. package/package.json +15 -13
  13. package/src/DayPicker.tsx +113 -0
  14. package/src/components/Button/Button.test.tsx +47 -0
  15. package/src/components/Button/Button.tsx +36 -0
  16. package/src/components/Button/index.ts +1 -0
  17. package/src/components/Caption/Caption.test.tsx +86 -0
  18. package/src/components/Caption/Caption.tsx +54 -0
  19. package/src/components/Caption/index.ts +1 -0
  20. package/src/components/CaptionDropdowns/CaptionDropdowns.test.tsx +123 -0
  21. package/src/components/CaptionDropdowns/CaptionDropdowns.tsx +43 -0
  22. package/src/components/CaptionDropdowns/index.ts +1 -0
  23. package/src/components/CaptionLabel/CaptionLabel.test.tsx +29 -0
  24. package/src/components/CaptionLabel/CaptionLabel.tsx +32 -0
  25. package/src/components/CaptionLabel/index.ts +1 -0
  26. package/src/components/CaptionNavigation/CaptionNavigation.test.tsx +172 -0
  27. package/src/components/CaptionNavigation/CaptionNavigation.tsx +63 -0
  28. package/src/components/CaptionNavigation/index.ts +1 -0
  29. package/src/components/Day/Day.test.tsx +84 -0
  30. package/src/components/Day/Day.tsx +30 -0
  31. package/src/components/Day/index.ts +1 -0
  32. package/src/components/DayContent/DayContent.test.tsx +51 -0
  33. package/src/components/DayContent/DayContent.tsx +36 -0
  34. package/src/components/DayContent/index.ts +1 -0
  35. package/src/components/Dropdown/Dropdown.test.tsx +73 -0
  36. package/src/components/Dropdown/Dropdown.tsx +56 -0
  37. package/src/components/Dropdown/index.ts +1 -0
  38. package/src/components/Footer/Footer.test.tsx +29 -0
  39. package/src/components/Footer/Footer.tsx +20 -0
  40. package/src/components/Footer/index.ts +1 -0
  41. package/src/components/Head/Head.test.tsx +117 -0
  42. package/src/components/Head/Head.tsx +51 -0
  43. package/src/components/Head/index.ts +1 -0
  44. package/src/components/Head/utils/getWeekdays.test.ts +36 -0
  45. package/src/components/Head/utils/getWeekdays.ts +22 -0
  46. package/src/components/Head/utils/index.ts +1 -0
  47. package/src/components/IconDropdown/IconDropdown.test.tsx +20 -0
  48. package/src/components/IconDropdown/IconDropdown.tsx +24 -0
  49. package/src/components/IconDropdown/index.ts +1 -0
  50. package/src/components/IconLeft/IconLeft.test.tsx +20 -0
  51. package/src/components/IconLeft/IconLeft.tsx +18 -0
  52. package/src/components/IconLeft/index.ts +1 -0
  53. package/src/components/IconRight/IconRight.test.tsx +20 -0
  54. package/src/components/IconRight/IconRight.tsx +17 -0
  55. package/src/components/IconRight/index.ts +1 -0
  56. package/src/components/Month/Month.test.tsx +216 -0
  57. package/src/components/Month/Month.tsx +53 -0
  58. package/src/components/Month/index.ts +1 -0
  59. package/src/components/MonthsDropdown/MonthsDropdown.test.tsx +99 -0
  60. package/src/components/MonthsDropdown/MonthsDropdown.tsx +75 -0
  61. package/src/components/MonthsDropdown/index.ts +1 -0
  62. package/src/components/Navigation/Navigation.test.tsx +129 -0
  63. package/src/components/Navigation/Navigation.tsx +102 -0
  64. package/src/components/Navigation/index.ts +1 -0
  65. package/src/components/Root/Root.test.tsx +123 -0
  66. package/src/components/Root/Root.tsx +58 -0
  67. package/src/components/Root/index.ts +1 -0
  68. package/src/components/Row/Row.test.tsx +69 -0
  69. package/src/components/Row/Row.tsx +51 -0
  70. package/src/components/Row/index.ts +1 -0
  71. package/src/components/Table/Table.test.tsx +42 -0
  72. package/src/components/Table/Table.tsx +60 -0
  73. package/src/components/Table/__snapshots__/Table.test.tsx.snap +1453 -0
  74. package/src/components/Table/index.ts +1 -0
  75. package/src/components/Table/utils/daysToMonthWeeks.ts +47 -0
  76. package/src/components/Table/utils/getMonthWeeks.test.ts +68 -0
  77. package/src/components/Table/utils/getMonthWeeks.ts +55 -0
  78. package/src/components/WeekNumber/WeekNumber.test.tsx +46 -0
  79. package/src/components/WeekNumber/WeekNumber.tsx +58 -0
  80. package/src/components/WeekNumber/__snapshots__/WeekNumber.test.tsx.snap +11 -0
  81. package/src/components/WeekNumber/index.ts +1 -0
  82. package/src/components/YearsDropdown/YearsDropdown.test.tsx +98 -0
  83. package/src/components/YearsDropdown/YearsDropdown.tsx +76 -0
  84. package/src/components/YearsDropdown/index.ts +1 -0
  85. package/src/contexts/DayPicker/DayPickerContext.tsx +156 -0
  86. package/src/contexts/DayPicker/defaultClassNames.ts +58 -0
  87. package/src/contexts/DayPicker/defaultContextValue.ts +37 -0
  88. package/src/contexts/DayPicker/formatters/formatCaption.test.ts +15 -0
  89. package/src/contexts/DayPicker/formatters/formatCaption.ts +12 -0
  90. package/src/contexts/DayPicker/formatters/formatDay.test.ts +7 -0
  91. package/src/contexts/DayPicker/formatters/formatDay.ts +9 -0
  92. package/src/contexts/DayPicker/formatters/formatMonthCaption.test.ts +15 -0
  93. package/src/contexts/DayPicker/formatters/formatMonthCaption.ts +12 -0
  94. package/src/contexts/DayPicker/formatters/formatWeekNumber.test.ts +5 -0
  95. package/src/contexts/DayPicker/formatters/formatWeekNumber.ts +6 -0
  96. package/src/contexts/DayPicker/formatters/formatWeekdayName.test.ts +15 -0
  97. package/src/contexts/DayPicker/formatters/formatWeekdayName.ts +12 -0
  98. package/src/contexts/DayPicker/formatters/formatYearCaption.test.ts +7 -0
  99. package/src/contexts/DayPicker/formatters/formatYearCaption.ts +11 -0
  100. package/src/contexts/DayPicker/formatters/index.ts +6 -0
  101. package/src/contexts/DayPicker/index.ts +2 -0
  102. package/src/contexts/DayPicker/labels/index.ts +7 -0
  103. package/src/contexts/DayPicker/labels/labelDay.test.ts +7 -0
  104. package/src/contexts/DayPicker/labels/labelDay.ts +10 -0
  105. package/src/contexts/DayPicker/labels/labelMonthDropdown.test.ts +5 -0
  106. package/src/contexts/DayPicker/labels/labelMonthDropdown.ts +6 -0
  107. package/src/contexts/DayPicker/labels/labelNext.test.ts +5 -0
  108. package/src/contexts/DayPicker/labels/labelNext.ts +8 -0
  109. package/src/contexts/DayPicker/labels/labelPrevious.test.ts +5 -0
  110. package/src/contexts/DayPicker/labels/labelPrevious.ts +8 -0
  111. package/src/contexts/DayPicker/labels/labelWeekNumber.test.ts +5 -0
  112. package/src/contexts/DayPicker/labels/labelWeekNumber.ts +8 -0
  113. package/src/contexts/DayPicker/labels/labelWeekday.test.ts +15 -0
  114. package/src/contexts/DayPicker/labels/labelWeekday.ts +10 -0
  115. package/src/contexts/DayPicker/labels/labelYearDropdown.test.ts +5 -0
  116. package/src/contexts/DayPicker/labels/labelYearDropdown.ts +6 -0
  117. package/src/contexts/DayPicker/useDayPicker.test.ts +297 -0
  118. package/src/contexts/DayPicker/useDayPicker.ts +17 -0
  119. package/src/contexts/DayPicker/utils/index.ts +1 -0
  120. package/src/contexts/DayPicker/utils/parseFromToProps.test.ts +47 -0
  121. package/src/contexts/DayPicker/utils/parseFromToProps.ts +32 -0
  122. package/src/contexts/Focus/FocusContext.tsx +174 -0
  123. package/src/contexts/Focus/index.ts +2 -0
  124. package/src/contexts/Focus/useFocusContext.test.ts +183 -0
  125. package/src/contexts/Focus/useFocusContext.ts +12 -0
  126. package/src/contexts/Focus/utils/getInitialFocusTarget.test.tsx +12 -0
  127. package/src/contexts/Focus/utils/getInitialFocusTarget.tsx +44 -0
  128. package/src/contexts/Modifiers/ModifiersContext.tsx +44 -0
  129. package/src/contexts/Modifiers/index.ts +2 -0
  130. package/src/contexts/Modifiers/useModifiers.test.ts +46 -0
  131. package/src/contexts/Modifiers/useModifiers.ts +17 -0
  132. package/src/contexts/Modifiers/utils/getActiveModifiers.test.ts +53 -0
  133. package/src/contexts/Modifiers/utils/getActiveModifiers.ts +33 -0
  134. package/src/contexts/Modifiers/utils/getCustomModifiers.test.ts +14 -0
  135. package/src/contexts/Modifiers/utils/getCustomModifiers.ts +14 -0
  136. package/src/contexts/Modifiers/utils/getInternalModifiers.test.ts +146 -0
  137. package/src/contexts/Modifiers/utils/getInternalModifiers.ts +58 -0
  138. package/src/contexts/Modifiers/utils/isDateInRange.test.ts +28 -0
  139. package/src/contexts/Modifiers/utils/isDateInRange.ts +27 -0
  140. package/src/contexts/Modifiers/utils/isMatch.test.ts +92 -0
  141. package/src/contexts/Modifiers/utils/isMatch.ts +76 -0
  142. package/src/contexts/Modifiers/utils/matcherToArray.test.ts +22 -0
  143. package/src/contexts/Modifiers/utils/matcherToArray.ts +14 -0
  144. package/src/contexts/Navigation/NavigationContext.tsx +84 -0
  145. package/src/contexts/Navigation/index.ts +2 -0
  146. package/src/contexts/Navigation/useNavigation.test.ts +126 -0
  147. package/src/contexts/Navigation/useNavigation.ts +12 -0
  148. package/src/contexts/Navigation/useNavigationState.test.ts +36 -0
  149. package/src/contexts/Navigation/useNavigationState.ts +25 -0
  150. package/src/contexts/Navigation/utils/getDisplayMonths.ts +31 -0
  151. package/src/contexts/Navigation/utils/getInitialMonth.test.ts +56 -0
  152. package/src/contexts/Navigation/utils/getInitialMonth.ts +24 -0
  153. package/src/contexts/Navigation/utils/getNextMonth.test.ts +75 -0
  154. package/src/contexts/Navigation/utils/getNextMonth.ts +45 -0
  155. package/src/contexts/Navigation/utils/getPreviousMonth.test.ts +55 -0
  156. package/src/contexts/Navigation/utils/getPreviousMonth.ts +44 -0
  157. package/src/contexts/RootProvider.tsx +37 -0
  158. package/src/contexts/SelectMultiple/SelectMultipleContext.tsx +135 -0
  159. package/src/contexts/SelectMultiple/index.ts +2 -0
  160. package/src/contexts/SelectMultiple/useSelectMultiple.test.ts +191 -0
  161. package/src/contexts/SelectMultiple/useSelectMultiple.ts +17 -0
  162. package/src/contexts/SelectRange/SelectRangeContext.tsx +158 -0
  163. package/src/contexts/SelectRange/index.ts +2 -0
  164. package/src/contexts/SelectRange/useSelectRange.test.ts +282 -0
  165. package/src/contexts/SelectRange/useSelectRange.ts +15 -0
  166. package/src/contexts/SelectRange/utils/addToRange.test.ts +119 -0
  167. package/src/contexts/SelectRange/utils/addToRange.ts +43 -0
  168. package/src/contexts/SelectSingle/SelectSingleContext.tsx +80 -0
  169. package/src/contexts/SelectSingle/index.ts +2 -0
  170. package/src/contexts/SelectSingle/useSelectSingle.test.ts +81 -0
  171. package/src/contexts/SelectSingle/useSelectSingle.ts +17 -0
  172. package/src/hooks/useActiveModifiers/index.ts +1 -0
  173. package/src/hooks/useActiveModifiers/useActiveModifiers.test.tsx +36 -0
  174. package/src/hooks/useActiveModifiers/useActiveModifiers.tsx +18 -0
  175. package/src/hooks/useControlledValue/index.ts +1 -0
  176. package/src/hooks/useControlledValue/useControlledValue.test.ts +68 -0
  177. package/src/hooks/useControlledValue/useControlledValue.ts +24 -0
  178. package/src/hooks/useDayEventHandlers/index.ts +1 -0
  179. package/src/hooks/useDayEventHandlers/useDayEventHandlers.test.tsx +213 -0
  180. package/src/hooks/useDayEventHandlers/useDayEventHandlers.tsx +195 -0
  181. package/src/hooks/useDayRender/index.ts +1 -0
  182. package/src/hooks/useDayRender/useDayRender.test.tsx +304 -0
  183. package/src/hooks/useDayRender/useDayRender.tsx +123 -0
  184. package/src/hooks/useDayRender/utils/getDayClassNames.test.ts +63 -0
  185. package/src/hooks/useDayRender/utils/getDayClassNames.ts +32 -0
  186. package/src/hooks/useDayRender/utils/getDayStyle.ts +19 -0
  187. package/src/hooks/useInput/index.ts +1 -0
  188. package/src/hooks/useInput/useInput.ts +175 -0
  189. package/src/hooks/useInput/utils/isValidDate.tsx +4 -0
  190. package/src/hooks/useSelectedDays/index.ts +1 -0
  191. package/src/hooks/useSelectedDays/useSelectedDays.test.ts +72 -0
  192. package/src/hooks/useSelectedDays/useSelectedDays.ts +32 -0
  193. package/src/index.ts +43 -0
  194. package/src/style.css +311 -0
  195. package/src/style.css.d.ts +38 -0
  196. package/src/types/DayPickerBase.ts +267 -0
  197. package/src/types/DayPickerDefault.ts +15 -0
  198. package/src/types/DayPickerMultiple.ts +26 -0
  199. package/src/types/DayPickerRange.ts +27 -0
  200. package/src/types/DayPickerSingle.ts +24 -0
  201. package/src/types/EventHandlers.ts +87 -0
  202. package/src/types/Formatters.ts +29 -0
  203. package/src/types/Labels.ts +36 -0
  204. package/src/types/Matchers.ts +106 -0
  205. package/src/types/Modifiers.ts +62 -0
  206. package/src/types/Styles.ts +125 -0
  207. package/tsconfig.json +24 -0
package/dist/style.css CHANGED
@@ -55,22 +55,23 @@
55
55
  border: 2px solid transparent;
56
56
  }
57
57
 
58
- .rdp-button[disabled] {
58
+ .rdp-button[aria-disabled='true'] {
59
59
  opacity: 0.25;
60
+ pointer-events: none;
60
61
  }
61
62
 
62
- .rdp-button:not([disabled]) {
63
+ .rdp-button:not([aria-disabled='true']) {
63
64
  cursor: pointer;
64
65
  }
65
66
 
66
- .rdp-button:focus:not([disabled]),
67
- .rdp-button:active:not([disabled]) {
67
+ .rdp-button:focus,
68
+ .rdp-button:active {
68
69
  color: inherit;
69
70
  border: var(--rdp-outline);
70
71
  background-color: var(--rdp-background-color);
71
72
  }
72
73
 
73
- .rdp-button:hover:not([disabled]) {
74
+ .rdp-button:hover:not([aria-disabled='true']) {
74
75
  background-color: var(--rdp-background-color);
75
76
  }
76
77
 
@@ -269,15 +270,15 @@
269
270
  font-weight: bold;
270
271
  }
271
272
 
272
- .rdp-day_selected:not([disabled]),
273
- .rdp-day_selected:focus:not([disabled]),
274
- .rdp-day_selected:active:not([disabled]),
275
- .rdp-day_selected:hover:not([disabled]) {
273
+ .rdp-day_selected:not([aria-disabled='true']),
274
+ .rdp-day_selected:focus:not([aria-disabled='true']),
275
+ .rdp-day_selected:active:not([aria-disabled='true']),
276
+ .rdp-day_selected:hover:not([aria-disabled='true']) {
276
277
  color: white;
277
278
  background-color: var(--rdp-accent-color);
278
279
  }
279
280
 
280
- .rdp-day_selected:focus:not([disabled]) {
281
+ .rdp-day_selected:focus:not([aria-disabled='true']) {
281
282
  border: var(--rdp-outline-selected);
282
283
  }
283
284
 
@@ -55,22 +55,23 @@
55
55
  border: 2px solid transparent;
56
56
  }
57
57
 
58
- .button[disabled] {
58
+ .button[aria-disabled='true'] {
59
59
  opacity: 0.25;
60
+ pointer-events: none;
60
61
  }
61
62
 
62
- .button:not([disabled]) {
63
+ .button:not([aria-disabled='true']) {
63
64
  cursor: pointer;
64
65
  }
65
66
 
66
- .button:focus:not([disabled]),
67
- .button:active:not([disabled]) {
67
+ .button:focus,
68
+ .button:active {
68
69
  color: inherit;
69
70
  border: var(--rdp-outline);
70
71
  background-color: var(--rdp-background-color);
71
72
  }
72
73
 
73
- .button:hover:not([disabled]) {
74
+ .button:hover:not([aria-disabled='true']) {
74
75
  background-color: var(--rdp-background-color);
75
76
  }
76
77
 
@@ -269,15 +270,15 @@
269
270
  font-weight: bold;
270
271
  }
271
272
 
272
- .day_selected:not([disabled]),
273
- .day_selected:focus:not([disabled]),
274
- .day_selected:active:not([disabled]),
275
- .day_selected:hover:not([disabled]) {
273
+ .day_selected:not([aria-disabled='true']),
274
+ .day_selected:focus:not([aria-disabled='true']),
275
+ .day_selected:active:not([aria-disabled='true']),
276
+ .day_selected:hover:not([aria-disabled='true']) {
276
277
  color: white;
277
278
  background-color: var(--rdp-accent-color);
278
279
  }
279
280
 
280
- .day_selected:focus:not([disabled]) {
281
+ .day_selected:focus:not([aria-disabled='true']) {
281
282
  border: var(--rdp-outline-selected);
282
283
  }
283
284
 
@@ -84,10 +84,16 @@ export declare type StyledElement<T = string | React.CSSProperties> = {
84
84
  /** The day when today. */
85
85
  readonly day_today: T;
86
86
  };
87
+ /** These elements must not be in the `styles` or `classNames` records as they are styled via the `modifiersStyles` or `modifiersClassNames` pop */
88
+ export declare type InternalModifiersElement = 'day_outside' | 'day_selected' | 'day_disabled' | 'day_hidden' | 'day_range_start' | 'day_range_end' | 'day_range_middle' | 'day_today';
87
89
  /** The class names of each element. */
88
90
  export declare type ClassNames = Partial<StyledElement<string>>;
89
- /** The inline-styles of each element. */
90
- export declare type Styles = Partial<StyledElement<React.CSSProperties>>;
91
+ /**
92
+ * The inline-styles of each styled element, to use with the `styles` prop. Day
93
+ * modifiers, such as `today` or `hidden`, should be styled using the
94
+ * `modifiersStyles` prop.
95
+ */
96
+ export declare type Styles = Partial<Omit<StyledElement<React.CSSProperties>, InternalModifiersElement>>;
91
97
  /** Props of a component that can be styled via classNames or inline-styles. */
92
98
  export declare type StyledComponent = {
93
99
  className?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-day-picker",
3
- "version": "8.0.3",
3
+ "version": "8.0.6",
4
4
  "description": "Customizable Date Picker for React",
5
5
  "author": "Giampaolo Bellavite <io@gpbl.dev>",
6
6
  "homepage": "http://react-day-picker.js.org",
@@ -28,31 +28,33 @@
28
28
  "typecheck-watch": "tsc --project ./tsconfig.json --noEmit --skipLibCheck --watch"
29
29
  },
30
30
  "files": [
31
- "dist"
31
+ "dist",
32
+ "src",
33
+ "tsconfig.json"
32
34
  ],
33
35
  "dependencies": {
34
- "@reach/auto-id": "^0.16.0"
36
+ "@reach/auto-id": "0.16.0"
35
37
  },
36
38
  "devDependencies": {
37
39
  "@rollup/plugin-alias": "^3.1.9",
38
- "@rollup/plugin-commonjs": "^21.0.3",
40
+ "@rollup/plugin-commonjs": "^21.1.0",
39
41
  "@rollup/plugin-typescript": "^8.3.1",
40
- "@testing-library/jest-dom": "^5.16.3",
42
+ "@testing-library/jest-dom": "^5.16.4",
41
43
  "@testing-library/react": "^12.1.4",
42
44
  "@testing-library/react-hooks": "^7.0.2",
43
45
  "@testing-library/user-event": "^13.5.0",
44
46
  "@types/jest": "^27.4.1",
45
47
  "@types/node": "^17.0.23",
46
- "@types/react": "^17.0.43",
47
- "@typescript-eslint/eslint-plugin": "^5.17.0",
48
- "@typescript-eslint/parser": "^5.17.0",
48
+ "@types/react": "^17.0.44",
49
+ "@typescript-eslint/eslint-plugin": "^5.18.0",
50
+ "@typescript-eslint/parser": "^5.18.0",
49
51
  "date-fns": "^2.28.0",
50
- "eslint": "^8.12.0",
52
+ "eslint": "^8.13.0",
51
53
  "eslint-config-prettier": "^8.5.0",
52
54
  "eslint-config-rdp": "workspace:^",
53
- "eslint-import-resolver-typescript": "^2.7.0",
54
- "eslint-plugin-import": "^2.25.4",
55
- "eslint-plugin-jest": "^26.1.3",
55
+ "eslint-import-resolver-typescript": "^2.7.1",
56
+ "eslint-plugin-import": "^2.26.0",
57
+ "eslint-plugin-jest": "^26.1.4",
56
58
  "eslint-plugin-prettier": "^4.0.0",
57
59
  "eslint-plugin-react-hooks": "^4.4.0",
58
60
  "jest": "^27.5.1",
@@ -69,7 +71,7 @@
69
71
  "timekeeper": "^2.2.0",
70
72
  "ts-jest": "^27.1.4",
71
73
  "ts-node": "^10.7.0",
72
- "tsc-alias": "^1.6.5",
74
+ "tsc-alias": "^1.6.6",
73
75
  "tslib": "^2.3.1",
74
76
  "typed-css-modules": "^0.7.0",
75
77
  "typescript": "~4.5.5"
@@ -0,0 +1,113 @@
1
+ import React from 'react';
2
+
3
+ import { DaySelectionMode } from 'types/DayPickerBase';
4
+ import { DayPickerDefaultProps } from 'types/DayPickerDefault';
5
+ import { DayPickerMultipleProps } from 'types/DayPickerMultiple';
6
+ import { DayPickerRangeProps } from 'types/DayPickerRange';
7
+ import { DayPickerSingleProps } from 'types/DayPickerSingle';
8
+
9
+ import { Root } from './components/Root';
10
+ import { RootProvider } from './contexts/RootProvider';
11
+
12
+ /**
13
+ * DayPicker render a date picker component to let users pick dates from a
14
+ * calendar. See http://react-day-picker.js.org for updated documentation and
15
+ * examples.
16
+ *
17
+ * ### Customization
18
+ *
19
+ * DayPicker offers different customization props. For example,
20
+ *
21
+ * - show multiple months using `numberOfMonths`
22
+ * - display a dropdown to navigate the months via `captionLayout`
23
+ * - display the week numbers with `showWeekNumbers`
24
+ * - disable or hide days with `disabled` or `hidden`
25
+ *
26
+ * ### Controlling the months
27
+ *
28
+ * Change the initially displayed month using the `defaultMonth` prop. The
29
+ * displayed months are controlled by DayPicker and stored in its internal
30
+ * state. To control the months yourself, use `month` instead of `defaultMonth`
31
+ * and use the `onMonthChange` event to set it.
32
+ *
33
+ * To limit the months the user can navigate to, use
34
+ * `fromDate`/`fromMonth`/`fromYear` or `toDate`/`toMonth`/`toYear`.
35
+ *
36
+ * ### Selection modes
37
+ *
38
+ * DayPicker supports different selection mode that can be toggled using the
39
+ * `mode` prop:
40
+ *
41
+ * - `mode="single"`: only one day can be selected. Use `required` to make the
42
+ * selection required. Use the `onSelect` event handler to get the selected
43
+ * days.
44
+ * - `mode="multiple"`: users can select one or more days. Limit the amount of
45
+ * days that can be selected with the `min` or the `max` props.
46
+ * - `mode="range"`: users can select a range of days. Limit the amount of days
47
+ * in the range with the `min` or the `max` props.
48
+ * - `mode="default"` (default): the built-in selections are disabled. Implement
49
+ * your own selection mode with `onDayClick`.
50
+ *
51
+ * The selection modes should cover the most common use cases. In case you
52
+ * need a more refined way of selecting days, use `mode="default"`. Use the
53
+ * `selected` props and add the day event handlers to add/remove days from the
54
+ * selection.
55
+ *
56
+ * ### Modifiers
57
+ *
58
+ * A _modifier_ represents different styles or states for the days displayed in
59
+ * the calendar (like "selected" or "disabled"). Define custom modifiers using
60
+ * the `modifiers` prop.
61
+ *
62
+ * ### Formatters and custom component
63
+ *
64
+ * You can customize how the content is displayed in the date picker by using
65
+ * either the formatters or replacing the internal components.
66
+ *
67
+ * For the most common cases you want to use the `formatters` prop to change how
68
+ * the content is formatted in the calendar. Use the `components` prop to
69
+ * replace the internal components, like the navigation icons.
70
+ *
71
+ * ### Styling
72
+ *
73
+ * DayPicker comes with a default, basic style in `react-day-picker/style` – use
74
+ * it as template for your own style.
75
+ *
76
+ * If you are using CSS modules, pass the imported styles object the
77
+ * `classNames` props.
78
+ *
79
+ * You can also style the elements via inline-styles using the `styles` prop.
80
+ *
81
+ * ### Form fields
82
+ *
83
+ * If you need to bind the date picker to a form field, you can use the
84
+ * `useInput` hooks for a basic behavior. See the `useInput` source as an
85
+ * example to bind the date picker with form fields.
86
+ *
87
+ * ### Localization
88
+ *
89
+ * To localize DayPicker, import the locale from `date-fns` package and use the
90
+ * `locale` prop.
91
+ *
92
+ * For example, to use Spanish locale:
93
+ *
94
+ * ```
95
+ * import es from 'date-fns/locale/es';
96
+ * <DayPicker locale={es} />
97
+ * ```
98
+ */
99
+
100
+ export type DayPickerProps = { mode?: DaySelectionMode } & (
101
+ | DayPickerDefaultProps
102
+ | DayPickerSingleProps
103
+ | DayPickerMultipleProps
104
+ | DayPickerRangeProps
105
+ );
106
+
107
+ export function DayPicker(props: DayPickerProps): JSX.Element {
108
+ return (
109
+ <RootProvider {...props}>
110
+ <Root />
111
+ </RootProvider>
112
+ );
113
+ }
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+
3
+ import { screen } from '@testing-library/react';
4
+
5
+ import { customRender } from 'test/render';
6
+
7
+ import { Button } from './Button';
8
+
9
+ let button: HTMLButtonElement;
10
+
11
+ describe('when rendered without props', () => {
12
+ beforeEach(() => {
13
+ customRender(<Button className="foo" style={{ color: 'blue' }} />);
14
+ button = screen.getByRole('button');
15
+ });
16
+ test('should render a button with type "button"', () => {
17
+ expect(button).toHaveAttribute('type', 'button');
18
+ });
19
+ test('should render a button with the button class name', () => {
20
+ expect(button).toHaveClass('rdp-button');
21
+ });
22
+ test('should render a button with the reset class name', () => {
23
+ expect(button).toHaveClass('rdp-button_reset');
24
+ });
25
+ test('should add the class name', () => {
26
+ expect(button).toHaveClass('foo');
27
+ });
28
+ test('should apply the style', () => {
29
+ expect(button).toHaveStyle({ color: 'blue' });
30
+ });
31
+ });
32
+
33
+ describe('when using class names and styles from context', () => {
34
+ beforeEach(() => {
35
+ customRender(<Button />, {
36
+ classNames: { button: 'foo' },
37
+ styles: { button: { color: 'red' } }
38
+ });
39
+ button = screen.getByRole('button');
40
+ });
41
+ test('should apply the style', () => {
42
+ expect(button).toHaveStyle({ color: 'red' });
43
+ });
44
+ test('should apply the class name', () => {
45
+ expect(button).toHaveClass('foo');
46
+ });
47
+ });
@@ -0,0 +1,36 @@
1
+ import React, { forwardRef } from 'react';
2
+
3
+ import { useDayPicker } from 'contexts/DayPicker';
4
+
5
+ /** The props for the [[Button]] component. */
6
+ export type ButtonProps = React.HTMLProps<HTMLButtonElement>;
7
+
8
+ /**
9
+ * Render a button HTML element applying the reset class name.
10
+ */
11
+ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
12
+ (props, ref) => {
13
+ const { classNames, styles } = useDayPicker();
14
+
15
+ const classNamesArr = [classNames.button_reset, classNames.button];
16
+ if (props.className) {
17
+ classNamesArr.push(props.className);
18
+ }
19
+ const className = classNamesArr.join(' ');
20
+
21
+ const style = { ...styles.button_reset, ...styles.button };
22
+ if (props.style) {
23
+ Object.assign(style, props.style);
24
+ }
25
+
26
+ return (
27
+ <button
28
+ {...props}
29
+ ref={ref}
30
+ type="button"
31
+ className={className}
32
+ style={style}
33
+ />
34
+ );
35
+ }
36
+ );
@@ -0,0 +1 @@
1
+ export * from './Button';
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+
3
+ import { screen } from '@testing-library/react';
4
+ import { DayPickerProps } from 'DayPicker';
5
+
6
+ import {
7
+ getMonthCaption,
8
+ getMonthDropdown,
9
+ getNextButton,
10
+ getPrevButton,
11
+ getYearDropdown,
12
+ queryNextButton,
13
+ queryPrevButton
14
+ } from 'test/po';
15
+ import { customRender } from 'test/render';
16
+ import { freezeBeforeAll } from 'test/utils';
17
+
18
+ import { CustomComponents } from 'types/DayPickerBase';
19
+
20
+ import { Caption, CaptionProps } from './Caption';
21
+
22
+ const today = new Date(2021, 8);
23
+
24
+ freezeBeforeAll(today);
25
+
26
+ function setup(props: CaptionProps, dayPickerProps?: DayPickerProps) {
27
+ customRender(<Caption {...props} />, dayPickerProps);
28
+ }
29
+
30
+ describe('when navigation is disabled', () => {
31
+ const props = { displayMonth: today };
32
+ const dayPickerProps = { disableNavigation: true };
33
+ beforeEach(() => setup(props, dayPickerProps));
34
+ test('should display the caption label', () => {
35
+ expect(getMonthCaption()).toHaveTextContent('September 2021');
36
+ });
37
+ test('should not render the navigation', () => {
38
+ expect(queryPrevButton()).toBeNull();
39
+ expect(queryNextButton()).toBeNull();
40
+ });
41
+ });
42
+
43
+ describe('when using a custom CaptionLabel component', () => {
44
+ const components: CustomComponents = {
45
+ CaptionLabel: () => <>custom label foo</>
46
+ };
47
+ const props = { displayMonth: today };
48
+ beforeEach(() => {
49
+ setup(props, { components });
50
+ });
51
+ test('it should render the custom component instead', () => {
52
+ expect(screen.getByText('custom label foo')).toBeInTheDocument();
53
+ });
54
+ });
55
+
56
+ describe('when the caption layout is "dropdown"', () => {
57
+ const dayPickerProps: DayPickerProps = {
58
+ captionLayout: 'dropdown',
59
+ fromYear: 2020,
60
+ toYear: 2025
61
+ };
62
+ const props = { displayMonth: today };
63
+ beforeEach(() => {
64
+ setup(props, dayPickerProps);
65
+ });
66
+ test('should render the month drop-down', () => {
67
+ expect(getMonthDropdown()).toBeInTheDocument();
68
+ });
69
+ test('should render the year drop-down', () => {
70
+ expect(getYearDropdown()).toBeInTheDocument();
71
+ });
72
+ });
73
+
74
+ describe('when the caption layout is "buttons"', () => {
75
+ const dayPickerProps: DayPickerProps = {
76
+ captionLayout: 'buttons'
77
+ };
78
+ test('should render the next month button', () => {
79
+ customRender(<Caption displayMonth={today} />, dayPickerProps);
80
+ expect(getNextButton()).toBeInTheDocument();
81
+ });
82
+ test('should render the previous month button', () => {
83
+ customRender(<Caption displayMonth={today} />, dayPickerProps);
84
+ expect(getPrevButton()).toBeInTheDocument();
85
+ });
86
+ });
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+
3
+ import { CaptionDropdowns } from 'components/CaptionDropdowns';
4
+ import { CaptionLabel } from 'components/CaptionLabel';
5
+ import { CaptionNavigation } from 'components/CaptionNavigation';
6
+ import { useDayPicker } from 'contexts/DayPicker';
7
+
8
+ /** Represent the props of the [[Caption]] component. */
9
+ export interface CaptionProps {
10
+ /** The ID for the heading element. Must be the same as the labelled-by in Table. */
11
+ id?: string;
12
+ /** The month where the caption is displayed. */
13
+ displayMonth: Date;
14
+ }
15
+
16
+ /**
17
+ * The layout of the caption:
18
+ *
19
+ * - `dropdown`: display dropdowns for choosing the month and the year.
20
+ * - `buttons`: display previous month / next month buttons.
21
+ */
22
+ export type CaptionLayout = 'dropdown' | 'buttons';
23
+
24
+ /**
25
+ * Render the caption of a month. The caption has a different layout when
26
+ * setting the [[DayPickerProps.captionLayout]] prop.
27
+ */
28
+ export function Caption(props: CaptionProps): JSX.Element {
29
+ const { classNames, disableNavigation, styles, captionLayout, components } =
30
+ useDayPicker();
31
+
32
+ const CaptionLabelComponent = components?.CaptionLabel ?? CaptionLabel;
33
+
34
+ let caption: JSX.Element;
35
+ if (disableNavigation) {
36
+ caption = (
37
+ <CaptionLabelComponent id={props.id} displayMonth={props.displayMonth} />
38
+ );
39
+ } else if (captionLayout === 'dropdown') {
40
+ caption = (
41
+ <CaptionDropdowns displayMonth={props.displayMonth} id={props.id} />
42
+ );
43
+ } else {
44
+ caption = (
45
+ <CaptionNavigation displayMonth={props.displayMonth} id={props.id} />
46
+ );
47
+ }
48
+
49
+ return (
50
+ <div className={classNames.caption} style={styles.caption}>
51
+ {caption}
52
+ </div>
53
+ );
54
+ }
@@ -0,0 +1 @@
1
+ export * from './Caption';
@@ -0,0 +1,123 @@
1
+ import React from 'react';
2
+
3
+ import { screen } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+ import { setMonth, setYear } from 'date-fns';
6
+ import { DayPickerProps } from 'DayPicker';
7
+
8
+ import {
9
+ getMonthDropdown,
10
+ getYearDropdown,
11
+ queryMonthDropdown,
12
+ queryYearDropdown
13
+ } from 'test/po';
14
+ import { customRender } from 'test/render';
15
+ import { freezeBeforeAll } from 'test/utils';
16
+
17
+ import { CaptionProps } from 'components/Caption';
18
+ import { CustomComponents } from 'types/DayPickerBase';
19
+
20
+ import { CaptionDropdowns } from './CaptionDropdowns';
21
+
22
+ const today = new Date(2021, 8);
23
+ const fromYear = 2020;
24
+ const toYear = 2025;
25
+
26
+ freezeBeforeAll(today);
27
+
28
+ function setup(props: CaptionProps, dayPickerProps?: DayPickerProps) {
29
+ customRender(<CaptionDropdowns {...props} />, dayPickerProps);
30
+ }
31
+
32
+ describe('when using a custom CaptionLabel component', () => {
33
+ const components: CustomComponents = {
34
+ CaptionLabel: () => <>custom label foo</>
35
+ };
36
+ const props = { displayMonth: today };
37
+ beforeEach(() => {
38
+ setup(props, { components });
39
+ });
40
+ test('it should render the custom component instead', () => {
41
+ expect(screen.getByText('custom label foo')).toBeInTheDocument();
42
+ });
43
+ });
44
+
45
+ describe('when rendered with custom styles or classnames', () => {
46
+ let container: HTMLElement;
47
+
48
+ beforeEach(() => {
49
+ const dayPickerProps: DayPickerProps = {
50
+ captionLayout: 'dropdown',
51
+ fromYear,
52
+ toYear,
53
+ classNames: { caption_dropdowns: 'foo_dropdowns' },
54
+ styles: { caption_dropdowns: { color: 'red' } }
55
+ };
56
+ const view = customRender(
57
+ <CaptionDropdowns displayMonth={today} />,
58
+ dayPickerProps
59
+ );
60
+ container = view.container;
61
+ });
62
+ test('should use the `caption_dropdowns` class name', () => {
63
+ expect(container.firstChild).toHaveClass('foo_dropdowns');
64
+ });
65
+ test('should use the `caption_dropdowns` style', () => {
66
+ expect(container.firstChild).toHaveStyle({ color: 'red' });
67
+ });
68
+ test('should render the month drop-down', () => {
69
+ expect(getMonthDropdown()).toBeInTheDocument();
70
+ });
71
+ test('should render the year drop-down', () => {
72
+ expect(getYearDropdown()).toBeInTheDocument();
73
+ });
74
+ });
75
+
76
+ describe('when a month is selected', () => {
77
+ const dayPickerProps: DayPickerProps = {
78
+ captionLayout: 'dropdown',
79
+ fromYear,
80
+ toYear,
81
+ onMonthChange: jest.fn()
82
+ };
83
+ beforeEach(() => {
84
+ customRender(<CaptionDropdowns displayMonth={today} />, dayPickerProps);
85
+ });
86
+ describe('from the months drop-down', () => {
87
+ const newMonth = setMonth(today, 0);
88
+ beforeEach(() => {
89
+ userEvent.selectOptions(
90
+ getMonthDropdown(),
91
+ newMonth.getMonth().toString()
92
+ );
93
+ });
94
+ test('should call the `onMonthChange` callback', () => {
95
+ expect(dayPickerProps.onMonthChange).toHaveBeenCalledWith(newMonth);
96
+ });
97
+ });
98
+ describe('from the years drop-down', () => {
99
+ const newYear = setYear(today, 2022);
100
+ beforeEach(() => {
101
+ userEvent.selectOptions(
102
+ getYearDropdown(),
103
+ newYear.getFullYear().toString()
104
+ );
105
+ });
106
+ test('should call the `onMonthChange` callback', () => {
107
+ expect(dayPickerProps.onMonthChange).toHaveBeenCalledWith(newYear);
108
+ });
109
+ });
110
+ });
111
+
112
+ describe('when no date limits are set', () => {
113
+ const dayPickerProps: DayPickerProps = {
114
+ captionLayout: 'dropdown'
115
+ };
116
+ beforeEach(() => {
117
+ customRender(<CaptionDropdowns displayMonth={today} />, dayPickerProps);
118
+ });
119
+ test('should not render the drop-downs', () => {
120
+ expect(queryMonthDropdown()).toBeNull();
121
+ expect(queryYearDropdown()).toBeNull();
122
+ });
123
+ });