react-day-picker 8.0.3 → 8.0.4
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.
- package/package.json +13 -11
- package/src/DayPicker.tsx +113 -0
- package/src/components/Button/Button.test.tsx +47 -0
- package/src/components/Button/Button.tsx +36 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Caption/Caption.test.tsx +86 -0
- package/src/components/Caption/Caption.tsx +54 -0
- package/src/components/Caption/index.ts +1 -0
- package/src/components/CaptionDropdowns/CaptionDropdowns.test.tsx +123 -0
- package/src/components/CaptionDropdowns/CaptionDropdowns.tsx +43 -0
- package/src/components/CaptionDropdowns/index.ts +1 -0
- package/src/components/CaptionLabel/CaptionLabel.test.tsx +29 -0
- package/src/components/CaptionLabel/CaptionLabel.tsx +32 -0
- package/src/components/CaptionLabel/index.ts +1 -0
- package/src/components/CaptionNavigation/CaptionNavigation.test.tsx +172 -0
- package/src/components/CaptionNavigation/CaptionNavigation.tsx +63 -0
- package/src/components/CaptionNavigation/index.ts +1 -0
- package/src/components/Day/Day.test.tsx +84 -0
- package/src/components/Day/Day.tsx +30 -0
- package/src/components/Day/index.ts +1 -0
- package/src/components/DayContent/DayContent.test.tsx +51 -0
- package/src/components/DayContent/DayContent.tsx +36 -0
- package/src/components/DayContent/index.ts +1 -0
- package/src/components/Dropdown/Dropdown.test.tsx +73 -0
- package/src/components/Dropdown/Dropdown.tsx +56 -0
- package/src/components/Dropdown/index.ts +1 -0
- package/src/components/Footer/Footer.test.tsx +29 -0
- package/src/components/Footer/Footer.tsx +20 -0
- package/src/components/Footer/index.ts +1 -0
- package/src/components/Head/Head.test.tsx +117 -0
- package/src/components/Head/Head.tsx +51 -0
- package/src/components/Head/index.ts +1 -0
- package/src/components/Head/utils/getWeekdays.test.ts +36 -0
- package/src/components/Head/utils/getWeekdays.ts +22 -0
- package/src/components/Head/utils/index.ts +1 -0
- package/src/components/IconDropdown/IconDropdown.test.tsx +20 -0
- package/src/components/IconDropdown/IconDropdown.tsx +24 -0
- package/src/components/IconDropdown/index.ts +1 -0
- package/src/components/IconLeft/IconLeft.test.tsx +20 -0
- package/src/components/IconLeft/IconLeft.tsx +18 -0
- package/src/components/IconLeft/index.ts +1 -0
- package/src/components/IconRight/IconRight.test.tsx +20 -0
- package/src/components/IconRight/IconRight.tsx +17 -0
- package/src/components/IconRight/index.ts +1 -0
- package/src/components/Month/Month.test.tsx +216 -0
- package/src/components/Month/Month.tsx +53 -0
- package/src/components/Month/index.ts +1 -0
- package/src/components/MonthsDropdown/MonthsDropdown.test.tsx +99 -0
- package/src/components/MonthsDropdown/MonthsDropdown.tsx +75 -0
- package/src/components/MonthsDropdown/index.ts +1 -0
- package/src/components/Navigation/Navigation.test.tsx +129 -0
- package/src/components/Navigation/Navigation.tsx +102 -0
- package/src/components/Navigation/index.ts +1 -0
- package/src/components/Root/Root.test.tsx +123 -0
- package/src/components/Root/Root.tsx +58 -0
- package/src/components/Root/index.ts +1 -0
- package/src/components/Row/Row.test.tsx +69 -0
- package/src/components/Row/Row.tsx +51 -0
- package/src/components/Row/index.ts +1 -0
- package/src/components/Table/Table.test.tsx +42 -0
- package/src/components/Table/Table.tsx +60 -0
- package/src/components/Table/__snapshots__/Table.test.tsx.snap +1453 -0
- package/src/components/Table/index.ts +1 -0
- package/src/components/Table/utils/daysToMonthWeeks.ts +47 -0
- package/src/components/Table/utils/getMonthWeeks.test.ts +68 -0
- package/src/components/Table/utils/getMonthWeeks.ts +55 -0
- package/src/components/WeekNumber/WeekNumber.test.tsx +46 -0
- package/src/components/WeekNumber/WeekNumber.tsx +58 -0
- package/src/components/WeekNumber/__snapshots__/WeekNumber.test.tsx.snap +11 -0
- package/src/components/WeekNumber/index.ts +1 -0
- package/src/components/YearsDropdown/YearsDropdown.test.tsx +98 -0
- package/src/components/YearsDropdown/YearsDropdown.tsx +76 -0
- package/src/components/YearsDropdown/index.ts +1 -0
- package/src/contexts/DayPicker/DayPickerContext.tsx +156 -0
- package/src/contexts/DayPicker/defaultClassNames.ts +58 -0
- package/src/contexts/DayPicker/defaultContextValue.ts +37 -0
- package/src/contexts/DayPicker/formatters/formatCaption.test.ts +15 -0
- package/src/contexts/DayPicker/formatters/formatCaption.ts +12 -0
- package/src/contexts/DayPicker/formatters/formatDay.test.ts +7 -0
- package/src/contexts/DayPicker/formatters/formatDay.ts +9 -0
- package/src/contexts/DayPicker/formatters/formatMonthCaption.test.ts +15 -0
- package/src/contexts/DayPicker/formatters/formatMonthCaption.ts +12 -0
- package/src/contexts/DayPicker/formatters/formatWeekNumber.test.ts +5 -0
- package/src/contexts/DayPicker/formatters/formatWeekNumber.ts +6 -0
- package/src/contexts/DayPicker/formatters/formatWeekdayName.test.ts +15 -0
- package/src/contexts/DayPicker/formatters/formatWeekdayName.ts +12 -0
- package/src/contexts/DayPicker/formatters/formatYearCaption.test.ts +7 -0
- package/src/contexts/DayPicker/formatters/formatYearCaption.ts +11 -0
- package/src/contexts/DayPicker/formatters/index.ts +6 -0
- package/src/contexts/DayPicker/index.ts +2 -0
- package/src/contexts/DayPicker/labels/index.ts +7 -0
- package/src/contexts/DayPicker/labels/labelDay.test.ts +7 -0
- package/src/contexts/DayPicker/labels/labelDay.ts +10 -0
- package/src/contexts/DayPicker/labels/labelMonthDropdown.test.ts +5 -0
- package/src/contexts/DayPicker/labels/labelMonthDropdown.ts +6 -0
- package/src/contexts/DayPicker/labels/labelNext.test.ts +5 -0
- package/src/contexts/DayPicker/labels/labelNext.ts +8 -0
- package/src/contexts/DayPicker/labels/labelPrevious.test.ts +5 -0
- package/src/contexts/DayPicker/labels/labelPrevious.ts +8 -0
- package/src/contexts/DayPicker/labels/labelWeekNumber.test.ts +5 -0
- package/src/contexts/DayPicker/labels/labelWeekNumber.ts +8 -0
- package/src/contexts/DayPicker/labels/labelWeekday.test.ts +15 -0
- package/src/contexts/DayPicker/labels/labelWeekday.ts +10 -0
- package/src/contexts/DayPicker/labels/labelYearDropdown.test.ts +5 -0
- package/src/contexts/DayPicker/labels/labelYearDropdown.ts +6 -0
- package/src/contexts/DayPicker/useDayPicker.test.ts +297 -0
- package/src/contexts/DayPicker/useDayPicker.ts +17 -0
- package/src/contexts/DayPicker/utils/index.ts +1 -0
- package/src/contexts/DayPicker/utils/parseFromToProps.test.ts +47 -0
- package/src/contexts/DayPicker/utils/parseFromToProps.ts +32 -0
- package/src/contexts/Focus/FocusContext.tsx +174 -0
- package/src/contexts/Focus/index.ts +2 -0
- package/src/contexts/Focus/useFocusContext.test.ts +183 -0
- package/src/contexts/Focus/useFocusContext.ts +12 -0
- package/src/contexts/Focus/utils/getInitialFocusTarget.test.tsx +12 -0
- package/src/contexts/Focus/utils/getInitialFocusTarget.tsx +44 -0
- package/src/contexts/Modifiers/ModifiersContext.tsx +44 -0
- package/src/contexts/Modifiers/index.ts +2 -0
- package/src/contexts/Modifiers/useModifiers.test.ts +46 -0
- package/src/contexts/Modifiers/useModifiers.ts +17 -0
- package/src/contexts/Modifiers/utils/getActiveModifiers.test.ts +53 -0
- package/src/contexts/Modifiers/utils/getActiveModifiers.ts +33 -0
- package/src/contexts/Modifiers/utils/getCustomModifiers.test.ts +14 -0
- package/src/contexts/Modifiers/utils/getCustomModifiers.ts +14 -0
- package/src/contexts/Modifiers/utils/getInternalModifiers.test.ts +146 -0
- package/src/contexts/Modifiers/utils/getInternalModifiers.ts +58 -0
- package/src/contexts/Modifiers/utils/isDateInRange.test.ts +28 -0
- package/src/contexts/Modifiers/utils/isDateInRange.ts +27 -0
- package/src/contexts/Modifiers/utils/isMatch.test.ts +92 -0
- package/src/contexts/Modifiers/utils/isMatch.ts +76 -0
- package/src/contexts/Modifiers/utils/matcherToArray.test.ts +22 -0
- package/src/contexts/Modifiers/utils/matcherToArray.ts +14 -0
- package/src/contexts/Navigation/NavigationContext.tsx +84 -0
- package/src/contexts/Navigation/index.ts +2 -0
- package/src/contexts/Navigation/useNavigation.test.ts +126 -0
- package/src/contexts/Navigation/useNavigation.ts +12 -0
- package/src/contexts/Navigation/useNavigationState.test.ts +36 -0
- package/src/contexts/Navigation/useNavigationState.ts +25 -0
- package/src/contexts/Navigation/utils/getDisplayMonths.ts +31 -0
- package/src/contexts/Navigation/utils/getInitialMonth.test.ts +56 -0
- package/src/contexts/Navigation/utils/getInitialMonth.ts +24 -0
- package/src/contexts/Navigation/utils/getNextMonth.test.ts +75 -0
- package/src/contexts/Navigation/utils/getNextMonth.ts +45 -0
- package/src/contexts/Navigation/utils/getPreviousMonth.test.ts +55 -0
- package/src/contexts/Navigation/utils/getPreviousMonth.ts +44 -0
- package/src/contexts/RootProvider.tsx +37 -0
- package/src/contexts/SelectMultiple/SelectMultipleContext.tsx +135 -0
- package/src/contexts/SelectMultiple/index.ts +2 -0
- package/src/contexts/SelectMultiple/useSelectMultiple.test.ts +191 -0
- package/src/contexts/SelectMultiple/useSelectMultiple.ts +17 -0
- package/src/contexts/SelectRange/SelectRangeContext.tsx +158 -0
- package/src/contexts/SelectRange/index.ts +2 -0
- package/src/contexts/SelectRange/useSelectRange.test.ts +282 -0
- package/src/contexts/SelectRange/useSelectRange.ts +15 -0
- package/src/contexts/SelectRange/utils/addToRange.test.ts +119 -0
- package/src/contexts/SelectRange/utils/addToRange.ts +43 -0
- package/src/contexts/SelectSingle/SelectSingleContext.tsx +80 -0
- package/src/contexts/SelectSingle/index.ts +2 -0
- package/src/contexts/SelectSingle/useSelectSingle.test.ts +81 -0
- package/src/contexts/SelectSingle/useSelectSingle.ts +17 -0
- package/src/hooks/useActiveModifiers/index.ts +1 -0
- package/src/hooks/useActiveModifiers/useActiveModifiers.test.tsx +36 -0
- package/src/hooks/useActiveModifiers/useActiveModifiers.tsx +18 -0
- package/src/hooks/useControlledValue/index.ts +1 -0
- package/src/hooks/useControlledValue/useControlledValue.test.ts +68 -0
- package/src/hooks/useControlledValue/useControlledValue.ts +24 -0
- package/src/hooks/useDayEventHandlers/index.ts +1 -0
- package/src/hooks/useDayEventHandlers/useDayEventHandlers.test.tsx +213 -0
- package/src/hooks/useDayEventHandlers/useDayEventHandlers.tsx +195 -0
- package/src/hooks/useDayRender/index.ts +1 -0
- package/src/hooks/useDayRender/useDayRender.test.tsx +304 -0
- package/src/hooks/useDayRender/useDayRender.tsx +123 -0
- package/src/hooks/useDayRender/utils/getDayClassNames.test.ts +63 -0
- package/src/hooks/useDayRender/utils/getDayClassNames.ts +32 -0
- package/src/hooks/useDayRender/utils/getDayStyle.ts +19 -0
- package/src/hooks/useInput/index.ts +1 -0
- package/src/hooks/useInput/useInput.ts +175 -0
- package/src/hooks/useInput/utils/isValidDate.tsx +4 -0
- package/src/hooks/useSelectedDays/index.ts +1 -0
- package/src/hooks/useSelectedDays/useSelectedDays.test.ts +72 -0
- package/src/hooks/useSelectedDays/useSelectedDays.ts +32 -0
- package/src/index.ts +43 -0
- package/src/style.css +310 -0
- package/src/style.css.d.ts +38 -0
- package/src/types/DayPickerBase.ts +267 -0
- package/src/types/DayPickerDefault.ts +15 -0
- package/src/types/DayPickerMultiple.ts +26 -0
- package/src/types/DayPickerRange.ts +27 -0
- package/src/types/DayPickerSingle.ts +24 -0
- package/src/types/EventHandlers.ts +87 -0
- package/src/types/Formatters.ts +29 -0
- package/src/types/Labels.ts +36 -0
- package/src/types/Matchers.ts +106 -0
- package/src/types/Modifiers.ts +62 -0
- package/src/types/Styles.ts +108 -0
- package/tsconfig.json +24 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-day-picker",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.4",
|
|
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,7 +28,9 @@
|
|
|
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
36
|
"@reach/auto-id": "^0.16.0"
|
|
@@ -37,22 +39,22 @@
|
|
|
37
39
|
"@rollup/plugin-alias": "^3.1.9",
|
|
38
40
|
"@rollup/plugin-commonjs": "^21.0.3",
|
|
39
41
|
"@rollup/plugin-typescript": "^8.3.1",
|
|
40
|
-
"@testing-library/jest-dom": "^5.16.
|
|
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.
|
|
47
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
48
|
-
"@typescript-eslint/parser": "^5.
|
|
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.
|
|
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.
|
|
54
|
-
"eslint-plugin-import": "^2.
|
|
55
|
-
"eslint-plugin-jest": "^26.1.
|
|
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.
|
|
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
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { CaptionProps } from 'components/Caption/Caption';
|
|
4
|
+
import { CaptionLabel } from 'components/CaptionLabel';
|
|
5
|
+
import { MonthsDropdown } from 'components/MonthsDropdown';
|
|
6
|
+
import { YearsDropdown } from 'components/YearsDropdown';
|
|
7
|
+
import { useDayPicker } from 'contexts/DayPicker';
|
|
8
|
+
import { useNavigation } from 'contexts/Navigation';
|
|
9
|
+
import { MonthChangeEventHandler } from 'types/EventHandlers';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Render a caption with the dropdowns to navigate between months and years.
|
|
13
|
+
*/
|
|
14
|
+
export function CaptionDropdowns(props: CaptionProps): JSX.Element {
|
|
15
|
+
const { classNames, styles, onMonthChange, components } = useDayPicker();
|
|
16
|
+
const { goToMonth } = useNavigation();
|
|
17
|
+
|
|
18
|
+
const handleMonthChange: MonthChangeEventHandler = (newMonth) => {
|
|
19
|
+
goToMonth(newMonth);
|
|
20
|
+
onMonthChange?.(newMonth);
|
|
21
|
+
};
|
|
22
|
+
const CaptionLabelComponent = components?.CaptionLabel ?? CaptionLabel;
|
|
23
|
+
const captionLabel = (
|
|
24
|
+
<CaptionLabelComponent id={props.id} displayMonth={props.displayMonth} />
|
|
25
|
+
);
|
|
26
|
+
return (
|
|
27
|
+
<div
|
|
28
|
+
className={classNames.caption_dropdowns}
|
|
29
|
+
style={styles.caption_dropdowns}
|
|
30
|
+
>
|
|
31
|
+
{/* Caption label is visually hidden but for a11y. */}
|
|
32
|
+
<div className={classNames.vhidden}>{captionLabel}</div>
|
|
33
|
+
<MonthsDropdown
|
|
34
|
+
onChange={handleMonthChange}
|
|
35
|
+
displayMonth={props.displayMonth}
|
|
36
|
+
/>
|
|
37
|
+
<YearsDropdown
|
|
38
|
+
onChange={handleMonthChange}
|
|
39
|
+
displayMonth={props.displayMonth}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CaptionDropdowns';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { getMonthCaption } from 'test/po';
|
|
4
|
+
import { customRender } from 'test/render';
|
|
5
|
+
import { freezeBeforeAll } from 'test/utils';
|
|
6
|
+
|
|
7
|
+
import { CaptionLabel } from './CaptionLabel';
|
|
8
|
+
|
|
9
|
+
const today = new Date(1979, 8);
|
|
10
|
+
freezeBeforeAll(today);
|
|
11
|
+
|
|
12
|
+
test('should render the formatted display month', () => {
|
|
13
|
+
customRender(<CaptionLabel displayMonth={today} />);
|
|
14
|
+
expect(getMonthCaption()).toHaveTextContent('September 1979');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('should apply the `caption_label` class name', () => {
|
|
18
|
+
customRender(<CaptionLabel displayMonth={today} />, {
|
|
19
|
+
classNames: { caption_label: 'foo' }
|
|
20
|
+
});
|
|
21
|
+
expect(getMonthCaption()).toHaveClass('foo');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('should apply the `caption_label` style', () => {
|
|
25
|
+
customRender(<CaptionLabel displayMonth={today} />, {
|
|
26
|
+
styles: { caption_label: { color: 'red' } }
|
|
27
|
+
});
|
|
28
|
+
expect(getMonthCaption()).toHaveStyle({ color: 'red' });
|
|
29
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useDayPicker } from 'contexts/DayPicker';
|
|
4
|
+
|
|
5
|
+
/** The props for the [[CaptionLabel]] component. */
|
|
6
|
+
export interface CaptionLabelProps {
|
|
7
|
+
/** The ID for the heading element. Must be the same as the labelled-by in Table. */
|
|
8
|
+
id?: string;
|
|
9
|
+
/** The month where the caption is displayed. */
|
|
10
|
+
displayMonth: Date;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Render the caption for the displayed month. This component is used when `captionLayout="buttons"`. */
|
|
14
|
+
export function CaptionLabel(props: CaptionLabelProps): JSX.Element {
|
|
15
|
+
const {
|
|
16
|
+
locale,
|
|
17
|
+
classNames,
|
|
18
|
+
styles,
|
|
19
|
+
formatters: { formatCaption }
|
|
20
|
+
} = useDayPicker();
|
|
21
|
+
return (
|
|
22
|
+
<h2
|
|
23
|
+
className={classNames.caption_label}
|
|
24
|
+
style={styles.caption_label}
|
|
25
|
+
aria-live="polite"
|
|
26
|
+
aria-atomic="true"
|
|
27
|
+
id={props.id}
|
|
28
|
+
>
|
|
29
|
+
{formatCaption(props.displayMonth, { locale })}
|
|
30
|
+
</h2>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CaptionLabel';
|