react-native-country-select 0.2.6 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  <br>
2
2
 
3
3
  <div align = "center">
4
- <img src="lib/assets/images/preview.png" alt="React Native International Phone Number Input Lib preview">
4
+ <img src="lib/assets/images/preview.png" alt="React Native Country Picker and Select Lib preview">
5
5
  </div>
6
6
 
7
7
  <br>
@@ -9,7 +9,7 @@
9
9
  <h1 align="center">React Native Country Select</h1>
10
10
 
11
11
  <p>
12
- 🌍 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.
12
+ 🌍 React Native country picker with flags, search, TypeScript, i18n, and offline support. Lightweight, customizable, and designed with a modern UI.
13
13
  </p>
14
14
 
15
15
  <br>
@@ -246,6 +246,46 @@ export default function App() {
246
246
 
247
247
  <br>
248
248
 
249
+ - Multi Select Country
250
+
251
+ ```tsx
252
+ import React, {useState} from 'react';
253
+ import {Text, TouchableOpacity, View} from 'react-native';
254
+
255
+ import CountrySelect, {ICountry} from 'react-native-country-select';
256
+
257
+ export default function App() {
258
+ const [showPicker, setShowPicker] = useState<boolean>(false);
259
+ const [selectedCountries, setSelectedCountries] = useState<ICountry[]>([]);
260
+
261
+ const handleCountrySelect = (countries: ICountry[]) => {
262
+ setSelectedCountries(countries);
263
+ };
264
+
265
+ return (
266
+ <View
267
+ style={{
268
+ flex: 1,
269
+ }}>
270
+ <TouchableOpacity onPress={() => setShowPicker(true)}>
271
+ <Text>Select Countries</Text>
272
+ </TouchableOpacity>
273
+ <Text>Countries: {selectedCountries.length}</Text>
274
+
275
+ <CountrySelect
276
+ visible={showPicker}
277
+ isMultiSelect
278
+ selectedCountries={selectedCountries}
279
+ onSelect={handleCountrySelect}
280
+ onClose={() => setShowPicker(false)}
281
+ />
282
+ </View>
283
+ );
284
+ }
285
+ ```
286
+
287
+ <br>
288
+
249
289
  ### Modal Styles ([modalStyles](https://github.com/AstrOOnauta/react-native-country-select/blob/main/lib/interface/countrySelectStyles.ts))
250
290
 
251
291
  | Property | Type | Description |
@@ -280,6 +320,8 @@ export default function App() {
280
320
  | onSelect | (country: [ICountry](lib/interfaces/country.ts)) => void | Yes | - | Callback function called when a country is selected |
281
321
  | modalType | 'bottomSheet' \| 'popup' | No | 'bottomSheet' | Type of modal to display |
282
322
  | countrySelectStyle | [ICountrySelectStyle](lib/interfaces/countrySelectStyles.ts) | No | - | Custom styles for the country picker |
323
+ | isMultiSelect | boolean | No | false | Whether the user can select multiple options |
324
+ | selectedCountries | [ICountry[]](lib/interfaces/country.ts) | No | - | Array of countries to show in multi select mode |
283
325
  | isFullScreen | boolean | No | false | Whether the modal should be full screen |
284
326
  | popularCountries | string[] | No | [] | Array of country codes to show in popular section |
285
327
  | visibleCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to show (whitelist) |
@@ -287,6 +329,7 @@ export default function App() {
287
329
  | theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker |
288
330
  | language | [ICountrySelectLanguages](lib/interfaces/countrySelectLanguages.ts) | No | 'eng' | Language for country names (see supported languages below) |
289
331
  | showSearchInput | boolean | No | true | Whether to show the search input field |
332
+ | showAlphabetFilter | boolean | No | false | Whether to show the alphabetic filter on modal |
290
333
  | searchPlaceholder | string | No | 'Search country...' | Placeholder text for search input |
291
334
  | searchPlaceholderTextColor | string | No | '#00000080' | Placeholder text color for search input |
292
335
  | searchSelectionColor | string | No | default | Highlight, selection handle and cursor color of the search input |
@@ -381,7 +424,11 @@ Ensure your app is inclusive and usable by everyone by leveraging built-in React
381
424
  - `accessibilityLabelCountriesList`: Accessibility label for the countries list;
382
425
  - `accessibilityHintCountriesList`: Accessibility hint for the countries list;
383
426
  - `accessibilityLabelCountryItem`: Accessibility label for individual country items;
384
- - `accessibilityHintCountryItem`: Accessibility hint for individual country.
427
+ - `accessibilityHintCountryItem`: Accessibility hint for individual country;
428
+ - `accessibilityLabelAlphabetFilter`: Accessibility label for alphabet filter list;
429
+ - `accessibilityHintAlphabetFilter`: Accessibility hint for alphabet filter list;
430
+ - `accessibilityLabelAlphabetLetter`: Accessibility label for individual alphabet filter letter;
431
+ - `accessibilityHintAlphabetLetter`: Accessibility hint for individual alphabet filter letter.
385
432
 
386
433
  <br>
387
434
 
Binary file
@@ -0,0 +1,180 @@
1
+ /* eslint-disable no-undef-init */
2
+ /* eslint-disable react-hooks/exhaustive-deps */
3
+ /* eslint-disable react-native/no-inline-styles */
4
+ import React, {useEffect, useMemo, useRef} from 'react';
5
+ import {ScrollView, Text, TouchableOpacity, View} from 'react-native';
6
+
7
+ import {createStyles} from '../styles';
8
+ import {translations} from '../../utils/getTranslation';
9
+ import {createAlphabet} from '../../utils/createAlphabet';
10
+ import {AlphabeticFilterProps} from '../../interface/alfabeticFilterProps';
11
+ import {normalizeCountryName} from '../../utils/normalizeCountryName';
12
+
13
+ const ALPHABET_VIEWPORT_HEIGHT = 0;
14
+ const ALPHABET_ITEM_SIZE = 28;
15
+ const ALPHABET_VERTICAL_PADDING = 12;
16
+
17
+ export const AlphabeticFilter: React.FC<AlphabeticFilterProps> = ({
18
+ activeLetter,
19
+ onPressLetter,
20
+ theme = 'light',
21
+ language,
22
+ countries,
23
+ allCountriesStartIndex,
24
+ countrySelectStyle,
25
+ accessibilityLabelAlphabetFilter,
26
+ accessibilityHintAlphabetFilter,
27
+ accessibilityLabelAlphabetLetter,
28
+ accessibilityHintAlphabetLetter,
29
+ }) => {
30
+ const styles = createStyles(theme);
31
+ const alphabetScrollRef = useRef<ScrollView>(null);
32
+
33
+ const letterIndexMap = useMemo(() => {
34
+ const map: Record<string, number> = {};
35
+ for (let i = allCountriesStartIndex; i < countries.length; i++) {
36
+ const item = countries[i];
37
+ if ('isSection' in item) {
38
+ continue;
39
+ }
40
+ const country: any = item as any;
41
+ // Use English/common name to anchor alphabet jumps consistently
42
+ const name = country?.name?.common || '';
43
+ const first = (name?.[0] || '').toUpperCase();
44
+ if (first && map[first] === undefined) {
45
+ map[first] = i;
46
+ }
47
+ }
48
+ return map;
49
+ }, [countries, allCountriesStartIndex, language]);
50
+
51
+ const alphabet = createAlphabet();
52
+
53
+ const scrollAlphabetToLetter = (letter: string) => {
54
+ const letterIdx = alphabet.indexOf(letter);
55
+ if (letterIdx >= 0) {
56
+ const centerOffset = Math.max(
57
+ 0,
58
+ ALPHABET_VIEWPORT_HEIGHT / 2 - ALPHABET_ITEM_SIZE / 2,
59
+ );
60
+ const y = Math.max(
61
+ 0,
62
+ letterIdx * ALPHABET_ITEM_SIZE -
63
+ centerOffset +
64
+ ALPHABET_VERTICAL_PADDING,
65
+ );
66
+ alphabetScrollRef.current?.scrollTo({y, animated: true});
67
+ }
68
+ };
69
+
70
+ useEffect(() => {
71
+ if (!activeLetter) {
72
+ return;
73
+ }
74
+ scrollAlphabetToLetter(activeLetter);
75
+ }, [activeLetter, alphabet]);
76
+
77
+ return (
78
+ <ScrollView
79
+ testID="countrySelectAlphabetFilter"
80
+ accessibilityRole="list"
81
+ accessibilityLabel={
82
+ accessibilityLabelAlphabetFilter ||
83
+ translations.accessibilityLabelAlphabetFilter[language]
84
+ }
85
+ accessibilityHint={
86
+ accessibilityHintAlphabetFilter ||
87
+ translations.accessibilityHintAlphabetFilter[language]
88
+ }
89
+ ref={alphabetScrollRef}
90
+ style={[styles.alphabetContainer, countrySelectStyle?.alphabetContainer]}
91
+ contentContainerStyle={{alignItems: 'center', paddingVertical: 12}}
92
+ showsVerticalScrollIndicator={false}>
93
+ {alphabet.map(letter => {
94
+ const enabled = letterIndexMap[letter] !== undefined;
95
+ const isActive = activeLetter === letter;
96
+ if (enabled) {
97
+ return (
98
+ <TouchableOpacity
99
+ key={letter}
100
+ onPress={() => {
101
+ // Compute first index for this letter using normalized display name (same as sorting)
102
+ const lower = letter.toLowerCase();
103
+ let idxToGo: number | undefined = undefined;
104
+ for (
105
+ let i = allCountriesStartIndex;
106
+ i < countries.length;
107
+ i++
108
+ ) {
109
+ const it = countries[i] as any;
110
+ if ('isSection' in it) {
111
+ continue;
112
+ }
113
+ const displayName =
114
+ it?.translations?.[language]?.common ||
115
+ it?.name?.common ||
116
+ '';
117
+ const normalized = normalizeCountryName(
118
+ displayName.toLowerCase(),
119
+ );
120
+ if (normalized.startsWith(lower)) {
121
+ idxToGo = i;
122
+ break;
123
+ }
124
+ }
125
+ if (idxToGo !== undefined) {
126
+ onPressLetter(idxToGo);
127
+ }
128
+ scrollAlphabetToLetter(letter);
129
+ }}
130
+ style={[
131
+ styles.alphabetLetter,
132
+ isActive && styles.alphabetLetterActive,
133
+ countrySelectStyle?.alphabetLetter,
134
+ ]}
135
+ accessibilityRole="button"
136
+ accessibilityHint={
137
+ accessibilityHintAlphabetLetter ||
138
+ translations.accessibilityHintAlphabetLetter[language] +
139
+ ` ${letter}`
140
+ }
141
+ accessibilityLabel={
142
+ accessibilityLabelAlphabetLetter ||
143
+ translations.accessibilityLabelAlphabetLetter[language] +
144
+ ` ${letter}`
145
+ }>
146
+ <Text
147
+ style={[
148
+ styles.alphabetLetterText,
149
+ isActive && styles.alphabetLetterTextActive,
150
+ countrySelectStyle?.alphabetLetterText,
151
+ ]}>
152
+ {letter}
153
+ </Text>
154
+ </TouchableOpacity>
155
+ );
156
+ }
157
+ return (
158
+ <View
159
+ key={letter}
160
+ style={[
161
+ styles.alphabetLetter,
162
+ styles.alphabetLetterDisabled,
163
+ countrySelectStyle?.alphabetLetter,
164
+ ]}>
165
+ <Text
166
+ style={[
167
+ styles.alphabetLetterText,
168
+ styles.alphabetLetterTextDisabled,
169
+ countrySelectStyle?.alphabetLetterText,
170
+ ]}>
171
+ {letter}
172
+ </Text>
173
+ </View>
174
+ );
175
+ })}
176
+ </ScrollView>
177
+ );
178
+ };
179
+
180
+ export default AlphabeticFilter;
@@ -0,0 +1,225 @@
1
+ /* eslint-disable react-native/no-inline-styles */
2
+ import React, {useEffect, useMemo, useRef, useState} from 'react';
3
+ import {
4
+ Animated,
5
+ Modal,
6
+ ModalProps,
7
+ Pressable,
8
+ View,
9
+ PanResponder,
10
+ Keyboard,
11
+ NativeSyntheticEvent,
12
+ } from 'react-native';
13
+
14
+ import parseHeight from '../../utils/parseHeight';
15
+ import {ICountrySelectStyle} from '../../interface';
16
+
17
+ interface BottomSheetModalProps extends ModalProps {
18
+ visible: boolean;
19
+ onRequestClose: (event: NativeSyntheticEvent<any>) => void;
20
+ statusBarTranslucent?: boolean;
21
+ removedBackdrop?: boolean;
22
+ disabledBackdropPress?: boolean;
23
+ onBackdropPress?: () => void;
24
+ accessibilityLabelBackdrop?: string;
25
+ accessibilityHintBackdrop?: string;
26
+ styles: ICountrySelectStyle;
27
+ countrySelectStyle?: ICountrySelectStyle;
28
+ minBottomsheetHeight?: number | string;
29
+ maxBottomsheetHeight?: number | string;
30
+ initialBottomsheetHeight?: number | string;
31
+ dragHandleIndicatorComponent?: () => React.ReactElement;
32
+ header?: React.ReactNode;
33
+ children: React.ReactNode;
34
+ }
35
+
36
+ const MIN_HEIGHT_PERCENTAGE = 0.3;
37
+ const MAX_HEIGHT_PERCENTAGE = 0.9;
38
+ const INITIAL_HEIGHT_PERCENTAGE = 0.5;
39
+
40
+ export const BottomSheetModal: React.FC<BottomSheetModalProps> = ({
41
+ visible,
42
+ onRequestClose,
43
+ statusBarTranslucent,
44
+ removedBackdrop,
45
+ disabledBackdropPress,
46
+ onBackdropPress,
47
+ accessibilityLabelBackdrop,
48
+ accessibilityHintBackdrop,
49
+ styles,
50
+ countrySelectStyle,
51
+ minBottomsheetHeight,
52
+ maxBottomsheetHeight,
53
+ initialBottomsheetHeight,
54
+ dragHandleIndicatorComponent,
55
+ header,
56
+ children,
57
+ ...props
58
+ }) => {
59
+ const [modalHeight, setModalHeight] = useState(0);
60
+ const [bottomSheetSize, setBottomSheetSize] = useState({
61
+ minHeight: 0,
62
+ maxHeight: 0,
63
+ initialHeight: 0,
64
+ });
65
+ const sheetHeight = useRef(new Animated.Value(0)).current;
66
+ const lastHeightRef = useRef(0);
67
+ const dragStartYRef = useRef(0);
68
+
69
+ useEffect(() => {
70
+ const DRAG_HANDLE_HEIGHT = 20;
71
+ const availableHeight = Math.max(0, modalHeight - DRAG_HANDLE_HEIGHT);
72
+ const parsedMinHeight = parseHeight(minBottomsheetHeight, availableHeight);
73
+ const parsedMaxHeight = parseHeight(maxBottomsheetHeight, availableHeight);
74
+ const parsedInitialHeight = parseHeight(
75
+ initialBottomsheetHeight,
76
+ availableHeight,
77
+ );
78
+ setBottomSheetSize({
79
+ minHeight: parsedMinHeight || MIN_HEIGHT_PERCENTAGE * availableHeight,
80
+ maxHeight: parsedMaxHeight || MAX_HEIGHT_PERCENTAGE * availableHeight,
81
+ initialHeight:
82
+ parsedInitialHeight || INITIAL_HEIGHT_PERCENTAGE * availableHeight,
83
+ });
84
+ }, [
85
+ modalHeight,
86
+ minBottomsheetHeight,
87
+ maxBottomsheetHeight,
88
+ initialBottomsheetHeight,
89
+ ]);
90
+
91
+ useEffect(() => {
92
+ if (visible) {
93
+ sheetHeight.setValue(bottomSheetSize.initialHeight);
94
+ lastHeightRef.current = bottomSheetSize.initialHeight;
95
+ }
96
+ }, [visible, bottomSheetSize.initialHeight, sheetHeight]);
97
+
98
+ useEffect(() => {
99
+ const show = Keyboard.addListener('keyboardDidShow', () => {
100
+ sheetHeight.setValue(bottomSheetSize.maxHeight);
101
+ lastHeightRef.current = bottomSheetSize.maxHeight;
102
+ });
103
+ const hide = Keyboard.addListener('keyboardDidHide', () => {
104
+ sheetHeight.setValue(lastHeightRef.current);
105
+ });
106
+ return () => {
107
+ show?.remove();
108
+ hide?.remove();
109
+ };
110
+ }, [bottomSheetSize.maxHeight, sheetHeight]);
111
+
112
+ const panHandlers = useMemo(
113
+ () =>
114
+ PanResponder.create({
115
+ onStartShouldSetPanResponder: () => true,
116
+ onMoveShouldSetPanResponder: (_evt, gestureState) =>
117
+ Math.abs(gestureState.dy) > 5,
118
+ onPanResponderGrant: e => {
119
+ dragStartYRef.current = e.nativeEvent.pageY;
120
+ sheetHeight.stopAnimation();
121
+ },
122
+ onPanResponderMove: e => {
123
+ const currentY = e.nativeEvent.pageY;
124
+ const dy = currentY - dragStartYRef.current;
125
+ const proposedHeight = lastHeightRef.current - dy;
126
+ sheetHeight.setValue(proposedHeight);
127
+ },
128
+ onPanResponderRelease: e => {
129
+ const currentY = e.nativeEvent.pageY;
130
+ const dy = currentY - dragStartYRef.current;
131
+ const currentHeight = lastHeightRef.current - dy;
132
+ if (currentHeight < bottomSheetSize.minHeight) {
133
+ Animated.timing(sheetHeight, {
134
+ toValue: 0,
135
+ duration: 200,
136
+ useNativeDriver: false,
137
+ }).start();
138
+ return;
139
+ }
140
+ const finalHeight = Math.min(
141
+ Math.max(currentHeight, bottomSheetSize.minHeight),
142
+ bottomSheetSize.maxHeight,
143
+ );
144
+ Animated.spring(sheetHeight, {
145
+ toValue: finalHeight,
146
+ useNativeDriver: false,
147
+ tension: 50,
148
+ friction: 12,
149
+ }).start(() => {
150
+ lastHeightRef.current = finalHeight;
151
+ });
152
+ },
153
+ onPanResponderTerminate: () => {
154
+ Animated.spring(sheetHeight, {
155
+ toValue: lastHeightRef.current,
156
+ useNativeDriver: false,
157
+ tension: 50,
158
+ friction: 12,
159
+ }).start();
160
+ },
161
+ }),
162
+ [bottomSheetSize.minHeight, bottomSheetSize.maxHeight, sheetHeight],
163
+ );
164
+ return (
165
+ <Modal
166
+ visible={visible}
167
+ transparent
168
+ animationType="slide"
169
+ onRequestClose={onRequestClose}
170
+ statusBarTranslucent={statusBarTranslucent}
171
+ {...props}>
172
+ <View
173
+ testID="countrySelectContainer"
174
+ style={[styles.container, countrySelectStyle?.container]}
175
+ onLayout={e => setModalHeight(e.nativeEvent.layout.height)}>
176
+ <Pressable
177
+ testID="countrySelectBackdrop"
178
+ accessibilityRole="button"
179
+ accessibilityLabel={accessibilityLabelBackdrop}
180
+ accessibilityHint={accessibilityHintBackdrop}
181
+ disabled={disabledBackdropPress || removedBackdrop}
182
+ style={[
183
+ styles.backdrop,
184
+ countrySelectStyle?.backdrop,
185
+ removedBackdrop && {backgroundColor: 'transparent'},
186
+ ]}
187
+ onPress={onBackdropPress || onRequestClose}
188
+ />
189
+ <Animated.View
190
+ testID="countrySelectContent"
191
+ style={[
192
+ styles.content,
193
+ countrySelectStyle?.content,
194
+ {
195
+ height: sheetHeight,
196
+ minHeight: bottomSheetSize.minHeight,
197
+ maxHeight: bottomSheetSize.maxHeight,
198
+ },
199
+ ]}>
200
+ <View
201
+ {...panHandlers.panHandlers}
202
+ style={[
203
+ styles.dragHandleContainer,
204
+ countrySelectStyle?.dragHandleContainer,
205
+ ]}>
206
+ {dragHandleIndicatorComponent ? (
207
+ dragHandleIndicatorComponent()
208
+ ) : (
209
+ <View
210
+ style={[
211
+ styles.dragHandleIndicator,
212
+ countrySelectStyle?.dragHandleIndicator,
213
+ ]}
214
+ />
215
+ )}
216
+ </View>
217
+ {header}
218
+ <Animated.View style={{flex: 1, flexDirection: 'row'}}>
219
+ {children}
220
+ </Animated.View>
221
+ </Animated.View>
222
+ </View>
223
+ </Modal>
224
+ );
225
+ };
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import {Text, TouchableOpacity} from 'react-native';
3
+
4
+ import {createStyles} from '../styles';
5
+ import {ICloseButtonProps} from '../../interface';
6
+ import {translations} from '../../utils/getTranslation';
7
+
8
+ export const CloseButton: React.FC<ICloseButtonProps> = ({
9
+ theme,
10
+ language,
11
+ onClose,
12
+ countrySelectStyle,
13
+ accessibilityLabelCloseButton,
14
+ accessibilityHintCloseButton,
15
+ }) => {
16
+ const styles = createStyles(theme);
17
+ return (
18
+ <TouchableOpacity
19
+ testID="countrySelectCloseButton"
20
+ accessibilityRole="button"
21
+ accessibilityLabel={
22
+ accessibilityLabelCloseButton ||
23
+ translations.accessibilityLabelCloseButton[language]
24
+ }
25
+ accessibilityHint={
26
+ accessibilityHintCloseButton ||
27
+ translations.accessibilityHintCloseButton[language]
28
+ }
29
+ style={[styles.closeButton, countrySelectStyle?.closeButton]}
30
+ activeOpacity={0.6}
31
+ onPress={onClose}>
32
+ <Text
33
+ style={[styles.closeButtonText, countrySelectStyle?.closeButtonText]}>
34
+ {'\u00D7'}
35
+ </Text>
36
+ </TouchableOpacity>
37
+ );
38
+ };
@@ -3,17 +3,15 @@ import {View, Text, TouchableOpacity} from 'react-native';
3
3
 
4
4
  import {createStyles} from '../styles';
5
5
  import {translations} from '../../utils/getTranslation';
6
- import {ICountryItemProps, ICountrySelectLanguages} from '../../interface';
7
-
8
- const DEFAULT_LANGUAGE: ICountrySelectLanguages = 'eng';
6
+ import {ICountryItemProps} from '../../interface';
9
7
 
10
8
  export const CountryItem = memo<ICountryItemProps>(
11
9
  ({
12
- item,
10
+ country,
11
+ isSelected,
13
12
  onSelect,
14
- onClose,
15
13
  theme = 'light',
16
- language,
14
+ language = 'eng',
17
15
  countrySelectStyle,
18
16
  accessibilityLabel,
19
17
  accessibilityHint,
@@ -26,33 +24,43 @@ export const CountryItem = memo<ICountryItemProps>(
26
24
  accessibilityRole="button"
27
25
  accessibilityLabel={
28
26
  accessibilityLabel ||
29
- translations.accessibilityLabelCountryItem[language]
27
+ translations.accessibilityLabelCountryItem[language] +
28
+ ` ${country.translations[language]?.common}`
30
29
  }
31
30
  accessibilityHint={
32
31
  accessibilityHint ||
33
- translations.accessibilityHintCountryItem[language]
32
+ translations.accessibilityHintCountryItem[language] +
33
+ ` ${country.translations[language]?.common}`
34
34
  }
35
- style={[styles.countryItem, countrySelectStyle?.countryItem]}
36
- onPress={() => {
37
- onSelect(item);
38
- onClose();
39
- }}>
35
+ style={[
36
+ styles.countryItem,
37
+ countrySelectStyle?.countryItem,
38
+ isSelected && styles.countryItemSelected,
39
+ ]}
40
+ onPress={() => onSelect(country)}>
40
41
  <Text
41
42
  testID="countrySelectItemFlag"
42
43
  style={[styles.flag, countrySelectStyle?.flag]}>
43
- {item.flag || item.cca2}
44
+ {country.flag || country.cca2}
44
45
  </Text>
45
46
  <View style={[styles.countryInfo, countrySelectStyle?.countryInfo]}>
46
47
  <Text
47
48
  testID="countrySelectItemCallingCode"
48
- style={[styles.callingCode, countrySelectStyle?.callingCode]}>
49
- {item.idd.root}
49
+ style={[
50
+ styles.callingCode,
51
+ countrySelectStyle?.callingCode,
52
+ isSelected && styles.callingCodeSelected,
53
+ ]}>
54
+ {country.idd.root}
50
55
  </Text>
51
56
  <Text
52
57
  testID="countrySelectItemName"
53
- style={[styles.countryName, countrySelectStyle?.countryName]}>
54
- {item?.translations[language]?.common ||
55
- item?.translations[DEFAULT_LANGUAGE]?.common}
58
+ style={[
59
+ styles.countryName,
60
+ countrySelectStyle?.countryName,
61
+ isSelected && styles.countryNameSelected,
62
+ ]}>
63
+ {country?.translations[language]?.common}
56
64
  </Text>
57
65
  </View>
58
66
  </TouchableOpacity>