@uxf/datepicker 11.86.0 → 11.87.0

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.
@@ -32,6 +32,7 @@ exports.DateRangePickerContext = (0, react_1.createContext)({
32
32
  onDateFocus: () => undefined,
33
33
  onDateHover: () => undefined,
34
34
  onDateSelect: () => undefined,
35
+ onDatesSelect: () => undefined,
35
36
  onResetDates: () => undefined,
36
37
  unavailableDates: [],
37
38
  });
@@ -44,6 +44,7 @@ export interface UseDateRangePickerReturnType extends UseDatePickerNavigationRet
44
44
  onDateFocus: (date: Date) => void;
45
45
  onDateHover: (date: Date | null) => void;
46
46
  onDateSelect: (date: Date) => void;
47
+ onDatesSelect: (startDate: Date, endDate: Date | null) => void;
47
48
  onResetDates: () => void;
48
49
  preventScroll?: boolean;
49
50
  unavailableDates: Date[];
@@ -153,6 +153,28 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
153
153
  setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, date));
154
154
  }
155
155
  }
156
+ function onDatesSelect(start, end) {
157
+ if ((0, can_select_range_1.canSelectRange)({
158
+ minBookingDays,
159
+ exactMinBookingDays,
160
+ minBookingDate,
161
+ maxBookingDate,
162
+ isDateBlocked: disabledDatesByUser,
163
+ startDate: start,
164
+ endDate: end,
165
+ })) {
166
+ onDatesChange({
167
+ endDate: end,
168
+ startDate: start,
169
+ focusedInput: exports.START_DATE,
170
+ });
171
+ }
172
+ if (focusedInput !== exports.END_DATE &&
173
+ (!focusedDate || !(0, dayjs_en_1.dayjsEn)(start).isSame(focusedDate, "month")) &&
174
+ changeActiveMonthOnSelect) {
175
+ setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, start));
176
+ }
177
+ }
156
178
  // eslint-disable-next-line complexity
157
179
  function onDateHover(date) {
158
180
  if (!date) {
@@ -224,6 +246,7 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
224
246
  onDateFocus,
225
247
  onDateHover,
226
248
  onDateSelect,
249
+ onDatesSelect,
227
250
  onResetDates,
228
251
  unavailableDates: disabledDates,
229
252
  };
@@ -85,3 +85,173 @@ test("date select", () => {
85
85
  });
86
86
  expect(result.current.isDateSelected(BASE_DATE)).toBe(false);
87
87
  });
88
+ test("date range select - valid range", () => {
89
+ const { result: state } = (0, react_1.renderHook)(() => (0, react_2.useState)({ startDate: null, endDate: null, focusedInput: "startDate" }));
90
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
91
+ startDate: state.current[0].startDate,
92
+ endDate: state.current[0].endDate,
93
+ onDatesChange: (data) => state.current[1](data),
94
+ focusedInput: state.current[0].focusedInput,
95
+ minBookingDate: new Date("2020-01-01"),
96
+ }));
97
+ const START_DATE = new Date("2021-09-15");
98
+ const END_DATE = new Date("2021-09-20");
99
+ (0, react_1.act)(() => {
100
+ result.current.onDatesSelect(START_DATE, END_DATE);
101
+ rerender();
102
+ });
103
+ expect(result.current.isStartDate(START_DATE)).toBe(true);
104
+ expect(result.current.isEndDate(END_DATE)).toBe(true);
105
+ expect(result.current.isDateInsideRange(new Date("2021-09-17"))).toBe(true);
106
+ });
107
+ test("date range select - with null end date", () => {
108
+ const { result: state } = (0, react_1.renderHook)(() => (0, react_2.useState)({ startDate: null, endDate: null, focusedInput: "startDate" }));
109
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
110
+ startDate: state.current[0].startDate,
111
+ endDate: state.current[0].endDate,
112
+ onDatesChange: (data) => state.current[1](data),
113
+ focusedInput: state.current[0].focusedInput,
114
+ minBookingDate: new Date("2020-01-01"),
115
+ }));
116
+ const START_DATE = new Date("2021-09-15");
117
+ (0, react_1.act)(() => {
118
+ result.current.onDatesSelect(START_DATE, null);
119
+ rerender();
120
+ });
121
+ expect(result.current.isStartDate(START_DATE)).toBe(true);
122
+ expect(state.current[0].endDate).toBe(null);
123
+ });
124
+ test("date range select - with minBookingDays", () => {
125
+ const { result: state } = (0, react_1.renderHook)(() => (0, react_2.useState)({ startDate: null, endDate: null, focusedInput: "startDate" }));
126
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
127
+ startDate: state.current[0].startDate,
128
+ endDate: state.current[0].endDate,
129
+ onDatesChange: (data) => state.current[1](data),
130
+ focusedInput: state.current[0].focusedInput,
131
+ minBookingDate: new Date("2020-01-01"),
132
+ minBookingDays: 3,
133
+ }));
134
+ const START_DATE = new Date("2021-09-15");
135
+ const END_DATE = new Date("2021-09-17");
136
+ (0, react_1.act)(() => {
137
+ result.current.onDatesSelect(START_DATE, END_DATE);
138
+ rerender();
139
+ });
140
+ expect(result.current.isStartDate(START_DATE)).toBe(true);
141
+ expect(result.current.isEndDate(END_DATE)).toBe(true);
142
+ });
143
+ test("date range select - invalid range with minBookingDays", () => {
144
+ const onDatesChange = jest.fn();
145
+ const { result } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
146
+ startDate: null,
147
+ endDate: null,
148
+ onDatesChange,
149
+ focusedInput: "startDate",
150
+ minBookingDate: new Date("2020-01-01"),
151
+ minBookingDays: 5,
152
+ }));
153
+ const START_DATE = new Date("2021-09-15");
154
+ const END_DATE = new Date("2021-09-17"); // Only 3 days, but minBookingDays is 5
155
+ (0, react_1.act)(() => {
156
+ result.current.onDatesSelect(START_DATE, END_DATE);
157
+ });
158
+ // onDatesChange should not be called with invalid range
159
+ expect(onDatesChange).not.toHaveBeenCalled();
160
+ });
161
+ test("date range select - with exactMinBookingDays", () => {
162
+ const { result: state } = (0, react_1.renderHook)(() => (0, react_2.useState)({ startDate: null, endDate: null, focusedInput: "startDate" }));
163
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
164
+ startDate: state.current[0].startDate,
165
+ endDate: state.current[0].endDate,
166
+ onDatesChange: (data) => state.current[1](data),
167
+ focusedInput: state.current[0].focusedInput,
168
+ minBookingDate: new Date("2020-01-01"),
169
+ minBookingDays: 3,
170
+ exactMinBookingDays: true,
171
+ }));
172
+ const START_DATE = new Date("2021-09-15");
173
+ const END_DATE = new Date("2021-09-17");
174
+ (0, react_1.act)(() => {
175
+ result.current.onDatesSelect(START_DATE, END_DATE);
176
+ rerender();
177
+ });
178
+ expect(result.current.isStartDate(START_DATE)).toBe(true);
179
+ expect(result.current.isEndDate(END_DATE)).toBe(true);
180
+ });
181
+ test("date range select - blocked dates in range", () => {
182
+ const onDatesChange = jest.fn();
183
+ const { result } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
184
+ startDate: null,
185
+ endDate: null,
186
+ onDatesChange,
187
+ focusedInput: "startDate",
188
+ minBookingDate: new Date("2020-01-01"),
189
+ unavailableDates: [new Date("2021-09-17")],
190
+ }));
191
+ const START_DATE = new Date("2021-09-15");
192
+ const END_DATE = new Date("2021-09-20");
193
+ (0, react_1.act)(() => {
194
+ result.current.onDatesSelect(START_DATE, END_DATE);
195
+ });
196
+ // onDatesChange should not be called when blocked date is in range
197
+ expect(onDatesChange).not.toHaveBeenCalled();
198
+ });
199
+ test("date range select - with changeActiveMonthOnSelect", () => {
200
+ const { result: state } = (0, react_1.renderHook)(() => (0, react_2.useState)({ startDate: null, endDate: null, focusedInput: "startDate" }));
201
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
202
+ startDate: state.current[0].startDate,
203
+ endDate: state.current[0].endDate,
204
+ onDatesChange: (data) => state.current[1](data),
205
+ focusedInput: state.current[0].focusedInput,
206
+ minBookingDate: new Date("2020-01-01"),
207
+ changeActiveMonthOnSelect: true,
208
+ }));
209
+ const START_DATE = new Date("2022-12-15");
210
+ const END_DATE = new Date("2022-12-20");
211
+ const initialActiveMonths = result.current.activeMonths;
212
+ (0, react_1.act)(() => {
213
+ result.current.onDatesSelect(START_DATE, END_DATE);
214
+ rerender();
215
+ });
216
+ // Active months should change to the selected date's month
217
+ expect(result.current.activeMonths[0].year).toBe(2022);
218
+ expect(result.current.activeMonths[0].month).toBe(11); // December is month 11
219
+ expect(result.current.activeMonths).not.toEqual(initialActiveMonths);
220
+ });
221
+ test("date range select - respects maxBookingDate", () => {
222
+ const onDatesChange = jest.fn();
223
+ const { result } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
224
+ startDate: null,
225
+ endDate: null,
226
+ onDatesChange,
227
+ focusedInput: "startDate",
228
+ minBookingDate: new Date("2020-01-01"),
229
+ maxBookingDate: new Date("2021-09-18"),
230
+ }));
231
+ const START_DATE = new Date("2021-09-15");
232
+ const END_DATE = new Date("2021-09-20"); // After maxBookingDate
233
+ (0, react_1.act)(() => {
234
+ result.current.onDatesSelect(START_DATE, END_DATE);
235
+ });
236
+ // onDatesChange should not be called when end date is after maxBookingDate
237
+ expect(onDatesChange).not.toHaveBeenCalled();
238
+ });
239
+ test("date range select - with isDateBlocked callback", () => {
240
+ const onDatesChange = jest.fn();
241
+ const isDateBlocked = (date) => date.getDate() === 17;
242
+ const { result } = (0, react_1.renderHook)(() => (0, use_date_range_picker_1.useDateRangePicker)({
243
+ startDate: null,
244
+ endDate: null,
245
+ onDatesChange,
246
+ focusedInput: "startDate",
247
+ minBookingDate: new Date("2020-01-01"),
248
+ isDateBlocked,
249
+ }));
250
+ const START_DATE = new Date("2021-09-15");
251
+ const END_DATE = new Date("2021-09-20");
252
+ (0, react_1.act)(() => {
253
+ result.current.onDatesSelect(START_DATE, END_DATE);
254
+ });
255
+ // onDatesChange should not be called when a blocked date (17th) is in the range
256
+ expect(onDatesChange).not.toHaveBeenCalled();
257
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/datepicker",
3
- "version": "11.86.0",
3
+ "version": "11.87.0",
4
4
  "description": "A set of React hooks to create an awesome datepicker.",
5
5
  "main": "index.js",
6
6
  "scripts": {