willba-component-library 0.2.78 → 0.2.80

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.
Files changed (107) hide show
  1. package/lib/assets/IconsSvg.d.ts +9 -0
  2. package/lib/assets/SpinnerSvg.d.ts +5 -0
  3. package/lib/components/Button/Button.d.ts +29 -0
  4. package/lib/components/Button/Button.stories.d.ts +7 -0
  5. package/lib/components/Button/index.d.ts +1 -0
  6. package/lib/components/FilterBar/FilterBar.d.ts +5 -0
  7. package/lib/components/FilterBar/FilterBar.stories.d.ts +6 -0
  8. package/lib/components/FilterBar/FilterBarTypes.d.ts +56 -0
  9. package/lib/components/FilterBar/components/buttons/close-button/CloseButton.d.ts +7 -0
  10. package/lib/components/FilterBar/components/buttons/index.d.ts +4 -0
  11. package/lib/components/FilterBar/components/buttons/select-button/SelectButton.d.ts +10 -0
  12. package/lib/components/FilterBar/components/buttons/submit-button/SubmitButton.d.ts +3 -0
  13. package/lib/components/FilterBar/components/buttons/tab-button/TabButton.d.ts +10 -0
  14. package/lib/components/FilterBar/components/calendar/Calendar.d.ts +14 -0
  15. package/lib/components/FilterBar/components/categories/Categories.d.ts +8 -0
  16. package/lib/components/FilterBar/components/divider/Divider.d.ts +3 -0
  17. package/lib/components/FilterBar/components/guests/GuestCount/GuestCount.d.ts +4 -0
  18. package/lib/components/FilterBar/components/guests/Guests.d.ts +10 -0
  19. package/lib/components/FilterBar/components/index.d.ts +4 -0
  20. package/lib/components/FilterBar/hooks/index.d.ts +2 -0
  21. package/lib/components/FilterBar/hooks/useCloseFilterSection.d.ts +8 -0
  22. package/lib/components/FilterBar/hooks/useFilterBar.d.ts +27 -0
  23. package/lib/components/FilterBar/hooks/useScrollInToView.d.ts +9 -0
  24. package/lib/components/FilterBar/hooks/useUpdateTranslations.d.ts +5 -0
  25. package/lib/components/FilterBar/index.d.ts +2 -0
  26. package/lib/components/FilterBar/utils/index.d.ts +1 -0
  27. package/lib/components/FilterBar/utils/parseDates.d.ts +6 -0
  28. package/lib/components/FilterBar/utils/parseGuests.d.ts +17 -0
  29. package/lib/components/FilterCalendar/FilterCalendar.d.ts +5 -0
  30. package/lib/components/FilterCalendar/FilterCalendar.stories.d.ts +6 -0
  31. package/lib/components/FilterCalendar/FilterCalendarTypes.d.ts +9 -0
  32. package/lib/components/FilterCalendar/components/Footer.d.ts +10 -0
  33. package/lib/components/FilterCalendar/hooks/useFilterCalendar.d.ts +21 -0
  34. package/lib/components/FilterCalendar/index.d.ts +2 -0
  35. package/lib/core/components/buttons/close-button/CloseButton.d.ts +7 -0
  36. package/lib/core/components/buttons/submit-button/SubmitButton.d.ts +11 -0
  37. package/lib/core/components/calendar/Calendar.d.ts +5 -0
  38. package/lib/core/components/calendar/CalendarTypes.d.ts +39 -0
  39. package/{src/core/components/calendar/hooks/index.ts → lib/core/components/calendar/hooks/index.d.ts} +3 -3
  40. package/lib/core/components/calendar/hooks/useCalendarLoadingSpinner.d.ts +5 -0
  41. package/lib/core/components/calendar/hooks/useCalendarTooltips.d.ts +5 -0
  42. package/lib/core/components/calendar/hooks/useUpdateDisabledDates.d.ts +14 -0
  43. package/lib/core/components/calendar/utils/calendarSelectionRules.d.ts +15 -0
  44. package/lib/core/components/calendar/utils/checkForContinuousSelection.d.ts +11 -0
  45. package/lib/core/components/calendar/utils/disabledDatesByPage.d.ts +9 -0
  46. package/lib/core/components/calendar/utils/handleCalendarModifiers.d.ts +47 -0
  47. package/lib/core/components/calendar/utils/handleRangeContextDisabledDates.d.ts +27 -0
  48. package/{src/core/components/calendar/utils/index.ts → lib/core/components/calendar/utils/index.d.ts} +8 -8
  49. package/lib/core/components/calendar/utils/nightsCount.d.ts +6 -0
  50. package/lib/core/components/calendar/utils/parseDate.d.ts +7 -0
  51. package/lib/core/components/calendar/utils/parseDates.d.ts +6 -0
  52. package/lib/core/components/index.d.ts +3 -0
  53. package/lib/core/hooks/index.d.ts +3 -0
  54. package/lib/core/hooks/useAwaitRender.d.ts +1 -0
  55. package/lib/core/hooks/useCloseFilterSection.d.ts +8 -0
  56. package/lib/core/hooks/useUpdateTranslations.d.ts +5 -0
  57. package/lib/core/utils/handleOverlappingDates.d.ts +1 -0
  58. package/lib/core/utils/index.d.ts +3 -0
  59. package/lib/core/utils/nightsCount.d.ts +6 -0
  60. package/lib/core/utils/parseDate.d.ts +7 -0
  61. package/lib/core/utils/parseDates.d.ts +6 -0
  62. package/lib/i18n.d.ts +2 -0
  63. package/lib/index.d.ts +119 -0
  64. package/lib/index.esm.js +11576 -0
  65. package/lib/index.esm.js.map +1 -0
  66. package/lib/index.js +11598 -0
  67. package/lib/index.js.map +1 -0
  68. package/lib/index.umd.js +11602 -0
  69. package/lib/index.umd.js.map +1 -0
  70. package/lib/themes/useTheme.d.ts +13 -0
  71. package/package.json +1 -1
  72. package/src/assets/SpinnerSvg.tsx +40 -0
  73. package/src/components/FilterBar/FilterBar.stories.tsx +1 -2
  74. package/src/components/FilterBar/FilterBar.tsx +1 -1
  75. package/src/components/FilterBar/components/buttons/tab-button/TabButton.css +1 -1
  76. package/src/components/FilterBar/hooks/useFilterBar.tsx +1 -1
  77. package/src/components/FilterCalendar/FilterCalendar.css +10 -26
  78. package/src/components/FilterCalendar/FilterCalendar.stories.tsx +153 -522
  79. package/src/components/FilterCalendar/FilterCalendar.tsx +54 -25
  80. package/src/components/FilterCalendar/FilterCalendarTypes.ts +1 -0
  81. package/src/components/FilterCalendar/hooks/useFilterCalendar.ts +4 -94
  82. package/src/core/components/buttons/submit-button/SubmitButton.css +2 -16
  83. package/src/core/components/buttons/submit-button/SubmitButton.tsx +5 -6
  84. package/src/core/components/calendar/Calendar.css +18 -71
  85. package/src/core/components/calendar/Calendar.tsx +342 -132
  86. package/src/core/components/calendar/CalendarTypes.ts +3 -10
  87. package/src/core/utils/index.ts +3 -0
  88. package/src/locales/en/common.json +1 -7
  89. package/src/locales/en/filterBar.json +1 -2
  90. package/src/locales/fi/common.json +1 -7
  91. package/src/locales/fi/filterBar.json +1 -2
  92. package/src/themes/Default.css +3 -12
  93. package/src/themes/useTheme.tsx +0 -3
  94. package/src/assets/IconsSvg.tsx +0 -68
  95. package/src/components/FilterCalendar/components/Footer.tsx +0 -96
  96. package/src/core/components/calendar/hooks/useCalendarLoadingSpinner.tsx +0 -19
  97. package/src/core/components/calendar/hooks/useCalendarTooltips.tsx +0 -125
  98. package/src/core/components/calendar/hooks/useUpdateDisabledDates.tsx +0 -107
  99. package/src/core/components/calendar/utils/calendarSelectionRules.tsx +0 -228
  100. package/src/core/components/calendar/utils/checkForContinuousSelection.tsx +0 -86
  101. package/src/core/components/calendar/utils/disabledDatesByPage.tsx +0 -36
  102. package/src/core/components/calendar/utils/handleCalendarModifiers.tsx +0 -147
  103. package/src/core/components/calendar/utils/handleRangeContextDisabledDates.tsx +0 -75
  104. package/willba-component-library-0.2.77.tgz +0 -0
  105. /package/src/core/{components/calendar/utils → utils}/nightsCount.tsx +0 -0
  106. /package/src/core/{components/calendar/utils → utils}/parseDate.tsx +0 -0
  107. /package/src/core/{components/calendar/utils → utils}/parseDates.tsx +0 -0
@@ -1,24 +1,12 @@
1
- import React, { forwardRef } from 'react'
2
- import { startOfDay } from 'date-fns'
1
+ import React, { forwardRef, useEffect, useMemo, useState } from 'react'
2
+ import { addDays, startOfDay, format } from 'date-fns'
3
3
  import { fi, enUS } from 'date-fns/locale'
4
4
  import { useTranslation } from 'react-i18next'
5
- import { DateRange, DayPicker } from 'react-day-picker'
5
+ import { DateRange, DayPicker, Matcher } from 'react-day-picker'
6
6
  import { useMediaQuery } from 'react-responsive'
7
7
 
8
- import { CalendarTypes } from './CalendarTypes'
9
- import { IconsSvg } from '../../../assets/IconsSvg'
10
- import {
11
- calendarSelectionRules,
12
- checkForContinuousSelection,
13
- handleCalendarModifiers,
14
- disabledDatesByPage as handleDisabledDatesByPage,
15
- handleRangeContextDisabledDates,
16
- } from './utils'
17
- import {
18
- useCalendarLoadingSpinner,
19
- useCalendarTooltips,
20
- useUpdateDisabledDates,
21
- } from './hooks'
8
+ import { CalendarTypes, DisableCalendarDates } from './CalendarTypes'
9
+ import { SpinnerSVG } from '../../../assets/SpinnerSvg'
22
10
 
23
11
  import 'react-day-picker/dist/style.css'
24
12
  import './Calendar.css'
@@ -36,14 +24,11 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
36
24
  setDisabledDates,
37
25
  updateCalendarMonthNavigation,
38
26
  setUpdateCalendarMonthNavigation,
39
- updateCalendarDefaultMonth,
27
+ updateCalendarDefaultMoth,
40
28
  loadingData,
29
+ initialCalendarRange,
41
30
  showFeedback,
42
31
  palette,
43
- setCalendarHasError,
44
- setUpdatedForSubmit,
45
- rangeContext,
46
- calendarHasError,
47
32
  }: CalendarTypes,
48
33
  ref
49
34
  ) => {
@@ -53,16 +38,81 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
53
38
  const isTablet = useMediaQuery({ maxWidth: 960 })
54
39
  const today = startOfDay(new Date())
55
40
  const selectedStartDate = calendarRange?.from
56
- const rangeContextStartDate = rangeContext?.from
57
41
 
58
- // Handle initial disable dates including overlapping availableDates.lastCheckOut and disabledDates.start
59
- const { newDisableCalendarDates, overlappingDate, lastPossibleCheckout } =
60
- useUpdateDisabledDates({
61
- disableCalendarDates,
62
- calendarRange,
63
- updateCalendarMonthNavigation,
64
- updateCalendarDefaultMonth,
65
- })
42
+ // Handle overlapping availableDates.lastCheckOut and disabledDates.start
43
+ const [overlappingDate, setOverlappingDate] = useState<
44
+ DateRange[] | undefined
45
+ >(undefined)
46
+
47
+ const newDisableCalendarDates = useMemo(() => {
48
+ if (disableCalendarDates?.availableDates) {
49
+ const dateFormat = 'dd-MM-yyyy'
50
+
51
+ const { disabledDates } = disableCalendarDates
52
+
53
+ const { updatedDisabledDates, newOverlappingDates } = (
54
+ disabledDates || []
55
+ ).reduce(
56
+ (
57
+ acc: {
58
+ updatedDisabledDates: { to: Date; from: Date }[]
59
+ newOverlappingDates: { to: Date; from: Date }[]
60
+ },
61
+ dateRange
62
+ ) => {
63
+ const formattedFromDate = format(dateRange.from, dateFormat)
64
+ const formattedToDate = format(dateRange.to, dateFormat)
65
+
66
+ const hasTwoOverlappingDates =
67
+ disableCalendarDates.availableDates?.some(
68
+ (item) =>
69
+ format(item.lastCheckOut, dateFormat) === formattedFromDate &&
70
+ format(item.lastCheckOut, dateFormat) === formattedToDate
71
+ )
72
+
73
+ const hasOneOverlappingDate =
74
+ disableCalendarDates.availableDates?.some(
75
+ (item) =>
76
+ format(item.lastCheckOut, dateFormat) === formattedFromDate &&
77
+ format(item.lastCheckOut, dateFormat) !== formattedToDate
78
+ )
79
+
80
+ if (hasTwoOverlappingDates) {
81
+ acc.newOverlappingDates.push(dateRange)
82
+ } else if (hasOneOverlappingDate) {
83
+ acc.newOverlappingDates.push(dateRange)
84
+ acc.updatedDisabledDates.push({
85
+ ...dateRange,
86
+ from: addDays(dateRange.from, 1),
87
+ })
88
+ } else {
89
+ acc.updatedDisabledDates.push(dateRange)
90
+ }
91
+
92
+ return acc
93
+ },
94
+ { updatedDisabledDates: [], newOverlappingDates: [] }
95
+ )
96
+
97
+ if (newOverlappingDates.length) {
98
+ setOverlappingDate((prev = []) => [...prev, ...newOverlappingDates])
99
+ }
100
+
101
+ const newDisableCalendarDates = {
102
+ ...disableCalendarDates,
103
+ disabledDates: updatedDisabledDates,
104
+ }
105
+
106
+ return newDisableCalendarDates
107
+ }
108
+ return disableCalendarDates
109
+ }, [
110
+ disableCalendarDates,
111
+ calendarRange,
112
+ updateCalendarMonthNavigation,
113
+ initialCalendarRange,
114
+ updateCalendarDefaultMoth,
115
+ ])
66
116
 
67
117
  // Handle disable dates by page
68
118
  const disabledDatesByPage = handleDisabledDatesByPage({
@@ -72,72 +122,132 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
72
122
  })
73
123
 
74
124
  // Handle tooltip
75
- useCalendarTooltips({
76
- showFeedback,
77
- })
125
+ useEffect(() => {
126
+ if (typeof document === 'undefined' || !showFeedback) return
78
127
 
79
- // Handle loading spinner
80
- useCalendarLoadingSpinner({
81
- loadingData,
82
- })
128
+ // Children
129
+ const calendarTooltip = document.querySelector('.will-calendar-tooltip')
130
+ const calendarTooltipCheckOut = document.querySelector(
131
+ '.will-calendar-tooltip-check-out'
132
+ )
83
133
 
84
- // Handle the date selection and availability for selection logic.
85
- const handleOnSelect = (range?: DateRange) => {
86
- setCalendarHasError && calendarHasError && setCalendarHasError(false)
87
-
88
- calendarSelectionRules({
89
- range,
90
- newDisableCalendarDates,
91
- setCalendarRange,
92
- setDisabledDates,
93
- calendarRange,
94
- overlappingDate,
95
- setCalendarHasError,
96
- rangeContext,
97
- })
98
-
99
- setUpdatedForSubmit && setUpdatedForSubmit(true)
100
- }
101
-
102
- // Handle disabled dates for range context
103
- const {
104
- findFirstPossibleRangeContextCheckIn,
105
- findLastPossibleRangeContextCheckOut,
106
- firstPossibleRangeContextCheckIn,
107
- lastPossibleRangeContextCheckOut,
108
- currentSelectionLastCheckoutDate,
109
- } = handleRangeContextDisabledDates({
110
- rangeContext,
111
- availableDates: newDisableCalendarDates?.availableDates,
112
- calendarRange,
113
- })
134
+ const calendarTooltipOverlappingDate = document.querySelector(
135
+ '.will-calendar-tooltip-overlapping-date'
136
+ )
137
+
138
+ const loadingSpinner = document.querySelector(
139
+ '.will-filter-bar-calendar .will-calendar-spinner'
140
+ )
141
+
142
+ // Parents
143
+ const calendarButtons = document.querySelectorAll(
144
+ '.will-filter-bar-calendar .rdp-cell:has(.booked):not(:has(.disabled-after-check-in))'
145
+ )
146
+ const calendarButtonsCheckOut = document.querySelectorAll(
147
+ '.will-filter-bar-calendar .rdp-cell:has(.booked.disabled-after-check-in)'
148
+ )
149
+ const calendarMonthContainer = document.querySelector(
150
+ '.will-filter-bar-calendar .rdp-months'
151
+ )
152
+ const calendarOverlappingDate = document.querySelectorAll(
153
+ '.will-filter-bar-calendar .rdp-cell:has(.overlapping-date)'
154
+ )
155
+
156
+ const tooltipClonesCheckIn: Element[] = []
157
+ const tooltipClonesCheckOut: Element[] = []
158
+ const tooltipClonesSpinner: Element[] = []
159
+ const tooltipClonesOverlappingDates: Element[] = []
114
160
 
115
- // Handle check for continuous selection in the range context
116
- checkForContinuousSelection({
117
- setCalendarHasError,
118
- rangeContext,
161
+ if (calendarTooltip && calendarButtons.length > 0) {
162
+ calendarButtons.forEach((element) => {
163
+ const tooltipClone: Element = calendarTooltip.cloneNode(
164
+ true
165
+ ) as Element
166
+ element.appendChild(tooltipClone)
167
+ tooltipClonesCheckIn.push(tooltipClone)
168
+ })
169
+ }
170
+
171
+ if (calendarTooltipCheckOut && calendarButtonsCheckOut.length > 0) {
172
+ calendarButtonsCheckOut.forEach((element) => {
173
+ const tooltipClone: Element = calendarTooltipCheckOut.cloneNode(
174
+ true
175
+ ) as Element
176
+ element.appendChild(tooltipClone)
177
+ tooltipClonesCheckOut.push(tooltipClone)
178
+ })
179
+ }
180
+
181
+ if (loadingSpinner && calendarMonthContainer) {
182
+ const tooltipClone: Element = loadingSpinner.cloneNode(true) as Element
183
+ calendarMonthContainer.appendChild(tooltipClone)
184
+ tooltipClonesSpinner.push(tooltipClone)
185
+ }
186
+
187
+ if (
188
+ calendarTooltipOverlappingDate &&
189
+ calendarOverlappingDate.length > 0
190
+ ) {
191
+ calendarOverlappingDate.forEach((element) => {
192
+ const tooltipClone: Element =
193
+ calendarTooltipOverlappingDate.cloneNode(true) as Element
194
+ element.appendChild(tooltipClone)
195
+ tooltipClonesOverlappingDates.push(tooltipClone)
196
+ })
197
+ }
198
+
199
+ return () => {
200
+ tooltipClonesCheckIn.forEach((clone) => clone.remove())
201
+ tooltipClonesCheckOut.forEach((clone) => clone.remove())
202
+ tooltipClonesSpinner.forEach((clone) => clone.remove())
203
+ tooltipClonesOverlappingDates.forEach((clone) => clone.remove())
204
+ }
205
+ }, [
119
206
  calendarRange,
120
- calendarHasError,
121
- disabledDates: newDisableCalendarDates?.disabledDates,
122
- })
207
+ updateCalendarMonthNavigation,
208
+ overlappingDate,
209
+ initialCalendarRange,
210
+ updateCalendarDefaultMoth,
211
+ ])
212
+
213
+ // Handle loading spinner
214
+ useEffect(() => {
215
+ if (typeof document === 'undefined') return
216
+ const loadingSpinner: HTMLElement | null = document.querySelector(
217
+ '.will-filter-bar-calendar .rdp-months .will-calendar-spinner'
218
+ )
219
+ if (loadingData) {
220
+ if (loadingSpinner) loadingSpinner.style.display = 'flex'
221
+ } else {
222
+ if (loadingSpinner) loadingSpinner.style.display = 'none'
223
+ }
224
+ }, [loadingData, updateCalendarMonthNavigation, updateCalendarDefaultMoth])
123
225
 
124
226
  return (
125
227
  <div className="will-filter-bar-calendar" ref={ref}>
126
228
  <div className="will-calendar-filter-container">
127
229
  <DayPicker
128
- key={updateCalendarDefaultMonth}
230
+ key={updateCalendarDefaultMoth}
129
231
  id="will-calendar"
130
232
  mode="range"
131
233
  locale={language === 'en' ? enUS : fi}
132
234
  numberOfMonths={!isTablet ? 2 : 1}
133
235
  weekStartsOn={1}
134
236
  selected={calendarRange}
135
- onSelect={(range) => handleOnSelect(range)}
237
+ onSelect={(range) =>
238
+ handleSelectedCheckIn({
239
+ range,
240
+ newDisableCalendarDates,
241
+ setCalendarRange,
242
+ setDisabledDates,
243
+ calendarRange,
244
+ overlappingDate,
245
+ })
246
+ }
136
247
  captionLayout="dropdown-buttons"
137
248
  defaultMonth={
138
- calendarRange?.from ||
249
+ initialCalendarRange?.from ||
139
250
  selectedStartDate ||
140
- rangeContextStartDate ||
141
251
  (newDisableCalendarDates?.disabledDates?.length
142
252
  ? newDisableCalendarDates.disabledDates[0].from
143
253
  : today)
@@ -146,20 +256,8 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
146
256
  disabledDatesByPage.length
147
257
  ? disabledDatesByPage
148
258
  : disabledDates?.length
149
- ? [
150
- lastPossibleCheckout && lastPossibleCheckout,
151
- ...disabledDates,
152
- ...firstPossibleRangeContextCheckIn,
153
- ...lastPossibleRangeContextCheckOut,
154
- ]
155
- : newDisableCalendarDates?.disabledDates?.length
156
- ? [
157
- lastPossibleCheckout && lastPossibleCheckout,
158
- ...newDisableCalendarDates.disabledDates,
159
- ...firstPossibleRangeContextCheckIn,
160
- ...lastPossibleRangeContextCheckOut,
161
- ]
162
- : []
259
+ ? disabledDates
260
+ : newDisableCalendarDates?.disabledDates || []
163
261
  }
164
262
  fromMonth={today}
165
263
  onMonthChange={(val) => {
@@ -168,43 +266,55 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
168
266
  setUpdateCalendarMonthNavigation((prev) => !prev))
169
267
  : null
170
268
  }}
171
- classNames={{
172
- day_range_start: calendarRange?.from ? 'rdp-day_range_start' : '',
173
- day_range_end: calendarRange?.to ? 'rdp-day_range_end' : '',
174
- }}
175
269
  modifiersClassNames={{
176
270
  today: 'my-today',
177
271
  booked: 'booked',
178
272
  disabledAfterCheckIn: 'disabled-after-check-in',
179
273
  overlappingDate: 'overlapping-date',
180
274
 
181
- noActiveSelectionStart: 'no-active-selection-start',
182
- noActiveSelectionMid: 'no-active-selection-mid',
183
- noActiveSelectionEnd: 'no-active-selection-end',
275
+ noActiveSelectionStart:
276
+ 'rdp-day_selected rdp-day_range_start no-active-selection ',
277
+ noActiveSelectionMid:
278
+ 'rdp-day_selected rdp-day_range_middle no-active-selection',
279
+ noActiveSelectionEnd:
280
+ 'rdp-day_selected rdp-day_range_end no-active-selection',
281
+ }}
282
+ modifiers={{
283
+ booked: disabledDatesByPage.length
284
+ ? disabledDatesByPage
285
+ : disabledDates?.length
286
+ ? disabledDates
287
+ : newDisableCalendarDates?.disabledDates || [],
184
288
 
185
- checkoutOptionsMid:
186
- 'rdp-day_selected rdp-day_range_middle checkout-option',
289
+ disabledAfterCheckIn: calendarRange?.from
290
+ ? [{ after: calendarRange.from }]
291
+ : [],
187
292
 
188
- checkInOnly: 'check-in-only',
189
- checkOutOnly: 'check-out-only',
293
+ noActiveSelectionStart: !calendarRange
294
+ ? initialCalendarRange?.from || []
295
+ : [],
296
+ noActiveSelectionMid:
297
+ !calendarRange &&
298
+ initialCalendarRange?.from &&
299
+ initialCalendarRange?.to
300
+ ? [
301
+ {
302
+ after: initialCalendarRange?.from,
303
+ before: initialCalendarRange?.to,
304
+ },
305
+ ]
306
+ : [],
307
+ noActiveSelectionEnd: !calendarRange
308
+ ? initialCalendarRange?.to || []
309
+ : [],
310
+
311
+ overlappingDate:
312
+ (!calendarRange?.from &&
313
+ overlappingDate?.map((item) => ({
314
+ from: item.from,
315
+ }))) ||
316
+ [],
190
317
  }}
191
- modifiers={
192
- // This function handles conditions for applying the modifiersClassNames
193
- handleCalendarModifiers({
194
- newDisableCalendarDates,
195
- calendarRange,
196
- disabledDatesByPage,
197
- disabledDates,
198
- overlappingDate,
199
- rangeContext,
200
- lastPossibleCheckout,
201
- findFirstPossibleRangeContextCheckIn,
202
- findLastPossibleRangeContextCheckOut,
203
- firstPossibleRangeContextCheckIn,
204
- lastPossibleRangeContextCheckOut,
205
- currentSelectionLastCheckoutDate,
206
- })
207
- }
208
318
  />
209
319
 
210
320
  <div className={'will-calendar-tooltip'}>
@@ -216,21 +326,121 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
216
326
  <div className={'will-calendar-tooltip-overlapping-date'}>
217
327
  <div>{t('checkOutOnly')}</div>
218
328
  </div>
219
- <div className={'will-calendar-tooltip-check-in-only'}>
220
- <div>{t('checkInOnly')}</div>
221
- </div>
222
- <div className={'will-calendar-tooltip-check-out-only'}>
223
- <div>{t('checkOutOnly')}</div>
224
- </div>
225
329
  <div className={'will-calendar-spinner'}>
226
- <IconsSvg
227
- fill={palette?.primary || 'inherit'}
228
- size={50}
229
- icon="spinner"
230
- />
330
+ <SpinnerSVG fill={palette?.primary || 'inherit'} size={50} />
231
331
  </div>
232
332
  </div>
233
333
  </div>
234
334
  )
235
335
  }
236
336
  )
337
+
338
+ /////////
339
+
340
+ const handleSelectedCheckIn = ({
341
+ range,
342
+ newDisableCalendarDates,
343
+ setCalendarRange,
344
+ setDisabledDates,
345
+ calendarRange,
346
+ overlappingDate,
347
+ }: {
348
+ range: DateRange | undefined
349
+ newDisableCalendarDates?: DisableCalendarDates
350
+ setCalendarRange: (range: DateRange | undefined) => void
351
+ setDisabledDates: ((arg: Matcher[]) => void) | undefined
352
+ calendarRange?: DateRange
353
+ overlappingDate?: DateRange[]
354
+ }) => {
355
+ // Calendar dates select logic
356
+ const dateFormat = 'dd-MM-yyyy'
357
+ const rangeFrom = range?.from ? format(range.from, dateFormat) : null
358
+ const rangeTo = range?.to ? format(range.to, dateFormat) : null
359
+ const calendarFrom = calendarRange?.from
360
+ ? format(calendarRange?.from, dateFormat)
361
+ : null
362
+
363
+ const overlappingDateFrom = overlappingDate?.length
364
+ ? overlappingDate.find(
365
+ (date) => format(date.from || 1, dateFormat) === rangeFrom
366
+ )
367
+ : null
368
+
369
+ const checkOutRange = newDisableCalendarDates?.availableDates?.length
370
+ ? newDisableCalendarDates.availableDates.find(
371
+ (checkInDate) =>
372
+ format(checkInDate.checkIn || 1, dateFormat) ===
373
+ format(range?.from || 1, dateFormat)
374
+ )
375
+ : null
376
+
377
+ if (rangeFrom && checkOutRange && setDisabledDates) {
378
+ const checkIn = addDays(checkOutRange.checkIn, 1)
379
+ const firstCheckOut = addDays(checkOutRange.firstCheckOut, -1)
380
+ const noDatesRange =
381
+ format(checkIn, dateFormat) ===
382
+ format(checkOutRange.firstCheckOut, dateFormat)
383
+
384
+ setDisabledDates([
385
+ // { before: findCheckOutRange?.checkIn },
386
+
387
+ ...(newDisableCalendarDates?.disabledDates || []),
388
+
389
+ {
390
+ from: noDatesRange ? undefined : checkIn,
391
+ to: noDatesRange ? undefined : firstCheckOut,
392
+ },
393
+
394
+ { after: checkOutRange?.lastCheckOut },
395
+ ])
396
+ }
397
+
398
+ if (
399
+ (rangeTo && rangeFrom && rangeFrom === rangeTo) ||
400
+ (!rangeTo && !rangeFrom) ||
401
+ overlappingDateFrom
402
+ ) {
403
+ setCalendarRange(undefined)
404
+ setDisabledDates && setDisabledDates([])
405
+ } else if (calendarFrom && rangeFrom && rangeFrom !== calendarFrom) {
406
+ setCalendarRange({
407
+ from: range?.from,
408
+ to: undefined,
409
+ })
410
+ } else {
411
+ setCalendarRange(range)
412
+ }
413
+ }
414
+
415
+ const handleDisabledDatesByPage = ({
416
+ newDisableCalendarDates,
417
+ selectedPath,
418
+ today,
419
+ }: {
420
+ newDisableCalendarDates?: DisableCalendarDates
421
+ selectedPath?: string
422
+ today: Date
423
+ }) => {
424
+ const daysToOffsetCalendar =
425
+ newDisableCalendarDates?.disabledDatesByPage && selectedPath
426
+ ? [
427
+ newDisableCalendarDates?.disabledDatesByPage?.find(
428
+ (item) => selectedPath === item.page
429
+ ),
430
+ ]
431
+ : []
432
+
433
+ return daysToOffsetCalendar.length
434
+ ? [
435
+ {
436
+ from: addDays(
437
+ today,
438
+ daysToOffsetCalendar.length && daysToOffsetCalendar[0]?.offset
439
+ ? daysToOffsetCalendar[0]?.offset
440
+ : -2
441
+ ),
442
+ to: addDays(today, -100),
443
+ },
444
+ ]
445
+ : []
446
+ }
@@ -18,11 +18,6 @@ export type DisableCalendarDates = {
18
18
  }[]
19
19
  }
20
20
 
21
- export type RangeContext = {
22
- from: Date
23
- to: Date
24
- }
25
-
26
21
  export type CalendarTypes = {
27
22
  calendarRange?: DateRange | undefined
28
23
  setCalendarRange: (range: DateRange | undefined) => void
@@ -34,14 +29,12 @@ export type CalendarTypes = {
34
29
  disabledDates?: Matcher[]
35
30
  setDisabledDates?: (arg: Matcher[]) => void
36
31
  loadingData?: boolean
32
+ initialCalendarRange?: DateRange | undefined
37
33
  showFeedback?: boolean
38
34
  noActiveSelection?: boolean
39
35
  palette?: Palette
36
+
40
37
  updateCalendarMonthNavigation?: boolean
41
38
  setUpdateCalendarMonthNavigation?: (arg: (prev: boolean) => boolean) => void
42
- updateCalendarDefaultMonth?: number
43
- setCalendarHasError?: (arg: boolean) => void
44
- setUpdatedForSubmit?: (arg: boolean) => void
45
- rangeContext?: RangeContext
46
- calendarHasError?: boolean
39
+ updateCalendarDefaultMoth?: number
47
40
  }
@@ -0,0 +1,3 @@
1
+ export { parseDates } from './parseDates'
2
+ export { parseDate } from './parseDate'
3
+ export { nightsCount } from './nightsCount'
@@ -8,11 +8,5 @@
8
8
  "clearDates": "Clear dates",
9
9
  "noCheckIn": "Room not available",
10
10
  "noCheckOut": "Check-out not available",
11
- "checkOutOnly": "Check-out only",
12
- "checkInOnly": "Check-in only",
13
- "errors": {
14
- "calendarErrors": {
15
- "checkInAvailabilityError": "All room reservations in a single purchase must be for the same dates. If you need reservations for different dates, please make a separate purchase."
16
- }
17
- }
11
+ "checkOutOnly": "Check-out only"
18
12
  }
@@ -7,8 +7,7 @@
7
7
  "endDate": "End date",
8
8
  "title": "Calendar",
9
9
  "checkoutOnly": "Check-out only",
10
- "hasDisableDates": "Contains unavailable dates",
11
- "minNights": "2 nights min"
10
+ "hasDisableDates": "Contains unavailable dates"
12
11
  },
13
12
  "guests": {
14
13
  "label": "Number of guests",
@@ -8,12 +8,6 @@
8
8
  "clearDates": "Tyhjennä",
9
9
  "noCheckIn": "Huone ei saatavilla",
10
10
  "noCheckOut": "Uloskirjaus ei saatavilla",
11
- "checkOutOnly": "Vain uloskirjaus",
12
- "checkInOnly": "Vain sisäänkirjaus",
13
- "errors": {
14
- "calendarErrors": {
15
- "checkInAvailabilityError": "Yhdellä ostolla tehdyt huonevaraukset tulee olla samalle ajankohdalle. Jos tarvitset huonevarauksia eri ajankohdille, ole hyvä ja tee uusi osto."
16
- }
17
- }
11
+ "checkOutOnly": "Vain uloskirjaus"
18
12
  }
19
13
 
@@ -7,8 +7,7 @@
7
7
  "endDate": "Loppu",
8
8
  "title": "Kalenteri",
9
9
  "checkoutOnly": "Check-out only",
10
- "hasDisableDates": "Contains unavailable dates",
11
- "minNights": "2 nights min"
10
+ "hasDisableDates": "Contains unavailable dates"
12
11
  },
13
12
  "guests": {
14
13
  "label": "Vierasmäärä",
@@ -15,30 +15,21 @@
15
15
  --will-primary: #374269;
16
16
  --will-secondary: #374269;
17
17
  --will-grey: #ABA7AF;
18
- --will-light-grey: #C8C8C8;
19
18
  --will-white: #fff;
20
19
  --will-white-transparent: #ffffffcf;
21
20
  --will-black: #000;
22
21
  --will-onahau: #CDEEFF;
23
22
  --will-text: #5A5959;
24
23
  --will-charcoal-blue: #384265;
25
- --will-error: #d32f2f;
26
-
27
- /* Transparent */
28
- --will-transparent-black: rgba(0, 0, 0, 0.5);
29
24
  --will-transparent-white: rgba(255, 255, 255, 0.30);
30
- --will-transparent-lavender: rgba(171, 167, 175, 0.30);
31
-
32
- /* Color mix */
33
- --will-primary-lighter: color-mix(in srgb, var(--will-primary), white 50%);
34
- --will-primary-lightest: color-mix(in srgb, var(--will-primary), white 80%);
25
+ --will-transparent-black: rgba(171, 167, 175, 0.30);
35
26
 
36
-
37
- /* Shadows */
27
+ /* Confines */
38
28
  --will-box-shadow-dark: 0px 2px 12px 2px #a1a1a180;
39
29
  --will-box-shadow-light: 0px 2px 12px 2px #bcb9b980;
40
30
 
41
31
  /* Breakpoints */
32
+
42
33
  --will-lg: 1140px;
43
34
  --will-md: 960px;
44
35
  --will-sm: 600px;