@transferwise/components 0.0.0-experimental-fa3aa98 → 0.0.0-experimental-f4a328f
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/build/Calendar/Calendar.js +16 -94
- package/build/Calendar/Calendar.js.map +1 -1
- package/build/Calendar/Calendar.messages.js +0 -12
- package/build/Calendar/Calendar.messages.js.map +1 -1
- package/build/Calendar/Calendar.messages.mjs +0 -12
- package/build/Calendar/Calendar.messages.mjs.map +1 -1
- package/build/Calendar/Calendar.mjs +17 -95
- package/build/Calendar/Calendar.mjs.map +1 -1
- package/build/Calendar/DateHeader/DateHeader.js +1 -5
- package/build/Calendar/DateHeader/DateHeader.js.map +1 -1
- package/build/Calendar/DateHeader/DateHeader.mjs +1 -5
- package/build/Calendar/DateHeader/DateHeader.mjs.map +1 -1
- package/build/Calendar/DayCalendar/DayCalendar.js +0 -14
- package/build/Calendar/DayCalendar/DayCalendar.js.map +1 -1
- package/build/Calendar/DayCalendar/DayCalendar.mjs +0 -14
- package/build/Calendar/DayCalendar/DayCalendar.mjs.map +1 -1
- package/build/Calendar/DayCalendar/Table/DayCalendarTable.js +19 -53
- package/build/Calendar/DayCalendar/Table/DayCalendarTable.js.map +1 -1
- package/build/Calendar/DayCalendar/Table/DayCalendarTable.mjs +19 -53
- package/build/Calendar/DayCalendar/Table/DayCalendarTable.mjs.map +1 -1
- package/build/Calendar/MonthCalendar/MonthCalendar.js +0 -6
- package/build/Calendar/MonthCalendar/MonthCalendar.js.map +1 -1
- package/build/Calendar/MonthCalendar/MonthCalendar.mjs +0 -6
- package/build/Calendar/MonthCalendar/MonthCalendar.mjs.map +1 -1
- package/build/Calendar/MonthCalendar/Table/MonthCalendarTable.js +3 -8
- package/build/Calendar/MonthCalendar/Table/MonthCalendarTable.js.map +1 -1
- package/build/Calendar/MonthCalendar/Table/MonthCalendarTable.mjs +3 -8
- package/build/Calendar/MonthCalendar/Table/MonthCalendarTable.mjs.map +1 -1
- package/build/Calendar/YearCalendar/Table/YearCalendarTable.js +3 -8
- package/build/Calendar/YearCalendar/Table/YearCalendarTable.js.map +1 -1
- package/build/Calendar/YearCalendar/Table/YearCalendarTable.mjs +3 -8
- package/build/Calendar/YearCalendar/Table/YearCalendarTable.mjs.map +1 -1
- package/build/Calendar/YearCalendar/YearCalendar.js +0 -7
- package/build/Calendar/YearCalendar/YearCalendar.js.map +1 -1
- package/build/Calendar/YearCalendar/YearCalendar.mjs +0 -7
- package/build/Calendar/YearCalendar/YearCalendar.mjs.map +1 -1
- package/build/Calendar/{TableLink → tableLink}/TableLink.js +11 -26
- package/build/Calendar/tableLink/TableLink.js.map +1 -0
- package/build/Calendar/{TableLink → tableLink}/TableLink.mjs +11 -26
- package/build/Calendar/tableLink/TableLink.mjs.map +1 -0
- package/build/DateLookup/DateLookup.js +9 -20
- package/build/DateLookup/DateLookup.js.map +1 -1
- package/build/DateLookup/DateLookup.mjs +9 -20
- package/build/DateLookup/DateLookup.mjs.map +1 -1
- package/build/Markup/Markup.js +137 -0
- package/build/Markup/Markup.js.map +1 -0
- package/build/Markup/Markup.mjs +132 -0
- package/build/Markup/Markup.mjs.map +1 -0
- package/build/Markup/constants.js +36 -0
- package/build/Markup/constants.js.map +1 -0
- package/build/Markup/constants.mjs +29 -0
- package/build/Markup/constants.mjs.map +1 -0
- package/build/Markup/utils/parseMarkup.js +236 -0
- package/build/Markup/utils/parseMarkup.js.map +1 -0
- package/build/Markup/utils/parseMarkup.mjs +231 -0
- package/build/Markup/utils/parseMarkup.mjs.map +1 -0
- package/build/Markup/utils/sanitise.js +114 -0
- package/build/Markup/utils/sanitise.js.map +1 -0
- package/build/Markup/utils/sanitise.mjs +111 -0
- package/build/Markup/utils/sanitise.mjs.map +1 -0
- package/build/i18n/en.json +0 -4
- package/build/i18n/en.json.js +0 -4
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +0 -4
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/index.js +4 -2
- package/build/index.js.map +1 -1
- package/build/index.mjs +2 -1
- package/build/index.mjs.map +1 -1
- package/build/main.css +78 -123
- package/build/styles/Calendar/Calendar.css +37 -112
- package/build/styles/Markup/Markup.css +28 -0
- package/build/styles/Markup/_stories/Vulnerability/Vulnerability.css +69 -0
- package/build/styles/main.css +78 -123
- package/build/types/Body/Body.d.ts +2 -2
- package/build/types/Calendar/Calendar.d.ts +3 -16
- package/build/types/Calendar/Calendar.d.ts.map +1 -1
- package/build/types/Calendar/Calendar.messages.d.ts +0 -20
- package/build/types/Calendar/Calendar.messages.d.ts.map +1 -1
- package/build/types/Calendar/DateHeader/DateHeader.d.ts +0 -2
- package/build/types/Calendar/DateHeader/DateHeader.d.ts.map +1 -1
- package/build/types/Calendar/DayCalendar/DayCalendar.d.ts +1 -5
- package/build/types/Calendar/DayCalendar/DayCalendar.d.ts.map +1 -1
- package/build/types/Calendar/DayCalendar/Table/DayCalendarTable.d.ts +0 -4
- package/build/types/Calendar/DayCalendar/Table/DayCalendarTable.d.ts.map +1 -1
- package/build/types/Calendar/MonthCalendar/MonthCalendar.d.ts +0 -1
- package/build/types/Calendar/MonthCalendar/MonthCalendar.d.ts.map +1 -1
- package/build/types/Calendar/MonthCalendar/Table/MonthCalendarTable.d.ts +1 -2
- package/build/types/Calendar/MonthCalendar/Table/MonthCalendarTable.d.ts.map +1 -1
- package/build/types/Calendar/YearCalendar/Table/YearCalendarTable.d.ts +1 -2
- package/build/types/Calendar/YearCalendar/Table/YearCalendarTable.d.ts.map +1 -1
- package/build/types/Calendar/YearCalendar/YearCalendar.d.ts +0 -1
- package/build/types/Calendar/YearCalendar/YearCalendar.d.ts.map +1 -1
- package/build/types/Calendar/index.d.ts +0 -1
- package/build/types/Calendar/index.d.ts.map +1 -1
- package/build/types/Calendar/{TableLink → tableLink}/TableLink.d.ts +1 -3
- package/build/types/Calendar/tableLink/TableLink.d.ts.map +1 -0
- package/build/types/Calendar/tableLink/index.d.ts.map +1 -0
- package/build/types/DateLookup/DateLookup.d.ts +5 -24
- package/build/types/DateLookup/DateLookup.d.ts.map +1 -1
- package/build/types/DateLookup/index.d.ts +0 -1
- package/build/types/DateLookup/index.d.ts.map +1 -1
- package/build/types/IconButton/IconButton.d.ts +1 -1
- package/build/types/Markup/Markup.d.ts +18 -0
- package/build/types/Markup/Markup.d.ts.map +1 -0
- package/build/types/Markup/Markup.types.d.ts +77 -0
- package/build/types/Markup/Markup.types.d.ts.map +1 -0
- package/build/types/Markup/_stories/Vulnerability/Vulnerability.d.ts +12 -0
- package/build/types/Markup/_stories/Vulnerability/Vulnerability.d.ts.map +1 -0
- package/build/types/Markup/constants.d.ts +20 -0
- package/build/types/Markup/constants.d.ts.map +1 -0
- package/build/types/Markup/index.d.ts +3 -0
- package/build/types/Markup/index.d.ts.map +1 -0
- package/build/types/Markup/utils/parseMarkup.d.ts +8 -0
- package/build/types/Markup/utils/parseMarkup.d.ts.map +1 -0
- package/build/types/Markup/utils/sanitise.d.ts +4 -0
- package/build/types/Markup/utils/sanitise.d.ts.map +1 -0
- package/build/types/Title/Title.d.ts +2 -2
- package/build/types/Upload/Steps/UploadImageStep/UploadImageStep.d.ts +1 -1
- package/build/types/UploadInput/UploadItem/UploadItemLink.d.ts +1 -1
- package/build/types/common/DateUtils/index.d.ts +0 -2
- package/build/types/common/DateUtils/index.d.ts.map +1 -1
- package/build/types/index.d.ts +4 -3
- package/build/types/index.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +0 -8
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Calendar/Calendar.css +37 -112
- package/src/Calendar/Calendar.less +35 -5
- package/src/Calendar/Calendar.messages.ts +0 -21
- package/src/Calendar/Calendar.test.tsx +27 -288
- package/src/Calendar/Calendar.tsx +19 -136
- package/src/Calendar/DateHeader/DateHeader.tsx +0 -6
- package/src/Calendar/DayCalendar/DayCalendar.tsx +1 -33
- package/src/Calendar/DayCalendar/Table/DayCalendarTable.tsx +28 -62
- package/src/Calendar/MonthCalendar/MonthCalendar.tsx +0 -8
- package/src/Calendar/MonthCalendar/Table/MonthCalendarTable.tsx +3 -15
- package/src/Calendar/YearCalendar/Table/YearCalendarTable.tsx +3 -15
- package/src/Calendar/YearCalendar/YearCalendar.tsx +0 -9
- package/src/Calendar/_stories/Calendar.story.tsx +4 -138
- package/src/Calendar/index.ts +0 -7
- package/src/Calendar/{TableLink → tableLink}/TableLink.tsx +14 -29
- package/src/DateLookup/DateLookup.test.tsx +37 -34
- package/src/DateLookup/DateLookup.tsx +13 -37
- package/src/DateLookup/_stories/DateLookup.story.tsx +2 -124
- package/src/DateLookup/index.ts +0 -6
- package/src/Markup/Markup.css +28 -0
- package/src/Markup/Markup.injection.test.tsx +163 -0
- package/src/Markup/Markup.less +29 -0
- package/src/Markup/Markup.test.tsx +463 -0
- package/src/Markup/Markup.tsx +169 -0
- package/src/Markup/Markup.types.ts +62 -0
- package/src/Markup/_stories/Markup.docs.mdx +75 -0
- package/src/Markup/_stories/Markup.security.docs.mdx +343 -0
- package/src/Markup/_stories/Markup.story.tsx +266 -0
- package/src/Markup/_stories/Vulnerability/Vulnerability.css +69 -0
- package/src/Markup/_stories/Vulnerability/Vulnerability.tsx +30 -0
- package/src/Markup/constants.ts +41 -0
- package/src/Markup/index.ts +2 -0
- package/src/Markup/utils/parseMarkup.test.ts +706 -0
- package/src/Markup/utils/parseMarkup.ts +234 -0
- package/src/Markup/utils/sanitise.test.ts +497 -0
- package/src/Markup/utils/sanitise.ts +133 -0
- package/src/common/DateUtils/index.ts +0 -2
- package/src/i18n/en.json +0 -4
- package/src/index.ts +4 -3
- package/src/main.css +78 -123
- package/src/main.less +1 -0
- package/build/Calendar/TableLink/TableLink.js.map +0 -1
- package/build/Calendar/TableLink/TableLink.mjs.map +0 -1
- package/build/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.js +0 -33
- package/build/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.js.map +0 -1
- package/build/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.mjs +0 -31
- package/build/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.mjs.map +0 -1
- package/build/common/DateUtils/isDateDisabled/isDateDisabled.js +0 -40
- package/build/common/DateUtils/isDateDisabled/isDateDisabled.js.map +0 -1
- package/build/common/DateUtils/isDateDisabled/isDateDisabled.mjs +0 -38
- package/build/common/DateUtils/isDateDisabled/isDateDisabled.mjs.map +0 -1
- package/build/styles/Calendar/TableLink/TableLink.css +0 -115
- package/build/types/Calendar/Calendar.types.d.ts +0 -32
- package/build/types/Calendar/Calendar.types.d.ts.map +0 -1
- package/build/types/Calendar/TableLink/TableLink.d.ts.map +0 -1
- package/build/types/Calendar/TableLink/index.d.ts.map +0 -1
- package/build/types/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.d.ts +0 -3
- package/build/types/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.d.ts.map +0 -1
- package/build/types/common/DateUtils/isDateDisabled/isDateDisabled.d.ts +0 -3
- package/build/types/common/DateUtils/isDateDisabled/isDateDisabled.d.ts.map +0 -1
- package/src/Calendar/Calendar.disabledDates.test.tsx +0 -518
- package/src/Calendar/Calendar.types.ts +0 -35
- package/src/Calendar/TableLink/TableLink.css +0 -115
- package/src/Calendar/TableLink/TableLink.less +0 -68
- package/src/Calendar/_stories/Calendar.accessibility.docs.mdx +0 -118
- package/src/Calendar/_stories/Calendar.test.story.tsx +0 -74
- package/src/DateLookup/DateLookup.disabledDates.test.tsx +0 -293
- package/src/DateLookup/_stories/DateLookup.accessibility.docs.mdx +0 -108
- package/src/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.test.ts +0 -98
- package/src/common/DateUtils/hasDisabledDatesInMonth/hasDisabledDatesInMonth.ts +0 -45
- package/src/common/DateUtils/isDateDisabled/isDateDisabled.test.ts +0 -169
- package/src/common/DateUtils/isDateDisabled/isDateDisabled.ts +0 -59
- /package/build/types/Calendar/{TableLink → tableLink}/index.d.ts +0 -0
- /package/src/Calendar/{TableLink → tableLink}/index.ts +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { mockMatchMedia, render, screen, userEvent } from '../test-utils';
|
|
2
2
|
import Calendar from './Calendar';
|
|
3
|
-
import type { DisabledRules } from './Calendar.types';
|
|
4
3
|
|
|
5
4
|
mockMatchMedia();
|
|
6
5
|
|
|
@@ -16,159 +15,35 @@ describe('Calendar', () => {
|
|
|
16
15
|
['{ArrowUp}', -7],
|
|
17
16
|
['{ArrowDown}', +7],
|
|
18
17
|
])("handles '%s' to step %d day(s)", async (text: string, step: number) => {
|
|
19
|
-
const
|
|
20
|
-
render(<Calendar value={initialValue}
|
|
18
|
+
const handleChange = jest.fn();
|
|
19
|
+
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
21
20
|
|
|
22
21
|
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
23
22
|
await user.keyboard(text);
|
|
24
23
|
|
|
25
24
|
const expected = new Date(initialValue);
|
|
26
25
|
expected.setDate(initialValue.getDate() + step);
|
|
27
|
-
expect(
|
|
26
|
+
expect(handleChange).toHaveBeenCalledWith(expected);
|
|
28
27
|
});
|
|
29
28
|
|
|
30
29
|
it('selects a day on click', async () => {
|
|
31
|
-
const handleDateFocus = jest.fn();
|
|
32
|
-
render(<Calendar value={initialValue} onDateFocus={handleDateFocus} />);
|
|
33
|
-
|
|
34
|
-
await user.click(screen.getByText('15'));
|
|
35
|
-
|
|
36
|
-
expect(handleDateFocus).toHaveBeenCalledWith(new Date(2000, 0, 15), { isEnabled: true });
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('fires both onDateFocus and onChange when clicking a day', async () => {
|
|
40
|
-
const handleDateFocus = jest.fn();
|
|
41
30
|
const handleChange = jest.fn();
|
|
42
|
-
render(
|
|
43
|
-
<Calendar value={initialValue} onDateFocus={handleDateFocus} onChange={handleChange} />,
|
|
44
|
-
);
|
|
31
|
+
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
45
32
|
|
|
46
33
|
await user.click(screen.getByText('15'));
|
|
47
34
|
|
|
48
|
-
expect(handleDateFocus).toHaveBeenCalledWith(new Date(2000, 0, 15), { isEnabled: true });
|
|
49
35
|
expect(handleChange).toHaveBeenCalledWith(new Date(2000, 0, 15));
|
|
50
36
|
});
|
|
51
37
|
|
|
52
|
-
it('
|
|
38
|
+
it('calls onSelect instead of onChange when clicking a day', async () => {
|
|
53
39
|
const handleChange = jest.fn();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
57
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
58
|
-
|
|
59
|
-
await user.keyboard('{ArrowRight}');
|
|
60
|
-
|
|
61
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('fires onChange when Enter is pressed on focused date', async () => {
|
|
65
|
-
const handleChange = jest.fn();
|
|
66
|
-
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
67
|
-
|
|
68
|
-
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
69
|
-
await user.keyboard('{ArrowRight}');
|
|
70
|
-
await user.keyboard('{Enter}');
|
|
71
|
-
|
|
72
|
-
const expected = new Date(initialValue);
|
|
73
|
-
expected.setDate(initialValue.getDate() + 1);
|
|
74
|
-
expect(handleChange).toHaveBeenCalledWith(expected);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('does not fire onChange when Enter is pressed on a disabled focused date', async () => {
|
|
78
|
-
const handleChange = jest.fn();
|
|
79
|
-
const disabledRules: DisabledRules = {
|
|
80
|
-
weekdays: ['sat', 'sun'],
|
|
81
|
-
reason: 'Closed on weekends.',
|
|
82
|
-
};
|
|
83
|
-
render(
|
|
84
|
-
<Calendar
|
|
85
|
-
value={new Date(2000, 0, 7)}
|
|
86
|
-
disabledRules={disabledRules}
|
|
87
|
-
onChange={handleChange}
|
|
88
|
-
/>,
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
92
|
-
// Click on selected day (Friday) fires onChange once
|
|
93
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
94
|
-
|
|
95
|
-
// ArrowRight from Jan 7 (Friday) → Jan 8 (Saturday = disabled)
|
|
96
|
-
await user.keyboard('{ArrowRight}');
|
|
97
|
-
await user.keyboard('{Enter}');
|
|
98
|
-
|
|
99
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('fires onDateFocus with isEnabled: false when Enter is pressed on a disabled focused date', async () => {
|
|
103
|
-
const handleDateFocus = jest.fn();
|
|
104
|
-
const disabledRules: DisabledRules = {
|
|
105
|
-
weekdays: ['sat', 'sun'],
|
|
106
|
-
reason: 'Closed on weekends.',
|
|
107
|
-
};
|
|
108
|
-
render(
|
|
109
|
-
<Calendar
|
|
110
|
-
value={new Date(2000, 0, 7)}
|
|
111
|
-
disabledRules={disabledRules}
|
|
112
|
-
onDateFocus={handleDateFocus}
|
|
113
|
-
/>,
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
117
|
-
handleDateFocus.mockClear();
|
|
118
|
-
|
|
119
|
-
// ArrowRight from Jan 7 (Friday) → Jan 8 (Saturday = disabled)
|
|
120
|
-
await user.keyboard('{ArrowRight}');
|
|
121
|
-
handleDateFocus.mockClear();
|
|
122
|
-
|
|
123
|
-
await user.keyboard('{Enter}');
|
|
124
|
-
|
|
125
|
-
expect(handleDateFocus).toHaveBeenCalledWith(new Date(2000, 0, 8), { isEnabled: false });
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('fires onChange when Space is pressed on a focused enabled date', async () => {
|
|
129
|
-
const handleChange = jest.fn();
|
|
130
|
-
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
131
|
-
|
|
132
|
-
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
133
|
-
await user.keyboard('{ArrowRight}');
|
|
134
|
-
await user.keyboard(' ');
|
|
135
|
-
|
|
136
|
-
const expected = new Date(initialValue);
|
|
137
|
-
expected.setDate(initialValue.getDate() + 1);
|
|
138
|
-
expect(handleChange).toHaveBeenCalledWith(expected);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('does not fire onChange when Space is pressed on a disabled focused date', async () => {
|
|
142
|
-
const handleChange = jest.fn();
|
|
143
|
-
const disabledRules: DisabledRules = {
|
|
144
|
-
weekdays: ['sat', 'sun'],
|
|
145
|
-
reason: 'Closed on weekends.',
|
|
146
|
-
};
|
|
147
|
-
render(
|
|
148
|
-
<Calendar
|
|
149
|
-
value={new Date(2000, 0, 7)}
|
|
150
|
-
disabledRules={disabledRules}
|
|
151
|
-
onChange={handleChange}
|
|
152
|
-
/>,
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
156
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
157
|
-
|
|
158
|
-
// ArrowRight from Jan 7 (Friday) → Jan 8 (Saturday = disabled)
|
|
159
|
-
await user.keyboard('{ArrowRight}');
|
|
160
|
-
await user.keyboard(' ');
|
|
161
|
-
|
|
162
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('renders and remains interactive without onDateFocus', async () => {
|
|
166
|
-
const handleChange = jest.fn();
|
|
167
|
-
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
40
|
+
const handleSelect = jest.fn();
|
|
41
|
+
render(<Calendar value={initialValue} onChange={handleChange} onSelect={handleSelect} />);
|
|
168
42
|
|
|
169
43
|
await user.click(screen.getByText('15'));
|
|
170
44
|
|
|
171
|
-
expect(
|
|
45
|
+
expect(handleSelect).toHaveBeenCalledWith(new Date(2000, 0, 15));
|
|
46
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
172
47
|
});
|
|
173
48
|
});
|
|
174
49
|
|
|
@@ -179,15 +54,15 @@ describe('Calendar', () => {
|
|
|
179
54
|
['{ArrowUp}', -4],
|
|
180
55
|
['{ArrowDown}', +4],
|
|
181
56
|
])("handles '%s' to step %d year(s)", async (text: string, step: number) => {
|
|
182
|
-
const
|
|
183
|
-
render(<Calendar value={initialValue}
|
|
57
|
+
const handleChange = jest.fn();
|
|
58
|
+
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
184
59
|
|
|
185
60
|
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
186
61
|
await user.keyboard(text);
|
|
187
62
|
|
|
188
63
|
const expected = new Date(initialValue);
|
|
189
64
|
expected.setFullYear(initialValue.getFullYear() + step);
|
|
190
|
-
expect(
|
|
65
|
+
expect(handleChange).toHaveBeenCalledWith(expected);
|
|
191
66
|
});
|
|
192
67
|
});
|
|
193
68
|
|
|
@@ -198,8 +73,8 @@ describe('Calendar', () => {
|
|
|
198
73
|
['{ArrowUp}', -4],
|
|
199
74
|
['{ArrowDown}', +4],
|
|
200
75
|
])("handles '%s' to step %d month(s)", async (text: string, step: number) => {
|
|
201
|
-
const
|
|
202
|
-
render(<Calendar value={initialValue}
|
|
76
|
+
const handleChange = jest.fn();
|
|
77
|
+
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
203
78
|
|
|
204
79
|
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
205
80
|
await user.keyboard(' ');
|
|
@@ -207,166 +82,48 @@ describe('Calendar', () => {
|
|
|
207
82
|
|
|
208
83
|
const expected = new Date(initialValue);
|
|
209
84
|
expected.setMonth(initialValue.getMonth() + step);
|
|
210
|
-
expect(
|
|
85
|
+
expect(handleChange).toHaveBeenCalledWith(expected);
|
|
211
86
|
});
|
|
212
87
|
});
|
|
213
88
|
|
|
214
89
|
describe('min/max clamping', () => {
|
|
215
|
-
it('limits
|
|
90
|
+
it('limits navigation to min value', async () => {
|
|
216
91
|
const min = new Date(initialValue);
|
|
217
92
|
min.setDate(min.getDate() - 1);
|
|
218
|
-
const
|
|
219
|
-
render(<Calendar value={initialValue} min={min}
|
|
93
|
+
const handleChange = jest.fn();
|
|
94
|
+
render(<Calendar value={initialValue} min={min} onChange={handleChange} />);
|
|
220
95
|
|
|
221
96
|
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
222
97
|
await user.keyboard('{ArrowLeft}{ArrowLeft}');
|
|
223
98
|
|
|
224
|
-
expect(
|
|
99
|
+
expect(handleChange).toHaveBeenLastCalledWith(min);
|
|
225
100
|
});
|
|
226
101
|
|
|
227
|
-
it('limits
|
|
102
|
+
it('limits navigation to max value', async () => {
|
|
228
103
|
const max = new Date(initialValue);
|
|
229
104
|
max.setDate(max.getDate() + 1);
|
|
230
|
-
const
|
|
231
|
-
render(<Calendar value={initialValue} max={max}
|
|
105
|
+
const handleChange = jest.fn();
|
|
106
|
+
render(<Calendar value={initialValue} max={max} onChange={handleChange} />);
|
|
232
107
|
|
|
233
108
|
await user.click(screen.getByRole('button', { name: /selected day/iu }));
|
|
234
109
|
await user.keyboard('{ArrowRight}{ArrowRight}');
|
|
235
110
|
|
|
236
|
-
expect(
|
|
111
|
+
expect(handleChange).toHaveBeenLastCalledWith(max);
|
|
237
112
|
});
|
|
238
113
|
|
|
239
114
|
it('clamps value to range when value is outside min/max', () => {
|
|
240
115
|
const min = new Date(2000, 0, 5);
|
|
241
116
|
const max = new Date(2000, 0, 20);
|
|
242
|
-
const
|
|
243
|
-
render(<Calendar value={initialValue} min={min} max={max}
|
|
244
|
-
|
|
245
|
-
expect(handleDateFocus).toHaveBeenCalledWith(min, { isEnabled: true });
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('navigation button boundary disabling', () => {
|
|
250
|
-
describe('day view — previous/next month', () => {
|
|
251
|
-
it('disables previous month button when min is in the current view month', () => {
|
|
252
|
-
render(<Calendar value={new Date(2000, 3, 15)} min={new Date(2000, 3, 1)} />);
|
|
253
|
-
expect(screen.getByRole('button', { name: /previous month/iu })).toBeDisabled();
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('disables next month button when max is in the current view month', () => {
|
|
257
|
-
render(<Calendar value={new Date(2000, 3, 15)} max={new Date(2000, 3, 30)} />);
|
|
258
|
-
expect(screen.getByRole('button', { name: /next month/iu })).toBeDisabled();
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('does not disable month buttons when min/max are in adjacent months', () => {
|
|
262
|
-
render(
|
|
263
|
-
<Calendar
|
|
264
|
-
value={new Date(2000, 3, 15)}
|
|
265
|
-
min={new Date(2000, 2, 1)}
|
|
266
|
-
max={new Date(2000, 4, 30)}
|
|
267
|
-
/>,
|
|
268
|
-
);
|
|
269
|
-
expect(screen.getByRole('button', { name: /previous month/iu })).toBeEnabled();
|
|
270
|
-
expect(screen.getByRole('button', { name: /next month/iu })).toBeEnabled();
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it('does not disable month buttons when no min/max is set', () => {
|
|
274
|
-
render(<Calendar value={new Date(2000, 3, 15)} />);
|
|
275
|
-
expect(screen.getByRole('button', { name: /previous month/iu })).toBeEnabled();
|
|
276
|
-
expect(screen.getByRole('button', { name: /next month/iu })).toBeEnabled();
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('disables previous month button when min is in January and view is January', () => {
|
|
280
|
-
// Edge case: month wraps to previous year
|
|
281
|
-
render(<Calendar value={new Date(2000, 0, 15)} min={new Date(2000, 0, 1)} />);
|
|
282
|
-
expect(screen.getByRole('button', { name: /previous month/iu })).toBeDisabled();
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it('disables next month button when max is in December and view is December', () => {
|
|
286
|
-
// Edge case: month wraps to next year
|
|
287
|
-
render(<Calendar value={new Date(2000, 11, 15)} max={new Date(2000, 11, 31)} />);
|
|
288
|
-
expect(screen.getByRole('button', { name: /next month/iu })).toBeDisabled();
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
describe('month view — previous/next year', () => {
|
|
293
|
-
it('disables previous year button when min year equals view year', async () => {
|
|
294
|
-
render(<Calendar value={new Date(2000, 3, 15)} min={new Date(2000, 0, 1)} />);
|
|
295
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
296
|
-
await user.click(screen.getByRole('button', { name: /2000, selected year/iu }));
|
|
297
|
-
expect(screen.getByRole('button', { name: /previous year/iu })).toBeDisabled();
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it('disables next year button when max year equals view year', async () => {
|
|
301
|
-
render(<Calendar value={new Date(2000, 3, 15)} max={new Date(2000, 11, 31)} />);
|
|
302
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
303
|
-
await user.click(screen.getByRole('button', { name: /2000, selected year/iu }));
|
|
304
|
-
expect(screen.getByRole('button', { name: /next year/iu })).toBeDisabled();
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
it('does not disable year buttons when min/max are in adjacent years', async () => {
|
|
308
|
-
render(
|
|
309
|
-
<Calendar
|
|
310
|
-
value={new Date(2000, 3, 15)}
|
|
311
|
-
min={new Date(1999, 0, 1)}
|
|
312
|
-
max={new Date(2001, 11, 31)}
|
|
313
|
-
/>,
|
|
314
|
-
);
|
|
315
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
316
|
-
await user.click(screen.getByRole('button', { name: /2000, selected year/iu }));
|
|
317
|
-
expect(screen.getByRole('button', { name: /previous year/iu })).toBeEnabled();
|
|
318
|
-
expect(screen.getByRole('button', { name: /next year/iu })).toBeEnabled();
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
it('does not disable year buttons when no min/max is set', async () => {
|
|
322
|
-
render(<Calendar value={new Date(2000, 3, 15)} />);
|
|
323
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
324
|
-
await user.click(screen.getByRole('button', { name: /2000, selected year/iu }));
|
|
325
|
-
expect(screen.getByRole('button', { name: /previous year/iu })).toBeEnabled();
|
|
326
|
-
expect(screen.getByRole('button', { name: /next year/iu })).toBeEnabled();
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
describe('year view — previous/next 20 years', () => {
|
|
331
|
-
it('disables previous 20-year button when min falls in the current block', async () => {
|
|
332
|
-
// value is 2000, block is 2000–2019, min is 2005 → previous block (1980–1999) is entirely before min
|
|
333
|
-
render(<Calendar value={new Date(2005, 0, 1)} min={new Date(2005, 0, 1)} />);
|
|
334
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
335
|
-
expect(screen.getByRole('button', { name: /previous 20 years/iu })).toBeDisabled();
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
it('disables next 20-year button when max falls in the current block', async () => {
|
|
339
|
-
// value is 2000, block is 2000–2019, max is 2015 → next block (2020–2039) is entirely after max
|
|
340
|
-
render(<Calendar value={new Date(2000, 0, 1)} max={new Date(2015, 11, 31)} />);
|
|
341
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
342
|
-
expect(screen.getByRole('button', { name: /next 20 years/iu })).toBeDisabled();
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
it('does not disable 20-year buttons when min/max span multiple blocks', async () => {
|
|
346
|
-
render(
|
|
347
|
-
<Calendar
|
|
348
|
-
value={new Date(2000, 0, 1)}
|
|
349
|
-
min={new Date(1985, 0, 1)}
|
|
350
|
-
max={new Date(2025, 11, 31)}
|
|
351
|
-
/>,
|
|
352
|
-
);
|
|
353
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
354
|
-
expect(screen.getByRole('button', { name: /previous 20 years/iu })).toBeEnabled();
|
|
355
|
-
expect(screen.getByRole('button', { name: /next 20 years/iu })).toBeEnabled();
|
|
356
|
-
});
|
|
117
|
+
const handleChange = jest.fn();
|
|
118
|
+
render(<Calendar value={initialValue} min={min} max={max} onChange={handleChange} />);
|
|
357
119
|
|
|
358
|
-
|
|
359
|
-
render(<Calendar value={new Date(2000, 0, 1)} />);
|
|
360
|
-
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
361
|
-
expect(screen.getByRole('button', { name: /previous 20 years/iu })).toBeEnabled();
|
|
362
|
-
expect(screen.getByRole('button', { name: /next 20 years/iu })).toBeEnabled();
|
|
363
|
-
});
|
|
120
|
+
expect(handleChange).toHaveBeenCalledWith(min);
|
|
364
121
|
});
|
|
365
122
|
});
|
|
366
123
|
|
|
367
124
|
describe('view switching', () => {
|
|
368
125
|
it('switches to year view and back to day view', async () => {
|
|
369
|
-
render(<Calendar value={initialValue} />);
|
|
126
|
+
render(<Calendar value={initialValue} onChange={jest.fn()} />);
|
|
370
127
|
|
|
371
128
|
await user.click(screen.getByRole('button', { name: /year view/iu }));
|
|
372
129
|
expect(screen.getByRole('button', { name: /selected year/iu })).toBeInTheDocument();
|
|
@@ -377,23 +134,5 @@ describe('Calendar', () => {
|
|
|
377
134
|
await user.click(screen.getByRole('button', { name: /selected month/iu }));
|
|
378
135
|
expect(screen.getByRole('button', { name: /next month/iu })).toBeInTheDocument();
|
|
379
136
|
});
|
|
380
|
-
|
|
381
|
-
it('switches to year view when header button is activated with keyboard', async () => {
|
|
382
|
-
const handleChange = jest.fn();
|
|
383
|
-
render(<Calendar value={initialValue} onChange={handleChange} />);
|
|
384
|
-
|
|
385
|
-
// Tab through to the year view header button
|
|
386
|
-
const yearViewButton = screen.getByRole('button', { name: /year view/iu });
|
|
387
|
-
await user.tab();
|
|
388
|
-
while (document.activeElement !== yearViewButton) {
|
|
389
|
-
await user.tab();
|
|
390
|
-
}
|
|
391
|
-
expect(yearViewButton).toHaveFocus();
|
|
392
|
-
|
|
393
|
-
await user.keyboard('{Enter}');
|
|
394
|
-
|
|
395
|
-
expect(screen.getByRole('button', { name: /selected year/iu })).toBeInTheDocument();
|
|
396
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
397
|
-
});
|
|
398
137
|
});
|
|
399
138
|
});
|
|
@@ -1,88 +1,40 @@
|
|
|
1
|
-
import { useState, useCallback, useEffect,
|
|
2
|
-
import { useIntl } from 'react-intl';
|
|
3
|
-
import { formatDate } from '@transferwise/formatting';
|
|
1
|
+
import { useState, useCallback, useEffect, KeyboardEvent } from 'react';
|
|
4
2
|
|
|
5
3
|
import { MonthFormat } from '../common';
|
|
6
|
-
import {
|
|
7
|
-
isWithinRange,
|
|
8
|
-
moveToWithinRange,
|
|
9
|
-
returnDateView,
|
|
10
|
-
isDateDisabled,
|
|
11
|
-
hasDisabledDatesInMonth,
|
|
12
|
-
} from '../common/DateUtils';
|
|
13
|
-
import { InlinePrompt } from '../Prompt/InlinePrompt';
|
|
14
|
-
import type { DateChangeMeta, DisabledRules } from './Calendar.types';
|
|
4
|
+
import { isWithinRange, moveToWithinRange, returnDateView } from '../common/DateUtils';
|
|
15
5
|
import DayCalendar from './DayCalendar';
|
|
16
6
|
import { getStartOfDay } from './GetStartOfDay';
|
|
17
|
-
import messages from './Calendar.messages';
|
|
18
7
|
import MonthCalendar from './MonthCalendar';
|
|
19
8
|
import YearCalendar from './YearCalendar';
|
|
20
9
|
|
|
21
10
|
export interface CalendarProps {
|
|
22
|
-
/** The currently selected date, or `null` for no selection. */
|
|
23
11
|
value: Date | null;
|
|
24
|
-
/** Earliest selectable date (inclusive). Dates before this are interactive but not selectable, and show a boundary prompt. */
|
|
25
12
|
min?: Date | null;
|
|
26
|
-
/** Latest selectable date (inclusive). Dates after this are interactive but not selectable, and show a boundary prompt. */
|
|
27
13
|
max?: Date | null;
|
|
28
|
-
/** Month name format in the header. Defaults to `'long'` (e.g. "January"). */
|
|
29
14
|
monthFormat?: `${MonthFormat}`;
|
|
30
|
-
/** Placeholder text shown in the month/year cells when no date is selected. */
|
|
31
15
|
placeholder?: string;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/** Called whenever the focused date changes — including disabled and out-of-range dates. `meta.isEnabled` is `false` when the date is not selectable. */
|
|
35
|
-
onDateFocus?: (date: Date | null, meta: DateChangeMeta) => void;
|
|
36
|
-
/** Called when a date is confirmed (click or Enter). Only fires for enabled dates. */
|
|
37
|
-
onChange?: (date: Date | null) => void;
|
|
16
|
+
onChange: (date: Date | null) => void;
|
|
17
|
+
onSelect?: (date: Date) => void;
|
|
38
18
|
}
|
|
39
19
|
|
|
40
|
-
/**
|
|
41
|
-
* Inline calendar for selecting a single date. Powers [DateLookup](?path=/docs/forms-datelookup--docs).
|
|
42
|
-
*/
|
|
43
20
|
const Calendar = ({
|
|
44
21
|
value,
|
|
45
22
|
min: minProp = null,
|
|
46
23
|
max: maxProp = null,
|
|
47
24
|
monthFormat = MonthFormat.LONG,
|
|
48
25
|
placeholder,
|
|
49
|
-
disabledRules,
|
|
50
|
-
onDateFocus,
|
|
51
26
|
onChange,
|
|
27
|
+
onSelect,
|
|
52
28
|
}: CalendarProps) => {
|
|
53
|
-
const intl = useIntl();
|
|
54
29
|
const selectedDate = getStartOfDay(value);
|
|
55
30
|
const min = getStartOfDay(minProp);
|
|
56
31
|
const max = getStartOfDay(maxProp);
|
|
57
|
-
const disabledReasonId = useId();
|
|
58
|
-
const disabledRulesRef = useRef(disabledRules);
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
disabledRulesRef.current = disabledRules;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const [focusedDate, setFocusedDate] = useState<Date | null>(selectedDate);
|
|
64
|
-
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
67
|
-
setFocusedDate(selectedDate);
|
|
68
|
-
}, [selectedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
69
|
-
|
|
70
|
-
const checkIsEnabled = (date: Date | null) => {
|
|
71
|
-
if (!date) return true;
|
|
72
|
-
return isWithinRange(date, min, max) && !isDateDisabled(date, disabledRulesRef.current);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const focusedDateDisabled = focusedDate
|
|
76
|
-
? !isWithinRange(focusedDate, min, max) || isDateDisabled(focusedDate, disabledRules)
|
|
77
|
-
: false;
|
|
78
32
|
|
|
79
33
|
useEffect(() => {
|
|
80
34
|
if (selectedDate && !isWithinRange(selectedDate, min, max)) {
|
|
81
|
-
|
|
82
|
-
setFocusedDate(clamped); // eslint-disable-line react-hooks/set-state-in-effect
|
|
83
|
-
onDateFocus?.(clamped, { isEnabled: checkIsEnabled(clamped) });
|
|
35
|
+
onChange(moveToWithinRange(selectedDate, min, max));
|
|
84
36
|
}
|
|
85
|
-
}, [selectedDate?.getTime(), min?.getTime(), max?.getTime(),
|
|
37
|
+
}, [selectedDate?.getTime(), min?.getTime(), max?.getTime(), onChange]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
86
38
|
|
|
87
39
|
const dateView = returnDateView(selectedDate, min, max);
|
|
88
40
|
const [viewMonth, setViewMonth] = useState(dateView.getMonth());
|
|
@@ -97,14 +49,6 @@ const Calendar = ({
|
|
|
97
49
|
setViewYear(view.getFullYear());
|
|
98
50
|
}, [selectedDate?.getTime(), min?.getTime(), max?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
99
51
|
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
if (focusedDate) {
|
|
102
|
-
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
103
|
-
setViewMonth(focusedDate.getMonth());
|
|
104
|
-
setViewYear(focusedDate.getFullYear());
|
|
105
|
-
}
|
|
106
|
-
}, [focusedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
107
|
-
|
|
108
52
|
const handleViewDateUpdate = useCallback(
|
|
109
53
|
// eslint-disable-next-line react-hooks/preserve-manual-memoization
|
|
110
54
|
({ month, year }: { month?: number; year?: number }) => {
|
|
@@ -120,36 +64,33 @@ const Calendar = ({
|
|
|
120
64
|
|
|
121
65
|
const handleSelectedDateUpdate = useCallback(
|
|
122
66
|
(date: Date) => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (isEnabled && onChange) {
|
|
67
|
+
if (onSelect) {
|
|
68
|
+
onSelect(date);
|
|
69
|
+
} else {
|
|
127
70
|
onChange(date);
|
|
128
71
|
}
|
|
129
72
|
},
|
|
130
|
-
[
|
|
73
|
+
[onChange, onSelect],
|
|
131
74
|
);
|
|
132
75
|
|
|
133
76
|
const adjustDate = useCallback(
|
|
134
77
|
(daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {
|
|
135
|
-
const base = focusedDate ?? selectedDate;
|
|
136
78
|
let date: Date | null;
|
|
137
|
-
if (
|
|
79
|
+
if (selectedDate) {
|
|
138
80
|
date = new Date(
|
|
139
|
-
mode === 'year' ?
|
|
140
|
-
mode === 'month' ?
|
|
141
|
-
mode === 'day' ?
|
|
81
|
+
mode === 'year' ? selectedDate.getFullYear() + yearsToAdd : selectedDate.getFullYear(),
|
|
82
|
+
mode === 'month' ? selectedDate.getMonth() + monthsToAdd : selectedDate.getMonth(),
|
|
83
|
+
mode === 'day' ? selectedDate.getDate() + daysToAdd : selectedDate.getDate(),
|
|
142
84
|
);
|
|
143
85
|
} else {
|
|
144
86
|
date = getStartOfDay(new Date());
|
|
145
87
|
}
|
|
146
88
|
date &&= moveToWithinRange(date, min, max);
|
|
147
|
-
if (date?.getTime() !==
|
|
148
|
-
|
|
149
|
-
onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });
|
|
89
|
+
if (date?.getTime() !== selectedDate?.getTime()) {
|
|
90
|
+
onChange(date);
|
|
150
91
|
}
|
|
151
92
|
},
|
|
152
|
-
[
|
|
93
|
+
[selectedDate, min, max, mode, onChange],
|
|
153
94
|
);
|
|
154
95
|
|
|
155
96
|
const handleKeyDown = useCallback(
|
|
@@ -171,70 +112,24 @@ const Calendar = ({
|
|
|
171
112
|
adjustDate(7, 4, 4);
|
|
172
113
|
event.preventDefault();
|
|
173
114
|
break;
|
|
174
|
-
case 'Enter':
|
|
175
|
-
case ' ':
|
|
176
|
-
if (
|
|
177
|
-
mode === 'day' &&
|
|
178
|
-
focusedDate &&
|
|
179
|
-
(event.target as HTMLElement).hasAttribute('data-calendar-cell')
|
|
180
|
-
) {
|
|
181
|
-
handleSelectedDateUpdate(focusedDate);
|
|
182
|
-
event.preventDefault();
|
|
183
|
-
}
|
|
184
|
-
break;
|
|
185
115
|
default:
|
|
186
116
|
break;
|
|
187
117
|
}
|
|
188
118
|
},
|
|
189
|
-
[adjustDate
|
|
119
|
+
[adjustDate],
|
|
190
120
|
);
|
|
191
121
|
|
|
192
|
-
const focusedDateOutOfRange = focusedDate ? !isWithinRange(focusedDate, min, max) : false;
|
|
193
|
-
|
|
194
|
-
const formatDateForPrompt = (date: Date) =>
|
|
195
|
-
formatDate(date, intl.locale, { day: 'numeric', month: 'long', year: 'numeric' });
|
|
196
|
-
|
|
197
|
-
const outOfRangePromptText =
|
|
198
|
-
min && max
|
|
199
|
-
? intl.formatMessage(messages.outOfRangeBetween, {
|
|
200
|
-
min: formatDateForPrompt(min),
|
|
201
|
-
max: formatDateForPrompt(max),
|
|
202
|
-
})
|
|
203
|
-
: min
|
|
204
|
-
? intl.formatMessage(messages.outOfRangeAfter, { min: formatDateForPrompt(min) })
|
|
205
|
-
: max
|
|
206
|
-
? intl.formatMessage(messages.outOfRangeBefore, { max: formatDateForPrompt(max) })
|
|
207
|
-
: '';
|
|
208
|
-
|
|
209
|
-
const hasOutOfRangeDates = mode === 'day' && !!(min || max);
|
|
210
|
-
const showRulesPrompt =
|
|
211
|
-
mode === 'day' &&
|
|
212
|
-
!!disabledRules &&
|
|
213
|
-
hasDisabledDatesInMonth(viewMonth, viewYear, disabledRules, min, max);
|
|
214
|
-
const showOutOfRangePrompt = mode === 'day' && focusedDateOutOfRange;
|
|
215
|
-
const showPrompt = hasOutOfRangeDates || showRulesPrompt;
|
|
216
|
-
|
|
217
|
-
const promptText = showOutOfRangePrompt
|
|
218
|
-
? outOfRangePromptText
|
|
219
|
-
: (disabledRules?.reason ?? outOfRangePromptText);
|
|
220
|
-
const promptSentiment = showOutOfRangePrompt || focusedDateDisabled ? 'negative' : 'neutral';
|
|
221
|
-
const promptClassName =
|
|
222
|
-
showOutOfRangePrompt || (showRulesPrompt && !showOutOfRangePrompt) ? 'm-t-1' : 'sr-only';
|
|
223
|
-
|
|
224
122
|
return (
|
|
225
123
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
226
124
|
<div onKeyDown={handleKeyDown}>
|
|
227
125
|
{mode === 'day' && (
|
|
228
126
|
<DayCalendar
|
|
229
127
|
selectedDate={selectedDate}
|
|
230
|
-
focusedDate={focusedDate}
|
|
231
128
|
min={min}
|
|
232
129
|
max={max}
|
|
233
130
|
viewMonth={viewMonth}
|
|
234
131
|
viewYear={viewYear}
|
|
235
132
|
monthFormat={monthFormat}
|
|
236
|
-
disabledRules={disabledRules}
|
|
237
|
-
disabledReasonId={showPrompt ? disabledReasonId : undefined}
|
|
238
133
|
onSelect={handleSelectedDateUpdate}
|
|
239
134
|
onLabelClick={switchToYears}
|
|
240
135
|
onViewDateUpdate={handleViewDateUpdate}
|
|
@@ -243,7 +138,6 @@ const Calendar = ({
|
|
|
243
138
|
{mode === 'month' && (
|
|
244
139
|
<MonthCalendar
|
|
245
140
|
selectedDate={selectedDate}
|
|
246
|
-
focusedDate={focusedDate}
|
|
247
141
|
min={min}
|
|
248
142
|
max={max}
|
|
249
143
|
viewYear={viewYear}
|
|
@@ -256,7 +150,6 @@ const Calendar = ({
|
|
|
256
150
|
{mode === 'year' && (
|
|
257
151
|
<YearCalendar
|
|
258
152
|
selectedDate={selectedDate}
|
|
259
|
-
focusedDate={focusedDate}
|
|
260
153
|
min={min}
|
|
261
154
|
max={max}
|
|
262
155
|
viewYear={viewYear}
|
|
@@ -265,16 +158,6 @@ const Calendar = ({
|
|
|
265
158
|
onViewDateUpdate={handleViewDateUpdate}
|
|
266
159
|
/>
|
|
267
160
|
)}
|
|
268
|
-
{showPrompt && (
|
|
269
|
-
<InlinePrompt
|
|
270
|
-
sentiment={promptSentiment}
|
|
271
|
-
width="full"
|
|
272
|
-
id={disabledReasonId}
|
|
273
|
-
className={promptClassName}
|
|
274
|
-
>
|
|
275
|
-
{promptText}
|
|
276
|
-
</InlinePrompt>
|
|
277
|
-
)}
|
|
278
161
|
</div>
|
|
279
162
|
);
|
|
280
163
|
};
|