related-ui-components 1.6.5 → 1.6.7

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.
@@ -1,479 +1,489 @@
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
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
+ // Remove TouchableWithoutFeedback as it's no longer needed for the overlay
12
+ } from "react-native";
13
+ import { GestureHandlerRootView } from "react-native-gesture-handler";
14
+ import BottomSheet, {
15
+ BottomSheetView,
16
+ BottomSheetBackdrop, // Import BottomSheetBackdrop
17
+ BottomSheetBackdropProps, // Import props type for type safety
18
+ } from "@gorhom/bottom-sheet";
19
+ import PointsRangeSelector from "./PointsRangeSelector";
20
+ import { BrandIcon } from "../BrandIcon";
21
+ import { Ionicons } from "@expo/vector-icons";
22
+ import Checkbox from "expo-checkbox";
23
+ import { useTheme, ThemeType } from "../../theme"; // Import ThemeType
20
24
 
21
- type SortOption = {
22
- name: string;
23
- value: string;
24
- id: number;
25
- checked?: boolean;
26
- };
27
- export 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
- }
25
+ // ... (Keep existing type definitions: SortOption, Brand, FilterResult) ...
26
+ type SortOption = {
27
+ name: string;
28
+ value: string;
29
+ id: number;
30
+ checked?: boolean;
31
+ };
32
+ export type Brand = {
33
+ id: string;
34
+ name: string;
35
+ logo: ImageSourcePropType;
36
+ checked?: boolean;
37
+ };
38
+ export type FilterResult = {
39
+ sort: SortOption | undefined;
40
+ pointsRange: { min: number; max: number };
41
+ selectedBrands: Brand[];
42
+ };
92
43
 
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);
44
+ interface FiltersProps {
45
+ isRTL?: boolean;
46
+ sortOptions?: SortOption[];
47
+ sortSectionTitle?: string;
48
+ sectionTitleStyle?: TextStyle;
49
+ sortSectionStyle?: ViewStyle;
50
+ rangeMinLimit?: number;
51
+ rangeMaxLimit?: number;
52
+ rangeInitialMin?: number;
53
+ rangeInitialMax?: number;
54
+ showPointsRange?: boolean;
55
+ pointsRangeSectionTitle?: string;
56
+ pointsRangeContainerStyle?: ViewStyle;
57
+ pointsRangeInputsContainerStyle?: ViewStyle;
58
+ pointsRangeCustomInputContainerStyle?: ViewStyle;
59
+ pointsRangeCustomInputFieldStyle?: ViewStyle;
60
+ pointsRangeSliderContainerStyle?: ViewStyle;
61
+ pointsRangeMultiSliderContainerStyle?: ViewStyle;
62
+ pointsRangeTrackStyle?: ViewStyle;
63
+ pointsRangeSelectedTrackStyle?: ViewStyle;
64
+ pointsRangeUnselectedTrackStyle?: ViewStyle;
65
+ pointsRangeMarkerStyle?: ViewStyle;
66
+ pointsRangeMarkerEnabledStyle?: ViewStyle;
67
+ pointsRangeMarkerDisabledStyle?: ViewStyle;
68
+ pointsRangeMarkerDotStyle?: ViewStyle;
69
+ pointsRangeInputProps?: any;
70
+ pointsRangeMultiSliderProps?: any;
71
+ brands?: Brand[];
72
+ brandContainerStyle?: ViewStyle;
73
+ brandActiveIcon?: React.ReactNode;
74
+ brandActiveIconStyle?: ViewStyle;
75
+ brandSectionTile?: string;
76
+ onActionButtonPress?: (result: FilterResult) => void;
77
+ containerStyle?: ViewStyle;
78
+ headerStyle?: ViewStyle;
79
+ titleStyle?: TextStyle;
80
+ resetTextStyle?: TextStyle;
81
+ sectionStyle?: ViewStyle;
82
+ optionRowStyle?: ViewStyle;
83
+ optionTextStyle?: TextStyle;
84
+ checkboxColor?: string;
85
+ applyButtonStyle?: ViewStyle;
86
+ applyButtonTextStyle?: TextStyle;
87
+ bottomSheetStyle?: ViewStyle;
88
+ headerTitleText?: string;
89
+ headerResetText?: string;
90
+ bottomSheetIndex?: number;
91
+ handleIndicatorStyle?: ViewStyle;
92
+ applyButtonText?: string;
93
+ overlayColor?: string;
94
+ onClose?: () => void;
95
+ visible?: boolean;
96
+ }
153
97
 
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]);
98
+ const Filters: React.FC<FiltersProps> = ({
99
+ isRTL: isRTLProp,
100
+ sortOptions = [],
101
+ sortSectionTitle = "Sort",
102
+ sectionTitleStyle,
103
+ sortSectionStyle,
104
+ onActionButtonPress,
105
+ rangeInitialMax = 1000,
106
+ rangeInitialMin = 0,
107
+ rangeMaxLimit = 1000,
108
+ rangeMinLimit = 0,
109
+ pointsRangeContainerStyle,
110
+ pointsRangeInputsContainerStyle,
111
+ pointsRangeCustomInputContainerStyle,
112
+ pointsRangeCustomInputFieldStyle,
113
+ pointsRangeSliderContainerStyle,
114
+ pointsRangeMultiSliderContainerStyle,
115
+ pointsRangeTrackStyle,
116
+ pointsRangeSelectedTrackStyle,
117
+ pointsRangeUnselectedTrackStyle,
118
+ pointsRangeMarkerStyle,
119
+ pointsRangeMarkerEnabledStyle,
120
+ pointsRangeMarkerDisabledStyle,
121
+ pointsRangeMarkerDotStyle,
122
+ pointsRangeInputProps,
123
+ pointsRangeMultiSliderProps,
124
+ containerStyle,
125
+ headerStyle,
126
+ titleStyle,
127
+ resetTextStyle,
128
+ sectionStyle,
129
+ optionRowStyle,
130
+ optionTextStyle,
131
+ checkboxColor: checkboxColorProp,
132
+ applyButtonStyle,
133
+ applyButtonTextStyle,
134
+ bottomSheetStyle,
135
+ bottomSheetIndex = 0,
136
+ handleIndicatorStyle,
137
+ brands = [],
138
+ brandContainerStyle,
139
+ brandActiveIcon,
140
+ showPointsRange = true,
141
+ pointsRangeSectionTitle = "Points range",
142
+ brandActiveIconStyle,
143
+ brandSectionTile = "Brands",
144
+ applyButtonText = "Apply Filter",
145
+ headerResetText = "Reset All",
146
+ headerTitleText = "Filter",
147
+ onClose,
148
+ visible = true,
149
+ }) => {
150
+ const { theme, isRTL: themeIsRTL } = useTheme();
151
+ const isRTL = isRTLProp ?? themeIsRTL ?? I18nManager.isRTL;
152
+ const bottomSheetRef = useRef<BottomSheet>(null);
153
+ const styles = createStyles(theme, isRTL);
154
+ const checkboxColor = checkboxColorProp ?? theme.primary;
155
+ const [isVisible, setIsVisible] = useState(visible);
156
+
157
+ useEffect(() => {
158
+ if (visible) {
159
+ setIsVisible(true);
160
+ setTimeout(() => bottomSheetRef.current?.snapToIndex(bottomSheetIndex), 0);
161
+ } else {
162
+ bottomSheetRef.current?.close();
163
+ setIsVisible(false);
164
+ }
165
+ }, [visible, bottomSheetIndex]);
161
166
 
162
- const handleSheetChanges = useCallback((index: number) => {
167
+ const handleSheetChanges = useCallback(
168
+ (index: number) => {
163
169
  if (index === -1) {
164
170
  setIsVisible(false);
171
+ if (onClose) {
172
+ onClose();
173
+ }
165
174
  }
166
- }, []);
167
-
168
- const [resetCounter, setResetCounter] = useState(0);
175
+ },
176
+ [onClose]
177
+ );
169
178
 
179
+ const [resetCounter, setResetCounter] = useState(0);
170
180
 
171
- const [checkedItem, setCheckedItem] = useState<number | null>(
172
- sortOptions.find(option => option.checked)?.id || null
173
- );
181
+ const [checkedItem, setCheckedItem] = useState<number | null>(
182
+ sortOptions.find((option) => option.checked)?.id || null
183
+ );
174
184
 
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 }>({
185
+ const [selectedBrands, setSelectedBrands] = useState<
186
+ Record<string, boolean>
187
+ >(
188
+ brands.reduce((acc, option) => {
189
+ acc[option.id] = option.checked || false;
190
+ return acc;
191
+ }, {} as Record<string, boolean>)
192
+ );
193
+ const [pointsRange, setPointsRange] = useState<{ min: number; max: number }>(
194
+ {
182
195
  min: rangeInitialMin,
183
196
  max: rangeInitialMax,
184
- });
197
+ }
198
+ );
185
199
 
186
- const handleCheckboxChange = (id: number) => {
187
- setCheckedItem(id);
188
- };
200
+ const handleCheckboxChange = (id: number) => {
201
+ setCheckedItem(id);
202
+ };
189
203
 
190
- const handleBrandSelect = (id: string) => {
191
- setSelectedBrands((prevState) => ({
192
- ...prevState,
193
- [id]: !prevState[id],
194
- }));
195
- };
204
+ const handleBrandSelect = (id: string) => {
205
+ setSelectedBrands((prevState) => ({
206
+ ...prevState,
207
+ [id]: !prevState[id],
208
+ }));
209
+ };
196
210
 
197
- const handleApplyFilter = () => {
198
- if (onActionButtonPress) {
199
- const selectedSortOption = sortOptions.find(
200
- (option) => option.id == checkedItem
201
- );
211
+ const closeBottomSheet = useCallback(() => {
212
+ bottomSheetRef.current?.close();
213
+ }, [/* onClose */]);
202
214
 
203
- const selectedBrandsList = brands.filter(
204
- (brand) => selectedBrands[brand.id]
205
- );
215
+ const handleApplyFilter = () => {
216
+ if (onActionButtonPress) {
217
+ const selectedSortOption = sortOptions.find(
218
+ (option) => option.id == checkedItem
219
+ );
206
220
 
207
- const filterResult: FilterResult = {
208
- sort: selectedSortOption,
209
- pointsRange: pointsRange,
210
- selectedBrands: selectedBrandsList,
211
- };
221
+ const selectedBrandsList = brands.filter(
222
+ (brand) => selectedBrands[brand.id]
223
+ );
212
224
 
213
- onActionButtonPress(filterResult);
214
- closeBottomSheet(); // Close the filter after applying
215
- }
216
- };
225
+ const filterResult: FilterResult = {
226
+ sort: selectedSortOption,
227
+ pointsRange: pointsRange,
228
+ selectedBrands: selectedBrandsList,
229
+ };
217
230
 
218
- const handleResetAll = () => {
219
- const resetBrands = brands.reduce((acc, option) => {
220
- acc[option.id] = false;
221
- return acc;
222
- }, {} as Record<string, boolean>);
231
+ onActionButtonPress(filterResult);
232
+ }
233
+ closeBottomSheet();
234
+ };
223
235
 
224
- setCheckedItem(null);
225
- setSelectedBrands(resetBrands);
226
- setPointsRange({ min: rangeMinLimit, max: rangeInitialMax });
227
- setResetCounter((prev) => prev + 1);
228
- };
236
+ const handleResetAll = () => {
237
+ const resetBrands = brands.reduce((acc, option) => {
238
+ acc[option.id] = false;
239
+ return acc;
240
+ }, {} as Record<string, boolean>);
229
241
 
230
- const closeBottomSheet = useCallback(() => {
231
- if (bottomSheetRef.current) {
232
- bottomSheetRef.current.close();
233
- }
234
- setIsVisible(false);
235
- if (onClose) {
236
- onClose();
237
- }
238
- }, [onClose]);
242
+ setCheckedItem(null);
243
+ setSelectedBrands(resetBrands);
244
+ setPointsRange({ min: rangeMinLimit, max: rangeInitialMax });
245
+ setResetCounter((prev) => prev + 1);
246
+ };
239
247
 
240
- // If not visible, don't render anything
241
- if (!isVisible) {
242
- return null;
243
- }
248
+ const renderBackdrop = useCallback(
249
+ (props: BottomSheetBackdropProps) => (
250
+ <BottomSheetBackdrop
251
+ {...props}
252
+ appearsOnIndex={0}
253
+ disappearsOnIndex={-1}
254
+ pressBehavior="close"
255
+ opacity={0.5}
256
+ />
257
+ ),
258
+ []
259
+ );
260
+
261
+ if (!visible) {
262
+ return null;
263
+ }
244
264
 
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}
265
+ return (
266
+ <GestureHandlerRootView style={styles.gestureHandlerRoot}>
267
+ <BottomSheet
268
+ ref={bottomSheetRef}
269
+ index={isVisible ? bottomSheetIndex : -1}
270
+ onChange={handleSheetChanges}
271
+ handleComponent={() => null}
272
+ style={bottomSheetStyle}
273
+ backgroundStyle={{ backgroundColor: theme.surface }}
274
+ handleIndicatorStyle={[styles.handleIndicator, handleIndicatorStyle]}
275
+ enablePanDownToClose={true}
276
+ backdropComponent={renderBackdrop}
277
+ >
278
+ <View style={[styles.container, containerStyle]}>
279
+ <View style={[styles.header, headerStyle]}>
280
+ <Text style={[styles.title, titleStyle]}>{headerTitleText}</Text>
281
+ <TouchableOpacity onPress={handleResetAll}>
282
+ <Text style={[styles.resetText, resetTextStyle]}>
283
+ {headerResetText}
284
+ </Text>
285
+ </TouchableOpacity>
286
+ </View>
287
+ <BottomSheetView style={{ paddingBottom: 75 }}>
288
+ {sortOptions && sortOptions.length > 0 && (
289
+ <View style={[styles.section, sectionStyle, sortSectionStyle]}>
290
+ <Text style={[styles.sectionTitle, sectionTitleStyle]}>
291
+ {sortSectionTitle}
273
292
  </Text>
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>
299
- ))}
300
- </View>
301
- )}
293
+ {sortOptions.map((option) => (
294
+ <View
295
+ style={[styles.optionRow, optionRowStyle]}
296
+ key={option.id}
297
+ >
298
+ <Checkbox
299
+ value={option.id == checkedItem}
300
+ color={checkboxColor}
301
+ hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
302
+ onValueChange={() => handleCheckboxChange(option.id)}
303
+ />
304
+ <Text style={[styles.optionText, optionTextStyle]}>
305
+ {option.name}
306
+ </Text>
307
+ </View>
308
+ ))}
309
+ </View>
310
+ )}
302
311
 
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
- )}
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
+ )}
340
349
 
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>
350
+ {brands && brands.length > 0 && (
351
+ <View style={[styles.section, sectionStyle]}>
352
+ <Text style={[styles.sectionTitle, sectionTitleStyle]}>
353
+ {brandSectionTile}
354
+ </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
+ />
377
+ ))}
370
378
  </View>
371
- )}
379
+ </View>
380
+ )}
372
381
 
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
- };
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
+ };
387
396
 
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
- });
397
+ const createStyles = (theme: ThemeType, isRTL: boolean) =>
398
+ StyleSheet.create({
399
+ // overlayContainer is likely not needed anymore
400
+ // overlay: { ... }, // Removed - handled by backdropComponent
401
+ gestureHandlerRoot: {
402
+ // Style needed for GestureHandlerRootView if it needs specific layout,
403
+ // often just flex: 1 or position absolute covering the screen
404
+ position: 'absolute',
405
+ top: 0,
406
+ left: 0,
407
+ right: 0,
408
+ bottom: 0,
409
+ zIndex: 1000, // Ensure it's above other content
410
+ },
411
+ container: {
412
+ flex: 1,
413
+ paddingHorizontal: 25,
414
+ backgroundColor: theme.surface, // Background is set on BottomSheet backgroundStyle now
415
+ },
416
+ handleIndicator: {
417
+ width: 40,
418
+ height: 4,
419
+ backgroundColor: theme.border,
420
+ alignSelf: "center",
421
+ marginTop: 8,
422
+ borderRadius: 2,
423
+ },
424
+ header: {
425
+ flexDirection: isRTL ? "row-reverse" : "row",
426
+ justifyContent: "space-between",
427
+ alignItems: "center",
428
+ paddingVertical: 15,
429
+ borderBottomWidth: 1,
430
+ borderBottomColor: theme.border,
431
+ },
432
+ title: {
433
+ fontSize: 18,
434
+ fontWeight: "bold",
435
+ color: theme.text,
436
+ textAlign: isRTL ? "right" : "left",
437
+ },
438
+ resetText: {
439
+ fontSize: 14,
440
+ color: theme.primary,
441
+ fontWeight: "500",
442
+ textAlign: isRTL ? "left" : "right",
443
+ },
444
+ section: {
445
+ marginTop: 20,
446
+ },
447
+ sectionTitle: {
448
+ fontSize: 16,
449
+ fontWeight: "500",
450
+ color: theme.helper,
451
+ marginBottom: 15,
452
+ textAlign: isRTL ? "right" : "left",
453
+ },
454
+ optionRow: {
455
+ flexDirection: isRTL ? "row-reverse" : "row",
456
+ alignItems: "center",
457
+ marginBottom: 15,
458
+ gap: 5,
459
+ },
460
+ optionText: {
461
+ fontSize: 15,
462
+ color: theme.text,
463
+ textAlign: isRTL ? "right" : "left",
464
+ marginLeft: isRTL ? 0 : 8,
465
+ marginRight: isRTL ? 8 : 0,
466
+ },
467
+ brandsGrid: {
468
+ flexDirection: "row",
469
+ flexWrap: "wrap",
470
+ gap: 10,
471
+ justifyContent: isRTL ? "flex-end" : "flex-start",
472
+ },
473
+ applyButton: {
474
+ backgroundColor: theme.primary,
475
+ borderRadius: 30,
476
+ paddingVertical: 15,
477
+ alignItems: "center",
478
+ marginTop: 30,
479
+ // Consider adding marginBottom if needed, especially inside BottomSheetView
480
+ // marginBottom: 20,
481
+ },
482
+ applyButtonText: {
483
+ color: theme.onPrimary,
484
+ fontSize: 16,
485
+ fontWeight: "bold",
486
+ },
487
+ });
478
488
 
479
- export default Filters;
489
+ export default Filters;