related-ui-components 1.3.0 → 1.3.2

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 (68) hide show
  1. package/lib/commonjs/app.js +19 -27
  2. package/lib/commonjs/app.js.map +1 -1
  3. package/lib/commonjs/components/Banner/README.md +3 -3
  4. package/lib/commonjs/components/Card/templates/README.md +3 -3
  5. package/lib/commonjs/components/Filters/Filters.js +13 -26
  6. package/lib/commonjs/components/Filters/Filters.js.map +1 -1
  7. package/lib/commonjs/components/Filters/README.md +1 -1
  8. package/lib/commonjs/components/ScratchCard/README.md +2 -2
  9. package/lib/commonjs/constants/BRANDS.js +2 -1
  10. package/lib/commonjs/constants/BRANDS.js.map +1 -1
  11. package/lib/module/app.js +21 -30
  12. package/lib/module/app.js.map +1 -1
  13. package/lib/module/components/Banner/README.md +3 -3
  14. package/lib/module/components/Card/templates/README.md +3 -3
  15. package/lib/module/components/Filters/Filters.js +13 -26
  16. package/lib/module/components/Filters/Filters.js.map +1 -1
  17. package/lib/module/components/Filters/README.md +1 -1
  18. package/lib/module/components/ScratchCard/README.md +2 -2
  19. package/lib/module/constants/BRANDS.js +2 -1
  20. package/lib/module/constants/BRANDS.js.map +1 -1
  21. package/lib/typescript/commonjs/app.d.ts.map +1 -1
  22. package/lib/typescript/commonjs/components/Banner/Banner.d.ts +2 -2
  23. package/lib/typescript/commonjs/components/Banner/Banner.d.ts.map +1 -1
  24. package/lib/typescript/commonjs/components/Banner/BannerWithDetails.d.ts +3 -3
  25. package/lib/typescript/commonjs/components/Banner/BannerWithDetails.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/components/Card/templates/DealCard.d.ts +2 -2
  27. package/lib/typescript/commonjs/components/Card/templates/DealCard.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/components/Card/templates/DealCardWithBackgroundImage.d.ts +2 -2
  29. package/lib/typescript/commonjs/components/Card/templates/DealCardWithBackgroundImage.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/components/Card/templates/SimpleTrendingCard.d.ts +2 -2
  31. package/lib/typescript/commonjs/components/Card/templates/SimpleTrendingCard.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/components/Card/types.d.ts +2 -2
  33. package/lib/typescript/commonjs/components/Card/types.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/components/Filters/Filters.d.ts +5 -3
  35. package/lib/typescript/commonjs/components/Filters/Filters.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/constants/BRANDS.d.ts +8 -2
  37. package/lib/typescript/commonjs/constants/BRANDS.d.ts.map +1 -1
  38. package/lib/typescript/module/app.d.ts.map +1 -1
  39. package/lib/typescript/module/components/Banner/Banner.d.ts +2 -2
  40. package/lib/typescript/module/components/Banner/Banner.d.ts.map +1 -1
  41. package/lib/typescript/module/components/Banner/BannerWithDetails.d.ts +3 -3
  42. package/lib/typescript/module/components/Banner/BannerWithDetails.d.ts.map +1 -1
  43. package/lib/typescript/module/components/Card/templates/DealCard.d.ts +2 -2
  44. package/lib/typescript/module/components/Card/templates/DealCard.d.ts.map +1 -1
  45. package/lib/typescript/module/components/Card/templates/DealCardWithBackgroundImage.d.ts +2 -2
  46. package/lib/typescript/module/components/Card/templates/DealCardWithBackgroundImage.d.ts.map +1 -1
  47. package/lib/typescript/module/components/Card/templates/SimpleTrendingCard.d.ts +2 -2
  48. package/lib/typescript/module/components/Card/templates/SimpleTrendingCard.d.ts.map +1 -1
  49. package/lib/typescript/module/components/Card/types.d.ts +2 -2
  50. package/lib/typescript/module/components/Card/types.d.ts.map +1 -1
  51. package/lib/typescript/module/components/Filters/Filters.d.ts +5 -3
  52. package/lib/typescript/module/components/Filters/Filters.d.ts.map +1 -1
  53. package/lib/typescript/module/constants/BRANDS.d.ts +8 -2
  54. package/lib/typescript/module/constants/BRANDS.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/src/app.tsx +10 -18
  57. package/src/components/Banner/Banner.tsx +2 -2
  58. package/src/components/Banner/BannerWithDetails.tsx +3 -3
  59. package/src/components/Banner/README.md +3 -3
  60. package/src/components/Card/templates/DealCard.tsx +2 -2
  61. package/src/components/Card/templates/DealCardWithBackgroundImage.tsx +2 -2
  62. package/src/components/Card/templates/README.md +3 -3
  63. package/src/components/Card/templates/SimpleTrendingCard.tsx +2 -2
  64. package/src/components/Card/types.ts +2 -2
  65. package/src/components/Filters/Filters.tsx +454 -463
  66. package/src/components/Filters/README.md +1 -1
  67. package/src/components/ScratchCard/README.md +2 -2
  68. package/src/constants/BRANDS.ts +1 -0
@@ -1,488 +1,479 @@
1
- import React, { useCallback, useEffect, useRef, useState } from "react";
2
- import {
3
- View,
4
- Text,
5
- StyleSheet,
6
- TouchableOpacity,
7
- TextStyle,
8
- ViewStyle,
9
- ImageRequireSource,
10
- I18nManager,
11
- TouchableWithoutFeedback,
12
- } from "react-native";
13
- import { GestureHandlerRootView } from "react-native-gesture-handler";
14
- import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
15
- import PointsRangeSelector from "./PointsRangeSelector";
16
- import { BrandIcon } from "../BrandIcon";
17
- import { Ionicons } from "@expo/vector-icons";
18
- import Checkbox from "expo-checkbox";
19
- import { useTheme, ThemeType } from "../../theme"; // Import ThemeType
1
+ import React, { useCallback, useEffect, useRef, useState } from "react";
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ TextStyle,
8
+ ViewStyle,
9
+ ImageSourcePropType,
10
+ I18nManager,
11
+ TouchableWithoutFeedback,
12
+ } from "react-native";
13
+ import { GestureHandlerRootView } from "react-native-gesture-handler";
14
+ import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
15
+ import PointsRangeSelector from "./PointsRangeSelector";
16
+ import { BrandIcon } from "../BrandIcon";
17
+ import { Ionicons } from "@expo/vector-icons";
18
+ import Checkbox from "expo-checkbox";
19
+ import { useTheme, ThemeType } from "../../theme"; // Import ThemeType
20
20
 
21
- type SortOption = {
22
- name: string;
23
- value: string;
24
- id: number;
25
- };
26
- type Brand = {
27
- id: string;
28
- name: string;
29
- logo: ImageRequireSource;
30
- };
31
- export type FilterResult = {
32
- sort: SortOption[];
33
- pointsRange: { min: number; max: number };
34
- selectedBrands: Brand[];
35
- };
36
- interface FiltersProps {
37
- isRTL?: boolean;
38
- sortOptions?: SortOption[];
39
- sortSectionTitle?: string;
40
- sectionTitleStyle?: TextStyle;
41
- sortSectionStyle?: ViewStyle;
42
- rangeMinLimit?: number;
43
- rangeMaxLimit?: number;
44
- rangeInitialMin?: number;
45
- rangeInitialMax?: number;
46
- showPointsRange?: boolean;
47
- pointsRangeSectionTitle?: string;
48
- pointsRangeContainerStyle?: ViewStyle;
49
- pointsRangeInputsContainerStyle?: ViewStyle;
50
- pointsRangeCustomInputContainerStyle?: ViewStyle;
51
- pointsRangeCustomInputFieldStyle?: ViewStyle;
52
- pointsRangeSliderContainerStyle?: ViewStyle;
53
- pointsRangeMultiSliderContainerStyle?: ViewStyle;
54
- pointsRangeTrackStyle?: ViewStyle;
55
- pointsRangeSelectedTrackStyle?: ViewStyle;
56
- pointsRangeUnselectedTrackStyle?: ViewStyle;
57
- pointsRangeMarkerStyle?: ViewStyle;
58
- pointsRangeMarkerEnabledStyle?: ViewStyle;
59
- pointsRangeMarkerDisabledStyle?: ViewStyle;
60
- pointsRangeMarkerDotStyle?: ViewStyle;
61
- pointsRangeInputProps?: any;
62
- pointsRangeMultiSliderProps?: any;
63
- brands?: Brand[];
64
- brandContainerStyle?: ViewStyle;
65
- brandActiveIcon?: React.ReactNode;
66
- brandActiveIconStyle?: ViewStyle;
67
- brandSectionTile?: string;
68
- onActionButtonPress?: (result: FilterResult) => void;
69
- containerStyle?: ViewStyle;
70
- headerStyle?: ViewStyle;
71
- titleStyle?: TextStyle;
72
- resetTextStyle?: TextStyle;
73
- sectionStyle?: ViewStyle;
74
- optionRowStyle?: ViewStyle;
75
- optionTextStyle?: TextStyle;
76
- checkboxColor?: string;
77
- applyButtonStyle?: ViewStyle;
78
- applyButtonTextStyle?: TextStyle;
79
- bottomSheetStyle?: ViewStyle;
80
- headerTitleText?: string;
81
- headerResetText?: string;
82
- bottomSheetIndex?: number;
83
- snapPoints?: string[];
84
- handleIndicatorStyle?: ViewStyle;
85
- applyButtonText?: string;
86
- overlayColor?: string;
87
- onClose?: () => void;
88
- visible?: boolean;
89
- }
21
+ type SortOption = {
22
+ name: string;
23
+ value: string;
24
+ id: number;
25
+ checked?: boolean;
26
+ };
27
+ type Brand = {
28
+ id: string;
29
+ name: string;
30
+ logo: ImageSourcePropType;
31
+ checked?: boolean;
32
+ };
33
+ export type FilterResult = {
34
+ sort: SortOption | undefined;
35
+ pointsRange: { min: number; max: number };
36
+ selectedBrands: Brand[];
37
+ };
38
+ interface FiltersProps {
39
+ isRTL?: boolean;
40
+ sortOptions?: SortOption[];
41
+ sortSectionTitle?: string;
42
+ sectionTitleStyle?: TextStyle;
43
+ sortSectionStyle?: ViewStyle;
44
+ rangeMinLimit?: number;
45
+ rangeMaxLimit?: number;
46
+ rangeInitialMin?: number;
47
+ rangeInitialMax?: number;
48
+ showPointsRange?: boolean;
49
+ pointsRangeSectionTitle?: string;
50
+ pointsRangeContainerStyle?: ViewStyle;
51
+ pointsRangeInputsContainerStyle?: ViewStyle;
52
+ pointsRangeCustomInputContainerStyle?: ViewStyle;
53
+ pointsRangeCustomInputFieldStyle?: ViewStyle;
54
+ pointsRangeSliderContainerStyle?: ViewStyle;
55
+ pointsRangeMultiSliderContainerStyle?: ViewStyle;
56
+ pointsRangeTrackStyle?: ViewStyle;
57
+ pointsRangeSelectedTrackStyle?: ViewStyle;
58
+ pointsRangeUnselectedTrackStyle?: ViewStyle;
59
+ pointsRangeMarkerStyle?: ViewStyle;
60
+ pointsRangeMarkerEnabledStyle?: ViewStyle;
61
+ pointsRangeMarkerDisabledStyle?: ViewStyle;
62
+ pointsRangeMarkerDotStyle?: ViewStyle;
63
+ pointsRangeInputProps?: any;
64
+ pointsRangeMultiSliderProps?: any;
65
+ brands?: Brand[];
66
+ brandContainerStyle?: ViewStyle;
67
+ brandActiveIcon?: React.ReactNode;
68
+ brandActiveIconStyle?: ViewStyle;
69
+ brandSectionTile?: string;
70
+ onActionButtonPress?: (result: FilterResult) => void;
71
+ containerStyle?: ViewStyle;
72
+ headerStyle?: ViewStyle;
73
+ titleStyle?: TextStyle;
74
+ resetTextStyle?: TextStyle;
75
+ sectionStyle?: ViewStyle;
76
+ optionRowStyle?: ViewStyle;
77
+ optionTextStyle?: TextStyle;
78
+ checkboxColor?: string;
79
+ applyButtonStyle?: ViewStyle;
80
+ applyButtonTextStyle?: TextStyle;
81
+ bottomSheetStyle?: ViewStyle;
82
+ headerTitleText?: string;
83
+ headerResetText?: string;
84
+ bottomSheetIndex?: number;
85
+ snapPoints?: string[];
86
+ handleIndicatorStyle?: ViewStyle;
87
+ applyButtonText?: string;
88
+ overlayColor?: string;
89
+ onClose?: () => void;
90
+ visible?: boolean;
91
+ }
90
92
 
91
- const Filters: React.FC<FiltersProps> = ({
92
- isRTL = I18nManager.isRTL,
93
- sortOptions = [],
94
- sortSectionTitle = "Sort",
95
- sectionTitleStyle,
96
- sortSectionStyle,
97
- onActionButtonPress,
98
- rangeInitialMax = 1000,
99
- rangeInitialMin = 0,
100
- rangeMaxLimit = 1000,
101
- rangeMinLimit = 0,
102
- pointsRangeContainerStyle,
103
- pointsRangeInputsContainerStyle,
104
- pointsRangeCustomInputContainerStyle,
105
- pointsRangeCustomInputFieldStyle,
106
- pointsRangeSliderContainerStyle,
107
- pointsRangeMultiSliderContainerStyle,
108
- pointsRangeTrackStyle,
109
- pointsRangeSelectedTrackStyle,
110
- pointsRangeUnselectedTrackStyle,
111
- pointsRangeMarkerStyle,
112
- pointsRangeMarkerEnabledStyle,
113
- pointsRangeMarkerDisabledStyle,
114
- pointsRangeMarkerDotStyle,
115
- pointsRangeInputProps,
116
- pointsRangeMultiSliderProps,
117
- containerStyle,
118
- headerStyle,
119
- titleStyle,
120
- resetTextStyle,
121
- sectionStyle,
122
- optionRowStyle,
123
- optionTextStyle,
124
- checkboxColor: checkboxColorProp,
125
- applyButtonStyle,
126
- applyButtonTextStyle,
127
- bottomSheetStyle,
128
- bottomSheetIndex = 0,
129
- snapPoints = ["50%", "90%"],
130
- handleIndicatorStyle,
131
- brands = [],
132
- brandContainerStyle,
133
- brandActiveIcon,
134
- showPointsRange = true,
135
- pointsRangeSectionTitle = "Points range",
136
- brandActiveIconStyle,
137
- brandSectionTile = "Brands",
138
- applyButtonText = "Apply Filter",
139
- headerResetText = "Reset All",
140
- headerTitleText = "Filter",
141
- overlayColor = "rgba(0, 0, 0, 0.5)",
142
- onClose,
143
- visible = true,
144
- }) => {
145
- const {theme, isRTL : rtl} = useTheme();
146
- isRTL = rtl || isRTL;
147
- const bottomSheetRef = useRef<BottomSheet>(null);
148
- const styles = createStyles(theme, isRTL);
149
- const checkboxColor = checkboxColorProp ?? theme.primary;
150
- const [isVisible, setIsVisible] = useState(visible);
93
+ const Filters: React.FC<FiltersProps> = ({
94
+ isRTL = I18nManager.isRTL,
95
+ sortOptions = [],
96
+ sortSectionTitle = "Sort",
97
+ sectionTitleStyle,
98
+ sortSectionStyle,
99
+ onActionButtonPress,
100
+ rangeInitialMax = 1000,
101
+ rangeInitialMin = 0,
102
+ rangeMaxLimit = 1000,
103
+ rangeMinLimit = 0,
104
+ pointsRangeContainerStyle,
105
+ pointsRangeInputsContainerStyle,
106
+ pointsRangeCustomInputContainerStyle,
107
+ pointsRangeCustomInputFieldStyle,
108
+ pointsRangeSliderContainerStyle,
109
+ pointsRangeMultiSliderContainerStyle,
110
+ pointsRangeTrackStyle,
111
+ pointsRangeSelectedTrackStyle,
112
+ pointsRangeUnselectedTrackStyle,
113
+ pointsRangeMarkerStyle,
114
+ pointsRangeMarkerEnabledStyle,
115
+ pointsRangeMarkerDisabledStyle,
116
+ pointsRangeMarkerDotStyle,
117
+ pointsRangeInputProps,
118
+ pointsRangeMultiSliderProps,
119
+ containerStyle,
120
+ headerStyle,
121
+ titleStyle,
122
+ resetTextStyle,
123
+ sectionStyle,
124
+ optionRowStyle,
125
+ optionTextStyle,
126
+ checkboxColor: checkboxColorProp,
127
+ applyButtonStyle,
128
+ applyButtonTextStyle,
129
+ bottomSheetStyle,
130
+ bottomSheetIndex = 0,
131
+ snapPoints = ["50%", "90%"],
132
+ handleIndicatorStyle,
133
+ brands = [],
134
+ brandContainerStyle,
135
+ brandActiveIcon,
136
+ showPointsRange = true,
137
+ pointsRangeSectionTitle = "Points range",
138
+ brandActiveIconStyle,
139
+ brandSectionTile = "Brands",
140
+ applyButtonText = "Apply Filter",
141
+ headerResetText = "Reset All",
142
+ headerTitleText = "Filter",
143
+ overlayColor = "rgba(0, 0, 0, 0.5)",
144
+ onClose,
145
+ visible = true,
146
+ }) => {
147
+ const {theme, isRTL : rtl} = useTheme();
148
+ isRTL = rtl || isRTL;
149
+ const bottomSheetRef = useRef<BottomSheet>(null);
150
+ const styles = createStyles(theme, isRTL);
151
+ const checkboxColor = checkboxColorProp ?? theme.primary;
152
+ const [isVisible, setIsVisible] = useState(visible);
151
153
 
152
- // Sync the internal isVisible state with the visible prop
153
- useEffect(() => {
154
- setIsVisible(visible);
155
- if (visible && bottomSheetRef.current) {
156
- bottomSheetRef.current.snapToIndex(0);
157
- }
158
- }, [visible]);
154
+ // Sync the internal isVisible state with the visible prop
155
+ useEffect(() => {
156
+ setIsVisible(visible);
157
+ if (visible && bottomSheetRef.current) {
158
+ bottomSheetRef.current.snapToIndex(0);
159
+ }
160
+ }, [visible]);
159
161
 
160
- const handleSheetChanges = useCallback((index: number) => {
161
- console.log("handleSheetChanges", index);
162
- // If the sheet is closed (index -1), handle visibility
163
- if (index === -1) {
164
- setIsVisible(false);
165
- }
166
- }, []);
162
+ const handleSheetChanges = useCallback((index: number) => {
163
+ if (index === -1) {
164
+ setIsVisible(false);
165
+ }
166
+ }, []);
167
167
 
168
- const [resetCounter, setResetCounter] = useState(0);
168
+ const [resetCounter, setResetCounter] = useState(0);
169
169
 
170
- const [checkedItems, setCheckedItems] = useState<Record<string, boolean>>(
171
- sortOptions.reduce((acc, option) => {
172
- acc[option.id] = false;
173
- return acc;
174
- }, {} as Record<string, boolean>)
175
- );
176
- const [selectedBrands, setSelectedBrands] = useState<Record<string, boolean>>(
177
- brands.reduce((acc, option) => {
178
- acc[option.id] = false;
179
- return acc;
180
- }, {} as Record<string, boolean>)
181
- );
182
- const [pointsRange, setPointsRange] = useState<{ min: number; max: number }>({
183
- min: rangeInitialMin,
184
- max: rangeInitialMax,
185
- });
186
170
 
187
- const handleCheckboxChange = (id: string) => {
188
- setCheckedItems((prevState) => ({
189
- ...prevState,
190
- [id]: !prevState[id],
191
- }));
192
- };
171
+ const [checkedItem, setCheckedItem] = useState<number | null>(
172
+ sortOptions.find(option => option.checked)?.id || null
173
+ );
193
174
 
194
- const handleBrandSelect = (id: string) => {
195
- setSelectedBrands((prevState) => ({
196
- ...prevState,
197
- [id]: !prevState[id],
198
- }));
199
- };
175
+ const [selectedBrands, setSelectedBrands] = useState<Record<string, boolean>>(
176
+ brands.reduce((acc, option) => {
177
+ acc[option.id] = option.checked || false;
178
+ return acc;
179
+ }, {} as Record<string, boolean>)
180
+ );
181
+ const [pointsRange, setPointsRange] = useState<{ min: number; max: number }>({
182
+ min: rangeInitialMin,
183
+ max: rangeInitialMax,
184
+ });
200
185
 
201
- const handleApplyFilter = () => {
202
- if (onActionButtonPress) {
203
- const selectedSortOptions = sortOptions.filter(
204
- (option) => checkedItems[option.id]
205
- );
186
+ const handleCheckboxChange = (id: number) => {
187
+ setCheckedItem(id);
188
+ };
206
189
 
207
- const selectedBrandsList = brands.filter(
208
- (brand) => selectedBrands[brand.id]
209
- );
190
+ const handleBrandSelect = (id: string) => {
191
+ setSelectedBrands((prevState) => ({
192
+ ...prevState,
193
+ [id]: !prevState[id],
194
+ }));
195
+ };
210
196
 
211
- const filterResult: FilterResult = {
212
- sort: selectedSortOptions,
213
- pointsRange: pointsRange,
214
- selectedBrands: selectedBrandsList,
215
- };
197
+ const handleApplyFilter = () => {
198
+ if (onActionButtonPress) {
199
+ const selectedSortOption = sortOptions.find(
200
+ (option) => option.id == checkedItem
201
+ );
216
202
 
217
- onActionButtonPress(filterResult);
218
- closeBottomSheet(); // Close the filter after applying
219
- }
220
- };
203
+ const selectedBrandsList = brands.filter(
204
+ (brand) => selectedBrands[brand.id]
205
+ );
221
206
 
222
- const handleResetAll = () => {
223
- const resetState = sortOptions.reduce((acc, option) => {
224
- acc[option.id] = false;
225
- return acc;
226
- }, {} as Record<string, boolean>);
207
+ const filterResult: FilterResult = {
208
+ sort: selectedSortOption,
209
+ pointsRange: pointsRange,
210
+ selectedBrands: selectedBrandsList,
211
+ };
227
212
 
228
- const resetBrands = brands.reduce((acc, option) => {
229
- acc[option.id] = false;
230
- return acc;
231
- }, {} as Record<string, boolean>);
213
+ onActionButtonPress(filterResult);
214
+ closeBottomSheet(); // Close the filter after applying
215
+ }
216
+ };
232
217
 
233
- setCheckedItems(resetState);
234
- setSelectedBrands(resetBrands);
235
- setPointsRange({ min: rangeInitialMin, max: rangeInitialMax });
236
- setResetCounter((prev) => prev + 1);
237
- };
238
-
239
- const closeBottomSheet = useCallback(() => {
240
- if (bottomSheetRef.current) {
241
- bottomSheetRef.current.close();
242
- }
243
- setIsVisible(false);
244
- if (onClose) {
245
- onClose();
246
- }
247
- }, [onClose]);
218
+ const handleResetAll = () => {
219
+ const resetBrands = brands.reduce((acc, option) => {
220
+ acc[option.id] = false;
221
+ return acc;
222
+ }, {} as Record<string, boolean>);
248
223
 
249
- // If not visible, don't render anything
250
- if (!isVisible) {
251
- return null;
252
- }
224
+ setCheckedItem(null);
225
+ setSelectedBrands(resetBrands);
226
+ setPointsRange({ min: rangeInitialMin, max: rangeInitialMax });
227
+ setResetCounter((prev) => prev + 1);
228
+ };
253
229
 
254
- return (
255
- <GestureHandlerRootView style={styles.overlayContainer}>
256
- {/* Semi-transparent overlay */}
257
- <TouchableWithoutFeedback onPress={closeBottomSheet}>
258
- <View style={[styles.overlay, { backgroundColor: overlayColor }]} />
259
- </TouchableWithoutFeedback>
260
-
261
- <BottomSheet
262
- ref={bottomSheetRef}
263
- index={bottomSheetIndex}
264
- handleComponent={() => null}
265
- onChange={handleSheetChanges}
266
- style={bottomSheetStyle}
267
- backgroundStyle={{ backgroundColor: theme.surface }}
268
- handleIndicatorStyle={[styles.handleIndicator, handleIndicatorStyle]}
269
- // snapPoints={snapPoints}
270
- enablePanDownToClose={true}
271
- // onClose={() => {
272
- // setIsVisible(false);
273
- // if (onClose) onClose();
274
- // }}
275
- >
276
- <View style={[styles.container, containerStyle]}>
277
- <View style={[styles.header, headerStyle]}>
278
- <Text style={[styles.title, titleStyle]}>{headerTitleText}</Text>
279
- <TouchableOpacity onPress={handleResetAll}>
280
- <Text style={[styles.resetText, resetTextStyle]}>
281
- {headerResetText}
282
- </Text>
283
- </TouchableOpacity>
284
- </View>
285
- <BottomSheetView style={{ paddingBottom: 75 }}>
286
- {sortOptions && sortOptions.length > 0 && (
287
- <View style={[styles.section, sectionStyle, sortSectionStyle]}>
288
- <Text style={[styles.sectionTitle, sectionTitleStyle]}>
289
- {sortSectionTitle}
290
- </Text>
291
- {sortOptions.map((option) => (
292
- <View
293
- style={[styles.optionRow, optionRowStyle]}
294
- key={option.id}
295
- >
296
- <Checkbox
297
- value={checkedItems[option.id]}
298
- color={checkboxColor}
299
- hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
300
- onValueChange={() =>
301
- handleCheckboxChange(option.id.toString())
302
- }
303
- />
304
- <Text style={[styles.optionText, optionTextStyle]}>
305
- {option.name}
306
- </Text>
307
- </View>
308
- ))}
309
- </View>
310
- )}
230
+ const closeBottomSheet = useCallback(() => {
231
+ if (bottomSheetRef.current) {
232
+ bottomSheetRef.current.close();
233
+ }
234
+ setIsVisible(false);
235
+ if (onClose) {
236
+ onClose();
237
+ }
238
+ }, [onClose]);
311
239
 
312
- {showPointsRange && (
313
- <View style={[styles.section, sectionStyle]}>
314
- <Text style={[styles.sectionTitle, sectionTitleStyle]}>
315
- {pointsRangeSectionTitle}
316
- </Text>
317
- <PointsRangeSelector
318
- resetKey={resetCounter}
319
- initialMax={rangeInitialMax}
320
- initialMin={rangeInitialMin}
321
- minLimit={rangeMinLimit}
322
- maxLimit={rangeMaxLimit}
323
- isRTL={isRTL}
324
- containerStyle={pointsRangeContainerStyle}
325
- inputsContainerStyle={pointsRangeInputsContainerStyle}
326
- customInputContainerStyle={
327
- pointsRangeCustomInputContainerStyle
328
- }
329
- customInputFieldStyle={pointsRangeCustomInputFieldStyle}
330
- sliderContainerStyle={pointsRangeSliderContainerStyle}
331
- multiSliderContainerStyle={
332
- pointsRangeMultiSliderContainerStyle
333
- }
334
- trackStyle={pointsRangeTrackStyle}
335
- selectedTrackStyle={pointsRangeSelectedTrackStyle}
336
- unselectedTrackStyle={pointsRangeUnselectedTrackStyle}
337
- markerStyle={pointsRangeMarkerStyle}
338
- markerEnabledStyle={pointsRangeMarkerEnabledStyle}
339
- markerDisabledStyle={pointsRangeMarkerDisabledStyle}
340
- markerDotStyle={pointsRangeMarkerDotStyle}
341
- inputProps={pointsRangeInputProps}
342
- multiSliderProps={pointsRangeMultiSliderProps}
343
- onChange={(min: number, max: number) => {
344
- setPointsRange({ min, max });
345
- }}
346
- />
347
- </View>
348
- )}
240
+ // If not visible, don't render anything
241
+ if (!isVisible) {
242
+ return null;
243
+ }
349
244
 
350
- {brands && brands.length > 0 && (
351
- <View style={[styles.section, sectionStyle]}>
352
- <Text style={[styles.sectionTitle, sectionTitleStyle]}>
353
- {brandSectionTile}
245
+ return (
246
+ <GestureHandlerRootView style={styles.overlayContainer}>
247
+ {/* Semi-transparent overlay */}
248
+ <TouchableWithoutFeedback onPress={closeBottomSheet}>
249
+ <View style={[styles.overlay, { backgroundColor: overlayColor }]} />
250
+ </TouchableWithoutFeedback>
251
+
252
+ <BottomSheet
253
+ ref={bottomSheetRef}
254
+ index={bottomSheetIndex}
255
+ handleComponent={() => null}
256
+ onChange={handleSheetChanges}
257
+ style={bottomSheetStyle}
258
+ backgroundStyle={{ backgroundColor: theme.surface }}
259
+ handleIndicatorStyle={[styles.handleIndicator, handleIndicatorStyle]}
260
+ // snapPoints={snapPoints}
261
+ enablePanDownToClose={true}
262
+ onClose={() => {
263
+ setIsVisible(false);
264
+ if (onClose) onClose();
265
+ }}
266
+ >
267
+ <View style={[styles.container, containerStyle]}>
268
+ <View style={[styles.header, headerStyle]}>
269
+ <Text style={[styles.title, titleStyle]}>{headerTitleText}</Text>
270
+ <TouchableOpacity onPress={handleResetAll}>
271
+ <Text style={[styles.resetText, resetTextStyle]}>
272
+ {headerResetText}
354
273
  </Text>
355
- <View style={[styles.brandsGrid, brandContainerStyle]}>
356
- {brands.map((brand) => (
357
- <BrandIcon
358
- key={brand.id}
359
- size={50}
360
- selected={selectedBrands[brand.id]}
361
- onPress={() => handleBrandSelect(brand.id.toString())}
362
- brand={{
363
- id: brand.id,
364
- name: brand.name,
365
- logo: brand.logo,
366
- }}
367
- selectionIndicatorIcon={
368
- brandActiveIcon || (
369
- <Ionicons
370
- name="checkmark-outline"
371
- color={theme.onPrimary}
372
- />
373
- )
374
- }
375
- selectionIndicatorStyle={brandActiveIconStyle}
376
- />
274
+ </TouchableOpacity>
275
+ </View>
276
+ <BottomSheetView style={{ paddingBottom: 75 }}>
277
+ {sortOptions && sortOptions.length > 0 && (
278
+ <View style={[styles.section, sectionStyle, sortSectionStyle]}>
279
+ <Text style={[styles.sectionTitle, sectionTitleStyle]}>
280
+ {sortSectionTitle}
281
+ </Text>
282
+ {sortOptions.map((option) => (
283
+ <View
284
+ style={[styles.optionRow, optionRowStyle]}
285
+ key={option.id}
286
+ >
287
+ <Checkbox
288
+ value={option.id == checkedItem}
289
+ color={checkboxColor}
290
+ hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
291
+ onValueChange={() =>
292
+ handleCheckboxChange(option.id)
293
+ }
294
+ />
295
+ <Text style={[styles.optionText, optionTextStyle]}>
296
+ {option.name}
297
+ </Text>
298
+ </View>
377
299
  ))}
378
300
  </View>
379
- </View>
380
- )}
301
+ )}
381
302
 
382
- <TouchableOpacity
383
- style={[styles.applyButton, applyButtonStyle]}
384
- onPress={handleApplyFilter}
385
- >
386
- <Text style={[styles.applyButtonText, applyButtonTextStyle]}>
387
- {applyButtonText}
388
- </Text>
389
- </TouchableOpacity>
390
- </BottomSheetView>
391
- </View>
392
- </BottomSheet>
393
- </GestureHandlerRootView>
394
- );
395
- };
303
+ {showPointsRange && (
304
+ <View style={[styles.section, sectionStyle]}>
305
+ <Text style={[styles.sectionTitle, sectionTitleStyle]}>
306
+ {pointsRangeSectionTitle}
307
+ </Text>
308
+ <PointsRangeSelector
309
+ resetKey={resetCounter}
310
+ initialMax={rangeInitialMax}
311
+ initialMin={rangeInitialMin}
312
+ minLimit={rangeMinLimit}
313
+ maxLimit={rangeMaxLimit}
314
+ isRTL={isRTL}
315
+ containerStyle={pointsRangeContainerStyle}
316
+ inputsContainerStyle={pointsRangeInputsContainerStyle}
317
+ customInputContainerStyle={
318
+ pointsRangeCustomInputContainerStyle
319
+ }
320
+ customInputFieldStyle={pointsRangeCustomInputFieldStyle}
321
+ sliderContainerStyle={pointsRangeSliderContainerStyle}
322
+ multiSliderContainerStyle={
323
+ pointsRangeMultiSliderContainerStyle
324
+ }
325
+ trackStyle={pointsRangeTrackStyle}
326
+ selectedTrackStyle={pointsRangeSelectedTrackStyle}
327
+ unselectedTrackStyle={pointsRangeUnselectedTrackStyle}
328
+ markerStyle={pointsRangeMarkerStyle}
329
+ markerEnabledStyle={pointsRangeMarkerEnabledStyle}
330
+ markerDisabledStyle={pointsRangeMarkerDisabledStyle}
331
+ markerDotStyle={pointsRangeMarkerDotStyle}
332
+ inputProps={pointsRangeInputProps}
333
+ multiSliderProps={pointsRangeMultiSliderProps}
334
+ onChange={(min: number, max: number) => {
335
+ setPointsRange({ min, max });
336
+ }}
337
+ />
338
+ </View>
339
+ )}
340
+
341
+ {brands && brands.length > 0 && (
342
+ <View style={[styles.section, sectionStyle]}>
343
+ <Text style={[styles.sectionTitle, sectionTitleStyle]}>
344
+ {brandSectionTile}
345
+ </Text>
346
+ <View style={[styles.brandsGrid, brandContainerStyle]}>
347
+ {brands.map((brand) => (
348
+ <BrandIcon
349
+ key={brand.id}
350
+ size={50}
351
+ selected={selectedBrands[brand.id]}
352
+ onPress={() => handleBrandSelect(brand.id.toString())}
353
+ brand={{
354
+ id: brand.id,
355
+ name: brand.name,
356
+ logo: brand.logo,
357
+ }}
358
+ selectionIndicatorIcon={
359
+ brandActiveIcon || (
360
+ <Ionicons
361
+ name="checkmark-outline"
362
+ color={theme.onPrimary}
363
+ />
364
+ )
365
+ }
366
+ selectionIndicatorStyle={brandActiveIconStyle}
367
+ />
368
+ ))}
369
+ </View>
370
+ </View>
371
+ )}
372
+
373
+ <TouchableOpacity
374
+ style={[styles.applyButton, applyButtonStyle]}
375
+ onPress={handleApplyFilter}
376
+ >
377
+ <Text style={[styles.applyButtonText, applyButtonTextStyle]}>
378
+ {applyButtonText}
379
+ </Text>
380
+ </TouchableOpacity>
381
+ </BottomSheetView>
382
+ </View>
383
+ </BottomSheet>
384
+ </GestureHandlerRootView>
385
+ );
386
+ };
396
387
 
397
- const createStyles = (theme: ThemeType, isRTL: boolean) =>
398
- StyleSheet.create({
399
- overlayContainer: {
400
- flex: 1,
401
- position: 'absolute',
402
- top: 0,
403
- left: 0,
404
- right: 0,
405
- bottom: 0,
406
- zIndex: 1000,
407
- },
408
- overlay: {
409
- ...StyleSheet.absoluteFillObject,
410
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
411
- },
412
- container: {
413
- flex: 1,
414
- paddingHorizontal: 25,
415
- backgroundColor: theme.surface,
416
- },
417
- handleIndicator: {
418
- width: 40,
419
- height: 4,
420
- backgroundColor: theme.border,
421
- alignSelf: "center",
422
- marginTop: 8,
423
- borderRadius: 2,
424
- },
425
- header: {
426
- flexDirection: isRTL ? "row-reverse" : "row",
427
- justifyContent: "space-between",
428
- alignItems: "center",
429
- paddingVertical: 15,
430
- borderBottomWidth: 1,
431
- borderBottomColor: theme.border,
432
- },
433
- title: {
434
- fontSize: 18,
435
- fontWeight: "bold",
436
- color: theme.text,
437
- textAlign: isRTL ? "right" : "left",
438
- },
439
- resetText: {
440
- fontSize: 14,
441
- color: theme.primary,
442
- fontWeight: "500",
443
- textAlign: isRTL ? "left" : "right",
444
- },
445
- section: {
446
- marginTop: 20,
447
- },
448
- sectionTitle: {
449
- fontSize: 16,
450
- fontWeight: "500",
451
- color: theme.helper,
452
- marginBottom: 15,
453
- textAlign: isRTL ? "right" : "left",
454
- },
455
- optionRow: {
456
- flexDirection: isRTL ? "row-reverse" : "row",
457
- alignItems: "center",
458
- marginBottom: 15,
459
- gap: 5,
460
- },
461
- optionText: {
462
- fontSize: 15,
463
- color: theme.text,
464
- textAlign: isRTL ? "right" : "left",
465
- marginLeft: isRTL ? 0 : 8,
466
- marginRight: isRTL ? 8 : 0,
467
- },
468
- brandsGrid: {
469
- flexDirection: "row",
470
- flexWrap: "wrap",
471
- gap: 10,
472
- justifyContent: isRTL ? "flex-end" : "flex-start",
473
- },
474
- applyButton: {
475
- backgroundColor: theme.primary,
476
- borderRadius: 30,
477
- paddingVertical: 15,
478
- alignItems: "center",
479
- marginTop: 30,
480
- },
481
- applyButtonText: {
482
- color: theme.onPrimary,
483
- fontSize: 16,
484
- fontWeight: "bold",
485
- },
486
- });
388
+ const createStyles = (theme: ThemeType, isRTL: boolean) =>
389
+ StyleSheet.create({
390
+ overlayContainer: {
391
+ flex: 1,
392
+ position: 'absolute',
393
+ top: 0,
394
+ left: 0,
395
+ right: 0,
396
+ bottom: 0,
397
+ zIndex: 1000,
398
+ },
399
+ overlay: {
400
+ ...StyleSheet.absoluteFillObject,
401
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
402
+ },
403
+ container: {
404
+ flex: 1,
405
+ paddingHorizontal: 25,
406
+ backgroundColor: theme.surface,
407
+ },
408
+ handleIndicator: {
409
+ width: 40,
410
+ height: 4,
411
+ backgroundColor: theme.border,
412
+ alignSelf: "center",
413
+ marginTop: 8,
414
+ borderRadius: 2,
415
+ },
416
+ header: {
417
+ flexDirection: isRTL ? "row-reverse" : "row",
418
+ justifyContent: "space-between",
419
+ alignItems: "center",
420
+ paddingVertical: 15,
421
+ borderBottomWidth: 1,
422
+ borderBottomColor: theme.border,
423
+ },
424
+ title: {
425
+ fontSize: 18,
426
+ fontWeight: "bold",
427
+ color: theme.text,
428
+ textAlign: isRTL ? "right" : "left",
429
+ },
430
+ resetText: {
431
+ fontSize: 14,
432
+ color: theme.primary,
433
+ fontWeight: "500",
434
+ textAlign: isRTL ? "left" : "right",
435
+ },
436
+ section: {
437
+ marginTop: 20,
438
+ },
439
+ sectionTitle: {
440
+ fontSize: 16,
441
+ fontWeight: "500",
442
+ color: theme.helper,
443
+ marginBottom: 15,
444
+ textAlign: isRTL ? "right" : "left",
445
+ },
446
+ optionRow: {
447
+ flexDirection: isRTL ? "row-reverse" : "row",
448
+ alignItems: "center",
449
+ marginBottom: 15,
450
+ gap: 5,
451
+ },
452
+ optionText: {
453
+ fontSize: 15,
454
+ color: theme.text,
455
+ textAlign: isRTL ? "right" : "left",
456
+ marginLeft: isRTL ? 0 : 8,
457
+ marginRight: isRTL ? 8 : 0,
458
+ },
459
+ brandsGrid: {
460
+ flexDirection: "row",
461
+ flexWrap: "wrap",
462
+ gap: 10,
463
+ justifyContent: isRTL ? "flex-end" : "flex-start",
464
+ },
465
+ applyButton: {
466
+ backgroundColor: theme.primary,
467
+ borderRadius: 30,
468
+ paddingVertical: 15,
469
+ alignItems: "center",
470
+ marginTop: 30,
471
+ },
472
+ applyButtonText: {
473
+ color: theme.onPrimary,
474
+ fontSize: 16,
475
+ fontWeight: "bold",
476
+ },
477
+ });
487
478
 
488
- export default Filters;
479
+ export default Filters;