@uxf/datepicker 11.111.0-canary.1 → 11.111.2
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/hooks/use-date-picker-navigation.d.ts +3 -4
- package/hooks/use-date-picker-navigation.js +34 -30
- package/hooks/use-date-picker-navigation.test.js +4 -40
- package/hooks/use-date-picker.js +26 -40
- package/hooks/use-date-picker.test.js +2 -2
- package/hooks/use-date-range-picker.js +76 -103
- package/hooks/use-day.js +11 -12
- package/hooks/use-decade.js +8 -9
- package/package.json +4 -9
- package/utils/can-select-range.d.ts +5 -6
- package/utils/can-select-range.js +19 -7
- package/utils/can-select-range.test.js +27 -30
- package/utils/dayjs-utils.d.ts +1 -0
- package/utils/dayjs-utils.js +5 -1
- package/utils/get-current-year-month-and-date.js +2 -1
- package/utils/get-date-invervals.js +5 -2
- package/utils/get-date-month-and-year.js +5 -6
- package/utils/get-days.js +9 -12
- package/utils/get-each.d.ts +1 -2
- package/utils/get-each.js +9 -37
- package/utils/get-each.test.js +19 -34
- package/utils/get-initial-months.js +6 -3
- package/utils/get-months.js +7 -7
- package/utils/get-next-active-month.js +10 -6
- package/utils/get-weekday-labels.js +2 -4
- package/utils/get-years.js +4 -5
- package/utils/is-date-blocked.d.ts +6 -7
- package/utils/is-date-blocked.js +7 -6
- package/utils/is-date-blocked.test.js +11 -108
- package/utils/is-date-hovered.d.ts +5 -6
- package/utils/is-date-hovered.js +24 -17
- package/utils/is-date-hovered.test.js +25 -42
- package/utils/is-date-inside-range.d.ts +1 -2
- package/utils/is-date-inside-range.js +2 -1
- package/utils/is-date-selected.test.js +8 -16
- package/utils/is-end-date.d.ts +1 -2
- package/utils/is-end-date.js +2 -1
- package/utils/is-end-date.test.js +6 -11
- package/utils/is-first-or-last-selected-date.d.ts +1 -2
- package/utils/is-first-or-last-selected-date.js +3 -1
- package/utils/is-first-or-last-selected-date.test.js +6 -9
- package/utils/is-in-unavailable-dates.d.ts +1 -2
- package/utils/is-in-unavailable-dates.js +2 -1
- package/utils/is-in-unavailable-dates.test.js +6 -10
- package/utils/is-start-date.d.ts +1 -2
- package/utils/is-start-date.js +2 -1
- package/utils/is-start-date.test.js +6 -12
- package/jest.dst.config.js +0 -22
- package/jest.dst.global-setup.js +0 -14
- package/utils/date-string.d.ts +0 -34
- package/utils/date-string.js +0 -64
- package/utils/date-string.test.d.ts +0 -1
- package/utils/date-string.test.js +0 -63
- package/utils/dst-robustness.test.d.ts +0 -11
- package/utils/dst-robustness.test.js +0 -328
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { DateString } from "@uxf/core/date";
|
|
2
1
|
import { Dispatch, SetStateAction } from "react";
|
|
3
2
|
import { MonthType } from "../utils/types";
|
|
4
3
|
export interface UseDatePickerNavigationProps {
|
|
5
4
|
activeMonths: MonthType[];
|
|
6
5
|
setActiveMonths: Dispatch<SetStateAction<MonthType[]>>;
|
|
7
|
-
setFocusedDate:
|
|
8
|
-
minBookingDate?:
|
|
9
|
-
maxBookingDate?:
|
|
6
|
+
setFocusedDate: Dispatch<SetStateAction<Date | null>>;
|
|
7
|
+
minBookingDate?: Date;
|
|
8
|
+
maxBookingDate?: Date;
|
|
10
9
|
numberOfMonths: number;
|
|
11
10
|
}
|
|
12
11
|
export interface UseDatePickerNavigationReturnType {
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useDatePickerNavigation = useDatePickerNavigation;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
const
|
|
6
|
-
const date_string_1 = require("../utils/date-string");
|
|
5
|
+
const dayjs_utils_1 = require("../utils/dayjs-utils");
|
|
7
6
|
const get_initial_months_1 = require("../utils/get-initial-months");
|
|
8
7
|
const get_next_active_month_1 = require("../utils/get-next-active-month");
|
|
9
8
|
function useDatePickerNavigation({ activeMonths, setActiveMonths, setFocusedDate, minBookingDate, maxBookingDate, numberOfMonths, }) {
|
|
10
|
-
var _a, _b;
|
|
9
|
+
var _a, _b, _c, _d;
|
|
11
10
|
const goToPrevMonths = (0, react_1.useCallback)(() => {
|
|
12
11
|
const newActiveMonths = (0, get_next_active_month_1.getNextActiveMonth)(activeMonths, numberOfMonths, -1);
|
|
13
12
|
setActiveMonths(newActiveMonths);
|
|
@@ -50,35 +49,40 @@ function useDatePickerNavigation({ activeMonths, setActiveMonths, setFocusedDate
|
|
|
50
49
|
setFocusedDate(null);
|
|
51
50
|
return newActiveMonths;
|
|
52
51
|
}, [activeMonths, numberOfMonths, setActiveMonths, setFocusedDate]);
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
const canGoToPrevMonth = minBookingDate
|
|
53
|
+
? !(0, dayjs_utils_1.dayjsEnRaw)((_b = (_a = activeMonths.at(0)) === null || _a === void 0 ? void 0 : _a.date) !== null && _b !== void 0 ? _b : new Date()).isBefore((0, dayjs_utils_1.dayjsEnRaw)(minBookingDate))
|
|
54
|
+
: true;
|
|
55
|
+
const canGoToNextMonth = maxBookingDate
|
|
56
|
+
? !(0, dayjs_utils_1.dayjsEnWithTz)(activeMonths[activeMonths.length - 1].date)
|
|
57
|
+
.endOf("month")
|
|
58
|
+
.isAfter((0, dayjs_utils_1.dayjsEnWithTz)(maxBookingDate))
|
|
59
|
+
: true;
|
|
60
|
+
const canGoToPrevYear = minBookingDate
|
|
61
|
+
? !(0, dayjs_utils_1.dayjsEnWithTz)((_d = (_c = activeMonths.at(0)) === null || _c === void 0 ? void 0 : _c.date) !== null && _d !== void 0 ? _d : new Date())
|
|
62
|
+
.subtract(1, "year")
|
|
63
|
+
.endOf("year")
|
|
64
|
+
.isBefore((0, dayjs_utils_1.dayjsEnRaw)(minBookingDate))
|
|
65
|
+
: true;
|
|
66
|
+
const canGoToNextYear = maxBookingDate
|
|
67
|
+
? !(0, dayjs_utils_1.dayjsEnWithTz)(activeMonths[activeMonths.length - 1].date)
|
|
68
|
+
.add(1, "year")
|
|
69
|
+
.startOf("year")
|
|
70
|
+
.isAfter((0, dayjs_utils_1.dayjsEnWithTz)(maxBookingDate))
|
|
71
|
+
: true;
|
|
65
72
|
const canGoTo = (0, react_1.useCallback)((month, type) => {
|
|
66
|
-
if (
|
|
67
|
-
|
|
73
|
+
if (minBookingDate || maxBookingDate) {
|
|
74
|
+
if (minBookingDate && maxBookingDate) {
|
|
75
|
+
return ((0, dayjs_utils_1.dayjsEnWithTz)(month).endOf(type).add(1, "day").isAfter(minBookingDate, "day") &&
|
|
76
|
+
(0, dayjs_utils_1.dayjsEnWithTz)(month).startOf(type).subtract(1, "day").isBefore(maxBookingDate, "day"));
|
|
77
|
+
}
|
|
78
|
+
if (minBookingDate) {
|
|
79
|
+
return (0, dayjs_utils_1.dayjsEnWithTz)(month).endOf(type).add(1, "day").isAfter(minBookingDate, "day");
|
|
80
|
+
}
|
|
81
|
+
if (maxBookingDate) {
|
|
82
|
+
return (0, dayjs_utils_1.dayjsEnWithTz)(month).startOf(type).subtract(1, "day").isBefore(maxBookingDate, "day");
|
|
83
|
+
}
|
|
68
84
|
}
|
|
69
|
-
|
|
70
|
-
const year = parseInt(ds.slice(0, 4), 10);
|
|
71
|
-
if (type === "month") {
|
|
72
|
-
// Month is reachable if its range overlaps [minBookingDate, maxBookingDate].
|
|
73
|
-
// "end of this month + 1 day > min" AND "start of this month - 1 day < max"
|
|
74
|
-
const afterMin = !minBookingDate || (0, date_string_1.addMonths)(ds, 1) > minBookingDate;
|
|
75
|
-
const beforeMax = !maxBookingDate || (0, date_string_1.addDays)(ds, -1) < maxBookingDate;
|
|
76
|
-
return afterMin && beforeMax;
|
|
77
|
-
}
|
|
78
|
-
// type === "year"
|
|
79
|
-
const afterMin = !minBookingDate || (0, create_date_string_1.createDateString)(year + 1, 0) > minBookingDate;
|
|
80
|
-
const beforeMax = !maxBookingDate || (0, create_date_string_1.createDateString)(year - 1, 11, 31) < maxBookingDate;
|
|
81
|
-
return afterMin && beforeMax;
|
|
85
|
+
return true;
|
|
82
86
|
}, [maxBookingDate, minBookingDate]);
|
|
83
87
|
const canGoToMonth = (0, react_1.useCallback)((date) => canGoTo(date, "month"), [canGoTo]);
|
|
84
88
|
const canGoToYear = (0, react_1.useCallback)((date) => canGoTo(date, "year"), [canGoTo]);
|
|
@@ -24,8 +24,8 @@ test("base data with min and max date", () => {
|
|
|
24
24
|
setActiveMonths: () => undefined,
|
|
25
25
|
numberOfMonths: 1,
|
|
26
26
|
setFocusedDate: () => undefined,
|
|
27
|
-
minBookingDate: "2015-05-05",
|
|
28
|
-
maxBookingDate: "2025-10-11",
|
|
27
|
+
minBookingDate: new Date("2015-05-05"),
|
|
28
|
+
maxBookingDate: new Date("2025-10-11"),
|
|
29
29
|
}));
|
|
30
30
|
expect(result.current.canGoToMonth(new Date("2021-08-01"))).toBe(true);
|
|
31
31
|
expect(result.current.canGoToMonth(new Date("2015-04-01"))).toBe(false);
|
|
@@ -34,42 +34,6 @@ test("base data with min and max date", () => {
|
|
|
34
34
|
expect(result.current.canGoToYear(new Date("2014-01-01"))).toBe(false);
|
|
35
35
|
expect(result.current.canGoToYear(new Date("2026-01-01"))).toBe(false);
|
|
36
36
|
});
|
|
37
|
-
test("canGoToNextMonth edge cases with maxBookingDate", () => {
|
|
38
|
-
// Active month: September 2021 (lastMonthStr = "2021-09-01")
|
|
39
|
-
// addMonths("2021-09-01", 1) = "2021-10-01"
|
|
40
|
-
// maxBookingDate = 1st of next month ("2021-10-01"):
|
|
41
|
-
// "2021-10-01" <= "2021-10-01" → true → can navigate forward
|
|
42
|
-
// (October has at least one bookable day)
|
|
43
|
-
const { result: result1 } = (0, react_1.renderHook)(() => (0, use_date_picker_navigation_1.useDatePickerNavigation)({
|
|
44
|
-
activeMonths: ACTIVE_MONTHS,
|
|
45
|
-
setActiveMonths: () => undefined,
|
|
46
|
-
numberOfMonths: 1,
|
|
47
|
-
setFocusedDate: () => undefined,
|
|
48
|
-
maxBookingDate: "2021-10-01",
|
|
49
|
-
}));
|
|
50
|
-
expect(result1.current.canGoToNextMonth).toBe(true);
|
|
51
|
-
// maxBookingDate = last day of current month ("2021-09-30"):
|
|
52
|
-
// "2021-10-01" <= "2021-09-30" → false → cannot navigate forward
|
|
53
|
-
// (October is entirely past maxBookingDate)
|
|
54
|
-
const { result: result2 } = (0, react_1.renderHook)(() => (0, use_date_picker_navigation_1.useDatePickerNavigation)({
|
|
55
|
-
activeMonths: ACTIVE_MONTHS,
|
|
56
|
-
setActiveMonths: () => undefined,
|
|
57
|
-
numberOfMonths: 1,
|
|
58
|
-
setFocusedDate: () => undefined,
|
|
59
|
-
maxBookingDate: "2021-09-30",
|
|
60
|
-
}));
|
|
61
|
-
expect(result2.current.canGoToNextMonth).toBe(false);
|
|
62
|
-
// maxBookingDate = mid-next-month ("2021-10-15"):
|
|
63
|
-
// "2021-10-01" <= "2021-10-15" → true → can navigate forward
|
|
64
|
-
const { result: result3 } = (0, react_1.renderHook)(() => (0, use_date_picker_navigation_1.useDatePickerNavigation)({
|
|
65
|
-
activeMonths: ACTIVE_MONTHS,
|
|
66
|
-
setActiveMonths: () => undefined,
|
|
67
|
-
numberOfMonths: 1,
|
|
68
|
-
setFocusedDate: () => undefined,
|
|
69
|
-
maxBookingDate: "2021-10-15",
|
|
70
|
-
}));
|
|
71
|
-
expect(result3.current.canGoToNextMonth).toBe(true);
|
|
72
|
-
});
|
|
73
37
|
test("actions", () => {
|
|
74
38
|
const { result: state } = (0, react_1.renderHook)(() => (0, react_2.useState)([{ month: 8, year: 2021, date: new Date("2021-09-01") }]));
|
|
75
39
|
const { result, rerender } = (0, react_1.renderHook)(() => {
|
|
@@ -79,8 +43,8 @@ test("actions", () => {
|
|
|
79
43
|
setActiveMonths,
|
|
80
44
|
numberOfMonths: 1,
|
|
81
45
|
setFocusedDate: () => undefined,
|
|
82
|
-
minBookingDate: "2020-12-25",
|
|
83
|
-
maxBookingDate: "2022-03-11",
|
|
46
|
+
minBookingDate: new Date("2020-12-25"),
|
|
47
|
+
maxBookingDate: new Date("2022-03-11"),
|
|
84
48
|
});
|
|
85
49
|
});
|
|
86
50
|
// go to year 2020
|
package/hooks/use-date-picker.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useDatePicker = useDatePicker;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
const
|
|
5
|
+
const dayjs_utils_1 = require("../utils/dayjs-utils");
|
|
6
6
|
const get_initial_months_1 = require("../utils/get-initial-months");
|
|
7
7
|
const is_date_blocked_1 = require("../utils/is-date-blocked");
|
|
8
8
|
const is_date_hovered_1 = require("../utils/is-date-hovered");
|
|
@@ -10,50 +10,38 @@ const is_in_unavailable_dates_1 = require("../utils/is-in-unavailable-dates");
|
|
|
10
10
|
const is_start_date_1 = require("../utils/is-start-date");
|
|
11
11
|
const use_date_picker_navigation_1 = require("./use-date-picker-navigation");
|
|
12
12
|
function useDatePicker({ datesConfig = [], firstDayOfWeek = 0, initialVisibleMonth, isDateBlocked: isDateBlockedProps = () => false, maxBookingDate, minBookingDate, numberOfMonths = 1, onDateChange, preventScroll, selectedDate, unavailableDates = [], }) {
|
|
13
|
-
// --- Normalize all Date inputs to DateString at boundary ---
|
|
14
|
-
const normalizedSelectedDate = selectedDate ? (0, date_string_1.toDateString)(selectedDate) : null;
|
|
15
|
-
const normalizedMinBookingDate = minBookingDate ? (0, date_string_1.toDateString)(minBookingDate) : undefined;
|
|
16
|
-
const normalizedMaxBookingDate = maxBookingDate ? (0, date_string_1.toDateString)(maxBookingDate) : undefined;
|
|
17
13
|
const disabledDatesFromConfig = datesConfig.filter((config) => config.isDisabled).flatMap((config) => config.dates);
|
|
18
|
-
const
|
|
19
|
-
...unavailableDates.map(date_string_1.toDateString),
|
|
20
|
-
...disabledDatesFromConfig.map(date_string_1.toDateString),
|
|
21
|
-
];
|
|
14
|
+
const disabledDates = [...unavailableDates, ...disabledDatesFromConfig];
|
|
22
15
|
const [activeMonths, setActiveMonths] = (0, react_1.useState)(() => selectedDate
|
|
23
16
|
? (0, get_initial_months_1.getInitialMonths)(numberOfMonths, selectedDate)
|
|
24
17
|
: (0, get_initial_months_1.getInitialMonths)(numberOfMonths, initialVisibleMonth || null));
|
|
25
18
|
const [hoveredDate, setHoveredDate] = (0, react_1.useState)(null);
|
|
26
|
-
const [focusedDate, setFocusedDate] = (0, react_1.useState)(
|
|
27
|
-
// Consumer's isDateBlocked callback still receives Date via fromDateString
|
|
19
|
+
const [focusedDate, setFocusedDate] = (0, react_1.useState)(selectedDate);
|
|
28
20
|
const disabledDatesByUser = (date) => {
|
|
29
|
-
return (0, is_in_unavailable_dates_1.isInUnavailableDates)(
|
|
21
|
+
return (0, is_in_unavailable_dates_1.isInUnavailableDates)(disabledDates, date) || isDateBlockedProps(date);
|
|
30
22
|
};
|
|
31
23
|
const onDateFocus = (0, react_1.useCallback)((date) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const focusedYYYYMM = (0, date_string_1.toDateString)(date).slice(0, 7);
|
|
35
|
-
if (!focusedDate ||
|
|
36
|
-
!activeMonths.some((m) => `${m.year}-${String(m.month + 1).padStart(2, "0")}` === focusedYYYYMM)) {
|
|
24
|
+
setFocusedDate(date);
|
|
25
|
+
if (!focusedDate || !activeMonths.map((m) => m.month).includes((0, dayjs_utils_1.dayjsEnRaw)(date).month())) {
|
|
37
26
|
setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, date));
|
|
38
27
|
}
|
|
39
28
|
}, [activeMonths, focusedDate, numberOfMonths]);
|
|
40
|
-
const _isDateSelected = (date) => (0, is_start_date_1.isStartDate)(
|
|
29
|
+
const _isDateSelected = (date) => (0, is_start_date_1.isStartDate)(date, selectedDate);
|
|
41
30
|
const _isDateBlocked = (date) => (0, is_date_blocked_1.isDateBlocked)({
|
|
42
|
-
date
|
|
43
|
-
minBookingDate
|
|
44
|
-
maxBookingDate
|
|
45
|
-
startDate:
|
|
46
|
-
endDate:
|
|
31
|
+
date,
|
|
32
|
+
minBookingDate,
|
|
33
|
+
maxBookingDate,
|
|
34
|
+
startDate: selectedDate,
|
|
35
|
+
endDate: selectedDate,
|
|
47
36
|
minBookingDays: 1,
|
|
48
|
-
isDateBlockedFn:
|
|
49
|
-
unavailableDates: allDisabledDates,
|
|
37
|
+
isDateBlockedFn: disabledDatesByUser,
|
|
50
38
|
});
|
|
51
|
-
const isDateFocused = (date) => focusedDate
|
|
39
|
+
const isDateFocused = (date) => (focusedDate ? (0, dayjs_utils_1.dayjsEnRaw)(date).isSame(focusedDate, "day") : false);
|
|
52
40
|
const _isDateHovered = (date) => (0, is_date_hovered_1.isDateHovered)({
|
|
53
|
-
date
|
|
41
|
+
date,
|
|
54
42
|
hoveredDate,
|
|
55
|
-
startDate:
|
|
56
|
-
endDate:
|
|
43
|
+
startDate: selectedDate,
|
|
44
|
+
endDate: selectedDate,
|
|
57
45
|
minBookingDays: 1,
|
|
58
46
|
exactMinBookingDays: false,
|
|
59
47
|
isDateBlocked: disabledDatesByUser,
|
|
@@ -77,8 +65,7 @@ function useDatePicker({ datesConfig = [], firstDayOfWeek = 0, initialVisibleMon
|
|
|
77
65
|
onDateChange(null);
|
|
78
66
|
}, [onDateChange]);
|
|
79
67
|
function onDateSelect(date) {
|
|
80
|
-
|
|
81
|
-
if (dateStr !== normalizedSelectedDate) {
|
|
68
|
+
if (!(0, dayjs_utils_1.dayjsEnRaw)(date).isSame(selectedDate)) {
|
|
82
69
|
onDateChange(date);
|
|
83
70
|
}
|
|
84
71
|
else {
|
|
@@ -90,10 +77,9 @@ function useDatePicker({ datesConfig = [], firstDayOfWeek = 0, initialVisibleMon
|
|
|
90
77
|
setHoveredDate(null);
|
|
91
78
|
}
|
|
92
79
|
else {
|
|
93
|
-
const
|
|
94
|
-
const isNotBlocked = !_isDateBlocked(date) || (normalizedSelectedDate && dateStr === normalizedSelectedDate);
|
|
80
|
+
const isNotBlocked = !_isDateBlocked(date) || (selectedDate && (0, dayjs_utils_1.dayjsEnRaw)(date).isSame(selectedDate, "day"));
|
|
95
81
|
if (isNotBlocked) {
|
|
96
|
-
setHoveredDate(
|
|
82
|
+
setHoveredDate(date);
|
|
97
83
|
}
|
|
98
84
|
else if (hoveredDate !== null) {
|
|
99
85
|
setHoveredDate(null);
|
|
@@ -103,17 +89,17 @@ function useDatePicker({ datesConfig = [], firstDayOfWeek = 0, initialVisibleMon
|
|
|
103
89
|
return {
|
|
104
90
|
...(0, use_date_picker_navigation_1.useDatePickerNavigation)({
|
|
105
91
|
activeMonths,
|
|
106
|
-
maxBookingDate
|
|
107
|
-
minBookingDate
|
|
92
|
+
maxBookingDate,
|
|
93
|
+
minBookingDate,
|
|
108
94
|
numberOfMonths,
|
|
109
95
|
setActiveMonths,
|
|
110
|
-
setFocusedDate
|
|
96
|
+
setFocusedDate,
|
|
111
97
|
}),
|
|
112
98
|
activeMonths,
|
|
113
99
|
datesConfig,
|
|
114
100
|
firstDayOfWeek,
|
|
115
|
-
focusedDate
|
|
116
|
-
hoveredDate
|
|
101
|
+
focusedDate,
|
|
102
|
+
hoveredDate,
|
|
117
103
|
isDateBlocked: _isDateBlocked,
|
|
118
104
|
isDateFocused,
|
|
119
105
|
isDateHovered: _isDateHovered,
|
|
@@ -125,6 +111,6 @@ function useDatePicker({ datesConfig = [], firstDayOfWeek = 0, initialVisibleMon
|
|
|
125
111
|
onResetDates: onReset,
|
|
126
112
|
preventScroll,
|
|
127
113
|
selectedDate,
|
|
128
|
-
unavailableDates:
|
|
114
|
+
unavailableDates: disabledDates,
|
|
129
115
|
};
|
|
130
116
|
}
|
|
@@ -4,11 +4,11 @@ const react_1 = require("@testing-library/react");
|
|
|
4
4
|
const react_2 = require("react");
|
|
5
5
|
const use_date_picker_1 = require("./use-date-picker");
|
|
6
6
|
test("base data", () => {
|
|
7
|
-
const BASE_DATE = new Date("2021-09-15T00:00:
|
|
7
|
+
const BASE_DATE = new Date("2021-09-15T00:00:00+02:00");
|
|
8
8
|
const { result } = (0, react_1.renderHook)(() => (0, use_date_picker_1.useDatePicker)({
|
|
9
9
|
selectedDate: BASE_DATE,
|
|
10
10
|
onDateChange: () => undefined,
|
|
11
|
-
minBookingDate: new Date("2020-01-
|
|
11
|
+
minBookingDate: new Date("2020-01-01"),
|
|
12
12
|
}));
|
|
13
13
|
expect(result.current.firstDayOfWeek).toBe(0);
|
|
14
14
|
expect(result.current.focusedDate).toStrictEqual(BASE_DATE);
|
|
@@ -4,7 +4,7 @@ exports.END_DATE = exports.START_DATE = void 0;
|
|
|
4
4
|
exports.useDateRangePicker = useDateRangePicker;
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const can_select_range_1 = require("../utils/can-select-range");
|
|
7
|
-
const
|
|
7
|
+
const dayjs_utils_1 = require("../utils/dayjs-utils");
|
|
8
8
|
const get_initial_months_1 = require("../utils/get-initial-months");
|
|
9
9
|
const is_date_blocked_1 = require("../utils/is-date-blocked");
|
|
10
10
|
const is_date_hovered_1 = require("../utils/is-date-hovered");
|
|
@@ -17,62 +17,44 @@ const use_date_picker_navigation_1 = require("./use-date-picker-navigation");
|
|
|
17
17
|
exports.START_DATE = "startDate";
|
|
18
18
|
exports.END_DATE = "endDate";
|
|
19
19
|
function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [], endDate, exactMinBookingDays = false, firstDayOfWeek = 0, focusedInput, initialVisibleMonth, isDateBlocked: isDateBlockedProps, maxBookingDate, minBookingDate, minBookingDays = 1, numberOfMonths = 2, onDatesChange, startDate, unavailableDates = [], }) {
|
|
20
|
-
// --- Normalize all Date inputs to DateString at boundary ---
|
|
21
|
-
const normalizedStartDate = startDate ? (0, date_string_1.toDateString)(startDate) : null;
|
|
22
|
-
const normalizedEndDate = endDate ? (0, date_string_1.toDateString)(endDate) : null;
|
|
23
|
-
const normalizedMinBookingDate = minBookingDate ? (0, date_string_1.toDateString)(minBookingDate) : undefined;
|
|
24
|
-
const normalizedMaxBookingDate = maxBookingDate ? (0, date_string_1.toDateString)(maxBookingDate) : undefined;
|
|
25
20
|
const disabledDatesFromConfig = datesConfig.filter((config) => config.isDisabled).flatMap((config) => config.dates);
|
|
26
|
-
const
|
|
27
|
-
...unavailableDates.map(date_string_1.toDateString),
|
|
28
|
-
...disabledDatesFromConfig.map(date_string_1.toDateString),
|
|
29
|
-
];
|
|
21
|
+
const disabledDates = [...unavailableDates, ...disabledDatesFromConfig];
|
|
30
22
|
const [activeMonths, setActiveMonths] = (0, react_1.useState)(() => startDate
|
|
31
23
|
? (0, get_initial_months_1.getInitialMonths)(numberOfMonths, startDate)
|
|
32
24
|
: (0, get_initial_months_1.getInitialMonths)(numberOfMonths, initialVisibleMonth || null));
|
|
33
25
|
const [hoveredDate, setHoveredDate] = (0, react_1.useState)(null);
|
|
34
|
-
const [focusedDate, setFocusedDate] = (0, react_1.useState)(
|
|
35
|
-
|
|
36
|
-
const disabledDatesByUser = isDateBlockedProps || allDisabledDates.length > 0
|
|
26
|
+
const [focusedDate, setFocusedDate] = (0, react_1.useState)(startDate);
|
|
27
|
+
const disabledDatesByUser = isDateBlockedProps || disabledDates.length > 0
|
|
37
28
|
? (date) => {
|
|
38
29
|
var _a;
|
|
39
|
-
return (
|
|
40
|
-
((_a = isDateBlockedProps === null || isDateBlockedProps === void 0 ? void 0 : isDateBlockedProps((0, date_string_1.fromDateString)(date))) !== null && _a !== void 0 ? _a : false));
|
|
30
|
+
return (0, is_in_unavailable_dates_1.isInUnavailableDates)(disabledDates, date) || ((_a = isDateBlockedProps === null || isDateBlockedProps === void 0 ? void 0 : isDateBlockedProps(date)) !== null && _a !== void 0 ? _a : false);
|
|
41
31
|
}
|
|
42
32
|
: null;
|
|
43
33
|
const onDateFocus = (0, react_1.useCallback)((date) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const focusedYYYYMM = (0, date_string_1.toDateString)(date).slice(0, 7);
|
|
47
|
-
if (!focusedDate ||
|
|
48
|
-
!activeMonths.some((m) => `${m.year}-${String(m.month + 1).padStart(2, "0")}` === focusedYYYYMM)) {
|
|
34
|
+
setFocusedDate(date);
|
|
35
|
+
if (!focusedDate || !activeMonths.map((m) => m.month).includes((0, dayjs_utils_1.dayjsEnRaw)(date).month())) {
|
|
49
36
|
setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, date));
|
|
50
37
|
}
|
|
51
38
|
}, [activeMonths, focusedDate, numberOfMonths]);
|
|
52
|
-
const _isDateSelected = (date) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
};
|
|
57
|
-
const _isStartDate = (date) => (0, is_start_date_1.isStartDate)((0, date_string_1.toDateString)(date), normalizedStartDate);
|
|
58
|
-
const _isEndDate = (date) => (0, is_end_date_1.isEndDate)((0, date_string_1.toDateString)(date), normalizedEndDate);
|
|
59
|
-
const _isDateInsideRange = (date) => (0, is_date_inside_range_1.isDateInsideRange)((0, date_string_1.toDateString)(date), normalizedStartDate, normalizedEndDate);
|
|
39
|
+
const _isDateSelected = (date) => (0, is_date_inside_range_1.isDateInsideRange)(date, startDate, endDate) || (0, is_first_or_last_selected_date_1.isFirstOrLastSelectedDate)(date, startDate, endDate);
|
|
40
|
+
const _isStartDate = (date) => (0, is_start_date_1.isStartDate)(date, startDate);
|
|
41
|
+
const _isEndDate = (date) => (0, is_end_date_1.isEndDate)(date, endDate);
|
|
42
|
+
const _isDateInsideRange = (date) => (0, is_date_inside_range_1.isDateInsideRange)(date, startDate, endDate);
|
|
60
43
|
const _isDateBlocked = (date) => (0, is_date_blocked_1.isDateBlocked)({
|
|
61
|
-
date
|
|
62
|
-
minBookingDate
|
|
63
|
-
maxBookingDate
|
|
64
|
-
startDate
|
|
65
|
-
endDate
|
|
44
|
+
date,
|
|
45
|
+
minBookingDate,
|
|
46
|
+
maxBookingDate,
|
|
47
|
+
startDate,
|
|
48
|
+
endDate,
|
|
66
49
|
minBookingDays,
|
|
67
|
-
isDateBlockedFn:
|
|
68
|
-
unavailableDates: allDisabledDates,
|
|
50
|
+
isDateBlockedFn: disabledDatesByUser,
|
|
69
51
|
});
|
|
70
|
-
const isDateFocused = (date) => focusedDate
|
|
52
|
+
const isDateFocused = (date) => (focusedDate ? (0, dayjs_utils_1.dayjsEnRaw)(date).isSame(focusedDate, "day") : false);
|
|
71
53
|
const _isDateHovered = (date) => (0, is_date_hovered_1.isDateHovered)({
|
|
72
|
-
date
|
|
54
|
+
date,
|
|
73
55
|
hoveredDate,
|
|
74
|
-
startDate
|
|
75
|
-
endDate
|
|
56
|
+
startDate,
|
|
57
|
+
endDate,
|
|
76
58
|
minBookingDays,
|
|
77
59
|
exactMinBookingDays,
|
|
78
60
|
isDateBlocked: disabledDatesByUser,
|
|
@@ -101,45 +83,41 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
|
|
|
101
83
|
}, [onDatesChange]);
|
|
102
84
|
// eslint-disable-next-line complexity
|
|
103
85
|
function onDateSelect(date) {
|
|
104
|
-
const dateStr = (0, date_string_1.toDateString)(date);
|
|
105
86
|
if ((focusedInput === exports.END_DATE || focusedInput === exports.START_DATE) &&
|
|
106
87
|
minBookingDays > 0 &&
|
|
107
88
|
exactMinBookingDays &&
|
|
108
89
|
(0, can_select_range_1.canSelectRange)({
|
|
109
90
|
minBookingDays,
|
|
110
91
|
exactMinBookingDays,
|
|
111
|
-
minBookingDate
|
|
112
|
-
maxBookingDate
|
|
92
|
+
minBookingDate,
|
|
93
|
+
maxBookingDate,
|
|
113
94
|
isDateBlocked: disabledDatesByUser,
|
|
114
|
-
startDate:
|
|
95
|
+
startDate: date,
|
|
115
96
|
endDate: null,
|
|
116
97
|
})) {
|
|
117
98
|
onDatesChange({
|
|
118
|
-
startDate:
|
|
119
|
-
endDate: (0,
|
|
99
|
+
startDate: date,
|
|
100
|
+
endDate: (0, dayjs_utils_1.dayjsEnRaw)(date)
|
|
101
|
+
.add(minBookingDays - 1, "day")
|
|
102
|
+
.toDate(),
|
|
120
103
|
focusedInput: null,
|
|
121
104
|
});
|
|
122
105
|
}
|
|
123
|
-
else if ((((focusedInput === exports.END_DATE &&
|
|
124
|
-
(focusedInput === exports.START_DATE &&
|
|
106
|
+
else if ((((focusedInput === exports.END_DATE && startDate && (0, dayjs_utils_1.dayjsEnRaw)(date).isBefore(startDate)) ||
|
|
107
|
+
(focusedInput === exports.START_DATE && endDate && (0, dayjs_utils_1.dayjsEnRaw)(date).isAfter(endDate))) &&
|
|
125
108
|
!exactMinBookingDays &&
|
|
126
109
|
(0, can_select_range_1.canSelectRange)({
|
|
127
110
|
minBookingDays,
|
|
128
111
|
isDateBlocked: disabledDatesByUser,
|
|
129
|
-
startDate:
|
|
112
|
+
startDate: date,
|
|
130
113
|
endDate: null,
|
|
131
114
|
})) ||
|
|
132
115
|
(focusedInput === exports.START_DATE &&
|
|
133
116
|
!exactMinBookingDays &&
|
|
134
|
-
(0, can_select_range_1.canSelectRange)({
|
|
135
|
-
minBookingDays,
|
|
136
|
-
isDateBlocked: disabledDatesByUser,
|
|
137
|
-
endDate: normalizedEndDate,
|
|
138
|
-
startDate: dateStr,
|
|
139
|
-
}))) {
|
|
117
|
+
(0, can_select_range_1.canSelectRange)({ minBookingDays, isDateBlocked: disabledDatesByUser, endDate, startDate: date }))) {
|
|
140
118
|
onDatesChange({
|
|
141
119
|
endDate: null,
|
|
142
|
-
startDate:
|
|
120
|
+
startDate: date,
|
|
143
121
|
focusedInput: exports.END_DATE,
|
|
144
122
|
});
|
|
145
123
|
}
|
|
@@ -149,58 +127,51 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
|
|
|
149
127
|
minBookingDays,
|
|
150
128
|
isDateBlocked: disabledDatesByUser,
|
|
151
129
|
endDate: null,
|
|
152
|
-
startDate:
|
|
130
|
+
startDate: date,
|
|
153
131
|
})) {
|
|
154
132
|
onDatesChange({
|
|
155
133
|
endDate: null,
|
|
156
|
-
startDate:
|
|
134
|
+
startDate: date,
|
|
157
135
|
focusedInput: exports.END_DATE,
|
|
158
136
|
});
|
|
159
137
|
}
|
|
160
138
|
else if (focusedInput === exports.END_DATE &&
|
|
161
|
-
|
|
162
|
-
|
|
139
|
+
startDate &&
|
|
140
|
+
!(0, dayjs_utils_1.dayjsEnRaw)(date).isBefore(startDate) &&
|
|
163
141
|
!exactMinBookingDays &&
|
|
164
|
-
(0, can_select_range_1.canSelectRange)({
|
|
165
|
-
minBookingDays,
|
|
166
|
-
isDateBlocked: disabledDatesByUser,
|
|
167
|
-
startDate: normalizedStartDate,
|
|
168
|
-
endDate: dateStr,
|
|
169
|
-
})) {
|
|
142
|
+
(0, can_select_range_1.canSelectRange)({ minBookingDays, isDateBlocked: disabledDatesByUser, startDate, endDate: date })) {
|
|
170
143
|
onDatesChange({
|
|
171
|
-
startDate
|
|
172
|
-
endDate:
|
|
144
|
+
startDate,
|
|
145
|
+
endDate: date,
|
|
173
146
|
focusedInput: null,
|
|
174
147
|
});
|
|
175
148
|
}
|
|
176
149
|
if (focusedInput !== exports.END_DATE &&
|
|
177
|
-
(!focusedDate ||
|
|
150
|
+
(!focusedDate || !(0, dayjs_utils_1.dayjsEnRaw)(date).isSame(focusedDate, "month")) &&
|
|
178
151
|
changeActiveMonthOnSelect) {
|
|
179
|
-
setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths,
|
|
152
|
+
setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, date));
|
|
180
153
|
}
|
|
181
154
|
}
|
|
182
155
|
function onDatesSelect(start, end) {
|
|
183
|
-
const startStr = (0, date_string_1.toDateString)(start);
|
|
184
|
-
const endStr = end ? (0, date_string_1.toDateString)(end) : null;
|
|
185
156
|
if ((0, can_select_range_1.canSelectRange)({
|
|
186
157
|
minBookingDays,
|
|
187
158
|
exactMinBookingDays,
|
|
188
|
-
minBookingDate
|
|
189
|
-
maxBookingDate
|
|
159
|
+
minBookingDate,
|
|
160
|
+
maxBookingDate,
|
|
190
161
|
isDateBlocked: disabledDatesByUser,
|
|
191
|
-
startDate:
|
|
192
|
-
endDate:
|
|
162
|
+
startDate: start,
|
|
163
|
+
endDate: end,
|
|
193
164
|
})) {
|
|
194
165
|
onDatesChange({
|
|
195
|
-
endDate:
|
|
196
|
-
startDate:
|
|
166
|
+
endDate: end,
|
|
167
|
+
startDate: start,
|
|
197
168
|
focusedInput: exports.START_DATE,
|
|
198
169
|
});
|
|
199
170
|
}
|
|
200
171
|
if (focusedInput !== exports.END_DATE &&
|
|
201
|
-
(!focusedDate ||
|
|
172
|
+
(!focusedDate || !(0, dayjs_utils_1.dayjsEnRaw)(start).isSame(focusedDate, "month")) &&
|
|
202
173
|
changeActiveMonthOnSelect) {
|
|
203
|
-
setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths,
|
|
174
|
+
setActiveMonths((0, get_initial_months_1.getInitialMonths)(numberOfMonths, start));
|
|
204
175
|
}
|
|
205
176
|
}
|
|
206
177
|
// eslint-disable-next-line complexity
|
|
@@ -209,20 +180,20 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
|
|
|
209
180
|
setHoveredDate(null);
|
|
210
181
|
}
|
|
211
182
|
else {
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
? dateStr >= (0, date_string_1.addDays)(normalizedMinBookingDate, -1)
|
|
183
|
+
const isNotBlocked = !_isDateBlocked(date) || (startDate && (0, dayjs_utils_1.dayjsEnRaw)(date).isSame(startDate, "day"));
|
|
184
|
+
const isHoveredDateAfterOrEqualMinDate = minBookingDate
|
|
185
|
+
? !(0, dayjs_utils_1.dayjsEnRaw)(date).isBefore((0, dayjs_utils_1.dayjsEnRaw)(minBookingDate).subtract(1, "day"))
|
|
216
186
|
: true;
|
|
217
|
-
const isHoveredDateBeforeOrEqualMaxDate =
|
|
218
|
-
|
|
187
|
+
const isHoveredDateBeforeOrEqualMaxDate = maxBookingDate ? !(0, dayjs_utils_1.dayjsEnRaw)(date).isAfter(maxBookingDate) : true;
|
|
188
|
+
// Exact minimal booking days
|
|
189
|
+
const potentialEndDate = (0, dayjs_utils_1.dayjsEnRaw)(date)
|
|
190
|
+
.add(minBookingDays - 1, "day")
|
|
191
|
+
.toDate();
|
|
192
|
+
const isPotentialEndDateAfterOrEqualMinDate = minBookingDate
|
|
193
|
+
? !(0, dayjs_utils_1.dayjsEnRaw)(potentialEndDate).isBefore(minBookingDate)
|
|
219
194
|
: true;
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
? potentialEndDateStr >= normalizedMinBookingDate
|
|
223
|
-
: true;
|
|
224
|
-
const isPotentialEndDateBeforeOrEqualMaxDate = normalizedMaxBookingDate
|
|
225
|
-
? potentialEndDateStr <= normalizedMaxBookingDate
|
|
195
|
+
const isPotentialEndDateBeforeOrEqualMaxDate = maxBookingDate
|
|
196
|
+
? !(0, dayjs_utils_1.dayjsEnRaw)(potentialEndDate).isAfter(maxBookingDate)
|
|
226
197
|
: true;
|
|
227
198
|
const isExactAndInRange = exactMinBookingDays &&
|
|
228
199
|
minBookingDays > 1 &&
|
|
@@ -230,17 +201,19 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
|
|
|
230
201
|
isHoveredDateBeforeOrEqualMaxDate &&
|
|
231
202
|
isPotentialEndDateAfterOrEqualMinDate &&
|
|
232
203
|
isPotentialEndDateBeforeOrEqualMaxDate;
|
|
233
|
-
|
|
234
|
-
|
|
204
|
+
// Is date in range
|
|
205
|
+
const isInRange = startDate &&
|
|
206
|
+
!endDate &&
|
|
235
207
|
!exactMinBookingDays &&
|
|
236
208
|
isHoveredDateAfterOrEqualMinDate &&
|
|
237
209
|
isHoveredDateBeforeOrEqualMaxDate;
|
|
238
|
-
|
|
239
|
-
|
|
210
|
+
// Is start date hovered and in range
|
|
211
|
+
const isMinBookingDaysInRange = minBookingDays > 1 && startDate
|
|
212
|
+
? (0, dayjs_utils_1.dayjsEnRaw)(date).isBetween(startDate, (0, dayjs_utils_1.dayjsEnRaw)(startDate).add(minBookingDays - 2, "day"))
|
|
240
213
|
: true;
|
|
241
|
-
const isStartDateHoveredAndInRange =
|
|
214
|
+
const isStartDateHoveredAndInRange = startDate && (0, dayjs_utils_1.dayjsEnRaw)(date).isSame(startDate, "day") && isMinBookingDaysInRange;
|
|
242
215
|
if (isNotBlocked && (isExactAndInRange || isInRange || isStartDateHoveredAndInRange)) {
|
|
243
|
-
setHoveredDate(
|
|
216
|
+
setHoveredDate(date);
|
|
244
217
|
}
|
|
245
218
|
else if (hoveredDate !== null) {
|
|
246
219
|
setHoveredDate(null);
|
|
@@ -250,17 +223,17 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
|
|
|
250
223
|
return {
|
|
251
224
|
...(0, use_date_picker_navigation_1.useDatePickerNavigation)({
|
|
252
225
|
activeMonths,
|
|
253
|
-
maxBookingDate
|
|
254
|
-
minBookingDate
|
|
226
|
+
maxBookingDate,
|
|
227
|
+
minBookingDate,
|
|
255
228
|
numberOfMonths,
|
|
256
229
|
setActiveMonths,
|
|
257
|
-
setFocusedDate
|
|
230
|
+
setFocusedDate,
|
|
258
231
|
}),
|
|
259
232
|
activeMonths,
|
|
260
233
|
datesConfig,
|
|
261
234
|
firstDayOfWeek,
|
|
262
|
-
focusedDate
|
|
263
|
-
hoveredDate
|
|
235
|
+
focusedDate,
|
|
236
|
+
hoveredDate,
|
|
264
237
|
isDateBlocked: _isDateBlocked,
|
|
265
238
|
isDateFocused,
|
|
266
239
|
isDateHovered: _isDateHovered,
|
|
@@ -274,6 +247,6 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, datesConfig = [
|
|
|
274
247
|
onDateSelect,
|
|
275
248
|
onDatesSelect,
|
|
276
249
|
onResetDates,
|
|
277
|
-
unavailableDates:
|
|
250
|
+
unavailableDates: disabledDates,
|
|
278
251
|
};
|
|
279
252
|
}
|