willba-component-library 0.2.23 → 0.2.25
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/index.esm.js +94 -100
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +93 -99
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +93 -99
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/core/components/calendar/Calendar.css +24 -6
- package/src/core/components/calendar/Calendar.tsx +123 -115
- package/src/locales/en/common.json +2 -1
- package/src/locales/fi/common.json +2 -1
package/package.json
CHANGED
|
@@ -87,7 +87,8 @@
|
|
|
87
87
|
|
|
88
88
|
/* Tooltip */
|
|
89
89
|
.will-root .will-calendar-filter-container .will-calendar-tooltip,
|
|
90
|
-
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out
|
|
90
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out,
|
|
91
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-overlapping-date {
|
|
91
92
|
position: absolute;
|
|
92
93
|
top: -42px;
|
|
93
94
|
transform: translateX(calc(-50% + 20px));
|
|
@@ -96,7 +97,8 @@
|
|
|
96
97
|
z-index: 2;
|
|
97
98
|
}
|
|
98
99
|
.will-root .will-calendar-filter-container .will-calendar-tooltip > div,
|
|
99
|
-
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out> div
|
|
100
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out > div,
|
|
101
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-overlapping-date > div {
|
|
100
102
|
background-color: white;
|
|
101
103
|
position: relative;
|
|
102
104
|
padding: 5px 10px;
|
|
@@ -105,7 +107,8 @@
|
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
.will-root .will-calendar-filter-container .will-calendar-tooltip::before,
|
|
108
|
-
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out::before
|
|
110
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out::before,
|
|
111
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-overlapping-date::before {
|
|
109
112
|
content: "";
|
|
110
113
|
width: 10px;
|
|
111
114
|
height: 10px;
|
|
@@ -119,7 +122,8 @@
|
|
|
119
122
|
}
|
|
120
123
|
|
|
121
124
|
.will-root .will-calendar-filter-container .rdp-cell:hover .will-calendar-tooltip,
|
|
122
|
-
.will-root .will-calendar-filter-container .rdp-cell:hover .will-calendar-tooltip-check-out
|
|
125
|
+
.will-root .will-calendar-filter-container .rdp-cell:hover .will-calendar-tooltip-check-out,
|
|
126
|
+
.will-root .will-calendar-filter-container .rdp-cell:hover .will-calendar-tooltip-overlapping-date {
|
|
123
127
|
display: block;
|
|
124
128
|
}
|
|
125
129
|
|
|
@@ -145,8 +149,22 @@
|
|
|
145
149
|
|
|
146
150
|
/* No active selection */
|
|
147
151
|
|
|
148
|
-
.will-root .will-calendar-filter-container .no-active-selection
|
|
149
|
-
|
|
152
|
+
.will-root .will-calendar-filter-container .rdp-day_selected.rdp-day_range_start.no-active-selection,
|
|
153
|
+
.will-root .will-calendar-filter-container .rdp-day_selected.rdp-day_range_middle.no-active-selection,
|
|
154
|
+
.will-root .will-calendar-filter-container .rdp-day_selected.rdp-day_range_end.no-active-selection {
|
|
155
|
+
background-color: var(--will-grey);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Overlapping date */
|
|
159
|
+
|
|
160
|
+
.will-root .will-calendar-filter-container .overlapping-date {
|
|
161
|
+
user-select: none;
|
|
162
|
+
pointer-events: none;
|
|
163
|
+
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.will-root .will-calendar-filter-container .overlapping-date:hover {
|
|
167
|
+
cursor: not-allowed;
|
|
150
168
|
}
|
|
151
169
|
|
|
152
170
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef, useEffect } from 'react'
|
|
1
|
+
import React, { forwardRef, useEffect, useMemo, useState } from 'react'
|
|
2
2
|
import { addDays, startOfDay, format } from 'date-fns'
|
|
3
3
|
import { fi, enUS } from 'date-fns/locale'
|
|
4
4
|
import { useTranslation } from 'react-i18next'
|
|
@@ -36,19 +36,61 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
36
36
|
const today = startOfDay(new Date())
|
|
37
37
|
const selectedStartDate = calendarRange?.from
|
|
38
38
|
|
|
39
|
+
// Handle loading spinner
|
|
39
40
|
useEffect(() => {
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
if (typeof document === 'undefined') return
|
|
42
|
+
const loadingSpinner: HTMLElement | null = document.querySelector(
|
|
43
|
+
'.will-filter-bar-calendar .will-calendar-spinner'
|
|
44
|
+
)
|
|
45
|
+
if (loadingData) {
|
|
46
|
+
if (loadingSpinner) loadingSpinner.style.display = 'flex'
|
|
47
|
+
} else {
|
|
48
|
+
if (loadingSpinner) loadingSpinner.style.display = 'none'
|
|
49
|
+
}
|
|
50
|
+
}, [loadingData])
|
|
51
|
+
|
|
52
|
+
// Handle overlapping availableDates.lastCheckOut and disabledDates.start
|
|
53
|
+
const [overlappingDate, setOverlappingDate] = useState<
|
|
54
|
+
DateRange | undefined
|
|
55
|
+
>(undefined)
|
|
56
|
+
|
|
57
|
+
useMemo(() => {
|
|
58
|
+
if (disableCalendarDates?.availableDates) {
|
|
59
|
+
const dateFormat = 'dd-MM-yyyy'
|
|
60
|
+
|
|
61
|
+
const availableDateMap = new Map()
|
|
62
|
+
disableCalendarDates.availableDates?.forEach((available) => {
|
|
63
|
+
availableDateMap.set(
|
|
64
|
+
format(available.lastCheckOut, dateFormat),
|
|
65
|
+
available
|
|
66
|
+
)
|
|
49
67
|
})
|
|
68
|
+
|
|
69
|
+
const updatedDisabledDates = disableCalendarDates.disabledDates?.map(
|
|
70
|
+
(dateRange) => {
|
|
71
|
+
const formattedFromDate = format(dateRange.from, dateFormat)
|
|
72
|
+
if (availableDateMap.has(formattedFromDate)) {
|
|
73
|
+
setOverlappingDate(dateRange)
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
...dateRange,
|
|
77
|
+
from: addDays(dateRange.from, 1),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return dateRange
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
disableCalendarDates.disabledDates = updatedDisabledDates
|
|
50
85
|
}
|
|
51
|
-
}, [disableCalendarDates
|
|
86
|
+
}, [disableCalendarDates])
|
|
87
|
+
|
|
88
|
+
// Handle disable dates by page
|
|
89
|
+
const disabledDatesByPage = handleDisabledDatesByPage({
|
|
90
|
+
today,
|
|
91
|
+
selectedPath,
|
|
92
|
+
disableCalendarDates,
|
|
93
|
+
})
|
|
52
94
|
|
|
53
95
|
// Handle tooltip
|
|
54
96
|
useEffect(() => {
|
|
@@ -58,6 +100,11 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
58
100
|
const calendarTooltipCheckOut = document.querySelector(
|
|
59
101
|
'.will-calendar-tooltip-check-out'
|
|
60
102
|
)
|
|
103
|
+
|
|
104
|
+
const calendarTooltipOverlappingDate = document.querySelector(
|
|
105
|
+
'.will-calendar-tooltip-overlapping-date'
|
|
106
|
+
)
|
|
107
|
+
|
|
61
108
|
const loadingSpinner = document.querySelector(
|
|
62
109
|
'.will-filter-bar-calendar .will-calendar-spinner'
|
|
63
110
|
)
|
|
@@ -70,6 +117,13 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
70
117
|
const calendarMonthContainer = document.querySelector(
|
|
71
118
|
'.will-filter-bar-calendar .rdp-months'
|
|
72
119
|
)
|
|
120
|
+
const calendarOverlappingDate = document.querySelector(
|
|
121
|
+
'.will-filter-bar-calendar .rdp-cell:has(.overlapping-date)'
|
|
122
|
+
)
|
|
123
|
+
const appendedOverlappingDateTooltip: HTMLElement | null =
|
|
124
|
+
document.querySelector(
|
|
125
|
+
'.will-filter-bar-calendar .rdp-cell .will-calendar-tooltip-overlapping-date'
|
|
126
|
+
)
|
|
73
127
|
|
|
74
128
|
const tooltipClones: Element[] = []
|
|
75
129
|
const tooltipClonesCheckOut: Element[] = []
|
|
@@ -98,61 +152,24 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
98
152
|
calendarMonthContainer.appendChild(loadingSpinner)
|
|
99
153
|
}
|
|
100
154
|
|
|
155
|
+
if (
|
|
156
|
+
calendarOverlappingDate &&
|
|
157
|
+
calendarTooltipOverlappingDate &&
|
|
158
|
+
!appendedOverlappingDateTooltip &&
|
|
159
|
+
!calendarRange
|
|
160
|
+
) {
|
|
161
|
+
calendarOverlappingDate.appendChild(calendarTooltipOverlappingDate)
|
|
162
|
+
} else if (calendarRange && appendedOverlappingDateTooltip) {
|
|
163
|
+
appendedOverlappingDateTooltip.style.visibility = 'hidden'
|
|
164
|
+
} else if (!calendarRange && appendedOverlappingDateTooltip) {
|
|
165
|
+
appendedOverlappingDateTooltip.style.visibility = 'visible'
|
|
166
|
+
}
|
|
167
|
+
|
|
101
168
|
return () => {
|
|
102
169
|
tooltipClones.forEach((clone) => clone.remove())
|
|
103
170
|
tooltipClonesCheckOut.forEach((clone) => clone.remove())
|
|
104
171
|
}
|
|
105
|
-
}, [calendarRange, updateCalendar])
|
|
106
|
-
|
|
107
|
-
// Handle loading spinner
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
if (typeof document === 'undefined') return
|
|
110
|
-
const loadingSpinner: HTMLElement | null = document.querySelector(
|
|
111
|
-
'.will-filter-bar-calendar .will-calendar-spinner'
|
|
112
|
-
)
|
|
113
|
-
if (loadingData) {
|
|
114
|
-
if (loadingSpinner) loadingSpinner.style.display = 'flex'
|
|
115
|
-
} else {
|
|
116
|
-
if (loadingSpinner) loadingSpinner.style.display = 'none'
|
|
117
|
-
}
|
|
118
|
-
}, [loadingData])
|
|
119
|
-
|
|
120
|
-
// Handle overlapping availableDates.lastCheckOut and disabledDates.start
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
if (disableCalendarDates) {
|
|
123
|
-
const dateFormat = 'dd-MM-yyyy'
|
|
124
|
-
|
|
125
|
-
const availableDateMap = new Map()
|
|
126
|
-
disableCalendarDates.availableDates?.forEach((available) => {
|
|
127
|
-
availableDateMap.set(
|
|
128
|
-
format(available.lastCheckOut, dateFormat),
|
|
129
|
-
available
|
|
130
|
-
)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
const updatedDisabledDates = disableCalendarDates.disabledDates?.map(
|
|
134
|
-
(dateRange) => {
|
|
135
|
-
const formattedFromDate = format(dateRange.from, dateFormat)
|
|
136
|
-
if (availableDateMap.has(formattedFromDate)) {
|
|
137
|
-
return {
|
|
138
|
-
...dateRange,
|
|
139
|
-
from: addDays(dateRange.from, 1),
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return dateRange
|
|
143
|
-
}
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
disableCalendarDates.disabledDates = updatedDisabledDates
|
|
147
|
-
}
|
|
148
|
-
}, [disableCalendarDates])
|
|
149
|
-
|
|
150
|
-
// Handle disable dates by page
|
|
151
|
-
const disabledDatesByPage = handleDisabledDatesByPage({
|
|
152
|
-
today,
|
|
153
|
-
selectedPath,
|
|
154
|
-
disableCalendarDates,
|
|
155
|
-
})
|
|
172
|
+
}, [calendarRange, updateCalendar, overlappingDate])
|
|
156
173
|
|
|
157
174
|
return (
|
|
158
175
|
<div className="will-filter-bar-calendar" ref={ref}>
|
|
@@ -171,14 +188,9 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
171
188
|
setCalendarRange,
|
|
172
189
|
setDisabledDates,
|
|
173
190
|
calendarRange,
|
|
191
|
+
overlappingDate,
|
|
174
192
|
})
|
|
175
193
|
}
|
|
176
|
-
modifiersClassNames={{
|
|
177
|
-
today: 'my-today',
|
|
178
|
-
booked: 'booked',
|
|
179
|
-
disabledAfterCheckIn: 'disabled-after-check-in',
|
|
180
|
-
noActiveSelection: 'no-active-selection',
|
|
181
|
-
}}
|
|
182
194
|
captionLayout="dropdown-buttons"
|
|
183
195
|
defaultMonth={
|
|
184
196
|
selectedStartDate ||
|
|
@@ -199,6 +211,19 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
199
211
|
? (requestDates(val), setUpdateCalendar((prev) => !prev))
|
|
200
212
|
: null
|
|
201
213
|
}}
|
|
214
|
+
modifiersClassNames={{
|
|
215
|
+
today: 'my-today',
|
|
216
|
+
booked: 'booked',
|
|
217
|
+
disabledAfterCheckIn: 'disabled-after-check-in',
|
|
218
|
+
overlappingDate: 'overlapping-date',
|
|
219
|
+
|
|
220
|
+
noActiveSelectionStart:
|
|
221
|
+
'rdp-day_selected rdp-day_range_start no-active-selection ',
|
|
222
|
+
noActiveSelectionMid:
|
|
223
|
+
'rdp-day_selected rdp-day_range_middle no-active-selection',
|
|
224
|
+
noActiveSelectionEnd:
|
|
225
|
+
'rdp-day_selected rdp-day_range_end no-active-selection',
|
|
226
|
+
}}
|
|
202
227
|
modifiers={{
|
|
203
228
|
booked: disabledDatesByPage.length
|
|
204
229
|
? disabledDatesByPage
|
|
@@ -210,9 +235,26 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
210
235
|
? [{ after: calendarRange.from }]
|
|
211
236
|
: [],
|
|
212
237
|
|
|
213
|
-
|
|
214
|
-
? initialCalendarRange || []
|
|
238
|
+
noActiveSelectionStart: !calendarRange
|
|
239
|
+
? initialCalendarRange?.from || []
|
|
240
|
+
: [],
|
|
241
|
+
noActiveSelectionMid:
|
|
242
|
+
!calendarRange &&
|
|
243
|
+
initialCalendarRange?.from &&
|
|
244
|
+
initialCalendarRange?.to
|
|
245
|
+
? [
|
|
246
|
+
{
|
|
247
|
+
after: initialCalendarRange?.from,
|
|
248
|
+
before: initialCalendarRange?.to,
|
|
249
|
+
},
|
|
250
|
+
]
|
|
251
|
+
: [],
|
|
252
|
+
noActiveSelectionEnd: !calendarRange
|
|
253
|
+
? initialCalendarRange?.to || []
|
|
215
254
|
: [],
|
|
255
|
+
|
|
256
|
+
overlappingDate:
|
|
257
|
+
(!calendarRange?.from && overlappingDate?.from) || [],
|
|
216
258
|
}}
|
|
217
259
|
/>
|
|
218
260
|
|
|
@@ -222,6 +264,9 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
222
264
|
<div className={'will-calendar-tooltip-check-out'}>
|
|
223
265
|
<div>{t('noCheckOut')}</div>
|
|
224
266
|
</div>
|
|
267
|
+
<div className={'will-calendar-tooltip-overlapping-date'}>
|
|
268
|
+
<div>{t('checkOutOnly')}</div>
|
|
269
|
+
</div>
|
|
225
270
|
<div className={'will-calendar-spinner'}>Loading...</div>
|
|
226
271
|
</div>
|
|
227
272
|
</div>
|
|
@@ -237,12 +282,14 @@ const handleSelectedCheckIn = ({
|
|
|
237
282
|
setCalendarRange,
|
|
238
283
|
setDisabledDates,
|
|
239
284
|
calendarRange,
|
|
285
|
+
overlappingDate,
|
|
240
286
|
}: {
|
|
241
287
|
range: DateRange | undefined
|
|
242
288
|
disableCalendarDates?: DisableCalendarDates
|
|
243
289
|
setCalendarRange: (range: DateRange | undefined) => void
|
|
244
290
|
setDisabledDates: ((arg: Matcher[]) => void) | undefined
|
|
245
291
|
calendarRange?: DateRange
|
|
292
|
+
overlappingDate?: DateRange
|
|
246
293
|
}) => {
|
|
247
294
|
// Calendar dates select logic
|
|
248
295
|
const dateFormat = 'dd-MM-yyyy'
|
|
@@ -255,6 +302,10 @@ const handleSelectedCheckIn = ({
|
|
|
255
302
|
? format(calendarRange?.to, dateFormat)
|
|
256
303
|
: null
|
|
257
304
|
|
|
305
|
+
const overlappingDateFrom = overlappingDate?.from
|
|
306
|
+
? format(overlappingDate.from, dateFormat)
|
|
307
|
+
: null
|
|
308
|
+
|
|
258
309
|
const checkOutRange = disableCalendarDates?.availableDates?.length
|
|
259
310
|
? disableCalendarDates.availableDates.find(
|
|
260
311
|
(checkInDate) =>
|
|
@@ -270,19 +321,6 @@ const handleSelectedCheckIn = ({
|
|
|
270
321
|
format(checkIn, dateFormat) ===
|
|
271
322
|
format(checkOutRange.firstCheckOut, dateFormat)
|
|
272
323
|
|
|
273
|
-
// Handle overlapping availableDates.lastCheckOut and disabledDates.start
|
|
274
|
-
// const filteredDisabledCalendarDates =
|
|
275
|
-
// disableCalendarDates?.disabledDates?.map((dateRange) => {
|
|
276
|
-
// if (
|
|
277
|
-
// dateRange.from &&
|
|
278
|
-
// format(dateRange.from, dateFormat) ===
|
|
279
|
-
// format(checkOutRange.lastCheckOut, dateFormat)
|
|
280
|
-
// ) {
|
|
281
|
-
// return { ...dateRange, from: addDays(checkOutRange.lastCheckOut, 1) }
|
|
282
|
-
// }
|
|
283
|
-
// return dateRange
|
|
284
|
-
// })
|
|
285
|
-
|
|
286
324
|
setDisabledDates([
|
|
287
325
|
// { before: findCheckOutRange?.checkIn },
|
|
288
326
|
|
|
@@ -299,7 +337,8 @@ const handleSelectedCheckIn = ({
|
|
|
299
337
|
|
|
300
338
|
if (
|
|
301
339
|
(rangeTo && rangeFrom && rangeFrom === rangeTo) ||
|
|
302
|
-
(!rangeTo && !rangeFrom)
|
|
340
|
+
(!rangeTo && !rangeFrom) ||
|
|
341
|
+
rangeFrom === overlappingDateFrom
|
|
303
342
|
) {
|
|
304
343
|
setCalendarRange(undefined)
|
|
305
344
|
setDisabledDates && setDisabledDates([])
|
|
@@ -345,34 +384,3 @@ const handleDisabledDatesByPage = ({
|
|
|
345
384
|
]
|
|
346
385
|
: []
|
|
347
386
|
}
|
|
348
|
-
|
|
349
|
-
// const handleOverlappingDates = ({
|
|
350
|
-
// disableCalendarDates,
|
|
351
|
-
// }: {
|
|
352
|
-
// disableCalendarDates?: DisableCalendarDates
|
|
353
|
-
// }): DisableCalendarDates | undefined => {
|
|
354
|
-
// if (!disableCalendarDates) return undefined
|
|
355
|
-
|
|
356
|
-
// const dateFormat = 'dd-MM-yyyy'
|
|
357
|
-
|
|
358
|
-
// disableCalendarDates.disabledDates = disableCalendarDates.disabledDates?.map(
|
|
359
|
-
// (dateRange) => {
|
|
360
|
-
// const overlappingDate = disableCalendarDates.availableDates?.find(
|
|
361
|
-
// (available) =>
|
|
362
|
-
// format(available.lastCheckOut, dateFormat) ===
|
|
363
|
-
// format(dateRange.from, dateFormat)
|
|
364
|
-
// )
|
|
365
|
-
|
|
366
|
-
// if (overlappingDate) {
|
|
367
|
-
// return {
|
|
368
|
-
// ...dateRange,
|
|
369
|
-
// from: addDays(dateRange.from, 1),
|
|
370
|
-
// }
|
|
371
|
-
// }
|
|
372
|
-
|
|
373
|
-
// return dateRange
|
|
374
|
-
// }
|
|
375
|
-
// )
|
|
376
|
-
|
|
377
|
-
// return disableCalendarDates
|
|
378
|
-
// }
|