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.
- package/README.md +1 -1
- package/dist/hooks/useDayRender/useDayRender.d.ts +1 -1
- package/dist/hooks/useInput/useInput.d.ts +2 -2
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/react-day-picker.min.js +1 -0
- package/dist/style.css +11 -10
- package/dist/style.module.css +11 -10
- package/dist/types/Styles.d.ts +8 -2
- package/package.json +15 -13
- 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 +311 -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 +125 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Dropdown';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { getTableFooter, queryTableFooter } from 'test/po';
|
|
4
|
+
import { customRender } from 'test/render';
|
|
5
|
+
|
|
6
|
+
import { Footer } from './Footer';
|
|
7
|
+
|
|
8
|
+
customRender(
|
|
9
|
+
<table role="grid">
|
|
10
|
+
<Footer />
|
|
11
|
+
</table>
|
|
12
|
+
);
|
|
13
|
+
test('should not render anything as default', () => {
|
|
14
|
+
expect(queryTableFooter()).toBeNull();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('when using the `footer` prop', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
customRender(
|
|
20
|
+
<table role="grid">
|
|
21
|
+
<Footer />
|
|
22
|
+
</table>,
|
|
23
|
+
{ footer: 'footer_foo' }
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
test('should render the table footer', () => {
|
|
27
|
+
expect(getTableFooter()).toHaveTextContent('footer_foo');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useDayPicker } from 'contexts/DayPicker';
|
|
4
|
+
|
|
5
|
+
/** Render the Footer component (empty as default).*/
|
|
6
|
+
export function Footer(): JSX.Element {
|
|
7
|
+
const {
|
|
8
|
+
footer,
|
|
9
|
+
styles,
|
|
10
|
+
classNames: { tfoot }
|
|
11
|
+
} = useDayPicker();
|
|
12
|
+
if (!footer) return <></>;
|
|
13
|
+
return (
|
|
14
|
+
<tfoot className={tfoot} style={styles.tfoot}>
|
|
15
|
+
<tr>
|
|
16
|
+
<td colSpan={8}>{footer}</td>
|
|
17
|
+
</tr>
|
|
18
|
+
</tfoot>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Footer';
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { RenderResult, screen } from '@testing-library/react';
|
|
4
|
+
import { DayPickerProps } from 'DayPicker';
|
|
5
|
+
|
|
6
|
+
import { customRender } from 'test/render';
|
|
7
|
+
|
|
8
|
+
import { defaultClassNames } from 'contexts/DayPicker/defaultClassNames';
|
|
9
|
+
import { formatWeekdayName } from 'contexts/DayPicker/formatters';
|
|
10
|
+
import { labelWeekday } from 'contexts/DayPicker/labels';
|
|
11
|
+
|
|
12
|
+
import { Head } from './Head';
|
|
13
|
+
import { getWeekdays } from './utils/getWeekdays';
|
|
14
|
+
|
|
15
|
+
let container: HTMLElement;
|
|
16
|
+
let view: RenderResult;
|
|
17
|
+
|
|
18
|
+
let thElements: HTMLTableCellElement[];
|
|
19
|
+
|
|
20
|
+
function setup(dayPickerProps: DayPickerProps = {}) {
|
|
21
|
+
view = customRender(
|
|
22
|
+
<table>
|
|
23
|
+
<Head />
|
|
24
|
+
</table>,
|
|
25
|
+
dayPickerProps
|
|
26
|
+
);
|
|
27
|
+
container = view.container.firstChild as HTMLTableCellElement;
|
|
28
|
+
thElements = Array.from(container.getElementsByTagName('th'));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const dayPickerProps = {
|
|
32
|
+
styles: {
|
|
33
|
+
head: { color: 'red' },
|
|
34
|
+
head_row: { color: 'blue' },
|
|
35
|
+
head_cell: { color: 'green' }
|
|
36
|
+
},
|
|
37
|
+
classNames: {
|
|
38
|
+
head: 'foo',
|
|
39
|
+
head_row: 'foo_row',
|
|
40
|
+
head_cell: 'foo_head-cell'
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
describe('when rendered', () => {
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
setup(dayPickerProps);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('thead should have the `head` style', () => {
|
|
50
|
+
expect(container.firstChild).toHaveStyle(dayPickerProps.styles.head);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('thead should have the `head` class', () => {
|
|
54
|
+
expect(container.firstChild).toHaveClass(dayPickerProps.classNames.head);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('tr element should have the `head_row` style', () => {
|
|
58
|
+
expect(container.firstChild?.firstChild).toHaveStyle(
|
|
59
|
+
dayPickerProps.styles.head_row
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('tr element should have the `head_row` class', () => {
|
|
64
|
+
expect(container.firstChild?.firstChild).toHaveClass(
|
|
65
|
+
dayPickerProps.classNames.head_row
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
test('should render 7 head elements', () => {
|
|
69
|
+
expect(thElements).toHaveLength(7);
|
|
70
|
+
});
|
|
71
|
+
test('should render the head elements with the "head_cell" class name', () => {
|
|
72
|
+
thElements.forEach((el) => {
|
|
73
|
+
expect(el).toHaveClass(dayPickerProps.classNames.head_cell);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
test('the formatted weekday name should be ARIA-hidden', () => {
|
|
77
|
+
const weekdays = getWeekdays();
|
|
78
|
+
weekdays.forEach((weekday) => {
|
|
79
|
+
const text = formatWeekdayName(weekday);
|
|
80
|
+
expect(screen.getByText(text)).toHaveAttribute('aria-hidden', 'true');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
test('the label should not be visible', () => {
|
|
84
|
+
const weekdays = getWeekdays();
|
|
85
|
+
weekdays.forEach((weekday) => {
|
|
86
|
+
const text = labelWeekday(weekday);
|
|
87
|
+
expect(screen.getByText(text)).toHaveClass(defaultClassNames.vhidden);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('when showing the week numbers', () => {
|
|
93
|
+
beforeEach(() => {
|
|
94
|
+
setup({ ...dayPickerProps, showWeekNumber: true });
|
|
95
|
+
});
|
|
96
|
+
test('should render 8 head elements', () => {
|
|
97
|
+
expect(thElements).toHaveLength(8);
|
|
98
|
+
});
|
|
99
|
+
test('the first head element should be empty', () => {
|
|
100
|
+
expect(thElements[0]).toHaveTextContent('');
|
|
101
|
+
});
|
|
102
|
+
test('should render the head elements with the "head_cell" class name', () => {
|
|
103
|
+
thElements.forEach((el) => {
|
|
104
|
+
expect(el).toHaveClass(dayPickerProps.classNames.head_cell);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
test('should render the head elements with the "head_cell" style', () => {
|
|
108
|
+
thElements.forEach((el) => {
|
|
109
|
+
expect(el).toHaveStyle(dayPickerProps.styles.head_cell);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
test('should render the head elements with the "col" scope', () => {
|
|
113
|
+
thElements.forEach((el) => {
|
|
114
|
+
expect(el).toHaveAttribute('scope', 'col');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useDayPicker } from 'contexts/DayPicker';
|
|
4
|
+
|
|
5
|
+
import { getWeekdays } from './utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Render the Head component - i.e. the table head with the weekday names.
|
|
9
|
+
*/
|
|
10
|
+
export function Head(): JSX.Element {
|
|
11
|
+
const {
|
|
12
|
+
classNames,
|
|
13
|
+
styles,
|
|
14
|
+
showWeekNumber,
|
|
15
|
+
locale,
|
|
16
|
+
weekStartsOn,
|
|
17
|
+
formatters: { formatWeekdayName },
|
|
18
|
+
labels: { labelWeekday }
|
|
19
|
+
} = useDayPicker();
|
|
20
|
+
|
|
21
|
+
const weekdays = getWeekdays(locale, weekStartsOn);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<thead style={styles.head} className={classNames.head}>
|
|
25
|
+
<tr style={styles.head_row} className={classNames.head_row}>
|
|
26
|
+
{showWeekNumber && (
|
|
27
|
+
<th
|
|
28
|
+
scope="col"
|
|
29
|
+
style={styles.head_cell}
|
|
30
|
+
className={classNames.head_cell}
|
|
31
|
+
></th>
|
|
32
|
+
)}
|
|
33
|
+
{weekdays.map((weekday, i) => (
|
|
34
|
+
<th
|
|
35
|
+
key={i}
|
|
36
|
+
scope="col"
|
|
37
|
+
className={classNames.head_cell}
|
|
38
|
+
style={styles.head_cell}
|
|
39
|
+
>
|
|
40
|
+
<span aria-hidden={true}>
|
|
41
|
+
{formatWeekdayName(weekday, { locale })}
|
|
42
|
+
</span>
|
|
43
|
+
<span className={classNames.vhidden}>
|
|
44
|
+
{labelWeekday(weekday, { locale })}
|
|
45
|
+
</span>
|
|
46
|
+
</th>
|
|
47
|
+
))}
|
|
48
|
+
</tr>
|
|
49
|
+
</thead>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Head';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import es from 'date-fns/locale/es';
|
|
2
|
+
|
|
3
|
+
import { freezeBeforeAll } from 'test/utils';
|
|
4
|
+
|
|
5
|
+
import { getWeekdays } from './getWeekdays';
|
|
6
|
+
|
|
7
|
+
const today = new Date(2022, 1, 12);
|
|
8
|
+
const prevSunday = new Date(2022, 1, 6);
|
|
9
|
+
|
|
10
|
+
freezeBeforeAll(today);
|
|
11
|
+
|
|
12
|
+
let result: Date[];
|
|
13
|
+
|
|
14
|
+
describe('when rendered without a locale', () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
result = getWeekdays();
|
|
17
|
+
});
|
|
18
|
+
test('should return 7 days', () => {
|
|
19
|
+
expect(result).toHaveLength(7);
|
|
20
|
+
});
|
|
21
|
+
test('should return Sunday as first day', () => {
|
|
22
|
+
expect(result[0]).toEqual(prevSunday);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe.each<0 | 1 | 2 | 3 | 4 | 5 | 6>([0, 1, 2, 3, 4, 5, 6])(
|
|
27
|
+
'when week start on %s',
|
|
28
|
+
(weekStartsOn) => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
result = getWeekdays(es, weekStartsOn);
|
|
31
|
+
});
|
|
32
|
+
test('the first date should be weekStartsOn', () => {
|
|
33
|
+
expect(result[0].getDay()).toBe(weekStartsOn);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import addDays from 'date-fns/addDays';
|
|
2
|
+
import startOfWeek from 'date-fns/startOfWeek';
|
|
3
|
+
|
|
4
|
+
import type { Locale } from 'date-fns';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Generate a series of 7 days, starting from the week, to use for formatting
|
|
8
|
+
* the weekday names (Monday, Tuesday, etc.).
|
|
9
|
+
*/
|
|
10
|
+
export function getWeekdays(
|
|
11
|
+
locale?: Locale,
|
|
12
|
+
/** The index of the first day of the week (0 - Sunday) */
|
|
13
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6
|
|
14
|
+
): Date[] {
|
|
15
|
+
const start = startOfWeek(new Date(), { locale, weekStartsOn });
|
|
16
|
+
const days = [];
|
|
17
|
+
for (let i = 0; i < 7; i++) {
|
|
18
|
+
const day = addDays(start, i);
|
|
19
|
+
days.push(day);
|
|
20
|
+
}
|
|
21
|
+
return days;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getWeekdays';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { customRender } from 'test/render';
|
|
4
|
+
|
|
5
|
+
import { IconDropdown } from './IconDropdown';
|
|
6
|
+
|
|
7
|
+
let root: HTMLElement;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
const view = customRender(
|
|
11
|
+
<IconDropdown className="foo" style={{ color: 'red' }} />
|
|
12
|
+
);
|
|
13
|
+
root = view.container.firstChild as HTMLElement;
|
|
14
|
+
});
|
|
15
|
+
test('should add the class name', () => {
|
|
16
|
+
expect(root).toHaveClass('foo');
|
|
17
|
+
});
|
|
18
|
+
test('should apply the style', () => {
|
|
19
|
+
expect(root).toHaveStyle({ color: 'red' });
|
|
20
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { StyledComponent } from 'types/Styles';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Render the icon in the styled drop-down.
|
|
7
|
+
*/
|
|
8
|
+
export function IconDropdown(props: StyledComponent): JSX.Element {
|
|
9
|
+
return (
|
|
10
|
+
<svg
|
|
11
|
+
width="8px"
|
|
12
|
+
height="8px"
|
|
13
|
+
viewBox="0 0 120 120"
|
|
14
|
+
data-testid="iconDropdown"
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
<path
|
|
18
|
+
d="M4.22182541,48.2218254 C8.44222828,44.0014225 15.2388494,43.9273804 19.5496459,47.9996989 L19.7781746,48.2218254 L60,88.443 L100.221825,48.2218254 C104.442228,44.0014225 111.238849,43.9273804 115.549646,47.9996989 L115.778175,48.2218254 C119.998577,52.4422283 120.07262,59.2388494 116.000301,63.5496459 L115.778175,63.7781746 L67.7781746,111.778175 C63.5577717,115.998577 56.7611506,116.07262 52.4503541,112.000301 L52.2218254,111.778175 L4.22182541,63.7781746 C-0.0739418023,59.4824074 -0.0739418023,52.5175926 4.22182541,48.2218254 Z"
|
|
19
|
+
fill="currentColor"
|
|
20
|
+
fillRule="nonzero"
|
|
21
|
+
></path>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './IconDropdown';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { customRender } from 'test/render';
|
|
4
|
+
|
|
5
|
+
import { IconLeft } from './IconLeft';
|
|
6
|
+
|
|
7
|
+
let root: HTMLElement;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
const view = customRender(
|
|
11
|
+
<IconLeft className="foo" style={{ color: 'red' }} />
|
|
12
|
+
);
|
|
13
|
+
root = view.container.firstChild as HTMLElement;
|
|
14
|
+
});
|
|
15
|
+
test('should add the class name', () => {
|
|
16
|
+
expect(root).toHaveClass('foo');
|
|
17
|
+
});
|
|
18
|
+
test('should apply the style', () => {
|
|
19
|
+
expect(root).toHaveStyle({ color: 'red' });
|
|
20
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { StyledComponent } from 'types/Styles';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Render the "previous month" button in the navigation.
|
|
7
|
+
*/
|
|
8
|
+
export function IconLeft(props: StyledComponent): JSX.Element {
|
|
9
|
+
return (
|
|
10
|
+
<svg width="16px" height="16px" viewBox="0 0 120 120" {...props}>
|
|
11
|
+
<path
|
|
12
|
+
d="M69.490332,3.34314575 C72.6145263,0.218951416 77.6798462,0.218951416 80.8040405,3.34314575 C83.8617626,6.40086786 83.9268205,11.3179931 80.9992143,14.4548388 L80.8040405,14.6568542 L35.461,60 L80.8040405,105.343146 C83.8617626,108.400868 83.9268205,113.317993 80.9992143,116.454839 L80.8040405,116.656854 C77.7463184,119.714576 72.8291931,119.779634 69.6923475,116.852028 L69.490332,116.656854 L18.490332,65.6568542 C15.4326099,62.5991321 15.367552,57.6820069 18.2951583,54.5451612 L18.490332,54.3431458 L69.490332,3.34314575 Z"
|
|
13
|
+
fill="currentColor"
|
|
14
|
+
fillRule="nonzero"
|
|
15
|
+
></path>
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './IconLeft';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { customRender } from 'test/render';
|
|
4
|
+
|
|
5
|
+
import { IconRight } from './IconRight';
|
|
6
|
+
|
|
7
|
+
let root: HTMLElement;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
const view = customRender(
|
|
11
|
+
<IconRight className="foo" style={{ color: 'red' }} />
|
|
12
|
+
);
|
|
13
|
+
root = view.container.firstChild as HTMLElement;
|
|
14
|
+
});
|
|
15
|
+
test('should add the class name', () => {
|
|
16
|
+
expect(root).toHaveClass('foo');
|
|
17
|
+
});
|
|
18
|
+
test('should apply the style', () => {
|
|
19
|
+
expect(root).toHaveStyle({ color: 'red' });
|
|
20
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { StyledComponent } from 'types/Styles';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Render the "next month" button in the navigation.
|
|
7
|
+
*/
|
|
8
|
+
export function IconRight(props: StyledComponent): JSX.Element {
|
|
9
|
+
return (
|
|
10
|
+
<svg width="16px" height="16px" viewBox="0 0 120 120" {...props}>
|
|
11
|
+
<path
|
|
12
|
+
d="M49.8040405,3.34314575 C46.6798462,0.218951416 41.6145263,0.218951416 38.490332,3.34314575 C35.4326099,6.40086786 35.367552,11.3179931 38.2951583,14.4548388 L38.490332,14.6568542 L83.8333725,60 L38.490332,105.343146 C35.4326099,108.400868 35.367552,113.317993 38.2951583,116.454839 L38.490332,116.656854 C41.5480541,119.714576 46.4651794,119.779634 49.602025,116.852028 L49.8040405,116.656854 L100.804041,65.6568542 C103.861763,62.5991321 103.926821,57.6820069 100.999214,54.5451612 L100.804041,54.3431458 L49.8040405,3.34314575 Z"
|
|
13
|
+
fill="currentColor"
|
|
14
|
+
></path>
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './IconRight';
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { screen } from '@testing-library/react';
|
|
4
|
+
import { DayPickerProps } from 'DayPicker';
|
|
5
|
+
|
|
6
|
+
import { getMonthCaption, getMonthGrid } from 'test/po';
|
|
7
|
+
import { customRender } from 'test/render';
|
|
8
|
+
|
|
9
|
+
import { CustomComponents } from 'types/DayPickerBase';
|
|
10
|
+
|
|
11
|
+
import { Month, MonthProps } from './Month';
|
|
12
|
+
|
|
13
|
+
let root: HTMLDivElement;
|
|
14
|
+
|
|
15
|
+
const displayMonth = new Date(2022, 10, 4);
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
const testStyles: Record<string, any> = {
|
|
19
|
+
caption_start: { color: 'red' },
|
|
20
|
+
caption_end: { background: 'blue' },
|
|
21
|
+
caption_between: { fontSize: 20 }
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const testClassNames: Record<string, string> = {
|
|
25
|
+
caption_start: 'caption_start',
|
|
26
|
+
caption_end: 'caption_end',
|
|
27
|
+
caption_between: 'caption_between'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type Test = {
|
|
31
|
+
monthProps: MonthProps;
|
|
32
|
+
dayPickerProps: DayPickerProps;
|
|
33
|
+
expected: string[];
|
|
34
|
+
notExpected: string[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function setup(props: MonthProps, dayPickerProps?: DayPickerProps) {
|
|
38
|
+
const view = customRender(<Month {...props} />, dayPickerProps);
|
|
39
|
+
root = view.container.firstChild as HTMLDivElement;
|
|
40
|
+
}
|
|
41
|
+
describe('when rendered', () => {
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
setup({ displayIndex: 0, displayMonth });
|
|
44
|
+
});
|
|
45
|
+
test('the caption id should be the aria-labelledby of the grid', () => {
|
|
46
|
+
const captionId = getMonthCaption().getAttribute('id');
|
|
47
|
+
const gridLabelledBy = getMonthGrid().getAttribute('aria-labelledby');
|
|
48
|
+
expect(captionId).toEqual(gridLabelledBy);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('when using a custom Caption component', () => {
|
|
53
|
+
const components: CustomComponents = {
|
|
54
|
+
Caption: () => <>custom caption foo</>
|
|
55
|
+
};
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
setup({ displayIndex: 0, displayMonth }, { components });
|
|
58
|
+
});
|
|
59
|
+
test('it should render the custom component instead', () => {
|
|
60
|
+
expect(screen.getByText('custom caption foo')).toBeInTheDocument();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('when dir is ltr', () => {
|
|
65
|
+
const testLtr: Test[] = [
|
|
66
|
+
{
|
|
67
|
+
monthProps: {
|
|
68
|
+
displayIndex: 0,
|
|
69
|
+
displayMonth
|
|
70
|
+
},
|
|
71
|
+
dayPickerProps: {
|
|
72
|
+
numberOfMonths: 1,
|
|
73
|
+
styles: testStyles,
|
|
74
|
+
classNames: testClassNames
|
|
75
|
+
},
|
|
76
|
+
expected: ['caption_start', 'caption_end'],
|
|
77
|
+
notExpected: ['caption_between']
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
monthProps: {
|
|
81
|
+
displayIndex: 0,
|
|
82
|
+
displayMonth
|
|
83
|
+
},
|
|
84
|
+
dayPickerProps: {
|
|
85
|
+
numberOfMonths: 2,
|
|
86
|
+
styles: testStyles,
|
|
87
|
+
classNames: testClassNames
|
|
88
|
+
},
|
|
89
|
+
expected: ['caption_start'],
|
|
90
|
+
notExpected: ['caption_between', 'caption_end']
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
monthProps: {
|
|
94
|
+
displayIndex: 1,
|
|
95
|
+
displayMonth
|
|
96
|
+
},
|
|
97
|
+
dayPickerProps: {
|
|
98
|
+
numberOfMonths: 2,
|
|
99
|
+
styles: testStyles,
|
|
100
|
+
classNames: testClassNames
|
|
101
|
+
},
|
|
102
|
+
expected: ['caption_end'],
|
|
103
|
+
notExpected: ['caption_start', 'caption_between']
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
monthProps: {
|
|
107
|
+
displayIndex: 1,
|
|
108
|
+
displayMonth
|
|
109
|
+
},
|
|
110
|
+
dayPickerProps: {
|
|
111
|
+
numberOfMonths: 3,
|
|
112
|
+
styles: testStyles,
|
|
113
|
+
classNames: testClassNames
|
|
114
|
+
},
|
|
115
|
+
expected: ['caption_between'],
|
|
116
|
+
notExpected: ['caption_start', 'caption_end']
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
describe.each(testLtr)(
|
|
121
|
+
'when displayIndex is $monthProps.displayIndex and numberOfMonths is $dayPickerProps.numberOfMonths',
|
|
122
|
+
({ monthProps, dayPickerProps, expected, notExpected }) => {
|
|
123
|
+
beforeEach(() => {
|
|
124
|
+
setup(monthProps, dayPickerProps);
|
|
125
|
+
});
|
|
126
|
+
test.each(expected)(`the root should have the %s class`, (name) =>
|
|
127
|
+
expect(root).toHaveClass(testClassNames[name])
|
|
128
|
+
);
|
|
129
|
+
test.each(expected)(`the root should have the %s style`, (name) =>
|
|
130
|
+
expect(root).toHaveStyle(testStyles[name])
|
|
131
|
+
);
|
|
132
|
+
test.each(notExpected)(`the root should not have the %s class`, (name) =>
|
|
133
|
+
expect(root).not.toHaveClass(testClassNames[name])
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('when dir is rtl', () => {
|
|
140
|
+
const testRtl: Test[] = [
|
|
141
|
+
{
|
|
142
|
+
monthProps: {
|
|
143
|
+
displayIndex: 0,
|
|
144
|
+
displayMonth
|
|
145
|
+
},
|
|
146
|
+
dayPickerProps: {
|
|
147
|
+
dir: 'rtl',
|
|
148
|
+
numberOfMonths: 1,
|
|
149
|
+
styles: testStyles,
|
|
150
|
+
classNames: testClassNames
|
|
151
|
+
},
|
|
152
|
+
expected: ['caption_start', 'caption_end'],
|
|
153
|
+
notExpected: ['caption_between']
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
monthProps: {
|
|
157
|
+
displayIndex: 0,
|
|
158
|
+
displayMonth
|
|
159
|
+
},
|
|
160
|
+
dayPickerProps: {
|
|
161
|
+
dir: 'rtl',
|
|
162
|
+
numberOfMonths: 2,
|
|
163
|
+
styles: testStyles,
|
|
164
|
+
classNames: testClassNames
|
|
165
|
+
},
|
|
166
|
+
expected: ['caption_end'],
|
|
167
|
+
notExpected: ['caption_between', 'caption_start']
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
monthProps: {
|
|
171
|
+
displayIndex: 1,
|
|
172
|
+
displayMonth
|
|
173
|
+
},
|
|
174
|
+
dayPickerProps: {
|
|
175
|
+
dir: 'rtl',
|
|
176
|
+
numberOfMonths: 2,
|
|
177
|
+
styles: testStyles,
|
|
178
|
+
classNames: testClassNames
|
|
179
|
+
},
|
|
180
|
+
expected: ['caption_start'],
|
|
181
|
+
notExpected: ['caption_end', 'caption_between']
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
monthProps: {
|
|
185
|
+
displayIndex: 1,
|
|
186
|
+
displayMonth
|
|
187
|
+
},
|
|
188
|
+
dayPickerProps: {
|
|
189
|
+
dir: 'rtl',
|
|
190
|
+
numberOfMonths: 3,
|
|
191
|
+
styles: testStyles,
|
|
192
|
+
classNames: testClassNames
|
|
193
|
+
},
|
|
194
|
+
expected: ['caption_between'],
|
|
195
|
+
notExpected: ['caption_start', 'caption_end']
|
|
196
|
+
}
|
|
197
|
+
];
|
|
198
|
+
|
|
199
|
+
describe.each(testRtl)(
|
|
200
|
+
'when displayIndex is $monthProps.displayIndex and numberOfMonths is $dayPickerProps.numberOfMonths',
|
|
201
|
+
({ monthProps, dayPickerProps, expected, notExpected }) => {
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
setup(monthProps, dayPickerProps);
|
|
204
|
+
});
|
|
205
|
+
test.each(expected)(`the root should have the %s class`, (name) =>
|
|
206
|
+
expect(root).toHaveClass(testClassNames[name])
|
|
207
|
+
);
|
|
208
|
+
test.each(expected)(`the root should have the %s style`, (name) =>
|
|
209
|
+
expect(root).toHaveStyle(testStyles[name])
|
|
210
|
+
);
|
|
211
|
+
test.each(notExpected)(`the root should not have the %s class`, (name) =>
|
|
212
|
+
expect(root).not.toHaveClass(testClassNames[name])
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
});
|