1 | import React from "react";
|
2 |
|
3 | import type {
|
4 | DateLib,
|
5 | DateRange,
|
6 | DayPickerProps,
|
7 | Modifiers,
|
8 | PropsRange,
|
9 | Selection
|
10 | } from "../types/index.js";
|
11 | import { addToRange, dateMatchModifiers } from "../utils/index.js";
|
12 | import { rangeIncludesDate } from "../utils/rangeIncludesDate.js";
|
13 |
|
14 | export function useRange<T extends DayPickerProps>(
|
15 | props: T,
|
16 | dateLib: DateLib
|
17 | ): Selection<T> {
|
18 | const {
|
19 | disabled,
|
20 | excludeDisabled,
|
21 | selected: initiallySelected,
|
22 | required,
|
23 | onSelect
|
24 | } = props as PropsRange;
|
25 |
|
26 | const [selected, setSelected] = React.useState<DateRange | undefined>(
|
27 | initiallySelected
|
28 | );
|
29 |
|
30 |
|
31 | React.useEffect(() => {
|
32 | setSelected(initiallySelected);
|
33 | }, [initiallySelected]);
|
34 |
|
35 | const isSelected = (date: Date) =>
|
36 | selected && rangeIncludesDate(selected, date, false, dateLib);
|
37 |
|
38 | const select = (
|
39 | triggerDate: Date,
|
40 | modifiers: Modifiers,
|
41 | e: React.MouseEvent | React.KeyboardEvent
|
42 | ) => {
|
43 | const { min, max } = props as PropsRange;
|
44 | const newRange = triggerDate
|
45 | ? addToRange(triggerDate, selected, min, max, required, dateLib)
|
46 | : undefined;
|
47 |
|
48 | if (newRange?.from && newRange.to) {
|
49 | let newDate = newRange.from;
|
50 | while (dateLib.differenceInCalendarDays(newRange.to, newDate) > 0) {
|
51 | newDate = dateLib.addDays(newDate, 1);
|
52 | if (
|
53 | excludeDisabled &&
|
54 | disabled &&
|
55 | dateMatchModifiers(newDate, disabled, dateLib)
|
56 | ) {
|
57 |
|
58 | newRange.from = triggerDate;
|
59 | newRange.to = undefined;
|
60 | break;
|
61 | }
|
62 | }
|
63 | }
|
64 |
|
65 | setSelected(newRange);
|
66 | onSelect?.(newRange, triggerDate, modifiers, e);
|
67 |
|
68 | return newRange;
|
69 | };
|
70 |
|
71 | return {
|
72 | selected,
|
73 | select,
|
74 | isSelected
|
75 | } as Selection<T>;
|
76 | }
|