willba-component-library 0.3.26 → 0.4.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.
- package/README.md +75 -113
- package/lib/components/FilterBar/FilterBar.d.ts +1 -1
- package/lib/components/FilterCalendar/FilterCalendar.d.ts +1 -1
- package/lib/core/i18n/I18nProvider.d.ts +6 -0
- package/lib/core/i18n/index.d.ts +1 -0
- package/lib/embed.d.ts +18 -0
- package/lib/embed.esm.js +74 -0
- package/lib/embed.esm.js.map +1 -0
- package/lib/embed.umd.js +74 -0
- package/lib/embed.umd.js.map +1 -0
- package/lib/i18n.d.ts +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.esm.js +1112 -931
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1111 -930
- package/lib/index.js.map +1 -1
- package/package.json +9 -1
- package/.nvmrc +0 -1
- package/.storybook/main.ts +0 -17
- package/.storybook/preview.ts +0 -15
- package/lib/components/FilterBar/components/buttons/index.d.ts +0 -4
- package/lib/components/FilterBar/components/buttons/select-button/SelectButton.d.ts +0 -13
- package/lib/components/FilterBar/components/buttons/tab-button/TabButton.d.ts +0 -10
- package/lib/components/FilterBar/components/cards/image-card/ImageCard.d.ts +0 -11
- package/lib/components/FilterBar/components/cards/index.d.ts +0 -1
- package/lib/components/FilterBar/components/categories/Categories.d.ts +0 -8
- package/lib/components/FilterBar/components/common/FilterSectionHeader.d.ts +0 -8
- package/lib/components/FilterBar/components/dates/Dates.d.ts +0 -17
- package/lib/components/FilterBar/components/dates/index.d.ts +0 -1
- package/lib/components/FilterBar/components/guests/GuestCount/GuestCount.d.ts +0 -4
- package/lib/components/FilterBar/components/guests/Guests.d.ts +0 -12
- package/lib/components/FilterBar/components/locations/Locations.d.ts +0 -14
- package/lib/components/FilterBar/hooks/useFilterBar.d.ts +0 -32
- package/lib/components/FilterBar/hooks/useFilterUi.d.ts +0 -8
- package/lib/components/FilterBar/utils/calculateDropdownPosition.d.ts +0 -12
- package/lib/components/FilterBar/utils/getLocalizedContent.d.ts +0 -8
- package/lib/core/components/buttons/close-button/CloseButton.d.ts +0 -7
- package/lib/core/components/buttons/submit-button/SubmitButton.d.ts +0 -14
- package/lib/index.umd.js +0 -12489
- package/lib/index.umd.js.map +0 -1
- package/prettier.config.js +0 -6
- package/rollup.config.mjs +0 -63
- package/src/assets/IconsSvg.tsx +0 -69
- package/src/components/Button/Button.stories.tsx +0 -34
- package/src/components/Button/Button.tsx +0 -56
- package/src/components/Button/button.css +0 -30
- package/src/components/Button/index.ts +0 -1
- package/src/components/FilterBar/FilterBar.css +0 -35
- package/src/components/FilterBar/FilterBar.stories.tsx +0 -116
- package/src/components/FilterBar/FilterBar.tsx +0 -64
- package/src/components/FilterBar/FilterBarTypes.ts +0 -71
- package/src/components/FilterBar/components/Divider/Divider.css +0 -14
- package/src/components/FilterBar/components/Divider/Divider.tsx +0 -7
- package/src/components/FilterBar/components/FilterControls/FilterControls.css +0 -22
- package/src/components/FilterBar/components/FilterControls/FilterControls.tsx +0 -139
- package/src/components/FilterBar/components/FilterPanels/Categories/Categories.css +0 -21
- package/src/components/FilterBar/components/FilterPanels/Categories/Categories.tsx +0 -49
- package/src/components/FilterBar/components/FilterPanels/Dates/Dates.css +0 -9
- package/src/components/FilterBar/components/FilterPanels/Dates/Dates.tsx +0 -60
- package/src/components/FilterBar/components/FilterPanels/FilterPanels.css +0 -22
- package/src/components/FilterBar/components/FilterPanels/FilterPanels.tsx +0 -111
- package/src/components/FilterBar/components/FilterPanels/Guests/GuestCount/GuestCount.css +0 -58
- package/src/components/FilterBar/components/FilterPanels/Guests/GuestCount/GuestCount.tsx +0 -85
- package/src/components/FilterBar/components/FilterPanels/Guests/Guests.css +0 -24
- package/src/components/FilterBar/components/FilterPanels/Guests/Guests.tsx +0 -59
- package/src/components/FilterBar/components/FilterPanels/Locations/Locations.css +0 -16
- package/src/components/FilterBar/components/FilterPanels/Locations/Locations.tsx +0 -94
- package/src/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.css +0 -34
- package/src/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.tsx +0 -17
- package/src/components/FilterBar/components/FilterTabs/FilterTabs.css +0 -10
- package/src/components/FilterBar/components/FilterTabs/FilterTabs.tsx +0 -50
- package/src/components/FilterBar/components/ImageCard/ImageCard.css +0 -30
- package/src/components/FilterBar/components/ImageCard/ImageCard.tsx +0 -45
- package/src/components/FilterBar/components/SelectButton/SelectButton.css +0 -76
- package/src/components/FilterBar/components/SelectButton/SelectButton.tsx +0 -54
- package/src/components/FilterBar/components/TabButton/TabButton.css +0 -36
- package/src/components/FilterBar/components/TabButton/TabButton.tsx +0 -23
- package/src/components/FilterBar/components/index.ts +0 -6
- package/src/components/FilterBar/hooks/index.ts +0 -5
- package/src/components/FilterBar/hooks/useFilterActions.tsx +0 -126
- package/src/components/FilterBar/hooks/useFilterRefs.tsx +0 -21
- package/src/components/FilterBar/hooks/useFilterState.tsx +0 -86
- package/src/components/FilterBar/hooks/usePanelPosition.tsx +0 -52
- package/src/components/FilterBar/hooks/useScrollInToView.tsx +0 -29
- package/src/components/FilterBar/index.ts +0 -3
- package/src/components/FilterBar/providers/FilterBarProvider.tsx +0 -172
- package/src/components/FilterBar/providers/index.ts +0 -1
- package/src/components/FilterBar/utils/ageCategoriesRules.ts +0 -27
- package/src/components/FilterBar/utils/index.tsx +0 -3
- package/src/components/FilterBar/utils/parseGuests.tsx +0 -65
- package/src/components/FilterBar/utils/parseLocations.ts +0 -28
- package/src/components/FilterCalendar/FilterCalendar.css +0 -109
- package/src/components/FilterCalendar/FilterCalendar.stories.tsx +0 -554
- package/src/components/FilterCalendar/FilterCalendar.tsx +0 -115
- package/src/components/FilterCalendar/FilterCalendarTypes.ts +0 -11
- package/src/components/FilterCalendar/components/Footer.tsx +0 -96
- package/src/components/FilterCalendar/hooks/useFilterCalendar.ts +0 -163
- package/src/components/FilterCalendar/index.ts +0 -3
- package/src/core/components/buttons/CloseButton/CloseButton.css +0 -33
- package/src/core/components/buttons/CloseButton/CloseButton.tsx +0 -16
- package/src/core/components/buttons/SubmitButton/SubmitButton.css +0 -54
- package/src/core/components/buttons/SubmitButton/SubmitButton.tsx +0 -42
- package/src/core/components/calendar/Calendar.css +0 -280
- package/src/core/components/calendar/Calendar.tsx +0 -253
- package/src/core/components/calendar/CalendarTypes.ts +0 -48
- package/src/core/components/calendar/hooks/index.ts +0 -3
- package/src/core/components/calendar/hooks/useCalendarLoadingSpinner.tsx +0 -19
- package/src/core/components/calendar/hooks/useCalendarTooltips.tsx +0 -125
- package/src/core/components/calendar/hooks/useUpdateDisabledDates.tsx +0 -105
- package/src/core/components/calendar/utils/calendarSelectionRules.tsx +0 -180
- package/src/core/components/calendar/utils/checkForContinuousSelection.tsx +0 -86
- package/src/core/components/calendar/utils/disabledDatesByPage.tsx +0 -31
- package/src/core/components/calendar/utils/handleCalendarModifiers.tsx +0 -118
- package/src/core/components/calendar/utils/handleRangeContextDisabledDates.tsx +0 -75
- package/src/core/components/calendar/utils/index.ts +0 -8
- package/src/core/components/calendar/utils/nightsCount.tsx +0 -19
- package/src/core/components/calendar/utils/parseDate.tsx +0 -17
- package/src/core/components/calendar/utils/parseDates.tsx +0 -12
- package/src/core/components/index.ts +0 -7
- package/src/core/hooks/index.ts +0 -4
- package/src/core/hooks/useAutoFocus.tsx +0 -27
- package/src/core/hooks/useAwaitRender.tsx +0 -12
- package/src/core/hooks/useCloseFilterSection.tsx +0 -29
- package/src/core/hooks/useUpdateTranslations.tsx +0 -14
- package/src/i18n.ts +0 -27
- package/src/index.ts +0 -8
- package/src/locales/en/common.json +0 -18
- package/src/locales/en/filterBar.json +0 -33
- package/src/locales/fi/common.json +0 -19
- package/src/locales/fi/filterBar.json +0 -33
- package/src/themes/Default.css +0 -69
- package/src/themes/useTheme.tsx +0 -27
- package/stories/Button.stories.ts +0 -50
- package/stories/Button.tsx +0 -53
- package/stories/Configure.mdx +0 -364
- package/stories/Header.stories.ts +0 -27
- package/stories/Header.tsx +0 -70
- package/stories/Page.stories.ts +0 -29
- package/stories/Page.tsx +0 -91
- package/stories/assets/accessibility.png +0 -0
- package/stories/assets/accessibility.svg +0 -5
- package/stories/assets/addon-library.png +0 -0
- package/stories/assets/assets.png +0 -0
- package/stories/assets/context.png +0 -0
- package/stories/assets/discord.svg +0 -15
- package/stories/assets/docs.png +0 -0
- package/stories/assets/figma-plugin.png +0 -0
- package/stories/assets/github.svg +0 -3
- package/stories/assets/share.png +0 -0
- package/stories/assets/styling.png +0 -0
- package/stories/assets/testing.png +0 -0
- package/stories/assets/theming.png +0 -0
- package/stories/assets/tutorials.svg +0 -12
- package/stories/assets/youtube.svg +0 -4
- package/stories/button.css +0 -30
- package/stories/header.css +0 -32
- package/stories/page.css +0 -69
- package/tsconfig.json +0 -29
- /package/lib/components/FilterBar/components/{divider → Divider}/Divider.d.ts +0 -0
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { addDays, isAfter, isBefore, endOfDay, isEqual } from 'date-fns'
|
|
2
|
-
import { DateRange, Matcher } from 'react-day-picker'
|
|
3
|
-
|
|
4
|
-
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
5
|
-
|
|
6
|
-
type Props = {
|
|
7
|
-
range: DateRange | undefined
|
|
8
|
-
newDisableCalendarDates?: DisableCalendarDates
|
|
9
|
-
setCalendarRange: (range: DateRange | undefined) => void
|
|
10
|
-
setCalendarHasError?: (arg: boolean) => void
|
|
11
|
-
calendarRange?: DateRange
|
|
12
|
-
overlappingDate?: DateRange[]
|
|
13
|
-
calendarHasError?: boolean
|
|
14
|
-
rangeContext?: RangeContext
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const calendarSelectionRules = ({
|
|
18
|
-
range,
|
|
19
|
-
newDisableCalendarDates,
|
|
20
|
-
setCalendarRange,
|
|
21
|
-
calendarRange,
|
|
22
|
-
overlappingDate,
|
|
23
|
-
setCalendarHasError,
|
|
24
|
-
rangeContext,
|
|
25
|
-
}: Props) => {
|
|
26
|
-
// Get and parse needed data
|
|
27
|
-
const rangeFrom = range?.from ? endOfDay(range.from) : null
|
|
28
|
-
const rangeTo = range?.to ? endOfDay(range.to) : null
|
|
29
|
-
const calendarRangeFrom = calendarRange?.from
|
|
30
|
-
? endOfDay(calendarRange.from)
|
|
31
|
-
: null
|
|
32
|
-
const calendarRangeTo = calendarRange?.to ? endOfDay(calendarRange.to) : null
|
|
33
|
-
|
|
34
|
-
const rangeContextFrom = rangeContext?.from
|
|
35
|
-
? endOfDay(rangeContext.from)
|
|
36
|
-
: null
|
|
37
|
-
const rangeContextTo = rangeContext?.to ? endOfDay(rangeContext.to) : null
|
|
38
|
-
|
|
39
|
-
// When some dates are not available for selection, the earliest date will be available only for "end"
|
|
40
|
-
// and the latest date will only be available for "start"
|
|
41
|
-
const rangeFromDate =
|
|
42
|
-
!range && calendarRangeFrom && calendarRangeTo
|
|
43
|
-
? calendarRangeFrom
|
|
44
|
-
: rangeFrom
|
|
45
|
-
const overlappingDateFrom = overlappingDate?.length
|
|
46
|
-
? overlappingDate.find((date) =>
|
|
47
|
-
!!(date.from && rangeFromDate)
|
|
48
|
-
? isEqual(endOfDay(date.from), rangeFromDate)
|
|
49
|
-
: false
|
|
50
|
-
)
|
|
51
|
-
: null
|
|
52
|
-
|
|
53
|
-
const overlappingDateTo = overlappingDate?.length
|
|
54
|
-
? overlappingDate.find((date) =>
|
|
55
|
-
!!(date.from && rangeTo) ? isEqual(endOfDay(date.from), rangeTo) : false
|
|
56
|
-
)
|
|
57
|
-
: null
|
|
58
|
-
//----------
|
|
59
|
-
|
|
60
|
-
const checkOutRange = newDisableCalendarDates?.availableDates?.length
|
|
61
|
-
? newDisableCalendarDates.availableDates.find((checkInDate) =>
|
|
62
|
-
!!(checkInDate.checkIn && rangeFrom)
|
|
63
|
-
? isEqual(endOfDay(checkInDate.checkIn), rangeFrom)
|
|
64
|
-
: false
|
|
65
|
-
)
|
|
66
|
-
: null
|
|
67
|
-
|
|
68
|
-
// Calendar selection rules: The cases are handled sequentially, starting from simple selections to more complex contextual selections.
|
|
69
|
-
// The rules are processed in a specific order, so one case is handled before another.
|
|
70
|
-
// Changing the order will cause the rules to break or not work properly.
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
(calendarRangeFrom &&
|
|
74
|
-
overlappingDateFrom &&
|
|
75
|
-
rangeFrom &&
|
|
76
|
-
!isEqual(rangeFrom, calendarRangeFrom)) ||
|
|
77
|
-
!range ||
|
|
78
|
-
(calendarRangeFrom &&
|
|
79
|
-
calendarRangeTo &&
|
|
80
|
-
overlappingDateTo &&
|
|
81
|
-
rangeTo &&
|
|
82
|
-
!isEqual(rangeTo, calendarRangeTo))
|
|
83
|
-
) {
|
|
84
|
-
// 1. If dates overlap, clear the selection.
|
|
85
|
-
return setCalendarRange(undefined)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
// 2. If selected "start" is after "range context end", clear selection and display error.
|
|
90
|
-
// Also, if there are unavailable dates between the rangeContext "start" and "end", do not allow a fully overlapping selection.
|
|
91
|
-
(rangeFrom && rangeContextTo && isAfter(rangeFrom, rangeContextTo)) ||
|
|
92
|
-
// In case of current rangeTo is after contextRange and user clicks the new check-in
|
|
93
|
-
(calendarRangeFrom &&
|
|
94
|
-
calendarRangeTo &&
|
|
95
|
-
rangeContextTo &&
|
|
96
|
-
rangeTo &&
|
|
97
|
-
// If rangeTo has been adjusted, the current click was at the end
|
|
98
|
-
// In this case we can verify if the new click (check-in-to-be) goes over the context range end
|
|
99
|
-
!isEqual(rangeTo, calendarRangeTo) &&
|
|
100
|
-
isAfter(rangeTo, rangeContextTo))
|
|
101
|
-
) {
|
|
102
|
-
setCalendarHasError && setCalendarHasError(true)
|
|
103
|
-
return setCalendarRange(undefined)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (rangeFrom && rangeTo && isEqual(rangeFrom, rangeTo)) {
|
|
107
|
-
// 3. If "start" is selected and the same date is clicked again, keep the current "start" selection.
|
|
108
|
-
return setCalendarRange({ from: rangeFrom, to: undefined })
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (calendarRangeFrom && calendarRangeTo && !range) {
|
|
112
|
-
// 4. If "calendarRange" has dates selected and the same "start" date is clicked, the "range" will become undefined.
|
|
113
|
-
// Set the current selection (calendarRange) to the initial "start" of calendarRange.
|
|
114
|
-
return setCalendarRange({ from: calendarRangeFrom, to: undefined })
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 5. Handle gap selection backwards and forwards
|
|
118
|
-
if (
|
|
119
|
-
// In the range context case, every date selection that is after selected "start" last checkout,
|
|
120
|
-
// clear selection and prompt error
|
|
121
|
-
rangeContext &&
|
|
122
|
-
rangeTo &&
|
|
123
|
-
checkOutRange?.lastCheckOut &&
|
|
124
|
-
isAfter(rangeTo, endOfDay(checkOutRange.lastCheckOut)) &&
|
|
125
|
-
// Handle case of existing range that span over the end of the context range
|
|
126
|
-
((calendarRangeTo && !isEqual(rangeTo, calendarRangeTo)) ||
|
|
127
|
-
!calendarRangeTo) &&
|
|
128
|
-
isAfter(rangeTo, endOfDay(rangeContext.to))
|
|
129
|
-
) {
|
|
130
|
-
setCalendarHasError && setCalendarHasError(true)
|
|
131
|
-
return setCalendarRange(undefined)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
// Enforce on every date selection before current "start", mark as "start" selection
|
|
136
|
-
rangeFrom &&
|
|
137
|
-
calendarRangeFrom &&
|
|
138
|
-
isBefore(rangeFrom, calendarRangeFrom)
|
|
139
|
-
) {
|
|
140
|
-
return setCalendarRange({ from: rangeFrom, to: undefined })
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
// Every date selection that is after selected "start" last checkout, mark as "start"
|
|
145
|
-
rangeTo &&
|
|
146
|
-
checkOutRange?.lastCheckOut &&
|
|
147
|
-
isAfter(rangeTo, endOfDay(checkOutRange.lastCheckOut))
|
|
148
|
-
) {
|
|
149
|
-
if (overlappingDateTo) {
|
|
150
|
-
return setCalendarRange(undefined)
|
|
151
|
-
}
|
|
152
|
-
return setCalendarRange({ from: rangeTo, to: undefined })
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (
|
|
156
|
-
calendarRangeFrom &&
|
|
157
|
-
rangeFrom &&
|
|
158
|
-
!isEqual(calendarRangeFrom, rangeFrom)
|
|
159
|
-
) {
|
|
160
|
-
// 6. If "calendarRange" has selected dates and the new selection "start" differs from the current "calendarRange start", reset and make a new "start" selection.
|
|
161
|
-
return setCalendarRange({ from: rangeFrom, to: undefined })
|
|
162
|
-
} else if (calendarRangeTo && rangeTo && !isEqual(calendarRangeTo, rangeTo)) {
|
|
163
|
-
// 7. If "calendarRange" has selected dates and the new selection "end" differs from the current "calendarRange end", reset and make a new "start" selection.
|
|
164
|
-
|
|
165
|
-
return setCalendarRange({ from: rangeTo, to: undefined })
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
// 8. If selected "end" is before "context start", mark as "start" and display error
|
|
170
|
-
rangeFrom &&
|
|
171
|
-
rangeTo &&
|
|
172
|
-
rangeContextFrom &&
|
|
173
|
-
isBefore(rangeTo, rangeContextFrom)
|
|
174
|
-
) {
|
|
175
|
-
setCalendarHasError && setCalendarHasError(true)
|
|
176
|
-
return setCalendarRange({ from: rangeTo, to: undefined })
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
setCalendarRange(range)
|
|
180
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react'
|
|
2
|
-
import { DateRange } from 'react-day-picker'
|
|
3
|
-
import {
|
|
4
|
-
isAfter,
|
|
5
|
-
isEqual,
|
|
6
|
-
isBefore,
|
|
7
|
-
endOfDay,
|
|
8
|
-
isWithinInterval,
|
|
9
|
-
areIntervalsOverlapping,
|
|
10
|
-
} from 'date-fns'
|
|
11
|
-
|
|
12
|
-
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
13
|
-
|
|
14
|
-
type Props = {
|
|
15
|
-
setCalendarHasError?: (arg: boolean) => void
|
|
16
|
-
rangeContext?: RangeContext
|
|
17
|
-
calendarRange?: DateRange
|
|
18
|
-
calendarHasError?: boolean
|
|
19
|
-
disabledDates?: DisableCalendarDates['disabledDates']
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Case: If the selected dates do not overlap with the rangeContext during continuous selection,
|
|
23
|
-
// set setCalendarHasError to true. This will display an error message and
|
|
24
|
-
// prevent the submission of the selected dates.
|
|
25
|
-
|
|
26
|
-
export const checkForContinuousSelection = ({
|
|
27
|
-
setCalendarHasError,
|
|
28
|
-
rangeContext,
|
|
29
|
-
calendarRange,
|
|
30
|
-
calendarHasError,
|
|
31
|
-
disabledDates,
|
|
32
|
-
}: Props) => {
|
|
33
|
-
const calendarRangeFrom = calendarRange?.from && endOfDay(calendarRange.from)
|
|
34
|
-
const calendarRangeTo = calendarRange?.to && endOfDay(calendarRange.to)
|
|
35
|
-
const rangeContextFrom = rangeContext?.from && endOfDay(rangeContext.from)
|
|
36
|
-
const rangeContextTo = rangeContext?.to && endOfDay(rangeContext.to)
|
|
37
|
-
|
|
38
|
-
// Checking if rangeFrom is equal to or before rangeContextTo
|
|
39
|
-
const startIsEqualOrBeforeRangeContextEnd =
|
|
40
|
-
calendarRangeFrom && rangeContextTo
|
|
41
|
-
? isBefore(calendarRangeFrom, rangeContextTo) ||
|
|
42
|
-
isEqual(calendarRangeFrom, rangeContextTo)
|
|
43
|
-
: null
|
|
44
|
-
|
|
45
|
-
// Checking if rangeTo is equal to or after rangeContextFrom
|
|
46
|
-
const endIsEqualOrAfterRangeContextStart =
|
|
47
|
-
calendarRangeTo && rangeContextFrom && rangeContextTo
|
|
48
|
-
? isAfter(calendarRangeTo, rangeContextFrom) ||
|
|
49
|
-
isEqual(calendarRangeTo, rangeContextFrom)
|
|
50
|
-
: null
|
|
51
|
-
|
|
52
|
-
// Check if selection overlapping unavailable dates
|
|
53
|
-
const selectionOverlappingUnavailableDate = disabledDates?.find((range) => {
|
|
54
|
-
const rangeFrom = endOfDay(range.from)
|
|
55
|
-
const rangeTo = endOfDay(range.to)
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
rangeContextFrom &&
|
|
59
|
-
rangeContextTo &&
|
|
60
|
-
areIntervalsOverlapping(
|
|
61
|
-
{ start: rangeContextFrom, end: rangeContextTo },
|
|
62
|
-
{ start: rangeFrom, end: rangeTo }
|
|
63
|
-
) &&
|
|
64
|
-
calendarRangeFrom &&
|
|
65
|
-
calendarRangeTo &&
|
|
66
|
-
areIntervalsOverlapping(
|
|
67
|
-
{ start: calendarRangeFrom, end: calendarRangeTo },
|
|
68
|
-
{ start: rangeFrom, end: rangeTo }
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
if (
|
|
75
|
-
(rangeContext &&
|
|
76
|
-
calendarRangeFrom &&
|
|
77
|
-
!startIsEqualOrBeforeRangeContextEnd) ||
|
|
78
|
-
(rangeContext &&
|
|
79
|
-
calendarRangeTo &&
|
|
80
|
-
!endIsEqualOrAfterRangeContextStart) ||
|
|
81
|
-
selectionOverlappingUnavailableDate
|
|
82
|
-
) {
|
|
83
|
-
!!(setCalendarHasError && !calendarHasError) && setCalendarHasError(true)
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { addDays } from 'date-fns'
|
|
2
|
-
|
|
3
|
-
import { DisableCalendarDates } from '../CalendarTypes'
|
|
4
|
-
|
|
5
|
-
export const disabledDatesByPage = ({
|
|
6
|
-
newDisableCalendarDates,
|
|
7
|
-
selectedPath,
|
|
8
|
-
today,
|
|
9
|
-
}: {
|
|
10
|
-
newDisableCalendarDates?: DisableCalendarDates
|
|
11
|
-
selectedPath?: string
|
|
12
|
-
today: Date
|
|
13
|
-
}) => {
|
|
14
|
-
const daysToOffsetCalendar =
|
|
15
|
-
newDisableCalendarDates?.disabledDatesByPage && selectedPath
|
|
16
|
-
? [
|
|
17
|
-
newDisableCalendarDates?.disabledDatesByPage?.find(
|
|
18
|
-
(item) => selectedPath === item.page
|
|
19
|
-
),
|
|
20
|
-
]
|
|
21
|
-
: []
|
|
22
|
-
|
|
23
|
-
return daysToOffsetCalendar.length
|
|
24
|
-
? [
|
|
25
|
-
{
|
|
26
|
-
from: addDays(today, daysToOffsetCalendar[0]?.offset ?? -1),
|
|
27
|
-
to: addDays(today, -100),
|
|
28
|
-
},
|
|
29
|
-
]
|
|
30
|
-
: []
|
|
31
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { addDays, endOfDay, isAfter, isBefore } from 'date-fns'
|
|
2
|
-
import { DateRange, Matcher } from 'react-day-picker'
|
|
3
|
-
|
|
4
|
-
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
5
|
-
|
|
6
|
-
type Props = {
|
|
7
|
-
calendarRange?: DateRange
|
|
8
|
-
disabledDates?: Matcher[]
|
|
9
|
-
overlappingDate?: DateRange[]
|
|
10
|
-
rangeContext?: RangeContext
|
|
11
|
-
findFirstPossibleRangeContextCheckIn?: NonNullable<
|
|
12
|
-
DisableCalendarDates['availableDates']
|
|
13
|
-
>['0']
|
|
14
|
-
findLastPossibleRangeContextCheckOut?: NonNullable<
|
|
15
|
-
DisableCalendarDates['availableDates']
|
|
16
|
-
>['0']
|
|
17
|
-
currentSelectionLastCheckoutDate?: NonNullable<
|
|
18
|
-
DisableCalendarDates['availableDates']
|
|
19
|
-
>['0']
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const handleCalendarModifiers = ({
|
|
23
|
-
calendarRange,
|
|
24
|
-
disabledDates,
|
|
25
|
-
overlappingDate,
|
|
26
|
-
rangeContext,
|
|
27
|
-
findFirstPossibleRangeContextCheckIn,
|
|
28
|
-
findLastPossibleRangeContextCheckOut,
|
|
29
|
-
currentSelectionLastCheckoutDate,
|
|
30
|
-
}: Props) => {
|
|
31
|
-
// Parse data
|
|
32
|
-
const calendarRangeFrom = calendarRange?.from && endOfDay(calendarRange.from)
|
|
33
|
-
const calendarRangeTo = calendarRange?.to && endOfDay(calendarRange.to)
|
|
34
|
-
const rangeContextFrom = rangeContext?.from && endOfDay(rangeContext.from)
|
|
35
|
-
const rangeContextTo = rangeContext?.to && endOfDay(rangeContext.to)
|
|
36
|
-
|
|
37
|
-
const filteredOverlappingDates = overlappingDate
|
|
38
|
-
? overlappingDate
|
|
39
|
-
.filter((date) => {
|
|
40
|
-
const dateFrom = date.from ? endOfDay(date.from) : null
|
|
41
|
-
const isBeforeRange =
|
|
42
|
-
dateFrom &&
|
|
43
|
-
findFirstPossibleRangeContextCheckIn?.checkIn &&
|
|
44
|
-
isBefore(dateFrom, findFirstPossibleRangeContextCheckIn?.checkIn)
|
|
45
|
-
const isAfterRange =
|
|
46
|
-
dateFrom &&
|
|
47
|
-
findLastPossibleRangeContextCheckOut?.lastCheckOut &&
|
|
48
|
-
isAfter(
|
|
49
|
-
dateFrom,
|
|
50
|
-
endOfDay(findLastPossibleRangeContextCheckOut?.lastCheckOut)
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
return !(isBeforeRange || isAfterRange)
|
|
54
|
-
})
|
|
55
|
-
.map((date) => ({ from: date.from }))
|
|
56
|
-
: []
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
booked: disabledDates || [],
|
|
60
|
-
|
|
61
|
-
disabledAfterCheckIn: calendarRangeFrom
|
|
62
|
-
? [{ after: calendarRangeFrom }]
|
|
63
|
-
: [],
|
|
64
|
-
|
|
65
|
-
overlappingDate:
|
|
66
|
-
!calendarRangeFrom && !!filteredOverlappingDates.length
|
|
67
|
-
? filteredOverlappingDates.map((date) => ({ from: date.from }))
|
|
68
|
-
: [],
|
|
69
|
-
|
|
70
|
-
noActiveSelectionStart: rangeContextFrom || [],
|
|
71
|
-
|
|
72
|
-
noActiveSelectionMid: [
|
|
73
|
-
rangeContextFrom && rangeContextTo
|
|
74
|
-
? { after: rangeContextFrom, before: rangeContextTo }
|
|
75
|
-
: [],
|
|
76
|
-
],
|
|
77
|
-
|
|
78
|
-
noActiveSelectionEnd: rangeContextTo || [],
|
|
79
|
-
|
|
80
|
-
checkoutOptionsMid: [
|
|
81
|
-
...(calendarRangeFrom &&
|
|
82
|
-
!calendarRangeTo &&
|
|
83
|
-
currentSelectionLastCheckoutDate?.lastCheckOut
|
|
84
|
-
? [
|
|
85
|
-
{
|
|
86
|
-
after: calendarRangeFrom,
|
|
87
|
-
before: addDays(currentSelectionLastCheckoutDate.lastCheckOut, 1),
|
|
88
|
-
},
|
|
89
|
-
]
|
|
90
|
-
: []),
|
|
91
|
-
],
|
|
92
|
-
|
|
93
|
-
checkInOnly: [
|
|
94
|
-
...(findFirstPossibleRangeContextCheckIn?.checkIn &&
|
|
95
|
-
rangeContext &&
|
|
96
|
-
rangeContextFrom
|
|
97
|
-
? [
|
|
98
|
-
{
|
|
99
|
-
from: findFirstPossibleRangeContextCheckIn.checkIn,
|
|
100
|
-
to: addDays(rangeContextFrom, -1),
|
|
101
|
-
},
|
|
102
|
-
]
|
|
103
|
-
: []),
|
|
104
|
-
],
|
|
105
|
-
|
|
106
|
-
checkOutOnly: [
|
|
107
|
-
...(findLastPossibleRangeContextCheckOut?.checkIn &&
|
|
108
|
-
findLastPossibleRangeContextCheckOut.lastCheckOut
|
|
109
|
-
? [
|
|
110
|
-
{
|
|
111
|
-
from: addDays(findLastPossibleRangeContextCheckOut.checkIn, 1),
|
|
112
|
-
to: findLastPossibleRangeContextCheckOut.lastCheckOut,
|
|
113
|
-
},
|
|
114
|
-
]
|
|
115
|
-
: []),
|
|
116
|
-
],
|
|
117
|
-
}
|
|
118
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { DateRange, Matcher } from 'react-day-picker'
|
|
2
|
-
import { isEqual, endOfDay } from 'date-fns'
|
|
3
|
-
|
|
4
|
-
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
5
|
-
|
|
6
|
-
type Props = {
|
|
7
|
-
rangeContext?: RangeContext
|
|
8
|
-
availableDates?: DisableCalendarDates['availableDates']
|
|
9
|
-
calendarRange?: DateRange
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const handleRangeContextDisabledDates = ({
|
|
13
|
-
rangeContext,
|
|
14
|
-
availableDates,
|
|
15
|
-
calendarRange,
|
|
16
|
-
}: Props) => {
|
|
17
|
-
let findFirstPossibleRangeContextCheckIn:
|
|
18
|
-
| NonNullable<DisableCalendarDates['availableDates']>['0']
|
|
19
|
-
| undefined
|
|
20
|
-
let findLastPossibleRangeContextCheckOut:
|
|
21
|
-
| NonNullable<DisableCalendarDates['availableDates']>['0']
|
|
22
|
-
| undefined
|
|
23
|
-
|
|
24
|
-
let firstPossibleRangeContextCheckIn: Matcher[] = []
|
|
25
|
-
let lastPossibleRangeContextCheckOut: Matcher[] = []
|
|
26
|
-
|
|
27
|
-
// Parse data
|
|
28
|
-
const rangeContextFrom = rangeContext?.from && endOfDay(rangeContext.from)
|
|
29
|
-
const rangeContextTo = rangeContext?.to && endOfDay(rangeContext.to)
|
|
30
|
-
const calendarRangeFrom = calendarRange?.from && endOfDay(calendarRange.from)
|
|
31
|
-
|
|
32
|
-
if (rangeContext && availableDates?.length) {
|
|
33
|
-
// Find the first possible check-in after the last date gap till the range context
|
|
34
|
-
|
|
35
|
-
findFirstPossibleRangeContextCheckIn = availableDates?.find(
|
|
36
|
-
(date) =>
|
|
37
|
-
rangeContextFrom &&
|
|
38
|
-
endOfDay(date.checkIn) < rangeContextFrom &&
|
|
39
|
-
endOfDay(date.lastCheckOut) >= rangeContextFrom
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
if (findFirstPossibleRangeContextCheckIn?.checkIn) {
|
|
43
|
-
firstPossibleRangeContextCheckIn.push({
|
|
44
|
-
before: findFirstPossibleRangeContextCheckIn.checkIn,
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Find the last possible checkout before the first date gap till the range context
|
|
49
|
-
findLastPossibleRangeContextCheckOut = availableDates?.find(
|
|
50
|
-
(date) =>
|
|
51
|
-
rangeContextTo && isEqual(rangeContextTo, endOfDay(date.checkIn))
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
if (findLastPossibleRangeContextCheckOut?.checkIn) {
|
|
55
|
-
lastPossibleRangeContextCheckOut.push({
|
|
56
|
-
after: findLastPossibleRangeContextCheckOut.lastCheckOut,
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Get possible check-out dates for current check-in
|
|
62
|
-
const currentSelectionAvailability = availableDates?.find((date) => {
|
|
63
|
-
return calendarRangeFrom
|
|
64
|
-
? isEqual(endOfDay(date.checkIn), calendarRangeFrom)
|
|
65
|
-
: false
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
findFirstPossibleRangeContextCheckIn,
|
|
70
|
-
findLastPossibleRangeContextCheckOut,
|
|
71
|
-
firstPossibleRangeContextCheckIn,
|
|
72
|
-
lastPossibleRangeContextCheckOut,
|
|
73
|
-
currentSelectionAvailability,
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { parseDates } from './parseDates'
|
|
2
|
-
export { parseDate } from './parseDate'
|
|
3
|
-
export { nightsCount } from './nightsCount'
|
|
4
|
-
export { calendarSelectionRules } from './calendarSelectionRules'
|
|
5
|
-
export { disabledDatesByPage } from './disabledDatesByPage'
|
|
6
|
-
export { handleCalendarModifiers } from './handleCalendarModifiers'
|
|
7
|
-
export { handleRangeContextDisabledDates } from './handleRangeContextDisabledDates'
|
|
8
|
-
export { checkForContinuousSelection } from './checkForContinuousSelection'
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { differenceInCalendarDays } from 'date-fns'
|
|
2
|
-
import { DateRange } from 'react-day-picker'
|
|
3
|
-
|
|
4
|
-
type Props = {
|
|
5
|
-
calendarRange?: DateRange
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const nightsCount = ({ calendarRange }: Props) => {
|
|
9
|
-
if (!calendarRange || !calendarRange.from || !calendarRange.to) {
|
|
10
|
-
return undefined
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const diffDays = differenceInCalendarDays(
|
|
14
|
-
calendarRange.to,
|
|
15
|
-
calendarRange.from
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
return diffDays
|
|
19
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { format } from 'date-fns'
|
|
2
|
-
import { fi, enUS } from 'date-fns/locale'
|
|
3
|
-
|
|
4
|
-
type Props = {
|
|
5
|
-
date?: Date
|
|
6
|
-
dateFormat?: string
|
|
7
|
-
language?: string
|
|
8
|
-
}
|
|
9
|
-
export const parseDate = ({
|
|
10
|
-
date,
|
|
11
|
-
dateFormat = 'dd.MM.yyyy',
|
|
12
|
-
language,
|
|
13
|
-
}: Props) => {
|
|
14
|
-
return date
|
|
15
|
-
? format(date, dateFormat, { locale: language === 'en' ? enUS : fi })
|
|
16
|
-
: null
|
|
17
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { format } from 'date-fns'
|
|
2
|
-
import { DateRange } from 'react-day-picker'
|
|
3
|
-
|
|
4
|
-
type Props = {
|
|
5
|
-
calendarRange?: DateRange
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const parseDates = ({ calendarRange }: Props) =>
|
|
9
|
-
calendarRange?.to && calendarRange?.from
|
|
10
|
-
? `${format(calendarRange.from, 'dd.MM.yyyy')} -
|
|
11
|
-
${format(calendarRange.to, 'dd.MM.yyyy')}`
|
|
12
|
-
: null
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { SubmitButton } from './buttons/SubmitButton/SubmitButton'
|
|
2
|
-
export { CloseButton } from './buttons/CloseButton/CloseButton'
|
|
3
|
-
|
|
4
|
-
// Calendar
|
|
5
|
-
export { Calendar } from './calendar/Calendar'
|
|
6
|
-
export type { CalendarTypes } from './calendar/CalendarTypes'
|
|
7
|
-
export { parseDates } from './calendar/utils'
|
package/src/core/hooks/index.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react'
|
|
2
|
-
|
|
3
|
-
export const useAutoFocus = <T extends HTMLElement>(autoFocus?: boolean) => {
|
|
4
|
-
const ref = useRef<T>(null)
|
|
5
|
-
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
if (!autoFocus || !ref.current) return
|
|
8
|
-
|
|
9
|
-
const attemptFocus = (attempts = 0): void => {
|
|
10
|
-
if (attempts > 20 || !ref.current) return
|
|
11
|
-
|
|
12
|
-
const focusable = ref.current.querySelector<HTMLElement>(
|
|
13
|
-
'button:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
if (focusable) {
|
|
17
|
-
focusable.focus()
|
|
18
|
-
} else {
|
|
19
|
-
requestAnimationFrame(() => attemptFocus(attempts + 1))
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
requestAnimationFrame(() => attemptFocus())
|
|
24
|
-
}, [autoFocus])
|
|
25
|
-
|
|
26
|
-
return ref
|
|
27
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react'
|
|
2
|
-
|
|
3
|
-
export const useAwaitRender = () => {
|
|
4
|
-
const [initialRenderComplete, setInitialRenderComplete] =
|
|
5
|
-
useState<boolean>(false)
|
|
6
|
-
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
setInitialRenderComplete(true)
|
|
9
|
-
}, [])
|
|
10
|
-
|
|
11
|
-
if (!initialRenderComplete) return null
|
|
12
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react'
|
|
2
|
-
|
|
3
|
-
type Props = {
|
|
4
|
-
handleSelectedFilter: (arg: boolean) => void
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// TODO - Refactor and rename this hook
|
|
8
|
-
export const useCloseFilterSection = ({ handleSelectedFilter }: Props) => {
|
|
9
|
-
const filterSectionRef = useRef<HTMLDivElement | null>(null)
|
|
10
|
-
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
13
|
-
if (
|
|
14
|
-
filterSectionRef.current &&
|
|
15
|
-
!filterSectionRef.current.contains(event.target as Node)
|
|
16
|
-
) {
|
|
17
|
-
handleSelectedFilter(false)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
document.addEventListener('mousedown', handleClickOutside)
|
|
22
|
-
|
|
23
|
-
return () => {
|
|
24
|
-
document.removeEventListener('mousedown', handleClickOutside)
|
|
25
|
-
}
|
|
26
|
-
}, [filterSectionRef])
|
|
27
|
-
|
|
28
|
-
return { filterSectionRef }
|
|
29
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react'
|
|
2
|
-
import i18n from '../../i18n'
|
|
3
|
-
|
|
4
|
-
type Props = { language?: string }
|
|
5
|
-
|
|
6
|
-
export const useUpdateTranslations = ({ language }: Props) => {
|
|
7
|
-
const [rerenderKey, setRerenderKey] = useState(0)
|
|
8
|
-
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
i18n.changeLanguage(language)
|
|
11
|
-
|
|
12
|
-
setRerenderKey((prevKey) => prevKey + 1)
|
|
13
|
-
}, [language])
|
|
14
|
-
}
|
package/src/i18n.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import i18n from 'i18next'
|
|
2
|
-
import { initReactI18next } from 'react-i18next'
|
|
3
|
-
|
|
4
|
-
import enFilterBar from './locales/en/filterBar.json'
|
|
5
|
-
import enCommon from './locales/en/common.json'
|
|
6
|
-
import fiFilterBar from './locales/fi/filterBar.json'
|
|
7
|
-
import fiCommon from './locales/fi/common.json'
|
|
8
|
-
|
|
9
|
-
const urlParams =
|
|
10
|
-
typeof window !== 'undefined'
|
|
11
|
-
? new URLSearchParams(window.location.search)
|
|
12
|
-
: null
|
|
13
|
-
const localeFromUrl = urlParams?.get('locale') || 'fi'
|
|
14
|
-
|
|
15
|
-
i18n.use(initReactI18next).init({
|
|
16
|
-
resources: {
|
|
17
|
-
en: { filterBar: enFilterBar, common: enCommon },
|
|
18
|
-
fi: { filterBar: fiFilterBar, common: fiCommon },
|
|
19
|
-
},
|
|
20
|
-
lng: localeFromUrl,
|
|
21
|
-
fallbackLng: 'fi',
|
|
22
|
-
interpolation: {
|
|
23
|
-
escapeValue: false,
|
|
24
|
-
},
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export default i18n
|