willba-component-library 0.3.13 → 0.3.15

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 (110) hide show
  1. package/README.md +12 -12
  2. package/lib/assets/IconsSvg.d.ts +2 -1
  3. package/lib/components/Button/Button.d.ts +2 -2
  4. package/lib/components/FilterBar/FilterBar.d.ts +3 -2
  5. package/lib/components/FilterBar/components/FilterControls/FilterControls.d.ts +3 -0
  6. package/lib/components/FilterBar/components/FilterPanels/Categories/Categories.d.ts +11 -0
  7. package/lib/components/FilterBar/components/FilterPanels/Dates/Dates.d.ts +16 -0
  8. package/lib/components/FilterBar/components/FilterPanels/FilterPanels.d.ts +3 -0
  9. package/lib/components/FilterBar/components/FilterPanels/Guests/GuestCount/GuestCount.d.ts +4 -0
  10. package/lib/components/FilterBar/components/FilterPanels/Guests/Guests.d.ts +12 -0
  11. package/lib/components/FilterBar/components/FilterPanels/Locations/Locations.d.ts +14 -0
  12. package/lib/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.d.ts +8 -0
  13. package/lib/components/FilterBar/components/FilterTabs/FilterTabs.d.ts +3 -0
  14. package/lib/components/FilterBar/components/ImageCard/ImageCard.d.ts +11 -0
  15. package/lib/components/FilterBar/components/SelectButton/SelectButton.d.ts +13 -0
  16. package/lib/components/FilterBar/components/TabButton/TabButton.d.ts +10 -0
  17. package/lib/components/FilterBar/components/buttons/select-button/SelectButton.d.ts +2 -1
  18. package/lib/components/FilterBar/components/buttons/tab-button/TabButton.d.ts +2 -1
  19. package/lib/components/FilterBar/components/cards/image-card/ImageCard.d.ts +2 -1
  20. package/lib/components/FilterBar/components/categories/Categories.d.ts +2 -1
  21. package/lib/components/FilterBar/components/common/FilterSectionHeader.d.ts +2 -2
  22. package/lib/components/FilterBar/components/dates/Dates.d.ts +2 -2
  23. package/lib/components/FilterBar/components/divider/Divider.d.ts +2 -1
  24. package/lib/components/FilterBar/components/guests/Guests.d.ts +2 -1
  25. package/lib/components/FilterBar/components/index.d.ts +6 -5
  26. package/lib/components/FilterBar/components/locations/Locations.d.ts +2 -1
  27. package/lib/components/FilterBar/hooks/index.d.ts +4 -1
  28. package/lib/components/FilterBar/hooks/useFilterActions.d.ts +25 -0
  29. package/lib/components/FilterBar/hooks/useFilterState.d.ts +22 -0
  30. package/lib/components/FilterBar/hooks/useFilterUi.d.ts +7 -0
  31. package/lib/components/FilterBar/hooks/usePanelPosition.d.ts +12 -0
  32. package/lib/components/FilterBar/index.d.ts +1 -1
  33. package/lib/components/FilterBar/providers/FilterBarProvider.d.ts +31 -0
  34. package/lib/components/FilterBar/providers/index.d.ts +1 -0
  35. package/lib/components/FilterBar/utils/ageCategoriesRules.d.ts +7 -0
  36. package/lib/components/FilterBar/utils/index.d.ts +1 -1
  37. package/lib/components/FilterBar/utils/parseGuests.d.ts +5 -1
  38. package/lib/components/FilterCalendar/FilterCalendar.d.ts +3 -2
  39. package/lib/components/FilterCalendar/components/Footer.d.ts +2 -1
  40. package/lib/core/components/buttons/CloseButton/CloseButton.d.ts +7 -0
  41. package/lib/core/components/buttons/SubmitButton/SubmitButton.d.ts +14 -0
  42. package/lib/core/components/buttons/close-button/CloseButton.d.ts +2 -1
  43. package/lib/core/components/buttons/submit-button/SubmitButton.d.ts +2 -1
  44. package/lib/core/components/calendar/Calendar.d.ts +2 -1
  45. package/lib/core/components/index.d.ts +4 -2
  46. package/lib/index.d.ts +4 -5
  47. package/lib/index.esm.js +1593 -1480
  48. package/lib/index.esm.js.map +1 -1
  49. package/lib/index.js +2156 -2043
  50. package/lib/index.js.map +1 -1
  51. package/lib/index.umd.js +2159 -2045
  52. package/lib/index.umd.js.map +1 -1
  53. package/lib/themes/useTheme.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/rollup.config.mjs +1 -1
  56. package/src/components/FilterBar/FilterBar.css +4 -70
  57. package/src/components/FilterBar/FilterBar.stories.tsx +1 -1
  58. package/src/components/FilterBar/FilterBar.tsx +28 -283
  59. package/src/components/FilterBar/components/FilterControls/FilterControls.css +18 -0
  60. package/src/components/FilterBar/components/FilterControls/FilterControls.tsx +135 -0
  61. package/src/components/FilterBar/components/{categories → FilterPanels/Categories}/Categories.css +1 -1
  62. package/src/components/FilterBar/components/{categories → FilterPanels/Categories}/Categories.tsx +3 -1
  63. package/src/components/FilterBar/components/{dates → FilterPanels/Dates}/Dates.tsx +11 -11
  64. package/src/components/FilterBar/components/FilterPanels/FilterPanels.css +24 -0
  65. package/src/components/FilterBar/components/FilterPanels/FilterPanels.tsx +115 -0
  66. package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/GuestCount/GuestCount.tsx +1 -1
  67. package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/Guests.css +5 -6
  68. package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/Guests.tsx +7 -7
  69. package/src/components/FilterBar/components/{locations → FilterPanels/Locations}/Locations.css +1 -1
  70. package/src/components/FilterBar/components/{locations → FilterPanels/Locations}/Locations.tsx +7 -6
  71. package/src/components/FilterBar/components/{common/FilterSectionHeader.tsx → FilterPanels/SectionHeader/SectionHeader.tsx} +2 -2
  72. package/src/components/FilterBar/components/FilterTabs/FilterTabs.css +10 -0
  73. package/src/components/FilterBar/components/FilterTabs/FilterTabs.tsx +47 -0
  74. package/src/components/FilterBar/components/{buttons/select-button → SelectButton}/SelectButton.css +1 -0
  75. package/src/components/FilterBar/components/{buttons/select-button → SelectButton}/SelectButton.tsx +7 -6
  76. package/src/components/FilterBar/components/index.ts +6 -6
  77. package/src/components/FilterBar/hooks/index.ts +4 -1
  78. package/src/components/FilterBar/hooks/useFilterActions.tsx +126 -0
  79. package/src/components/FilterBar/hooks/useFilterState.tsx +86 -0
  80. package/src/components/FilterBar/hooks/useFilterUi.tsx +19 -0
  81. package/src/components/FilterBar/hooks/usePanelPosition.tsx +66 -0
  82. package/src/components/FilterBar/index.ts +1 -1
  83. package/src/components/FilterBar/providers/FilterBarProvider.tsx +169 -0
  84. package/src/components/FilterBar/providers/index.ts +1 -0
  85. package/src/components/FilterBar/utils/ageCategoriesRules.ts +27 -0
  86. package/src/components/FilterBar/utils/index.tsx +1 -1
  87. package/src/components/FilterBar/utils/parseGuests.tsx +20 -9
  88. package/src/components/FilterBar/utils/{parseLocations.tsx → parseLocations.ts} +3 -4
  89. package/src/components/FilterCalendar/FilterCalendar.tsx +2 -2
  90. package/src/core/components/index.ts +5 -2
  91. package/src/index.ts +1 -1
  92. package/src/themes/useTheme.tsx +1 -1
  93. package/src/components/FilterBar/components/buttons/index.ts +0 -5
  94. package/src/components/FilterBar/components/cards/index.ts +0 -1
  95. package/src/components/FilterBar/components/dates/index.ts +0 -1
  96. package/src/components/FilterBar/hooks/useFilterBar.tsx +0 -208
  97. package/src/components/FilterBar/utils/calculateDropdownPosition.tsx +0 -96
  98. /package/src/components/FilterBar/components/{divider → Divider}/Divider.css +0 -0
  99. /package/src/components/FilterBar/components/{divider → Divider}/Divider.tsx +0 -0
  100. /package/src/components/FilterBar/components/{dates → FilterPanels/Dates}/Dates.css +0 -0
  101. /package/src/components/FilterBar/components/{guests → FilterPanels/Guests}/GuestCount/GuestCount.css +0 -0
  102. /package/src/components/FilterBar/components/{common/FilterSectionHeader.css → FilterPanels/SectionHeader/SectionHeader.css} +0 -0
  103. /package/src/components/FilterBar/components/{cards/image-card → ImageCard}/ImageCard.css +0 -0
  104. /package/src/components/FilterBar/components/{cards/image-card → ImageCard}/ImageCard.tsx +0 -0
  105. /package/src/components/FilterBar/components/{buttons/tab-button → TabButton}/TabButton.css +0 -0
  106. /package/src/components/FilterBar/components/{buttons/tab-button → TabButton}/TabButton.tsx +0 -0
  107. /package/src/core/components/buttons/{close-button → CloseButton}/CloseButton.css +0 -0
  108. /package/src/core/components/buttons/{close-button → CloseButton}/CloseButton.tsx +0 -0
  109. /package/src/core/components/buttons/{submit-button → SubmitButton}/SubmitButton.css +0 -0
  110. /package/src/core/components/buttons/{submit-button → SubmitButton}/SubmitButton.tsx +0 -0
@@ -12,4 +12,4 @@ export interface CustomPaletteTypes extends CSSProperties {
12
12
  '--will-secondary'?: string;
13
13
  '--will-error'?: string;
14
14
  }
15
- export default function useTheme({ palette }: ThemeProps): CustomPaletteTypes;
15
+ export declare const useTheme: ({ palette }: ThemeProps) => CustomPaletteTypes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "willba-component-library",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "description": "A custom UI component library",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.esm.js",
package/rollup.config.mjs CHANGED
@@ -46,7 +46,7 @@ export default [
46
46
  resolve(),
47
47
  commonjs(),
48
48
  typescript({
49
- jsx: 'react-jsx',
49
+ jsx: 'react',
50
50
  }),
51
51
  postcss({
52
52
  extensions: ['.css'],
@@ -16,80 +16,14 @@
16
16
  position: relative;
17
17
  }
18
18
 
19
- /* Tabs */
20
-
21
- .will-filter-bar-tabs {
22
- display: flex;
23
- align-items: center;
24
- justify-content: center;
25
- position: relative;
26
- z-index: 222;
27
- background: transparent;
28
- padding: 10px;
29
- gap: 10px;
30
- }
31
-
32
- /* Header */
33
- .will-filter-bar-header {
34
- display: flex;
35
- justify-content: space-between;
36
- padding: 10px;
37
- position: relative;
38
- z-index: 222;
39
- border-radius: 40px;
40
- background-color: var(--will-white);
41
- }
42
-
43
- @media (max-width: 960px) {
44
- .will-filter-bar-header {
45
- flex-direction: column;
46
- padding: 20px;
47
- border-radius: 25px;
48
- overflow: hidden;
49
- }
50
- }
51
-
52
- /* Container */
53
-
54
- .will-filter-bar-container {
55
- background-color: var(--will-white);
56
- min-height: 100px;
57
- position: absolute;
58
- top: 125px;
59
- z-index: 111;
60
- border-radius: 25px;
61
- box-shadow: var(--will-box-shadow);
62
- }
63
-
64
- @media (max-width: 960px) {
65
- .will-root {
66
- width: 100%;
67
- min-width: auto;
68
- max-height: 100vh;
69
- z-index: 3;
70
- }
71
-
72
- .will-filter-bar-container {
73
- margin-top: 10px;
74
- top: 0;
75
- padding: 45px 20px;
76
- position: relative;
77
- }
78
- }
79
-
80
19
  /* Common */
81
20
 
82
- .will-filter-bar-header.dark,
83
- .will-filter-bar-container.dark {
21
+ .will-filter-bar-controls.dark,
22
+ .will-filter-bar-panels.dark {
84
23
  box-shadow: var(--will-box-shadow-dark);
85
24
  }
86
25
 
87
- .will-filter-bar-header.light,
88
- .will-filter-bar-container.light {
26
+ .will-filter-bar-controls.light,
27
+ .will-filter-bar-panels.light {
89
28
  box-shadow: var(--will-box-shadow-light);
90
29
  }
91
-
92
- .will-guest-count {
93
- display: inline-block;
94
- min-width: 10px;
95
- }
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
  import type { Meta, StoryObj } from '@storybook/react'
3
3
 
4
- import FilterBar from './FilterBar'
4
+ import { FilterBar } from './FilterBar'
5
5
  import { Filters } from './FilterBarTypes'
6
6
 
7
7
  const meta: Meta<typeof FilterBar> = {
@@ -1,41 +1,18 @@
1
- import React, {
2
- CSSProperties,
3
- MutableRefObject,
4
- useEffect,
5
- useRef,
6
- useState,
7
- } from 'react'
8
- import { useTranslation } from 'react-i18next'
9
- import { FaSearch } from 'react-icons/fa'
1
+ import React from 'react'
10
2
 
11
- import useTheme from '../../themes/useTheme'
12
- import '../../themes/Default.css'
13
- import {
14
- useAwaitRender,
15
- useCloseFilterSection,
16
- useUpdateTranslations,
17
- } from '../../core/hooks'
18
- import { SubmitButton } from '../../core/components'
19
- import { parseDates } from '../../core/components/calendar/utils'
3
+ import { useTheme } from '../../themes/useTheme'
4
+ import { useAwaitRender, useUpdateTranslations } from '../../core/hooks'
20
5
 
21
- import { parseGuests, parseLocations, calculateDropdownPosition } from './utils'
22
- import { FilterBarTypes, FilterSections, Pages } from './FilterBarTypes'
23
- import { useFilterBar, useScrollInToView } from './hooks'
24
- import {
25
- TabButton,
26
- SelectButton,
27
- Guests,
28
- Divider,
29
- Categories,
30
- Locations,
31
- } from './components'
6
+ import { FilterBarTypes } from './FilterBarTypes'
7
+ import { FilterPanels, FilterControls, FilterTabs } from './components'
8
+ import { FilterBarProvider } from './providers'
32
9
 
10
+ import '../../themes/Default.css'
33
11
  import './FilterBar.css'
34
- import { Dates } from './components/dates'
35
12
 
36
- export default function FilterBar({
13
+ export const FilterBar = ({
37
14
  language = LANGUAGE_FALLBACK,
38
- ageCategories = AGE_CATEGORIES_FALLBACK,
15
+ ageCategories,
39
16
  redirectUrl = REDIRECT_URL_FALLBACK,
40
17
  palette,
41
18
  onSubmit,
@@ -45,276 +22,44 @@ export default function FilterBar({
45
22
  tabs,
46
23
  outerLoading,
47
24
  locations,
48
- }: FilterBarTypes) {
25
+ }: FilterBarTypes) => {
49
26
  const themePalette = useTheme({ palette })
50
27
 
51
28
  // Translations
52
29
  useUpdateTranslations({ language })
53
- const { t } = useTranslation('filterBar')
54
-
55
- // Refs for SelectButtons
56
- const locationsButtonRef = useRef<HTMLButtonElement>(null)
57
- const datesButtonRef = useRef<HTMLButtonElement>(null)
58
- const guestsButtonRef = useRef<HTMLButtonElement>(null)
59
- const previouslyFocusedButtonRef = useRef<HTMLButtonElement | null>(null)
60
- const headerRef = useRef<HTMLDivElement>(null)
61
-
62
- // Dropdown positioning
63
- const [dropdownStyle, setDropdownStyle] = useState<CSSProperties>({})
64
-
65
- // Filters
66
- const {
67
- selectedFilter,
68
- ageCategoryCounts,
69
- categories,
70
- calendarRange,
71
- selectedPath,
72
- innerLoading,
73
- selectedLocations,
74
- setSelectedLocations,
75
- setCalendarRange,
76
- setCategories,
77
- handleSelectedFilter,
78
- handleSubmit,
79
- updateGuestsCount,
80
- setSelectedPath,
81
- handleResetFilters,
82
- } = useFilterBar({
83
- redirectUrl,
84
- ageCategories,
85
- onSubmit,
86
- tabs,
87
- locations,
88
- })
89
-
90
- // Scroll in to view
91
- const { isMobile, targetFilterBarRef } = useScrollInToView({ selectedFilter })
92
-
93
- // Handle close filter section
94
- const { filtersRef } = useCloseFilterSection({ handleSelectedFilter })
95
-
96
- // Enhanced handleSelectedFilter with positioning
97
- const handleSelectedFilterWithPosition = (filter: FilterSections | false) => {
98
- if (filter) {
99
- const position = calculateDropdownPosition({
100
- filterSection: filter,
101
- headerRef,
102
- locationsButtonRef,
103
- datesButtonRef,
104
- guestsButtonRef,
105
- isMobile,
106
- })
107
- setDropdownStyle(position)
108
- }
109
- handleSelectedFilter(filter)
110
- }
111
-
112
- // Store previously focused button and restore focus when closing
113
- useEffect(() => {
114
- if (!selectedFilter && previouslyFocusedButtonRef.current) {
115
- previouslyFocusedButtonRef.current.focus()
116
- previouslyFocusedButtonRef.current = null
117
- }
118
- }, [selectedFilter])
119
30
 
120
31
  // Display component after fully loaded
121
32
  useAwaitRender()
122
33
 
123
- // Parsed data for filter section description
124
- const parsedDates = parseDates({ calendarRange })
125
- const parsedGuests = parseGuests({
126
- ageCategoryCounts,
127
- ageCategories,
128
- guestsPlaceholder: t('guests.labelPlaceholder'),
129
- guestLabel: t('guests.guestLabel'),
130
- guestsLabel: t('guests.guestsLabel'),
131
- })
132
- const parsedLocations = parseLocations({
133
- selectedLocations,
134
- locationsPlaceholder: t('locations.placeholder'),
135
- locationsSelectedLabel: t('locations.selected'),
136
- })
137
-
138
34
  return (
139
- <div
140
- className={`will-root ${fullWidth ? 'is-full-width' : ''}`}
141
- style={themePalette}
35
+ <FilterBarProvider
36
+ language={language}
37
+ ageCategories={ageCategories}
38
+ redirectUrl={redirectUrl}
39
+ palette={palette}
40
+ onSubmit={onSubmit}
41
+ fullWidth={fullWidth}
42
+ disableCalendarDates={disableCalendarDates}
43
+ mode={mode}
44
+ tabs={tabs}
45
+ outerLoading={outerLoading}
46
+ locations={locations}
142
47
  >
143
- {tabs && tabs.length > 1 && (
144
- <div className="will-filter-bar-tabs" ref={targetFilterBarRef}>
145
- {tabs
146
- .sort((a, b) => a.order - b.order)
147
- .map((tab, idx) => (
148
- <TabButton
149
- key={`tab-${idx}`}
150
- label={tab.label || t(`tabs.${tab.path.substring(1)}`)}
151
- onClick={() => {
152
- setSelectedPath(tab.path)
153
- handleResetFilters()
154
- handleSelectedFilter(false)
155
- }}
156
- active={selectedPath === tab.path}
157
- mode={mode}
158
- />
159
- ))}
160
- </div>
161
- )}
162
-
163
48
  <div
164
- className={`will-filter-bar-header ${mode || 'light'}`}
165
- ref={(el) => {
166
- ;(headerRef as MutableRefObject<HTMLDivElement | null>).current = el
167
- if (tabs?.length === 1 && targetFilterBarRef) {
168
- ;(
169
- targetFilterBarRef as MutableRefObject<HTMLDivElement | null>
170
- ).current = el
171
- }
172
- }}
49
+ className={`will-root ${fullWidth ? 'is-full-width' : ''}`}
50
+ style={themePalette}
173
51
  >
174
- {!!locations?.data?.length && (
175
- <>
176
- <SelectButton
177
- ref={locationsButtonRef}
178
- label={t('locations.label')}
179
- description={parsedLocations}
180
- onClick={() => {
181
- previouslyFocusedButtonRef.current = locationsButtonRef.current
182
- handleSelectedFilterWithPosition(FilterSections.LOCATIONS)
183
- }}
184
- active={!!selectedLocations.length}
185
- disabled={locations?.disabled}
186
- ariaExpanded={selectedFilter === FilterSections.LOCATIONS}
187
- ariaControls="will-locations-filter"
188
- />
189
-
190
- <Divider />
191
- </>
192
- )}
52
+ <FilterTabs />
193
53
 
194
- <SelectButton
195
- ref={datesButtonRef}
196
- label={t('calendar.label')}
197
- description={
198
- parsedDates
199
- ? parsedDates
200
- : selectedPath === Pages.ROOMS
201
- ? t('calendar.roomsLabelPlaceholder')
202
- : t('calendar.eventsLabelPlaceholder')
203
- }
204
- onClick={() => {
205
- previouslyFocusedButtonRef.current = datesButtonRef.current
206
- handleSelectedFilterWithPosition(FilterSections.CALENDAR)
207
- }}
208
- active={!!parsedDates}
209
- ariaExpanded={selectedFilter === FilterSections.CALENDAR}
210
- ariaControls="will-calendar-filter"
211
- />
54
+ <FilterControls />
212
55
 
213
- {selectedPath !== Pages.EVENTS && (
214
- <>
215
- <Divider />
216
-
217
- <SelectButton
218
- ref={guestsButtonRef}
219
- label={t('guests.label')}
220
- description={parsedGuests.content}
221
- onClick={() => {
222
- previouslyFocusedButtonRef.current = guestsButtonRef.current
223
- handleSelectedFilterWithPosition(FilterSections.GUESTS)
224
- }}
225
- active={!!parsedGuests.data.total}
226
- ariaExpanded={selectedFilter === FilterSections.GUESTS}
227
- ariaControls="will-guests-filter"
228
- />
229
- </>
230
- )}
231
-
232
- <SubmitButton
233
- onClick={handleSubmit}
234
- startIcon={<FaSearch />}
235
- label={t('common:search')}
236
- isLoading={innerLoading || outerLoading}
237
- />
56
+ <FilterPanels />
238
57
  </div>
239
-
240
- {selectedFilter && (
241
- <div
242
- className={`will-filter-bar-container ${mode || 'light'}`}
243
- style={{
244
- ...((!tabs || tabs.length < 2) && !isMobile ? { top: 66 } : {}),
245
- ...dropdownStyle,
246
- }}
247
- >
248
- {selectedFilter === FilterSections.CALENDAR && (
249
- <div id="will-dates-filter">
250
- <Dates
251
- autoFocus
252
- ref={filtersRef}
253
- onClose={() => handleSelectedFilter(false)}
254
- calendarRange={calendarRange}
255
- setCalendarRange={setCalendarRange}
256
- disableCalendarDates={disableCalendarDates}
257
- selectedPath={selectedPath}
258
- language={language}
259
- filtersRef={filtersRef}
260
- />
261
- </div>
262
- )}
263
- {selectedFilter === FilterSections.GUESTS && (
264
- <div id="will-guests-filter">
265
- <Guests
266
- updateGuestsCount={updateGuestsCount}
267
- ageCategories={ageCategories}
268
- ageCategoryCounts={ageCategoryCounts}
269
- ref={filtersRef}
270
- autoFocus
271
- onClose={() => handleSelectedFilter(false)}
272
- />
273
- </div>
274
- )}
275
- {selectedFilter === FilterSections.CATEGORIES && (
276
- <div id="will-categories-filter">
277
- <Categories
278
- categories={categories}
279
- setCategories={setCategories}
280
- />
281
- </div>
282
- )}
283
- {selectedFilter === FilterSections.LOCATIONS && (
284
- <div id="will-locations-filter">
285
- <Locations
286
- autoFocus
287
- ref={filtersRef}
288
- locations={locations?.data}
289
- language={language}
290
- selectedLocations={selectedLocations}
291
- setSelectedLocations={setSelectedLocations}
292
- multiSelect={locations?.multiSelect}
293
- onClose={() => handleSelectedFilter(false)}
294
- />
295
- </div>
296
- )}
297
- </div>
298
- )}
299
- </div>
58
+ </FilterBarProvider>
300
59
  )
301
60
  }
302
61
 
303
62
  ////////////
304
63
 
305
- const AGE_CATEGORIES_FALLBACK = [
306
- {
307
- id: '1',
308
- name: 'Adults',
309
- sortOrder: 1,
310
- minVal: 0,
311
- },
312
- {
313
- id: '2',
314
- name: 'Kids',
315
- sortOrder: 2,
316
- minVal: 0,
317
- },
318
- ]
319
64
  const REDIRECT_URL_FALLBACK = 'http://localhost:3000/'
320
65
  const LANGUAGE_FALLBACK = 'en'
@@ -0,0 +1,18 @@
1
+ .will-filter-bar-controls {
2
+ display: flex;
3
+ justify-content: space-between;
4
+ padding: 10px;
5
+ position: relative;
6
+ z-index: 222;
7
+ border-radius: 40px;
8
+ background-color: var(--will-white);
9
+ }
10
+
11
+ @media (max-width: 960px) {
12
+ .will-filter-bar-controls {
13
+ flex-direction: column;
14
+ padding: 20px;
15
+ border-radius: 25px;
16
+ overflow: hidden;
17
+ }
18
+ }
@@ -0,0 +1,135 @@
1
+ import React, { useEffect } from 'react'
2
+ import { useTranslation } from 'react-i18next'
3
+ import { FaSearch } from 'react-icons/fa'
4
+
5
+ import { parseDates, SubmitButton } from '../../../../core/components'
6
+ import { useFilterBar } from '../../providers'
7
+ import { parseGuests, parseLocations } from '../../utils'
8
+ import { FilterSections, Pages } from '../../FilterBarTypes'
9
+
10
+ import { Divider } from '../Divider/Divider'
11
+ import { SelectButton } from '../SelectButton/SelectButton'
12
+
13
+ import './FilterControls.css'
14
+
15
+ export const FilterControls = () => {
16
+ const { t } = useTranslation('filterBar')
17
+
18
+ const {
19
+ calendarRange,
20
+ selectedFilter,
21
+ selectedPath,
22
+ ageCategoryCounts,
23
+ selectedLocations,
24
+ mode,
25
+ tabs,
26
+ ageCategories,
27
+ locations,
28
+ innerLoading,
29
+ outerLoading,
30
+
31
+ handleSubmit,
32
+ handleSelectedFilter,
33
+
34
+ // Refs
35
+ previouslyFocusedButtonRef,
36
+ buttonRefs,
37
+ //
38
+ targetFilterBarRef,
39
+ } = useFilterBar()
40
+
41
+ // Store previously focused button and restore focus when closing
42
+ useEffect(() => {
43
+ if (!selectedFilter && previouslyFocusedButtonRef.current) {
44
+ previouslyFocusedButtonRef.current.focus()
45
+ previouslyFocusedButtonRef.current = null
46
+ }
47
+ }, [selectedFilter])
48
+
49
+ // Parsed data for filter section description
50
+ const parsedDates = parseDates({ calendarRange })
51
+ const parsedGuests = parseGuests({
52
+ ageCategoryCounts,
53
+ ageCategories,
54
+ guestsPlaceholder: t('guests.labelPlaceholder'),
55
+ guestLabel: t('guests.guestLabel'),
56
+ guestsLabel: t('guests.guestsLabel'),
57
+ })
58
+ const parsedLocations = parseLocations({
59
+ selectedLocations,
60
+ locationsPlaceholder: t('locations.placeholder'),
61
+ locationsSelectedLabel: t('locations.selected'),
62
+ })
63
+
64
+ return (
65
+ <div
66
+ className={`will-filter-bar-controls ${mode || 'light'}`}
67
+ ref={tabs?.length === 1 ? targetFilterBarRef : null}
68
+ >
69
+ {!!locations?.data?.length && (
70
+ <>
71
+ <SelectButton
72
+ ref={(el) => (buttonRefs.current[FilterSections.LOCATIONS] = el)}
73
+ label={t('locations.label')}
74
+ description={parsedLocations}
75
+ onClick={(e) => {
76
+ previouslyFocusedButtonRef.current = e.currentTarget
77
+ handleSelectedFilter(FilterSections.LOCATIONS)
78
+ }}
79
+ active={!!selectedLocations.length}
80
+ disabled={locations?.disabled}
81
+ ariaExpanded={selectedFilter === FilterSections.LOCATIONS}
82
+ ariaControls="will-filter-bar-locations"
83
+ />
84
+
85
+ <Divider />
86
+ </>
87
+ )}
88
+
89
+ <SelectButton
90
+ ref={(el) => (buttonRefs.current[FilterSections.CALENDAR] = el)}
91
+ label={t('calendar.label')}
92
+ description={
93
+ parsedDates
94
+ ? parsedDates
95
+ : selectedPath === Pages.ROOMS
96
+ ? t('calendar.roomsLabelPlaceholder')
97
+ : t('calendar.eventsLabelPlaceholder')
98
+ }
99
+ onClick={(e) => {
100
+ previouslyFocusedButtonRef.current = e.currentTarget
101
+ handleSelectedFilter(FilterSections.CALENDAR)
102
+ }}
103
+ active={!!parsedDates}
104
+ ariaExpanded={selectedFilter === FilterSections.CALENDAR}
105
+ ariaControls="will-filter-bar-dates"
106
+ />
107
+
108
+ {selectedPath !== Pages.EVENTS && (
109
+ <>
110
+ <Divider />
111
+
112
+ <SelectButton
113
+ ref={(el) => (buttonRefs.current[FilterSections.GUESTS] = el)}
114
+ label={t('guests.label')}
115
+ description={parsedGuests.content}
116
+ onClick={(e) => {
117
+ previouslyFocusedButtonRef.current = e.currentTarget
118
+ handleSelectedFilter(FilterSections.GUESTS)
119
+ }}
120
+ active={!!parsedGuests.data.total}
121
+ ariaExpanded={selectedFilter === FilterSections.GUESTS}
122
+ ariaControls="will-guests-filter"
123
+ />
124
+ </>
125
+ )}
126
+
127
+ <SubmitButton
128
+ onClick={handleSubmit}
129
+ startIcon={<FaSearch />}
130
+ label={t('common:search')}
131
+ isLoading={innerLoading || outerLoading}
132
+ />
133
+ </div>
134
+ )
135
+ }
@@ -1,4 +1,4 @@
1
- .will-filter-bar-categories {
1
+ #will-filter-bar-categories {
2
2
  text-align: center;
3
3
  }
4
4
 
@@ -26,7 +26,7 @@ export const Categories = ({ categories, setCategories }: Props) => {
26
26
  }
27
27
 
28
28
  return (
29
- <div className="will-filter-bar-categories">
29
+ <div id="will-filter-bar-categories">
30
30
  <h3 className="will-categories-filter-title">{t('categories.label')}</h3>
31
31
 
32
32
  <div className="will-categories-filter-inner">
@@ -45,3 +45,5 @@ export const Categories = ({ categories, setCategories }: Props) => {
45
45
  </div>
46
46
  )
47
47
  }
48
+
49
+ Categories.displayName = 'Categories'
@@ -1,10 +1,13 @@
1
1
  import React, { RefObject, forwardRef } from 'react'
2
-
3
2
  import { DateRange } from 'react-day-picker'
4
- import { Calendar } from '../../../../core/components'
5
- import { DisableCalendarDates } from '../../../../core/components/calendar/CalendarTypes'
6
- import { CloseButton } from '../buttons'
7
- import { FilterSectionHeader } from '../common/FilterSectionHeader'
3
+
4
+ import {
5
+ CalendarTypes,
6
+ CloseButton,
7
+ Calendar,
8
+ } from '../../../../../core/components'
9
+
10
+ import { SectionHeader } from '../SectionHeader/SectionHeader'
8
11
 
9
12
  import './Dates.css'
10
13
 
@@ -14,10 +17,9 @@ type Props = {
14
17
  autoFocus?: boolean
15
18
  calendarRange: DateRange | undefined
16
19
  setCalendarRange: (range: DateRange | undefined) => void
17
- disableCalendarDates?: DisableCalendarDates
20
+ disableCalendarDates?: CalendarTypes['disableCalendarDates']
18
21
  selectedPath?: string
19
22
  language?: string
20
- filtersRef?: RefObject<HTMLDivElement>
21
23
  }
22
24
 
23
25
  export const Dates = forwardRef<HTMLDivElement, Props>(
@@ -30,13 +32,12 @@ export const Dates = forwardRef<HTMLDivElement, Props>(
30
32
  disableCalendarDates,
31
33
  selectedPath,
32
34
  language,
33
- filtersRef,
34
35
  },
35
36
  ref
36
37
  ) => {
37
38
  return (
38
- <div className="will-filter-bar-dates" ref={ref}>
39
- <FilterSectionHeader
39
+ <div id="will-filter-bar-dates" ref={ref}>
40
+ <SectionHeader
40
41
  title={''}
41
42
  action={onClose && <CloseButton handleClose={onClose} />}
42
43
  />
@@ -49,7 +50,6 @@ export const Dates = forwardRef<HTMLDivElement, Props>(
49
50
  disableCalendarDates={disableCalendarDates}
50
51
  selectedPath={selectedPath}
51
52
  language={language}
52
- ref={filtersRef}
53
53
  />
54
54
  </div>
55
55
  </div>