willba-component-library 0.2.56 → 0.2.58
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/lib/components/FilterCalendar/FilterCalendar.stories.d.ts +1 -0
- package/lib/index.esm.js +78 -54
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +78 -54
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +78 -54
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/FilterCalendar/FilterCalendar.stories.tsx +436 -29
- package/src/core/components/calendar/utils/calendarSelectionRules.tsx +92 -76
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addDays,
|
|
3
|
-
startOfDay,
|
|
4
|
-
format,
|
|
5
|
-
isAfter,
|
|
6
|
-
isBefore,
|
|
7
|
-
endOfDay,
|
|
8
|
-
} from 'date-fns'
|
|
1
|
+
import { addDays, isAfter, isBefore, endOfDay, isEqual } from 'date-fns'
|
|
9
2
|
import { DateRange, Matcher } from 'react-day-picker'
|
|
10
3
|
|
|
11
4
|
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
@@ -33,30 +26,31 @@ export const calendarSelectionRules = ({
|
|
|
33
26
|
rangeContext,
|
|
34
27
|
}: Props) => {
|
|
35
28
|
// Get and parse needed data
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
? format(calendarRange?.from, dateFormat)
|
|
41
|
-
: null
|
|
42
|
-
const calendarTo = calendarRange?.to
|
|
43
|
-
? format(calendarRange?.to, dateFormat)
|
|
29
|
+
const rangeFrom = range?.from ? endOfDay(range.from) : null
|
|
30
|
+
const rangeTo = range?.to ? endOfDay(range.to) : null
|
|
31
|
+
const calendarRangeFrom = calendarRange?.from
|
|
32
|
+
? endOfDay(calendarRange.from)
|
|
44
33
|
: null
|
|
34
|
+
const calendarRangeTo = calendarRange?.to ? endOfDay(calendarRange.to) : null
|
|
35
|
+
|
|
45
36
|
const rangeContextFrom = rangeContext?.from
|
|
46
|
-
?
|
|
37
|
+
? endOfDay(rangeContext.from)
|
|
47
38
|
: null
|
|
39
|
+
const rangeContextTo = rangeContext?.to ? endOfDay(rangeContext.to) : null
|
|
48
40
|
|
|
49
41
|
const overlappingDateFrom = overlappingDate?.length
|
|
50
42
|
? overlappingDate.find((date) =>
|
|
51
|
-
|
|
43
|
+
!!(date.from && rangeFrom)
|
|
44
|
+
? isEqual(endOfDay(date.from), rangeFrom)
|
|
45
|
+
: false
|
|
52
46
|
)
|
|
53
47
|
: null
|
|
54
48
|
|
|
55
49
|
const checkOutRange = newDisableCalendarDates?.availableDates?.length
|
|
56
|
-
? newDisableCalendarDates.availableDates.find(
|
|
57
|
-
(checkInDate)
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
? newDisableCalendarDates.availableDates.find((checkInDate) =>
|
|
51
|
+
!!(checkInDate.checkIn && rangeFrom)
|
|
52
|
+
? isEqual(endOfDay(checkInDate.checkIn), rangeFrom)
|
|
53
|
+
: false
|
|
60
54
|
)
|
|
61
55
|
: null
|
|
62
56
|
|
|
@@ -65,57 +59,85 @@ export const calendarSelectionRules = ({
|
|
|
65
59
|
rangeFrom,
|
|
66
60
|
checkOutRange,
|
|
67
61
|
setDisabledDates,
|
|
68
|
-
dateFormat,
|
|
69
62
|
newDisableCalendarDates,
|
|
70
63
|
})
|
|
71
64
|
|
|
72
|
-
// Calendar selection rules
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return setCalendarRange({ from: calendarRange?.from, to: undefined })
|
|
81
|
-
|
|
82
|
-
case range?.to &&
|
|
83
|
-
calendarRange?.to &&
|
|
84
|
-
isAfter(endOfDay(range.to), endOfDay(calendarRange.to)) &&
|
|
85
|
-
!(
|
|
86
|
-
range?.to &&
|
|
87
|
-
rangeContext?.to &&
|
|
88
|
-
isAfter(startOfDay(range.to), startOfDay(rangeContext.to))
|
|
89
|
-
):
|
|
90
|
-
// Handle checkout selection greater than current checkout
|
|
91
|
-
return setCalendarRange({ from: range?.to, to: undefined })
|
|
92
|
-
|
|
93
|
-
case calendarFrom && rangeFrom && rangeFrom !== calendarFrom:
|
|
94
|
-
// Handle check-in selection prior to current check-in
|
|
95
|
-
return setCalendarRange({ from: range?.from, to: undefined })
|
|
96
|
-
|
|
97
|
-
case checkOutRange && range?.to && checkOutRange.lastCheckOut < range.to:
|
|
98
|
-
return setCalendarRange({ from: range?.to, to: undefined })
|
|
99
|
-
|
|
100
|
-
// Handle checkout selection between the range context and first passible check-in
|
|
101
|
-
case range?.to &&
|
|
102
|
-
rangeContext?.from &&
|
|
103
|
-
isBefore(startOfDay(range.to), startOfDay(rangeContext.from)):
|
|
104
|
-
return setCalendarRange({ from: range?.to, to: undefined })
|
|
105
|
-
|
|
106
|
-
case range?.from &&
|
|
107
|
-
rangeContext?.to &&
|
|
108
|
-
isAfter(startOfDay(range.from), startOfDay(rangeContext.to)):
|
|
109
|
-
return (
|
|
110
|
-
setCalendarRange(undefined),
|
|
111
|
-
setCalendarHasError && setCalendarHasError(true)
|
|
112
|
-
)
|
|
113
|
-
//
|
|
65
|
+
// Calendar selection rules: The cases are handled sequentially, starting from simple selections to more complex contextual selections.
|
|
66
|
+
// The rules are processed in a specific order, so one case is handled before another.
|
|
67
|
+
// Changing the order will cause the rules to break or not work properly.
|
|
68
|
+
|
|
69
|
+
if (!!overlappingDateFrom) {
|
|
70
|
+
// 1. If dates overlap, clear the selection.
|
|
71
|
+
return setCalendarRange(undefined)
|
|
72
|
+
}
|
|
114
73
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
74
|
+
if (
|
|
75
|
+
// 2. If selected "start" is after "range context end", clear selection and display error
|
|
76
|
+
(rangeFrom && rangeContextTo && isAfter(rangeFrom, rangeContextTo)) ||
|
|
77
|
+
(calendarRangeFrom &&
|
|
78
|
+
calendarRangeTo &&
|
|
79
|
+
rangeContextTo &&
|
|
80
|
+
rangeTo &&
|
|
81
|
+
isAfter(rangeTo, rangeContextTo))
|
|
82
|
+
) {
|
|
83
|
+
setCalendarHasError && setCalendarHasError(true)
|
|
84
|
+
return setCalendarRange(undefined)
|
|
118
85
|
}
|
|
86
|
+
|
|
87
|
+
if (rangeFrom && rangeTo && isEqual(rangeFrom, rangeTo)) {
|
|
88
|
+
// 3. If "start" is selected and the same date is clicked again, keep the current "start" selection.
|
|
89
|
+
return setCalendarRange({ from: rangeFrom, to: undefined })
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (calendarRangeFrom && calendarRangeTo && !range) {
|
|
93
|
+
// 4. If "calendarRange" has dates selected and the same "start" date is clicked, the "range" will become undefined.
|
|
94
|
+
// Set the current selection (calendarRange) to the initial "start" of calendarRange.
|
|
95
|
+
return setCalendarRange({ from: calendarRangeFrom, to: undefined })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 5. Handle gap selection backwards and forwards
|
|
99
|
+
if (
|
|
100
|
+
// Enforce on every date selection before current "start", mark as "start" selection
|
|
101
|
+
rangeFrom &&
|
|
102
|
+
calendarRangeFrom &&
|
|
103
|
+
isBefore(rangeFrom, calendarRangeFrom)
|
|
104
|
+
) {
|
|
105
|
+
return setCalendarRange({ from: rangeFrom, to: undefined })
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (
|
|
109
|
+
// Every date selection that is after selected "start" last checkout, mark as "start"
|
|
110
|
+
rangeTo &&
|
|
111
|
+
checkOutRange?.lastCheckOut &&
|
|
112
|
+
isAfter(rangeTo, endOfDay(checkOutRange.lastCheckOut))
|
|
113
|
+
) {
|
|
114
|
+
return setCalendarRange({ from: rangeTo, to: undefined })
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (
|
|
118
|
+
calendarRangeFrom &&
|
|
119
|
+
rangeFrom &&
|
|
120
|
+
!isEqual(calendarRangeFrom, rangeFrom)
|
|
121
|
+
) {
|
|
122
|
+
// 6. If "calendarRange" has selected dates and the new selection "start" differs from the current "calendarRange start", reset and make a new "start" selection.
|
|
123
|
+
return setCalendarRange({ from: rangeFrom, to: undefined })
|
|
124
|
+
} else if (calendarRangeTo && rangeTo && !isEqual(calendarRangeTo, rangeTo)) {
|
|
125
|
+
// 7. If "calendarRange" has selected dates and the new selection "end" differs from the current "calendarRange end", reset and make a new "start" selection.
|
|
126
|
+
return setCalendarRange({ from: rangeTo, to: undefined })
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (
|
|
130
|
+
// 8. If selected "end" is before "context start", mark as "start" and display error
|
|
131
|
+
rangeFrom &&
|
|
132
|
+
rangeTo &&
|
|
133
|
+
rangeContextFrom &&
|
|
134
|
+
isBefore(rangeTo, rangeContextFrom)
|
|
135
|
+
) {
|
|
136
|
+
setCalendarHasError && setCalendarHasError(true)
|
|
137
|
+
return setCalendarRange({ from: rangeTo, to: undefined })
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
setCalendarRange(range)
|
|
119
141
|
}
|
|
120
142
|
|
|
121
143
|
/////////
|
|
@@ -124,26 +146,20 @@ const disableFutureDates = ({
|
|
|
124
146
|
rangeFrom,
|
|
125
147
|
checkOutRange,
|
|
126
148
|
setDisabledDates,
|
|
127
|
-
dateFormat,
|
|
128
149
|
newDisableCalendarDates,
|
|
129
150
|
}: {
|
|
130
|
-
rangeFrom:
|
|
151
|
+
rangeFrom: Date | null
|
|
131
152
|
checkOutRange?:
|
|
132
153
|
| NonNullable<DisableCalendarDates['availableDates']>['0']
|
|
133
154
|
| null
|
|
134
155
|
setDisabledDates?: (arg: Matcher[]) => void
|
|
135
|
-
dateFormat: string
|
|
136
156
|
newDisableCalendarDates?: DisableCalendarDates
|
|
137
157
|
}) => {
|
|
138
158
|
if (rangeFrom && checkOutRange && setDisabledDates) {
|
|
139
159
|
// Get and parse data
|
|
140
160
|
const checkIn = addDays(checkOutRange.checkIn, 1)
|
|
141
161
|
const firstCheckOut = addDays(checkOutRange.firstCheckOut, -1)
|
|
142
|
-
const noDatesRange =
|
|
143
|
-
format(checkIn, dateFormat) ===
|
|
144
|
-
format(checkOutRange.firstCheckOut, dateFormat)
|
|
145
|
-
|
|
146
|
-
// -------------------
|
|
162
|
+
const noDatesRange = isEqual(checkIn, checkOutRange.firstCheckOut)
|
|
147
163
|
|
|
148
164
|
setDisabledDates([
|
|
149
165
|
// Will disable all dates before the check-in date
|