react-native-country-select 0.1.2 → 0.1.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 +12 -0
- package/lib/assets/images/preview.png +0 -0
- package/lib/components/CountryItem/index.tsx +24 -6
- package/lib/components/CountrySelect/index.tsx +75 -21
- package/lib/components/styles.ts +16 -1
- package/lib/index.d.ts +2 -0
- package/lib/interface/countryItemProps.ts +2 -0
- package/lib/interface/countrySelectProps.ts +6 -0
- package/lib/interface/countrySelectStyles.ts +28 -0
- package/lib/interface/index.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
<br>
|
2
|
+
|
3
|
+
<div align = "center">
|
4
|
+
<img src="lib/assets/images/preview.png" alt="React Native International Phone Number Input Lib preview">
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<br>
|
8
|
+
|
1
9
|
<h1 align="center">React Native Country Select</h1>
|
2
10
|
|
3
11
|
<p>
|
@@ -198,11 +206,15 @@ export default function App() {
|
|
198
206
|
| visible | boolean | Yes | false | Controls the visibility of the country picker modal |
|
199
207
|
| onClose | () => void | Yes | - | Callback function called when the modal is closed |
|
200
208
|
| onSelect | (country: ICountry) => void | Yes | - | Callback function called when a country is selected |
|
209
|
+
| countrySelectStyle | ICountrySelectStyle | No | - | Custom styles for the country picker |
|
210
|
+
| isFullScreen | boolean | No | false | Whether the modal should be full screen |
|
201
211
|
| popularCountries | string[] | No | [] | Array of country codes to show in popular section |
|
202
212
|
| visibleCountries | ICountryCca2[] | No | [] | Array of country codes to show (whitelist) |
|
203
213
|
| hiddenCountries | ICountryCca2[] | No | [] | Array of country codes to hide (blacklist) |
|
204
214
|
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker |
|
205
215
|
| language | ICountrySelectLanguages | No | 'eng' | Language for country names (see supported languages below) |
|
216
|
+
| showSearchInput | boolean | No | true | Whether to show the search input field |
|
217
|
+
| searchPlaceholder | string | No | 'Search country...' | Placeholder text for search input |
|
206
218
|
| disabledBackdropPress | boolean | No | false | Whether to disable backdrop press to close |
|
207
219
|
| removedBackdrop | boolean | No | false | Whether to remove the backdrop completely |
|
208
220
|
| onBackdropPress | () => void | No | - | Custom callback for backdrop press |
|
Binary file
|
@@ -7,7 +7,14 @@ import {ICountryItemProps, ICountrySelectLanguages} from '../../interface';
|
|
7
7
|
const DEFAULT_LANGUAGE: ICountrySelectLanguages = 'eng';
|
8
8
|
|
9
9
|
export const CountryItem = memo<ICountryItemProps>(
|
10
|
-
({
|
10
|
+
({
|
11
|
+
item,
|
12
|
+
onSelect,
|
13
|
+
onClose,
|
14
|
+
theme = 'light',
|
15
|
+
language,
|
16
|
+
countrySelectStyle,
|
17
|
+
}) => {
|
11
18
|
const styles = createStyles(theme);
|
12
19
|
|
13
20
|
return (
|
@@ -16,21 +23,32 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
16
23
|
accessibilityRole="button"
|
17
24
|
accessibilityLabel="Country Select Item"
|
18
25
|
accessibilityHint="Click to select a country"
|
19
|
-
style={styles.countryItem}
|
26
|
+
style={[styles.countryItem, countrySelectStyle?.popup?.countryItem]}
|
20
27
|
onPress={() => {
|
21
28
|
onSelect(item);
|
22
29
|
onClose();
|
23
30
|
}}>
|
24
|
-
<Text
|
31
|
+
<Text
|
32
|
+
testID="countrySelectItemFlag"
|
33
|
+
style={[styles.flag, countrySelectStyle?.popup?.flag]}>
|
25
34
|
{item.flag}
|
26
35
|
</Text>
|
27
|
-
<View
|
36
|
+
<View
|
37
|
+
style={[styles.countryInfo, countrySelectStyle?.popup?.countryInfo]}>
|
28
38
|
<Text
|
29
39
|
testID="countrySelectItemCallingCode"
|
30
|
-
style={
|
40
|
+
style={[
|
41
|
+
styles.callingCode,
|
42
|
+
countrySelectStyle?.popup?.callingCode,
|
43
|
+
]}>
|
31
44
|
{item.idd.root}
|
32
45
|
</Text>
|
33
|
-
<Text
|
46
|
+
<Text
|
47
|
+
testID="countrySelectItemName"
|
48
|
+
style={[
|
49
|
+
styles.countryName,
|
50
|
+
countrySelectStyle?.popup?.countryName,
|
51
|
+
]}>
|
34
52
|
{item?.translations[language]?.common ||
|
35
53
|
item?.translations[DEFAULT_LANGUAGE]?.common}
|
36
54
|
</Text>
|
@@ -9,6 +9,7 @@ import {
|
|
9
9
|
ListRenderItem,
|
10
10
|
Modal,
|
11
11
|
Text,
|
12
|
+
TouchableOpacity,
|
12
13
|
} from 'react-native';
|
13
14
|
|
14
15
|
import {CountryItem} from '../CountryItem';
|
@@ -30,10 +31,14 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
30
31
|
onClose,
|
31
32
|
onSelect,
|
32
33
|
theme = 'light',
|
34
|
+
isFullScreen = false,
|
35
|
+
countrySelectStyle,
|
33
36
|
popularCountries = [],
|
34
37
|
visibleCountries = [],
|
35
38
|
hiddenCountries = [],
|
36
39
|
language = DEFAULT_LANGUAGE,
|
40
|
+
showSearchInput = true,
|
41
|
+
searchPlaceholder,
|
37
42
|
disabledBackdropPress,
|
38
43
|
removedBackdrop,
|
39
44
|
onBackdropPress,
|
@@ -96,12 +101,20 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
96
101
|
|
97
102
|
const filteredCountries = countriesData.filter(country => {
|
98
103
|
const countryName = getCountryNameInLanguage(country);
|
104
|
+
const normalizedCountryName = normalizeCountryName(
|
105
|
+
countryName.toLowerCase(),
|
106
|
+
);
|
107
|
+
const normalizedQuery = normalizeCountryName(query);
|
99
108
|
const callingCode = country.idd.root.toLowerCase();
|
100
109
|
const flag = country.flag.toLowerCase();
|
110
|
+
const countryCode = country.cca2.toLowerCase();
|
111
|
+
|
101
112
|
return (
|
102
|
-
|
113
|
+
normalizedCountryName.includes(normalizedQuery) ||
|
114
|
+
countryName.toLowerCase().includes(query) ||
|
103
115
|
callingCode.includes(query) ||
|
104
|
-
flag.includes(query)
|
116
|
+
flag.includes(query) ||
|
117
|
+
countryCode.includes(query)
|
105
118
|
);
|
106
119
|
});
|
107
120
|
|
@@ -174,7 +187,10 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
174
187
|
<Text
|
175
188
|
testID="countrySelectSectionTitle"
|
176
189
|
accessibilityRole="header"
|
177
|
-
style={
|
190
|
+
style={[
|
191
|
+
styles.sectionTitle,
|
192
|
+
countrySelectStyle?.popup?.sectionTitle,
|
193
|
+
]}>
|
178
194
|
{popularCountriesTitle && index === 0
|
179
195
|
? popularCountriesTitle
|
180
196
|
: allCountriesTitle && index > 0
|
@@ -195,6 +211,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
195
211
|
onClose={onClose}
|
196
212
|
theme={theme}
|
197
213
|
language={language}
|
214
|
+
countrySelectStyle={countrySelectStyle}
|
198
215
|
/>
|
199
216
|
);
|
200
217
|
},
|
@@ -220,28 +237,65 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
220
237
|
style={[
|
221
238
|
styles.backdrop,
|
222
239
|
{alignItems: 'center', justifyContent: 'center'},
|
240
|
+
countrySelectStyle?.popup?.backdrop,
|
223
241
|
removedBackdrop && {backgroundColor: 'transparent'},
|
224
242
|
]}
|
225
243
|
disabled={disabledBackdropPress || removedBackdrop}
|
226
244
|
onPress={onBackdropPress || onClose}>
|
227
|
-
<Pressable
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
+
<Pressable
|
246
|
+
style={[
|
247
|
+
styles.popupContainer,
|
248
|
+
countrySelectStyle?.popup?.popupContainer,
|
249
|
+
isFullScreen && {flex: 1, width: '100%', height: '100%'},
|
250
|
+
]}>
|
251
|
+
<View
|
252
|
+
style={[
|
253
|
+
styles.popupContent,
|
254
|
+
countrySelectStyle?.popup?.popupContent,
|
255
|
+
]}>
|
256
|
+
<View
|
257
|
+
style={[
|
258
|
+
styles.searchContainer,
|
259
|
+
countrySelectStyle?.popup?.searchContainer,
|
260
|
+
]}>
|
261
|
+
{isFullScreen && (
|
262
|
+
<TouchableOpacity
|
263
|
+
style={[
|
264
|
+
styles.closeButton,
|
265
|
+
countrySelectStyle?.popup?.closeButton,
|
266
|
+
]}
|
267
|
+
activeOpacity={0.6}
|
268
|
+
onPress={onClose}>
|
269
|
+
<Text
|
270
|
+
style={[
|
271
|
+
styles.closeButtonText,
|
272
|
+
countrySelectStyle?.popup?.closeButtonText,
|
273
|
+
]}>
|
274
|
+
{'\u00D7'}
|
275
|
+
</Text>
|
276
|
+
</TouchableOpacity>
|
277
|
+
)}
|
278
|
+
{showSearchInput && (
|
279
|
+
<TextInput
|
280
|
+
testID="countrySelectSearchInput"
|
281
|
+
accessibilityRole="text"
|
282
|
+
accessibilityLabel="Country Select Search Input"
|
283
|
+
accessibilityHint="Type to search for a country"
|
284
|
+
style={[
|
285
|
+
styles.searchInput,
|
286
|
+
countrySelectStyle?.popup?.searchInput,
|
287
|
+
]}
|
288
|
+
placeholder={
|
289
|
+
searchPlaceholder ||
|
290
|
+
translations.searchPlaceholder[
|
291
|
+
language as ICountrySelectLanguages
|
292
|
+
]
|
293
|
+
}
|
294
|
+
placeholderTextColor={styles.searchInputPlaceholder.color}
|
295
|
+
value={searchQuery}
|
296
|
+
onChangeText={setSearchQuery}
|
297
|
+
/>
|
298
|
+
)}
|
245
299
|
</View>
|
246
300
|
|
247
301
|
<FlatList
|
package/lib/components/styles.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {StyleSheet} from 'react-native';
|
1
|
+
import {StatusBar, StyleSheet} from 'react-native';
|
2
2
|
|
3
3
|
export const createStyles = (theme: 'light' | 'dark') =>
|
4
4
|
StyleSheet.create({
|
@@ -7,6 +7,7 @@ export const createStyles = (theme: 'light' | 'dark') =>
|
|
7
7
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
8
8
|
},
|
9
9
|
popupContainer: {
|
10
|
+
paddingTop: StatusBar.currentHeight,
|
10
11
|
width: '90%',
|
11
12
|
maxWidth: 600,
|
12
13
|
height: '60%',
|
@@ -31,6 +32,7 @@ export const createStyles = (theme: 'light' | 'dark') =>
|
|
31
32
|
flex: 1,
|
32
33
|
borderRadius: 8,
|
33
34
|
paddingHorizontal: 16,
|
35
|
+
minHeight: 44,
|
34
36
|
fontSize: 16,
|
35
37
|
borderColor: theme === 'dark' ? '#F3F3F3' : '#303030',
|
36
38
|
borderWidth: 1,
|
@@ -80,4 +82,17 @@ export const createStyles = (theme: 'light' | 'dark') =>
|
|
80
82
|
paddingVertical: 8,
|
81
83
|
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
82
84
|
},
|
85
|
+
closeButton: {
|
86
|
+
marginRight: 10,
|
87
|
+
paddingHorizontal: 18,
|
88
|
+
alignItems: 'center',
|
89
|
+
justifyContent: 'center',
|
90
|
+
backgroundColor: theme === 'dark' ? '#303030' : '#F5F5F5',
|
91
|
+
borderRadius: 12,
|
92
|
+
},
|
93
|
+
closeButtonText: {
|
94
|
+
fontSize: 24,
|
95
|
+
lineHeight: 28,
|
96
|
+
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
97
|
+
},
|
83
98
|
});
|
package/lib/index.d.ts
CHANGED
@@ -5,6 +5,7 @@ import {
|
|
5
5
|
ICountryCca2,
|
6
6
|
ICountryItemProps,
|
7
7
|
ICountrySelectProps,
|
8
|
+
ICountrySelectStyle,
|
8
9
|
ICountrySelectLanguages,
|
9
10
|
} from './interface';
|
10
11
|
|
@@ -17,5 +18,6 @@ export {
|
|
17
18
|
ICountryCca2,
|
18
19
|
ICountryItemProps,
|
19
20
|
ICountrySelectProps,
|
21
|
+
ICountrySelectStyle,
|
20
22
|
ICountrySelectLanguages,
|
21
23
|
};
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import {ICountry} from './country';
|
2
|
+
import {ICountrySelectStyle} from './countrySelectStyles';
|
2
3
|
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
3
4
|
|
4
5
|
export interface ICountryItemProps {
|
@@ -7,4 +8,5 @@ export interface ICountryItemProps {
|
|
7
8
|
onClose: () => void;
|
8
9
|
language: ICountrySelectLanguages;
|
9
10
|
theme?: 'light' | 'dark';
|
11
|
+
countrySelectStyle?: ICountrySelectStyle;
|
10
12
|
}
|
@@ -1,19 +1,25 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
import {ModalProps} from 'react-native';
|
2
3
|
|
3
4
|
import {ICountry} from './country';
|
4
5
|
import {ICountryCca2} from './countryCca2';
|
5
6
|
import {ISectionTitle} from './sectionTitle';
|
7
|
+
import {ICountrySelectStyle} from './countrySelectStyles';
|
6
8
|
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
7
9
|
|
8
10
|
export interface ICountrySelectProps extends ModalProps {
|
9
11
|
visible: boolean;
|
10
12
|
onClose: () => void;
|
11
13
|
onSelect: (country: ICountry) => void;
|
14
|
+
countrySelectStyle?: ICountrySelectStyle;
|
12
15
|
theme?: 'light' | 'dark';
|
16
|
+
isFullScreen?: boolean;
|
13
17
|
popularCountries?: string[];
|
14
18
|
visibleCountries?: ICountryCca2[];
|
15
19
|
hiddenCountries?: ICountryCca2[];
|
16
20
|
language?: ICountrySelectLanguages;
|
21
|
+
showSearchInput?: boolean;
|
22
|
+
searchPlaceholder?: string;
|
17
23
|
disabledBackdropPress?: boolean;
|
18
24
|
removedBackdrop?: boolean;
|
19
25
|
onBackdropPress?: () => void;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import {StyleProp, TextStyle, ViewStyle} from 'react-native';
|
2
|
+
|
3
|
+
interface IBaseModalStyle {
|
4
|
+
backdrop?: StyleProp<ViewStyle>;
|
5
|
+
closeButton?: StyleProp<ViewStyle>;
|
6
|
+
closeButtonText?: StyleProp<TextStyle>;
|
7
|
+
searchContainer?: StyleProp<ViewStyle>;
|
8
|
+
searchInput?: StyleProp<TextStyle>;
|
9
|
+
searchInputPlaceholder?: {
|
10
|
+
color: string;
|
11
|
+
};
|
12
|
+
sectionTitle?: StyleProp<TextStyle>;
|
13
|
+
list?: StyleProp<ViewStyle>;
|
14
|
+
countryItem?: StyleProp<ViewStyle>;
|
15
|
+
flag?: StyleProp<TextStyle>;
|
16
|
+
countryInfo?: StyleProp<ViewStyle>;
|
17
|
+
callingCode?: StyleProp<TextStyle>;
|
18
|
+
countryName?: StyleProp<TextStyle>;
|
19
|
+
}
|
20
|
+
|
21
|
+
interface IPopupStyle extends IBaseModalStyle {
|
22
|
+
popupContainer?: StyleProp<ViewStyle>;
|
23
|
+
popupContent?: StyleProp<ViewStyle>;
|
24
|
+
}
|
25
|
+
|
26
|
+
export interface ICountrySelectStyle {
|
27
|
+
popup?: IPopupStyle;
|
28
|
+
}
|
package/lib/interface/index.ts
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// Re-export all interfaces from their respective files
|
2
1
|
export * from './countryCca2';
|
3
2
|
export * from './countrySelectLanguages';
|
4
3
|
export * from './country';
|
@@ -6,3 +5,4 @@ export * from './countrySelectProps';
|
|
6
5
|
export * from './countryItemProps';
|
7
6
|
export * from './sectionTitle';
|
8
7
|
export * from './itemList';
|
8
|
+
export * from './countrySelectStyles';
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "react-native-country-select",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.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",
|