react-native-country-select 0.2.1 → 0.2.3
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/README.md +32 -29
- package/lib/components/CountryItem/index.tsx +5 -32
- package/lib/components/CountrySelect/index.tsx +81 -79
- package/lib/components/styles.js +39 -38
- package/lib/interface/countryItemProps.ts +0 -1
- package/lib/interface/countrySelectProps.ts +3 -0
- package/lib/interface/countrySelectStyles.ts +5 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -248,35 +248,38 @@ export default function App() {
|
|
|
248
248
|
|
|
249
249
|
## CountrySelect Props
|
|
250
250
|
|
|
251
|
-
| Prop | Type | Required | Default | Description
|
|
252
|
-
| ---------------------------- | ----------------------------------------------------------------------- | -------- | -------------------- |
|
|
253
|
-
| visible | boolean | Yes | false | Controls the visibility of the country picker modal
|
|
254
|
-
| onClose | () => void | Yes | - | Callback function called when the modal is closed
|
|
255
|
-
| onSelect | (country: [ICountry](lib/interfaces/country.ts)) => void | Yes | - | Callback function called when a country is selected
|
|
256
|
-
| modalType | 'bottomSheet' \| 'popup' | No | 'bottomSheet' | Type of modal to display
|
|
257
|
-
| countrySelectStyle | [ICountrySelectStyle](lib/interfaces/countrySelectStyles.ts) | No | - | Custom styles for the country picker
|
|
258
|
-
| isFullScreen | boolean | No | false | Whether the modal should be full screen
|
|
259
|
-
| popularCountries | string[] | No | [] | Array of country codes to show in popular section
|
|
260
|
-
| visibleCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to show (whitelist)
|
|
261
|
-
| hiddenCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to hide (blacklist)
|
|
262
|
-
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker
|
|
263
|
-
| language | [ICountrySelectLanguages](lib/interfaces/countrySelectLanguages.ts) | No | 'eng' | Language for country names (see supported languages below)
|
|
264
|
-
| showSearchInput | boolean | No | true | Whether to show the search input field
|
|
265
|
-
| searchPlaceholder | string | No | 'Search country...' | Placeholder text for search input
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
|
|
|
273
|
-
|
|
|
274
|
-
|
|
|
275
|
-
|
|
|
276
|
-
|
|
|
277
|
-
|
|
|
278
|
-
|
|
|
279
|
-
|
|
|
251
|
+
| Prop | Type | Required | Default | Description |
|
|
252
|
+
| ---------------------------- | ----------------------------------------------------------------------- | -------- | -------------------- | ---------------------------------------------------------------- |
|
|
253
|
+
| visible | boolean | Yes | false | Controls the visibility of the country picker modal |
|
|
254
|
+
| onClose | () => void | Yes | - | Callback function called when the modal is closed |
|
|
255
|
+
| onSelect | (country: [ICountry](lib/interfaces/country.ts)) => void | Yes | - | Callback function called when a country is selected |
|
|
256
|
+
| modalType | 'bottomSheet' \| 'popup' | No | 'bottomSheet' | Type of modal to display |
|
|
257
|
+
| countrySelectStyle | [ICountrySelectStyle](lib/interfaces/countrySelectStyles.ts) | No | - | Custom styles for the country picker |
|
|
258
|
+
| isFullScreen | boolean | No | false | Whether the modal should be full screen |
|
|
259
|
+
| popularCountries | string[] | No | [] | Array of country codes to show in popular section |
|
|
260
|
+
| visibleCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to show (whitelist) |
|
|
261
|
+
| hiddenCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to hide (blacklist) |
|
|
262
|
+
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker |
|
|
263
|
+
| language | [ICountrySelectLanguages](lib/interfaces/countrySelectLanguages.ts) | No | 'eng' | Language for country names (see supported languages below) |
|
|
264
|
+
| showSearchInput | boolean | No | true | Whether to show the search input field |
|
|
265
|
+
| searchPlaceholder | string | No | 'Search country...' | Placeholder text for search input |
|
|
266
|
+
| searchPlaceholderTextColor | string | No | '#00000080' | Placeholder text color for search input |
|
|
267
|
+
| searchSelectionColor | string | No | default | Highlight, selection handle and cursor color of the search input |
|
|
268
|
+
| minBottomsheetHeight | number \| string | No | 30% | Minimum height for bottom sheet modal |
|
|
269
|
+
| maxBottomsheetHeight | number \| string | No | 80% | Maximum height for bottom sheet modal |
|
|
270
|
+
| initialBottomsheetHeight | number \| string | No | 50% | Initial height for bottom sheet modal |
|
|
271
|
+
| disabledBackdropPress | boolean | No | false | Whether to disable backdrop press to close |
|
|
272
|
+
| removedBackdrop | boolean | No | false | Whether to remove the backdrop completely |
|
|
273
|
+
| onBackdropPress | () => void | No | - | Custom callback for backdrop press |
|
|
274
|
+
| dragHandleIndicatorComponent | () => ReactElement | - | - | Custom component for drag handle indicator on bottom sheet |
|
|
275
|
+
| countryItemComponent | (item: [ICountry](lib/interfaces/country.ts)) => ReactElement | No | - | Custom component for country items |
|
|
276
|
+
| sectionTitleComponent | (item: [ISectionTitle](lib/interfaces/sectionTitle.ts)) => ReactElement | No | - | Custom component for section titles |
|
|
277
|
+
| closeButtonComponent | () => ReactElement | No | - | Custom component for closeButton |
|
|
278
|
+
| showCloseButton | boolean | No | false | Whether to show the close button |
|
|
279
|
+
| popularCountriesTitle | string | No | 'Popular Countries' | Popular Countries section title |
|
|
280
|
+
| allCountriesTitle | string | No | 'All Countries' | All Countries section title |
|
|
281
|
+
| showsVerticalScrollIndicator | boolean | No | false | Displays a horizontal scroll indicator |
|
|
282
|
+
| countryNotFoundMessage | string | No | "No countries found" | Country not found in search |
|
|
280
283
|
|
|
281
284
|
<br>
|
|
282
285
|
|
|
@@ -13,7 +13,6 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
13
13
|
onClose,
|
|
14
14
|
theme = 'light',
|
|
15
15
|
language,
|
|
16
|
-
modalType,
|
|
17
16
|
countrySelectStyle,
|
|
18
17
|
}) => {
|
|
19
18
|
const styles = createStyles(theme);
|
|
@@ -24,51 +23,25 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
24
23
|
accessibilityRole="button"
|
|
25
24
|
accessibilityLabel="Country Select Item"
|
|
26
25
|
accessibilityHint="Click to select a country"
|
|
27
|
-
style={[
|
|
28
|
-
styles.countryItem,
|
|
29
|
-
modalType === 'popup'
|
|
30
|
-
? countrySelectStyle?.popup?.countryItem
|
|
31
|
-
: countrySelectStyle?.bottomSheet?.countryItem,
|
|
32
|
-
]}
|
|
26
|
+
style={[styles.countryItem, countrySelectStyle?.countryItem]}
|
|
33
27
|
onPress={() => {
|
|
34
28
|
onSelect(item);
|
|
35
29
|
onClose();
|
|
36
30
|
}}>
|
|
37
31
|
<Text
|
|
38
32
|
testID="countrySelectItemFlag"
|
|
39
|
-
style={[
|
|
40
|
-
styles.flag,
|
|
41
|
-
modalType === 'popup'
|
|
42
|
-
? countrySelectStyle?.popup?.flag
|
|
43
|
-
: countrySelectStyle?.bottomSheet?.flag,
|
|
44
|
-
]}>
|
|
33
|
+
style={[styles.flag, countrySelectStyle?.flag]}>
|
|
45
34
|
{item.flag || item.cca2}
|
|
46
35
|
</Text>
|
|
47
|
-
<View
|
|
48
|
-
style={[
|
|
49
|
-
styles.countryInfo,
|
|
50
|
-
modalType === 'popup'
|
|
51
|
-
? countrySelectStyle?.popup?.countryInfo
|
|
52
|
-
: countrySelectStyle?.bottomSheet?.countryInfo,
|
|
53
|
-
]}>
|
|
36
|
+
<View style={[styles.countryInfo, countrySelectStyle?.countryInfo]}>
|
|
54
37
|
<Text
|
|
55
38
|
testID="countrySelectItemCallingCode"
|
|
56
|
-
style={[
|
|
57
|
-
styles.callingCode,
|
|
58
|
-
modalType === 'popup'
|
|
59
|
-
? countrySelectStyle?.popup?.callingCode
|
|
60
|
-
: countrySelectStyle?.bottomSheet?.callingCode,
|
|
61
|
-
]}>
|
|
39
|
+
style={[styles.callingCode, countrySelectStyle?.callingCode]}>
|
|
62
40
|
{item.idd.root}
|
|
63
41
|
</Text>
|
|
64
42
|
<Text
|
|
65
43
|
testID="countrySelectItemName"
|
|
66
|
-
style={[
|
|
67
|
-
styles.countryName,
|
|
68
|
-
modalType === 'popup'
|
|
69
|
-
? countrySelectStyle?.popup?.countryName
|
|
70
|
-
: countrySelectStyle?.bottomSheet?.countryName,
|
|
71
|
-
]}>
|
|
44
|
+
style={[styles.countryName, countrySelectStyle?.countryName]}>
|
|
72
45
|
{item?.translations[language]?.common ||
|
|
73
46
|
item?.translations[DEFAULT_LANGUAGE]?.common}
|
|
74
47
|
</Text>
|
|
@@ -52,6 +52,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
52
52
|
language = DEFAULT_LANGUAGE,
|
|
53
53
|
showSearchInput = true,
|
|
54
54
|
searchPlaceholder,
|
|
55
|
+
searchPlaceholderTextColor,
|
|
56
|
+
searchSelectionColor,
|
|
55
57
|
showCloseButton = false,
|
|
56
58
|
minBottomsheetHeight,
|
|
57
59
|
maxBottomsheetHeight,
|
|
@@ -59,6 +61,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
59
61
|
disabledBackdropPress,
|
|
60
62
|
removedBackdrop,
|
|
61
63
|
onBackdropPress,
|
|
64
|
+
dragHandleIndicatorComponent,
|
|
62
65
|
sectionTitleComponent,
|
|
63
66
|
countryItemComponent,
|
|
64
67
|
closeButtonComponent,
|
|
@@ -68,15 +71,15 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
68
71
|
countryNotFoundMessage,
|
|
69
72
|
...props
|
|
70
73
|
}) => {
|
|
71
|
-
const
|
|
72
|
-
const styles = createStyles(theme);
|
|
74
|
+
const [modalHeight, setModalHeight] = useState(useWindowDimensions().height);
|
|
75
|
+
const styles = createStyles(theme, modalType, isFullScreen);
|
|
73
76
|
|
|
74
77
|
const [searchQuery, setSearchQuery] = useState('');
|
|
75
78
|
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
|
|
76
79
|
const [bottomSheetSize, setBottomSheetSize] = useState({
|
|
77
|
-
minHeight: MIN_HEIGHT_PERCENTAGE *
|
|
78
|
-
maxHeight: MAX_HEIGHT_PERCENTAGE *
|
|
79
|
-
initialHeight: INITIAL_HEIGHT_PERCENTAGE *
|
|
80
|
+
minHeight: MIN_HEIGHT_PERCENTAGE * modalHeight,
|
|
81
|
+
maxHeight: MAX_HEIGHT_PERCENTAGE * modalHeight,
|
|
82
|
+
initialHeight: INITIAL_HEIGHT_PERCENTAGE * modalHeight,
|
|
80
83
|
});
|
|
81
84
|
|
|
82
85
|
const sheetHeight = useRef(
|
|
@@ -91,7 +94,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
const DRAG_HANDLE_HEIGHT = 20;
|
|
94
|
-
const availableHeight =
|
|
97
|
+
const availableHeight = modalHeight - DRAG_HANDLE_HEIGHT;
|
|
95
98
|
|
|
96
99
|
const parsedMinHeight = parseHeight(minBottomsheetHeight, availableHeight);
|
|
97
100
|
const parsedMaxHeight = parseHeight(maxBottomsheetHeight, availableHeight);
|
|
@@ -110,7 +113,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
110
113
|
minBottomsheetHeight,
|
|
111
114
|
maxBottomsheetHeight,
|
|
112
115
|
initialBottomsheetHeight,
|
|
113
|
-
|
|
116
|
+
modalHeight,
|
|
114
117
|
modalType,
|
|
115
118
|
]);
|
|
116
119
|
|
|
@@ -132,12 +135,10 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
if (isKeyboardVisible) {
|
|
135
|
-
sheetHeight.setValue(
|
|
136
|
-
parseHeight(bottomSheetSize.maxHeight, windowHeight),
|
|
137
|
-
);
|
|
138
|
+
sheetHeight.setValue(parseHeight(bottomSheetSize.maxHeight, modalHeight));
|
|
138
139
|
lastHeight.current = bottomSheetSize.maxHeight;
|
|
139
140
|
} else {
|
|
140
|
-
sheetHeight.setValue(parseHeight(lastHeight.current,
|
|
141
|
+
sheetHeight.setValue(parseHeight(lastHeight.current, modalHeight));
|
|
141
142
|
}
|
|
142
143
|
}, [isKeyboardVisible, modalType]);
|
|
143
144
|
|
|
@@ -263,21 +264,29 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
263
264
|
const getCountries = useMemo(() => {
|
|
264
265
|
const query = searchQuery.toLowerCase();
|
|
265
266
|
|
|
266
|
-
|
|
267
|
-
let countriesData = countries as unknown as ICountry[];
|
|
267
|
+
let countriesData = countries as unknown as ICountry[];
|
|
268
268
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
if (visibleCountries.length > 0 && hiddenCountries.length > 0) {
|
|
270
|
+
countriesData = (countries as unknown as ICountry[]).filter(
|
|
271
|
+
country =>
|
|
272
|
+
visibleCountries.includes(country.cca2) &&
|
|
273
|
+
!hiddenCountries.includes(country.cca2),
|
|
274
|
+
);
|
|
275
|
+
}
|
|
274
276
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
if (visibleCountries.length > 0 && hiddenCountries.length === 0) {
|
|
278
|
+
countriesData = (countries as unknown as ICountry[]).filter(country =>
|
|
279
|
+
visibleCountries.includes(country.cca2),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
280
282
|
|
|
283
|
+
if (hiddenCountries.length > 0 && visibleCountries.length === 0) {
|
|
284
|
+
countriesData = (countries as unknown as ICountry[]).filter(
|
|
285
|
+
country => !hiddenCountries.includes(country.cca2),
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (query.length > 0) {
|
|
281
290
|
const filteredCountries = countriesData.filter(country => {
|
|
282
291
|
const countryName = getCountryNameInLanguage(country);
|
|
283
292
|
const normalizedCountryName = normalizeCountryName(
|
|
@@ -300,26 +309,12 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
300
309
|
return sortCountriesAlphabetically(filteredCountries);
|
|
301
310
|
}
|
|
302
311
|
|
|
303
|
-
let allCountries = countries as unknown as ICountry[];
|
|
304
|
-
|
|
305
|
-
if (visibleCountries.length > 0) {
|
|
306
|
-
allCountries = (countries as unknown as ICountry[]).filter(country =>
|
|
307
|
-
visibleCountries.includes(country.cca2),
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (hiddenCountries.length > 0) {
|
|
312
|
-
allCountries = (countries as unknown as ICountry[]).filter(
|
|
313
|
-
country => !hiddenCountries.includes(country.cca2),
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
312
|
const popularCountriesData = sortCountriesAlphabetically(
|
|
318
|
-
|
|
313
|
+
countriesData.filter(country => popularCountries.includes(country.cca2)),
|
|
319
314
|
);
|
|
320
315
|
|
|
321
316
|
const otherCountriesData = sortCountriesAlphabetically(
|
|
322
|
-
|
|
317
|
+
countriesData.filter(country => !popularCountries.includes(country.cca2)),
|
|
323
318
|
);
|
|
324
319
|
|
|
325
320
|
const result: IListItem[] = [];
|
|
@@ -388,14 +383,11 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
388
383
|
accessibilityRole="button"
|
|
389
384
|
accessibilityLabel="Country Select Modal Close Button"
|
|
390
385
|
accessibilityHint="Click to close the Country Select modal"
|
|
391
|
-
style={[styles.closeButton, countrySelectStyle?.
|
|
386
|
+
style={[styles.closeButton, countrySelectStyle?.closeButton]}
|
|
392
387
|
activeOpacity={0.6}
|
|
393
388
|
onPress={onClose}>
|
|
394
389
|
<Text
|
|
395
|
-
style={[
|
|
396
|
-
styles.closeButtonText,
|
|
397
|
-
countrySelectStyle?.popup?.closeButtonText,
|
|
398
|
-
]}>
|
|
390
|
+
style={[styles.closeButtonText, countrySelectStyle?.closeButtonText]}>
|
|
399
391
|
{'\u00D7'}
|
|
400
392
|
</Text>
|
|
401
393
|
</TouchableOpacity>
|
|
@@ -409,22 +401,16 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
409
401
|
accessibilityRole="text"
|
|
410
402
|
accessibilityLabel="Country Select Search Input"
|
|
411
403
|
accessibilityHint="Type to search for a country"
|
|
412
|
-
style={[
|
|
413
|
-
styles.searchInput,
|
|
414
|
-
modalType === 'popup'
|
|
415
|
-
? countrySelectStyle?.popup?.searchInput
|
|
416
|
-
: countrySelectStyle?.bottomSheet?.searchInput,
|
|
417
|
-
]}
|
|
404
|
+
style={[styles.searchInput, countrySelectStyle?.searchInput]}
|
|
418
405
|
placeholder={
|
|
419
406
|
searchPlaceholder ||
|
|
420
407
|
translations.searchPlaceholder[language as ICountrySelectLanguages]
|
|
421
408
|
}
|
|
422
409
|
placeholderTextColor={
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
: countrySelectStyle?.bottomSheet?.searchInputPlaceholder?.color) ||
|
|
426
|
-
styles.searchInputPlaceholder.color
|
|
410
|
+
searchPlaceholderTextColor ||
|
|
411
|
+
(theme === 'dark' ? '#FFFFFF80' : '#00000080')
|
|
427
412
|
}
|
|
413
|
+
selectionColor={searchSelectionColor}
|
|
428
414
|
value={searchQuery}
|
|
429
415
|
onChangeText={setSearchQuery}
|
|
430
416
|
/>
|
|
@@ -437,16 +423,12 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
437
423
|
<View
|
|
438
424
|
style={[
|
|
439
425
|
styles.countryNotFoundContainer,
|
|
440
|
-
|
|
441
|
-
? countrySelectStyle?.popup?.countryNotFoundContainer
|
|
442
|
-
: countrySelectStyle?.bottomSheet?.countryNotFoundContainer,
|
|
426
|
+
countrySelectStyle?.countryNotFoundContainer,
|
|
443
427
|
]}>
|
|
444
428
|
<Text
|
|
445
429
|
style={[
|
|
446
430
|
styles.countryNotFoundMessage,
|
|
447
|
-
|
|
448
|
-
? countrySelectStyle?.popup?.countryNotFoundMessage
|
|
449
|
-
: countrySelectStyle?.bottomSheet?.countryNotFoundMessage,
|
|
431
|
+
countrySelectStyle?.countryNotFoundMessage,
|
|
450
432
|
]}>
|
|
451
433
|
{countryNotFoundMessage ||
|
|
452
434
|
translations.searchNotFoundMessage[
|
|
@@ -482,12 +464,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
482
464
|
<Text
|
|
483
465
|
testID="countrySelectSectionTitle"
|
|
484
466
|
accessibilityRole="header"
|
|
485
|
-
style={[
|
|
486
|
-
styles.sectionTitle,
|
|
487
|
-
modalType === 'popup'
|
|
488
|
-
? countrySelectStyle?.popup?.sectionTitle
|
|
489
|
-
: countrySelectStyle?.bottomSheet?.sectionTitle,
|
|
490
|
-
]}>
|
|
467
|
+
style={[styles.sectionTitle, countrySelectStyle?.sectionTitle]}>
|
|
491
468
|
{popularCountriesTitle && index === 0
|
|
492
469
|
? popularCountriesTitle
|
|
493
470
|
: allCountriesTitle && index > 0
|
|
@@ -508,7 +485,6 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
508
485
|
onClose={onClose}
|
|
509
486
|
theme={theme}
|
|
510
487
|
language={language}
|
|
511
|
-
modalType={modalType}
|
|
512
488
|
countrySelectStyle={countrySelectStyle}
|
|
513
489
|
/>
|
|
514
490
|
);
|
|
@@ -541,14 +517,14 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
541
517
|
style={[
|
|
542
518
|
styles.backdrop,
|
|
543
519
|
{alignItems: 'center', justifyContent: 'center'},
|
|
544
|
-
countrySelectStyle?.
|
|
520
|
+
countrySelectStyle?.backdrop,
|
|
545
521
|
removedBackdrop && {backgroundColor: 'transparent'},
|
|
546
522
|
]}
|
|
547
523
|
onPress={onBackdropPress || onClose}>
|
|
548
524
|
<Pressable
|
|
549
525
|
style={[
|
|
550
|
-
styles.
|
|
551
|
-
countrySelectStyle?.
|
|
526
|
+
styles.container,
|
|
527
|
+
countrySelectStyle?.container,
|
|
552
528
|
isFullScreen && {
|
|
553
529
|
flex: 1,
|
|
554
530
|
width: '100%',
|
|
@@ -557,8 +533,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
557
533
|
]}>
|
|
558
534
|
<View
|
|
559
535
|
style={[
|
|
560
|
-
styles.
|
|
561
|
-
countrySelectStyle?.
|
|
536
|
+
styles.content,
|
|
537
|
+
countrySelectStyle?.content,
|
|
562
538
|
isFullScreen && {
|
|
563
539
|
borderRadius: 0,
|
|
564
540
|
},
|
|
@@ -567,7 +543,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
567
543
|
<View
|
|
568
544
|
style={[
|
|
569
545
|
styles.searchContainer,
|
|
570
|
-
countrySelectStyle?.
|
|
546
|
+
countrySelectStyle?.searchContainer,
|
|
571
547
|
]}>
|
|
572
548
|
{(isFullScreen || showCloseButton) && renderCloseButton()}
|
|
573
549
|
{showSearchInput && renderSearchInput()}
|
|
@@ -593,8 +569,13 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
593
569
|
<View
|
|
594
570
|
style={[
|
|
595
571
|
styles.backdrop,
|
|
572
|
+
countrySelectStyle?.backdrop,
|
|
596
573
|
removedBackdrop && {backgroundColor: 'transparent'},
|
|
597
|
-
]}
|
|
574
|
+
]}
|
|
575
|
+
onLayout={event => {
|
|
576
|
+
const {height} = event.nativeEvent.layout;
|
|
577
|
+
setModalHeight(height);
|
|
578
|
+
}}>
|
|
598
579
|
<Pressable
|
|
599
580
|
testID="countrySelectBackdrop"
|
|
600
581
|
accessibilityRole="button"
|
|
@@ -604,13 +585,30 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
604
585
|
style={{flex: 1}}
|
|
605
586
|
onPress={onBackdropPress || onClose}
|
|
606
587
|
/>
|
|
607
|
-
<View
|
|
608
|
-
|
|
609
|
-
|
|
588
|
+
<View
|
|
589
|
+
style={[styles.container, countrySelectStyle?.container]}
|
|
590
|
+
pointerEvents="auto">
|
|
591
|
+
<View
|
|
592
|
+
{...handlePanResponder.panHandlers}
|
|
593
|
+
style={[
|
|
594
|
+
styles.dragHandleContainer,
|
|
595
|
+
countrySelectStyle?.dragHandleContainer,
|
|
596
|
+
]}>
|
|
597
|
+
{dragHandleIndicatorComponent ? (
|
|
598
|
+
dragHandleIndicatorComponent()
|
|
599
|
+
) : (
|
|
600
|
+
<View
|
|
601
|
+
style={[
|
|
602
|
+
styles.dragHandleIndicator,
|
|
603
|
+
countrySelectStyle?.dragHandleIndicator,
|
|
604
|
+
]}
|
|
605
|
+
/>
|
|
606
|
+
)}
|
|
610
607
|
</View>
|
|
611
608
|
<Animated.View
|
|
612
609
|
style={[
|
|
613
|
-
styles.
|
|
610
|
+
styles.content,
|
|
611
|
+
countrySelectStyle?.content,
|
|
614
612
|
{
|
|
615
613
|
height: sheetHeight,
|
|
616
614
|
minHeight: bottomSheetSize.minHeight,
|
|
@@ -618,7 +616,11 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
618
616
|
},
|
|
619
617
|
]}>
|
|
620
618
|
{(showSearchInput || showCloseButton) && (
|
|
621
|
-
<View
|
|
619
|
+
<View
|
|
620
|
+
style={[
|
|
621
|
+
styles.searchContainer,
|
|
622
|
+
countrySelectStyle?.searchContainer,
|
|
623
|
+
]}>
|
|
622
624
|
{showCloseButton && renderCloseButton()}
|
|
623
625
|
{showSearchInput && renderSearchInput()}
|
|
624
626
|
</View>
|
package/lib/components/styles.js
CHANGED
|
@@ -1,44 +1,48 @@
|
|
|
1
1
|
import {Platform, StatusBar, StyleSheet} from 'react-native';
|
|
2
2
|
|
|
3
|
-
export const createStyles = theme =>
|
|
3
|
+
export const createStyles = (theme, modalType, isFullScreen) =>
|
|
4
4
|
StyleSheet.create({
|
|
5
5
|
backdrop: {
|
|
6
6
|
flex: 1,
|
|
7
7
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
8
8
|
},
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
9
|
+
container:
|
|
10
|
+
modalType === 'popup' || isFullScreen
|
|
11
|
+
? {
|
|
12
|
+
marginTop: StatusBar.currentHeight,
|
|
13
|
+
width: '90%',
|
|
14
|
+
maxWidth: 600,
|
|
15
|
+
height: '60%',
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
alignSelf: 'center',
|
|
19
|
+
}
|
|
20
|
+
: {
|
|
21
|
+
marginTop: StatusBar.currentHeight,
|
|
22
|
+
position: 'absolute',
|
|
23
|
+
bottom: 0,
|
|
24
|
+
left: 0,
|
|
25
|
+
right: 0,
|
|
26
|
+
width: '100%',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
},
|
|
29
|
+
content:
|
|
30
|
+
modalType === 'popup' || isFullScreen
|
|
31
|
+
? {
|
|
32
|
+
flex: 1,
|
|
33
|
+
width: '100%',
|
|
34
|
+
backgroundColor: theme === 'dark' ? '#202020' : '#FFFFFF',
|
|
35
|
+
borderRadius: 20,
|
|
36
|
+
alignSelf: 'center',
|
|
37
|
+
padding: 16,
|
|
38
|
+
}
|
|
39
|
+
: {
|
|
40
|
+
width: '100%',
|
|
41
|
+
backgroundColor: theme === 'dark' ? '#202020' : '#FFFFFF',
|
|
42
|
+
padding: 16,
|
|
43
|
+
paddingTop: 0,
|
|
44
|
+
},
|
|
45
|
+
dragHandleContainer: {
|
|
42
46
|
width: '100%',
|
|
43
47
|
height: 24,
|
|
44
48
|
justifyContent: 'center',
|
|
@@ -48,7 +52,7 @@ export const createStyles = theme =>
|
|
|
48
52
|
borderTopRightRadius: 20,
|
|
49
53
|
marginBottom: -1,
|
|
50
54
|
},
|
|
51
|
-
|
|
55
|
+
dragHandleIndicator: {
|
|
52
56
|
width: 40,
|
|
53
57
|
height: 4,
|
|
54
58
|
backgroundColor: theme === 'dark' ? '#FFFFFF40' : '#00000040',
|
|
@@ -69,9 +73,6 @@ export const createStyles = theme =>
|
|
|
69
73
|
borderWidth: 1,
|
|
70
74
|
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
|
71
75
|
},
|
|
72
|
-
searchInputPlaceholder: {
|
|
73
|
-
color: theme === 'dark' ? '#FFFFFF80' : '#00000080',
|
|
74
|
-
},
|
|
75
76
|
list: {
|
|
76
77
|
flex: 1,
|
|
77
78
|
},
|
|
@@ -20,6 +20,8 @@ export interface ICountrySelectProps extends ModalProps {
|
|
|
20
20
|
language?: ICountrySelectLanguages;
|
|
21
21
|
showSearchInput?: boolean;
|
|
22
22
|
searchPlaceholder?: string;
|
|
23
|
+
searchPlaceholderTextColor?: string;
|
|
24
|
+
searchSelectionColor?: string;
|
|
23
25
|
showCloseButton?: boolean;
|
|
24
26
|
minBottomsheetHeight?: number | string;
|
|
25
27
|
maxBottomsheetHeight?: number | string;
|
|
@@ -27,6 +29,7 @@ export interface ICountrySelectProps extends ModalProps {
|
|
|
27
29
|
disabledBackdropPress?: boolean;
|
|
28
30
|
removedBackdrop?: boolean;
|
|
29
31
|
onBackdropPress?: () => void;
|
|
32
|
+
dragHandleIndicatorComponent?: () => React.ReactElement;
|
|
30
33
|
countryItemComponent?: (item: ICountry) => React.ReactElement;
|
|
31
34
|
sectionTitleComponent?: (item: ISectionTitle) => React.ReactElement;
|
|
32
35
|
closeButtonComponent?: () => React.ReactElement;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {StyleProp, TextStyle, ViewStyle} from 'react-native';
|
|
2
2
|
|
|
3
|
-
interface
|
|
3
|
+
export interface ICountrySelectStyle {
|
|
4
4
|
backdrop?: StyleProp<ViewStyle>;
|
|
5
|
+
container?: StyleProp<ViewStyle>;
|
|
6
|
+
content?: StyleProp<ViewStyle>;
|
|
7
|
+
dragHandleContainer?: StyleProp<ViewStyle>;
|
|
8
|
+
dragHandleIndicator?: StyleProp<ViewStyle>;
|
|
5
9
|
closeButton?: StyleProp<ViewStyle>;
|
|
6
10
|
closeButtonText?: StyleProp<TextStyle>;
|
|
7
11
|
searchContainer?: StyleProp<ViewStyle>;
|
|
8
12
|
searchInput?: StyleProp<TextStyle>;
|
|
9
|
-
searchInputPlaceholder?: {
|
|
10
|
-
color: string;
|
|
11
|
-
};
|
|
12
13
|
sectionTitle?: StyleProp<TextStyle>;
|
|
13
14
|
list?: StyleProp<ViewStyle>;
|
|
14
15
|
countryItem?: StyleProp<ViewStyle>;
|
|
@@ -19,18 +20,3 @@ interface IBaseModalStyle {
|
|
|
19
20
|
countryNotFoundContainer?: StyleProp<ViewStyle>;
|
|
20
21
|
countryNotFoundMessage?: StyleProp<TextStyle>;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
interface IPopupStyle extends IBaseModalStyle {
|
|
24
|
-
popupContainer?: StyleProp<ViewStyle>;
|
|
25
|
-
popupContent?: StyleProp<ViewStyle>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface IBottomSheetStyle extends IBaseModalStyle {
|
|
29
|
-
sheetContainer?: StyleProp<ViewStyle>;
|
|
30
|
-
sheetContent?: StyleProp<ViewStyle>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface ICountrySelectStyle {
|
|
34
|
-
popup?: IPopupStyle;
|
|
35
|
-
bottomSheet?: IBottomSheetStyle;
|
|
36
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-country-select",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "🌍 A lightweight and customizable country picker for React Native with modern UI, flags, search engine, and i18n support. Includes TypeScript types, offline support and no dependencies.",
|
|
5
5
|
"main": "lib/index.tsx",
|
|
6
6
|
"types": "lib/index.d.ts",
|