willba-component-library 0.3.19 → 0.3.21

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 (33) hide show
  1. package/README.md +1 -1
  2. package/lib/components/FilterBar/components/FilterPanels/Locations/Locations.d.ts +0 -1
  3. package/lib/components/FilterBar/components/FilterTabs/FilterTabs.d.ts +1 -1
  4. package/lib/components/FilterBar/hooks/index.d.ts +1 -1
  5. package/lib/components/FilterBar/hooks/useFilterRefs.d.ts +8 -0
  6. package/lib/components/FilterBar/hooks/useFilterUi.d.ts +2 -1
  7. package/lib/components/FilterBar/hooks/usePanelPosition.d.ts +2 -2
  8. package/lib/components/FilterBar/hooks/useScrollInToView.d.ts +1 -1
  9. package/lib/components/FilterBar/providers/FilterBarProvider.d.ts +3 -2
  10. package/lib/core/hooks/useCloseFilterSection.d.ts +1 -1
  11. package/lib/index.esm.js +57 -57
  12. package/lib/index.esm.js.map +1 -1
  13. package/lib/index.js +57 -57
  14. package/lib/index.js.map +1 -1
  15. package/lib/index.umd.js +57 -57
  16. package/lib/index.umd.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/components/FilterBar/FilterBar.tsx +1 -2
  19. package/src/components/FilterBar/components/FilterControls/FilterControls.tsx +10 -6
  20. package/src/components/FilterBar/components/FilterPanels/Dates/Dates.css +7 -1
  21. package/src/components/FilterBar/components/FilterPanels/FilterPanels.tsx +10 -12
  22. package/src/components/FilterBar/components/FilterPanels/Guests/Guests.css +2 -1
  23. package/src/components/FilterBar/components/FilterPanels/Locations/Locations.tsx +1 -3
  24. package/src/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.css +5 -1
  25. package/src/components/FilterBar/components/FilterTabs/FilterTabs.tsx +26 -23
  26. package/src/components/FilterBar/components/ImageCard/ImageCard.css +7 -1
  27. package/src/components/FilterBar/hooks/index.ts +1 -1
  28. package/src/components/FilterBar/hooks/{useFilterUi.tsx → useFilterRefs.tsx} +5 -3
  29. package/src/components/FilterBar/hooks/usePanelPosition.tsx +4 -4
  30. package/src/components/FilterBar/hooks/useScrollInToView.tsx +4 -4
  31. package/src/components/FilterBar/providers/FilterBarProvider.tsx +8 -6
  32. package/src/components/FilterCalendar/FilterCalendar.tsx +2 -2
  33. package/src/core/hooks/useCloseFilterSection.tsx +5 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "willba-component-library",
3
- "version": "0.3.19",
3
+ "version": "0.3.21",
4
4
  "description": "A custom UI component library",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.esm.js",
@@ -11,7 +11,7 @@ import '../../themes/Default.css'
11
11
  import './FilterBar.css'
12
12
 
13
13
  export const FilterBar = ({
14
- language = LANGUAGE_FALLBACK,
14
+ language,
15
15
  ageCategories,
16
16
  redirectUrl = REDIRECT_URL_FALLBACK,
17
17
  palette,
@@ -62,4 +62,3 @@ export const FilterBar = ({
62
62
  ////////////
63
63
 
64
64
  const REDIRECT_URL_FALLBACK = 'http://localhost:3000/'
65
- const LANGUAGE_FALLBACK = 'en'
@@ -27,15 +27,13 @@ export const FilterControls = () => {
27
27
  locations,
28
28
  innerLoading,
29
29
  outerLoading,
30
-
31
30
  handleSubmit,
32
31
  handleSelectedFilter,
33
32
 
34
- // Refs
35
33
  previouslyFocusedButtonRef,
36
34
  buttonRefs,
37
- //
38
- targetFilterBarRef,
35
+ tabsRef,
36
+ filtersRef,
39
37
  } = useFilterBar()
40
38
 
41
39
  // Store previously focused button and restore focus when closing
@@ -64,9 +62,15 @@ export const FilterControls = () => {
64
62
  return (
65
63
  <div
66
64
  className={`will-filter-bar-controls ${mode || 'light'}`}
67
- ref={tabs?.length === 1 ? targetFilterBarRef : null}
65
+ ref={(el) => {
66
+ filtersRef.current = el
67
+
68
+ if (tabs?.length === 1) {
69
+ tabsRef.current = el
70
+ }
71
+ }}
68
72
  >
69
- {!!locations?.data?.length && (
73
+ {locations?.data?.length && locations.data.length > 1 && (
70
74
  <>
71
75
  <SelectButton
72
76
  ref={(el) => (buttonRefs.current[FilterSections.LOCATIONS] = el)}
@@ -1,3 +1,9 @@
1
1
  .will-dates-filter-container {
2
- padding: 0 16px 16px 16px;
2
+ padding: 0 30px 16px 30px;
3
+ }
4
+
5
+ @media (max-width: 960px) {
6
+ .will-dates-filter-container {
7
+ padding: 0 20px 16px 20px;
8
+ }
3
9
  }
@@ -29,7 +29,7 @@ export const FilterPanels = () => {
29
29
  isMobile,
30
30
  panelRef,
31
31
  buttonRefs,
32
- targetFilterBarRef,
32
+ filtersRef,
33
33
  setSelectedLocations,
34
34
  setCalendarRange,
35
35
  handleSelectedFilter,
@@ -38,12 +38,12 @@ export const FilterPanels = () => {
38
38
  } = useFilterBar()
39
39
 
40
40
  // Handle close filter section
41
- const { filtersRef } = useCloseFilterSection({ handleSelectedFilter })
41
+ const { filterSectionRef } = useCloseFilterSection({ handleSelectedFilter })
42
42
 
43
43
  const { localStyles } = usePanelPosition({
44
44
  selectedFilter,
45
45
  panelRef,
46
- targetFilterBarRef,
46
+ filtersRef,
47
47
  buttonRefs,
48
48
  isMobile,
49
49
  })
@@ -54,7 +54,7 @@ export const FilterPanels = () => {
54
54
  return (
55
55
  <Dates
56
56
  autoFocus
57
- ref={filtersRef}
57
+ ref={filterSectionRef}
58
58
  onClose={() => handleSelectedFilter(false)}
59
59
  calendarRange={calendarRange}
60
60
  setCalendarRange={setCalendarRange}
@@ -67,7 +67,7 @@ export const FilterPanels = () => {
67
67
  return (
68
68
  <Guests
69
69
  autoFocus
70
- ref={filtersRef}
70
+ ref={filterSectionRef}
71
71
  ageCategories={ageCategories}
72
72
  ageCategoryCounts={ageCategoryCounts}
73
73
  updateGuestsCount={updateGuestsCount}
@@ -82,9 +82,8 @@ export const FilterPanels = () => {
82
82
  return (
83
83
  <Locations
84
84
  autoFocus
85
- ref={filtersRef}
85
+ ref={filterSectionRef}
86
86
  locations={locations?.data}
87
- language={language}
88
87
  selectedLocations={selectedLocations}
89
88
  setSelectedLocations={setSelectedLocations}
90
89
  multiSelect={locations?.multiSelect}
@@ -102,11 +101,10 @@ export const FilterPanels = () => {
102
101
  <div
103
102
  ref={panelRef}
104
103
  className={`will-filter-bar-panels ${mode || 'light'}`}
105
- style={
106
- (!tabs || tabs.length < 2) && !isMobile
107
- ? { top: 66 }
108
- : { ...localStyles }
109
- }
104
+ style={{
105
+ ...localStyles,
106
+ ...((!tabs || tabs.length < 2) && !isMobile ? { top: 66 } : {}),
107
+ }}
110
108
  >
111
109
  {renderContent()}
112
110
  </div>
@@ -7,12 +7,13 @@
7
7
  flex-direction: column;
8
8
  min-width: 400px;
9
9
  gap: 20px;
10
- padding: 0 16px 16px 16px;
10
+ padding: 0 30px 16px 30px;
11
11
  }
12
12
 
13
13
  @media (max-width: 960px) {
14
14
  .will-guests-filter-container {
15
15
  min-width: auto;
16
+ padding: 0 20px 16px 20px;
16
17
  }
17
18
  }
18
19
 
@@ -10,7 +10,6 @@ import './Locations.css'
10
10
 
11
11
  type Props = {
12
12
  locations?: Location[]
13
- language?: string
14
13
  selectedLocations: Location[]
15
14
  setSelectedLocations: (locations: Location[]) => void
16
15
  autoFocus?: boolean
@@ -22,7 +21,6 @@ export const Locations = forwardRef<HTMLDivElement, Props>(
22
21
  (
23
22
  {
24
23
  locations,
25
- language,
26
24
  selectedLocations,
27
25
  setSelectedLocations,
28
26
  autoFocus,
@@ -71,7 +69,7 @@ export const Locations = forwardRef<HTMLDivElement, Props>(
71
69
  />
72
70
 
73
71
  <div className="will-locations-filter-container">
74
- {!!(locations?.length && language) &&
72
+ {!!locations?.length &&
75
73
  locations.map((location, index) => {
76
74
  return (
77
75
  <ImageCard
@@ -2,7 +2,7 @@
2
2
  display: flex;
3
3
  justify-content: space-between;
4
4
  align-items: center;
5
- padding: 16px;
5
+ padding: 16px 30px;
6
6
  }
7
7
 
8
8
  .will-filter-section-title {
@@ -24,6 +24,10 @@
24
24
  }
25
25
 
26
26
  @media (max-width: 960px) {
27
+ .will-filter-section-header {
28
+ padding: 16px 20px;
29
+ }
30
+
27
31
  .will-filter-section-title {
28
32
  font-size: 18px;
29
33
  }
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { useMemo } from 'react'
2
2
 
3
3
  import { useTranslation } from 'react-i18next'
4
4
 
@@ -15,33 +15,36 @@ export const FilterTabs = () => {
15
15
  selectedPath,
16
16
  mode,
17
17
  tabs,
18
+ tabsRef,
18
19
  handleSelectedFilter,
19
20
  setSelectedPath,
20
21
  handleResetFilters,
21
- //
22
- targetFilterBarRef,
23
22
  } = useFilterBar()
24
23
 
24
+ const sortedTabs = useMemo(
25
+ () => [...(tabs ?? [])].sort((a, b) => a.order - b.order),
26
+ [tabs]
27
+ )
28
+
29
+ const handleTabClick = (path: string) => {
30
+ setSelectedPath(path)
31
+ handleResetFilters()
32
+ handleSelectedFilter(false)
33
+ }
34
+
35
+ if (sortedTabs.length <= 1) return null
36
+
25
37
  return (
26
- tabs &&
27
- tabs.length > 1 && (
28
- <div className="will-filter-bar-tabs" ref={targetFilterBarRef}>
29
- {tabs
30
- .sort((a, b) => a.order - b.order)
31
- .map((tab, idx) => (
32
- <TabButton
33
- key={`tab-${idx}`}
34
- label={tab.label || t(`tabs.${tab.path.substring(1)}`)}
35
- onClick={() => {
36
- setSelectedPath(tab.path)
37
- handleResetFilters()
38
- handleSelectedFilter(false)
39
- }}
40
- active={selectedPath === tab.path}
41
- mode={mode}
42
- />
43
- ))}
44
- </div>
45
- )
38
+ <div className="will-filter-bar-tabs" ref={tabsRef}>
39
+ {sortedTabs.map((tab) => (
40
+ <TabButton
41
+ key={tab.path}
42
+ label={tab.label || t(`tabs.${tab.path.slice(1)}`)}
43
+ onClick={() => handleTabClick(tab.path)}
44
+ active={selectedPath === tab.path}
45
+ mode={mode}
46
+ />
47
+ ))}
48
+ </div>
46
49
  )
47
50
  }
@@ -3,7 +3,7 @@
3
3
  gap: 20px;
4
4
  justify-content: space-between;
5
5
  align-items: center;
6
- padding: 8px 16px;
6
+ padding: 8px 30px;
7
7
  cursor: pointer;
8
8
  user-select: none;
9
9
  min-height: 40px;
@@ -22,3 +22,9 @@
22
22
  height: 68px;
23
23
  object-fit: cover;
24
24
  }
25
+
26
+ @media (max-width: 960px) {
27
+ .will-image-card {
28
+ padding: 8px 20px;
29
+ }
30
+ }
@@ -1,5 +1,5 @@
1
1
  export { useScrollInToView } from './useScrollInToView'
2
2
  export { useFilterState } from './useFilterState'
3
3
  export { useFilterActions } from './useFilterActions'
4
- export { useFilterUi } from './useFilterUi'
4
+ export { useFilterRefs } from './useFilterRefs'
5
5
  export { usePanelPosition } from './usePanelPosition'
@@ -2,18 +2,20 @@ import { useRef } from 'react'
2
2
 
3
3
  import { useScrollInToView } from './useScrollInToView'
4
4
 
5
- export const useFilterUi = (selectedFilter: string | boolean) => {
5
+ export const useFilterRefs = (selectedFilter: string | boolean) => {
6
6
  const buttonRefs = useRef<Record<string, HTMLButtonElement | null>>({})
7
7
  const panelRef = useRef<HTMLDivElement | null>(null)
8
8
  const previouslyFocusedButtonRef = useRef<HTMLButtonElement | null>(null)
9
+ const filtersRef = useRef<HTMLDivElement | null>(null)
9
10
 
10
- const { isMobile, targetFilterBarRef } = useScrollInToView({ selectedFilter })
11
+ const { isMobile, tabsRef } = useScrollInToView({ selectedFilter })
11
12
 
12
13
  return {
13
14
  previouslyFocusedButtonRef,
14
15
  isMobile,
15
- targetFilterBarRef,
16
+ tabsRef,
16
17
  panelRef,
17
18
  buttonRefs,
19
+ filtersRef,
18
20
  }
19
21
  }
@@ -9,7 +9,7 @@ import {
9
9
  type Props = {
10
10
  selectedFilter: string | boolean
11
11
  panelRef: RefObject<HTMLDivElement | null>
12
- targetFilterBarRef: RefObject<HTMLDivElement | null>
12
+ filtersRef: RefObject<HTMLDivElement | null>
13
13
  buttonRefs: MutableRefObject<Record<string, HTMLButtonElement | null>>
14
14
  isMobile: boolean
15
15
  }
@@ -17,7 +17,7 @@ type Props = {
17
17
  export const usePanelPosition = ({
18
18
  selectedFilter,
19
19
  panelRef,
20
- targetFilterBarRef,
20
+ filtersRef,
21
21
  buttonRefs,
22
22
  isMobile,
23
23
  }: Props) => {
@@ -30,7 +30,7 @@ export const usePanelPosition = ({
30
30
  }
31
31
 
32
32
  const panel = panelRef.current
33
- const container = targetFilterBarRef.current
33
+ const container = filtersRef.current
34
34
  const button = buttonRefs.current[selectedFilter]
35
35
 
36
36
  if (!panel || !container || !button) return
@@ -39,7 +39,7 @@ export const usePanelPosition = ({
39
39
  const containerRect = container.getBoundingClientRect()
40
40
  const buttonRect = button.getBoundingClientRect()
41
41
 
42
- const buttonLeft = buttonRect.left - containerRect.left
42
+ const buttonLeft = buttonRect.left - containerRect.left - 30 // Offset by 30px to account for controls section spacing
43
43
 
44
44
  const left = Math.max(
45
45
  0,
@@ -6,7 +6,7 @@ type Props = {
6
6
 
7
7
  export const useScrollInToView = ({ selectedFilter }: Props) => {
8
8
  const [isMobile, setIsMobile] = useState(true)
9
- const targetFilterBarRef = useRef<HTMLDivElement | null>(null)
9
+ const tabsRef = useRef<HTMLDivElement | null>(null)
10
10
 
11
11
  useEffect(() => {
12
12
  if (typeof window !== 'undefined' && window.innerWidth > 960) {
@@ -14,16 +14,16 @@ export const useScrollInToView = ({ selectedFilter }: Props) => {
14
14
  return
15
15
  }
16
16
 
17
- if (targetFilterBarRef.current && selectedFilter) {
17
+ if (tabsRef.current && selectedFilter) {
18
18
  window.scrollTo({
19
19
  behavior: 'smooth',
20
20
  top:
21
- targetFilterBarRef.current.getBoundingClientRect().top -
21
+ tabsRef.current.getBoundingClientRect().top -
22
22
  document.body.getBoundingClientRect().top -
23
23
  30,
24
24
  })
25
25
  }
26
26
  }, [selectedFilter])
27
27
 
28
- return { isMobile, targetFilterBarRef }
28
+ return { isMobile, tabsRef }
29
29
  }
@@ -9,7 +9,7 @@ import React, {
9
9
  import { DateRange } from 'react-day-picker'
10
10
 
11
11
  import { AgeCategoryCount, Location, FilterBarTypes } from '../FilterBarTypes'
12
- import { useFilterActions, useFilterState, useFilterUi } from '../hooks'
12
+ import { useFilterActions, useFilterState, useFilterRefs } from '../hooks'
13
13
 
14
14
  type FilterBarProviderProps = PropsWithChildren<FilterBarTypes>
15
15
 
@@ -38,10 +38,11 @@ type FilterBarContextType = FilterBarTypes & {
38
38
  previouslyFocusedButtonRef: MutableRefObject<HTMLButtonElement | null>
39
39
  panelRef: MutableRefObject<HTMLDivElement | null>
40
40
  buttonRefs: MutableRefObject<Record<string, HTMLButtonElement | null>>
41
+ filtersRef: MutableRefObject<HTMLDivElement | null>
41
42
 
42
43
  // Mobile
43
44
  isMobile: boolean
44
- targetFilterBarRef: RefObject<HTMLDivElement>
45
+ tabsRef: MutableRefObject<HTMLDivElement | null>
45
46
  }
46
47
 
47
48
  const FilterBarContext = createContext<FilterBarContextType | undefined>(
@@ -95,7 +96,7 @@ export const FilterBarProvider = ({
95
96
  setInnerLoading,
96
97
  })
97
98
 
98
- const filterUi = useFilterUi(selectedFilter)
99
+ const filterRefs = useFilterRefs(selectedFilter)
99
100
 
100
101
  const contextValue = useMemo(
101
102
  () => ({
@@ -128,7 +129,7 @@ export const FilterBarProvider = ({
128
129
  outerLoading,
129
130
  locations,
130
131
 
131
- ...filterUi,
132
+ ...filterRefs,
132
133
  }),
133
134
  [
134
135
  selectedFilter,
@@ -149,8 +150,9 @@ export const FilterBarProvider = ({
149
150
  tabs,
150
151
  outerLoading,
151
152
  locations,
152
- filterUi.isMobile,
153
- filterUi.targetFilterBarRef,
153
+ filterRefs.isMobile,
154
+ filterRefs.tabsRef,
155
+ filterRefs.filtersRef,
154
156
  ]
155
157
  )
156
158
 
@@ -62,14 +62,14 @@ export default function FilterCalendar({
62
62
  useAwaitRender()
63
63
 
64
64
  // Handle close filter section
65
- const { filtersRef } = useCloseFilterSection({
65
+ const { filterSectionRef } = useCloseFilterSection({
66
66
  handleSelectedFilter: setToggleCalendar,
67
67
  })
68
68
 
69
69
  return (
70
70
  <div className={`will-root`} style={themePalette}>
71
71
  {toggleCalendar && (
72
- <div className={`will-calendar-wrapper`} ref={filtersRef}>
72
+ <div className={`will-calendar-wrapper`} ref={filterSectionRef}>
73
73
  <div className={`will-calendar-header`}>
74
74
  <h2>{t('filterBar:calendar.title')}</h2>
75
75
  <CloseButton handleClose={() => setToggleCalendar(false)} />
@@ -6,13 +6,13 @@ type Props = {
6
6
 
7
7
  // TODO - Refactor and rename this hook
8
8
  export const useCloseFilterSection = ({ handleSelectedFilter }: Props) => {
9
- const filtersRef = useRef<HTMLDivElement | null>(null)
9
+ const filterSectionRef = useRef<HTMLDivElement | null>(null)
10
10
 
11
11
  useEffect(() => {
12
12
  const handleClickOutside = (event: MouseEvent) => {
13
13
  if (
14
- filtersRef.current &&
15
- !filtersRef.current.contains(event.target as Node)
14
+ filterSectionRef.current &&
15
+ !filterSectionRef.current.contains(event.target as Node)
16
16
  ) {
17
17
  handleSelectedFilter(false)
18
18
  }
@@ -23,7 +23,7 @@ export const useCloseFilterSection = ({ handleSelectedFilter }: Props) => {
23
23
  return () => {
24
24
  document.removeEventListener('mousedown', handleClickOutside)
25
25
  }
26
- }, [filtersRef])
26
+ }, [filterSectionRef])
27
27
 
28
- return { filtersRef }
28
+ return { filterSectionRef }
29
29
  }