react-native-country-select 0.1.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/LICENSE.md +7 -0
- package/README.md +296 -0
- package/lib/components/CountryItem/index.tsx +41 -0
- package/lib/components/CountrySelect/index.tsx +159 -0
- package/lib/components/index.ts +2 -0
- package/lib/components/styles.ts +83 -0
- package/lib/constants/countries.json +51471 -0
- package/lib/index.d.ts +21 -0
- package/lib/index.tsx +18 -0
- package/lib/interface/country.ts +111 -0
- package/lib/interface/countryCca2.ts +251 -0
- package/lib/interface/countryItemProps.ts +10 -0
- package/lib/interface/countrySelectLanguages.ts +34 -0
- package/lib/interface/countrySelectProps.ts +11 -0
- package/lib/interface/index.ts +9 -0
- package/lib/utils/getTranslation.ts +45 -0
- package/package.json +42 -0
package/LICENSE.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
ISC License
|
2
|
+
|
3
|
+
Copyright 2025-present Willian Barbosa Lima do Nascimento
|
4
|
+
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,296 @@
|
|
1
|
+
<h1 align="center">React Native Country Select</h1>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
🌍 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
|
+
</p>
|
6
|
+
|
7
|
+
<br>
|
8
|
+
|
9
|
+
<div align="center">
|
10
|
+
<a href="https://www.npmjs.com/package/react-native-country-select">
|
11
|
+
<img src="https://img.shields.io/npm/v/react-native-country-select.svg?style=flat-square">
|
12
|
+
</a>
|
13
|
+
<a href="https://www.npmjs.com/package/react-native-country-select">
|
14
|
+
<img src="https://img.shields.io/npm/dt/react-native-country-select.svg?style=flat-square&color=success">
|
15
|
+
</a>
|
16
|
+
<a href="https://github.com/AstrOOnauta/react-native-country-select">
|
17
|
+
<img src="https://img.shields.io/github/stars/AstrOOnauta/react-native-country-select?style=flat-square&color=success"/>
|
18
|
+
</a>
|
19
|
+
<a href="https://github.com/AstrOOnauta/react-native-country-select/issues">
|
20
|
+
<img src="https://img.shields.io/github/issues/AstrOOnauta/react-native-country-select?style=flat-square&color=blue"/>
|
21
|
+
</a>
|
22
|
+
<a href="https://github.com/AstrOOnauta/react-native-country-select/pulls">
|
23
|
+
<img src="https://img.shields.io/github/issues-pr/AstrOOnauta/react-native-country-select?style=flat-square&color=blue"/>
|
24
|
+
</a>
|
25
|
+
<a href="LICENSE.md">
|
26
|
+
<img src="https://img.shields.io/:license-isc-yellow.svg?style=flat-square"/>
|
27
|
+
</a>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<br>
|
31
|
+
|
32
|
+
<div align="center">
|
33
|
+
<a href="https://www.buymeacoffee.com/astroonauta" target="_blank">
|
34
|
+
<img src="https://survivingmexico.files.wordpress.com/2018/07/button-gif.gif" alt="Buy Me A Coffee" style="height: auto !important;width: 60% !important;">
|
35
|
+
</a>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<br>
|
39
|
+
|
40
|
+
## Features
|
41
|
+
|
42
|
+
- 📱 Cross-platform: works with iOS, Android and Expo;
|
43
|
+
- 🎨 Lib with custom and modern UI;
|
44
|
+
- 👨💻 Functional and class component support;
|
45
|
+
- 🈶 32 languages supported;
|
46
|
+
- ♿ Accessibility.
|
47
|
+
|
48
|
+
<br>
|
49
|
+
|
50
|
+
## Try it out
|
51
|
+
|
52
|
+
- [Demo](https://snack.expo.dev/@astroonauta/react-native-country-select)
|
53
|
+
|
54
|
+
<br>
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
```sh
|
59
|
+
npm install react-native-country-select
|
60
|
+
# or
|
61
|
+
yarn add react-native-country-select
|
62
|
+
```
|
63
|
+
|
64
|
+
<br>
|
65
|
+
|
66
|
+
## Basic Usage
|
67
|
+
|
68
|
+
- Class Component
|
69
|
+
|
70
|
+
```jsx
|
71
|
+
import React, {Component} from 'react';
|
72
|
+
import {Text, TouchableOpacity, View} from 'react-native';
|
73
|
+
import CountrySelect from 'react-native-country-select';
|
74
|
+
|
75
|
+
export default class App extends Component {
|
76
|
+
countryRef = null;
|
77
|
+
|
78
|
+
constructor(props) {
|
79
|
+
super(props);
|
80
|
+
this.state = {
|
81
|
+
showPicker: false,
|
82
|
+
country: null,
|
83
|
+
};
|
84
|
+
}
|
85
|
+
|
86
|
+
handleCountrySelect = country => {
|
87
|
+
this.setState({country});
|
88
|
+
};
|
89
|
+
|
90
|
+
render() {
|
91
|
+
return (
|
92
|
+
<View style={{flex: 1}}>
|
93
|
+
<TouchableOpacity onPress={() => this.setState({showPicker: true})}>
|
94
|
+
<Text>Select Country</Text>
|
95
|
+
</TouchableOpacity>
|
96
|
+
<Text>
|
97
|
+
Country:{' '}
|
98
|
+
{`${this.state.selectedCountry?.name?.common} (${this.state.selectedCountry?.cca2})`}
|
99
|
+
</Text>
|
100
|
+
|
101
|
+
<CountrySelect
|
102
|
+
visible={this.state.showPicker}
|
103
|
+
onClose={() => this.setState({showPicker: false})}
|
104
|
+
onSelect={this.handleCountrySelect}
|
105
|
+
/>
|
106
|
+
</View>
|
107
|
+
);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
```
|
111
|
+
|
112
|
+
<br>
|
113
|
+
|
114
|
+
- Function Component
|
115
|
+
|
116
|
+
```jsx
|
117
|
+
import React, {useState} from 'react';
|
118
|
+
import {Text, TouchableOpacity, View} from 'react-native';
|
119
|
+
|
120
|
+
import CountrySelect from 'react-native-country-select';
|
121
|
+
|
122
|
+
export default function App() {
|
123
|
+
const [showPicker, setShowPicker] = useState(false);
|
124
|
+
const [selectedCountry, setSelectedCountry] = useState(null);
|
125
|
+
|
126
|
+
const handleCountrySelect = country => {
|
127
|
+
setSelectedCountry(country);
|
128
|
+
};
|
129
|
+
|
130
|
+
return (
|
131
|
+
<View
|
132
|
+
style={{
|
133
|
+
flex: 1,
|
134
|
+
}}>
|
135
|
+
<TouchableOpacity onPress={() => setShowPicker(true)}>
|
136
|
+
<Text>Select Country</Text>
|
137
|
+
</TouchableOpacity>
|
138
|
+
<Text>
|
139
|
+
Country: {`${selectedCountry?.name?.common} (${selectedCountry?.cca2})`}
|
140
|
+
</Text>
|
141
|
+
|
142
|
+
<CountrySelect
|
143
|
+
visible={showPicker}
|
144
|
+
onClose={() => setShowPicker(false)}
|
145
|
+
onSelect={handleCountrySelect}
|
146
|
+
/>
|
147
|
+
</View>
|
148
|
+
);
|
149
|
+
}
|
150
|
+
```
|
151
|
+
|
152
|
+
<br>
|
153
|
+
|
154
|
+
- Typescript
|
155
|
+
|
156
|
+
```tsx
|
157
|
+
import React, {useState} from 'react';
|
158
|
+
import {Text, TouchableOpacity, View} from 'react-native';
|
159
|
+
|
160
|
+
import CountrySelect, {ICountry} from 'react-native-country-select';
|
161
|
+
|
162
|
+
export default function App() {
|
163
|
+
const [showPicker, setShowPicker] = useState<boolean>(false);
|
164
|
+
const [selectedCountry, setSelectedCountry] = useState<ICountry | null>(null);
|
165
|
+
|
166
|
+
const handleCountrySelect = (country: ICountry) => {
|
167
|
+
setSelectedCountry(country);
|
168
|
+
};
|
169
|
+
|
170
|
+
return (
|
171
|
+
<View
|
172
|
+
style={{
|
173
|
+
flex: 1,
|
174
|
+
}}>
|
175
|
+
<TouchableOpacity onPress={() => setShowPicker(true)}>
|
176
|
+
<Text>Select Country</Text>
|
177
|
+
</TouchableOpacity>
|
178
|
+
<Text>
|
179
|
+
Country: {`${selectedCountry?.name?.common} (${selectedCountry?.cca2})`}
|
180
|
+
</Text>
|
181
|
+
|
182
|
+
<CountrySelect
|
183
|
+
visible={showPicker}
|
184
|
+
onClose={() => setShowPicker(false)}
|
185
|
+
onSelect={handleCountrySelect}
|
186
|
+
/>
|
187
|
+
</View>
|
188
|
+
);
|
189
|
+
}
|
190
|
+
```
|
191
|
+
|
192
|
+
<br>
|
193
|
+
|
194
|
+
## CountrySelect Props
|
195
|
+
|
196
|
+
| Prop | Type | Required | Default | Description |
|
197
|
+
| -------- | --------------------------- | -------- | ------- | ---------------------------------------------------------- |
|
198
|
+
| visible | boolean | Yes | false | Controls the visibility of the country picker modal |
|
199
|
+
| onClose | () => void | Yes | - | Callback function called when the modal is closed |
|
200
|
+
| onSelect | (country: ICountry) => void | Yes | - | Callback function called when a country is selected |
|
201
|
+
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker |
|
202
|
+
| language | ICountrySelectLanguages | No | 'eng' | Language for country names (see supported languages below) |
|
203
|
+
|
204
|
+
<br>
|
205
|
+
|
206
|
+
### Supported Languages
|
207
|
+
|
208
|
+
The `language` prop supports the following values:
|
209
|
+
|
210
|
+
| Code | Language |
|
211
|
+
| ---------- | ------------------- |
|
212
|
+
| `ara` | Arabic |
|
213
|
+
| `bel` | Belarusian |
|
214
|
+
| `bre` | Breton |
|
215
|
+
| `bul` | Bulgarian |
|
216
|
+
| `ces` | Czech |
|
217
|
+
| `deu` | German |
|
218
|
+
| `ell` | Greek |
|
219
|
+
| `eng` | English |
|
220
|
+
| `est` | Estonian |
|
221
|
+
| `fin` | Finnish |
|
222
|
+
| `fra` | French |
|
223
|
+
| `heb` | Hebrew |
|
224
|
+
| `hrv` | Croatian |
|
225
|
+
| `hun` | Hungarian |
|
226
|
+
| `ita` | Italian |
|
227
|
+
| `jpn` | Japanese |
|
228
|
+
| `kor` | Korean |
|
229
|
+
| `nld` | Dutch |
|
230
|
+
| `per` | Persian |
|
231
|
+
| `pol` | Polish |
|
232
|
+
| `por` | Portuguese |
|
233
|
+
| `ron` | Romanian |
|
234
|
+
| `rus` | Russian |
|
235
|
+
| `slk` | Slovak |
|
236
|
+
| `spa` | Spanish |
|
237
|
+
| `srp` | Serbian |
|
238
|
+
| `swe` | Swedish |
|
239
|
+
| `tur` | Turkish |
|
240
|
+
| `ukr` | Ukrainian |
|
241
|
+
| `urd` | Urdu |
|
242
|
+
| `zho` | Chinese |
|
243
|
+
| `zho-Hans` | Simplified Chinese |
|
244
|
+
| `zho-Hant` | Traditional Chinese |
|
245
|
+
|
246
|
+
<br>
|
247
|
+
|
248
|
+
## Testing
|
249
|
+
|
250
|
+
When utilizing this package, you may need to target the CountrySelect component in your automated tests. To facilitate this, we provide a testID props for the CountrySelect component. The testID can be integrated with popular testing libraries such as @testing-library/react-native or Maestro. This enables you to efficiently locate and interact with CountrySelect elements within your tests, ensuring a robust and reliable testing experience.
|
251
|
+
|
252
|
+
```js
|
253
|
+
const countrySelect = getByTestId('countrySelectSearchInput');
|
254
|
+
const countrySelectList = getByTestId('countrySelectList');
|
255
|
+
const countrySelectItem = getByTestId('countrySelectItem');
|
256
|
+
```
|
257
|
+
|
258
|
+
<br>
|
259
|
+
|
260
|
+
## Accessibility
|
261
|
+
|
262
|
+
Ensure your app is inclusive and usable by everyone by leveraging built-in React Native accessibility features. The accessibility props are covered by this package.
|
263
|
+
|
264
|
+
<br>
|
265
|
+
|
266
|
+
## Contributing
|
267
|
+
|
268
|
+
Thank you for considering contributing to **react-native-country-select**!
|
269
|
+
|
270
|
+
- Fork or clone this repository
|
271
|
+
|
272
|
+
```bash
|
273
|
+
$ git clone https://github.com/AstrOOnauta/react-native-country-select.git
|
274
|
+
```
|
275
|
+
|
276
|
+
- Repair, Update and Enjoy 🛠️🚧⚙️
|
277
|
+
|
278
|
+
- Create a new PR to this repository
|
279
|
+
|
280
|
+
<br>
|
281
|
+
|
282
|
+
## Credits
|
283
|
+
|
284
|
+
@mledoze for the [countries data](https://github.com/mledoze/countries)
|
285
|
+
|
286
|
+
## License
|
287
|
+
|
288
|
+
[ISC](LICENSE.md)
|
289
|
+
|
290
|
+
<br>
|
291
|
+
|
292
|
+
<div align = "center">
|
293
|
+
<br>
|
294
|
+
Thanks for stopping by! 😁
|
295
|
+
<br>
|
296
|
+
</div>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import React, {memo} from 'react';
|
2
|
+
import {View, Text, TouchableOpacity} from 'react-native';
|
3
|
+
|
4
|
+
import {createStyles} from '../styles';
|
5
|
+
import {ICountryItemProps, ICountrySelectLanguages} from '../../interface';
|
6
|
+
|
7
|
+
const DEFAULT_LANGUAGE: ICountrySelectLanguages = 'eng';
|
8
|
+
|
9
|
+
export const CountryItem = memo<ICountryItemProps>(
|
10
|
+
({item, onSelect, onClose, theme = 'light', language}) => {
|
11
|
+
const styles = createStyles(theme);
|
12
|
+
|
13
|
+
return (
|
14
|
+
<TouchableOpacity
|
15
|
+
testID="countrySelectItem"
|
16
|
+
accessibilityRole="button"
|
17
|
+
accessibilityLabel="Country Select Item"
|
18
|
+
accessibilityHint="Click to select a country"
|
19
|
+
style={styles.countryItem}
|
20
|
+
onPress={() => {
|
21
|
+
onSelect(item);
|
22
|
+
onClose();
|
23
|
+
}}>
|
24
|
+
<Text testID="countrySelectItemFlag" style={styles.flag}>
|
25
|
+
{item.flag}
|
26
|
+
</Text>
|
27
|
+
<View style={styles.countryInfo}>
|
28
|
+
<Text
|
29
|
+
testID="countrySelectItemCallingCode"
|
30
|
+
style={styles.callingCode}>
|
31
|
+
{item.idd.root}
|
32
|
+
</Text>
|
33
|
+
<Text testID="countrySelectItemName" style={styles.countryName}>
|
34
|
+
{item?.translations[language]?.common ||
|
35
|
+
item?.translations[DEFAULT_LANGUAGE]?.common}
|
36
|
+
</Text>
|
37
|
+
</View>
|
38
|
+
</TouchableOpacity>
|
39
|
+
);
|
40
|
+
},
|
41
|
+
);
|
@@ -0,0 +1,159 @@
|
|
1
|
+
/* eslint-disable react-native/no-inline-styles */
|
2
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
3
|
+
import React, {useCallback, useMemo, useState} from 'react';
|
4
|
+
import {
|
5
|
+
View,
|
6
|
+
TextInput,
|
7
|
+
FlatList,
|
8
|
+
Pressable,
|
9
|
+
ListRenderItem,
|
10
|
+
Modal,
|
11
|
+
} from 'react-native';
|
12
|
+
|
13
|
+
import {CountryItem} from '../CountryItem';
|
14
|
+
|
15
|
+
import {createStyles} from '../styles';
|
16
|
+
import countries from '../../constants/countries.json';
|
17
|
+
import {translations} from '../../utils/getTranslation';
|
18
|
+
import {
|
19
|
+
ICountry,
|
20
|
+
ICountrySelectProps,
|
21
|
+
ICountrySelectLanguages,
|
22
|
+
} from '../../interface';
|
23
|
+
|
24
|
+
const DEFAULT_LANGUAGE: ICountrySelectLanguages = 'eng';
|
25
|
+
|
26
|
+
export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
27
|
+
visible,
|
28
|
+
onClose,
|
29
|
+
onSelect,
|
30
|
+
theme = 'light',
|
31
|
+
language = DEFAULT_LANGUAGE,
|
32
|
+
...props
|
33
|
+
}) => {
|
34
|
+
const styles = createStyles(theme);
|
35
|
+
|
36
|
+
const [searchQuery, setSearchQuery] = useState('');
|
37
|
+
|
38
|
+
// Obtain the country name in the selected language
|
39
|
+
const getCountryNameInLanguage = (country: ICountry): string => {
|
40
|
+
return (
|
41
|
+
country.translations[language]?.common ||
|
42
|
+
country.translations[DEFAULT_LANGUAGE]?.common ||
|
43
|
+
country.name.common ||
|
44
|
+
''
|
45
|
+
);
|
46
|
+
};
|
47
|
+
|
48
|
+
// Normalize country name and remove accents
|
49
|
+
const normalizeCountryName = (str: string) =>
|
50
|
+
str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
51
|
+
|
52
|
+
const sortCountriesAlphabetically = (
|
53
|
+
countriesList: ICountry[],
|
54
|
+
): ICountry[] => {
|
55
|
+
return [...countriesList].sort((a, b) => {
|
56
|
+
const nameA = normalizeCountryName(
|
57
|
+
getCountryNameInLanguage(a).toLowerCase(),
|
58
|
+
);
|
59
|
+
const nameB = normalizeCountryName(
|
60
|
+
getCountryNameInLanguage(b).toLowerCase(),
|
61
|
+
);
|
62
|
+
return nameA.localeCompare(nameB);
|
63
|
+
});
|
64
|
+
};
|
65
|
+
|
66
|
+
const getCountries = useMemo(() => {
|
67
|
+
const query = searchQuery.toLowerCase();
|
68
|
+
|
69
|
+
if (query.length > 0) {
|
70
|
+
let countriesData = countries as unknown as ICountry[];
|
71
|
+
|
72
|
+
const filteredCountries = countriesData.filter(country => {
|
73
|
+
const countryName = getCountryNameInLanguage(country);
|
74
|
+
const callingCode = country.idd.root.toLowerCase();
|
75
|
+
const flag = country.flag.toLowerCase();
|
76
|
+
return (
|
77
|
+
countryName.includes(query) ||
|
78
|
+
callingCode.includes(query) ||
|
79
|
+
flag.includes(query)
|
80
|
+
);
|
81
|
+
});
|
82
|
+
|
83
|
+
return sortCountriesAlphabetically(filteredCountries);
|
84
|
+
}
|
85
|
+
|
86
|
+
let allCountries = countries as unknown as ICountry[];
|
87
|
+
|
88
|
+
const result: ICountry[] = allCountries;
|
89
|
+
|
90
|
+
return result;
|
91
|
+
}, [searchQuery]);
|
92
|
+
|
93
|
+
const keyExtractor = useCallback((item: ICountry) => item.cca2, []);
|
94
|
+
|
95
|
+
const renderItem: ListRenderItem<ICountry> = useCallback(
|
96
|
+
({item}) => {
|
97
|
+
return (
|
98
|
+
<CountryItem
|
99
|
+
item={item as ICountry}
|
100
|
+
onSelect={onSelect}
|
101
|
+
onClose={onClose}
|
102
|
+
theme={theme}
|
103
|
+
language={language}
|
104
|
+
/>
|
105
|
+
);
|
106
|
+
},
|
107
|
+
[onSelect, onClose, styles, language],
|
108
|
+
);
|
109
|
+
|
110
|
+
return (
|
111
|
+
<Modal
|
112
|
+
visible={visible}
|
113
|
+
transparent
|
114
|
+
animationType="fade"
|
115
|
+
onRequestClose={onClose}
|
116
|
+
statusBarTranslucent
|
117
|
+
{...props}>
|
118
|
+
<Pressable
|
119
|
+
style={[
|
120
|
+
styles.backdrop,
|
121
|
+
{alignItems: 'center', justifyContent: 'center'},
|
122
|
+
]}
|
123
|
+
onPress={onClose}>
|
124
|
+
<Pressable style={styles.popupContainer}>
|
125
|
+
<View style={styles.popupContent}>
|
126
|
+
<View style={styles.searchContainer}>
|
127
|
+
<TextInput
|
128
|
+
testID="countrySelectSearchInput"
|
129
|
+
accessibilityRole="text"
|
130
|
+
accessibilityLabel="Country Select Search Input"
|
131
|
+
accessibilityHint="Type to search for a country"
|
132
|
+
style={styles.searchInput}
|
133
|
+
placeholder={
|
134
|
+
translations.searchPlaceholder[
|
135
|
+
language as ICountrySelectLanguages
|
136
|
+
]
|
137
|
+
}
|
138
|
+
placeholderTextColor={styles.searchInputPlaceholder.color}
|
139
|
+
value={searchQuery}
|
140
|
+
onChangeText={setSearchQuery}
|
141
|
+
/>
|
142
|
+
</View>
|
143
|
+
|
144
|
+
<FlatList
|
145
|
+
testID="countrySelectList"
|
146
|
+
accessibilityRole="list"
|
147
|
+
accessibilityLabel="Country Select List"
|
148
|
+
accessibilityHint="List of countries"
|
149
|
+
data={getCountries}
|
150
|
+
keyExtractor={keyExtractor}
|
151
|
+
renderItem={renderItem}
|
152
|
+
keyboardShouldPersistTaps="handled"
|
153
|
+
/>
|
154
|
+
</View>
|
155
|
+
</Pressable>
|
156
|
+
</Pressable>
|
157
|
+
</Modal>
|
158
|
+
);
|
159
|
+
};
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
2
|
+
|
3
|
+
export const createStyles = (theme: 'light' | 'dark') =>
|
4
|
+
StyleSheet.create({
|
5
|
+
backdrop: {
|
6
|
+
flex: 1,
|
7
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
8
|
+
},
|
9
|
+
popupContainer: {
|
10
|
+
width: '90%',
|
11
|
+
maxWidth: 600,
|
12
|
+
height: '60%',
|
13
|
+
alignItems: 'center',
|
14
|
+
justifyContent: 'center',
|
15
|
+
alignSelf: 'center',
|
16
|
+
},
|
17
|
+
popupContent: {
|
18
|
+
flex: 1,
|
19
|
+
width: '100%',
|
20
|
+
backgroundColor: theme === 'dark' ? '#202020' : '#FFFFFF',
|
21
|
+
borderRadius: 20,
|
22
|
+
alignSelf: 'center',
|
23
|
+
padding: 16,
|
24
|
+
},
|
25
|
+
searchContainer: {
|
26
|
+
marginBottom: 16,
|
27
|
+
paddingTop: 16,
|
28
|
+
flexDirection: 'row',
|
29
|
+
},
|
30
|
+
searchInput: {
|
31
|
+
flex: 1,
|
32
|
+
borderRadius: 8,
|
33
|
+
paddingHorizontal: 16,
|
34
|
+
fontSize: 16,
|
35
|
+
borderColor: theme === 'dark' ? '#F3F3F3' : '#303030',
|
36
|
+
borderWidth: 1,
|
37
|
+
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
38
|
+
},
|
39
|
+
searchInputPlaceholder: {
|
40
|
+
color: theme === 'dark' ? '#FFFFFF80' : '#00000080',
|
41
|
+
},
|
42
|
+
list: {
|
43
|
+
flex: 1,
|
44
|
+
},
|
45
|
+
countryItem: {
|
46
|
+
flex: 1,
|
47
|
+
flexDirection: 'row',
|
48
|
+
alignItems: 'center',
|
49
|
+
padding: 12,
|
50
|
+
marginBottom: 8,
|
51
|
+
backgroundColor: theme === 'dark' ? '#404040' : '#F3F3F3',
|
52
|
+
borderColor: theme === 'dark' ? '#F3F3F3' : '#303030',
|
53
|
+
borderWidth: 1,
|
54
|
+
borderRadius: 8,
|
55
|
+
},
|
56
|
+
flag: {
|
57
|
+
flex: 0.1,
|
58
|
+
fontSize: 16,
|
59
|
+
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
60
|
+
},
|
61
|
+
countryInfo: {
|
62
|
+
flex: 0.9,
|
63
|
+
flexDirection: 'row',
|
64
|
+
alignItems: 'center',
|
65
|
+
},
|
66
|
+
callingCode: {
|
67
|
+
flex: 0.2,
|
68
|
+
fontSize: 14,
|
69
|
+
color: theme === 'dark' ? '#FFFFFF80' : '#00000080',
|
70
|
+
},
|
71
|
+
countryName: {
|
72
|
+
flex: 0.8,
|
73
|
+
fontSize: 16,
|
74
|
+
fontWeight: '500',
|
75
|
+
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
76
|
+
},
|
77
|
+
sectionTitle: {
|
78
|
+
fontSize: 16,
|
79
|
+
fontWeight: '600',
|
80
|
+
paddingVertical: 8,
|
81
|
+
color: theme === 'dark' ? '#FFFFFF' : '#000000',
|
82
|
+
},
|
83
|
+
});
|