@uxf/datepicker 10.0.0 → 10.8.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.
@@ -30,4 +30,5 @@ exports.DatePickerContext = (0, react_1.createContext)({
30
30
  onDateSelect: () => undefined,
31
31
  onResetDates: () => undefined,
32
32
  preventScroll: undefined,
33
+ unavailableDates: [],
33
34
  });
@@ -32,4 +32,5 @@ exports.DateRangePickerContext = (0, react_1.createContext)({
32
32
  onDateHover: () => undefined,
33
33
  onDateSelect: () => undefined,
34
34
  onResetDates: () => undefined,
35
+ unavailableDates: [],
35
36
  });
@@ -28,5 +28,6 @@ export interface UseDatePickerReturnType extends UseDatePickerNavigationReturnTy
28
28
  onDateSelect: (date: Date) => void;
29
29
  onResetDates: () => void;
30
30
  preventScroll?: boolean;
31
+ unavailableDates: Date[];
31
32
  }
32
33
  export declare function useDatePicker({ firstDayOfWeek, initialVisibleMonth, isDateBlocked: isDateBlockedProps, maxBookingDate, minBookingDate, numberOfMonths, onDateChange, preventScroll, selectedDate, unavailableDates, }: UseDatePickerProps): UseDatePickerReturnType;
@@ -110,6 +110,7 @@ function useDatePicker({ firstDayOfWeek = 0, initialVisibleMonth, isDateBlocked:
110
110
  onDateSelect,
111
111
  onResetDates: onReset,
112
112
  preventScroll,
113
+ unavailableDates,
113
114
  };
114
115
  }
115
116
  exports.useDatePicker = useDatePicker;
@@ -43,5 +43,6 @@ export interface UseDateRangePickerReturnType extends UseDatePickerNavigationRet
43
43
  onDateSelect: (date: Date) => void;
44
44
  onResetDates: () => void;
45
45
  preventScroll?: boolean;
46
+ unavailableDates: Date[];
46
47
  }
47
48
  export declare function useDateRangePicker({ changeActiveMonthOnSelect, endDate, exactMinBookingDays, firstDayOfWeek, focusedInput, initialVisibleMonth, isDateBlocked: isDateBlockedProps, maxBookingDate, minBookingDate, minBookingDays, numberOfMonths, onDatesChange, startDate, unavailableDates, }: UseDateRangePickerProps): UseDateRangePickerReturnType;
@@ -220,6 +220,7 @@ function useDateRangePicker({ changeActiveMonthOnSelect = false, endDate, exactM
220
220
  onDateHover,
221
221
  onDateSelect,
222
222
  onResetDates,
223
+ unavailableDates,
223
224
  };
224
225
  }
225
226
  exports.useDateRangePicker = useDateRangePicker;
@@ -12,8 +12,11 @@ export interface UseDayProps {
12
12
  onDateHover: (date: Date) => void;
13
13
  onDateSelect: (date: Date) => void;
14
14
  preventScroll?: boolean;
15
+ unavailableDates: Date[];
15
16
  }
16
17
  export interface UseDayReturnType {
18
+ isFirstDisabled: boolean;
19
+ isLastDisabled: boolean;
17
20
  disabledDate: boolean;
18
21
  isHovered: boolean;
19
22
  isSelected: boolean;
@@ -25,4 +28,4 @@ export interface UseDayReturnType {
25
28
  onMouseEnter: () => void;
26
29
  tabIndex: number;
27
30
  }
28
- export declare function useDay({ date, dayRef, focusedDate, isDateBlocked, isDateFocused, isDateHovered, isDateInsideRange, isDateSelected, onDateFocus, onDateHover, onDateSelect, preventScroll, }: UseDayProps): UseDayReturnType;
31
+ export declare function useDay({ date, dayRef, focusedDate, isDateBlocked, isDateFocused, isDateHovered, isDateInsideRange, isDateSelected, onDateFocus, onDateHover, onDateSelect, preventScroll, unavailableDates, }: UseDayProps): UseDayReturnType;
package/hooks/use-day.js CHANGED
@@ -1,9 +1,14 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.useDay = void 0;
7
+ const dayjs_1 = __importDefault(require("dayjs"));
4
8
  const react_1 = require("react");
5
9
  const dayjs_en_1 = require("../utils/dayjs-en");
6
- function useDay({ date, dayRef, focusedDate, isDateBlocked, isDateFocused, isDateHovered, isDateInsideRange, isDateSelected, onDateFocus, onDateHover, onDateSelect, preventScroll, }) {
10
+ const get_date_invervals_1 = require("../utils/get-date-invervals");
11
+ function useDay({ date, dayRef, focusedDate, isDateBlocked, isDateFocused, isDateHovered, isDateInsideRange, isDateSelected, onDateFocus, onDateHover, onDateSelect, preventScroll, unavailableDates, }) {
7
12
  const onClick = (0, react_1.useCallback)(() => onDateSelect(date), [date, onDateSelect]);
8
13
  const onMouseEnter = (0, react_1.useCallback)(() => onDateHover(date), [date, onDateHover]);
9
14
  const disabled = isDateBlocked(date) && !isDateHovered(date);
@@ -34,8 +39,18 @@ function useDay({ date, dayRef, focusedDate, isDateBlocked, isDateFocused, isDat
34
39
  }
35
40
  }
36
41
  }, [date, onDateFocus]);
42
+ const sortedUnavailableDates = unavailableDates.slice().sort((a, b) => a.getTime() - b.getTime());
43
+ const dateIntervals = (0, get_date_invervals_1.getDateIntervals)(sortedUnavailableDates);
44
+ const _isFirstUnavailableDate = () => {
45
+ return dateIntervals.some((interval) => (0, dayjs_1.default)(interval.start).isSame(date, "day"));
46
+ };
47
+ const _isLastUnavailableDate = () => {
48
+ return dateIntervals.some((interval) => (0, dayjs_1.default)(interval.end).isSame(date, "day"));
49
+ };
37
50
  return {
38
51
  disabledDate: disabled,
52
+ isFirstDisabled: _isFirstUnavailableDate(),
53
+ isLastDisabled: _isLastUnavailableDate(),
39
54
  isHovered: isDateHovered(date),
40
55
  isSelected: isDateSelected(date),
41
56
  isInsideRange: isDateInsideRange ? isDateInsideRange(date) : false,
@@ -24,9 +24,36 @@ test("useDay", () => {
24
24
  isDateInsideRange: () => false,
25
25
  onDateHover: () => undefined,
26
26
  onDateSelect: () => undefined,
27
+ unavailableDates: [],
27
28
  }));
28
29
  expect(result.current.tabIndex).toBe(0);
29
30
  expect(result.current.disabledDate).toBe(false);
31
+ expect(result.current.isFirstDisabled).toBe(false);
32
+ expect(result.current.isLastDisabled).toBe(false);
33
+ expect(result.current.isHovered).toBe(false);
34
+ expect(result.current.isToday).toBe(false);
35
+ expect(result.current.isSelected).toBe(false);
36
+ expect(result.current.isInsideRange).toBe(false);
37
+ expect(result.current.isWithinHoverRange).toBe(false);
38
+ });
39
+ test("useDay with unavailableDates", () => {
40
+ const { result } = (0, react_hooks_1.renderHook)(() => (0, use_day_1.useDay)({
41
+ date: new Date("2021-09-05"),
42
+ isDateBlocked: () => true,
43
+ focusedDate: null,
44
+ onDateFocus: () => undefined,
45
+ isDateFocused: () => false,
46
+ isDateHovered: () => false,
47
+ isDateSelected: () => false,
48
+ isDateInsideRange: () => false,
49
+ onDateHover: () => undefined,
50
+ onDateSelect: () => undefined,
51
+ unavailableDates: [new Date("2021-09-05")],
52
+ }));
53
+ expect(result.current.tabIndex).toBe(0);
54
+ expect(result.current.disabledDate).toBe(true);
55
+ expect(result.current.isFirstDisabled).toBe(true);
56
+ expect(result.current.isLastDisabled).toBe(true);
30
57
  expect(result.current.isHovered).toBe(false);
31
58
  expect(result.current.isToday).toBe(false);
32
59
  expect(result.current.isSelected).toBe(false);
@@ -51,6 +78,7 @@ test("actions", () => {
51
78
  onDateHover: (date) => (hoveredDate = date),
52
79
  onDateSelect: (date) => (selectedDate = date),
53
80
  dayRef: ref.current,
81
+ unavailableDates: [new Date("2021-09-05")],
54
82
  }));
55
83
  // hover
56
84
  expect(result.current.isHovered).toBe(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/datepicker",
3
- "version": "10.0.0",
3
+ "version": "10.8.0",
4
4
  "description": "A set of React hooks to create an awesome datepicker.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const dayjs_1 = __importDefault(require("dayjs"));
7
+ const get_date_invervals_1 = require("./get-date-invervals");
8
+ describe("getDateIntervals", () => {
9
+ it("should return empty array for empty input", () => {
10
+ expect((0, get_date_invervals_1.getDateIntervals)([])).toStrictEqual([]);
11
+ });
12
+ it("should return single date as an interval", () => {
13
+ const date = (0, dayjs_1.default)("2023-10-12").toDate();
14
+ expect((0, get_date_invervals_1.getDateIntervals)([date])).toStrictEqual([{ start: date, end: date }]);
15
+ });
16
+ it("should group contiguous dates into intervals", () => {
17
+ const dates = [
18
+ (0, dayjs_1.default)("2023-10-12").toDate(),
19
+ (0, dayjs_1.default)("2023-10-13").toDate(),
20
+ (0, dayjs_1.default)("2023-10-14").toDate(),
21
+ (0, dayjs_1.default)("2023-10-16").toDate(),
22
+ (0, dayjs_1.default)("2023-10-17").toDate(),
23
+ ];
24
+ const expected = [
25
+ { start: dates[0], end: dates[2] },
26
+ { start: dates[3], end: dates[4] },
27
+ ];
28
+ expect((0, get_date_invervals_1.getDateIntervals)(dates)).toStrictEqual(expected);
29
+ });
30
+ it("should handle non-contiguous dates", () => {
31
+ const dates = [(0, dayjs_1.default)("2023-10-12").toDate(), (0, dayjs_1.default)("2023-10-14").toDate(), (0, dayjs_1.default)("2023-10-16").toDate()];
32
+ const expected = [
33
+ { start: dates[0], end: dates[0] },
34
+ { start: dates[1], end: dates[1] },
35
+ { start: dates[2], end: dates[2] },
36
+ ];
37
+ expect((0, get_date_invervals_1.getDateIntervals)(dates)).toStrictEqual(expected);
38
+ });
39
+ });
@@ -0,0 +1,3 @@
1
+ type ReturnType = Record<"start" | "end", Date>[];
2
+ export declare function getDateIntervals(dates: Date[]): ReturnType;
3
+ export {};
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getDateIntervals = void 0;
7
+ const dayjs_1 = __importDefault(require("dayjs"));
8
+ function getDateIntervals(dates) {
9
+ const intervals = [];
10
+ let currentStart = dates[0];
11
+ let currentEnd = dates[0];
12
+ for (let i = 1; i < dates.length; i++) {
13
+ const currentDate = dates[i];
14
+ const nextDate = (0, dayjs_1.default)(currentEnd).add(1, "day").toDate();
15
+ // If the current date matches the expected next date, it's contiguous
16
+ if ((0, dayjs_1.default)(currentDate).isSame(nextDate, "day")) {
17
+ currentEnd = currentDate;
18
+ }
19
+ else {
20
+ intervals.push({ start: currentStart, end: currentEnd });
21
+ currentStart = currentDate;
22
+ currentEnd = currentDate;
23
+ }
24
+ }
25
+ if (dates[0]) {
26
+ // Push the last interval
27
+ intervals.push({ start: currentStart, end: currentEnd });
28
+ }
29
+ return intervals;
30
+ }
31
+ exports.getDateIntervals = getDateIntervals;