related-ui-components 2.1.9 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/module/app.js +2 -2
- package/lib/module/app.js.map +1 -1
- package/lib/module/components/TravelBooking/CarRentalForm.js +31 -26
- package/lib/module/components/TravelBooking/CarRentalForm.js.map +1 -1
- package/lib/module/components/TravelBooking/FlightForm.js +21 -10
- package/lib/module/components/TravelBooking/FlightForm.js.map +1 -1
- package/lib/module/components/TravelBooking/FlightSummary.js +5 -0
- package/lib/module/components/TravelBooking/FlightSummary.js.map +1 -1
- package/lib/module/components/TravelBooking/HotelForm.js +26 -26
- package/lib/module/components/TravelBooking/HotelForm.js.map +1 -1
- package/lib/module/index.js +7 -4
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/app.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/CarRentalForm.d.ts +11 -0
- package/lib/typescript/src/components/TravelBooking/CarRentalForm.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/FlightForm.d.ts +8 -0
- package/lib/typescript/src/components/TravelBooking/FlightForm.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/FlightSummary.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/HotelForm.d.ts +9 -0
- package/lib/typescript/src/components/TravelBooking/HotelForm.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +0 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/app.tsx +5 -2
- package/src/components/TravelBooking/CarRentalForm.tsx +111 -69
- package/src/components/TravelBooking/FlightForm.tsx +108 -68
- package/src/components/TravelBooking/FlightSummary.tsx +3 -1
- package/src/components/TravelBooking/HotelForm.tsx +87 -61
- package/src/index.ts +5 -5
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ThemeType, useTheme } from "../../theme";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
3
9
|
import {
|
|
4
10
|
View,
|
|
5
11
|
Text,
|
|
@@ -11,9 +17,9 @@ import {
|
|
|
11
17
|
} from "react-native";
|
|
12
18
|
import { Ionicons } from "@expo/vector-icons";
|
|
13
19
|
import CustomInput from "../Input/Input";
|
|
14
|
-
import DateRangePicker from "../DateRangePicker/DateRangePicker";
|
|
15
|
-
import SuggestionList from "../Suggestions/SuggestionList";
|
|
16
|
-
import { FlightSuggestions, FormInputType } from "./types";
|
|
20
|
+
import DateRangePicker from "../DateRangePicker/DateRangePicker";
|
|
21
|
+
import SuggestionList from "../Suggestions/SuggestionList";
|
|
22
|
+
import { FlightSuggestions, FormInputType } from "./types";
|
|
17
23
|
import { TextInput } from "react-native-gesture-handler";
|
|
18
24
|
|
|
19
25
|
// --- Helper Types ---
|
|
@@ -39,6 +45,13 @@ export interface FlightFormProps {
|
|
|
39
45
|
}) => void;
|
|
40
46
|
onTextChange?: (text: string) => void;
|
|
41
47
|
|
|
48
|
+
onSelectionChange?: (details: {
|
|
49
|
+
from: LocationData | undefined;
|
|
50
|
+
to: LocationData | undefined;
|
|
51
|
+
departure: string | undefined; // Send YYYY-MM-DD
|
|
52
|
+
return?: string | undefined; // Send YYYY-MM-DD
|
|
53
|
+
}) => void;
|
|
54
|
+
|
|
42
55
|
fromLabel?: string;
|
|
43
56
|
fromPlaceholder?: string;
|
|
44
57
|
|
|
@@ -56,34 +69,36 @@ export interface FlightFormProps {
|
|
|
56
69
|
suggestionData?: FlightSuggestions[];
|
|
57
70
|
|
|
58
71
|
// --- Style Props ---
|
|
59
|
-
containerStyle?: StyleProp<ViewStyle>;
|
|
60
|
-
inputGroupContainerStyle?: StyleProp<ViewStyle>;
|
|
61
|
-
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
62
|
-
customInputContainerStyle?: StyleProp<ViewStyle>;
|
|
63
|
-
|
|
72
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
73
|
+
inputGroupContainerStyle?: StyleProp<ViewStyle>;
|
|
74
|
+
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
75
|
+
customInputContainerStyle?: StyleProp<ViewStyle>;
|
|
76
|
+
inputStyle?: StyleProp<ViewStyle>;
|
|
77
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
64
78
|
swapButtonContainerStyle?: StyleProp<ViewStyle>;
|
|
65
79
|
swapButtonStyle?: StyleProp<ViewStyle>;
|
|
66
80
|
swapIconStyle?: StyleProp<TextStyle>;
|
|
67
|
-
departureRowStyle?: StyleProp<ViewStyle>;
|
|
81
|
+
departureRowStyle?: StyleProp<ViewStyle>;
|
|
68
82
|
searchButtonStyle?: StyleProp<ViewStyle>;
|
|
69
|
-
searchIconStyle?: StyleProp<TextStyle>;
|
|
83
|
+
searchIconStyle?: StyleProp<TextStyle>;
|
|
70
84
|
|
|
71
85
|
// DateRangePicker specific styles (passed down)
|
|
72
86
|
dateRangePickerOuterContainerStyle?: StyleProp<ViewStyle>;
|
|
73
87
|
dateRangePickerLabelStyle?: StyleProp<TextStyle>;
|
|
74
88
|
dateRangePickerInputGroupStyle?: StyleProp<ViewStyle>;
|
|
75
|
-
dateRangePickerCalendarContainerStyle?: StyleProp<ViewStyle>;
|
|
89
|
+
dateRangePickerCalendarContainerStyle?: StyleProp<ViewStyle>;
|
|
90
|
+
dateRangePickerInputContainerStyle?: StyleProp<ViewStyle>;
|
|
76
91
|
|
|
77
92
|
// SuggestionList specific styles
|
|
78
93
|
suggestionListContainerStyle?: StyleProp<ViewStyle>;
|
|
79
94
|
// Styles for the default suggestion item rendering
|
|
80
|
-
suggestionItemGroupStyle?: StyleProp<ViewStyle>;
|
|
81
|
-
suggestionCityRowStyle?: StyleProp<ViewStyle>;
|
|
82
|
-
suggestionCityIconStyle?: StyleProp<TextStyle>;
|
|
83
|
-
suggestionCityTextStyle?: StyleProp<TextStyle>;
|
|
95
|
+
suggestionItemGroupStyle?: StyleProp<ViewStyle>;
|
|
96
|
+
suggestionCityRowStyle?: StyleProp<ViewStyle>;
|
|
97
|
+
suggestionCityIconStyle?: StyleProp<TextStyle>;
|
|
98
|
+
suggestionCityTextStyle?: StyleProp<TextStyle>;
|
|
84
99
|
suggestionAirportTouchableStyle?: StyleProp<ViewStyle>;
|
|
85
100
|
suggestionAirportIconStyle?: StyleProp<TextStyle>;
|
|
86
|
-
suggestionAirportTextStyle?: StyleProp<TextStyle>;
|
|
101
|
+
suggestionAirportTextStyle?: StyleProp<TextStyle>;
|
|
87
102
|
}
|
|
88
103
|
// --- Component ---
|
|
89
104
|
const FlightForm: React.FC<FlightFormProps> = ({
|
|
@@ -130,6 +145,9 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
130
145
|
suggestionAirportTouchableStyle,
|
|
131
146
|
suggestionAirportIconStyle,
|
|
132
147
|
suggestionAirportTextStyle,
|
|
148
|
+
inputStyle,
|
|
149
|
+
onSelectionChange,
|
|
150
|
+
dateRangePickerInputContainerStyle,
|
|
133
151
|
}) => {
|
|
134
152
|
const { theme, isRTL } = useTheme();
|
|
135
153
|
const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]);
|
|
@@ -160,6 +178,22 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
160
178
|
onSwapPress?.(currentFrom, currentTo);
|
|
161
179
|
}, [fromLocation, toLocation, onSwapPress]);
|
|
162
180
|
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
onSelectionChange?.({
|
|
183
|
+
from: fromLocation,
|
|
184
|
+
to: toLocation,
|
|
185
|
+
departure: departureDate,
|
|
186
|
+
return: isOneWay ? undefined : returnDate,
|
|
187
|
+
});
|
|
188
|
+
}, [
|
|
189
|
+
fromLocation,
|
|
190
|
+
toLocation,
|
|
191
|
+
departureDate,
|
|
192
|
+
returnDate,
|
|
193
|
+
isOneWay,
|
|
194
|
+
onSelectionChange,
|
|
195
|
+
]);
|
|
196
|
+
|
|
163
197
|
const handleSearch = useCallback(() => {
|
|
164
198
|
onSearchPress?.({
|
|
165
199
|
from: fromLocation,
|
|
@@ -178,7 +212,10 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
178
212
|
|
|
179
213
|
// --- Default Suggestion Renderer (Now Stylable) ---
|
|
180
214
|
const suggestionRenderItem = (item: FlightSuggestions) => (
|
|
181
|
-
<View
|
|
215
|
+
<View
|
|
216
|
+
key={item.id}
|
|
217
|
+
style={[styles.suggestionItemGroup, suggestionItemGroupStyle]}
|
|
218
|
+
>
|
|
182
219
|
<View style={[styles.suggestionCityRow, suggestionCityRowStyle]}>
|
|
183
220
|
<Ionicons
|
|
184
221
|
name="airplane" // Consider making icon name a prop too if needed
|
|
@@ -192,7 +229,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
192
229
|
</View>
|
|
193
230
|
{item.airports.map((airport, index) => (
|
|
194
231
|
<TouchableOpacity
|
|
195
|
-
key={`${item.id}-${index}`}
|
|
232
|
+
key={`${item.id}-${index}`}
|
|
196
233
|
style={[
|
|
197
234
|
styles.suggestionAirportTouchable,
|
|
198
235
|
suggestionAirportTouchableStyle,
|
|
@@ -233,6 +270,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
233
270
|
setFromLocation(text);
|
|
234
271
|
onTextChange?.(text);
|
|
235
272
|
}}
|
|
273
|
+
inputStyle={inputStyle}
|
|
236
274
|
label={fromLabel}
|
|
237
275
|
value={fromLocation}
|
|
238
276
|
labelStyle={[styles.label, labelStyle]}
|
|
@@ -248,7 +286,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
248
286
|
}
|
|
249
287
|
}, 150);
|
|
250
288
|
}}
|
|
251
|
-
|
|
289
|
+
inputContainerStyle={customInputContainerStyle}
|
|
252
290
|
/>
|
|
253
291
|
{suggestionData && (
|
|
254
292
|
<SuggestionList
|
|
@@ -260,20 +298,22 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
260
298
|
)}
|
|
261
299
|
</View>
|
|
262
300
|
|
|
263
|
-
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
301
|
+
{onSwapPress && (
|
|
302
|
+
<View style={[styles.swapButtonContainer, swapButtonContainerStyle]}>
|
|
303
|
+
<TouchableOpacity
|
|
304
|
+
style={[styles.swapButton, swapButtonStyle]}
|
|
305
|
+
onPress={handleSwap}
|
|
306
|
+
activeOpacity={0.7}
|
|
307
|
+
>
|
|
308
|
+
<Ionicons
|
|
309
|
+
name={swapIconName}
|
|
310
|
+
size={20}
|
|
311
|
+
color={theme.onSurface}
|
|
312
|
+
style={swapIconStyle}
|
|
313
|
+
/>
|
|
314
|
+
</TouchableOpacity>
|
|
315
|
+
</View>
|
|
316
|
+
)}
|
|
277
317
|
|
|
278
318
|
{/* Apply inputWrapperStyle */}
|
|
279
319
|
<View style={[styles.inputWrapper, inputWrapperStyle]}>
|
|
@@ -285,6 +325,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
285
325
|
}}
|
|
286
326
|
label={toLabel}
|
|
287
327
|
value={toLocation}
|
|
328
|
+
inputStyle={inputStyle}
|
|
288
329
|
labelStyle={[styles.label, labelStyle]}
|
|
289
330
|
placeholder={toPlaceholder}
|
|
290
331
|
onFocus={() => {
|
|
@@ -292,15 +333,13 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
292
333
|
onInputFocus?.(FormInputType.FLIGHT_TO);
|
|
293
334
|
}}
|
|
294
335
|
onBlur={() => {
|
|
295
|
-
// Delay blur slightly to allow suggestion press
|
|
296
336
|
setTimeout(() => {
|
|
297
337
|
if (focusedInput === FormInputType.FLIGHT_TO) {
|
|
298
338
|
setFocusedInput(undefined);
|
|
299
339
|
}
|
|
300
340
|
}, 150);
|
|
301
341
|
}}
|
|
302
|
-
|
|
303
|
-
containerStyle={customInputContainerStyle}
|
|
342
|
+
inputContainerStyle={customInputContainerStyle}
|
|
304
343
|
/>
|
|
305
344
|
{suggestionData && (
|
|
306
345
|
<SuggestionList
|
|
@@ -320,13 +359,14 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
320
359
|
returnLabel={returnLabel}
|
|
321
360
|
departureLabel={departureLabel}
|
|
322
361
|
outerContainerStyle={[
|
|
323
|
-
styles.dateRangePickerOuterContainer,
|
|
362
|
+
styles.dateRangePickerOuterContainer,
|
|
324
363
|
dateRangePickerOuterContainerStyle,
|
|
325
364
|
]}
|
|
365
|
+
inputContainerStyle={dateRangePickerInputContainerStyle}
|
|
326
366
|
labelStyle={[labelStyle, dateRangePickerLabelStyle]}
|
|
327
367
|
inputGroupStyle={dateRangePickerInputGroupStyle}
|
|
328
|
-
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
329
|
-
calendarThemeOverrides={calendarThemeOverrides}
|
|
368
|
+
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
369
|
+
calendarThemeOverrides={calendarThemeOverrides}
|
|
330
370
|
onDatesChange={(d) => {
|
|
331
371
|
setDepartureDate(d.departure);
|
|
332
372
|
setReturnDate(d.return);
|
|
@@ -336,18 +376,20 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
336
376
|
initialReturnDate={initialReturnDate}
|
|
337
377
|
/>
|
|
338
378
|
{/* Search Button */}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
379
|
+
{onSearchPress && (
|
|
380
|
+
<TouchableOpacity
|
|
381
|
+
style={[styles.searchButton, searchButtonStyle]}
|
|
382
|
+
onPress={handleSearch}
|
|
383
|
+
activeOpacity={0.8}
|
|
384
|
+
>
|
|
385
|
+
<Ionicons
|
|
386
|
+
name={searchIconName}
|
|
387
|
+
size={24}
|
|
388
|
+
color={theme.onPrimary}
|
|
389
|
+
style={searchIconStyle}
|
|
390
|
+
/>
|
|
391
|
+
</TouchableOpacity>
|
|
392
|
+
)}
|
|
351
393
|
</View>
|
|
352
394
|
</View>
|
|
353
395
|
);
|
|
@@ -363,11 +405,11 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
363
405
|
borderBottomLeftRadius: 8,
|
|
364
406
|
},
|
|
365
407
|
inputGroupContainer: {
|
|
366
|
-
position: "relative",
|
|
408
|
+
position: "relative",
|
|
367
409
|
},
|
|
368
410
|
inputWrapper: {
|
|
369
|
-
marginBottom: 15,
|
|
370
|
-
position: "relative",
|
|
411
|
+
marginBottom: 15,
|
|
412
|
+
position: "relative",
|
|
371
413
|
},
|
|
372
414
|
label: {
|
|
373
415
|
color: theme.labelText,
|
|
@@ -399,12 +441,12 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
399
441
|
},
|
|
400
442
|
departureRow: {
|
|
401
443
|
flexDirection: isRTL ? "row-reverse" : "row",
|
|
402
|
-
alignItems: "flex-end",
|
|
444
|
+
alignItems: "flex-end",
|
|
403
445
|
marginTop: 10,
|
|
404
|
-
gap: 10,
|
|
446
|
+
gap: 10,
|
|
405
447
|
},
|
|
406
448
|
dateRangePickerOuterContainer: {
|
|
407
|
-
flex: 1,
|
|
449
|
+
flex: 1,
|
|
408
450
|
},
|
|
409
451
|
searchButton: {
|
|
410
452
|
backgroundColor: theme.primary,
|
|
@@ -419,16 +461,15 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
419
461
|
paddingHorizontal: 12,
|
|
420
462
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
421
463
|
borderBottomColor: theme.border,
|
|
422
|
-
backgroundColor: theme.surface,
|
|
464
|
+
backgroundColor: theme.surface,
|
|
423
465
|
},
|
|
424
466
|
suggestionCityRow: {
|
|
425
467
|
flexDirection: "row",
|
|
426
468
|
alignItems: "center",
|
|
427
|
-
gap: 10,
|
|
428
|
-
marginBottom: 5,
|
|
429
|
-
},
|
|
430
|
-
suggestionCityIcon: {
|
|
469
|
+
gap: 10,
|
|
470
|
+
marginBottom: 5,
|
|
431
471
|
},
|
|
472
|
+
suggestionCityIcon: {},
|
|
432
473
|
suggestionCityText: {
|
|
433
474
|
fontSize: 15,
|
|
434
475
|
fontWeight: "600",
|
|
@@ -437,15 +478,14 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
437
478
|
suggestionAirportTouchable: {
|
|
438
479
|
flexDirection: "row",
|
|
439
480
|
alignItems: "center",
|
|
440
|
-
gap: 10,
|
|
481
|
+
gap: 10,
|
|
441
482
|
paddingVertical: 4,
|
|
442
|
-
marginLeft: 25,
|
|
443
|
-
},
|
|
444
|
-
suggestionAirportIcon: {
|
|
483
|
+
marginLeft: 25,
|
|
445
484
|
},
|
|
485
|
+
suggestionAirportIcon: {},
|
|
446
486
|
suggestionAirportText: {
|
|
447
487
|
fontSize: 14,
|
|
448
|
-
color: theme.onSurface,
|
|
488
|
+
color: theme.onSurface,
|
|
449
489
|
},
|
|
450
490
|
});
|
|
451
491
|
|
|
@@ -221,7 +221,9 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
221
221
|
label?: string
|
|
222
222
|
) => (
|
|
223
223
|
<View>
|
|
224
|
-
<Text
|
|
224
|
+
<Text style={{ color: theme.labelText, fontSize: 12, marginBottom: 6 }}>
|
|
225
|
+
{label}
|
|
226
|
+
</Text>
|
|
225
227
|
<View style={[styles.buttonGroupContainer, buttonGroupContainerStyle]}>
|
|
226
228
|
{items.map((item) => {
|
|
227
229
|
const isSelected = item === selectedValue;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ThemeType, useTheme } from "../../theme";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
3
9
|
import {
|
|
4
10
|
View,
|
|
5
11
|
Text,
|
|
@@ -15,9 +21,10 @@ import { Ionicons } from "@expo/vector-icons";
|
|
|
15
21
|
import CustomInput from "../Input/Input";
|
|
16
22
|
import DateRangePicker from "../DateRangePicker/DateRangePicker";
|
|
17
23
|
import { Picker } from "@react-native-picker/picker";
|
|
18
|
-
import SuggestionList from "../Suggestions/SuggestionList";
|
|
19
|
-
import { FormInputType, HotelSuggestions } from "./types";
|
|
24
|
+
import SuggestionList from "../Suggestions/SuggestionList";
|
|
25
|
+
import { FormInputType, HotelSuggestions } from "./types";
|
|
20
26
|
import { TextInput } from "react-native-gesture-handler";
|
|
27
|
+
import RNPickerSelect from "react-native-picker-select";
|
|
21
28
|
|
|
22
29
|
// --- Helper Types ---
|
|
23
30
|
type LocationData = string;
|
|
@@ -40,6 +47,13 @@ export interface HotelFormProps {
|
|
|
40
47
|
nationality: string | undefined;
|
|
41
48
|
}) => void;
|
|
42
49
|
|
|
50
|
+
onSelectionChange?: (details: {
|
|
51
|
+
destination: LocationData | undefined; // Renamed from destintation
|
|
52
|
+
checkin: string | undefined; // Send YYYY-MM-DD
|
|
53
|
+
checkout: string | undefined; // Send YYYY-MM-DD
|
|
54
|
+
nationality: string | undefined;
|
|
55
|
+
}) => void;
|
|
56
|
+
|
|
43
57
|
// Labels & Placeholders
|
|
44
58
|
destinationLabel?: string;
|
|
45
59
|
destinationPlaceholder?: string;
|
|
@@ -52,23 +66,24 @@ export interface HotelFormProps {
|
|
|
52
66
|
|
|
53
67
|
// Data & Config
|
|
54
68
|
suggestionData?: HotelSuggestions[];
|
|
55
|
-
nationalityData?: { label: string; value: string }[];
|
|
69
|
+
nationalityData?: { label: string; value: string }[];
|
|
56
70
|
calendarThemeOverrides?: object;
|
|
57
71
|
|
|
58
72
|
// --- Style Props ---
|
|
59
73
|
containerStyle?: StyleProp<ViewStyle>;
|
|
60
|
-
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
74
|
+
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
61
75
|
customInputContainerStyle?: StyleProp<ViewStyle>;
|
|
62
|
-
labelStyle?: StyleProp<TextStyle>;
|
|
63
|
-
checkoutRowStyle?: StyleProp<ViewStyle>;
|
|
76
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
77
|
+
checkoutRowStyle?: StyleProp<ViewStyle>;
|
|
64
78
|
searchButtonStyle?: StyleProp<ViewStyle>;
|
|
65
|
-
searchIconStyle?: StyleProp<TextStyle>;
|
|
79
|
+
searchIconStyle?: StyleProp<TextStyle>;
|
|
66
80
|
|
|
67
81
|
// DateRangePicker specific styles (passed down)
|
|
68
82
|
dateRangePickerOuterContainerStyle?: StyleProp<ViewStyle>;
|
|
69
|
-
dateRangePickerLabelStyle?: StyleProp<TextStyle>;
|
|
70
|
-
dateRangePickerInputGroupStyle?: StyleProp<ViewStyle>;
|
|
83
|
+
dateRangePickerLabelStyle?: StyleProp<TextStyle>;
|
|
84
|
+
dateRangePickerInputGroupStyle?: StyleProp<ViewStyle>;
|
|
71
85
|
dateRangePickerCalendarContainerStyle?: StyleProp<ViewStyle>;
|
|
86
|
+
dateRangePickerInputContainerStyle?: StyleProp<ViewStyle>;
|
|
72
87
|
|
|
73
88
|
// SuggestionList specific styles
|
|
74
89
|
suggestionListContainerStyle?: StyleProp<ViewStyle>;
|
|
@@ -76,23 +91,22 @@ export interface HotelFormProps {
|
|
|
76
91
|
suggestionItemTextStyle?: StyleProp<TextStyle>;
|
|
77
92
|
|
|
78
93
|
// Nationality Picker specific styles
|
|
79
|
-
nationalityPickerWrapperStyle?: StyleProp<ViewStyle>;
|
|
80
|
-
nationalityPickerLabelStyle?: StyleProp<TextStyle>;
|
|
94
|
+
nationalityPickerWrapperStyle?: StyleProp<ViewStyle>;
|
|
95
|
+
nationalityPickerLabelStyle?: StyleProp<TextStyle>;
|
|
96
|
+
nationalityPickerPlaceholderColor?: string;
|
|
97
|
+
nationalityPickerPlaceholder?: string;
|
|
81
98
|
pickerContainerStyle?: StyleProp<ViewStyle>;
|
|
82
|
-
pickerStyle?: StyleProp<TextStyle>;
|
|
99
|
+
pickerStyle?: StyleProp<TextStyle>;
|
|
83
100
|
}
|
|
84
101
|
|
|
85
|
-
// Default Nationality Data (can be overridden by prop)
|
|
86
102
|
const defaultNationalities = [
|
|
87
|
-
{ label: "Select Nationality", value: undefined }, // Placeholder
|
|
88
103
|
{ label: "United States", value: "US" },
|
|
89
104
|
{ label: "Canada", value: "CA" },
|
|
90
|
-
{ label: "United Kingdom", value: "GB" },
|
|
105
|
+
{ label: "United Kingdom", value: "GB" },
|
|
91
106
|
{ label: "India", value: "IN" },
|
|
92
107
|
{ label: "Australia", value: "AU" },
|
|
93
108
|
{ label: "Germany", value: "DE" },
|
|
94
109
|
{ label: "France", value: "FR" },
|
|
95
|
-
// Add more common nationalities or let user provide full list via props
|
|
96
110
|
];
|
|
97
111
|
|
|
98
112
|
// --- Component ---
|
|
@@ -137,6 +151,10 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
137
151
|
nationalityPickerLabelStyle,
|
|
138
152
|
pickerContainerStyle,
|
|
139
153
|
pickerStyle,
|
|
154
|
+
onSelectionChange,
|
|
155
|
+
dateRangePickerInputContainerStyle,
|
|
156
|
+
nationalityPickerPlaceholderColor,
|
|
157
|
+
nationalityPickerPlaceholder = "Select Nationality...",
|
|
140
158
|
}) => {
|
|
141
159
|
const { theme, isRTL } = useTheme();
|
|
142
160
|
const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]);
|
|
@@ -158,6 +176,21 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
158
176
|
>(initialNationality);
|
|
159
177
|
const [focusedInput, setFocusedInput] = useState<FormInputType>();
|
|
160
178
|
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
onSelectionChange?.({
|
|
181
|
+
destination: destination,
|
|
182
|
+
checkin: checkinDate,
|
|
183
|
+
checkout: checkoutDate,
|
|
184
|
+
nationality: selectedNationality,
|
|
185
|
+
});
|
|
186
|
+
}, [
|
|
187
|
+
destination,
|
|
188
|
+
checkinDate,
|
|
189
|
+
checkoutDate,
|
|
190
|
+
selectedNationality,
|
|
191
|
+
onSelectionChange,
|
|
192
|
+
]);
|
|
193
|
+
|
|
161
194
|
// --- Handlers ---
|
|
162
195
|
const handleSearch = useCallback(() => {
|
|
163
196
|
onSearchPress?.({
|
|
@@ -215,7 +248,7 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
215
248
|
}
|
|
216
249
|
}, 150);
|
|
217
250
|
}}
|
|
218
|
-
|
|
251
|
+
inputContainerStyle={customInputContainerStyle}
|
|
219
252
|
/>
|
|
220
253
|
{suggestionData && (
|
|
221
254
|
<SuggestionList
|
|
@@ -235,9 +268,10 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
235
268
|
dateRangePickerOuterContainerStyle,
|
|
236
269
|
]}
|
|
237
270
|
labelStyle={[labelStyle, dateRangePickerLabelStyle]}
|
|
271
|
+
inputContainerStyle={dateRangePickerInputContainerStyle}
|
|
238
272
|
inputGroupStyle={dateRangePickerInputGroupStyle}
|
|
239
|
-
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
240
|
-
calendarThemeOverrides={calendarThemeOverrides}
|
|
273
|
+
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
274
|
+
calendarThemeOverrides={calendarThemeOverrides}
|
|
241
275
|
onDatesChange={(d) => {
|
|
242
276
|
setCheckinDate(d.departure);
|
|
243
277
|
setCheckoutDate(d.return);
|
|
@@ -249,48 +283,40 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
249
283
|
|
|
250
284
|
<View style={[styles.checkoutRow, checkoutRowStyle]}>
|
|
251
285
|
<View
|
|
252
|
-
style={[
|
|
286
|
+
style={[
|
|
287
|
+
styles.nationalityPickerWrapper,
|
|
288
|
+
nationalityPickerWrapperStyle,
|
|
289
|
+
]}
|
|
253
290
|
>
|
|
254
|
-
<Text
|
|
255
|
-
style={[
|
|
256
|
-
styles.label,
|
|
257
|
-
labelStyle,
|
|
258
|
-
nationalityPickerLabelStyle,
|
|
259
|
-
]}
|
|
260
|
-
>
|
|
291
|
+
<Text style={[styles.label, labelStyle, nationalityPickerLabelStyle]}>
|
|
261
292
|
{nationalityLabel}
|
|
262
293
|
</Text>
|
|
263
294
|
<View style={[styles.pickerContainer, pickerContainerStyle]}>
|
|
264
|
-
<
|
|
265
|
-
|
|
295
|
+
<RNPickerSelect
|
|
296
|
+
items={nationalityData}
|
|
266
297
|
onValueChange={setSelectedNationality}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
key={nat.value || "placeholder"}
|
|
273
|
-
label={nat.label}
|
|
274
|
-
value={nat.value}
|
|
275
|
-
enabled={nat.value !== undefined}
|
|
276
|
-
/>
|
|
277
|
-
))}
|
|
278
|
-
</Picker>
|
|
298
|
+
placeholder={{
|
|
299
|
+
label: nationalityPickerPlaceholder,
|
|
300
|
+
color: nationalityPickerPlaceholderColor,
|
|
301
|
+
}}
|
|
302
|
+
/>
|
|
279
303
|
</View>
|
|
280
304
|
</View>
|
|
281
305
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
306
|
+
{onSearchPress && (
|
|
307
|
+
<TouchableOpacity
|
|
308
|
+
style={[styles.searchButton, searchButtonStyle]}
|
|
309
|
+
onPress={handleSearch}
|
|
310
|
+
activeOpacity={0.8}
|
|
311
|
+
>
|
|
312
|
+
<Ionicons
|
|
313
|
+
name={searchIconName}
|
|
314
|
+
size={24}
|
|
315
|
+
color={theme.onPrimary}
|
|
316
|
+
style={searchIconStyle}
|
|
317
|
+
/>
|
|
318
|
+
</TouchableOpacity>
|
|
319
|
+
)}
|
|
294
320
|
</View>
|
|
295
321
|
</View>
|
|
296
322
|
);
|
|
@@ -306,8 +332,8 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
306
332
|
borderBottomLeftRadius: 8,
|
|
307
333
|
},
|
|
308
334
|
inputWrapper: {
|
|
309
|
-
marginBottom: 15,
|
|
310
|
-
position: "relative",
|
|
335
|
+
marginBottom: 15,
|
|
336
|
+
position: "relative",
|
|
311
337
|
},
|
|
312
338
|
label: {
|
|
313
339
|
color: theme.labelText,
|
|
@@ -318,12 +344,12 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
318
344
|
marginBottom: 6,
|
|
319
345
|
},
|
|
320
346
|
dateRangePickerOuterContainer: {
|
|
321
|
-
marginTop: 10,
|
|
347
|
+
marginTop: 10,
|
|
322
348
|
},
|
|
323
349
|
checkoutRow: {
|
|
324
350
|
flexDirection: isRTL ? "row-reverse" : "row",
|
|
325
|
-
alignItems: "flex-end",
|
|
326
|
-
marginTop: 20,
|
|
351
|
+
alignItems: "flex-end",
|
|
352
|
+
marginTop: 20,
|
|
327
353
|
gap: 10,
|
|
328
354
|
},
|
|
329
355
|
nationalityPickerWrapper: {
|
|
@@ -334,8 +360,8 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
334
360
|
borderColor: theme.border,
|
|
335
361
|
borderRadius: 8,
|
|
336
362
|
backgroundColor: theme.surface,
|
|
337
|
-
justifyContent: "center",
|
|
338
|
-
height: 50,
|
|
363
|
+
justifyContent: "center",
|
|
364
|
+
height: 50,
|
|
339
365
|
},
|
|
340
366
|
picker: {
|
|
341
367
|
width: "100%",
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { registerRootComponent } from 'expo';
|
|
2
|
-
import "react-native-reanimated";
|
|
1
|
+
// import { registerRootComponent } from 'expo';
|
|
2
|
+
// import "react-native-reanimated";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
import App from "./app";
|
|
5
|
+
// import App from "./app";
|
|
6
6
|
|
|
7
|
-
registerRootComponent(App);
|
|
7
|
+
// registerRootComponent(App);
|
|
8
8
|
|
|
9
9
|
export * from "./theme"
|
|
10
10
|
export * from "./components";
|
|
11
|
-
export * from "./contexts";
|
|
11
|
+
export * from "./contexts";
|