@uxf/datepicker 11.86.0 → 11.88.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
  });
@@ -4,7 +4,6 @@ exports.useDatePicker = useDatePicker;
4
4
  const react_1 = require("react");
5
5
  const dayjs_en_1 = require("../utils/dayjs-en");
6
6
  const get_initial_months_1 = require("../utils/get-initial-months");
7
- const is_browser_1 = require("../utils/is-browser");
8
7
  const is_date_blocked_1 = require("../utils/is-date-blocked");
9
8
  const is_date_hovered_1 = require("../utils/is-date-hovered");
10
9
  const is_in_unavailable_dates_1 = require("../utils/is-in-unavailable-dates");
@@ -48,9 +47,6 @@ function useDatePicker({ datesConfig = [], firstDayOfWeek = 0, initialVisibleMon
48
47
  isDateBlocked: disabledDatesByUser,
49
48
  });
50
49
  (0, react_1.useEffect)(() => {
51
- if (!is_browser_1.isBrowser) {
52
- return;
53
- }
54
50
  function handleKeyDown(e) {
55
51
  var _a, _b;
56
52
  if ((e.key === "ArrowRight" || e.key === "ArrowLeft" || e.key === "ArrowDown" || e.key === "ArrowUp") &&
@@ -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[];
@@ -6,7 +6,6 @@ const react_1 = require("react");
6
6
  const can_select_range_1 = require("../utils/can-select-range");
7
7
  const dayjs_en_1 = require("../utils/dayjs-en");
8
8
  const get_initial_months_1 = require("../utils/get-initial-months");
9
- const is_browser_1 = require("../utils/is-browser");
10
9
  const is_date_blocked_1 = require("../utils/is-date-blocked");
11
10
  const is_date_hovered_1 = require("../utils/is-date-hovered");
12
11
  const is_date_inside_range_1 = require("../utils/is-date-inside-range");
@@ -58,9 +57,6 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
58
57
  isDateBlocked: disabledDatesByUser,
59
58
  });
60
59
  (0, react_1.useEffect)(() => {
61
- if (!is_browser_1.isBrowser) {
62
- return;
63
- }
64
60
  function handleKeyDown(e) {
65
61
  var _a, _b;
66
62
  if ((e.key === "ArrowRight" || e.key === "ArrowLeft" || e.key === "ArrowDown" || e.key === "ArrowUp") &&
@@ -153,6 +149,28 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
153
149
  setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, date));
154
150
  }
155
151
  }
152
+ function onDatesSelect(start, end) {
153
+ if ((0, can_select_range_1.canSelectRange)({
154
+ minBookingDays,
155
+ exactMinBookingDays,
156
+ minBookingDate,
157
+ maxBookingDate,
158
+ isDateBlocked: disabledDatesByUser,
159
+ startDate: start,
160
+ endDate: end,
161
+ })) {
162
+ onDatesChange({
163
+ endDate: end,
164
+ startDate: start,
165
+ focusedInput: exports.START_DATE,
166
+ });
167
+ }
168
+ if (focusedInput !== exports.END_DATE &&
169
+ (!focusedDate || !(0, dayjs_en_1.dayjsEn)(start).isSame(focusedDate, "month")) &&
170
+ changeActiveMonthOnSelect) {
171
+ setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, start));
172
+ }
173
+ }
156
174
  // eslint-disable-next-line complexity
157
175
  function onDateHover(date) {
158
176
  if (!date) {
@@ -224,6 +242,7 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
224
242
  onDateFocus,
225
243
  onDateHover,
226
244
  onDateSelect,
245
+ onDatesSelect,
227
246
  onResetDates,
228
247
  unavailableDates: disabledDates,
229
248
  };
@@ -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.88.0",
4
4
  "description": "A set of React hooks to create an awesome datepicker.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1 +0,0 @@
1
- export declare const isBrowser: boolean;
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isBrowser = void 0;
4
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
5
- exports.isBrowser = Boolean(typeof window !== "undefined" && window.document && window.document.createElement);