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 './useControlledValue';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { act } from 'react-dom/test-utils';
|
|
2
|
+
|
|
3
|
+
import { renderHook, RenderHookResult } from '@testing-library/react-hooks';
|
|
4
|
+
|
|
5
|
+
import { DispatchStateAction, useControlledValue } from './useControlledValue';
|
|
6
|
+
|
|
7
|
+
type RenderHookProps = {
|
|
8
|
+
defaultValue: string;
|
|
9
|
+
controlledValue: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function setup(defaultValue: string, controlledValue: string | undefined) {
|
|
13
|
+
return renderHook<RenderHookProps, [string, DispatchStateAction<string>]>(
|
|
14
|
+
(props) =>
|
|
15
|
+
useControlledValue<string>(props.defaultValue, props.controlledValue),
|
|
16
|
+
{
|
|
17
|
+
initialProps: { defaultValue, controlledValue }
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('when the value is controlled', () => {
|
|
23
|
+
const defaultValue = 'foo'; // not controlled
|
|
24
|
+
const controlledValue = 'bar'; // now controlled
|
|
25
|
+
let hook: RenderHookResult<
|
|
26
|
+
RenderHookProps,
|
|
27
|
+
[string, DispatchStateAction<string>]
|
|
28
|
+
>;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
hook = setup(defaultValue, controlledValue);
|
|
31
|
+
});
|
|
32
|
+
test('should return the controlled value', () => {
|
|
33
|
+
expect(hook.result.current[0]).toBe(controlledValue);
|
|
34
|
+
});
|
|
35
|
+
describe('when setting a new value', () => {
|
|
36
|
+
const newValue = 'taz';
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
act(() => hook.result.current[1](newValue));
|
|
39
|
+
});
|
|
40
|
+
test('should return the controlled value instead', () => {
|
|
41
|
+
expect(hook.result.current[0]).toBe(controlledValue);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('when the value is not controlled', () => {
|
|
47
|
+
const defaultValue = 'foo';
|
|
48
|
+
const controlledValue = undefined;
|
|
49
|
+
let hook: RenderHookResult<
|
|
50
|
+
RenderHookProps,
|
|
51
|
+
[string, DispatchStateAction<string>]
|
|
52
|
+
>;
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
hook = setup(defaultValue, controlledValue);
|
|
55
|
+
});
|
|
56
|
+
test('should return the value', () => {
|
|
57
|
+
expect(hook.result.current[0]).toBe(defaultValue);
|
|
58
|
+
});
|
|
59
|
+
describe('when setting a new value', () => {
|
|
60
|
+
const newValue = 'bar';
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
act(() => hook.result.current[1](newValue));
|
|
63
|
+
});
|
|
64
|
+
test('should return the new value', () => {
|
|
65
|
+
expect(hook.result.current[0]).toBe(newValue);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export type DispatchStateAction<T> = React.Dispatch<React.SetStateAction<T>>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Helper hook for using controlled/uncontrolled values from a component props.
|
|
7
|
+
*
|
|
8
|
+
* When the value is not controlled, pass `undefined` as `controlledValue` and
|
|
9
|
+
* use the returned setter to update it.
|
|
10
|
+
*
|
|
11
|
+
* When the value is controlled, pass the controlled value as second
|
|
12
|
+
* argument, which will be always returned as `value`.
|
|
13
|
+
*/
|
|
14
|
+
export function useControlledValue<T>(
|
|
15
|
+
defaultValue: T,
|
|
16
|
+
controlledValue: T | undefined
|
|
17
|
+
): [T, DispatchStateAction<T>] {
|
|
18
|
+
const [uncontrolledValue, setValue] = useState(defaultValue);
|
|
19
|
+
|
|
20
|
+
const value =
|
|
21
|
+
controlledValue === undefined ? uncontrolledValue : controlledValue;
|
|
22
|
+
|
|
23
|
+
return [value, setValue] as [T, DispatchStateAction<T>];
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useDayEventHandlers';
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { RenderResult } from '@testing-library/react-hooks';
|
|
2
|
+
import { DayPickerProps } from 'DayPicker';
|
|
3
|
+
|
|
4
|
+
import { customRenderHook } from 'test/render';
|
|
5
|
+
|
|
6
|
+
import { FocusContextValue } from 'contexts/Focus';
|
|
7
|
+
import { SelectMultipleContextValue } from 'contexts/SelectMultiple';
|
|
8
|
+
import { SelectRangeContextValue } from 'contexts/SelectRange';
|
|
9
|
+
import { SelectSingleContextValue } from 'contexts/SelectSingle';
|
|
10
|
+
import {
|
|
11
|
+
DayEventHandlers,
|
|
12
|
+
DayEventName,
|
|
13
|
+
EventName,
|
|
14
|
+
useDayEventHandlers
|
|
15
|
+
} from 'hooks/useDayEventHandlers';
|
|
16
|
+
import { ActiveModifiers } from 'types/Modifiers';
|
|
17
|
+
|
|
18
|
+
const today = new Date(2010, 5, 23);
|
|
19
|
+
|
|
20
|
+
const singleContext: SelectSingleContextValue = {
|
|
21
|
+
selected: today,
|
|
22
|
+
onDayClick: jest.fn()
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const multipleContext: SelectMultipleContextValue = {
|
|
26
|
+
selected: [today],
|
|
27
|
+
modifiers: { disabled: [] },
|
|
28
|
+
onDayClick: jest.fn()
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const rangeContext: SelectRangeContextValue = {
|
|
32
|
+
selected: undefined,
|
|
33
|
+
modifiers: {
|
|
34
|
+
disabled: [],
|
|
35
|
+
range_start: [],
|
|
36
|
+
range_end: [],
|
|
37
|
+
range_middle: []
|
|
38
|
+
},
|
|
39
|
+
onDayClick: jest.fn()
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const focusContext: FocusContextValue = {
|
|
43
|
+
focus: jest.fn(),
|
|
44
|
+
focusedDay: undefined,
|
|
45
|
+
focusTarget: undefined,
|
|
46
|
+
blur: jest.fn(),
|
|
47
|
+
focusDayAfter: jest.fn(),
|
|
48
|
+
focusDayBefore: jest.fn(),
|
|
49
|
+
focusWeekBefore: jest.fn(),
|
|
50
|
+
focusWeekAfter: jest.fn(),
|
|
51
|
+
focusMonthBefore: jest.fn(),
|
|
52
|
+
focusMonthAfter: jest.fn(),
|
|
53
|
+
focusYearBefore: jest.fn(),
|
|
54
|
+
focusYearAfter: jest.fn(),
|
|
55
|
+
focusStartOfWeek: jest.fn(),
|
|
56
|
+
focusEndOfWeek: jest.fn()
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const mockedContexts = {
|
|
60
|
+
single: singleContext,
|
|
61
|
+
multiple: multipleContext,
|
|
62
|
+
range: rangeContext,
|
|
63
|
+
focus: focusContext
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
let renderResult: RenderResult<DayEventHandlers>;
|
|
67
|
+
function setup(
|
|
68
|
+
date: Date,
|
|
69
|
+
activeModifiers: ActiveModifiers,
|
|
70
|
+
dayPickerProps?: DayPickerProps
|
|
71
|
+
) {
|
|
72
|
+
const view = customRenderHook(
|
|
73
|
+
() => useDayEventHandlers(date, activeModifiers),
|
|
74
|
+
dayPickerProps,
|
|
75
|
+
mockedContexts
|
|
76
|
+
);
|
|
77
|
+
renderResult = view.result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const tests: [EventName, DayEventName][] = [
|
|
81
|
+
['onClick', 'onDayClick'],
|
|
82
|
+
['onFocus', 'onDayFocus'],
|
|
83
|
+
['onBlur', 'onDayBlur'],
|
|
84
|
+
['onMouseEnter', 'onDayMouseEnter'],
|
|
85
|
+
['onMouseLeave', 'onDayMouseLeave'],
|
|
86
|
+
['onTouchEnd', 'onDayTouchEnd'],
|
|
87
|
+
['onTouchCancel', 'onDayTouchCancel'],
|
|
88
|
+
['onTouchMove', 'onDayTouchMove'],
|
|
89
|
+
['onTouchStart', 'onDayTouchStart'],
|
|
90
|
+
['onKeyUp', 'onDayKeyUp']
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
describe.each(tests)('when calling "%s"', (eventName, dayEventName) => {
|
|
94
|
+
const activeModifiers: ActiveModifiers = {};
|
|
95
|
+
const dayPickerProps = {
|
|
96
|
+
[dayEventName]: jest.fn()
|
|
97
|
+
};
|
|
98
|
+
const mouseEvent = {} as React.MouseEvent<HTMLButtonElement, MouseEvent>;
|
|
99
|
+
const date = today;
|
|
100
|
+
beforeEach(() => {
|
|
101
|
+
setup(date, activeModifiers, dayPickerProps);
|
|
102
|
+
//@ts-expect-error TOFIX: How to mock mouse event here?
|
|
103
|
+
renderResult.current[eventName]?.(mouseEvent);
|
|
104
|
+
});
|
|
105
|
+
test(`${dayEventName} should have been called`, () => {
|
|
106
|
+
expect(dayPickerProps[dayEventName]).toHaveBeenCalledWith(
|
|
107
|
+
date,
|
|
108
|
+
activeModifiers,
|
|
109
|
+
mouseEvent
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe.each<'single' | 'multiple' | 'range'>(['single', 'multiple', 'range'])(
|
|
115
|
+
'when calling "onClick" in "%s" selection mode',
|
|
116
|
+
(mode) => {
|
|
117
|
+
const activeModifiers: ActiveModifiers = {};
|
|
118
|
+
const dayPickerProps = { mode, onDayClick: jest.fn() };
|
|
119
|
+
const mouseEvent = {} as React.MouseEvent<HTMLButtonElement, MouseEvent>;
|
|
120
|
+
const date = today;
|
|
121
|
+
beforeEach(() => {
|
|
122
|
+
setup(date, activeModifiers, dayPickerProps);
|
|
123
|
+
renderResult.current.onClick?.(mouseEvent);
|
|
124
|
+
});
|
|
125
|
+
test(`should have called "onDayClick" from the day picker props`, () => {
|
|
126
|
+
expect(dayPickerProps.onDayClick).toHaveBeenCalled();
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
describe('when calling "onFocus"', () => {
|
|
132
|
+
const date = today;
|
|
133
|
+
const activeModifiers: ActiveModifiers = {};
|
|
134
|
+
const mouseEvent = {} as React.FocusEvent<HTMLButtonElement, Element>;
|
|
135
|
+
beforeEach(() => {
|
|
136
|
+
setup(date, activeModifiers);
|
|
137
|
+
renderResult.current.onFocus?.(mouseEvent);
|
|
138
|
+
});
|
|
139
|
+
test('should focus the date in the context', () => {
|
|
140
|
+
expect(focusContext.focus).toHaveBeenCalledWith(date);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('when calling "onBlur"', () => {
|
|
145
|
+
const date = today;
|
|
146
|
+
const activeModifiers: ActiveModifiers = {};
|
|
147
|
+
const mouseEvent = {} as React.FocusEvent<HTMLButtonElement, Element>;
|
|
148
|
+
beforeEach(() => {
|
|
149
|
+
setup(date, activeModifiers);
|
|
150
|
+
renderResult.current.onBlur?.(mouseEvent);
|
|
151
|
+
});
|
|
152
|
+
test('should blur the date in the context', () => {
|
|
153
|
+
expect(focusContext.blur).toHaveBeenCalled();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('when calling "onKeyDown"', () => {
|
|
158
|
+
const date = today;
|
|
159
|
+
const activeModifiers: ActiveModifiers = {};
|
|
160
|
+
|
|
161
|
+
const tests: [
|
|
162
|
+
key: string,
|
|
163
|
+
dir: string,
|
|
164
|
+
shiftKey: boolean,
|
|
165
|
+
expectedMethod: keyof FocusContextValue
|
|
166
|
+
][] = [
|
|
167
|
+
['ArrowLeft', 'ltr', false, 'focusDayBefore'],
|
|
168
|
+
['ArrowLeft', 'rtl', false, 'focusDayAfter'],
|
|
169
|
+
['ArrowRight', 'ltr', false, 'focusDayAfter'],
|
|
170
|
+
['ArrowRight', 'ltr', false, 'focusDayBefore'],
|
|
171
|
+
['ArrowRight', 'ltr', false, 'focusDayAfter'],
|
|
172
|
+
['ArrowDown', 'ltr', false, 'focusWeekAfter'],
|
|
173
|
+
['ArrowUp', 'ltr', false, 'focusWeekBefore'],
|
|
174
|
+
['PageUp', 'ltr', true, 'focusYearBefore'],
|
|
175
|
+
['PageUp', 'ltr', false, 'focusMonthBefore'],
|
|
176
|
+
['PageDown', 'ltr', true, 'focusYearAfter'],
|
|
177
|
+
['PageDown', 'ltr', false, 'focusMonthAfter'],
|
|
178
|
+
['Home', 'ltr', false, 'focusStartOfWeek'],
|
|
179
|
+
['End', 'ltr', false, 'focusEndOfWeek']
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
describe.each(tests)(
|
|
183
|
+
'when key is %s',
|
|
184
|
+
(key, dir, shiftKey, expectedMethod) => {
|
|
185
|
+
describe(`when text direction is "${dir.toUpperCase()}"`, () => {
|
|
186
|
+
describe(`when the shiftKey is ${
|
|
187
|
+
shiftKey ? '' : 'not'
|
|
188
|
+
} pressed`, () => {
|
|
189
|
+
const keyboardEvent = {
|
|
190
|
+
key,
|
|
191
|
+
shiftKey
|
|
192
|
+
} as React.KeyboardEvent<HTMLButtonElement>;
|
|
193
|
+
keyboardEvent.preventDefault = jest.fn();
|
|
194
|
+
keyboardEvent.stopPropagation = jest.fn();
|
|
195
|
+
|
|
196
|
+
beforeEach(() => {
|
|
197
|
+
setup(date, activeModifiers, { dir });
|
|
198
|
+
renderResult.current.onKeyDown?.(keyboardEvent);
|
|
199
|
+
});
|
|
200
|
+
test(`should call ${expectedMethod}`, () => {
|
|
201
|
+
expect(focusContext[expectedMethod]).toHaveBeenCalledWith();
|
|
202
|
+
});
|
|
203
|
+
test(`should prevent the default event`, () => {
|
|
204
|
+
expect(keyboardEvent.preventDefault).toHaveBeenCalledWith();
|
|
205
|
+
});
|
|
206
|
+
test(`should stop the event propagation`, () => {
|
|
207
|
+
expect(keyboardEvent.preventDefault).toHaveBeenCalledWith();
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
});
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FocusEventHandler,
|
|
3
|
+
HTMLProps,
|
|
4
|
+
KeyboardEventHandler,
|
|
5
|
+
MouseEventHandler,
|
|
6
|
+
TouchEventHandler
|
|
7
|
+
} from 'react';
|
|
8
|
+
|
|
9
|
+
import { useDayPicker } from 'contexts/DayPicker';
|
|
10
|
+
import { useFocusContext } from 'contexts/Focus';
|
|
11
|
+
import { useSelectMultiple } from 'contexts/SelectMultiple';
|
|
12
|
+
import { useSelectRange } from 'contexts/SelectRange';
|
|
13
|
+
import { useSelectSingle } from 'contexts/SelectSingle';
|
|
14
|
+
import { isDayPickerMultiple } from 'types/DayPickerMultiple';
|
|
15
|
+
import { isDayPickerRange } from 'types/DayPickerRange';
|
|
16
|
+
import { isDayPickerSingle } from 'types/DayPickerSingle';
|
|
17
|
+
import { ActiveModifiers } from 'types/Modifiers';
|
|
18
|
+
|
|
19
|
+
export type EventName =
|
|
20
|
+
| 'onClick'
|
|
21
|
+
| 'onFocus'
|
|
22
|
+
| 'onBlur'
|
|
23
|
+
| 'onKeyDown'
|
|
24
|
+
| 'onKeyUp'
|
|
25
|
+
| 'onMouseEnter'
|
|
26
|
+
| 'onMouseLeave'
|
|
27
|
+
| 'onTouchCancel'
|
|
28
|
+
| 'onTouchEnd'
|
|
29
|
+
| 'onTouchMove'
|
|
30
|
+
| 'onTouchStart';
|
|
31
|
+
|
|
32
|
+
export type DayEventName =
|
|
33
|
+
| 'onDayClick'
|
|
34
|
+
| 'onDayFocus'
|
|
35
|
+
| 'onDayBlur'
|
|
36
|
+
| 'onDayKeyDown'
|
|
37
|
+
| 'onDayKeyUp'
|
|
38
|
+
| 'onDayMouseEnter'
|
|
39
|
+
| 'onDayMouseLeave'
|
|
40
|
+
| 'onDayTouchCancel'
|
|
41
|
+
| 'onDayTouchEnd'
|
|
42
|
+
| 'onDayTouchMove'
|
|
43
|
+
| 'onDayTouchStart';
|
|
44
|
+
|
|
45
|
+
export type DayEventHandlers = Pick<HTMLProps<HTMLButtonElement>, EventName>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* This hook returns details about the content to render in the day cell.
|
|
49
|
+
*
|
|
50
|
+
*
|
|
51
|
+
* When a day cell is rendered in the table, DayPicker can either:
|
|
52
|
+
*
|
|
53
|
+
* - render nothing: when the day is outside the month or has matched the
|
|
54
|
+
* "hidden" modifier.
|
|
55
|
+
* - render a button when `onDayClick` or a selection mode is set.
|
|
56
|
+
* - render a non-interactive element: when no selection mode is set, the day
|
|
57
|
+
* cell shouldn’t respond to any interaction. DayPicker should render a `div`
|
|
58
|
+
* or a `span`.
|
|
59
|
+
*
|
|
60
|
+
* ### Usage
|
|
61
|
+
*
|
|
62
|
+
* Use this hook to customize the behavior of the [[Day]] component. Create a
|
|
63
|
+
* new `Day` component using this hook and pass it to the `components` prop.
|
|
64
|
+
* The source of [[Day]] can be a good starting point.
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
export function useDayEventHandlers(
|
|
68
|
+
date: Date,
|
|
69
|
+
activeModifiers: ActiveModifiers
|
|
70
|
+
): DayEventHandlers {
|
|
71
|
+
const dayPicker = useDayPicker();
|
|
72
|
+
const single = useSelectSingle();
|
|
73
|
+
const multiple = useSelectMultiple();
|
|
74
|
+
const range = useSelectRange();
|
|
75
|
+
const {
|
|
76
|
+
focusDayAfter,
|
|
77
|
+
focusDayBefore,
|
|
78
|
+
focusWeekAfter,
|
|
79
|
+
focusWeekBefore,
|
|
80
|
+
blur,
|
|
81
|
+
focus,
|
|
82
|
+
focusMonthBefore,
|
|
83
|
+
focusMonthAfter,
|
|
84
|
+
focusYearBefore,
|
|
85
|
+
focusYearAfter,
|
|
86
|
+
focusStartOfWeek,
|
|
87
|
+
focusEndOfWeek
|
|
88
|
+
} = useFocusContext();
|
|
89
|
+
|
|
90
|
+
const onClick: MouseEventHandler = (e) => {
|
|
91
|
+
if (isDayPickerSingle(dayPicker)) {
|
|
92
|
+
single.onDayClick?.(date, activeModifiers, e);
|
|
93
|
+
} else if (isDayPickerMultiple(dayPicker)) {
|
|
94
|
+
multiple.onDayClick?.(date, activeModifiers, e);
|
|
95
|
+
} else if (isDayPickerRange(dayPicker)) {
|
|
96
|
+
range.onDayClick?.(date, activeModifiers, e);
|
|
97
|
+
}
|
|
98
|
+
dayPicker.onDayClick?.(date, activeModifiers, e);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const onFocus: FocusEventHandler = (e) => {
|
|
102
|
+
focus(date);
|
|
103
|
+
dayPicker.onDayFocus?.(date, activeModifiers, e);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const onBlur: FocusEventHandler = (e) => {
|
|
107
|
+
blur();
|
|
108
|
+
dayPicker.onDayBlur?.(date, activeModifiers, e);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const onMouseEnter: MouseEventHandler = (e) => {
|
|
112
|
+
dayPicker.onDayMouseEnter?.(date, activeModifiers, e);
|
|
113
|
+
};
|
|
114
|
+
const onMouseLeave: MouseEventHandler = (e) => {
|
|
115
|
+
dayPicker.onDayMouseLeave?.(date, activeModifiers, e);
|
|
116
|
+
};
|
|
117
|
+
const onTouchCancel: TouchEventHandler = (e) => {
|
|
118
|
+
dayPicker.onDayTouchCancel?.(date, activeModifiers, e);
|
|
119
|
+
};
|
|
120
|
+
const onTouchEnd: TouchEventHandler = (e) => {
|
|
121
|
+
dayPicker.onDayTouchEnd?.(date, activeModifiers, e);
|
|
122
|
+
};
|
|
123
|
+
const onTouchMove: TouchEventHandler = (e) => {
|
|
124
|
+
dayPicker.onDayTouchMove?.(date, activeModifiers, e);
|
|
125
|
+
};
|
|
126
|
+
const onTouchStart: TouchEventHandler = (e) => {
|
|
127
|
+
dayPicker.onDayTouchStart?.(date, activeModifiers, e);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const onKeyUp: KeyboardEventHandler = (e) => {
|
|
131
|
+
dayPicker.onDayKeyUp?.(date, activeModifiers, e);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const onKeyDown: KeyboardEventHandler = (e) => {
|
|
135
|
+
switch (e.key) {
|
|
136
|
+
case 'ArrowLeft':
|
|
137
|
+
e.preventDefault();
|
|
138
|
+
e.stopPropagation();
|
|
139
|
+
dayPicker.dir === 'rtl' ? focusDayAfter() : focusDayBefore();
|
|
140
|
+
break;
|
|
141
|
+
case 'ArrowRight':
|
|
142
|
+
e.preventDefault();
|
|
143
|
+
e.stopPropagation();
|
|
144
|
+
dayPicker.dir === 'rtl' ? focusDayBefore() : focusDayAfter();
|
|
145
|
+
break;
|
|
146
|
+
case 'ArrowDown':
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
e.stopPropagation();
|
|
149
|
+
focusWeekAfter();
|
|
150
|
+
break;
|
|
151
|
+
case 'ArrowUp':
|
|
152
|
+
e.preventDefault();
|
|
153
|
+
e.stopPropagation();
|
|
154
|
+
focusWeekBefore();
|
|
155
|
+
break;
|
|
156
|
+
case 'PageUp':
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
e.stopPropagation();
|
|
159
|
+
e.shiftKey ? focusYearBefore() : focusMonthBefore();
|
|
160
|
+
break;
|
|
161
|
+
case 'PageDown':
|
|
162
|
+
e.preventDefault();
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
e.shiftKey ? focusYearAfter() : focusMonthAfter();
|
|
165
|
+
break;
|
|
166
|
+
case 'Home':
|
|
167
|
+
e.preventDefault();
|
|
168
|
+
e.stopPropagation();
|
|
169
|
+
focusStartOfWeek();
|
|
170
|
+
break;
|
|
171
|
+
case 'End':
|
|
172
|
+
e.preventDefault();
|
|
173
|
+
e.stopPropagation();
|
|
174
|
+
focusEndOfWeek();
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
dayPicker.onDayKeyDown?.(date, activeModifiers, e);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const eventHandlers: DayEventHandlers = {
|
|
181
|
+
onClick,
|
|
182
|
+
onFocus,
|
|
183
|
+
onBlur,
|
|
184
|
+
onKeyDown,
|
|
185
|
+
onKeyUp,
|
|
186
|
+
onMouseEnter,
|
|
187
|
+
onMouseLeave,
|
|
188
|
+
onTouchCancel,
|
|
189
|
+
onTouchEnd,
|
|
190
|
+
onTouchMove,
|
|
191
|
+
onTouchStart
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
return eventHandlers;
|
|
195
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useDayRender';
|